mirror of
https://github.com/wassname/talk.git
synced 2026-09-11 12:51:33 +08:00
Move files into tab structure
This commit is contained in:
@@ -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();
|
||||
});
|
||||
@@ -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 <logo>The Coral Project</logo>
|
||||
</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)>
|
||||
`;
|
||||
Reference in New Issue
Block a user