mirror of
https://github.com/wassname/talk.git
synced 2026-07-01 06:17:27 +08:00
[CORL-97] Add user status details popover to user drawer (#2431)
* show tooltip for user status details * localize strings * fix merge conflict * fix date formatting in user details popover * update snapshot * fix rebase
This commit is contained in:
committed by
Kim Gardner
parent
3f307002e2
commit
ff964b54a3
@@ -2,12 +2,12 @@ import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { ReadyState } from "react-relay";
|
||||
|
||||
import { UserStatusChangeContainer } from "coral-admin/components/UserStatus";
|
||||
import { CopyButton } from "coral-framework/components";
|
||||
import { useCoralContext } from "coral-framework/lib/bootstrap";
|
||||
import { graphql, QueryRenderer } from "coral-framework/lib/relay";
|
||||
|
||||
import { UserHistoryDrawerQuery as QueryTypes } from "coral-admin/__generated__/UserHistoryDrawerQuery.graphql";
|
||||
import { UserStatusChangeContainer } from "coral-admin/components/UserStatus";
|
||||
import {
|
||||
Button,
|
||||
CallOut,
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
} from "coral-ui/components";
|
||||
|
||||
import Tabs from "./Tabs";
|
||||
import UserStatusDetailsContainer from "./UserStatusDetailsContainer";
|
||||
|
||||
import styles from "./UserHistoryDrawerQuery.css";
|
||||
|
||||
@@ -48,6 +49,7 @@ const UserHistoryDrawerQuery: FunctionComponent<Props> = ({
|
||||
username
|
||||
email
|
||||
createdAt
|
||||
...UserStatusDetailsContainer_user
|
||||
...UserStatusChangeContainer_user
|
||||
}
|
||||
settings {
|
||||
@@ -92,7 +94,7 @@ const UserHistoryDrawerQuery: FunctionComponent<Props> = ({
|
||||
<span>{user.username}</span>
|
||||
</Flex>
|
||||
<div className={styles.userStatus}>
|
||||
<Flex alignItems="center">
|
||||
<Flex alignItems="center" itemGutter="half">
|
||||
<div className={styles.userStatusLabel}>
|
||||
<Typography variant="bodyCopyBold" container="div">
|
||||
<Flex alignItems="center" itemGutter="half">
|
||||
@@ -103,8 +105,13 @@ const UserHistoryDrawerQuery: FunctionComponent<Props> = ({
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.userStatusChange}>
|
||||
<UserStatusChangeContainer settings={settings} user={user} />
|
||||
<UserStatusChangeContainer
|
||||
settings={settings}
|
||||
user={user}
|
||||
fullWidth={false}
|
||||
/>
|
||||
</div>
|
||||
<UserStatusDetailsContainer user={user} />
|
||||
</Flex>
|
||||
</div>
|
||||
<div className={styles.userDetails}>
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
import { graphql, withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent, useMemo } from "react";
|
||||
|
||||
import { UserStatusDetailsContainer_user as UserData } from "coral-admin/__generated__/UserStatusDetailsContainer_user.graphql";
|
||||
import { useCoralContext } from "coral-framework/lib/bootstrap";
|
||||
import {
|
||||
BaseButton,
|
||||
Box,
|
||||
ClickOutside,
|
||||
Icon,
|
||||
Popover,
|
||||
Typography,
|
||||
} from "coral-ui/components";
|
||||
|
||||
interface Props {
|
||||
user: UserData;
|
||||
}
|
||||
|
||||
const UserStatusDetailsContainer: FunctionComponent<Props> = ({ user }) => {
|
||||
if (!user.status.ban.active && !user.status.suspension.active) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const activeBan = useMemo(() => {
|
||||
return user.status.ban.history.find(item => item.active);
|
||||
}, [user]);
|
||||
|
||||
const activeSuspension = useMemo(() => {
|
||||
return user.status.suspension.history.find(item => item.active);
|
||||
}, [user]);
|
||||
|
||||
const { locales } = useCoralContext();
|
||||
|
||||
const formatter = new Intl.DateTimeFormat(locales, {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Popover
|
||||
placement="bottom"
|
||||
id="userStatus-details-popover"
|
||||
body={({ toggleVisibility }) => (
|
||||
<ClickOutside onClickOutside={toggleVisibility}>
|
||||
<Box p={2}>
|
||||
{activeBan && (
|
||||
<div>
|
||||
<Localized
|
||||
id="userDetails-banned-on"
|
||||
$timestamp={formatter.format(activeBan.createdAt)}
|
||||
strong={<strong />}
|
||||
>
|
||||
<Typography>
|
||||
<strong>Banned on </strong>{" "}
|
||||
{formatter.format(activeBan.createdAt)}
|
||||
</Typography>
|
||||
</Localized>
|
||||
{activeBan.createdBy && (
|
||||
<Localized
|
||||
id="userDetails-banned-by"
|
||||
strong={<strong />}
|
||||
$username={activeBan.createdBy.username}
|
||||
>
|
||||
<Typography>
|
||||
<strong>by </strong>
|
||||
{activeBan.createdBy.username}
|
||||
</Typography>
|
||||
</Localized>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{activeSuspension && (
|
||||
<div>
|
||||
{activeSuspension.createdBy && (
|
||||
<Localized
|
||||
id="userDetails-suspended-by"
|
||||
strong={<strong />}
|
||||
$username={activeSuspension.createdBy.username}
|
||||
>
|
||||
<Typography>
|
||||
<strong>Suspended by </strong>
|
||||
{activeSuspension.createdBy.username}
|
||||
</Typography>
|
||||
</Localized>
|
||||
)}
|
||||
<Localized
|
||||
id="userDetails-suspension-start"
|
||||
strong={<strong />}
|
||||
$timestamp={formatter.format(activeSuspension.from.start)}
|
||||
>
|
||||
<Typography>
|
||||
<strong>Start: </strong>
|
||||
{formatter.format(activeSuspension.from.start)}
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Localized
|
||||
strong={<strong />}
|
||||
$timestamp={formatter.format(activeSuspension.from.finish)}
|
||||
id="userDetails-suspension-start"
|
||||
>
|
||||
<Typography>
|
||||
<strong>End: </strong>
|
||||
{formatter.format(activeSuspension.from.finish)}
|
||||
</Typography>
|
||||
</Localized>
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
</ClickOutside>
|
||||
)}
|
||||
>
|
||||
{({ toggleVisibility, ref }) => (
|
||||
<BaseButton
|
||||
onClick={evt => {
|
||||
evt.stopPropagation();
|
||||
toggleVisibility();
|
||||
}}
|
||||
aria-label="View user status details"
|
||||
ref={ref}
|
||||
>
|
||||
<Icon size="md" color="inherit">
|
||||
info
|
||||
</Icon>
|
||||
</BaseButton>
|
||||
)}
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
user: graphql`
|
||||
fragment UserStatusDetailsContainer_user on User {
|
||||
status {
|
||||
ban {
|
||||
active
|
||||
history {
|
||||
active
|
||||
createdAt
|
||||
createdBy {
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
suspension {
|
||||
until
|
||||
active
|
||||
history {
|
||||
active
|
||||
from {
|
||||
start
|
||||
finish
|
||||
}
|
||||
createdBy {
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
})(UserStatusDetailsContainer);
|
||||
|
||||
export default enhanced;
|
||||
@@ -682,3 +682,9 @@ invite-goToAdmin = Go to { -product-name } Admin
|
||||
invite-goToOrganization = Go to { $organizationName }
|
||||
invite-tokenNotFound =
|
||||
The specified link is invalid, check to see if it was copied correctly.
|
||||
|
||||
userDetails-banned-on = <strong>Banned on</strong> { $timestamp }
|
||||
userDetails-banned-by = <strong>by</strong> { $username }
|
||||
userDetails-suspended-by = <strong>Suspended by</strong> { $username }
|
||||
userDetails-suspension-start = <strong>Start:</strong> { $timestamp }
|
||||
userDetails-suspension-end = <strong>End:</strong> { $timestamp }
|
||||
Reference in New Issue
Block a user