mirror of
https://github.com/wassname/talk.git
synced 2026-08-02 13:10:23 +08:00
[CORL-218] In Stream Approve and Reject (#2340)
* feat: instream moderation * fix: tests * test: add tests for in stream moderation * fix: lint * fix: snapshots
This commit is contained in:
@@ -22,10 +22,10 @@ const UserBoxAuthenticated: FunctionComponent<
|
||||
<Flex itemGutter="half" wrap>
|
||||
<Localized
|
||||
id="general-userBoxAuthenticated-signedInAs"
|
||||
username={<Username />}
|
||||
Username={<Username />}
|
||||
>
|
||||
<Typography variant="bodyCopy" container="div">
|
||||
{"Signed in as <username></username>."}
|
||||
{"Signed in as <Username></Username>."}
|
||||
</Typography>
|
||||
</Localized>
|
||||
{props.showLogoutButton && (
|
||||
|
||||
+4
-4
@@ -6,14 +6,14 @@ exports[`renders correctly with logout button 1`] = `
|
||||
wrap={true}
|
||||
>
|
||||
<Localized
|
||||
Username={<Username />}
|
||||
id="general-userBoxAuthenticated-signedInAs"
|
||||
username={<Username />}
|
||||
>
|
||||
<ForwardRef(forwardRef)
|
||||
container="div"
|
||||
variant="bodyCopy"
|
||||
>
|
||||
Signed in as <username></username>.
|
||||
Signed in as <Username></Username>.
|
||||
</ForwardRef(forwardRef)>
|
||||
</Localized>
|
||||
<Localized
|
||||
@@ -48,14 +48,14 @@ exports[`renders correctly without logout button 1`] = `
|
||||
wrap={true}
|
||||
>
|
||||
<Localized
|
||||
Username={<Username />}
|
||||
id="general-userBoxAuthenticated-signedInAs"
|
||||
username={<Username />}
|
||||
>
|
||||
<ForwardRef(forwardRef)
|
||||
container="div"
|
||||
variant="bodyCopy"
|
||||
>
|
||||
Signed in as <username></username>.
|
||||
Signed in as <Username></Username>.
|
||||
</ForwardRef(forwardRef)>
|
||||
</Localized>
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
enum View {
|
||||
enum VIEW {
|
||||
SIGN_UP
|
||||
SIGN_IN
|
||||
FORGOT_PASSWORD
|
||||
}
|
||||
|
||||
enum Tab {
|
||||
enum TAB {
|
||||
COMMENTS
|
||||
PROFILE
|
||||
}
|
||||
|
||||
enum ProfileTab {
|
||||
enum PROFILE_TAB {
|
||||
MY_COMMENTS
|
||||
SETTINGS
|
||||
}
|
||||
|
||||
enum COMMENT_VIEWER_ACTION {
|
||||
EDIT
|
||||
ACCEPT
|
||||
REJECT
|
||||
}
|
||||
|
||||
type AuthPopup {
|
||||
open: Boolean!
|
||||
focus: Boolean!
|
||||
view: View
|
||||
view: VIEW
|
||||
}
|
||||
|
||||
extend type Comment {
|
||||
@@ -26,6 +32,9 @@ extend type Comment {
|
||||
# localReplies contains only comments created by the user
|
||||
# on the ultimate threading level.
|
||||
localReplies: [Comment!]
|
||||
|
||||
# Remember last viewer action that could have caused a status change.
|
||||
lastViewerAction: COMMENT_VIEWER_ACTION
|
||||
}
|
||||
|
||||
type Local {
|
||||
@@ -33,13 +42,13 @@ type Local {
|
||||
accessTokenExp: Int
|
||||
accessTokenJTI: String
|
||||
loggedIn: Boolean!
|
||||
activeTab: Tab!
|
||||
activeTab: TAB!
|
||||
authPopup: AuthPopup!
|
||||
storyID: String
|
||||
storyURL: String
|
||||
commentID: String
|
||||
defaultStreamOrderBy: COMMENT_SORT!
|
||||
profileTab: ProfileTab!
|
||||
profileTab: PROFILE_TAB!
|
||||
bla: [String]
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ function createDefaultProps(add: DeepPartial<Props> = {}): Props {
|
||||
},
|
||||
pending: false,
|
||||
tags: [],
|
||||
lastViewerAction: null,
|
||||
},
|
||||
settings: {
|
||||
disableCommenting: {
|
||||
|
||||
@@ -3,9 +3,9 @@ import React, { Component, MouseEvent } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { isBeforeDate } from "coral-common/utils";
|
||||
import { getURLWithCommentID } from "coral-framework/helpers";
|
||||
import { getURLWithCommentID, roleIsAtLeast } from "coral-framework/helpers";
|
||||
import withFragmentContainer from "coral-framework/lib/relay/withFragmentContainer";
|
||||
import { GQLUSER_STATUS } from "coral-framework/schema";
|
||||
import { GQLUSER_ROLE, GQLUSER_STATUS } from "coral-framework/schema";
|
||||
import { PropTypesOf } from "coral-framework/types";
|
||||
import { CommentContainer_comment as CommentData } from "coral-stream/__generated__/CommentContainer_comment.graphql";
|
||||
import { CommentContainer_settings as SettingsData } from "coral-stream/__generated__/CommentContainer_settings.graphql";
|
||||
@@ -23,6 +23,9 @@ import { isCommentVisible } from "../helpers";
|
||||
import ButtonsBar from "./ButtonsBar";
|
||||
import EditCommentFormContainer from "./EditCommentForm";
|
||||
import IndentedComment from "./IndentedComment";
|
||||
import CaretContainer, {
|
||||
RejectedTombstoneContainer,
|
||||
} from "./ModerationDropdown";
|
||||
import PermalinkButtonContainer from "./PermalinkButton";
|
||||
import ReactionButtonContainer from "./ReactionButton";
|
||||
import ReplyButton from "./ReplyButton";
|
||||
@@ -158,6 +161,9 @@ export class CommentContainer extends Component<Props, State> {
|
||||
this.props.viewer &&
|
||||
this.props.viewer.status.current.includes(GQLUSER_STATUS.BANNED)
|
||||
);
|
||||
const showCaret =
|
||||
this.props.viewer &&
|
||||
roleIsAtLeast(this.props.viewer.role, GQLUSER_ROLE.MODERATOR);
|
||||
if (showEditDialog) {
|
||||
return (
|
||||
<div data-testid={`comment-${comment.id}`}>
|
||||
@@ -170,10 +176,15 @@ export class CommentContainer extends Component<Props, State> {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Comment is not visible, so don't render it.
|
||||
// This is the case when the comment was just edited and
|
||||
// the comment status has changed.
|
||||
if (!isCommentVisible(comment)) {
|
||||
// Comment is not visible after viewer rejected it.
|
||||
if (
|
||||
comment.lastViewerAction === "REJECT" &&
|
||||
comment.status === "REJECTED"
|
||||
) {
|
||||
return <RejectedTombstoneContainer comment={comment} />;
|
||||
}
|
||||
// Comment is not visible after edit, so don't render it anymore.
|
||||
if (comment.lastViewerAction === "EDIT" && !isCommentVisible(comment)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
@@ -201,18 +212,20 @@ export class CommentContainer extends Component<Props, State> {
|
||||
}
|
||||
tags={comment.tags.map(t => t.name)}
|
||||
topBarRight={
|
||||
(editable && (
|
||||
<Localized id="comments-commentContainer-editButton">
|
||||
<Button
|
||||
color="primary"
|
||||
variant="underlined"
|
||||
onClick={this.openEditDialog}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Localized>
|
||||
)) ||
|
||||
undefined
|
||||
<Flex itemGutter>
|
||||
{editable && (
|
||||
<Localized id="comments-commentContainer-editButton">
|
||||
<Button
|
||||
color="primary"
|
||||
variant="underlined"
|
||||
onClick={this.openEditDialog}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Localized>
|
||||
)}
|
||||
{showCaret && <CaretContainer comment={comment} />}
|
||||
</Flex>
|
||||
}
|
||||
footer={
|
||||
<>
|
||||
@@ -292,6 +305,7 @@ const enhanced = withSetCommentIDMutation(
|
||||
ignoredUsers {
|
||||
id
|
||||
}
|
||||
role
|
||||
...UsernameWithPopoverContainer_viewer
|
||||
...ReactionButtonContainer_viewer
|
||||
...ReportButtonContainer_viewer
|
||||
@@ -330,10 +344,13 @@ const enhanced = withSetCommentIDMutation(
|
||||
name
|
||||
}
|
||||
pending
|
||||
lastViewerAction
|
||||
...ReplyCommentFormContainer_comment
|
||||
...EditCommentFormContainer_comment
|
||||
...ReactionButtonContainer_comment
|
||||
...ReportButtonContainer_comment
|
||||
...CaretContainer_comment
|
||||
...RejectedTombstoneContainer_comment
|
||||
}
|
||||
`,
|
||||
settings: graphql`
|
||||
|
||||
@@ -51,7 +51,10 @@ function commit(environment: Environment, input: EditCommentInput) {
|
||||
},
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
|
||||
},
|
||||
updater: store => {
|
||||
store.get(input.commentID)!.setValue("EDIT", "lastViewerAction");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@ const InReplyTo: FunctionComponent<Props> = ({ username }) => {
|
||||
return (
|
||||
<Flex alignItems="center">
|
||||
<Icon className={styles.icon}>reply</Icon>{" "}
|
||||
<Localized id="comments-inReplyTo" username={<Username />}>
|
||||
<Localized id="comments-inReplyTo" Username={<Username />}>
|
||||
<Typography
|
||||
variant="timestamp"
|
||||
container="span"
|
||||
className={styles.inReplyTo}
|
||||
>
|
||||
{"In reply to <username><username>"}
|
||||
{"In reply to <Username></Username>"}
|
||||
</Typography>
|
||||
</Localized>
|
||||
</Flex>
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { graphql } from "react-relay";
|
||||
import { Environment } from "relay-runtime";
|
||||
|
||||
import {
|
||||
commitMutationPromiseNormalized,
|
||||
createMutation,
|
||||
MutationInput,
|
||||
} from "coral-framework/lib/relay";
|
||||
import { AcceptCommentMutation as MutationTypes } from "coral-stream/__generated__/AcceptCommentMutation.graphql";
|
||||
|
||||
let clientMutationId = 0;
|
||||
|
||||
const AcceptCommentMutation = createMutation(
|
||||
"acceptComment",
|
||||
(environment: Environment, input: MutationInput<MutationTypes>) =>
|
||||
commitMutationPromiseNormalized<MutationTypes>(environment, {
|
||||
mutation: graphql`
|
||||
mutation AcceptCommentMutation($input: AcceptCommentInput!) {
|
||||
acceptComment(input: $input) {
|
||||
comment {
|
||||
status
|
||||
}
|
||||
clientMutationId
|
||||
}
|
||||
}
|
||||
`,
|
||||
optimisticResponse: {
|
||||
acceptComment: {
|
||||
comment: {
|
||||
status: "ACCEPTED",
|
||||
},
|
||||
},
|
||||
},
|
||||
variables: {
|
||||
input: {
|
||||
...input,
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
},
|
||||
updater: store => {
|
||||
store.get(input.commentID)!.setValue("ACCEPT", "lastViewerAction");
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
export default AcceptCommentMutation;
|
||||
@@ -0,0 +1,3 @@
|
||||
.root {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { CaretContainer_comment as CommentData } from "coral-stream/__generated__/CaretContainer_comment.graphql";
|
||||
import { Button, ClickOutside, Icon, Popover } from "coral-ui/components";
|
||||
|
||||
import ModerationDropdownContainer from "./ModerationDropdownContainer";
|
||||
|
||||
import styles from "./CaretContainer.css";
|
||||
|
||||
interface Props {
|
||||
comment: CommentData;
|
||||
}
|
||||
|
||||
const CaretContainer: FunctionComponent<Props> = props => {
|
||||
const popoverID = `comments-moderationMenu`;
|
||||
return (
|
||||
<Localized
|
||||
id="comments-moderationDropdown-popover"
|
||||
attrs={{ description: true }}
|
||||
>
|
||||
<Popover
|
||||
id={popoverID}
|
||||
placement="bottom-end"
|
||||
description="A popover menu to moderate the comment"
|
||||
body={({ toggleVisibility }) => (
|
||||
<ClickOutside onClickOutside={toggleVisibility}>
|
||||
<ModerationDropdownContainer
|
||||
comment={props.comment}
|
||||
onDismiss={toggleVisibility}
|
||||
/>
|
||||
</ClickOutside>
|
||||
)}
|
||||
>
|
||||
{({ toggleVisibility, visible, ref }) => (
|
||||
<Localized
|
||||
id="comments-moderationDropdown-caretButton"
|
||||
attrs={{ "aria-label": true }}
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="small"
|
||||
className={styles.root}
|
||||
onClick={toggleVisibility}
|
||||
aria-controls={popoverID}
|
||||
active={visible}
|
||||
ref={ref}
|
||||
aria-label="Moderate"
|
||||
>
|
||||
<Icon>{visible ? "expand_less" : "expand_more"}</Icon>
|
||||
</Button>
|
||||
</Localized>
|
||||
)}
|
||||
</Popover>
|
||||
</Localized>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
comment: graphql`
|
||||
fragment CaretContainer_comment on Comment {
|
||||
...ModerationDropdownContainer_comment
|
||||
}
|
||||
`,
|
||||
})(CaretContainer);
|
||||
|
||||
export default enhanced;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
.approved {
|
||||
color: var(--palette-success-dark);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
.rejected {
|
||||
color: var(--palette-error-dark);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { FunctionComponent, useCallback } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { useMutation, withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { ModerationDropdownContainer_comment as CommentData } from "coral-stream/__generated__/ModerationDropdownContainer_comment.graphql";
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownButton,
|
||||
DropdownDivider,
|
||||
Icon,
|
||||
} from "coral-ui/components";
|
||||
|
||||
import AcceptCommentMutation from "./AcceptCommentMutation";
|
||||
import styles from "./ModerationDropdownContainer.css";
|
||||
import RejectCommentMutation from "./RejectCommentMutation";
|
||||
|
||||
interface Props {
|
||||
comment: CommentData;
|
||||
onDismiss: () => void;
|
||||
}
|
||||
|
||||
const ModerationDropdownContainer: FunctionComponent<Props> = ({
|
||||
comment,
|
||||
onDismiss,
|
||||
}) => {
|
||||
const accept = useMutation(AcceptCommentMutation);
|
||||
const reject = useMutation(RejectCommentMutation);
|
||||
|
||||
const onAccept = useCallback(() => {
|
||||
accept({ commentID: comment.id, commentRevisionID: comment.revision.id });
|
||||
}, [accept, comment]);
|
||||
const onReject = useCallback(
|
||||
() =>
|
||||
reject({ commentID: comment.id, commentRevisionID: comment.revision.id }),
|
||||
[accept, comment]
|
||||
);
|
||||
|
||||
const accepted = comment.status === "ACCEPTED";
|
||||
const rejected = comment.status === "REJECTED";
|
||||
|
||||
return (
|
||||
<Dropdown>
|
||||
{accepted ? (
|
||||
<Localized id="comments-moderationDropdown-approved">
|
||||
<DropdownButton
|
||||
icon={<Icon className={styles.approved}>check</Icon>}
|
||||
className={styles.approved}
|
||||
disabled
|
||||
>
|
||||
Approved
|
||||
</DropdownButton>
|
||||
</Localized>
|
||||
) : (
|
||||
<Localized id="comments-moderationDropdown-approve">
|
||||
<DropdownButton icon={<Icon>check</Icon>} onClick={onAccept}>
|
||||
Approve
|
||||
</DropdownButton>
|
||||
</Localized>
|
||||
)}
|
||||
{rejected ? (
|
||||
<Localized id="comments-moderationDropdown-rejected">
|
||||
<DropdownButton
|
||||
icon={<Icon className={styles.rejected}>close</Icon>}
|
||||
className={styles.rejected}
|
||||
disabled
|
||||
>
|
||||
Rejected
|
||||
</DropdownButton>
|
||||
</Localized>
|
||||
) : (
|
||||
<Localized id="comments-moderationDropdown-reject">
|
||||
<DropdownButton icon={<Icon>close</Icon>} onClick={onReject}>
|
||||
Reject
|
||||
</DropdownButton>
|
||||
</Localized>
|
||||
)}
|
||||
<DropdownDivider />
|
||||
<Localized id="comments-moderationDropdown-goToModerate">
|
||||
<DropdownButton
|
||||
href={`/admin/moderate/comment/${comment.id}`}
|
||||
target="_blank"
|
||||
anchor
|
||||
>
|
||||
Go to Moderate
|
||||
</DropdownButton>
|
||||
</Localized>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
comment: graphql`
|
||||
fragment ModerationDropdownContainer_comment on Comment {
|
||||
id
|
||||
revision {
|
||||
id
|
||||
}
|
||||
status
|
||||
}
|
||||
`,
|
||||
})(ModerationDropdownContainer);
|
||||
|
||||
export default enhanced;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { graphql } from "react-relay";
|
||||
import { Environment } from "relay-runtime";
|
||||
|
||||
import {
|
||||
commitMutationPromiseNormalized,
|
||||
createMutation,
|
||||
MutationInput,
|
||||
} from "coral-framework/lib/relay";
|
||||
import { RejectCommentMutation as MutationTypes } from "coral-stream/__generated__/RejectCommentMutation.graphql";
|
||||
|
||||
let clientMutationId = 0;
|
||||
|
||||
const RejectCommentMutation = createMutation(
|
||||
"rejectComment",
|
||||
(environment: Environment, input: MutationInput<MutationTypes>) =>
|
||||
commitMutationPromiseNormalized<MutationTypes>(environment, {
|
||||
mutation: graphql`
|
||||
mutation RejectCommentMutation($input: RejectCommentInput!) {
|
||||
rejectComment(input: $input) {
|
||||
comment {
|
||||
status
|
||||
}
|
||||
clientMutationId
|
||||
}
|
||||
}
|
||||
`,
|
||||
optimisticResponse: {
|
||||
rejectComment: {
|
||||
comment: {
|
||||
status: "REJECTED",
|
||||
},
|
||||
},
|
||||
},
|
||||
variables: {
|
||||
input: {
|
||||
...input,
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
},
|
||||
updater: store => {
|
||||
store.get(input.commentID)!.setValue("REJECT", "lastViewerAction");
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
export default RejectCommentMutation;
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import React, { FunctionComponent, useMemo } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { RejectedTombstoneContainer_comment as CommentData } from "coral-stream/__generated__/RejectedTombstoneContainer_comment.graphql";
|
||||
import { CallOut, TextLink } from "coral-ui/components";
|
||||
import { Localized } from "fluent-react/compat";
|
||||
|
||||
interface Props {
|
||||
comment: CommentData;
|
||||
}
|
||||
|
||||
const RejectedTombstoneContainer: FunctionComponent<Props> = ({ comment }) => {
|
||||
const Link = useMemo<React.FunctionComponent>(
|
||||
() => ({ children }) => (
|
||||
<TextLink href={`/admin/moderate/comment/${comment.id}`} target="_blank">
|
||||
{children}
|
||||
</TextLink>
|
||||
),
|
||||
[comment]
|
||||
);
|
||||
return (
|
||||
<CallOut color="primary" fullWidth>
|
||||
<Localized id="comments-rejectedTombstone" TextLink={<Link />}>
|
||||
<div>
|
||||
You have rejected this comment.{" "}
|
||||
<Link>Go to Moderate to review this decision.</Link>
|
||||
</div>
|
||||
</Localized>
|
||||
</CallOut>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
comment: graphql`
|
||||
fragment RejectedTombstoneContainer_comment on Comment {
|
||||
id
|
||||
}
|
||||
`,
|
||||
})(RejectedTombstoneContainer);
|
||||
|
||||
export default enhanced;
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default, default as CaretContainer } from "./CaretContainer";
|
||||
export {
|
||||
default as RejectedTombstoneContainer,
|
||||
} from "./RejectedTombstoneContainer";
|
||||
+2
-2
@@ -52,10 +52,10 @@ function commit(environment: Environment, input: CreateCommentReactionInput) {
|
||||
total: currentCount + 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any,
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -51,10 +51,10 @@ function commit(environment: Environment, input: RemoveCommentReactionInput) {
|
||||
total: currentCount - 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any,
|
||||
clientMutationId: clientMutationId.toString(),
|
||||
},
|
||||
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ function commit(
|
||||
},
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
|
||||
},
|
||||
optimisticUpdater: store => {
|
||||
// Skip optimistic update if comment is probably premoderated.
|
||||
if (expectPremoderation) {
|
||||
|
||||
@@ -19,9 +19,9 @@ const ReplyTo: FunctionComponent<Props> = ({ username }) => {
|
||||
return (
|
||||
<Flex alignItems="center" className={styles.root}>
|
||||
<Icon>reply</Icon>{" "}
|
||||
<Localized id="comments-replyTo" username={<Username />}>
|
||||
<Localized id="comments-replyTo" Username={<Username />}>
|
||||
<Typography container="span" className={styles.text}>
|
||||
{"Replying to: <username></username>"}
|
||||
{"Replying to: <Username></Username>"}
|
||||
</Typography>
|
||||
</Localized>
|
||||
</Flex>
|
||||
|
||||
+2
-2
@@ -10,14 +10,14 @@ exports[`renders correctly 1`] = `
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
<Localized
|
||||
Username={<Username />}
|
||||
id="comments-replyTo"
|
||||
username={<Username />}
|
||||
>
|
||||
<ForwardRef(forwardRef)
|
||||
className="ReplyTo-text"
|
||||
container="span"
|
||||
>
|
||||
Replying to: <username></username>
|
||||
Replying to: <Username></Username>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Localized>
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
+56
@@ -29,6 +29,7 @@ exports[`hide reply button 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -70,6 +71,7 @@ exports[`hide reply button 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -86,6 +88,11 @@ exports[`hide reply button 1`] = `
|
||||
parentAuthorName={null}
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -131,6 +138,7 @@ exports[`renders body only 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -178,6 +186,7 @@ exports[`renders body only 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -194,6 +203,11 @@ exports[`renders body only 1`] = `
|
||||
parentAuthorName={null}
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -239,6 +253,7 @@ exports[`renders disabled reply when commenting has been disabled 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -286,6 +301,7 @@ exports[`renders disabled reply when commenting has been disabled 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -302,6 +318,11 @@ exports[`renders disabled reply when commenting has been disabled 1`] = `
|
||||
parentAuthorName={null}
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -347,6 +368,7 @@ exports[`renders disabled reply when story is closed 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -394,6 +416,7 @@ exports[`renders disabled reply when story is closed 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -410,6 +433,11 @@ exports[`renders disabled reply when story is closed 1`] = `
|
||||
parentAuthorName={null}
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -455,6 +483,7 @@ exports[`renders in reply to 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": Object {
|
||||
"author": Object {
|
||||
"username": "ParentAuthor",
|
||||
@@ -506,6 +535,7 @@ exports[`renders in reply to 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": Object {
|
||||
"author": Object {
|
||||
"username": "ParentAuthor",
|
||||
@@ -526,6 +556,11 @@ exports[`renders in reply to 1`] = `
|
||||
parentAuthorName="ParentAuthor"
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -571,6 +606,7 @@ exports[`renders staff badge 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -622,6 +658,7 @@ exports[`renders staff badge 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -646,6 +683,11 @@ exports[`renders staff badge 1`] = `
|
||||
"Staff",
|
||||
]
|
||||
}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -691,6 +733,7 @@ exports[`renders username and body 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -738,6 +781,7 @@ exports[`renders username and body 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -754,6 +798,11 @@ exports[`renders username and body 1`] = `
|
||||
parentAuthorName={null}
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
@@ -799,6 +848,7 @@ exports[`shows conversation link 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -846,6 +896,7 @@ exports[`shows conversation link 1`] = `
|
||||
"edited": false,
|
||||
},
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"parent": null,
|
||||
"pending": false,
|
||||
"status": "NONE",
|
||||
@@ -867,6 +918,11 @@ exports[`shows conversation link 1`] = `
|
||||
parentAuthorName={null}
|
||||
showEditedMarker={false}
|
||||
tags={Array []}
|
||||
topBarRight={
|
||||
<ForwardRef(forwardRef)
|
||||
itemGutter={true}
|
||||
/>
|
||||
}
|
||||
username={
|
||||
<Relay(UsernameWithPopoverContainer)
|
||||
user={
|
||||
|
||||
@@ -11,15 +11,15 @@ exports[`renders correctly 1`] = `
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
<Localized
|
||||
Username={<Username />}
|
||||
id="comments-inReplyTo"
|
||||
username={<Username />}
|
||||
>
|
||||
<ForwardRef(forwardRef)
|
||||
className="InReplyTo-inReplyTo"
|
||||
container="span"
|
||||
variant="timestamp"
|
||||
>
|
||||
In reply to <username><username>
|
||||
In reply to <Username></Username>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Localized>
|
||||
</ForwardRef(forwardRef)>
|
||||
|
||||
+6
-6
@@ -8,8 +8,8 @@ import React, {
|
||||
|
||||
import { usePrevious } from "coral-framework/hooks";
|
||||
import { graphql, withFragmentContainer } from "coral-framework/lib/relay";
|
||||
import { TombstoneOrHideContainer_comment as CommentData } from "coral-stream/__generated__/TombstoneOrHideContainer_comment.graphql";
|
||||
import { TombstoneOrHideContainer_viewer as ViewerData } from "coral-stream/__generated__/TombstoneOrHideContainer_viewer.graphql";
|
||||
import { IgnoredTombstoneOrHideContainer_comment as CommentData } from "coral-stream/__generated__/IgnoredTombstoneOrHideContainer_comment.graphql";
|
||||
import { IgnoredTombstoneOrHideContainer_viewer as ViewerData } from "coral-stream/__generated__/IgnoredTombstoneOrHideContainer_viewer.graphql";
|
||||
import { CallOut } from "coral-ui/components";
|
||||
|
||||
interface Props {
|
||||
@@ -37,7 +37,7 @@ const useTombstone = (hide: boolean) => {
|
||||
return tombstone;
|
||||
};
|
||||
|
||||
const TombstoneOrHideContainer: FunctionComponent<Props> = ({
|
||||
const IgnoredTombstoneOrHideContainer: FunctionComponent<Props> = ({
|
||||
viewer,
|
||||
comment,
|
||||
children,
|
||||
@@ -70,20 +70,20 @@ const TombstoneOrHideContainer: FunctionComponent<Props> = ({
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
viewer: graphql`
|
||||
fragment TombstoneOrHideContainer_viewer on User {
|
||||
fragment IgnoredTombstoneOrHideContainer_viewer on User {
|
||||
ignoredUsers {
|
||||
id
|
||||
}
|
||||
}
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment TombstoneOrHideContainer_comment on Comment {
|
||||
fragment IgnoredTombstoneOrHideContainer_comment on Comment {
|
||||
author {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
`,
|
||||
})(TombstoneOrHideContainer);
|
||||
})(IgnoredTombstoneOrHideContainer);
|
||||
|
||||
export default enhanced;
|
||||
@@ -47,7 +47,7 @@ const enhanced = withFragmentContainer<Props>({
|
||||
viewer: graphql`
|
||||
fragment LocalReplyListContainer_viewer on User {
|
||||
...CommentContainer_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
}
|
||||
`,
|
||||
story: graphql`
|
||||
@@ -61,7 +61,7 @@ const enhanced = withFragmentContainer<Props>({
|
||||
localReplies {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -6,13 +6,13 @@ import { PropTypesOf } from "coral-framework/types";
|
||||
import { Button, HorizontalGutter } from "coral-ui/components";
|
||||
|
||||
import CommentContainer from "../Comment";
|
||||
import IgnoredTombstoneOrHideContainer from "../IgnoredTombstoneOrHideContainer";
|
||||
import Indent from "../Indent";
|
||||
import TombstoneOrHideContainer from "../TombstoneOrHideContainer";
|
||||
|
||||
export interface ReplyListProps {
|
||||
story: PropTypesOf<typeof CommentContainer>["story"];
|
||||
viewer: PropTypesOf<typeof CommentContainer>["viewer"] &
|
||||
PropTypesOf<typeof TombstoneOrHideContainer>["viewer"];
|
||||
PropTypesOf<typeof IgnoredTombstoneOrHideContainer>["viewer"];
|
||||
comment: {
|
||||
id: string;
|
||||
};
|
||||
@@ -22,7 +22,7 @@ export interface ReplyListProps {
|
||||
replyListElement?: React.ReactElement<any>;
|
||||
showConversationLink?: boolean;
|
||||
} & PropTypesOf<typeof CommentContainer>["comment"] &
|
||||
PropTypesOf<typeof TombstoneOrHideContainer>["comment"]
|
||||
PropTypesOf<typeof IgnoredTombstoneOrHideContainer>["comment"]
|
||||
>;
|
||||
settings: PropTypesOf<typeof CommentContainer>["settings"];
|
||||
onShowAll?: () => void;
|
||||
@@ -41,7 +41,7 @@ const ReplyList: FunctionComponent<ReplyListProps> = props => {
|
||||
role="log"
|
||||
>
|
||||
{props.comments.map(comment => (
|
||||
<TombstoneOrHideContainer
|
||||
<IgnoredTombstoneOrHideContainer
|
||||
key={comment.id}
|
||||
viewer={props.viewer}
|
||||
comment={comment}
|
||||
@@ -60,7 +60,7 @@ const ReplyList: FunctionComponent<ReplyListProps> = props => {
|
||||
/>
|
||||
{comment.replyListElement}
|
||||
</HorizontalGutter>
|
||||
</TombstoneOrHideContainer>
|
||||
</IgnoredTombstoneOrHideContainer>
|
||||
))}
|
||||
{props.hasMore && (
|
||||
<Indent level={props.indentLevel} noBorder>
|
||||
|
||||
@@ -22,6 +22,7 @@ it("renders correctly", () => {
|
||||
replies: {
|
||||
edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }],
|
||||
},
|
||||
lastViewerAction: null,
|
||||
},
|
||||
settings: {
|
||||
reaction: {
|
||||
@@ -51,6 +52,7 @@ it("renders correctly when replies are empty", () => {
|
||||
id: "comment-id",
|
||||
status: "NONE",
|
||||
replies: { edges: [] },
|
||||
lastViewerAction: null,
|
||||
},
|
||||
relay: {
|
||||
hasMore: noop,
|
||||
@@ -83,6 +85,7 @@ describe("when has more replies", () => {
|
||||
replies: {
|
||||
edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }],
|
||||
},
|
||||
lastViewerAction: null,
|
||||
},
|
||||
settings: {
|
||||
reaction: {
|
||||
|
||||
@@ -53,27 +53,25 @@ export class ReplyListContainer extends React.Component<Props> {
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
// Don't render replies if comment is not visible.
|
||||
// We have this comment here because it's
|
||||
// status just changed due to an edit.
|
||||
// We keep it around for the CommentContainer to show
|
||||
// some information to the user.
|
||||
const comments = !isCommentVisible(this.props.comment)
|
||||
? []
|
||||
: this.props.comment.replies.edges.map(edge => ({
|
||||
...edge.node,
|
||||
replyListElement: this.props.ReplyListComponent && (
|
||||
<this.props.ReplyListComponent
|
||||
viewer={this.props.viewer}
|
||||
comment={edge.node}
|
||||
story={this.props.story}
|
||||
settings={this.props.settings}
|
||||
/>
|
||||
),
|
||||
// ReplyListContainer5 contains replyCount.
|
||||
showConversationLink:
|
||||
((edge.node as any) as ReplyNode5).replyCount > 0,
|
||||
}));
|
||||
const comments =
|
||||
// Comment is not visible after a viewer action, so don't render it anymore.
|
||||
this.props.comment.lastViewerAction &&
|
||||
!isCommentVisible(this.props.comment)
|
||||
? []
|
||||
: this.props.comment.replies.edges.map(edge => ({
|
||||
...edge.node,
|
||||
replyListElement: this.props.ReplyListComponent && (
|
||||
<this.props.ReplyListComponent
|
||||
viewer={this.props.viewer}
|
||||
comment={edge.node}
|
||||
story={this.props.story}
|
||||
settings={this.props.settings}
|
||||
/>
|
||||
),
|
||||
// ReplyListContainer5 contains replyCount.
|
||||
showConversationLink:
|
||||
((edge.node as any) as ReplyNode5).replyCount > 0,
|
||||
}));
|
||||
return (
|
||||
<ReplyList
|
||||
viewer={this.props.viewer}
|
||||
@@ -164,7 +162,7 @@ const ReplyListContainer5 = createReplyListContainer(
|
||||
viewer: graphql`
|
||||
fragment ReplyListContainer5_viewer on User {
|
||||
...CommentContainer_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
...LocalReplyListContainer_viewer
|
||||
}
|
||||
`,
|
||||
@@ -189,6 +187,7 @@ const ReplyListContainer5 = createReplyListContainer(
|
||||
) {
|
||||
id
|
||||
status
|
||||
lastViewerAction
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
@@ -196,7 +195,7 @@ const ReplyListContainer5 = createReplyListContainer(
|
||||
id
|
||||
replyCount
|
||||
...CommentContainer_comment
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
...LocalReplyListContainer_comment
|
||||
}
|
||||
}
|
||||
@@ -230,7 +229,7 @@ const ReplyListContainer4 = createReplyListContainer(
|
||||
fragment ReplyListContainer4_viewer on User {
|
||||
...ReplyListContainer5_viewer
|
||||
...CommentContainer_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
}
|
||||
`,
|
||||
settings: graphql`
|
||||
@@ -254,13 +253,14 @@ const ReplyListContainer4 = createReplyListContainer(
|
||||
) {
|
||||
id
|
||||
status
|
||||
lastViewerAction
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
...ReplyListContainer5_comment
|
||||
}
|
||||
}
|
||||
@@ -293,7 +293,7 @@ const ReplyListContainer3 = createReplyListContainer(
|
||||
fragment ReplyListContainer3_viewer on User {
|
||||
...ReplyListContainer4_viewer
|
||||
...CommentContainer_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
}
|
||||
`,
|
||||
settings: graphql`
|
||||
@@ -317,13 +317,14 @@ const ReplyListContainer3 = createReplyListContainer(
|
||||
) {
|
||||
id
|
||||
status
|
||||
lastViewerAction
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
...ReplyListContainer4_comment
|
||||
}
|
||||
}
|
||||
@@ -356,7 +357,7 @@ const ReplyListContainer2 = createReplyListContainer(
|
||||
fragment ReplyListContainer2_viewer on User {
|
||||
...ReplyListContainer3_viewer
|
||||
...CommentContainer_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
}
|
||||
`,
|
||||
settings: graphql`
|
||||
@@ -380,13 +381,14 @@ const ReplyListContainer2 = createReplyListContainer(
|
||||
) {
|
||||
id
|
||||
status
|
||||
lastViewerAction
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
...ReplyListContainer3_comment
|
||||
}
|
||||
}
|
||||
@@ -419,7 +421,7 @@ const ReplyListContainer1 = createReplyListContainer(
|
||||
fragment ReplyListContainer1_viewer on User {
|
||||
...ReplyListContainer2_viewer
|
||||
...CommentContainer_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
}
|
||||
`,
|
||||
settings: graphql`
|
||||
@@ -443,13 +445,14 @@ const ReplyListContainer1 = createReplyListContainer(
|
||||
) {
|
||||
id
|
||||
status
|
||||
lastViewerAction
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
...ReplyListContainer2_comment
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -6,7 +6,7 @@ exports[`renders correctly 1`] = `
|
||||
id="coral-comments-replyList-log--comment-id"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -45,8 +45,8 @@ exports[`renders correctly 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -87,7 +87,7 @@ exports[`renders correctly 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
</ForwardRef(forwardRef)>
|
||||
`;
|
||||
|
||||
@@ -97,7 +97,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
id="coral-comments-replyList-log--comment-id"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -134,8 +134,8 @@ exports[`when there is more disables load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -172,7 +172,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Indent
|
||||
level={1}
|
||||
noBorder={true}
|
||||
@@ -201,7 +201,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
id="coral-comments-replyList-log--comment-id"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -238,8 +238,8 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -276,7 +276,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Indent
|
||||
level={1}
|
||||
noBorder={true}
|
||||
|
||||
+4
@@ -5,6 +5,7 @@ exports[`renders correctly 1`] = `
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"replies": Object {
|
||||
"edges": Array [
|
||||
Object {
|
||||
@@ -104,6 +105,7 @@ exports[`when has more replies renders hasMore 1`] = `
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"replies": Object {
|
||||
"edges": Array [
|
||||
Object {
|
||||
@@ -162,6 +164,7 @@ exports[`when has more replies when showing all disables show all button 1`] = `
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"replies": Object {
|
||||
"edges": Array [
|
||||
Object {
|
||||
@@ -220,6 +223,7 @@ exports[`when has more replies when showing all enable show all button after loa
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-id",
|
||||
"lastViewerAction": null,
|
||||
"replies": Object {
|
||||
"edges": Array [
|
||||
Object {
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ function commit(
|
||||
},
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
|
||||
},
|
||||
optimisticUpdater: store => {
|
||||
// Skip optimistic update if comment is probably premoderated.
|
||||
if (expectPremoderation) {
|
||||
|
||||
@@ -7,8 +7,8 @@ import UserBoxContainer from "coral-stream/common/UserBox";
|
||||
import { Button, Flex, HorizontalGutter, Spinner } from "coral-ui/components";
|
||||
|
||||
import CommentContainer from "../Comment";
|
||||
import IgnoredTombstoneOrHideContainer from "../IgnoredTombstoneOrHideContainer";
|
||||
import ReplyListContainer from "../ReplyList";
|
||||
import TombstoneOrHideContainer from "../TombstoneOrHideContainer";
|
||||
import BannedInfo from "./BannedInfo";
|
||||
import CommunityGuidelinesContainer from "./CommunityGuidelines";
|
||||
import PostCommentFormContainer from "./PostCommentForm";
|
||||
@@ -35,7 +35,7 @@ export interface StreamProps {
|
||||
comments: ReadonlyArray<
|
||||
{ id: string } & PropTypesOf<typeof CommentContainer>["comment"] &
|
||||
PropTypesOf<typeof ReplyListContainer>["comment"] &
|
||||
PropTypesOf<typeof TombstoneOrHideContainer>["comment"]
|
||||
PropTypesOf<typeof IgnoredTombstoneOrHideContainer>["comment"]
|
||||
>;
|
||||
onLoadMore?: () => void;
|
||||
hasMore?: boolean;
|
||||
@@ -44,7 +44,7 @@ export interface StreamProps {
|
||||
| PropTypesOf<typeof UserBoxContainer>["viewer"] &
|
||||
PropTypesOf<typeof CommentContainer>["viewer"] &
|
||||
PropTypesOf<typeof ReplyListContainer>["viewer"] &
|
||||
PropTypesOf<typeof TombstoneOrHideContainer>["viewer"]
|
||||
PropTypesOf<typeof IgnoredTombstoneOrHideContainer>["viewer"]
|
||||
| null;
|
||||
orderBy: PropTypesOf<typeof SortMenu>["orderBy"];
|
||||
onChangeOrderBy: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
||||
@@ -84,7 +84,7 @@ const Stream: FunctionComponent<StreamProps> = props => {
|
||||
aria-live="polite"
|
||||
>
|
||||
{props.comments.map(comment => (
|
||||
<TombstoneOrHideContainer
|
||||
<IgnoredTombstoneOrHideContainer
|
||||
key={comment.id}
|
||||
viewer={props.viewer}
|
||||
comment={comment}
|
||||
@@ -103,7 +103,7 @@ const Stream: FunctionComponent<StreamProps> = props => {
|
||||
story={props.story}
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
</TombstoneOrHideContainer>
|
||||
</IgnoredTombstoneOrHideContainer>
|
||||
))}
|
||||
{props.hasMore && (
|
||||
<Localized id="comments-stream-loadMore">
|
||||
|
||||
@@ -127,7 +127,7 @@ const enhanced = withPaginationContainer<
|
||||
edges {
|
||||
node {
|
||||
...StreamContainer_comment @relay(mask: false)
|
||||
...TombstoneOrHideContainer_comment
|
||||
...IgnoredTombstoneOrHideContainer_comment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,7 +146,7 @@ const enhanced = withPaginationContainer<
|
||||
...UserBoxContainer_viewer
|
||||
...CreateCommentReplyMutation_viewer
|
||||
...CreateCommentMutation_viewer
|
||||
...TombstoneOrHideContainer_viewer
|
||||
...IgnoredTombstoneOrHideContainer_viewer
|
||||
status {
|
||||
current
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ exports[`renders correctly 1`] = `
|
||||
id="coral-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -103,8 +103,8 @@ exports[`renders correctly 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -157,7 +157,7 @@ exports[`renders correctly 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
</ForwardRef(forwardRef)>
|
||||
</ForwardRef(forwardRef)>
|
||||
`;
|
||||
@@ -212,7 +212,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
id="coral-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -265,8 +265,8 @@ exports[`when there is more disables load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -319,7 +319,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Localized
|
||||
id="comments-stream-loadMore"
|
||||
>
|
||||
@@ -388,7 +388,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
id="coral-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -441,8 +441,8 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -495,7 +495,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
viewer={null}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Localized
|
||||
id="comments-stream-loadMore"
|
||||
>
|
||||
@@ -564,7 +564,7 @@ exports[`when use is logged in renders correctly 1`] = `
|
||||
id="coral-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
@@ -617,8 +617,8 @@ exports[`when use is logged in renders correctly 1`] = `
|
||||
viewer={Object {}}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
<Relay(TombstoneOrHideContainer)
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
<Relay(IgnoredTombstoneOrHideContainer)
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
@@ -671,7 +671,7 @@ exports[`when use is logged in renders correctly 1`] = `
|
||||
viewer={Object {}}
|
||||
/>
|
||||
</ForwardRef(forwardRef)>
|
||||
</Relay(TombstoneOrHideContainer)>
|
||||
</Relay(IgnoredTombstoneOrHideContainer)>
|
||||
</ForwardRef(forwardRef)>
|
||||
</ForwardRef(forwardRef)>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { FunctionComponent, useCallback } from "react";
|
||||
|
||||
import { PropTypesOf } from "coral-framework/types";
|
||||
import { ProfileLocal as Local } from "coral-stream/__generated__/ProfileLocal.graphql";
|
||||
import { ProfileLocal } from "coral-stream/__generated__/ProfileLocal.graphql";
|
||||
import UserBoxContainer from "coral-stream/common/UserBox";
|
||||
import {
|
||||
HorizontalGutter,
|
||||
@@ -24,13 +24,13 @@ export interface ProfileProps {
|
||||
}
|
||||
|
||||
const Profile: FunctionComponent<ProfileProps> = props => {
|
||||
const [local, setLocal] = useLocal<Local>(graphql`
|
||||
const [local, setLocal] = useLocal<ProfileLocal>(graphql`
|
||||
fragment ProfileLocal on Local {
|
||||
profileTab
|
||||
}
|
||||
`);
|
||||
const onTabClick = useCallback(
|
||||
(tab: Local["profileTab"]) => setLocal({ profileTab: tab }),
|
||||
(tab: ProfileLocal["profileTab"]) => setLocal({ profileTab: tab }),
|
||||
[setLocal]
|
||||
);
|
||||
return (
|
||||
|
||||
+25
@@ -170,6 +170,11 @@ exports[`renders permalink view 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -371,6 +376,11 @@ exports[`renders permalink view 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -570,6 +580,11 @@ exports[`renders permalink view 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -765,6 +780,11 @@ exports[`renders permalink view 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -949,6 +969,11 @@ exports[`renders permalink view 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
+20
@@ -204,6 +204,11 @@ exports[`renders conversation thread 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -418,6 +423,11 @@ exports[`shows more of this conversation 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -624,6 +634,11 @@ exports[`shows more of this conversation 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -823,6 +838,11 @@ exports[`shows more of this conversation 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
+60
-44
@@ -74,18 +74,22 @@ exports[`cancel edit 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -805,18 +809,22 @@ exports[`edit a comment: render comment with edit button 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -1029,18 +1037,22 @@ exports[`edit a comment: server response 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -1244,18 +1256,22 @@ exports[`shows expiry message: edit form closed 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -83,6 +83,11 @@ exports[`renders comment stream with load more button 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -267,6 +272,11 @@ exports[`renders comment stream with load more button 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
+15
-11
@@ -74,18 +74,22 @@ exports[`post a comment: optimistic response 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
+50
-11
@@ -73,6 +73,11 @@ exports[`post a reply: open reply form 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -455,18 +460,22 @@ exports[`post a reply: optimistic response 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -665,6 +674,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -872,6 +886,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -1079,6 +1098,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -1286,6 +1310,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -1493,6 +1522,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -1700,6 +1734,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
@@ -73,6 +73,11 @@ exports[`post a reply: open reply form 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -440,18 +445,22 @@ exports[`post a reply: optimistic response 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
+10
@@ -295,6 +295,11 @@ exports[`renders comment stream with community guidelines 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -479,6 +484,11 @@ exports[`renders comment stream with community guidelines 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
@@ -82,6 +82,11 @@ exports[`renders reply list 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -271,6 +276,11 @@ exports[`renders reply list 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -455,6 +465,11 @@ exports[`renders reply list 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -641,6 +656,11 @@ exports[`renders reply list 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
@@ -313,6 +313,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -502,6 +507,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
@@ -82,6 +82,11 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
+5
@@ -73,6 +73,11 @@ exports[`renders deepest comment with link 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
@@ -83,6 +83,11 @@ exports[`renders app with comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
@@ -267,6 +272,11 @@ exports[`renders app with comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLCOMMENT_STATUS, GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
waitForElement,
|
||||
within,
|
||||
} from "coral-framework/testHelpers";
|
||||
|
||||
import { moderators, settings, stories } from "../../fixtures";
|
||||
import create from "../create";
|
||||
|
||||
const story = stories[0];
|
||||
const firstComment = story.comments.edges[0].node;
|
||||
const viewer = moderators[0];
|
||||
|
||||
async function createTestRenderer(
|
||||
params: CreateTestRendererParams<GQLResolver> = {}
|
||||
) {
|
||||
const { testRenderer, context } = create({
|
||||
...params,
|
||||
resolvers: pureMerge(
|
||||
createResolversStub<GQLResolver>({
|
||||
Query: {
|
||||
settings: () => settings,
|
||||
viewer: () => viewer,
|
||||
story: () => story,
|
||||
},
|
||||
}),
|
||||
params.resolvers
|
||||
),
|
||||
initLocalState: (localRecord, source, environment) => {
|
||||
localRecord.setValue(story.id, "storyID");
|
||||
localRecord.setValue(true, "loggedIn");
|
||||
if (params.initLocalState) {
|
||||
params.initLocalState(localRecord, source, environment);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const tabPane = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("current-tab-pane")
|
||||
);
|
||||
|
||||
return {
|
||||
testRenderer,
|
||||
context,
|
||||
tabPane,
|
||||
};
|
||||
}
|
||||
|
||||
it("render go to moderate link", async () => {
|
||||
const { testRenderer } = await createTestRenderer();
|
||||
const comment = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID(`comment-${firstComment.id}`)
|
||||
);
|
||||
const caretButton = within(comment).getByLabelText("Moderate");
|
||||
caretButton.props.onClick();
|
||||
const link = within(comment).getByText("Go to Moderate", {
|
||||
selector: "a",
|
||||
exact: false,
|
||||
});
|
||||
expect(link.props.href).toBe(`/admin/moderate/comment/${firstComment.id}`);
|
||||
});
|
||||
|
||||
it("accept comment", async () => {
|
||||
const { testRenderer } = await createTestRenderer({
|
||||
resolvers: createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
acceptComment: ({ variables }) => {
|
||||
expectAndFail(variables).toMatchObject({
|
||||
commentID: firstComment.id,
|
||||
commentRevisionID: firstComment.revision.id,
|
||||
});
|
||||
return {
|
||||
comment: pureMerge<typeof firstComment>(firstComment, {
|
||||
status: GQLCOMMENT_STATUS.ACCEPTED,
|
||||
}),
|
||||
};
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
const comment = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID(`comment-${firstComment.id}`)
|
||||
);
|
||||
const caretButton = within(comment).getByLabelText("Moderate");
|
||||
caretButton.props.onClick();
|
||||
const approveButton = within(comment).getByText("Approve", {
|
||||
selector: "button",
|
||||
});
|
||||
approveButton.props.onClick();
|
||||
await waitForElement(() =>
|
||||
within(comment).getByText("Approved", { exact: false })
|
||||
);
|
||||
});
|
||||
|
||||
it("reject comment", async () => {
|
||||
const { testRenderer, tabPane } = await createTestRenderer({
|
||||
resolvers: createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
rejectComment: ({ variables }) => {
|
||||
expectAndFail(variables).toMatchObject({
|
||||
commentID: firstComment.id,
|
||||
commentRevisionID: firstComment.revision.id,
|
||||
});
|
||||
return {
|
||||
comment: pureMerge<typeof firstComment>(firstComment, {
|
||||
status: GQLCOMMENT_STATUS.REJECTED,
|
||||
}),
|
||||
};
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
const comment = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID(`comment-${firstComment.id}`)
|
||||
);
|
||||
const caretButton = within(comment).getByLabelText("Moderate");
|
||||
caretButton.props.onClick();
|
||||
const rejectButton = within(comment).getByText("Reject", {
|
||||
selector: "button",
|
||||
});
|
||||
rejectButton.props.onClick();
|
||||
await waitForElement(() =>
|
||||
within(tabPane).getByText("You have rejected this comment", {
|
||||
exact: false,
|
||||
})
|
||||
);
|
||||
const link = within(tabPane).getByText(
|
||||
"Go to Moderate to review this decision",
|
||||
{ selector: "a", exact: false }
|
||||
);
|
||||
expect(link.props.href).toBe(`/admin/moderate/comment/${firstComment.id}`);
|
||||
});
|
||||
Reference in New Issue
Block a user