Move files into tab structure

This commit is contained in:
Chi Vinh Le
2018-09-13 18:29:22 +02:00
parent 72f5af9f3b
commit db483849dd
109 changed files with 38 additions and 29 deletions
+2 -2
View File
@@ -3,8 +3,8 @@ import { StatelessComponent } from "react";
import { Flex } from "talk-ui/components";
import PermalinkViewQuery from "../queries/PermalinkViewQuery";
import StreamQuery from "../queries/StreamQuery";
import PermalinkViewQuery from "../tabs/comments/queries/PermalinkViewQuery";
import StreamQuery from "../tabs/comments/queries/StreamQuery";
import * as styles from "./App.css";
export interface AppProps {
@@ -1,8 +0,0 @@
.root {
}
.topBar {
margin-bottom: calc(0.5 * var(--spacing-unit));
}
.footer:not(:empty) {
margin-top: var(--spacing-unit);
}
@@ -1,21 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import Comment from "./Comment";
it("renders username and body", () => {
const props: PropTypesOf<typeof Comment> = {
author: {
username: "Marvin",
},
body: "Woof",
createdAt: "1995-12-17T03:24:00.000Z",
topBarRight: "topBarRight",
footer: "footer",
showEditedMarker: true,
};
const wrapper = shallow(<Comment {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,52 +0,0 @@
import React, { StatelessComponent } from "react";
import { Flex } from "talk-ui/components";
import * as styles from "./Comment.css";
import EditedMarker from "./EditedMarker";
import HTMLContent from "./HTMLContent";
import Timestamp from "./Timestamp";
import TopBarLeft from "./TopBarLeft";
import Username from "./Username";
export interface CommentProps {
className?: string;
author: {
username: string | null;
} | null;
body: string | null;
createdAt: string;
topBarRight?: React.ReactNode;
footer?: React.ReactNode;
showEditedMarker?: boolean;
}
const Comment: StatelessComponent<CommentProps> = props => {
return (
<div role="article" className={styles.root}>
<Flex
className={styles.topBar}
direction="row"
justifyContent="space-between"
>
<TopBarLeft>
{props.author &&
props.author.username && (
<Username>{props.author.username}</Username>
)}
<Flex direction="row" alignItems="baseline" itemGutter>
<Timestamp>{props.createdAt}</Timestamp>
{props.showEditedMarker && <EditedMarker />}
</Flex>
</TopBarLeft>
{props.topBarRight && <div>{props.topBarRight}</div>}
</Flex>
<HTMLContent>{props.body || ""}</HTMLContent>
<Flex className={styles.footer} direction="row" itemGutter="half">
{props.footer}
</Flex>
</div>
);
};
export default Comment;
@@ -1,3 +0,0 @@
.root {
composes: detail from "talk-ui/shared/typography.css";
}
@@ -1,9 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import EditedMarker from "./EditedMarker";
it("renders correctly", () => {
const wrapper = shallow(<EditedMarker />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,16 +0,0 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import styles from "./EditedMarker.css";
const EditedMarker: StatelessComponent = () => (
<div className={styles.root}>
(
<Localized id="comments-editedMarker-edited">
<span>Edited</span>
</Localized>
)
</div>
);
export default EditedMarker;
@@ -1,5 +0,0 @@
.blur {
filter: blur(2px);
user-select: none;
pointer-events: none;
}
@@ -1,19 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import IndentedComment from "./IndentedComment";
it("renders correctly", () => {
const props: PropTypesOf<typeof IndentedComment> = {
indentLevel: 1,
author: {
username: "Marvin",
},
body: "Woof",
createdAt: "1995-12-17T03:24:00.000Z",
};
const wrapper = shallow(<IndentedComment {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,26 +0,0 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import Indent from "../Indent";
import Comment from "./Comment";
import * as styles from "./IndentedComment.css";
export interface IndentedCommentProps extends PropTypesOf<typeof Comment> {
indentLevel?: number;
blur?: boolean;
}
const IndentedComment: StatelessComponent<IndentedCommentProps> = props => {
const { indentLevel, ...rest } = props;
const CommentElement = <Comment {...rest} />;
const CommentwithIndent = (
<Indent level={indentLevel} className={cn({ [styles.blur]: props.blur })}>
{CommentElement}
</Indent>
);
return CommentwithIndent;
};
export default IndentedComment;
@@ -1,17 +0,0 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import ReplyButton from "./ReplyButton";
it("renders correctly", () => {
const props: PropTypesOf<typeof ReplyButton> = {
id: "id",
onClick: noop,
active: true,
};
const wrapper = shallow(<ReplyButton {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,29 +0,0 @@
import { Localized } from "fluent-react/compat";
import React, { EventHandler, MouseEvent, StatelessComponent } from "react";
import { Button, ButtonIcon, MatchMedia } from "talk-ui/components";
interface Props {
id?: string;
onClick?: EventHandler<MouseEvent<HTMLButtonElement>>;
active?: boolean;
}
const ReplyButton: StatelessComponent<Props> = props => (
<Button
id={props.id}
onClick={props.onClick}
variant="ghost"
size="small"
active={props.active}
>
<MatchMedia gtWidth="xs">
<ButtonIcon>reply</ButtonIcon>
</MatchMedia>
<Localized id="comments-replyButton-reply">
<span>Reply</span>
</Localized>
</Button>
);
export default ReplyButton;
@@ -1,45 +0,0 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import { PropTypesOf } from "talk-framework/types";
import { UIContext, UIContextProps } from "talk-ui/components";
import TopBarLeft from "./TopBarLeft";
it("renders correctly on small screens", () => {
const props: PropTypesOf<typeof TopBarLeft> = {
children: <div>Hello World</div>,
};
const context: UIContextProps = {
mediaQueryValues: {
width: 320,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<TopBarLeft {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("renders correctly on big screens", () => {
const props: PropTypesOf<typeof TopBarLeft> = {
children: <div>Hello World</div>,
};
const context: UIContextProps = {
mediaQueryValues: {
width: 1600,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<TopBarLeft {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -1,30 +0,0 @@
import cn from "classnames";
import React from "react";
import { StatelessComponent } from "react";
import { Flex, MatchMedia } from "talk-ui/components";
export interface TopBarLeftProps {
className?: string;
children: React.ReactNode;
}
const TopBarLeft: StatelessComponent<TopBarLeftProps> = props => {
const rootClassName = cn(props.className);
return (
<MatchMedia gtWidth="xs">
{matches => (
<Flex
className={rootClassName}
alignItems="baseline"
direction={matches ? "row" : "column"}
itemGutter={matches ? true : "half"}
>
{props.children}
</Flex>
)}
</MatchMedia>
);
};
export default TopBarLeft;
@@ -1,3 +0,0 @@
.root {
line-height: 1;
}
@@ -1,45 +0,0 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import { PropTypesOf } from "talk-framework/types";
import { UIContext, UIContextProps } from "talk-ui/components";
import Username from "./Username";
it("renders correctly on small screens", () => {
const props: PropTypesOf<typeof Username> = {
children: "Marvin",
};
const context: UIContextProps = {
mediaQueryValues: {
width: 320,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<Username {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("renders correctly on big screens", () => {
const props: PropTypesOf<typeof Username> = {
children: "Marvin",
};
const context: UIContextProps = {
mediaQueryValues: {
width: 1600,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<Username {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -1,28 +0,0 @@
import React from "react";
import { StatelessComponent } from "react";
import { MatchMedia, Typography } from "talk-ui/components";
import * as styles from "./Username.css";
export interface UsernameProps {
children: string;
}
const Username: StatelessComponent<UsernameProps> = props => {
return (
<MatchMedia gtWidth="xs">
{matches => (
<Typography
variant={matches ? "heading2" : "heading3"}
className={styles.root}
container="span"
>
{props.children}
</Typography>
)}
</MatchMedia>
);
};
export default Username;
@@ -1,43 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders username and body 1`] = `
<div
className="Comment-root"
role="article"
>
<withPropsOnChange(Flex)
className="Comment-topBar"
direction="row"
justifyContent="space-between"
>
<TopBarLeft>
<Username>
Marvin
</Username>
<withPropsOnChange(Flex)
alignItems="baseline"
direction="row"
itemGutter={true}
>
<Timestamp>
1995-12-17T03:24:00.000Z
</Timestamp>
<EditedMarker />
</withPropsOnChange(Flex)>
</TopBarLeft>
<div>
topBarRight
</div>
</withPropsOnChange(Flex)>
<HTMLContent>
Woof
</HTMLContent>
<withPropsOnChange(Flex)
className="Comment-footer"
direction="row"
itemGutter="half"
>
footer
</withPropsOnChange(Flex)>
</div>
`;
@@ -1,17 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="EditedMarker-root"
>
(
<Localized
id="comments-editedMarker-edited"
>
<span>
Edited
</span>
</Localized>
)
</div>
`;
@@ -1,18 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<Indent
className=""
level={1}
>
<Comment
author={
Object {
"username": "Marvin",
}
}
body="Woof"
createdAt="1995-12-17T03:24:00.000Z"
/>
</Indent>
`;
@@ -1,26 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<withPropsOnChange(Button)
active={true}
id="id"
onClick={[Function]}
size="small"
variant="ghost"
>
<MatchMediaWithContext
gtWidth="xs"
>
<withPropsOnChange(ButtonIcon)>
reply
</withPropsOnChange(ButtonIcon)>
</MatchMediaWithContext>
<Localized
id="comments-replyButton-reply"
>
<span>
Reply
</span>
</Localized>
</withPropsOnChange(Button)>
`;
@@ -1,21 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly on big screens 1`] = `
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<div>
Hello World
</div>
</div>
`;
exports[`renders correctly on small screens 1`] = `
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<div>
Hello World
</div>
</div>
`;
@@ -1,17 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly on big screens 1`] = `
<span
className="Typography-root Typography-heading2 Typography-colorTextPrimary Username-root"
>
Marvin
</span>
`;
exports[`renders correctly on small screens 1`] = `
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Marvin
</span>
`;
@@ -1,4 +0,0 @@
export { default, default as IndentedComment } from "./IndentedComment";
export { default as TopBarLeft } from "./TopBarLeft";
export { default as Username } from "./Username";
export { default as Timestamp } from "./Timestamp";
@@ -1,161 +0,0 @@
import { CoralRTE } from "@coralproject/rte";
import { Localized } from "fluent-react/compat";
import React, {
EventHandler,
MouseEvent,
Ref,
StatelessComponent,
} from "react";
import { Field, Form } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
import { required } from "talk-framework/lib/validation";
import {
AriaInfo,
Button,
Flex,
HorizontalGutter,
Message,
MessageIcon,
RelativeTime,
Typography,
ValidationMessage,
} from "talk-ui/components";
import { Timestamp, TopBarLeft, Username } from "./Comment";
import RTE from "./RTE";
interface FormProps {
body: string;
}
export interface EditCommentFormProps {
id: string;
className?: string;
author: {
username: string | null;
} | null;
createdAt: string;
editableUntil: string;
onSubmit: OnSubmit<FormProps>;
onCancel?: EventHandler<MouseEvent<any>>;
onClose?: EventHandler<MouseEvent<any>>;
initialValues?: FormProps;
rteRef?: Ref<CoralRTE>;
expired?: boolean;
}
const EditCommentForm: StatelessComponent<EditCommentFormProps> = props => {
const inputID = `comments-editCommentForm-rte-${props.id}`;
return (
<Form onSubmit={props.onSubmit} initialValues={props.initialValues}>
{({ handleSubmit, submitting, hasValidationErrors, pristine }) => (
<form
className={props.className}
autoComplete="off"
onSubmit={handleSubmit}
id={`comments-editCommentForm-form-${props.id}`}
>
<HorizontalGutter>
<div>
<TopBarLeft>
{props.author &&
props.author.username && (
<Username>{props.author.username}</Username>
)}
<Timestamp>{props.createdAt}</Timestamp>
</TopBarLeft>
</div>
<Field name="body" validate={required}>
{({ input, meta }) => (
<div>
<Localized id="comments-editCommentForm-rteLabel">
<AriaInfo component="label" htmlFor={inputID}>
Edit comment
</AriaInfo>
</Localized>
<Localized
id="comments-editCommentForm-rte"
attrs={{ placeholder: true }}
>
<RTE
inputId={inputID}
onChange={({ html }) => input.onChange(html)}
value={input.value}
placeholder="Edit comment"
forwardRef={props.rteRef}
disabled={submitting || props.expired}
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<Typography align="right" color="error" gutterBottom>
{meta.error || meta.submitError}
</Typography>
)}
</div>
)}
</Field>
{props.expired ? (
<Localized id="comments-editCommentForm-editTimeExpired">
<ValidationMessage fullWidth>
Edit time has expired. You can no longer edit this comment.
Why not post another one?
</ValidationMessage>
</Localized>
) : (
<Message fullWidth>
<MessageIcon>alarm</MessageIcon>
<Localized
id="comments-editCommentForm-editRemainingTime"
time={<RelativeTime date={props.editableUntil} live />}
>
<span>{"Edit: <time></time> remaining"}</span>
</Localized>
</Message>
)}
<Flex direction="row" justifyContent="flex-end" itemGutter="half">
{props.expired ? (
<Localized id="comments-editCommentForm-close">
<Button
id={`comments-editCommentForm-closeButton-${props.id}`}
variant="outlined"
disabled={submitting}
onClick={props.onClose}
>
Close
</Button>
</Localized>
) : (
<>
<Localized id="comments-editCommentForm-cancel">
<Button
id={`comments-editCommentForm-cancelButton-${props.id}`}
variant="outlined"
disabled={submitting}
onClick={props.onCancel}
>
Cancel
</Button>
</Localized>
<Localized id="comments-editCommentForm-saveChanges">
<Button
color="primary"
variant="filled"
disabled={submitting || hasValidationErrors || pristine}
type="submit"
>
Save Changes
</Button>
</Localized>
</>
)}
</Flex>
</HorizontalGutter>
</form>
)}
</Form>
);
};
export default EditCommentForm;
@@ -1,11 +0,0 @@
.root {
}
.level1 {
padding-left: var(--spacing-unit);
border-left: 3px solid var(--palette-grey-darkest);
}
.noBorder {
border: 0;
}
@@ -1,33 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import Indent from "./Indent";
it("renders level0", () => {
const props: PropTypesOf<typeof Indent> = {
children: <div>Hello World</div>,
};
const wrapper = shallow(<Indent {...props} />);
expect(wrapper).toMatchSnapshot();
});
it("renders level1", () => {
const props: PropTypesOf<typeof Indent> = {
level: 1,
children: <div>Hello World</div>,
};
const wrapper = shallow(<Indent {...props} />);
expect(wrapper).toMatchSnapshot();
});
it("renders without border", () => {
const props: PropTypesOf<typeof Indent> = {
level: 1,
noBorder: true,
children: <div>Hello World</div>,
};
const wrapper = shallow(<Indent {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,26 +0,0 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import * as styles from "./Indent.css";
export interface IndentProps {
className?: string;
level?: number;
noBorder?: boolean;
children: React.ReactNode;
}
const Indent: StatelessComponent<IndentProps> = props => {
return (
<div
className={cn(props.className, styles.root, {
[styles.level1]: props.level === 1,
[styles.noBorder]: props.noBorder,
})}
>
{props.children}
</div>
);
};
export default Indent;
@@ -1,4 +0,0 @@
.popover {
width: 350px;
max-width: 80%;
}
@@ -1,74 +0,0 @@
import { Localized } from "fluent-react/compat";
import React from "react";
import { oncePerFrame } from "talk-common/utils";
import {
Button,
ButtonIcon,
ClickOutside,
MatchMedia,
Popover,
} from "talk-ui/components";
import * as styles from "./PermalinkButton.css";
import PermalinkPopover from "./PermalinkPopover";
interface PermalinkProps {
commentID: string;
assetURL: string | null;
}
class Permalink extends React.Component<PermalinkProps> {
// Helper that prevents calling toggleVisibility more then once per frame.
// In essence this means we'll process an event only once.
// This might happen, when clicking on the button which will
// cause its onClick to happen as well as onClickOutside.
private toggleVisibilityOncePerFrame = oncePerFrame(
(toggleVisibility: () => void) => toggleVisibility()
);
public render() {
const { commentID, assetURL } = this.props;
const popoverID = `permalink-popover-${commentID}`;
return (
<Popover
id={popoverID}
placement="top-start"
description="A dialog showing a permalink to the comment"
className={styles.popover}
body={({ toggleVisibility }) => (
<ClickOutside
onClickOutside={() =>
this.toggleVisibilityOncePerFrame(toggleVisibility)
}
>
<PermalinkPopover
permalinkURL={`${assetURL}&commentID=${commentID}`}
toggleVisibility={toggleVisibility}
/>
</ClickOutside>
)}
>
{({ toggleVisibility, forwardRef, visible }) => (
<Button
onClick={() => this.toggleVisibilityOncePerFrame(toggleVisibility)}
aria-controls={popoverID}
forwardRef={forwardRef}
variant="ghost"
active={visible}
size="small"
>
<MatchMedia gtWidth="xs">
<ButtonIcon>share</ButtonIcon>
</MatchMedia>
<Localized id="comments-permalinkButton-share">
<span>Share</span>
</Localized>
</Button>
)}
</Popover>
);
}
}
export default Permalink;
@@ -1,6 +0,0 @@
.root {
}
.textField {
flex-grow: 1;
}
@@ -1,64 +0,0 @@
import { Localized } from "fluent-react/compat";
import React from "react";
import CopyToClipboard from "react-copy-to-clipboard";
import { Button, Flex, TextField } from "talk-ui/components";
import * as styles from "./PermalinkPopover.css";
interface InnerProps {
permalinkURL: string;
toggleVisibility: () => void;
}
interface State {
copied: boolean;
}
class PermalinkPopover extends React.Component<InnerProps> {
public state: State = {
copied: false,
};
private onCopy = async () => {
await this.toggleCopied();
setTimeout(() => {
this.toggleCopied();
}, 800);
};
private toggleCopied = () => {
this.setState((state: State) => ({
copied: !state.copied,
}));
};
public render() {
const { permalinkURL } = this.props;
const { copied } = this.state;
return (
<Flex itemGutter="half" className={styles.root}>
<TextField
defaultValue={permalinkURL}
className={styles.textField}
readOnly
/>
<CopyToClipboard text={permalinkURL} onCopy={this.onCopy}>
<Button color="primary" variant="filled" size="small">
{copied ? (
<Localized id="comments-permalinkPopover-copied">
<span>Copied!</span>
</Localized>
) : (
<Localized id="comments-permalinkPopover-copy">
<span>Copy</span>
</Localized>
)}
</Button>
</CopyToClipboard>
</Flex>
);
}
}
export default PermalinkPopover;
@@ -1 +0,0 @@
export { default } from "./PermalinkButton";
@@ -1,7 +0,0 @@
.root {
width: 100%;
}
.button {
margin-bottom: calc(2 * var(--spacing-unit));
}
@@ -1,54 +0,0 @@
import { Localized } from "fluent-react/compat";
import React, { MouseEvent, StatelessComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, Typography } from "talk-ui/components";
import CommentContainer from "../containers/CommentContainer";
import * as styles from "./PermalinkView.css";
export interface PermalinkViewProps {
me: PropTypesOf<typeof CommentContainer>["me"];
asset: PropTypesOf<typeof CommentContainer>["asset"];
comment: PropTypesOf<typeof CommentContainer>["comment"] | null;
showAllCommentsHref: string | null;
onShowAllComments: (e: MouseEvent<any>) => void;
}
const PermalinkView: StatelessComponent<PermalinkViewProps> = ({
showAllCommentsHref,
comment,
asset,
onShowAllComments,
me,
}) => {
return (
<div className={styles.root}>
{showAllCommentsHref && (
<Localized id="comments-permalinkView-showAllComments">
<Button
id="talk-comments-permalinkView-showAllComments"
variant="outlined"
color="primary"
onClick={onShowAllComments}
className={styles.button}
href={showAllCommentsHref}
target="_parent"
fullWidth
anchor
>
Show all Comments
</Button>
</Localized>
)}
{!comment && (
<Localized id="comments-permalinkView-commentNotFound">
<Typography>Comment not found</Typography>
</Localized>
)}
{comment && <CommentContainer me={me} comment={comment} asset={asset} />}
</div>
);
};
export default PermalinkView;
@@ -1,6 +0,0 @@
.root {
}
.poweredBy {
margin-top: calc(-0.5 * var(--spacing-unit));
}
@@ -1,96 +0,0 @@
import { FormState } from "final-form";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Field, Form, FormSpy } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
import { required } from "talk-framework/lib/validation";
import {
AriaInfo,
Button,
Flex,
HorizontalGutter,
Typography,
} from "talk-ui/components";
import * as styles from "./PostCommentForm.css";
import PoweredBy from "./PoweredBy";
import RTE from "./RTE";
interface FormProps {
body: string;
}
export interface PostCommentFormProps {
onSubmit: OnSubmit<FormProps>;
onChange?: (state: FormState) => void;
initialValues?: FormProps;
}
const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
<Form onSubmit={props.onSubmit} initialValues={props.initialValues}>
{({ handleSubmit, submitting, hasValidationErrors }) => (
<form
autoComplete="off"
onSubmit={handleSubmit}
className={styles.root}
id="comments-postCommentForm-form"
>
<FormSpy onChange={props.onChange} />
<HorizontalGutter>
<Field name="body" validate={required}>
{({ input, meta }) => (
<div>
<Localized id="comments-postCommentForm-rteLabel">
<AriaInfo
component="label"
htmlFor="comments-postCommentForm-field"
>
Post a comment
</AriaInfo>
</Localized>
<Localized
id="comments-postCommentForm-rte"
attrs={{ placeholder: true }}
>
<RTE
inputId="comments-postCommentForm-field"
onChange={({ html }) => input.onChange(html)}
value={input.value}
placeholder="Post a comment"
disabled={submitting}
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<Typography align="right" color="error" gutterBottom>
{meta.error || meta.submitError}
</Typography>
)}
</div>
)}
</Field>
<Flex
direction="row"
justifyContent="space-between"
alignItems="flex-start"
>
<PoweredBy className={styles.poweredBy} />
<Localized id="comments-postCommentForm-submit">
<Button
color="primary"
variant="filled"
disabled={submitting || hasValidationErrors}
type="submit"
>
Submit
</Button>
</Localized>
</Flex>
</HorizontalGutter>
</form>
)}
</Form>
);
export default PostCommentForm;
@@ -1,13 +0,0 @@
.root {
}
.textarea {
composes: bodyCopy from "talk-ui/shared/typography.css";
display: block;
height: 150px;
width: 100%;
box-sizing: border-box;
padding: var(--spacing-unit);
border-radius: var(--round-corners);
resize: vertical;
}
@@ -1,9 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import PostCommentFormFake from "./PostCommentFormFake";
it("renders correctly", () => {
const wrapper = shallow(<PostCommentFormFake />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,25 +0,0 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Button, HorizontalGutter } from "talk-ui/components";
import * as styles from "./PostCommentFormFake.css";
import RTE from "./RTE";
const PostCommentFormFake: StatelessComponent = props => (
<HorizontalGutter className={styles.root}>
<div aria-hidden="true">
<Localized
id="comments-postCommentFormFake-rte"
attrs={{ placeholder: true }}
>
<RTE placeholder="Post a comment" disabled />
</Localized>
</div>
<Localized id="comments-postCommentFormFake-signInAndJoin">
<Button color="primary" variant="filled" disabled type="submit" fullWidth>
Sign in and join the conversation
</Button>
</Localized>
</HorizontalGutter>
);
export default PostCommentFormFake;
@@ -1,14 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import PoweredBy from "./PoweredBy";
it("renders correctly", () => {
const props: PropTypesOf<typeof PoweredBy> = {
className: "custom",
};
const wrapper = shallow(<PoweredBy {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,25 +0,0 @@
import cn from "classnames";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Typography } from "talk-ui/components";
interface Props {
className: string;
}
const PoweredBy: StatelessComponent<Props> = props => {
return (
<div className={cn(props.className)}>
<Localized
id="comments-poweredBy"
logo={<Typography variant="heading4" container="span" />}
>
<Typography variant="detail" container="span" color="textSecondary">
{"Powered by <logo>The Coral Project</logo>"}
</Typography>
</Localized>
</div>
);
};
export default PoweredBy;
@@ -1,8 +0,0 @@
.content {
composes: root from "talk-stream/shared/htmlContent.css";
}
.placeholder {
composes: placeholder from "talk-ui/shared/typography.css";
margin: var(--spacing-unit) 0 0 calc(1px + var(--spacing-unit));
}
@@ -1,16 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import RTE from "./RTE";
it("renders correctly", () => {
const props: PropTypesOf<typeof RTE> = {
className: "custom",
placeholder: "Post a comment",
value: "Hello world",
};
const wrapper = shallow(<RTE {...props} />);
expect(wrapper).toMatchSnapshot();
});
-110
View File
@@ -1,110 +0,0 @@
import { Blockquote, Bold, CoralRTE, Italic } from "@coralproject/rte";
import { Localized as LocalizedOriginal } from "fluent-react/compat";
import React, { Ref, StatelessComponent } from "react";
import { Icon } from "talk-ui/components";
import { PropTypesOf } from "talk-ui/types";
import * as styles from "./RTE.css";
// Use a special Localized version that forwards
// ref and passes the api prop to the children.
// This is currently required in order for the RTE
// to detect and setup the features.
const Localized = React.forwardRef<any, PropTypesOf<typeof LocalizedOriginal>>(
({ api, ...props }, ref) => (
<LocalizedOriginal {...props}>
{React.cloneElement(React.Children.only(props.children), { api, ref })}
</LocalizedOriginal>
)
);
export interface RTEProps {
inputId?: string;
/**
* The content value of the component.
*/
defaultValue?: string;
/**
* The content value of the component.
*/
value?: string;
/**
* Convenient prop to override the root styling.
*/
className?: string;
/*
* If set renders a full width button
*/
fullWidth?: boolean;
/**
* Placeholder
*/
placeholder?: string;
/**
* onChange
*/
onChange?: (data: { html: string; text: string }) => void;
disabled?: boolean;
forwardRef?: Ref<CoralRTE>;
}
// tslint:disable:jsx-wrap-multiline
const features = [
<Localized key="bold" id="comments-rte-bold" attrs={{ title: true }}>
<Bold>
<Icon size="md">format_bold</Icon>
</Bold>
</Localized>,
<Localized key="italic" id="comments-rte-italic" attrs={{ title: true }}>
<Italic>
<Icon size="md">format_italic</Icon>
</Italic>
</Localized>,
<Localized
key="blockquote"
id="comments-rte-blockquote"
attrs={{ title: true }}
>
<Blockquote key="blockquote">
<Icon size="md">format_quote</Icon>
</Blockquote>
</Localized>,
];
// tslint:enable:jsx-wrap-multiline
const RTE: StatelessComponent<RTEProps> = props => {
const {
className,
fullWidth,
value,
inputId,
placeholder,
onChange,
disabled,
defaultValue,
forwardRef,
...rest
} = props;
return (
<div>
<CoralRTE
inputId={inputId}
className={className}
contentClassName={styles.content}
placeholderClassName={styles.placeholder}
onChange={onChange}
value={value || defaultValue}
disabled={disabled}
placeholder={placeholder}
features={features}
ref={forwardRef}
{...rest}
/>
</div>
);
};
export default RTE;
@@ -1,109 +0,0 @@
import { CoralRTE } from "@coralproject/rte";
import { FormState } from "final-form";
import { Localized } from "fluent-react/compat";
import React, {
EventHandler,
MouseEvent,
Ref,
StatelessComponent,
} from "react";
import { Field, Form, FormSpy } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
import { required } from "talk-framework/lib/validation";
import {
AriaInfo,
Button,
Flex,
HorizontalGutter,
Typography,
} from "talk-ui/components";
import RTE from "./RTE";
interface FormProps {
body: string;
}
export interface ReplyCommentFormProps {
id: string;
className?: string;
onSubmit: OnSubmit<FormProps>;
onCancel?: EventHandler<MouseEvent<any>>;
onChange?: (state: FormState) => void;
initialValues?: FormProps;
rteRef?: Ref<CoralRTE>;
}
const ReplyCommentForm: StatelessComponent<ReplyCommentFormProps> = props => {
const inputID = `comments-replyCommentForm-rte-${props.id}`;
return (
<Form onSubmit={props.onSubmit} initialValues={props.initialValues}>
{({ handleSubmit, submitting, hasValidationErrors }) => (
<form
className={props.className}
autoComplete="off"
onSubmit={handleSubmit}
id={`comments-replyCommentForm-form-${props.id}`}
>
<FormSpy onChange={props.onChange} />
<HorizontalGutter>
<Field name="body" validate={required}>
{({ input, meta }) => (
<div>
<Localized id="comments-replyCommentForm-rteLabel">
<AriaInfo component="label" htmlFor={inputID}>
Write a reply
</AriaInfo>
</Localized>
<Localized
id="comments-replyCommentForm-rte"
attrs={{ placeholder: true }}
>
<RTE
inputId={inputID}
onChange={({ html }) => input.onChange(html)}
value={input.value}
placeholder="Write a reply"
forwardRef={props.rteRef}
disabled={submitting}
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<Typography align="right" color="error" gutterBottom>
{meta.error || meta.submitError}
</Typography>
)}
</div>
)}
</Field>
<Flex direction="row" justifyContent="flex-end" itemGutter="half">
<Localized id="comments-replyCommentForm-cancel">
<Button
variant="outlined"
disabled={submitting}
onClick={props.onCancel}
>
Cancel
</Button>
</Localized>
<Localized id="comments-replyCommentForm-submit">
<Button
color="primary"
variant="filled"
disabled={submitting || hasValidationErrors}
type="submit"
>
Submit
</Button>
</Localized>
</Flex>
</HorizontalGutter>
</form>
)}
</Form>
);
};
export default ReplyCommentForm;
@@ -1,58 +0,0 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import sinon, { SinonSpy } from "sinon";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
import ReplyList from "./ReplyList";
const ReplyListN = removeFragmentRefs(ReplyList);
it("renders correctly", () => {
const props: PropTypesOf<typeof ReplyListN> = {
asset: { id: "asset-id" },
comment: { id: "comment-id" },
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onShowAll: noop,
hasMore: false,
disableShowAll: false,
indentLevel: 1,
me: null,
};
const wrapper = shallow(<ReplyListN {...props} />);
expect(wrapper).toMatchSnapshot();
});
describe("when there is more", () => {
const props: PropTypesOf<typeof ReplyListN> = {
asset: { id: "asset-id" },
comment: { id: "comment-id" },
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onShowAll: sinon.spy(),
hasMore: true,
disableShowAll: false,
indentLevel: 1,
me: null,
};
const wrapper = shallow(<ReplyListN {...props} />);
it("renders a load more button", () => {
expect(wrapper).toMatchSnapshot();
});
it("calls onLoadMore", () => {
wrapper
.find("#talk-comments-replyList-showAll--comment-id")
.simulate("click");
expect((props.onShowAll as SinonSpy).calledOnce).toBe(true);
});
const wrapperDisabledButton = shallow(
<ReplyListN {...props} disableShowAll />
);
it("disables load more button", () => {
expect(wrapperDisabledButton).toMatchSnapshot();
});
});
@@ -1,61 +0,0 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, HorizontalGutter } from "talk-ui/components";
import CommentContainer from "../containers/CommentContainer";
import Indent from "./Indent";
export interface ReplyListProps {
asset: PropTypesOf<typeof CommentContainer>["asset"];
me: PropTypesOf<typeof CommentContainer>["me"];
comment: {
id: string;
};
comments: ReadonlyArray<
{ id: string } & PropTypesOf<typeof CommentContainer>["comment"]
>;
onShowAll: () => void;
hasMore: boolean;
disableShowAll: boolean;
indentLevel?: number;
}
const ReplyList: StatelessComponent<ReplyListProps> = props => {
return (
<HorizontalGutter
id={`talk-comments-replyList-log--${props.comment.id}`}
role="log"
>
{props.comments.map(comment => (
<CommentContainer
key={comment.id}
me={props.me}
comment={comment}
asset={props.asset}
indentLevel={props.indentLevel}
/>
))}
{props.hasMore && (
<Indent level={props.indentLevel} noBorder>
<Localized id="comments-replyList-showAll">
<Button
id={`talk-comments-replyList-showAll--${props.comment.id}`}
aria-controls={`talk-comments-replyList-log--${props.comment.id}`}
onClick={props.onShowAll}
disabled={props.disableShowAll}
variant="outlined"
fullWidth
>
Show All Replies
</Button>
</Localized>
</Indent>
)}
</HorizontalGutter>
);
};
export default ReplyList;
@@ -1,3 +0,0 @@
.root {
width: 100%;
}
@@ -1,74 +0,0 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import sinon, { SinonSpy } from "sinon";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
import Stream from "./Stream";
const StreamN = removeFragmentRefs(Stream);
it("renders correctly", () => {
const props: PropTypesOf<typeof StreamN> = {
asset: {
id: "asset-id",
isClosed: false,
},
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onLoadMore: noop,
disableLoadMore: false,
hasMore: false,
me: null,
};
const wrapper = shallow(<StreamN {...props} />);
expect(wrapper).toMatchSnapshot();
});
describe("when use is logged in", () => {
it("renders correctly", () => {
const props: PropTypesOf<typeof StreamN> = {
asset: {
id: "asset-id",
isClosed: false,
},
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onLoadMore: noop,
disableLoadMore: false,
hasMore: false,
me: {},
};
const wrapper = shallow(<StreamN {...props} />);
expect(wrapper).toMatchSnapshot();
});
});
describe("when there is more", () => {
const props: PropTypesOf<typeof StreamN> = {
asset: {
id: "asset-id",
isClosed: false,
},
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onLoadMore: sinon.spy(),
disableLoadMore: false,
hasMore: true,
me: null,
};
const wrapper = shallow(<StreamN {...props} />);
it("renders a load more button", () => {
expect(wrapper).toMatchSnapshot();
});
it("calls onLoadMore", () => {
wrapper.find("#talk-comments-stream-loadMore").simulate("click");
expect((props.onLoadMore as SinonSpy).calledOnce).toBe(true);
});
const wrapperDisabledButton = shallow(<StreamN {...props} disableLoadMore />);
it("disables load more button", () => {
expect(wrapperDisabledButton).toMatchSnapshot();
});
});
@@ -1,84 +0,0 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, HorizontalGutter } from "talk-ui/components";
import CommentContainer from "../containers/CommentContainer";
import PostCommentFormContainer from "../containers/PostCommentFormContainer";
import ReplyListContainer from "../containers/ReplyListContainer";
import UserBoxContainer from "../containers/UserBoxContainer";
import PostCommentFormFake from "./PostCommentFormFake";
import * as styles from "./Stream.css";
export interface StreamProps {
asset: {
id: string;
isClosed?: boolean;
} & PropTypesOf<typeof CommentContainer>["asset"] &
PropTypesOf<typeof ReplyListContainer>["asset"];
comments: ReadonlyArray<
{ id: string } & PropTypesOf<typeof CommentContainer>["comment"] &
PropTypesOf<typeof ReplyListContainer>["comment"]
>;
onLoadMore?: () => void;
hasMore?: boolean;
disableLoadMore?: boolean;
me:
| PropTypesOf<typeof UserBoxContainer>["me"] &
PropTypesOf<typeof CommentContainer>["me"] &
PropTypesOf<typeof ReplyListContainer>["me"]
| null;
}
const Stream: StatelessComponent<StreamProps> = props => {
return (
<HorizontalGutter className={styles.root} size="double">
<HorizontalGutter size="half">
<UserBoxContainer me={props.me} />
{props.me ? (
<PostCommentFormContainer assetID={props.asset.id} />
) : (
<PostCommentFormFake />
)}
</HorizontalGutter>
<HorizontalGutter
id="talk-comments-stream-log"
role="log"
aria-live="polite"
>
{props.comments.map(comment => (
<HorizontalGutter key={comment.id}>
<CommentContainer
me={props.me}
comment={comment}
asset={props.asset}
/>
<ReplyListContainer
me={props.me}
comment={comment}
asset={props.asset}
/>
</HorizontalGutter>
))}
{props.hasMore && (
<Localized id="comments-stream-loadMore">
<Button
id={"talk-comments-stream-loadMore"}
onClick={props.onLoadMore}
variant="outlined"
fullWidth
disabled={props.disableLoadMore}
aria-controls="talk-comments-stream-log"
>
Load More
</Button>
</Localized>
)}
</HorizontalGutter>
</HorizontalGutter>
);
};
export default Stream;
@@ -1,31 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders level0 1`] = `
<div
className="Indent-root"
>
<div>
Hello World
</div>
</div>
`;
exports[`renders level1 1`] = `
<div
className="Indent-root Indent-level1"
>
<div>
Hello World
</div>
</div>
`;
exports[`renders without border 1`] = `
<div
className="Indent-root Indent-level1 Indent-noBorder"
>
<div>
Hello World
</div>
</div>
`;
@@ -1,38 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
className="PostCommentFormFake-root"
>
<div
aria-hidden="true"
>
<Localized
attrs={
Object {
"placeholder": true,
}
}
id="comments-postCommentFormFake-rte"
>
<RTE
disabled={true}
placeholder="Post a comment"
/>
</Localized>
</div>
<Localized
id="comments-postCommentFormFake-signInAndJoin"
>
<withPropsOnChange(Button)
color="primary"
disabled={true}
fullWidth={true}
type="submit"
variant="filled"
>
Sign in and join the conversation
</withPropsOnChange(Button)>
</Localized>
</withPropsOnChange(HorizontalGutter)>
`;
@@ -1,25 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="custom"
>
<Localized
id="comments-poweredBy"
logo={
<withPropsOnChange(Typography)
container="span"
variant="heading4"
/>
}
>
<withPropsOnChange(Typography)
color="textSecondary"
container="span"
variant="detail"
>
Powered by &lt;logo&gt;The Coral Project&lt;/logo&gt;
</withPropsOnChange(Typography)>
</Localized>
</div>
`;
@@ -1,70 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div>
<RTE
className="custom"
classNameDisabled=""
contentClassName="RTE-content"
contentClassNameDisabled=""
features={
Array [
<ForwardRef
attrs={
Object {
"title": true,
}
}
id="comments-rte-bold"
>
<Toggle>
<withPropsOnChange(Icon)
size="md"
>
format_bold
</withPropsOnChange(Icon)>
</Toggle>
</ForwardRef>,
<ForwardRef
attrs={
Object {
"title": true,
}
}
id="comments-rte-italic"
>
<Toggle>
<withPropsOnChange(Icon)
size="md"
>
format_italic
</withPropsOnChange(Icon)>
</Toggle>
</ForwardRef>,
<ForwardRef
attrs={
Object {
"title": true,
}
}
id="comments-rte-blockquote"
>
<Toggle>
<withPropsOnChange(Icon)
size="md"
>
format_quote
</withPropsOnChange(Icon)>
</Toggle>
</ForwardRef>,
]
}
placeholder="Post a comment"
placeholderClassName="RTE-placeholder"
placeholderClassNameDisabled=""
toolbarClassName=""
toolbarClassNameDisabled=""
value="Hello world"
/>
</div>
`;
@@ -1,153 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
id="talk-comments-replyList-log--comment-id"
role="log"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
}
}
comment={
Object {
"id": "comment-1",
}
}
indentLevel={1}
key="comment-1"
me={null}
/>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
}
}
comment={
Object {
"id": "comment-2",
}
}
indentLevel={1}
key="comment-2"
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
`;
exports[`when there is more disables load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
id="talk-comments-replyList-log--comment-id"
role="log"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
}
}
comment={
Object {
"id": "comment-1",
}
}
indentLevel={1}
key="comment-1"
me={null}
/>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
}
}
comment={
Object {
"id": "comment-2",
}
}
indentLevel={1}
key="comment-2"
me={null}
/>
<Indent
level={1}
noBorder={true}
>
<Localized
id="comments-replyList-showAll"
>
<withPropsOnChange(Button)
aria-controls="talk-comments-replyList-log--comment-id"
disabled={true}
fullWidth={true}
id="talk-comments-replyList-showAll--comment-id"
onClick={[Function]}
variant="outlined"
>
Show All Replies
</withPropsOnChange(Button)>
</Localized>
</Indent>
</withPropsOnChange(HorizontalGutter)>
`;
exports[`when there is more renders a load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
id="talk-comments-replyList-log--comment-id"
role="log"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
}
}
comment={
Object {
"id": "comment-1",
}
}
indentLevel={1}
key="comment-1"
me={null}
/>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
}
}
comment={
Object {
"id": "comment-2",
}
}
indentLevel={1}
key="comment-2"
me={null}
/>
<Indent
level={1}
noBorder={true}
>
<Localized
id="comments-replyList-showAll"
>
<withPropsOnChange(Button)
aria-controls="talk-comments-replyList-log--comment-id"
disabled={false}
fullWidth={true}
id="talk-comments-replyList-showAll--comment-id"
onClick={[Function]}
variant="outlined"
>
Show All Replies
</withPropsOnChange(Button)>
</Localized>
</Indent>
</withPropsOnChange(HorizontalGutter)>
`;
@@ -1,375 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
className="Stream-root"
size="double"
>
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
me={null}
/>
<PostCommentFormFake />
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
aria-live="polite"
id="talk-comments-stream-log"
role="log"
>
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={null}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={null}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
`;
exports[`when there is more disables load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
className="Stream-root"
size="double"
>
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
me={null}
/>
<PostCommentFormFake />
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
aria-live="polite"
id="talk-comments-stream-log"
role="log"
>
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={null}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={null}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
<Localized
id="comments-stream-loadMore"
>
<withPropsOnChange(Button)
aria-controls="talk-comments-stream-log"
disabled={true}
fullWidth={true}
id="talk-comments-stream-loadMore"
onClick={[Function]}
variant="outlined"
>
Load More
</withPropsOnChange(Button)>
</Localized>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
`;
exports[`when there is more renders a load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
className="Stream-root"
size="double"
>
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
me={null}
/>
<PostCommentFormFake />
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
aria-live="polite"
id="talk-comments-stream-log"
role="log"
>
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={null}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={null}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={null}
/>
</withPropsOnChange(HorizontalGutter)>
<Localized
id="comments-stream-loadMore"
>
<withPropsOnChange(Button)
aria-controls="talk-comments-stream-log"
disabled={false}
fullWidth={true}
id="talk-comments-stream-loadMore"
onClick={[Function]}
variant="outlined"
>
Load More
</withPropsOnChange(Button)>
</Localized>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
`;
exports[`when use is logged in renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
className="Stream-root"
size="double"
>
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
me={Object {}}
/>
<withContext(withContext(createMutationContainer(PostCommentFormContainer)))
assetID="asset-id"
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
aria-live="polite"
id="talk-comments-stream-log"
role="log"
>
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={Object {}}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-1",
}
}
me={Object {}}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={Object {}}
/>
<Relay(ReplyListContainer)
asset={
Object {
"id": "asset-id",
"isClosed": false,
}
}
comment={
Object {
"id": "comment-2",
}
}
me={Object {}}
/>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
`;