[CORL-156] Manage user suspension status (#2419)

* wire up suspension modal

* show user suspended callout on stream

* prevent comment actions for suspended users

* set default to 3 hour suspension

* add message field to suspension

* allow custom message for suspension

* show suspend success modal

* fix type errors

* remove unused code

* update styles

* fix fixture for streams

* add suspension ui tests

* fix types

* remove warnings?

* remove snapshot

* fix merge conflicts

* allow custom email message when banning users

* fix typo

* correct message type

* use final-form in suspend modal

* refactor suspend modal to use final-form

* refactor ban modal to use final-form

* refactor userStatusChangeContainer to use useCallback

* feat: improve translated form

* fix: addressed issue caused by i18n refactor

* update getMessage to accept arguments, remove format method

* translate suspend info

* change hour format

* make message a mandatory input for suspend and ban user

* fix types in user table

* Revert "fix types in user table"

This reverts commit d396e90b88bb1bd354c5cdbdd72b6d8f1ab72929.

* fix types for user table

* fix: small review tweaks
This commit is contained in:
Tessa Thornton
2019-08-02 21:16:21 +00:00
committed by Wyatt Johnson
parent 4e548e8fbf
commit 5df2de6afc
42 changed files with 1511 additions and 276 deletions
@@ -16,6 +16,7 @@ interface Props {
user: PropTypesOf<typeof UserRole>["user"] &
PropTypesOf<typeof UserStatus>["user"];
viewer: PropTypesOf<typeof UserRole>["viewer"];
settings: PropTypesOf<typeof UserStatus>["settings"];
onUsernameClicked?: (userID: string) => void;
}
@@ -27,6 +28,7 @@ const UserRow: FunctionComponent<Props> = ({
user,
viewer,
onUsernameClicked,
settings,
}) => {
const usernameClicked = useCallback(() => {
if (!onUsernameClicked) {
@@ -53,7 +55,7 @@ const UserRow: FunctionComponent<Props> = ({
<UserRole user={user} viewer={viewer} />
</TableCell>
<TableCell className={styles.statusColumn}>
<UserStatus user={user} fullWidth />
<UserStatus user={user} settings={settings} fullWidth />
</TableCell>
</TableRow>
);
@@ -1,6 +1,7 @@
import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { UserRowContainer_settings as SettingsData } from "coral-admin/__generated__/UserRowContainer_settings.graphql";
import { UserRowContainer_user as UserData } from "coral-admin/__generated__/UserRowContainer_user.graphql";
import { UserRowContainer_viewer as ViewerData } from "coral-admin/__generated__/UserRowContainer_viewer.graphql";
import { useCoralContext } from "coral-framework/lib/bootstrap";
@@ -11,6 +12,7 @@ import UserRow from "./UserRow";
interface Props {
user: UserData;
viewer: ViewerData;
settings: SettingsData;
onUsernameClicked?: (userID: string) => void;
}
@@ -19,6 +21,7 @@ const UserRowContainer: FunctionComponent<Props> = props => {
return (
<UserRow
user={props.user}
settings={props.settings}
viewer={props.viewer}
userID={props.user.id}
username={props.user.username!}
@@ -39,6 +42,11 @@ const enhanced = withFragmentContainer<Props>({
...UserRoleChangeContainer_viewer
}
`,
settings: graphql`
fragment UserRowContainer_settings on Settings {
...UserStatusChangeContainer_settings
}
`,
user: graphql`
fragment UserRowContainer_user on User {
...UserStatusChangeContainer_user
@@ -22,6 +22,7 @@ import styles from "./UserTable.css";
interface Props {
viewer: PropTypesOf<typeof UserRowContainer>["viewer"] | null;
settings: PropTypesOf<typeof UserRowContainer>["settings"] | null;
users: Array<{ id: string } & PropTypesOf<typeof UserRowContainer>["user"]>;
onLoadMore: () => void;
hasMore: boolean;
@@ -29,7 +30,11 @@ interface Props {
loading: boolean;
}
const UserTable: FunctionComponent<Props> = props => {
const UserTable: FunctionComponent<Props> = ({
viewer,
settings,
...props
}) => {
const [userDrawerUserID, setUserDrawerUserID] = useState("");
const [userDrawerVisible, setUserDrawerVisible] = useState(false);
@@ -45,7 +50,6 @@ const UserTable: FunctionComponent<Props> = props => {
setUserDrawerVisible(false);
setUserDrawerUserID("");
}, [setUserDrawerUserID, setUserDrawerVisible]);
return (
<>
<HorizontalGutter size="double">
@@ -77,11 +81,14 @@ const UserTable: FunctionComponent<Props> = props => {
</TableHead>
<TableBody>
{!props.loading &&
settings &&
viewer &&
props.users.map(u => (
<UserRowContainer
key={u.id}
user={u}
viewer={props.viewer!}
settings={settings}
viewer={viewer}
onUsernameClicked={onShowUserDrawer}
/>
))}
@@ -52,6 +52,7 @@ const UserTableContainer: FunctionComponent<Props> = props => {
/>
<UserTable
viewer={props.query && props.query.viewer}
settings={props.query && props.query.settings}
loading={!props.query || isRefetching}
users={users}
onLoadMore={loadMore}
@@ -87,6 +88,7 @@ const enhanced = withPaginationContainer<
}
settings {
...InviteUsersContainer_settings
...UserRowContainer_settings
}
users(
first: $count