mirror of
https://github.com/wassname/talk.git
synced 2026-07-19 11:28:50 +08:00
[CORL-249] Mod queues empty states (#2289)
* feat: mod queues empty states * fix: test
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
.root {
|
||||
composes: bodyCopy from "talk-ui/shared/typography.css";
|
||||
color: var(--palette-grey-dark);
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import cn from "classnames";
|
||||
import React, { StatelessComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { Card } from "talk-ui/components";
|
||||
|
||||
import styles from "./EmptyMessage.css";
|
||||
|
||||
interface Props extends PropTypesOf<typeof Card> {}
|
||||
|
||||
const EmptyMessage: StatelessComponent<Props> = props => (
|
||||
<Card {...props} className={cn(props.className, styles.root)} />
|
||||
);
|
||||
|
||||
export default EmptyMessage;
|
||||
@@ -18,6 +18,7 @@ interface Props {
|
||||
hasMore: boolean;
|
||||
disableLoadMore: boolean;
|
||||
danglingLogic: PropTypesOf<typeof ModerateCardContainer>["danglingLogic"];
|
||||
emptyElement?: React.ReactElement;
|
||||
}
|
||||
|
||||
const Queue: StatelessComponent<Props> = ({
|
||||
@@ -27,6 +28,7 @@ const Queue: StatelessComponent<Props> = ({
|
||||
disableLoadMore,
|
||||
onLoadMore,
|
||||
danglingLogic,
|
||||
emptyElement,
|
||||
}) => (
|
||||
<HorizontalGutter className={styles.root} size="double">
|
||||
<TransitionGroup component={null} appear={false} enter={false} exit>
|
||||
@@ -56,6 +58,7 @@ const Queue: StatelessComponent<Props> = ({
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
{comments.length === 0 && emptyElement}
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { RouteProps } from "found";
|
||||
import React from "react";
|
||||
import { graphql, GraphQLTaggedNode, RelayPaginationProp } from "react-relay";
|
||||
@@ -8,6 +9,7 @@ import { QueueContainerPaginationPendingQueryVariables } from "talk-admin/__gene
|
||||
import { IntersectionProvider } from "talk-framework/lib/intersection";
|
||||
import { withPaginationContainer } from "talk-framework/lib/relay";
|
||||
|
||||
import EmptyMessage from "../components/EmptyMessage";
|
||||
import LoadingQueue from "../components/LoadingQueue";
|
||||
import Queue from "../components/Queue";
|
||||
|
||||
@@ -15,6 +17,7 @@ interface QueueContainerProps {
|
||||
queue: QueueData;
|
||||
settings: SettingsData;
|
||||
relay: RelayPaginationProp;
|
||||
emptyElement: React.ReactElement;
|
||||
}
|
||||
|
||||
// TODO: use generated types
|
||||
@@ -39,6 +42,7 @@ export class QueueContainer extends React.Component<QueueContainerProps> {
|
||||
hasMore={this.props.relay.hasMore()}
|
||||
disableLoadMore={this.state.disableLoadMore}
|
||||
danglingLogic={danglingLogic}
|
||||
emptyElement={this.props.emptyElement}
|
||||
/>
|
||||
</IntersectionProvider>
|
||||
);
|
||||
@@ -67,7 +71,8 @@ type FragmentVariables = QueueContainerPaginationPendingQueryVariables;
|
||||
|
||||
const createQueueContainer = (
|
||||
queueQuery: GraphQLTaggedNode,
|
||||
paginationQuery: GraphQLTaggedNode
|
||||
paginationQuery: GraphQLTaggedNode,
|
||||
emptyElement: React.ReactElement
|
||||
) => {
|
||||
const enhanced = (withPaginationContainer<
|
||||
QueueContainerProps,
|
||||
@@ -131,7 +136,13 @@ const createQueueContainer = (
|
||||
if (Component && props) {
|
||||
const queue =
|
||||
anyProps.moderationQueues[Object.keys(anyProps.moderationQueues)[0]];
|
||||
return <Component queue={queue} settings={anyProps.settings} />;
|
||||
return (
|
||||
<Component
|
||||
queue={queue}
|
||||
settings={anyProps.settings}
|
||||
emptyElement={emptyElement}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <LoadingQueue />;
|
||||
},
|
||||
@@ -167,7 +178,13 @@ export const PendingQueueContainer = createQueueContainer(
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
`,
|
||||
// tslint:disable-next-line:jsx-wrap-multiline
|
||||
<Localized id="moderate-emptyQueue-pending">
|
||||
<EmptyMessage>
|
||||
Nicely done! There are no more pending comments to moderate.
|
||||
</EmptyMessage>
|
||||
</Localized>
|
||||
);
|
||||
|
||||
export const ReportedQueueContainer = createQueueContainer(
|
||||
@@ -197,7 +214,13 @@ export const ReportedQueueContainer = createQueueContainer(
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
`,
|
||||
// tslint:disable-next-line:jsx-wrap-multiline
|
||||
<Localized id="moderate-emptyQueue-reported">
|
||||
<EmptyMessage>
|
||||
Nicely done! There are no more reported comments to moderate.
|
||||
</EmptyMessage>
|
||||
</Localized>
|
||||
);
|
||||
|
||||
export const UnmoderatedQueueContainer = createQueueContainer(
|
||||
@@ -227,5 +250,9 @@ export const UnmoderatedQueueContainer = createQueueContainer(
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
`,
|
||||
// tslint:disable-next-line:jsx-wrap-multiline
|
||||
<Localized id="moderate-emptyQueue-unmoderated">
|
||||
<EmptyMessage>Nicely done! All comments have been moderated.</EmptyMessage>
|
||||
</Localized>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import { RouteProps } from "found";
|
||||
import React from "react";
|
||||
import { graphql, RelayPaginationProp } from "react-relay";
|
||||
@@ -7,6 +8,7 @@ import { RejectedQueueContainerPaginationQueryVariables } from "talk-admin/__gen
|
||||
import { IntersectionProvider } from "talk-framework/lib/intersection";
|
||||
import { withPaginationContainer } from "talk-framework/lib/relay";
|
||||
|
||||
import EmptyMessage from "../components/EmptyMessage";
|
||||
import LoadingQueue from "../components/LoadingQueue";
|
||||
import Queue from "../components/Queue";
|
||||
|
||||
@@ -38,7 +40,12 @@ export class RejectedQueueContainer extends React.Component<
|
||||
hasMore={this.props.relay.hasMore()}
|
||||
disableLoadMore={this.state.disableLoadMore}
|
||||
danglingLogic={danglingLogic}
|
||||
/>{" "}
|
||||
emptyElement={
|
||||
<Localized id="moderate-emptyQueue-rejected">
|
||||
<EmptyMessage>There are no rejected comments.</EmptyMessage>
|
||||
</Localized>
|
||||
}
|
||||
/>
|
||||
</IntersectionProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -574,7 +574,6 @@ exports[`rejected queue renders rejected queue with comments 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
@@ -1057,7 +1056,13 @@ exports[`reported queue renders empty reported queue 1`] = `
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root Queue-root HorizontalGutter-double"
|
||||
/>
|
||||
>
|
||||
<div
|
||||
className="Card-root EmptyMessage-root"
|
||||
>
|
||||
Nicely done! There are no more reported comments to moderate.
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -45,18 +45,8 @@ async function createTestRenderer(
|
||||
Query: {
|
||||
settings: () => settings,
|
||||
viewer: () => viewer,
|
||||
moderationQueues: ({ variables }) => {
|
||||
expectAndFail(variables).toEqual({
|
||||
storyID: null,
|
||||
});
|
||||
return emptyModerationQueues;
|
||||
},
|
||||
comments: ({ variables }) => {
|
||||
expectAndFail(variables).toEqual({
|
||||
storyID: null,
|
||||
});
|
||||
return emptyRejectedComments;
|
||||
},
|
||||
moderationQueues: () => emptyModerationQueues,
|
||||
comments: () => emptyRejectedComments,
|
||||
},
|
||||
}),
|
||||
params.resolvers
|
||||
@@ -89,6 +79,31 @@ describe("reported queue", () => {
|
||||
expect(toJSON(getByTestID("moderate-main-container"))).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders empty pending queue", async () => {
|
||||
replaceHistoryLocation("http://localhost/admin/moderate/pending");
|
||||
const testRenderer = await createTestRenderer();
|
||||
const { getByText } = within(testRenderer.root);
|
||||
await waitForElement(() => getByText("no more pending", { exact: false }));
|
||||
});
|
||||
|
||||
it("renders empty unmoderated queue", async () => {
|
||||
replaceHistoryLocation("http://localhost/admin/moderate/unmoderated");
|
||||
const testRenderer = await createTestRenderer();
|
||||
const { getByText } = within(testRenderer.root);
|
||||
await waitForElement(() =>
|
||||
getByText("comments have been moderated", { exact: false })
|
||||
);
|
||||
});
|
||||
|
||||
it("renders empty rejected queue", async () => {
|
||||
replaceHistoryLocation("http://localhost/admin/moderate/rejected");
|
||||
const testRenderer = await createTestRenderer();
|
||||
const { getByText } = within(testRenderer.root);
|
||||
await waitForElement(() =>
|
||||
getByText("no rejected comments", { exact: false })
|
||||
);
|
||||
});
|
||||
|
||||
it("renders reported queue with comments", async () => {
|
||||
const testRenderer = await createTestRenderer({
|
||||
resolvers: createResolversStub<GQLResolver>({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { withStyles } from "talk-ui/hocs";
|
||||
|
||||
import styles from "./Card.css";
|
||||
|
||||
export interface CardProps {
|
||||
export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* The content of the component.
|
||||
*/
|
||||
|
||||
@@ -319,6 +319,11 @@ moderate-marker-karma = Karma
|
||||
moderate-marker-bodyCount = Body Count
|
||||
moderate-marker-offensive = Offensive
|
||||
|
||||
moderate-emptyQueue-pending = Nicely done! There are no more pending comments to moderate.
|
||||
moderate-emptyQueue-reported = Nicely done! There are no more reported comments to moderate.
|
||||
moderate-emptyQueue-unmoderated = Nicely done! All comments have been moderated.
|
||||
moderate-emptyQueue-rejected = There are no rejected comments.
|
||||
|
||||
moderate-inReplyTo = Reply to <username><username>
|
||||
moderate-viewContext = View Context
|
||||
moderate-rejectButton =
|
||||
|
||||
Reference in New Issue
Block a user