Merge branch 'next' of github.com:coralproject/talk into next-profile

* 'next' of github.com:coralproject/talk:
  Adapt snapshot
  Fix lint
  Only show edit button for the author
  Use Message Component
  Adapt integration test
  Fix integration test
  Add edited marker
  fix: remove assetID from client queries to edit comment
  feat: merge metadata during edit
  fix: remove assetID from EditCommentInput
  Fix linting
  Add integration tests
  Add integration test
  More unit tests
  Fix lint and test
  Implement edit
This commit is contained in:
Belén Curcio
2018-09-14 09:49:07 -03:00
63 changed files with 4233 additions and 596 deletions
@@ -216,7 +216,7 @@ exports[`navigates to sign up form 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -239,7 +239,7 @@ exports[`navigates to sign up form 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -56,7 +56,7 @@ exports[`accepts correct password 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -92,7 +92,7 @@ exports[`accepts correct password 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -237,7 +237,7 @@ exports[`accepts correct password confirmation 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -273,7 +273,7 @@ exports[`accepts correct password confirmation 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -418,7 +418,7 @@ exports[`accepts valid email 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -454,7 +454,7 @@ exports[`accepts valid email 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -612,7 +612,7 @@ exports[`accepts valid username 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -635,7 +635,7 @@ exports[`accepts valid username 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -793,7 +793,7 @@ exports[`checks for invalid characters in username 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -829,7 +829,7 @@ exports[`checks for invalid characters in username 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -987,7 +987,7 @@ exports[`checks for invalid email 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -1023,7 +1023,7 @@ exports[`checks for invalid email 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1181,7 +1181,7 @@ exports[`checks for too long username 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -1217,7 +1217,7 @@ exports[`checks for too long username 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1375,7 +1375,7 @@ exports[`checks for too short password 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -1411,7 +1411,7 @@ exports[`checks for too short password 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1569,7 +1569,7 @@ exports[`checks for too short username 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -1605,7 +1605,7 @@ exports[`checks for too short username 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1763,7 +1763,7 @@ exports[`checks for wrong password confirmation 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -1799,7 +1799,7 @@ exports[`checks for wrong password confirmation 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -1944,7 +1944,7 @@ exports[`renders sign up form 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -1967,7 +1967,7 @@ exports[`renders sign up form 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2099,7 +2099,7 @@ exports[`shows error when submitting empty form 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -2135,7 +2135,7 @@ exports[`shows error when submitting empty form 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2280,7 +2280,7 @@ exports[`shows server error 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -2303,7 +2303,7 @@ exports[`shows server error 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2427,7 +2427,7 @@ exports[`shows server error 2`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -2450,7 +2450,7 @@ exports[`shows server error 2`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2569,7 +2569,7 @@ exports[`submits form successfully 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -2592,7 +2592,7 @@ exports[`submits form successfully 1`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -2711,7 +2711,7 @@ exports[`submits form successfully 2`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -2734,7 +2734,7 @@ exports[`submits form successfully 2`] = `
Password
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Must be at least 8 characters
</p>
@@ -53,7 +53,16 @@ interface CreateContextArguments {
*/
export const timeagoFormatter: Formatter = (value, unit, suffix) => {
// We use 'in' instead of 'from now' for language consistency
const ourSuffix = suffix === "from now" ? "in" : suffix;
const ourSuffix = suffix === "from now" ? "noSuffix" : suffix;
if (unit === "second" && suffix === "ago") {
return (
<Localized id="framework-timeago-just-now">
<span>Just now</span>
</Localized>
);
}
return (
<Localized
id="framework-timeago"
@@ -6,6 +6,3 @@
.footer:not(:empty) {
margin-top: var(--spacing-unit);
}
.reply {
margin-top: var(--spacing-unit);
}
@@ -7,12 +7,14 @@ import Comment from "./Comment";
it("renders username and body", () => {
const props: PropTypesOf<typeof Comment> = {
id: "comment-id",
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,32 +1,46 @@
import React, { ReactElement, StatelessComponent } from "react";
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 TopBar from "./TopBar";
import TopBarLeft from "./TopBarLeft";
import Username from "./Username";
export interface CommentProps {
id: string;
className?: string;
author: {
username: string | null;
} | null;
body: string | null;
createdAt: string;
footer?: ReactElement<any> | Array<ReactElement<any>>;
topBarRight?: React.ReactNode;
footer?: React.ReactNode;
showEditedMarker?: boolean;
}
const Comment: StatelessComponent<CommentProps> = props => {
return (
<div role="article" className={styles.root}>
<TopBar className={styles.topBar}>
{props.author &&
props.author.username && <Username>{props.author.username}</Username>}
<Timestamp>{props.createdAt}</Timestamp>
</TopBar>
<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}
@@ -0,0 +1,3 @@
.root {
composes: detail from "talk-ui/shared/typography.css";
}
@@ -0,0 +1,9 @@
import { shallow } from "enzyme";
import React from "react";
import EditedMarker from "./EditedMarker";
it("renders correctly", () => {
const wrapper = shallow(<EditedMarker />);
expect(wrapper).toMatchSnapshot();
});
@@ -0,0 +1,16 @@
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,22 +1,17 @@
import React from "react";
import dompurify from "dompurify";
import React, { StatelessComponent } from "react";
import styles from "./HTMLContent.css";
interface ContentProps {
interface HTMLContentProps {
children: string;
}
class HTMLContent extends React.Component<ContentProps> {
public render() {
const { children } = this.props;
return (
<div
className={styles.root}
dangerouslySetInnerHTML={{ __html: dompurify.sanitize(children) }}
/>
);
}
}
const HTMLContent: StatelessComponent<HTMLContentProps> = ({ children }) => (
<div
className={styles.root}
dangerouslySetInnerHTML={{ __html: dompurify.sanitize(children) }}
/>
);
export default HTMLContent;
@@ -8,7 +8,6 @@ import IndentedComment from "./IndentedComment";
it("renders correctly", () => {
const props: PropTypesOf<typeof IndentedComment> = {
indentLevel: 1,
id: "comment-id",
author: {
username: "Marvin",
},
@@ -4,10 +4,10 @@ import TestRenderer from "react-test-renderer";
import { PropTypesOf } from "talk-framework/types";
import { UIContext, UIContextProps } from "talk-ui/components";
import TopBar from "./TopBar";
import TopBarLeft from "./TopBarLeft";
it("renders correctly on small screens", () => {
const props: PropTypesOf<typeof TopBar> = {
const props: PropTypesOf<typeof TopBarLeft> = {
children: <div>Hello World</div>,
};
@@ -19,14 +19,14 @@ it("renders correctly on small screens", () => {
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<TopBar {...props} />
<TopBarLeft {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("renders correctly on big screens", () => {
const props: PropTypesOf<typeof TopBar> = {
const props: PropTypesOf<typeof TopBarLeft> = {
children: <div>Hello World</div>,
};
@@ -38,7 +38,7 @@ it("renders correctly on big screens", () => {
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<TopBar {...props} />
<TopBarLeft {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
@@ -4,12 +4,12 @@ import { StatelessComponent } from "react";
import { Flex, MatchMedia } from "talk-ui/components";
export interface TopBarProps {
export interface TopBarLeftProps {
className?: string;
children: React.ReactNode;
}
const TopBar: StatelessComponent<TopBarProps> = props => {
const TopBarLeft: StatelessComponent<TopBarLeftProps> = props => {
const rootClassName = cn(props.className);
return (
<MatchMedia gtWidth="xs">
@@ -27,4 +27,4 @@ const TopBar: StatelessComponent<TopBarProps> = props => {
);
};
export default TopBar;
export default TopBarLeft;
@@ -5,16 +5,30 @@ exports[`renders username and body 1`] = `
className="Comment-root"
role="article"
>
<TopBar
<withPropsOnChange(Flex)
className="Comment-topBar"
direction="row"
justifyContent="space-between"
>
<Username>
Marvin
</Username>
<Timestamp>
1995-12-17T03:24:00.000Z
</Timestamp>
</TopBar>
<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>
@@ -22,6 +36,8 @@ exports[`renders username and body 1`] = `
className="Comment-footer"
direction="row"
itemGutter="half"
/>
>
footer
</withPropsOnChange(Flex)>
</div>
`;
@@ -0,0 +1,17 @@
// 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>
`;
@@ -13,7 +13,6 @@ exports[`renders correctly 1`] = `
}
body="Woof"
createdAt="1995-12-17T03:24:00.000Z"
id="comment-id"
/>
</Indent>
`;
@@ -1 +1,4 @@
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";
@@ -0,0 +1,161 @@
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;
@@ -14,11 +14,7 @@ const PoweredBy: StatelessComponent<Props> = props => {
id="comments-poweredBy"
logo={<Typography variant="heading4" container="span" />}
>
<Typography
variant="inputDescription"
container="span"
color="textSecondary"
>
<Typography variant="detail" container="span" color="textSecondary">
{"Powered by <logo>The Coral Project</logo>"}
</Typography>
</Localized>
@@ -16,7 +16,7 @@ exports[`renders correctly 1`] = `
<withPropsOnChange(Typography)
color="textSecondary"
container="span"
variant="inputDescription"
variant="detail"
>
Powered by &lt;logo&gt;The Coral Project&lt;/logo&gt;
</withPropsOnChange(Typography)>
@@ -19,10 +19,15 @@ it("renders username and body", () => {
comment: {
id: "comment-id",
author: {
id: "author-id",
username: "Marvin",
},
body: "Woof",
createdAt: "1995-12-17T03:24:00.000Z",
editing: {
edited: false,
editableUntil: "1995-12-17T03:24:30.000Z",
},
pending: false,
},
indentLevel: 1,
@@ -42,10 +47,15 @@ it("renders body only", () => {
comment: {
id: "comment-id",
author: {
id: "author-id",
username: null,
},
body: "Woof",
createdAt: "1995-12-17T03:24:00.000Z",
editing: {
edited: false,
editableUntil: "1995-12-17T03:24:30.000Z",
},
pending: false,
},
indentLevel: 1,
@@ -1,6 +1,8 @@
import { Localized } from "fluent-react/compat";
import React, { Component } from "react";
import { graphql } from "react-relay";
import { isBeforeDate } from "talk-common/utils";
import withFragmentContainer from "talk-framework/lib/relay/withFragmentContainer";
import { PropTypesOf } from "talk-framework/types";
import { CommentContainer_asset as AssetData } from "talk-stream/__generated__/CommentContainer_asset.graphql";
@@ -11,10 +13,12 @@ import {
withShowAuthPopupMutation,
} from "talk-stream/mutations";
import { Button } from "talk-ui/components";
import Comment from "../components/Comment";
import ReplyButton from "../components/Comment/ReplyButton";
import ReplyCommentFormContainer from ".//ReplyCommentFormContainer";
import EditCommentFormContainer from "./EditCommentFormContainer";
import PermalinkButtonContainer from "./PermalinkButtonContainer";
import ReplyCommentFormContainer from "./ReplyCommentFormContainer";
interface InnerProps {
me: MeData | null;
@@ -26,13 +30,41 @@ interface InnerProps {
interface State {
showReplyDialog: boolean;
showEditDialog: boolean;
editable: boolean;
}
export class CommentContainer extends Component<InnerProps, State> {
private uneditableTimer: any;
public state = {
showReplyDialog: false,
showEditDialog: false,
editable: this.isEditable(),
};
constructor(props: InnerProps) {
super(props);
if (this.isEditable()) {
this.uneditableTimer = this.updateWhenNotEditable();
}
}
public componentWillUnmount() {
clearTimeout(this.uneditableTimer);
}
private isEditable() {
const isMyComment = !!(
this.props.me &&
this.props.comment.author &&
this.props.me.id === this.props.comment.author.id
);
return (
isMyComment && isBeforeDate(this.props.comment.editing.editableUntil)
);
}
private openReplyDialog = () => {
if (this.props.me) {
this.setState(state => ({
@@ -43,21 +75,72 @@ export class CommentContainer extends Component<InnerProps, State> {
}
};
private openEditDialog = () => {
if (this.props.me) {
this.setState(state => ({
showEditDialog: true,
}));
} else {
this.props.showAuthPopup({ view: "SIGN_IN" });
}
};
private closeEditDialog = () => {
this.setState(state => ({
showEditDialog: false,
}));
};
private closeReplyDialog = () => {
this.setState(state => ({
showReplyDialog: false,
}));
};
private updateWhenNotEditable() {
const ms =
new Date(this.props.comment.editing.editableUntil).getTime() - Date.now();
if (ms > 0) {
return setTimeout(() => this.setState({ editable: false }), ms);
}
return;
}
public render() {
const { comment, asset, ...rest } = this.props;
const { showReplyDialog } = this.state;
const { comment, asset, indentLevel } = this.props;
const { showReplyDialog, showEditDialog, editable } = this.state;
if (showEditDialog) {
return (
<EditCommentFormContainer
comment={comment}
onClose={this.closeEditDialog}
/>
);
}
return (
<>
<Comment
{...rest}
{...comment}
indentLevel={indentLevel}
author={comment.author}
body={comment.body}
createdAt={comment.createdAt}
blur={comment.pending || false}
showEditedMarker={comment.editing.edited}
topBarRight={
(editable && (
<Localized id="comments-commentContainer-editButton">
<Button
id={`comments-commentContainer-editButton-${comment.id}`}
color="primary"
variant="underlined"
onClick={this.openEditDialog}
>
Edit
</Button>
</Localized>
)) ||
undefined
}
footer={
<>
<ReplyButton
@@ -85,7 +168,7 @@ const enhanced = withShowAuthPopupMutation(
withFragmentContainer<InnerProps>({
me: graphql`
fragment CommentContainer_me on User {
__typename
id
}
`,
asset: graphql`
@@ -97,12 +180,18 @@ const enhanced = withShowAuthPopupMutation(
fragment CommentContainer_comment on Comment {
id
author {
id
username
}
body
createdAt
editing {
edited
editableUntil
}
pending
...ReplyCommentFormContainer_comment
...EditCommentFormContainer_comment
}
`,
})(CommentContainer)
@@ -0,0 +1,131 @@
import { CoralRTE } from "@coralproject/rte";
import React, { Component } from "react";
import { graphql } from "react-relay";
import { isBeforeDate } from "talk-common/utils";
import { withContext } from "talk-framework/lib/bootstrap";
import { BadUserInputError } from "talk-framework/lib/errors";
import { withFragmentContainer } from "talk-framework/lib/relay";
import { PropTypesOf } from "talk-framework/types";
import { EditCommentFormContainer_comment as CommentData } from "talk-stream/__generated__/EditCommentFormContainer_comment.graphql";
import EditCommentForm, {
EditCommentFormProps,
} from "../components/EditCommentForm";
import { EditCommentMutation, withEditCommentMutation } from "../mutations";
interface InnerProps {
editComment: EditCommentMutation;
comment: CommentData;
onClose?: () => void;
autofocus: boolean;
}
interface State {
initialValues?: EditCommentFormProps["initialValues"];
initialized: boolean;
expired: boolean;
}
export class EditCommentFormContainer extends Component<InnerProps, State> {
private expiredTimer: any;
public state: State = {
initialized: false,
expired: !isBeforeDate(this.props.comment.editing.editableUntil),
};
constructor(props: InnerProps) {
super(props);
this.expiredTimer = this.updateWhenExpired();
}
public componentWillUnmount() {
clearTimeout(this.expiredTimer);
}
private updateWhenExpired() {
const ms =
new Date(this.props.comment.editing.editableUntil).getTime() - Date.now();
if (ms > 0) {
return setTimeout(() => this.setState({ expired: true }), ms);
}
return;
}
private handleRTERef = (rte: CoralRTE | null) => {
if (rte && this.props.autofocus) {
rte.focus();
}
};
private handleOnCancelOrClose = () => {
if (this.props.onClose) {
this.props.onClose();
}
};
private handleOnSubmit: EditCommentFormProps["onSubmit"] = async (
input,
form
) => {
try {
await this.props.editComment({
commentID: this.props.comment.id,
body: input.body,
});
if (this.props.onClose) {
this.props.onClose();
}
} catch (error) {
if (error instanceof BadUserInputError) {
return error.invalidArgsLocalized;
}
// tslint:disable-next-line:no-console
console.error(error);
}
return undefined;
};
public render() {
return (
<EditCommentForm
id={this.props.comment.id}
onSubmit={this.handleOnSubmit}
initialValues={{ body: this.props.comment.body || "" }}
onCancel={this.handleOnCancelOrClose}
onClose={this.handleOnCancelOrClose}
rteRef={this.handleRTERef}
author={this.props.comment.author}
createdAt={this.props.comment.createdAt}
editableUntil={this.props.comment.editing.editableUntil}
expired={this.state.expired}
/>
);
}
}
const enhanced = withContext(({ sessionStorage, browserInfo }) => ({
// Disable autofocus on ios and enable for the rest.
autofocus: !browserInfo.ios,
}))(
withEditCommentMutation(
withFragmentContainer<InnerProps>({
comment: graphql`
fragment EditCommentFormContainer_comment on Comment {
id
body
createdAt
author {
username
}
editing {
editableUntil
}
}
`,
})(EditCommentFormContainer)
)
);
export type PostCommentFormContainerProps = PropTypesOf<typeof enhanced>;
export default enhanced;
@@ -5,6 +5,7 @@ exports[`renders body only 1`] = `
<IndentedComment
author={
Object {
"id": "author-id",
"username": null,
}
}
@@ -23,11 +24,8 @@ exports[`renders body only 1`] = `
/>
</React.Fragment>
}
id="comment-id"
indentLevel={1}
me={null}
pending={false}
showAuthPopup={[Function]}
showEditedMarker={false}
/>
</React.Fragment>
`;
@@ -37,6 +35,7 @@ exports[`renders username and body 1`] = `
<IndentedComment
author={
Object {
"id": "author-id",
"username": "Marvin",
}
}
@@ -55,11 +54,8 @@ exports[`renders username and body 1`] = `
/>
</React.Fragment>
}
id="comment-id"
indentLevel={1}
me={null}
pending={false}
showAuthPopup={[Function]}
showEditedMarker={false}
/>
</React.Fragment>
`;
@@ -93,6 +93,9 @@ function commit(
username: me.username,
},
body: input.body,
editing: {
editableUntil: new Date(Date.now() + 10000),
},
},
},
clientMutationId: (clientMutationId++).toString(),
@@ -0,0 +1,62 @@
import { graphql } from "react-relay";
import { Environment } from "relay-runtime";
import {
commitMutationPromiseNormalized,
createMutationContainer,
} from "talk-framework/lib/relay";
import { Omit } from "talk-framework/types";
import { EditCommentMutation as MutationTypes } from "talk-stream/__generated__/EditCommentMutation.graphql";
export type EditCommentInput = Omit<
MutationTypes["variables"]["input"],
"clientMutationId"
>;
const mutation = graphql`
mutation EditCommentMutation($input: EditCommentInput!) {
editComment(input: $input) {
comment {
body
editing {
edited
}
}
clientMutationId
}
}
`;
let clientMutationId = 0;
function commit(environment: Environment, input: EditCommentInput) {
return commitMutationPromiseNormalized<MutationTypes>(environment, {
mutation,
variables: {
input: {
...input,
clientMutationId: clientMutationId.toString(),
},
},
optimisticResponse: {
editComment: {
id: input.commentID,
body: input.body,
editing: {
edited: true,
},
clientMutationId: (clientMutationId++).toString(),
},
} as any, // TODO: (cvle) generated types should contain one for the optimistic response.
});
}
export const withEditCommentMutation = createMutationContainer(
"editComment",
commit
);
export type EditCommentMutation = (
input: EditCommentInput
) => Promise<MutationTypes["response"]["editComment"]>;
@@ -3,6 +3,11 @@ export {
CreateCommentMutation,
CreateCommentInput,
} from "./CreateCommentMutation";
export {
withEditCommentMutation,
EditCommentMutation,
EditCommentInput,
} from "./EditCommentMutation";
export {
withSetNetworkStatusMutation,
SetNetworkStatusMutation,
File diff suppressed because it is too large Load Diff
@@ -156,20 +156,28 @@ exports[`loads more comments 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -213,20 +221,28 @@ exports[`loads more comments 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -270,20 +286,28 @@ exports[`loads more comments 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Isabelle
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:14:00.000Z"
title="2018-07-06T18:14:00.000Z"
>
2018-07-06T18:14:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:14:00.000Z"
title="2018-07-06T18:14:00.000Z"
>
2018-07-06T18:14:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -477,20 +501,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -534,20 +566,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -31,20 +31,28 @@ exports[`renders permalink view 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -236,20 +244,28 @@ exports[`show all comments 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -188,20 +188,28 @@ exports[`show all comments 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -145,7 +145,7 @@ exports[`post a comment: optimistic response 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -189,20 +189,44 @@ exports[`post a comment: optimistic response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
<div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
id="comments-commentContainer-editButton-uuid-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Edit
</button>
</div>
</div>
<div
className="HTMLContent-root"
@@ -246,20 +270,28 @@ exports[`post a comment: optimistic response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -303,20 +335,28 @@ exports[`post a comment: optimistic response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -505,7 +545,7 @@ exports[`post a comment: server response 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -549,20 +589,28 @@ exports[`post a comment: server response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -606,20 +654,28 @@ exports[`post a comment: server response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -663,20 +719,28 @@ exports[`post a comment: server response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -865,7 +929,7 @@ exports[`renders comment stream 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -909,20 +973,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -966,20 +1038,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -151,7 +151,7 @@ exports[`post a reply: open reply form 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -195,20 +195,28 @@ exports[`post a reply: open reply form 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -309,10 +317,10 @@ exports[`post a reply: open reply form 1`] = `
aria-hidden="true"
className="RTE-placeholder RTE-placeholder"
>
Post a comment
Write a reply
</div>
<div
aria-placeholder="Post a comment"
aria-placeholder="Write a reply"
className="RTE-contentEditable RTE-content"
contentEditable={true}
dangerouslySetInnerHTML={
@@ -379,20 +387,28 @@ exports[`post a reply: open reply form 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -581,7 +597,7 @@ exports[`post a reply: optimistic response 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -625,20 +641,28 @@ exports[`post a reply: optimistic response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -736,7 +760,7 @@ exports[`post a reply: optimistic response 1`] = `
</button>
</div>
<div
aria-placeholder="Post a comment"
aria-placeholder="Write a reply"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
@@ -804,20 +828,44 @@ exports[`post a reply: optimistic response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
<div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
id="comments-commentContainer-editButton-uuid-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Edit
</button>
</div>
</div>
<div
className="HTMLContent-root"
@@ -862,20 +910,28 @@ exports[`post a reply: optimistic response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -1064,7 +1120,7 @@ exports[`post a reply: server response 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -1108,20 +1164,28 @@ exports[`post a reply: server response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -1166,20 +1230,28 @@ exports[`post a reply: server response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -1224,20 +1296,28 @@ exports[`post a reply: server response 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -1426,7 +1506,7 @@ exports[`renders comment stream 1`] = `
className="PostCommentForm-poweredBy"
>
<span
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Powered by
<span
@@ -1470,20 +1550,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -1527,20 +1615,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -156,20 +156,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -213,20 +221,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -271,20 +287,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -324,20 +348,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -156,20 +156,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -213,20 +221,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -156,20 +156,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -214,20 +222,28 @@ exports[`renders comment stream 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -442,20 +458,28 @@ exports[`show all replies 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Markus
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -500,20 +524,28 @@ exports[`show all replies 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Lukas
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -553,20 +585,28 @@ exports[`show all replies 1`] = `
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
Isabelle
</span>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:14:00.000Z"
title="2018-07-06T18:14:00.000Z"
>
2018-07-06T18:14:00.000Z
</time>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Isabelle
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:14:00.000Z"
title="2018-07-06T18:14:00.000Z"
>
2018-07-06T18:14:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
@@ -0,0 +1,135 @@
import timekeeper from "timekeeper";
import { timeout } from "talk-common/utils";
import { createSinonStub } from "talk-framework/testHelpers";
import create from "./create";
import { assets, users } from "./fixtures";
function createTestRenderer() {
const resolvers = {
Query: {
asset: createSinonStub(
s => s.throws(),
s => s.withArgs(undefined, { id: assets[0].id }).returns(assets[0])
),
me: createSinonStub(
s => s.throws(),
s => s.withArgs(undefined).returns(users[0])
),
},
Mutation: {
editComment: createSinonStub(
s => s.throws(),
s =>
s
.withArgs(undefined, {
input: {
commentID: assets[0].comments.edges[0].node.id,
body: "Edited!",
clientMutationId: "0",
},
})
.returns({
// TODO: add a type assertion here to ensure that if the type changes, that the test will fail
comment: {
id: assets[0].comments.edges[0].node.id,
body: "Edited! (from server)",
editing: {
edited: true,
},
},
clientMutationId: "0",
})
),
},
};
const { testRenderer } = create({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: localRecord => {
localRecord.setValue(assets[0].id, "assetID");
},
});
return testRenderer;
}
afterAll(() => {
timekeeper.reset();
});
it("edit a comment", async () => {
timekeeper.freeze(assets[0].comments.edges[0].node.createdAt);
const testRenderer = createTestRenderer();
// Wait for loading.
await timeout();
expect(testRenderer.toJSON()).toMatchSnapshot("render stream");
// Open edit form.
testRenderer.root
.findByProps({ id: "comments-commentContainer-editButton-comment-0" })
.props.onClick();
expect(testRenderer.toJSON()).toMatchSnapshot("edit form");
testRenderer.root
.findByProps({ inputId: "comments-editCommentForm-rte-comment-0" })
.props.onChange({ html: "Edited!" });
testRenderer.root
.findByProps({ id: "comments-editCommentForm-form-comment-0" })
.props.onSubmit();
// Test optimistic response.
expect(testRenderer.toJSON()).toMatchSnapshot("optimistic response");
// Wait for loading.
await timeout();
// Test after server response.
expect(testRenderer.toJSON()).toMatchSnapshot("server response");
});
it("cancel edit", async () => {
timekeeper.freeze(assets[0].comments.edges[0].node.createdAt);
const testRenderer = createTestRenderer();
await timeout();
// Open edit form.
testRenderer.root
.findByProps({ id: "comments-commentContainer-editButton-comment-0" })
.props.onClick();
// Cacnel edit form.
testRenderer.root
.findByProps({ id: "comments-editCommentForm-cancelButton-comment-0" })
.props.onClick();
expect(testRenderer.toJSON()).toMatchSnapshot("edit canceled");
});
it("shows expiry message", async () => {
timekeeper.freeze(assets[0].comments.edges[0].node.createdAt);
const testRenderer = createTestRenderer();
await timeout();
jest.useFakeTimers();
// Open edit form.
testRenderer.root
.findByProps({ id: "comments-commentContainer-editButton-comment-0" })
.props.onClick();
timekeeper.reset();
jest.runOnlyPendingTimers();
// Show edit time expired.
expect(testRenderer.toJSON()).toMatchSnapshot("edit time expired");
// Close edit form.
testRenderer.root
.findByProps({ id: "comments-editCommentForm-closeButton-comment-0" })
.props.onClick();
expect(testRenderer.toJSON()).toMatchSnapshot("edit form closed");
});
+16
View File
@@ -20,6 +20,10 @@ export const comments = [
body: "Joining Too",
createdAt: "2018-07-06T18:24:00.000Z",
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
editing: {
edited: false,
editableUntil: "2018-07-06T18:24:30.000Z",
},
},
{
id: "comment-1",
@@ -27,6 +31,10 @@ export const comments = [
body: "What's up?",
createdAt: "2018-07-06T18:20:00.000Z",
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
editing: {
edited: false,
editableUntil: "2018-07-06T18:20:30.000Z",
},
},
{
id: "comment-2",
@@ -34,6 +42,10 @@ export const comments = [
body: "Hey!",
createdAt: "2018-07-06T18:14:00.000Z",
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
editing: {
edited: false,
editableUntil: "2018-07-06T18:14:30.000Z",
},
},
];
@@ -68,6 +80,10 @@ export const commentWithReplies = {
hasNextPage: false,
},
},
editing: {
edited: false,
editableUntil: "2018-07-06T18:24:30.000Z",
},
};
export const assetWithReplies = {
@@ -35,6 +35,10 @@ beforeEach(() => {
author: users[0],
body: "<strong>Hello world! (from server)</strong>",
createdAt: "2018-07-06T18:24:00.000Z",
editing: {
edited: false,
editableUntil: "2018-07-06T18:24:30.000Z",
},
},
},
clientMutationId: "0",
@@ -39,6 +39,10 @@ beforeEach(() => {
edges: [],
pageInfo: { endCursor: null, hasNextPage: false },
},
editing: {
edited: false,
editableUntil: "2018-07-06T18:24:30.000Z",
},
},
},
clientMutationId: "0",
@@ -18,7 +18,7 @@ exports[`works with multiple form components 1`] = `
Username
</label>
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
@@ -11,7 +11,7 @@ const InputDescription: StatelessComponent<InputDescriptionProps> = props => {
const { className, children, ...rest } = props;
return (
<Typography
variant="inputDescription"
variant="detail"
color="textSecondary"
className={className}
{...rest}
@@ -2,7 +2,7 @@
exports[`renders correctly 1`] = `
<p
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
className="Typography-root Typography-detail Typography-colorTextSecondary"
>
Form Components should go here
</p>
@@ -1,4 +1,6 @@
.root {
align-self: flex-start;
margin-top: 1px;
&:first-child {
margin-right: calc(0.5 * var(--spacing-unit));
}
@@ -1 +1,2 @@
export { default } from "./Message";
export { default, default as Message } from "./Message";
export { default as MessageIcon } from "./MessageIcon";
@@ -1,4 +1,2 @@
.root {
composes: bodyCopy from "talk-ui/shared/typography.css";
background-color: transparent;
}
@@ -40,8 +40,8 @@
composes: inputLabel from "talk-ui/shared/typography.css";
}
.inputDescription {
composes: inputDescription from "talk-ui/shared/typography.css";
.detail {
composes: detail from "talk-ui/shared/typography.css";
}
.timestamp {
@@ -15,7 +15,7 @@ type Variant =
| "bodyCopy"
| "bodyCopyBold"
| "inputLabel"
| "inputDescription"
| "detail"
| "timestamp";
// Based on Typography Component of Material UI.
@@ -146,7 +146,7 @@ Typography.defaultProps = {
bodyCopyBold: "p",
timestamp: "span",
inputLabel: "label",
inputDescription: "p",
detail: "p",
},
noWrap: false,
paragraph: false,
+1
View File
@@ -22,3 +22,4 @@ export { default as Icon } from "./Icon";
export { default as AriaInfo } from "./AriaInfo";
export { default as Message } from "./Message";
export { Tab, TabBar, TabContent, TabPane } from "./Tabs";
export { default as Message, MessageIcon } from "./Message";
+1 -1
View File
@@ -155,7 +155,7 @@
color: var(--palette-text-primary);
}
.inputDescription {
.detail {
font-size: calc(14rem / var(--rem-base));
font-weight: var(--font-weight-regular);
font-family: var(--font-family-sans-serif);
+1
View File
@@ -2,3 +2,4 @@ export { default as timeout } from "./timeout";
export { default as animationFrame } from "./animationFrame";
export { default as pascalCase } from "./pascalCase";
export { default as oncePerFrame } from "./oncePerFrame";
export { default as isBeforeDate } from "./isBeforeDate";
@@ -0,0 +1,9 @@
import timekeeper from "timekeeper";
import isBeforeDate from "./isBeforeDate";
it("works correctly", () => {
timekeeper.freeze(new Date("2018-07-06T18:24:00.000Z"));
expect(isBeforeDate(new Date("2018-07-06T18:24:30.000Z"))).toBe(true);
expect(isBeforeDate(new Date("2018-07-06T18:23:30.000Z"))).toBe(false);
timekeeper.reset();
});
+3
View File
@@ -0,0 +1,3 @@
export default function isBeforeDate(date: string | number | Date) {
return new Date() < new Date(date);
}
@@ -26,7 +26,6 @@ export default (ctx: TenantContext) => ({
ctx.user!,
{
id: input.commentID,
asset_id: input.assetID,
body: input.body,
},
ctx.req
@@ -875,11 +875,6 @@ type CreateCommentPayload {
EditCommentInput provides the input for the editComment Mutation.
"""
input EditCommentInput {
"""
assetID is the ID of the Asset where we are editing a comment on.
"""
assetID: ID!
"""
commentID is the ID of the comment being edited.
"""
+16 -2
View File
@@ -2,6 +2,7 @@ import { Db } from "mongodb";
import uuid from "uuid";
import { Omit, Sub } from "talk-common/types";
import { dotize } from "talk-common/utils/dotize";
import {
GQLCOMMENT_SORT,
GQLCOMMENT_STATUS,
@@ -103,7 +104,7 @@ export async function createComment(
export type EditCommentInput = Pick<
Comment,
"id" | "author_id" | "body" | "status"
"id" | "author_id" | "body" | "status" | "metadata"
> & {
/**
* lastEditableCommentCreatedAt is the date that the last comment would have
@@ -125,7 +126,16 @@ export async function editComment(
];
const createdAt = new Date();
const { id, body, lastEditableCommentCreatedAt, status, author_id } = input;
const {
id,
body,
lastEditableCommentCreatedAt,
status,
author_id,
metadata,
} = input;
// TODO: (wyattjoh) consider resetting the action counts if we're starting fresh with a new comment
const result = await collection(db).findOneAndUpdate(
{
@@ -144,6 +154,10 @@ export async function editComment(
$set: {
body,
status,
// Embed all the metadata properties, this may override the existing
// metadata, but we won't replace metadata that has been recalculated.
// TODO: (wyattjoh) consider if we want to replace the metadata for edited comments instead of supplementing it
...dotize({ metadata }),
},
$push: {
body_history: {
+12 -9
View File
@@ -74,12 +74,7 @@ export async function create(
export type EditComment = Omit<
EditCommentInput,
"status" | "author_id" | "lastEditableCommentCreatedAt"
> & {
/**
* asset_id is the asset that the comment exists on.
*/
asset_id: string;
};
>;
export async function edit(
mongo: Db,
@@ -88,15 +83,22 @@ export async function edit(
input: EditComment,
req?: Request
) {
// Get the comment that we're editing.
let comment = await retrieveComment(mongo, tenant.id, input.id);
if (!comment) {
// TODO: replace to match error returned by the models/comments.ts
throw new Error("comment not found");
}
// Grab the asset that we'll use to check moderation pieces with.
const asset = await retrieveAsset(mongo, tenant.id, input.asset_id);
const asset = await retrieveAsset(mongo, tenant.id, comment.asset_id);
if (!asset) {
// TODO: (wyattjoh) return better error.
throw new Error("asset referenced does not exist");
}
// Run the comment through the moderation phases.
const { status } = await processForModeration({
const { status, metadata } = await processForModeration({
asset,
tenant,
comment: input,
@@ -106,11 +108,12 @@ export async function edit(
// TODO: (wyattjoh) use the actions somehow.
const comment = await editComment(mongo, tenant.id, {
comment = await editComment(mongo, tenant.id, {
id: input.id,
author_id: author.id,
body: input.body,
status,
metadata,
// The editable time is based on the current time, and the edit window
// length. By subtracting the current date from the edit window length, we
// get the maximum value for the `created_at` time that would be permitted
+1 -1
View File
@@ -6,10 +6,10 @@
framework-validation-required = Dies ist ein Pflichtpfeld.
framework-timeago-just-now = Gerade eben
framework-timeago =
{ $suffix ->
[ago] vor
[in] in
}
{ $value }
{ $unit ->
+5 -8
View File
@@ -13,6 +13,8 @@ framework-validation-invalidEmail = Please enter a valid email address.
framework-validation-passwordTooShort = Password must contain at least {$minLength} characters.
framework-validation-passwordsDoNotMatch = Passwords do not match. Try again.
framework-timeago-just-now = Just now
framework-timeago-time =
{ $value }
{ $unit ->
@@ -48,12 +50,7 @@ framework-timeago-time =
}
framework-timeago =
{ $value ->
[0] now
*[other]
{ $suffix ->
[ago] {framework-timeago-time} ago
[in] in {framework-timeago-time}
*[other] unknown suffix
}
{ $suffix ->
[ago] {framework-timeago-time} ago
[noSuffix] {framework-timeago-time}
}
+13 -1
View File
@@ -53,4 +53,16 @@ comments-replyCommentForm-submit = Submit
comments-replyCommentForm-cancel = Cancel
comments-replyCommentForm-rteLabel = Write a reply
comments-replyCommentForm-rte =
.placeholder = { comments-postCommentForm-rteLabel }
.placeholder = { comments-replyCommentForm-rteLabel }
comments-commentContainer-editButton = Edit
comments-editCommentForm-saveChanges = Save Changes
comments-editCommentForm-cancel = Cancel
comments-editCommentForm-close = Close
comments-editCommentForm-rteLabel = Edit comment
comments-editCommentForm-rte =
.placeholder = { comments-editCommentForm-rteLabel }
comments-editCommentForm-editRemainingTime = Edit: <time></time> remaining
comments-editCommentForm-editTimeExpired = Edit time has expired. You can no longer edit this comment. Why not post another one?
comments-editedMarker-edited = Edited
+1 -3
View File
@@ -2,14 +2,12 @@
### All keys must start with `framework` because this file is shared
### among different targets.
framework-timeago-just-now = Hace poco
framework-timeago =
{ $value ->
[0] ahora
*[other]
{ $suffix ->
[ago] hace
[in] en
*[other] unknown suffix
}
{ $value }
{ $unit ->
+1
View File
@@ -36,6 +36,7 @@ declare module "react-timeago" {
live?: boolean;
className: string;
formatter?: Formatter;
minPeriod?: number;
}
const TimeAgo: React.ComponentType<TimeAgoProps>;