From a36d944e4ad52b797fce415848ff5426780db084 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 11 Sep 2018 00:15:27 +0200 Subject: [PATCH 01/16] Implement edit --- .../framework/lib/bootstrap/createContext.tsx | 11 +- .../stream/components/Comment/Comment.css | 3 - .../stream/components/Comment/Comment.tsx | 23 ++- .../{TopBar.spec.tsx => TopBarLeft.spec.tsx} | 10 +- .../Comment/{TopBar.tsx => TopBarLeft.tsx} | 6 +- .../client/stream/components/Comment/index.ts | 3 + .../stream/components/EditCommentForm.tsx | 156 ++++++++++++++++++ .../stream/containers/CommentContainer.tsx | 76 ++++++++- .../containers/EditCommentFormContainer.tsx | 139 ++++++++++++++++ .../stream/mutations/CreateCommentMutation.ts | 3 + .../stream/mutations/EditCommentMutation.ts | 56 +++++++ src/core/client/stream/mutations/index.ts | 5 + .../components/RelativeTime/RelativeTime.css | 2 - src/core/common/utils/index.ts | 1 + src/core/common/utils/isBeforeDate.spec.ts | 0 src/core/common/utils/isBeforeDate.ts | 3 + src/locales/de/framework.ftl | 2 +- src/locales/en-US/framework.ftl | 13 +- src/locales/en-US/stream.ftl | 13 +- src/locales/es/framework.ftl | 4 +- src/types/react-timeago.d.ts | 1 + 21 files changed, 494 insertions(+), 36 deletions(-) rename src/core/client/stream/components/Comment/{TopBar.spec.tsx => TopBarLeft.spec.tsx} (81%) rename src/core/client/stream/components/Comment/{TopBar.tsx => TopBarLeft.tsx} (81%) create mode 100644 src/core/client/stream/components/EditCommentForm.tsx create mode 100644 src/core/client/stream/containers/EditCommentFormContainer.tsx create mode 100644 src/core/client/stream/mutations/EditCommentMutation.ts create mode 100644 src/core/common/utils/isBeforeDate.spec.ts create mode 100644 src/core/common/utils/isBeforeDate.ts diff --git a/src/core/client/framework/lib/bootstrap/createContext.tsx b/src/core/client/framework/lib/bootstrap/createContext.tsx index 839cee453..d11b3b83c 100644 --- a/src/core/client/framework/lib/bootstrap/createContext.tsx +++ b/src/core/client/framework/lib/bootstrap/createContext.tsx @@ -47,7 +47,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 ( + + Just now + + ); + } + return ( | Array>; footer?: ReactElement | Array>; } const Comment: StatelessComponent = props => { return (
- - {props.author && - props.author.username && {props.author.username}} - {props.createdAt} - + + + {props.author && + props.author.username && ( + {props.author.username} + )} + {props.createdAt} + +
{props.topBarRight}
+
{props.body || ""} {props.footer} diff --git a/src/core/client/stream/components/Comment/TopBar.spec.tsx b/src/core/client/stream/components/Comment/TopBarLeft.spec.tsx similarity index 81% rename from src/core/client/stream/components/Comment/TopBar.spec.tsx rename to src/core/client/stream/components/Comment/TopBarLeft.spec.tsx index 5ee691f70..8769bb3dd 100644 --- a/src/core/client/stream/components/Comment/TopBar.spec.tsx +++ b/src/core/client/stream/components/Comment/TopBarLeft.spec.tsx @@ -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 = { + const props: PropTypesOf = { children:
Hello World
, }; @@ -19,14 +19,14 @@ it("renders correctly on small screens", () => { const testRenderer = TestRenderer.create( - + ); expect(testRenderer.toJSON()).toMatchSnapshot(); }); it("renders correctly on big screens", () => { - const props: PropTypesOf = { + const props: PropTypesOf = { children:
Hello World
, }; @@ -38,7 +38,7 @@ it("renders correctly on big screens", () => { const testRenderer = TestRenderer.create( - + ); expect(testRenderer.toJSON()).toMatchSnapshot(); diff --git a/src/core/client/stream/components/Comment/TopBar.tsx b/src/core/client/stream/components/Comment/TopBarLeft.tsx similarity index 81% rename from src/core/client/stream/components/Comment/TopBar.tsx rename to src/core/client/stream/components/Comment/TopBarLeft.tsx index eed8aea32..5f3862020 100644 --- a/src/core/client/stream/components/Comment/TopBar.tsx +++ b/src/core/client/stream/components/Comment/TopBarLeft.tsx @@ -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 = props => { +const TopBarLeft: StatelessComponent = props => { const rootClassName = cn(props.className); return ( @@ -27,4 +27,4 @@ const TopBar: StatelessComponent = props => { ); }; -export default TopBar; +export default TopBarLeft; diff --git a/src/core/client/stream/components/Comment/index.ts b/src/core/client/stream/components/Comment/index.ts index abb1d79ae..56c2da651 100644 --- a/src/core/client/stream/components/Comment/index.ts +++ b/src/core/client/stream/components/Comment/index.ts @@ -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"; diff --git a/src/core/client/stream/components/EditCommentForm.tsx b/src/core/client/stream/components/EditCommentForm.tsx new file mode 100644 index 000000000..84c753b1b --- /dev/null +++ b/src/core/client/stream/components/EditCommentForm.tsx @@ -0,0 +1,156 @@ +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, + 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; + onCancel?: EventHandler>; + onClose?: EventHandler>; + initialValues?: FormProps; + rteRef?: Ref; + expired?: boolean; +} + +const EditCommentForm: StatelessComponent = props => { + const inputID = `comments-editCommentForm-rte-${props.id}`; + return ( +
+ {({ handleSubmit, submitting, hasValidationErrors, pristine }) => ( + + +
+ + {props.author && + props.author.username && ( + {props.author.username} + )} + {props.createdAt} + +
+ + {({ input, meta }) => ( +
+ + + Edit comment + + + + input.onChange(html)} + value={input.value} + placeholder="Edit comment" + forwardRef={props.rteRef} + disabled={submitting || props.expired} + /> + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} +
+ )} +
+ {props.expired ? ( + + + Edit time has expired. You can no longer edit this comment. + Why not post another one? + + + ) : ( + + } + > + {"Edit: remaining"} + + + )} + + {props.expired ? ( + + + + ) : ( + <> + + + + + + + + )} + +
+
+ )} + + ); +}; + +export default EditCommentForm; diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index 21b4b767e..c3368b9d0 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -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,28 @@ interface InnerProps { interface State { showReplyDialog: boolean; + showEditDialog: boolean; + editable: boolean; } export class CommentContainer extends Component { + private uneditableTimer: any; + public state = { showReplyDialog: false, + showEditDialog: false, + editable: isBeforeDate(this.props.comment.editing.editableUntil), }; + constructor(props: InnerProps) { + super(props); + this.uneditableTimer = this.updateWhenNotEditable(); + } + + public componentWillUnmount() { + clearTimeout(this.uneditableTimer); + } + private openReplyDialog = () => { if (this.props.me) { this.setState(state => ({ @@ -43,20 +62,68 @@ export class CommentContainer extends Component { } }; + 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 { showReplyDialog, showEditDialog, editable } = this.state; + if (showEditDialog) { + return ( + + ); + } return ( <> + + + )) || + undefined + } footer={ <> void; + asset: AssetData; + autofocus: boolean; +} + +interface State { + initialValues?: EditCommentFormProps["initialValues"]; + initialized: boolean; + expired: boolean; +} + +export class EditCommentFormContainer extends Component { + 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({ + assetID: this.props.asset.id, + 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 ( + + ); + } +} +const enhanced = withContext(({ sessionStorage, browserInfo }) => ({ + // Disable autofocus on ios and enable for the rest. + autofocus: !browserInfo.ios, +}))( + withEditCommentMutation( + withFragmentContainer({ + asset: graphql` + fragment EditCommentFormContainer_asset on Asset { + id + } + `, + comment: graphql` + fragment EditCommentFormContainer_comment on Comment { + id + body + createdAt + author { + username + } + editing { + editableUntil + } + } + `, + })(EditCommentFormContainer) + ) +); +export type PostCommentFormContainerProps = PropTypesOf; +export default enhanced; diff --git a/src/core/client/stream/mutations/CreateCommentMutation.ts b/src/core/client/stream/mutations/CreateCommentMutation.ts index a293a58e7..958ad9acc 100644 --- a/src/core/client/stream/mutations/CreateCommentMutation.ts +++ b/src/core/client/stream/mutations/CreateCommentMutation.ts @@ -92,6 +92,9 @@ function commit( username: me.username, }, body: input.body, + editing: { + editableUntil: new Date(Date.now() + 10000), + }, }, }, clientMutationId: (clientMutationId++).toString(), diff --git a/src/core/client/stream/mutations/EditCommentMutation.ts b/src/core/client/stream/mutations/EditCommentMutation.ts new file mode 100644 index 000000000..a3d456ed2 --- /dev/null +++ b/src/core/client/stream/mutations/EditCommentMutation.ts @@ -0,0 +1,56 @@ +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 + } + clientMutationId + } + } +`; + +let clientMutationId = 0; + +function commit(environment: Environment, input: EditCommentInput) { + return commitMutationPromiseNormalized(environment, { + mutation, + variables: { + input: { + ...input, + clientMutationId: clientMutationId.toString(), + }, + }, + optimisticResponse: { + editComment: { + id: input.commentID, + body: input.body, + 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; diff --git a/src/core/client/stream/mutations/index.ts b/src/core/client/stream/mutations/index.ts index 324fddbdc..6c920dfea 100644 --- a/src/core/client/stream/mutations/index.ts +++ b/src/core/client/stream/mutations/index.ts @@ -3,6 +3,11 @@ export { CreateCommentMutation, CreateCommentInput, } from "./CreateCommentMutation"; +export { + withEditCommentMutation, + EditCommentMutation, + EditCommentInput, +} from "./EditCommentMutation"; export { withSetNetworkStatusMutation, SetNetworkStatusMutation, diff --git a/src/core/client/ui/components/RelativeTime/RelativeTime.css b/src/core/client/ui/components/RelativeTime/RelativeTime.css index e0450679f..c3a2af639 100644 --- a/src/core/client/ui/components/RelativeTime/RelativeTime.css +++ b/src/core/client/ui/components/RelativeTime/RelativeTime.css @@ -1,4 +1,2 @@ .root { - composes: bodyCopy from "talk-ui/shared/typography.css"; - background-color: transparent; } diff --git a/src/core/common/utils/index.ts b/src/core/common/utils/index.ts index 28435047e..4d6df9fc5 100644 --- a/src/core/common/utils/index.ts +++ b/src/core/common/utils/index.ts @@ -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"; diff --git a/src/core/common/utils/isBeforeDate.spec.ts b/src/core/common/utils/isBeforeDate.spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/common/utils/isBeforeDate.ts b/src/core/common/utils/isBeforeDate.ts new file mode 100644 index 000000000..24d2a33e9 --- /dev/null +++ b/src/core/common/utils/isBeforeDate.ts @@ -0,0 +1,3 @@ +export default function isBeforeDate(date: string | number | Date) { + return new Date() < new Date(date); +} diff --git a/src/locales/de/framework.ftl b/src/locales/de/framework.ftl index 55dca1c8c..7ea668be3 100644 --- a/src/locales/de/framework.ftl +++ b/src/locales/de/framework.ftl @@ -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 -> diff --git a/src/locales/en-US/framework.ftl b/src/locales/en-US/framework.ftl index f03b2a50a..89eee969b 100644 --- a/src/locales/en-US/framework.ftl +++ b/src/locales/en-US/framework.ftl @@ -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} } diff --git a/src/locales/en-US/stream.ftl b/src/locales/en-US/stream.ftl index 29aac39c9..683ea792e 100644 --- a/src/locales/en-US/stream.ftl +++ b/src/locales/en-US/stream.ftl @@ -53,4 +53,15 @@ 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: remaining +comments-editCommentForm-editTimeExpired = Edit time has expired. You can no longer edit this comment. Why not post another one? diff --git a/src/locales/es/framework.ftl b/src/locales/es/framework.ftl index a383c75bb..86b5e6cb4 100644 --- a/src/locales/es/framework.ftl +++ b/src/locales/es/framework.ftl @@ -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 -> diff --git a/src/types/react-timeago.d.ts b/src/types/react-timeago.d.ts index 431bbf88e..02161745c 100644 --- a/src/types/react-timeago.d.ts +++ b/src/types/react-timeago.d.ts @@ -36,6 +36,7 @@ declare module "react-timeago" { live?: boolean; className: string; formatter?: Formatter; + minPeriod?: number; } const TimeAgo: React.ComponentType; From 4e63858c66293ebf7ad2213eed750defe09456ee Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 11 Sep 2018 17:25:40 +0200 Subject: [PATCH 02/16] Fix lint and test --- .../components/Comment/Comment.spec.tsx | 1 - .../stream/components/Comment/Comment.tsx | 2 +- .../Comment/IndentedComment.spec.tsx | 1 - .../__snapshots__/Comment.spec.tsx.snap | 20 +- ...spec.tsx.snap => TopBarLeft.spec.tsx.snap} | 0 .../containers/CommentContainer.spec.tsx | 6 + .../stream/containers/CommentContainer.tsx | 8 +- .../CommentContainer.spec.tsx.snap | 6 - .../test/__snapshots__/loadMore.spec.tsx.snap | 140 ++++---- .../__snapshots__/permalinkView.spec.tsx.snap | 56 ++-- ...permalinkViewCommentNotFound.spec.tsx.snap | 28 +- .../__snapshots__/postComment.spec.tsx.snap | 239 ++++++++------ .../__snapshots__/postReply.spec.tsx.snap | 301 +++++++++++------- .../__snapshots__/renderReplies.spec.tsx.snap | 112 ++++--- .../__snapshots__/renderStream.spec.tsx.snap | 56 ++-- .../showAllReplies.spec.tsx.snap | 140 ++++---- src/core/client/stream/test/fixtures.ts | 12 + .../client/stream/test/postComment.spec.tsx | 3 + .../client/stream/test/postReply.spec.tsx | 3 + 19 files changed, 667 insertions(+), 467 deletions(-) rename src/core/client/stream/components/Comment/__snapshots__/{TopBar.spec.tsx.snap => TopBarLeft.spec.tsx.snap} (100%) diff --git a/src/core/client/stream/components/Comment/Comment.spec.tsx b/src/core/client/stream/components/Comment/Comment.spec.tsx index 8b409adeb..cae068012 100644 --- a/src/core/client/stream/components/Comment/Comment.spec.tsx +++ b/src/core/client/stream/components/Comment/Comment.spec.tsx @@ -7,7 +7,6 @@ import Comment from "./Comment"; it("renders username and body", () => { const props: PropTypesOf = { - id: "comment-id", author: { username: "Marvin", }, diff --git a/src/core/client/stream/components/Comment/Comment.tsx b/src/core/client/stream/components/Comment/Comment.tsx index 37c6bb2ad..02dd50bfd 100644 --- a/src/core/client/stream/components/Comment/Comment.tsx +++ b/src/core/client/stream/components/Comment/Comment.tsx @@ -34,7 +34,7 @@ const Comment: StatelessComponent = props => { )} {props.createdAt} -
{props.topBarRight}
+ {props.topBarRight &&
{props.topBarRight}
}
{props.body || ""} diff --git a/src/core/client/stream/components/Comment/IndentedComment.spec.tsx b/src/core/client/stream/components/Comment/IndentedComment.spec.tsx index c86a66ef2..be489a804 100644 --- a/src/core/client/stream/components/Comment/IndentedComment.spec.tsx +++ b/src/core/client/stream/components/Comment/IndentedComment.spec.tsx @@ -8,7 +8,6 @@ import IndentedComment from "./IndentedComment"; it("renders correctly", () => { const props: PropTypesOf = { indentLevel: 1, - id: "comment-id", author: { username: "Marvin", }, diff --git a/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap index 246444f0d..cf9aa58ab 100644 --- a/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap +++ b/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap @@ -5,16 +5,20 @@ exports[`renders username and body 1`] = ` className="Comment-root" role="article" > - - - Marvin - - - 1995-12-17T03:24:00.000Z - - + + + Marvin + + + 1995-12-17T03:24:00.000Z + + + Woof diff --git a/src/core/client/stream/components/Comment/__snapshots__/TopBar.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/TopBarLeft.spec.tsx.snap similarity index 100% rename from src/core/client/stream/components/Comment/__snapshots__/TopBar.spec.tsx.snap rename to src/core/client/stream/components/Comment/__snapshots__/TopBarLeft.spec.tsx.snap diff --git a/src/core/client/stream/containers/CommentContainer.spec.tsx b/src/core/client/stream/containers/CommentContainer.spec.tsx index d43c241af..91f2acafb 100644 --- a/src/core/client/stream/containers/CommentContainer.spec.tsx +++ b/src/core/client/stream/containers/CommentContainer.spec.tsx @@ -23,6 +23,9 @@ it("renders username and body", () => { }, body: "Woof", createdAt: "1995-12-17T03:24:00.000Z", + editing: { + editableUntil: "1995-12-17T03:24:30.000Z", + }, }, indentLevel: 1, showAuthPopup: noop as any, @@ -45,6 +48,9 @@ it("renders body only", () => { }, body: "Woof", createdAt: "1995-12-17T03:24:00.000Z", + editing: { + editableUntil: "1995-12-17T03:24:30.000Z", + }, }, indentLevel: 1, showAuthPopup: noop as any, diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index c3368b9d0..9d6ae37f6 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -94,7 +94,7 @@ export class CommentContainer extends Component { } public render() { - const { comment, asset, ...rest } = this.props; + const { comment, asset, indentLevel } = this.props; const { showReplyDialog, showEditDialog, editable } = this.state; if (showEditDialog) { return ( @@ -108,8 +108,10 @@ export class CommentContainer extends Component { return ( <> diff --git a/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap index 4883c80e1..9ad26125f 100644 --- a/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap +++ b/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap @@ -22,10 +22,7 @@ exports[`renders body only 1`] = ` /> } - id="comment-id" indentLevel={1} - me={null} - showAuthPopup={[Function]} /> `; @@ -52,10 +49,7 @@ exports[`renders username and body 1`] = ` /> } - id="comment-id" indentLevel={1} - me={null} - showAuthPopup={[Function]} /> `; diff --git a/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap b/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap index 2b6612877..27964d7c7 100644 --- a/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap +++ b/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap @@ -153,20 +153,24 @@ exports[`loads more comments 1`] = ` role="article" >
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Isabelle - - + + Isabelle + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
+
+ +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
+
+ +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Markus - - + + Markus + + +
- - Lukas - - + + Lukas + + +
- - Isabelle - - + + Isabelle + + +
{ author: users[0], body: "Hello world! (from server)", createdAt: "2018-07-06T18:24:00.000Z", + editing: { + editableUntil: "2018-07-06T18:24:30.000Z", + }, }, }, clientMutationId: "0", diff --git a/src/core/client/stream/test/postReply.spec.tsx b/src/core/client/stream/test/postReply.spec.tsx index 3c64bc098..27a91b267 100644 --- a/src/core/client/stream/test/postReply.spec.tsx +++ b/src/core/client/stream/test/postReply.spec.tsx @@ -45,6 +45,9 @@ beforeEach(() => { edges: [], pageInfo: { endCursor: null, hasNextPage: false }, }, + editing: { + editableUntil: "2018-07-06T18:24:30.000Z", + }, }, }, clientMutationId: "0", From 170fb47daea9f4556b561b50c862e51fafc1fef0 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 11 Sep 2018 17:32:46 +0200 Subject: [PATCH 03/16] More unit tests --- .../client/stream/components/Comment/Comment.spec.tsx | 2 ++ src/core/client/stream/components/Comment/Comment.tsx | 4 ++-- .../Comment/__snapshots__/Comment.spec.tsx.snap | 7 ++++++- .../Comment/__snapshots__/IndentedComment.spec.tsx.snap | 1 - src/core/common/utils/isBeforeDate.spec.ts | 9 +++++++++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/client/stream/components/Comment/Comment.spec.tsx b/src/core/client/stream/components/Comment/Comment.spec.tsx index cae068012..f8d14f6eb 100644 --- a/src/core/client/stream/components/Comment/Comment.spec.tsx +++ b/src/core/client/stream/components/Comment/Comment.spec.tsx @@ -12,6 +12,8 @@ it("renders username and body", () => { }, body: "Woof", createdAt: "1995-12-17T03:24:00.000Z", + topBarRight: "topBarRight", + footer: "footer", }; const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); diff --git a/src/core/client/stream/components/Comment/Comment.tsx b/src/core/client/stream/components/Comment/Comment.tsx index 02dd50bfd..9a03094cc 100644 --- a/src/core/client/stream/components/Comment/Comment.tsx +++ b/src/core/client/stream/components/Comment/Comment.tsx @@ -15,8 +15,8 @@ export interface CommentProps { } | null; body: string | null; createdAt: string; - topBarRight?: ReactElement | Array>; - footer?: ReactElement | Array>; + topBarRight?: React.ReactNode; + footer?: React.ReactNode; } const Comment: StatelessComponent = props => { diff --git a/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap index cf9aa58ab..7d13e23ea 100644 --- a/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap +++ b/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap @@ -18,6 +18,9 @@ exports[`renders username and body 1`] = ` 1995-12-17T03:24:00.000Z +
+ topBarRight +
Woof @@ -26,6 +29,8 @@ exports[`renders username and body 1`] = ` className="Comment-footer" direction="row" itemGutter="half" - /> + > + footer +
`; diff --git a/src/core/client/stream/components/Comment/__snapshots__/IndentedComment.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/IndentedComment.spec.tsx.snap index ae2d56dee..d264e4050 100644 --- a/src/core/client/stream/components/Comment/__snapshots__/IndentedComment.spec.tsx.snap +++ b/src/core/client/stream/components/Comment/__snapshots__/IndentedComment.spec.tsx.snap @@ -12,7 +12,6 @@ exports[`renders correctly 1`] = ` } body="Woof" createdAt="1995-12-17T03:24:00.000Z" - id="comment-id" /> `; diff --git a/src/core/common/utils/isBeforeDate.spec.ts b/src/core/common/utils/isBeforeDate.spec.ts index e69de29bb..4359ca55a 100644 --- a/src/core/common/utils/isBeforeDate.spec.ts +++ b/src/core/common/utils/isBeforeDate.spec.ts @@ -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(); +}); From 7b221c40a0f91016f22e1261861094addae51e4d Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 11 Sep 2018 18:03:54 +0200 Subject: [PATCH 04/16] Add integration test --- .../stream/components/Comment/Comment.tsx | 2 +- .../stream/containers/CommentContainer.tsx | 1 + .../__snapshots__/editComment.spec.tsx.snap | 1459 +++++++++++++++++ .../client/stream/test/editComment.spec.tsx | 90 + 4 files changed, 1551 insertions(+), 1 deletion(-) create mode 100644 src/core/client/stream/test/__snapshots__/editComment.spec.tsx.snap create mode 100644 src/core/client/stream/test/editComment.spec.tsx diff --git a/src/core/client/stream/components/Comment/Comment.tsx b/src/core/client/stream/components/Comment/Comment.tsx index 9a03094cc..68fa6dab4 100644 --- a/src/core/client/stream/components/Comment/Comment.tsx +++ b/src/core/client/stream/components/Comment/Comment.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement, StatelessComponent } from "react"; +import React, { StatelessComponent } from "react"; import { Flex } from "talk-ui/components"; diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index 9d6ae37f6..df61c3f9e 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -116,6 +116,7 @@ export class CommentContainer extends Component { (editable && ( + + + +
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+
+ + Markus + + +
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+ + + Edit: + + remaining + +
+
+ + +
+
+ +
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; + +exports[`edit a comment: optimistic response 1`] = ` +
+
+
+
+
+
+ Signed in as + + Markus + + . +
+
+ + Not you?  + + +
+
+
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+
+ + Markus + + +
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+ + + Edit: + + remaining + +
+
+ + +
+
+ +
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; + +exports[`edit a comment: render stream 1`] = ` +
+
+
+
+
+
+ Signed in as + + Markus + + . +
+
+ + Not you?  + + +
+
+
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+ + Markus + + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; + +exports[`edit a comment: server response 1`] = ` +
+
+
+
+
+
+ Signed in as + + Markus + + . +
+
+ + Not you?  + + +
+
+
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+ + Markus + + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; diff --git a/src/core/client/stream/test/editComment.spec.tsx b/src/core/client/stream/test/editComment.spec.tsx new file mode 100644 index 000000000..b1d0a67e8 --- /dev/null +++ b/src/core/client/stream/test/editComment.spec.tsx @@ -0,0 +1,90 @@ +import { ReactTestRenderer } from "react-test-renderer"; +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"; + +let testRenderer: ReactTestRenderer; +beforeEach(() => { + 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, { clientAuthRevision: 0 }).returns(users[0]) + ), + }, + Mutation: { + editComment: createSinonStub( + s => s.throws(), + s => + s + .withArgs(undefined, { + input: { + assetID: assets[0].id, + 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)", + }, + clientMutationId: "0", + }) + ), + }, + }; + + timekeeper.freeze(assets[0].comments.edges[0].node.createdAt); + ({ testRenderer } = create({ + // Set this to true, to see graphql responses. + logNetwork: false, + resolvers, + initLocalState: localRecord => { + localRecord.setValue(assets[0].id, "assetID"); + }, + })); +}); + +afterAll(() => { + timekeeper.reset(); +}); + +it("edit a comment", async () => { + // 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"); +}); From 8a25e6826641009aaf9585c573cfaf9d887fdbf0 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 11 Sep 2018 21:16:22 +0200 Subject: [PATCH 05/16] Add integration tests --- .../stream/components/EditCommentForm.tsx | 2 + .../__snapshots__/editComment.spec.tsx.snap | 1028 +++++++++++++++++ .../__snapshots__/postComment.spec.tsx.snap | 1 + .../__snapshots__/postReply.spec.tsx.snap | 1 + .../client/stream/test/editComment.spec.tsx | 56 +- 5 files changed, 1082 insertions(+), 6 deletions(-) diff --git a/src/core/client/stream/components/EditCommentForm.tsx b/src/core/client/stream/components/EditCommentForm.tsx index 84c753b1b..454ffb41b 100644 --- a/src/core/client/stream/components/EditCommentForm.tsx +++ b/src/core/client/stream/components/EditCommentForm.tsx @@ -115,6 +115,7 @@ const EditCommentForm: StatelessComponent = props => { {props.expired ? ( +
+
+
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+ + Markus + + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; + exports[`edit a comment: edit form 1`] = `
`; + +exports[`shows expiry message: edit form closed 1`] = ` +
+
+
+
+
+
+ Signed in as + + Markus + + . +
+
+ + Not you?  + + +
+
+
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+ + Markus + + +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; + +exports[`shows expiry message: edit time expired 1`] = ` +
+
+
+
+
+
+ Signed in as + + Markus + + . +
+
+ + Not you?  + + +
+
+
+
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+
+ + Powered by + + ⁨The Coral Project⁩ + + +
+ +
+
+ +
+
+
+
+
+
+
+ + Markus + + +
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+ + Edit time has expired. You can no longer edit this comment. Why not post another one? +
+
+ +
+
+ +
+
+
+
+
+ + Lukas + + +
+
+
+
+ +
+
+
+
+
+
+`; diff --git a/src/core/client/stream/test/__snapshots__/postComment.spec.tsx.snap b/src/core/client/stream/test/__snapshots__/postComment.spec.tsx.snap index 15fe54400..0c0129082 100644 --- a/src/core/client/stream/test/__snapshots__/postComment.spec.tsx.snap +++ b/src/core/client/stream/test/__snapshots__/postComment.spec.tsx.snap @@ -207,6 +207,7 @@ exports[`post a comment: optimistic response 1`] = `
Powered by Lukas - + +
Powered by Lukas - + +
Powered by Markus - + +
Powered by Markus - + +
+ ( + + Edited + + ) +
+
Powered by Markus - + +
Powered by Lukas - + +
Markus - + +
Lukas - + +
Isabelle - + +
Markus - + +
Lukas - + +
Markus - + +
Markus - + +
Markus - + +
Powered by Markus - + +
Lukas - + +
Powered by Markus - + +
Markus - + +
Lukas - + +
Powered by Markus - + +
Lukas - + +
Powered by Markus - + +
Lukas - + +
Powered by Markus - + +
Markus - + +
Powered by Markus - + +
Markus - + +
Lukas - + +
Powered by Markus - + +
Lukas - + +
Markus - + +
Markus - + +
Markus - + +
Lukas - + +
Markus - + +
Lukas - + +
Markus - + +
Lukas - + +
Markus - + +
Lukas - + +
Isabelle - + +
{ body: "Hello world! (from server)", createdAt: "2018-07-06T18:24:00.000Z", editing: { + edited: false, editableUntil: "2018-07-06T18:24:30.000Z", }, }, diff --git a/src/core/client/stream/test/postReply.spec.tsx b/src/core/client/stream/test/postReply.spec.tsx index 27a91b267..e8d43bdc5 100644 --- a/src/core/client/stream/test/postReply.spec.tsx +++ b/src/core/client/stream/test/postReply.spec.tsx @@ -46,6 +46,7 @@ beforeEach(() => { pageInfo: { endCursor: null, hasNextPage: false }, }, editing: { + edited: false, editableUntil: "2018-07-06T18:24:30.000Z", }, }, diff --git a/src/core/client/ui/components/FormField/__snapshots__/FormField.spec.tsx.snap b/src/core/client/ui/components/FormField/__snapshots__/FormField.spec.tsx.snap index 874adc015..011020568 100644 --- a/src/core/client/ui/components/FormField/__snapshots__/FormField.spec.tsx.snap +++ b/src/core/client/ui/components/FormField/__snapshots__/FormField.spec.tsx.snap @@ -18,7 +18,7 @@ exports[`works with multiple form components 1`] = ` Username

A unique identifier displayed on your comments. You may use “_” and “.”

diff --git a/src/core/client/ui/components/InputDescription/InputDescription.tsx b/src/core/client/ui/components/InputDescription/InputDescription.tsx index d36d5fe7a..ae84ed141 100644 --- a/src/core/client/ui/components/InputDescription/InputDescription.tsx +++ b/src/core/client/ui/components/InputDescription/InputDescription.tsx @@ -11,7 +11,7 @@ const InputDescription: StatelessComponent = props => { const { className, children, ...rest } = props; return ( Form Components should go here

diff --git a/src/core/client/ui/components/Typography/Typography.css b/src/core/client/ui/components/Typography/Typography.css index a2bd115fe..be3e0954e 100644 --- a/src/core/client/ui/components/Typography/Typography.css +++ b/src/core/client/ui/components/Typography/Typography.css @@ -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 { diff --git a/src/core/client/ui/components/Typography/Typography.tsx b/src/core/client/ui/components/Typography/Typography.tsx index 2c4a20d94..b8f6d2396 100644 --- a/src/core/client/ui/components/Typography/Typography.tsx +++ b/src/core/client/ui/components/Typography/Typography.tsx @@ -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, diff --git a/src/core/client/ui/shared/typography.css b/src/core/client/ui/shared/typography.css index cb785f8fc..3012a3617 100644 --- a/src/core/client/ui/shared/typography.css +++ b/src/core/client/ui/shared/typography.css @@ -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); diff --git a/src/locales/en-US/stream.ftl b/src/locales/en-US/stream.ftl index 683ea792e..d939806a7 100644 --- a/src/locales/en-US/stream.ftl +++ b/src/locales/en-US/stream.ftl @@ -65,3 +65,4 @@ comments-editCommentForm-rte = .placeholder = { comments-editCommentForm-rteLabel } comments-editCommentForm-editRemainingTime = Edit: remaining comments-editCommentForm-editTimeExpired = Edit time has expired. You can no longer edit this comment. Why not post another one? +comments-editedMarker-edited = Edited From 2292e5d53f1ba6da890190e3e2cbfb5923a53989 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Wed, 12 Sep 2018 17:07:36 +0200 Subject: [PATCH 11/16] Fix integration test --- src/core/client/stream/test/editComment.spec.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/client/stream/test/editComment.spec.tsx b/src/core/client/stream/test/editComment.spec.tsx index d141201ea..de22f2384 100644 --- a/src/core/client/stream/test/editComment.spec.tsx +++ b/src/core/client/stream/test/editComment.spec.tsx @@ -25,7 +25,6 @@ function createTestRenderer() { s .withArgs(undefined, { input: { - assetID: assets[0].id, commentID: assets[0].comments.edges[0].node.id, body: "Edited!", clientMutationId: "0", From 32e56e805c60107e35752b2ee4a2adf2b053169f Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Wed, 12 Sep 2018 20:35:07 +0200 Subject: [PATCH 12/16] Adapt integration test --- src/core/client/stream/test/editComment.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/client/stream/test/editComment.spec.tsx b/src/core/client/stream/test/editComment.spec.tsx index de22f2384..a562c3b38 100644 --- a/src/core/client/stream/test/editComment.spec.tsx +++ b/src/core/client/stream/test/editComment.spec.tsx @@ -15,7 +15,7 @@ function createTestRenderer() { ), me: createSinonStub( s => s.throws(), - s => s.withArgs(undefined, { clientAuthRevision: 0 }).returns(users[0]) + s => s.withArgs(undefined).returns(users[0]) ), }, Mutation: { From c8cd68c6b7e2275e57a4de1f45a857fa54f2e8e3 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Wed, 12 Sep 2018 22:01:43 +0200 Subject: [PATCH 13/16] Use Message Component --- .../client/stream/components/EditCommentForm.tsx | 7 +++++-- .../test/__snapshots__/editComment.spec.tsx.snap | 16 ++++++++-------- .../client/ui/components/Message/MessageIcon.css | 2 ++ src/core/client/ui/components/Message/index.ts | 3 ++- src/core/client/ui/components/index.ts | 2 +- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/core/client/stream/components/EditCommentForm.tsx b/src/core/client/stream/components/EditCommentForm.tsx index 454ffb41b..d7d79ddd8 100644 --- a/src/core/client/stream/components/EditCommentForm.tsx +++ b/src/core/client/stream/components/EditCommentForm.tsx @@ -15,6 +15,8 @@ import { Button, Flex, HorizontalGutter, + Message, + MessageIcon, RelativeTime, Typography, ValidationMessage, @@ -102,14 +104,15 @@ const EditCommentForm: StatelessComponent = props => { ) : ( - + + alarm } > {"Edit: remaining"} - + )} {props.expired ? ( diff --git a/src/core/client/stream/test/__snapshots__/editComment.spec.tsx.snap b/src/core/client/stream/test/__snapshots__/editComment.spec.tsx.snap index ed29c75d0..6a91b49e0 100644 --- a/src/core/client/stream/test/__snapshots__/editComment.spec.tsx.snap +++ b/src/core/client/stream/test/__snapshots__/editComment.spec.tsx.snap @@ -629,13 +629,13 @@ exports[`edit a comment: edit form 1`] = `
Edit: @@ -1048,13 +1048,13 @@ exports[`edit a comment: optimistic response 1`] = `
Edit: @@ -2481,11 +2481,11 @@ exports[`shows expiry message: edit time expired 1`] = `
diff --git a/src/core/client/ui/components/Message/MessageIcon.css b/src/core/client/ui/components/Message/MessageIcon.css index df730b2de..0104b6cd1 100644 --- a/src/core/client/ui/components/Message/MessageIcon.css +++ b/src/core/client/ui/components/Message/MessageIcon.css @@ -1,4 +1,6 @@ .root { + align-self: flex-start; + margin-top: 1px; &:first-child { margin-right: calc(0.5 * var(--spacing-unit)); } diff --git a/src/core/client/ui/components/Message/index.ts b/src/core/client/ui/components/Message/index.ts index a6d22dd86..84f6b9009 100644 --- a/src/core/client/ui/components/Message/index.ts +++ b/src/core/client/ui/components/Message/index.ts @@ -1 +1,2 @@ -export { default } from "./Message"; +export { default, default as Message } from "./Message"; +export { default as MessageIcon } from "./MessageIcon"; diff --git a/src/core/client/ui/components/index.ts b/src/core/client/ui/components/index.ts index 61970ed25..a6d027393 100644 --- a/src/core/client/ui/components/index.ts +++ b/src/core/client/ui/components/index.ts @@ -20,4 +20,4 @@ export { default as Spinner } from "./Spinner"; export { default as HorizontalGutter } from "./HorizontalGutter"; export { default as Icon } from "./Icon"; export { default as AriaInfo } from "./AriaInfo"; -export { default as Message } from "./Message"; +export { default as Message, MessageIcon } from "./Message"; From 3955c960bf306a5038c14a59e50861980f5abc02 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 13 Sep 2018 16:42:04 +0200 Subject: [PATCH 14/16] Only show edit button for the author --- .../stream/containers/CommentContainer.tsx | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index 309c3d337..1cd09fd2e 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -40,18 +40,31 @@ export class CommentContainer extends Component { public state = { showReplyDialog: false, showEditDialog: false, - editable: isBeforeDate(this.props.comment.editing.editableUntil), + editable: this.isEditable(), }; constructor(props: InnerProps) { super(props); - this.uneditableTimer = this.updateWhenNotEditable(); + 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 => ({ @@ -155,7 +168,7 @@ const enhanced = withShowAuthPopupMutation( withFragmentContainer({ me: graphql` fragment CommentContainer_me on User { - __typename + id } `, asset: graphql` @@ -167,6 +180,7 @@ const enhanced = withShowAuthPopupMutation( fragment CommentContainer_comment on Comment { id author { + id username } body From ba2c2c32b2f4ac16a948bd6cfa80abe3b7274823 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 13 Sep 2018 18:20:55 +0200 Subject: [PATCH 15/16] Fix lint --- src/core/client/stream/containers/CommentContainer.spec.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/client/stream/containers/CommentContainer.spec.tsx b/src/core/client/stream/containers/CommentContainer.spec.tsx index 304ce4e9c..772a8df79 100644 --- a/src/core/client/stream/containers/CommentContainer.spec.tsx +++ b/src/core/client/stream/containers/CommentContainer.spec.tsx @@ -19,6 +19,7 @@ it("renders username and body", () => { comment: { id: "comment-id", author: { + id: "author-id", username: "Marvin", }, body: "Woof", @@ -46,6 +47,7 @@ it("renders body only", () => { comment: { id: "comment-id", author: { + id: "author-id", username: null, }, body: "Woof", From 72f5af9f3b59975cd34b28127618d5ad7f275b89 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 13 Sep 2018 18:29:05 +0200 Subject: [PATCH 16/16] Adapt snapshot --- .../containers/__snapshots__/CommentContainer.spec.tsx.snap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap index 835692858..f6e7f50ba 100644 --- a/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap +++ b/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap @@ -5,6 +5,7 @@ exports[`renders body only 1`] = `