[CORL-171] Comment Tags (#2248)

* feat: staff badge

* feat: added tag support on the server

* feat: use tags

* fix: server tests
This commit is contained in:
Kiwi
2019-03-29 22:29:17 +00:00
committed by Wyatt Johnson
parent f9114ef4be
commit d217fedf9c
60 changed files with 945 additions and 267 deletions
@@ -152,6 +152,7 @@ function commit(
total: 0,
},
},
tags: [],
},
},
clientMutationId: (clientMutationId++).toString(),
@@ -181,6 +181,7 @@ function commit(
total: 0,
},
},
tags: [],
},
},
clientMutationId: (clientMutationId++).toString(),
@@ -3,7 +3,7 @@ import React, { StatelessComponent } from "react";
import HTMLContent from "talk-stream/components/HTMLContent";
import Timestamp from "talk-stream/components/Timestamp";
import { Flex, HorizontalGutter } from "talk-ui/components";
import { Flex, HorizontalGutter, Tag } from "talk-ui/components";
import EditedMarker from "./EditedMarker";
import InReplyTo from "./InReplyTo";
@@ -22,6 +22,7 @@ export interface CommentProps {
showEditedMarker?: boolean;
highlight?: boolean;
parentAuthorName?: string | null;
tags?: ReadonlyArray<string>;
}
const Comment: StatelessComponent<CommentProps> = props => {
@@ -32,7 +33,10 @@ const Comment: StatelessComponent<CommentProps> = props => {
>
<Flex direction="row" justifyContent="space-between">
<TopBarLeft>
{props.username && <Username>{props.username}</Username>}
<Flex direction="row" alignItems="center" itemGutter="half">
{props.username && <Username>{props.username}</Username>}
{props.tags && props.tags.map((t, i) => <Tag key={i}>{t}</Tag>)}
</Flex>
<Flex direction="row" alignItems="baseline" itemGutter>
<Timestamp>{props.createdAt}</Timestamp>
{props.showEditedMarker && <EditedMarker />}
@@ -1,7 +1,7 @@
import React, { StatelessComponent } from "react";
import Timestamp from "talk-stream/components/Timestamp";
import { Flex } from "talk-ui/components";
import { Flex, Tag } from "talk-ui/components";
import TopBarLeft from "./TopBarLeft";
import Username from "./Username";
@@ -10,13 +10,17 @@ export interface RootParentProps {
id?: string;
username: string | null;
createdAt: string;
tags?: ReadonlyArray<string>;
}
const RootParent: StatelessComponent<RootParentProps> = props => {
return (
<Flex direction="row" justifyContent="space-between" id={props.id}>
<TopBarLeft>
{props.username && <Username>{props.username}</Username>}
<Flex direction="row" alignItems="center" itemGutter="half">
{props.username && <Username>{props.username}</Username>}
{props.tags && props.tags.map((t, i) => <Tag key={i}>{t}</Tag>)}
</Flex>
<Flex direction="row" alignItems="baseline" itemGutter>
<Timestamp>{props.createdAt}</Timestamp>
</Flex>
@@ -10,9 +10,15 @@ exports[`renders username and body 1`] = `
justifyContent="space-between"
>
<TopBarLeft>
<Username>
Marvin
</Username>
<ForwardRef(forwardRef)
alignItems="center"
direction="row"
itemGutter="half"
>
<Username>
Marvin
</Username>
</ForwardRef(forwardRef)>
<ForwardRef(forwardRef)
alignItems="baseline"
direction="row"
@@ -0,0 +1,6 @@
import React, { StatelessComponent } from "react";
import * as styles from "./Divider.css";
const Divider: StatelessComponent = () => <hr className={styles.root} />;
export default Divider;
@@ -36,6 +36,7 @@ function createDefaultProps(add: DeepPartial<Props> = {}): Props {
editableUntil: "1995-12-17T03:24:30.000Z",
},
pending: false,
tags: [],
},
settings: {
disableCommenting: {
@@ -128,3 +129,14 @@ it("renders disabled reply when commenting has been disabled", () => {
renderer.render(<CommentContainerN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders staff badge", () => {
const props = createDefaultProps({
comment: {
tags: [{ name: "Staff" }],
},
});
const renderer = createRenderer();
renderer.render(<CommentContainerN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -182,6 +182,7 @@ export class CommentContainer extends Component<Props, State> {
comment.parent.author &&
comment.parent.author.username
}
tags={comment.tags.map(t => t.name)}
topBarRight={
(editable && (
<Localized id="comments-commentContainer-editButton">
@@ -294,6 +295,9 @@ const enhanced = withSetCommentIDMutation(
edited
editableUntil
}
tags {
name
}
pending
...ReplyCommentFormContainer_comment
...EditCommentFormContainer_comment
@@ -41,6 +41,7 @@ exports[`hide reply button 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -71,6 +72,7 @@ exports[`hide reply button 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -82,6 +84,7 @@ exports[`hide reply button 1`] = `
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={Array []}
username="Marvin"
/>
</ForwardRef(forwardRef)>
@@ -135,6 +138,7 @@ exports[`renders body only 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -165,6 +169,7 @@ exports[`renders body only 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -176,6 +181,7 @@ exports[`renders body only 1`] = `
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={Array []}
username={null}
/>
</ForwardRef(forwardRef)>
@@ -229,6 +235,7 @@ exports[`renders disabled reply when commenting has been disabled 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -259,6 +266,7 @@ exports[`renders disabled reply when commenting has been disabled 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -270,6 +278,7 @@ exports[`renders disabled reply when commenting has been disabled 1`] = `
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={Array []}
username="Marvin"
/>
</ForwardRef(forwardRef)>
@@ -323,6 +332,7 @@ exports[`renders disabled reply when story is closed 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -353,6 +363,7 @@ exports[`renders disabled reply when story is closed 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -364,6 +375,7 @@ exports[`renders disabled reply when story is closed 1`] = `
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={Array []}
username="Marvin"
/>
</ForwardRef(forwardRef)>
@@ -421,6 +433,7 @@ exports[`renders in reply to 1`] = `
},
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -455,6 +468,7 @@ exports[`renders in reply to 1`] = `
},
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -466,6 +480,116 @@ exports[`renders in reply to 1`] = `
indentLevel={1}
parentAuthorName="ParentAuthor"
showEditedMarker={false}
tags={Array []}
username="Marvin"
/>
</ForwardRef(forwardRef)>
</div>
`;
exports[`renders staff badge 1`] = `
<div
data-testid="comment-comment-id"
>
<ForwardRef(forwardRef)>
<IndentedComment
blur={false}
body="Woof"
createdAt="1995-12-17T03:24:00.000Z"
footer={
<React.Fragment>
<ForwardRef(forwardRef)
justifyContent="space-between"
>
<ButtonsBar>
<ReplyButton
active={false}
disabled={false}
id="comments-commentContainer-replyButton-comment-id"
onClick={[Function]}
/>
<Relay(PermalinkButtonContainer)
commentID="comment-id"
story={
Object {
"isClosed": false,
"url": "http://localhost/story",
}
}
/>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(Relay(ReactionButtonContainer)))))))
comment={
Object {
"author": Object {
"id": "author-id",
"username": "Marvin",
},
"body": "Woof",
"createdAt": "1995-12-17T03:24:00.000Z",
"editing": Object {
"editableUntil": "1995-12-17T03:24:30.000Z",
"edited": false,
},
"id": "comment-id",
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [
Object {
"name": "Staff",
},
],
}
}
settings={
Object {
"disableCommenting": Object {
"enabled": false,
},
}
}
viewer={null}
/>
</ButtonsBar>
<ButtonsBar>
<withContext(createMutationContainer(Relay(ReportButtonContainer)))
comment={
Object {
"author": Object {
"id": "author-id",
"username": "Marvin",
},
"body": "Woof",
"createdAt": "1995-12-17T03:24:00.000Z",
"editing": Object {
"editableUntil": "1995-12-17T03:24:30.000Z",
"edited": false,
},
"id": "comment-id",
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [
Object {
"name": "Staff",
},
],
}
}
viewer={null}
/>
</ButtonsBar>
</ForwardRef(forwardRef)>
</React.Fragment>
}
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={
Array [
"Staff",
]
}
username="Marvin"
/>
</ForwardRef(forwardRef)>
@@ -519,6 +643,7 @@ exports[`renders username and body 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -549,6 +674,7 @@ exports[`renders username and body 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -560,6 +686,7 @@ exports[`renders username and body 1`] = `
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={Array []}
username="Marvin"
/>
</ForwardRef(forwardRef)>
@@ -613,6 +740,7 @@ exports[`shows conversation link 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
settings={
@@ -643,6 +771,7 @@ exports[`shows conversation link 1`] = `
"parent": null,
"pending": false,
"status": "NONE",
"tags": Array [],
}
}
viewer={null}
@@ -659,6 +788,7 @@ exports[`shows conversation link 1`] = `
indentLevel={1}
parentAuthorName={null}
showEditedMarker={false}
tags={Array []}
username="Marvin"
/>
</ForwardRef(forwardRef)>
@@ -1,17 +1,20 @@
import { noop } from "lodash";
import { merge, noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
import { DeepPartial, PropTypesOf } from "talk-framework/types";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import ConversationThread from "./ConversationThread";
const ConversationThreadN = removeFragmentRefs(ConversationThread);
describe("with 2 remaining parent comments", () => {
it("renders correctly", () => {
const props: PropTypesOf<typeof ConversationThreadN> = {
type Props = PropTypesOf<typeof ConversationThreadN>;
function createDefaultProps(add: DeepPartial<Props> = {}): Props {
return merge(
{},
{
className: "root",
viewer: {},
story: {},
@@ -25,29 +28,34 @@ describe("with 2 remaining parent comments", () => {
id: "root-parent",
createdAt: "1995-12-17T03:24:00.000Z",
username: "parentAuthor",
tags: [],
},
};
},
add
);
}
describe("with 2 remaining parent comments", () => {
it("renders correctly", () => {
const props = createDefaultProps();
const renderer = createRenderer();
renderer.render(<ConversationThreadN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders staff badge", () => {
const props = createDefaultProps({
rootParent: {
tags: ["Staff"],
},
});
const renderer = createRenderer();
renderer.render(<ConversationThreadN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders with disabled load more", () => {
const props: PropTypesOf<typeof ConversationThreadN> = {
className: "root",
viewer: {},
story: {},
settings: {},
comment: {},
const props = createDefaultProps({
disableLoadMore: true,
loadMore: noop,
remaining: 2,
parents: [],
rootParent: {
id: "root-parent",
createdAt: "1995-12-17T03:24:00.000Z",
username: "parentAuthor",
},
};
});
const renderer = createRenderer();
renderer.render(<ConversationThreadN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
@@ -55,18 +63,10 @@ describe("with 2 remaining parent comments", () => {
});
it("renders with no parent comments", () => {
const props: PropTypesOf<typeof ConversationThreadN> = {
className: "root",
viewer: {},
story: {},
settings: {},
comment: {},
disableLoadMore: false,
loadMore: noop,
const props = createDefaultProps({
remaining: 0,
parents: [],
rootParent: null,
};
});
const renderer = createRenderer();
renderer.render(<ConversationThreadN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
@@ -32,6 +32,7 @@ export interface ConversationThreadProps {
id: string;
createdAt: string;
username: string | null;
tags: ReadonlyArray<string>;
} | null;
}
@@ -64,6 +65,7 @@ const ConversationThread: StatelessComponent<
id={props.rootParent.id}
username={props.rootParent.username}
createdAt={props.rootParent.createdAt}
tags={props.rootParent.tags}
/>
</Circle>
)}
@@ -31,6 +31,76 @@ exports[`with 2 remaining parent comments renders correctly 1`] = `
<RootParent
createdAt="1995-12-17T03:24:00.000Z"
id="root-parent"
tags={Array []}
username="parentAuthor"
/>
</Circle>
<Circle
className="ConversationThread-loadMore"
hollow={true}
>
<ForwardRef(forwardRef)
alignItems="center"
itemGutter="half"
>
<Localized
$count={2}
id="comments-conversationThread-showMoreOfThisConversation"
>
<ForwardRef(forwardRef)
className="ConversationThread-showMoreButton"
disabled={false}
onClick={[Function]}
variant="underlined"
>
Show more of this conversation
</ForwardRef(forwardRef)>
</Localized>
<withPropsOnChange(Counter)>
2
</withPropsOnChange(Counter)>
</ForwardRef(forwardRef)>
</Circle>
</ForwardRef(forwardRef)>
<ForwardRef(forwardRef)
container={[Function]}
>
<Circle
end={true}
>
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
comment={Object {}}
highlight={true}
settings={Object {}}
story={Object {}}
viewer={Object {}}
/>
</Circle>
</ForwardRef(forwardRef)>
</div>
`;
exports[`with 2 remaining parent comments renders staff badge 1`] = `
<div
className="root ConversationThread-root"
data-testid="comments-permalinkView-conversationThread"
>
<ForwardRef(forwardRef)
container={
<Line
dotted={true}
/>
}
>
<Circle>
<RootParent
createdAt="1995-12-17T03:24:00.000Z"
id="root-parent"
tags={
Array [
"Staff",
]
}
username="parentAuthor"
/>
</Circle>
@@ -95,6 +165,7 @@ exports[`with 2 remaining parent comments renders with disabled load more 1`] =
<RootParent
createdAt="1995-12-17T03:24:00.000Z"
id="root-parent"
tags={Array []}
username="parentAuthor"
/>
</Circle>
@@ -71,6 +71,7 @@ class ConversationThreadContainer extends React.Component<
createdAt: comment.rootParent.createdAt,
username:
comment.rootParent.author && comment.rootParent.author.username,
tags: comment.rootParent.tags.map(t => t.name),
}) ||
null
}
@@ -122,6 +123,9 @@ const enhanced = withContext(ctx => ({
username
}
createdAt
tags {
name
}
}
parentCount
parents(last: $count, before: $cursor)
@@ -23,11 +23,15 @@ exports[`cancel edit 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -702,11 +706,15 @@ exports[`edit a comment: render comment with edit button 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -883,11 +891,15 @@ exports[`edit a comment: server response 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -1073,11 +1085,15 @@ exports[`shows expiry message: edit form closed 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -33,11 +33,15 @@ exports[`renders comment stream with load more button 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -183,11 +187,15 @@ exports[`renders comment stream with load more button 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Lukas
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -120,11 +120,15 @@ exports[`renders permalink view 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Lukas
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -287,11 +291,15 @@ exports[`renders permalink view 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -452,11 +460,15 @@ exports[`renders permalink view 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -613,11 +625,15 @@ exports[`renders permalink view 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -763,11 +779,15 @@ exports[`renders permalink view 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -28,16 +28,25 @@ exports[`renders conversation thread 1`] = `
</div>
<div
className="Flex-root Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-2"
id="comment-from-staff-0"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Moderator
</span>
<span
className="Tag-root"
>
Staff
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -143,11 +152,15 @@ exports[`renders conversation thread 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -323,11 +336,15 @@ exports[`shows more of this conversation 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Lukas
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -469,7 +486,7 @@ exports[`shows more of this conversation 1`] = `
</svg>
</div>
<div
data-testid="comment-comment-2"
data-testid="comment-comment-from-staff-0"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
@@ -490,11 +507,20 @@ exports[`shows more of this conversation 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Moderator
</span>
<span
className="Tag-root"
>
Staff
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -515,7 +541,7 @@ exports[`shows more of this conversation 1`] = `
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Hey!",
"__html": "Joining Too",
}
}
/>
@@ -528,7 +554,7 @@ exports[`shows more of this conversation 1`] = `
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
disabled={false}
id="comments-commentContainer-replyButton-comment-2"
id="comments-commentContainer-replyButton-comment-from-staff-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -545,7 +571,7 @@ exports[`shows more of this conversation 1`] = `
className="Popover-root"
>
<button
aria-controls="permalink-popover-comment-2"
aria-controls="permalink-popover-comment-from-staff-0"
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
onBlur={[Function]}
onClick={[Function]}
@@ -561,13 +587,13 @@ exports[`shows more of this conversation 1`] = `
</button>
<div
aria-hidden={true}
aria-labelledby="permalink-popover-comment-2-ariainfo"
id="permalink-popover-comment-2"
aria-labelledby="permalink-popover-comment-from-staff-0-ariainfo"
id="permalink-popover-comment-from-staff-0"
role="popup"
>
<div
className="AriaInfo-root"
id="permalink-popover-comment-2-ariainfo"
id="permalink-popover-comment-from-staff-0-ariainfo"
>
A dialog showing a permalink to the comment
</div>
@@ -655,11 +681,15 @@ exports[`shows more of this conversation 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -23,11 +23,15 @@ exports[`post a comment: optimistic response 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -23,11 +23,15 @@ exports[`post a reply: open reply form 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -366,11 +370,15 @@ exports[`post a reply: optimistic response 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -543,11 +551,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -716,11 +728,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -889,11 +905,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -1062,11 +1082,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -1235,11 +1259,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -1408,11 +1436,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -23,11 +23,15 @@ exports[`post a reply: open reply form 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -351,11 +355,15 @@ exports[`post a reply: optimistic response 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -242,11 +242,15 @@ exports[`renders comment stream with community guidelines 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -392,11 +396,15 @@ exports[`renders comment stream with community guidelines 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Lukas
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -32,11 +32,15 @@ exports[`renders reply list 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -187,11 +191,15 @@ exports[`renders reply list 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -337,11 +345,15 @@ exports[`renders reply list 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -489,11 +501,15 @@ exports[`renders reply list 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -260,11 +260,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -389,7 +393,7 @@ exports[`renders comment stream 1`] = `
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
data-testid="comment-comment-1"
data-testid="comment-comment-from-staff-0"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
@@ -410,11 +414,20 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Lukas
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Moderator
</span>
<span
className="Tag-root"
>
Staff
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -435,7 +448,7 @@ exports[`renders comment stream 1`] = `
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
"__html": "Joining Too",
}
}
/>
@@ -448,7 +461,7 @@ exports[`renders comment stream 1`] = `
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
disabled={false}
id="comments-commentContainer-replyButton-comment-1"
id="comments-commentContainer-replyButton-comment-from-staff-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -465,7 +478,7 @@ exports[`renders comment stream 1`] = `
className="Popover-root"
>
<button
aria-controls="permalink-popover-comment-1"
aria-controls="permalink-popover-comment-from-staff-0"
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
onBlur={[Function]}
onClick={[Function]}
@@ -481,13 +494,13 @@ exports[`renders comment stream 1`] = `
</button>
<div
aria-hidden={true}
aria-labelledby="permalink-popover-comment-1-ariainfo"
id="permalink-popover-comment-1"
aria-labelledby="permalink-popover-comment-from-staff-0-ariainfo"
id="permalink-popover-comment-from-staff-0"
role="popup"
>
<div
className="AriaInfo-root"
id="permalink-popover-comment-1-ariainfo"
id="permalink-popover-comment-from-staff-0-ariainfo"
>
A dialog showing a permalink to the comment
</div>
@@ -32,11 +32,15 @@ exports[`renders comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Lukas
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -23,11 +23,15 @@ exports[`renders deepest comment with link 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Markus
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -33,11 +33,15 @@ exports[`renders app with comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -183,11 +187,15 @@ exports[`renders app with comment stream 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
Isabelle
</span>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
</div>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
@@ -11,7 +11,7 @@ import {
within,
} from "talk-framework/testHelpers";
import { settings, stories, users } from "../fixtures";
import { commenters, settings, stories } from "../fixtures";
import create from "./create";
beforeAll(() => {
@@ -38,7 +38,7 @@ async function createTestRenderer(
...resolver,
Query: {
settings: sinon.stub().returns(settingsWithCharCount),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
story: sinon.stub().returns(stories[0]),
...resolver.Query,
},
@@ -10,7 +10,7 @@ import {
within,
} from "talk-framework/testHelpers";
import { settings, stories, users } from "../fixtures";
import { commenters, settings, stories } from "../fixtures";
import create from "./create";
const settingsWithCharCount = {
@@ -30,7 +30,7 @@ async function createTestRenderer(
...resolver,
Query: {
settings: sinon.stub().returns(settingsWithCharCount),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
story: sinon.stub().returns(stories[0]),
...resolver.Query,
},
@@ -10,7 +10,7 @@ import {
within,
} from "talk-framework/testHelpers";
import { settings, stories, users } from "../fixtures";
import { commenters, settings, stories } from "../fixtures";
import create from "./create";
const settingsWithCharCount = {
@@ -30,7 +30,7 @@ async function createTestRenderer(
...resolver,
Query: {
settings: sinon.stub().returns(settingsWithCharCount),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
story: sinon.stub().returns(stories[0]),
...resolver.Query,
},
@@ -10,10 +10,10 @@ import {
} from "talk-framework/testHelpers";
import {
commenters,
commentWithReplies,
settings,
storyWithReplies,
users,
} from "../fixtures";
import create from "./create";
@@ -30,7 +30,7 @@ function createTestRenderer(
.withArgs(undefined, { id: storyWithReplies.id, url: null })
.returns(storyWithReplies)
),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
settings: sinon.stub().returns(settings),
},
Mutation: {
@@ -8,7 +8,7 @@ import {
within,
} from "talk-framework/testHelpers";
import { comments, settings, stories } from "../fixtures";
import { comments, commentsFromStaff, settings, stories } from "../fixtures";
import create from "./create";
let testRenderer: ReactTestRenderer;
@@ -16,7 +16,7 @@ beforeEach(() => {
const commentStub = {
...comments[0],
parentCount: 2,
rootParent: comments[2],
rootParent: commentsFromStaff[0],
parents: createSinonStub(
s => s.throws(),
s =>
@@ -39,8 +39,8 @@ beforeEach(() => {
cursor: comments[1].createdAt,
},
{
node: comments[2],
cursor: comments[2].createdAt,
node: commentsFromStaff[0],
cursor: commentsFromStaff[0].createdAt,
},
],
})
@@ -15,7 +15,7 @@ import {
import RTE from "@coralproject/rte";
import { ReactTestInstance } from "react-test-renderer";
import { baseComment, settings, stories, users } from "../fixtures";
import { baseComment, commenters, settings, stories } from "../fixtures";
import create from "./create";
async function createTestRenderer(
@@ -26,7 +26,7 @@ async function createTestRenderer(
...resolver,
Query: {
settings: sinon.stub().returns(settings),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
story: sinon.stub().callsFake((_: any, variables: any) => {
expectAndFail(variables.id).toBe(stories[0].id);
return stories[0];
@@ -87,7 +87,7 @@ it("post a comment", async () => {
node: {
...baseComment,
id: "comment-x",
author: users[0],
author: commenters[0],
body: "<b>Hello world! (from server)</b>",
},
},
@@ -135,7 +135,7 @@ const postACommentAndHandleNonVisibleComment = async (
...baseComment,
id: "comment-x",
status: "SYSTEM_WITHHELD",
author: users[0],
author: commenters[0],
body: "<b>Hello world!</b>",
},
},
@@ -223,7 +223,7 @@ it("handle moderation nudge error", async () => {
...baseComment,
id: "comment-x",
status: "SYSTEM_WITHHELD",
author: users[0],
author: commenters[0],
body: "<b>Hello world!</b>",
},
},
@@ -10,9 +10,9 @@ import {
import {
baseComment,
commenters,
settings,
storyWithDeepestReplies,
users,
} from "../fixtures";
import create from "./create";
@@ -21,7 +21,7 @@ beforeEach(() => {
const resolvers = {
Query: {
settings: sinon.stub().returns(settings),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
story: createSinonStub(
s => s.throws(),
s =>
@@ -44,7 +44,7 @@ beforeEach(() => {
node: {
...baseComment,
id: "comment-x",
author: users[0],
author: commenters[0],
body: "<b>Hello world! (from server)</b>",
},
},
@@ -14,7 +14,7 @@ import {
} from "talk-framework/testHelpers";
import RTE from "@coralproject/rte";
import { baseComment, settings, stories, users } from "../fixtures";
import { baseComment, commenters, settings, stories } from "../fixtures";
import create from "./create";
async function createTestRenderer(
@@ -25,7 +25,7 @@ async function createTestRenderer(
...resolver,
Query: {
settings: sinon.stub().returns(settings),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
story: sinon.stub().callsFake((_: any, variables: any) => {
expectAndFail(variables.id).toBe(stories[0].id);
return stories[0];
@@ -93,7 +93,7 @@ it("post a reply", async () => {
node: {
...baseComment,
id: "comment-x",
author: users[0],
author: commenters[0],
body: "<b>Hello world! (from server)</b>",
},
},
@@ -146,7 +146,7 @@ it("post a reply and handle non-visible comment state", async () => {
...baseComment,
id: "comment-x",
status: "SYSTEM_WITHHELD",
author: users[0],
author: commenters[0],
body: "<b>Hello world!</b>",
},
},
@@ -229,7 +229,7 @@ it("handle moderation nudge error", async () => {
...baseComment,
id: "comment-x",
status: "SYSTEM_WITHHELD",
author: users[0],
author: commenters[0],
body: "<b>Hello world!</b>",
},
},
@@ -2,7 +2,7 @@ import sinon from "sinon";
import { waitForElement, within } from "talk-framework/testHelpers";
import { settings, stories, users } from "../fixtures";
import { commenters, settings, stories } from "../fixtures";
import create from "./create";
function createTestRenderer() {
@@ -15,7 +15,7 @@ function createTestRenderer() {
});
return stories[0];
}),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
settings: sinon.stub().returns(settings),
},
Mutation: {
@@ -3,7 +3,7 @@ import sinon from "sinon";
import { waitForElement, within } from "talk-framework/testHelpers";
import { settings, storyWithNoComments, users } from "../fixtures";
import { commenters, settings, storyWithNoComments } from "../fixtures";
import create from "./create";
async function createTestRenderer(
@@ -17,7 +17,7 @@ async function createTestRenderer(
const resolvers = {
Query: {
settings: sinon.stub().returns(merge({}, settings, data.settings)),
viewer: sinon.stub().returns((data.loggedIn && users[0]) || null),
viewer: sinon.stub().returns((data.loggedIn && commenters[0]) || null),
story: sinon.stub().callsFake((_: any, variables: any) => {
expectAndFail(variables.id).toBe(storyWithNoComments.id);
return merge({}, storyWithNoComments, data.story);
@@ -5,6 +5,8 @@ import { waitForElement, within } from "talk-framework/testHelpers";
import { settings, stories } from "../fixtures";
import create from "./create";
const story = stories[2];
async function createTestRenderer(
resolver: any = {},
options: { muteNetworkErrors?: boolean } = {}
@@ -14,8 +16,8 @@ async function createTestRenderer(
Query: {
settings: sinon.stub().returns(settings),
story: sinon.stub().callsFake((_: any, variables: any) => {
expectAndFail(variables.id).toBe(stories[0].id);
return stories[0];
expectAndFail(variables.id).toBe(story.id);
return story;
}),
...resolver.Query,
},
@@ -27,7 +29,7 @@ async function createTestRenderer(
muteNetworkErrors: options.muteNetworkErrors,
resolvers,
initLocalState: localRecord => {
localRecord.setValue(stories[0].id, "storyID");
localRecord.setValue(story.id, "storyID");
},
});
@@ -5,7 +5,7 @@ import { timeout } from "talk-common/utils";
import { InvalidRequestError } from "talk-framework/lib/errors";
import { wait, waitForElement, within } from "talk-framework/testHelpers";
import { settings, stories, users } from "../fixtures";
import { commenters, settings, stories } from "../fixtures";
import create from "./create";
function createTestRenderer(
@@ -21,7 +21,7 @@ function createTestRenderer(
});
return stories[0];
}),
viewer: sinon.stub().returns(users[0]),
viewer: sinon.stub().returns(commenters[0]),
settings: sinon.stub().returns(settings),
...resolver.Query,
},
@@ -2,7 +2,7 @@ import sinon from "sinon";
import { waitForElement, within } from "talk-framework/testHelpers";
import { settings, stories, viewerAsModerator } from "../fixtures";
import { moderators, settings, stories } from "../fixtures";
import create from "./create";
async function createTestRenderer(
@@ -14,7 +14,7 @@ async function createTestRenderer(
Query: {
settings: sinon.stub().returns(settings),
story: sinon.stub().returns(stories[0]),
viewer: sinon.stub().returns(viewerAsModerator),
viewer: sinon.stub().returns(moderators[0]),
...resolver.Query,
},
};
@@ -2,7 +2,7 @@ import sinon from "sinon";
import { waitForElement, within } from "talk-framework/testHelpers";
import { settings, stories, viewerAsModerator } from "../fixtures";
import { moderators, settings, stories } from "../fixtures";
import create from "./create";
async function createTestRenderer(
@@ -16,7 +16,7 @@ async function createTestRenderer(
expectAndFail(variables).toEqual({ id: stories[0].id, url: null });
return stories[0];
}),
viewer: sinon.stub().returns(viewerAsModerator),
viewer: sinon.stub().returns(moderators[0]),
...resolver.Query,
},
...resolver,
@@ -8,7 +8,7 @@ import {
within,
} from "talk-framework/testHelpers";
import { settings, stories, viewerAsModerator } from "../fixtures";
import { moderators, settings, stories } from "../fixtures";
import create from "./create";
async function createTestRenderer(
@@ -22,7 +22,7 @@ async function createTestRenderer(
expectAndFail(variables).toEqual({ id: stories[0].id, url: null });
return stories[0];
}),
viewer: sinon.stub().returns(viewerAsModerator),
viewer: sinon.stub().returns(moderators[0]),
...resolver.Query,
},
...resolver,
+48 -16
View File
@@ -73,7 +73,7 @@ export const settings = {
},
};
export const users = [
export const commenters = [
{
id: "user-0",
username: "Markus",
@@ -89,10 +89,15 @@ export const users = [
username: "Isabelle",
role: GQLUSER_ROLE.COMMENTER,
},
{
id: "user-3",
username: "Markus",
role: GQLUSER_ROLE.COMMENTER,
},
];
export const baseComment = {
author: users[0],
author: commenters[0],
body: "Comment Body",
revision: {
id: "revision-0",
@@ -110,43 +115,44 @@ export const baseComment = {
total: 0,
},
},
tags: [],
};
export const comments = denormalizeComments([
{
...baseComment,
id: "comment-0",
author: users[0],
author: commenters[0],
body: "Joining Too",
},
{
...baseComment,
id: "comment-1",
author: users[1],
author: commenters[1],
body: "What's up?",
},
{
...baseComment,
id: "comment-2",
author: users[2],
author: commenters[2],
body: "Hey!",
},
{
...baseComment,
id: "comment-3",
author: users[2],
author: commenters[2],
body: "Comment Body 3",
},
{
...baseComment,
id: "comment-4",
author: users[2],
author: commenters[2],
body: "Comment Body 4",
},
{
...baseComment,
id: "comment-5",
author: users[2],
author: commenters[2],
body: "Comment Body 5",
},
]);
@@ -154,7 +160,7 @@ export const comments = denormalizeComments([
export const commentWithReplies = denormalizeComment({
...baseComment,
id: "comment-with-replies",
author: users[0],
author: commenters[0],
body: "I like yoghurt",
replies: {
edges: [
@@ -171,7 +177,7 @@ export const commentWithReplies = denormalizeComment({
export const commentWithDeepReplies = denormalizeComment({
...baseComment,
id: "comment-with-deep-replies",
author: users[0],
author: commenters[0],
body: "I like yoghurt",
replies: {
edges: [
@@ -304,6 +310,24 @@ export const baseStory = {
},
};
export const moderators = [
{
id: "me-as-moderator",
username: "Moderator",
role: GQLUSER_ROLE.MODERATOR,
},
];
export const commentsFromStaff = denormalizeComments([
{
...baseComment,
id: "comment-from-staff-0",
author: moderators[0],
body: "Joining Too",
tags: [{ name: "Staff" }],
},
]);
export const stories = denormalizeStories([
{
...baseStory,
@@ -333,6 +357,20 @@ export const stories = denormalizeStories([
},
},
},
{
...baseStory,
id: "story-3",
url: "http://localhost/stories/story-3",
comments: {
edges: [
{ node: comments[0], cursor: comments[0].createdAt },
{ node: commentsFromStaff[0], cursor: commentsFromStaff[0].createdAt },
],
pageInfo: {
hasNextPage: false,
},
},
},
]);
export const storyWithNoComments = denormalizeStory({
@@ -397,12 +435,6 @@ export const storyWithDeepestReplies = denormalizeStory({
},
});
export const viewerAsModerator = {
id: "me-as-moderator",
username: "Moderator",
role: GQLUSER_ROLE.MODERATOR,
};
export const viewerWithComments = {
id: "me-with-comments",
username: "Markus",
@@ -0,0 +1,8 @@
.root {
composes: tagText from "talk-ui/shared/typography.css";
color: var(--palette-text-light);
padding: 3px 4px;
white-space: nowrap;
background-color: var(--palette-grey-dark);
border-radius: 1px;
}
+19
View File
@@ -0,0 +1,19 @@
---
name: Tag
menu: UI Kit
---
import { Playground, PropsTable } from "docz";
import Tag from "./Tag";
import HorizontalGutter from "../HorizontalGutter";
import Flex from "../Flex";
# Tag
## Basic Use
<Playground>
<HorizontalGutter>
<Tag>Staff</Tag>
</HorizontalGutter>
</Playground>
@@ -0,0 +1,15 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import { PropTypesOf } from "talk-ui/types";
import Tag from "./Tag";
it("renders correctly", () => {
const props: PropTypesOf<typeof Tag> = {
className: "custom",
children: "Spam",
};
const renderer = TestRenderer.create(<Tag {...props}>Staff</Tag>);
expect(renderer.toJSON()).toMatchSnapshot();
});
+31
View File
@@ -0,0 +1,31 @@
import cn from "classnames";
import React from "react";
import { StatelessComponent } from "react";
import { withStyles } from "talk-ui/hocs";
import styles from "./Tag.css";
interface Props {
className?: string;
/**
* Override or extend the styles applied to the component.
*/
classes: typeof styles;
children: React.ReactNode;
}
const Tag: StatelessComponent<Props> = props => {
const { className, children, classes, ...rest } = props;
const rootClassName = cn(classes.root, className);
return (
<span className={rootClassName} {...rest}>
{children}
</span>
);
};
const enhanced = withStyles(styles)(Tag);
export default enhanced;
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<span
className="Tag-root custom"
>
Staff
</span>
`;
@@ -0,0 +1 @@
export { default, default as Tag } from "./Tag";
+1
View File
@@ -54,3 +54,4 @@ export {
Button as DropdownButton,
} from "./Dropdown";
export { Table, TableBody, TableHead, TableRow, TableCell } from "./Table";
export { default as Tag } from "./Tag";
+7
View File
@@ -217,6 +217,13 @@
letter-spacing: calc(-0.35em / 13);
}
.tagText {
font-family: var(--font-family-sans-serif);
font-weight: var(--font-weight-regular);
font-size: calc(13rem / var(--rem-base));
letter-spacing: calc(-0.2em / 13);
}
.sideNavigationItem {
font-family: var(--font-family-sans-serif);
font-weight: var(--font-weight-regular);
@@ -0,0 +1,23 @@
import { GQLTagTypeResolver } from "talk-server/graph/tenant/schema/__generated__/types";
import {
COMMENT_TAG_TYPE_TRANSLATIONS,
CommentTag,
} from "talk-server/models/comment/tag";
import { translate } from "talk-server/services/i18n";
export const Tag: GQLTagTypeResolver<CommentTag> = {
name: ({ type }, input, ctx) => {
// Get the translation bundle.
const bundle = ctx.i18n.getBundle(ctx.lang);
// Return the translated string.
return translate(bundle, type, COMMENT_TAG_TYPE_TRANSLATIONS[type]);
},
createdBy: ({ createdBy }, input, ctx) => {
if (createdBy) {
return ctx.loaders.Users.user.load(createdBy);
}
return null;
},
};
@@ -21,6 +21,7 @@ import { Query } from "./Query";
import { RejectCommentPayload } from "./RejectCommentPayload";
import { Story } from "./Story";
import { StorySettings } from "./StorySettings";
import { Tag } from "./Tag";
import { User } from "./User";
const Resolvers: GQLResolver = {
@@ -44,6 +45,7 @@ const Resolvers: GQLResolver = {
RejectCommentPayload,
Story,
StorySettings,
Tag,
Time,
User,
};
@@ -1319,6 +1319,27 @@ type CommentRevision {
createdAt: Time!
}
"""
Tag is a simple text message that can be displayed to segment tagable entities.
"""
type Tag {
"""
name is the publicly displayable name assigned to this Tag.
"""
name: String!
"""
createdBy is the User that assigned the Tag. This is null when the Tag is
assigned by the System.
"""
createdBy: User @auth(roles: [MODERATOR, ADMIN])
"""
createdAt is the time that the Tag was assigned on.
"""
createdAt: Time! @auth(roles: [MODERATOR, ADMIN])
}
"""
Comment is a comment left by a User on an Story or another Comment as a reply.
"""
@@ -1439,6 +1460,11 @@ type Comment {
The permalink for this comment.
"""
permalink: String!
"""
tags are the list of tags assigned to the Comment.
"""
tags: [Tag!]!
}
type PageInfo {
+2
View File
@@ -0,0 +1,2 @@
tags-staff = Staff
tags-featured = Featured
@@ -26,6 +26,7 @@ import Query, {
createIndexFactory,
} from "talk-server/models/helpers/query";
import { TenantResource } from "talk-server/models/tenant";
import { CommentTag } from "./tag";
function collection(mongo: Db) {
return mongo.collection<Readonly<Comment>>("comments");
@@ -117,6 +118,12 @@ export interface Comment extends TenantResource {
*/
replyIDs: string[];
/**
* tags are CommentTag's on a specific Comment to be showcased with the
* Comment.
*/
tags: CommentTag[];
/**
* replyCount is the count of direct replies. It is stored as a separate value
* here even though the replyIDs field technically contained the same data in
@@ -187,6 +194,13 @@ export async function createCommentIndexes(mongo: Db) {
authorID: 1,
status: 1,
});
// Tag based Comment Connection pagination.
// { tags.type, ...connectionParams }
await variants(createIndex, {
tenantID: 1,
"tags.type": 1,
});
}
export type CreateCommentInput = Omit<
+44
View File
@@ -0,0 +1,44 @@
/**
* COMMENT_TAG_TYPE is the type of tag that can be added to a Comment.
*/
export enum COMMENT_TAG_TYPE {
/**
* STAFF is used for comments written by staff members.
*/
STAFF = "STAFF",
/**
* FEATURED is used when a given comment has been featured.
*/
FEATURED = "FEATURED",
}
/**
* COMMENT_TAG_TYPE_TRANSLATIONS is the set of translation keys associated with
* a given
*/
export const COMMENT_TAG_TYPE_TRANSLATIONS: Record<COMMENT_TAG_TYPE, string> = {
STAFF: "tags-staff",
FEATURED: "tags-featured",
};
/**
* CommentTag is used to represent a given Tag added to a Comment.
*/
export interface CommentTag {
/**
* type represents a specific tag that can be added to a Comment.
*/
type: COMMENT_TAG_TYPE;
/**
* createdBy is the ID of the user that created the Tag. If this tag was
* created by the system, this will be not provided.
*/
createdBy?: string;
/**
* createdAt is the time that the tag was added to the Comment.
*/
createdAt: Date;
}
+3 -2
View File
@@ -35,7 +35,7 @@ import { PhaseResult, processForModeration } from "./pipeline";
export type CreateComment = Omit<
CreateCommentInput,
"status" | "metadata" | "grandparentIDs" | "actionCounts"
"status" | "metadata" | "grandparentIDs" | "actionCounts" | "tags"
>;
export async function create(
@@ -113,7 +113,7 @@ export async function create(
throw err;
}
const { actions, body, status, metadata } = result;
const { actions, body, status, metadata, tags } = result;
// This is the first time this comment is being published.. So we need to
// ensure we don't run into any race conditions when we create the comment.
@@ -139,6 +139,7 @@ export async function create(
// Create the comment!
const comment = await createComment(mongo, tenant.id, {
...input,
tags,
body,
status,
grandparentIDs,
@@ -33,6 +33,7 @@ describe("compose", () => {
status,
metadata: {},
actions: [],
tags: [],
});
});
@@ -49,6 +50,7 @@ describe("compose", () => {
status,
metadata: { first: true, second: true },
actions: [],
tags: [],
});
});
@@ -111,6 +113,7 @@ describe("compose", () => {
status: GQLCOMMENT_STATUS.NONE,
metadata: { first: true, second: true },
actions: [],
tags: [],
});
});
});
@@ -2,6 +2,7 @@ import { Omit, Promiseable, RequireProperty } from "talk-common/types";
import { GQLCOMMENT_STATUS } from "talk-server/graph/tenant/schema/__generated__/types";
import { CreateActionInput } from "talk-server/models/action/comment";
import { EditCommentInput } from "talk-server/models/comment";
import { CommentTag } from "talk-server/models/comment/tag";
import { Story } from "talk-server/models/story";
import { Tenant } from "talk-server/models/tenant";
import { User } from "talk-server/models/user";
@@ -19,6 +20,7 @@ export interface PhaseResult {
status: GQLCOMMENT_STATUS;
metadata: Record<string, any>;
body: string;
tags: CommentTag[];
}
export interface ModerationPhaseContext {
@@ -52,6 +54,7 @@ export const compose = (
body: context.comment.body,
actions: [],
metadata: context.comment.metadata || {},
tags: [],
};
// Loop over all the moderation phases and see if we've resolved the status.
@@ -88,6 +91,17 @@ export const compose = (
final.body = body;
}
// If the result added any tags, we should push it into the existing tags.
const { tags } = result;
if (tags && tags.length > 0) {
final.tags.push(
// Only push in tags that we haven't already added.
...tags.filter(
({ type }) => !final.tags.some(tag => tag.type === type)
)
);
}
// If this result contained a status, then we've finished resolving
// phases!
const { status } = result;
@@ -2,6 +2,7 @@ import {
GQLCOMMENT_STATUS,
GQLUSER_ROLE,
} from "talk-server/graph/tenant/schema/__generated__/types";
import { COMMENT_TAG_TYPE } from "talk-server/models/comment/tag";
import {
IntermediateModerationPhase,
IntermediatePhaseResult,
@@ -14,6 +15,13 @@ export const staff: IntermediateModerationPhase = ({
if (author.role !== GQLUSER_ROLE.COMMENTER) {
return {
status: GQLCOMMENT_STATUS.ACCEPTED,
tags: [
{
type: COMMENT_TAG_TYPE.STAFF,
// FIXME: (wyattjoh) replace with date from context when https://github.com/coralproject/talk/pull/2247 is merged.
createdAt: new Date(),
},
],
};
}
};