From ac203607aee6e4dd7fc1ec60c1e84041fe60dfb7 Mon Sep 17 00:00:00 2001 From: Tessa Thornton Date: Fri, 6 Sep 2019 11:41:55 -0600 Subject: [PATCH] [CORL-561, CORL-562] Comment stream and account profile styling cleanup (#2517) * update styles for comment stream * more comment styling fixes * reconfigure settings tab and account settings in stream * add new button variant * style settings tab * style change username/email/password * clean up settings tab * integrate account deletion to account settings * update comment history styles * more history comment styles * update snaps * move userbox * fix tests * fix delete account tests * update message box styling * update snap * update snaps * fix lints * update snaps again * userbox styles * history comment styling * update snaps * fix ts * Integrate notifications settings * clean up account setting styles * update snaps and tests * fix lints * fix: PENDING_DELETION permissions * chore: sync stable classnames, rename settings to account * simplify css * update snaps --- .../__snapshots__/general.spec.tsx.snap | 12 +- src/core/client/stream/classes.ts | 44 +- .../stream/common/MessageBox/MessageBox.css | 4 +- .../common/MessageBox/MessageBoxIcon.css | 2 +- .../common/UserBox/UserBoxAuthenticated.css | 11 + .../common/UserBox/UserBoxAuthenticated.tsx | 24 +- .../UserBoxAuthenticated.spec.tsx.snap | 7 +- src/core/client/stream/local/local.graphql | 3 +- src/core/client/stream/shared/htmlContent.css | 1 + .../tabs/Comments/Comment/ButtonsBar.tsx | 2 +- .../stream/tabs/Comments/Comment/Comment.css | 1 + .../stream/tabs/Comments/Comment/Comment.tsx | 11 +- .../tabs/Comments/Comment/InReplyTo.css | 12 +- .../tabs/Comments/Comment/InReplyTo.tsx | 3 +- .../PermalinkButton/PermalinkButton.tsx | 7 +- .../PermalinkButton/PermalinkPopover.css | 2 +- .../Comment/ReactionButton/ReactionButton.css | 4 + .../Comment/ReactionButton/ReactionButton.tsx | 15 +- .../tabs/Comments/Comment/ReplyButton.css | 1 + .../tabs/Comments/Comment/ReplyButton.tsx | 7 +- .../Comment/ReportButton/ReportButton.css | 2 +- .../Comment/ReportButton/ReportButton.tsx | 16 +- .../Comments/Comment/Username/Username.tsx | 1 + .../__snapshots__/ButtonsBar.spec.tsx.snap | 1 + .../__snapshots__/Comment.spec.tsx.snap | 7 +- .../__snapshots__/ReplyButton.spec.tsx.snap | 3 +- .../AllCommentsTabContainer.css | 4 + .../AllCommentsTabContainer.tsx | 6 +- .../PostCommentForm/PostCommentForm.css | 4 + .../PostCommentForm/PostCommentForm.tsx | 5 + .../Profile/CommentHistory/CommentHistory.tsx | 7 +- .../Profile/CommentHistory/HistoryComment.css | 25 +- .../Profile/CommentHistory/HistoryComment.tsx | 51 +- .../HistoryCommentContainer.tsx | 10 + .../CommentHistory.spec.tsx.snap | 31 +- .../HistoryComment.spec.tsx.snap | 54 +- .../client/stream/tabs/Profile/Profile.tsx | 62 +- .../stream/tabs/Profile/ProfileContainer.tsx | 7 +- .../Settings/AccountSettingsContainer.css | 4 + .../Settings/AccountSettingsContainer.tsx | 73 ++ .../ChangeEmail/ChangeEmailContainer.css | 1 - .../ChangeEmail/ChangeEmailContainer.tsx | 41 +- .../ChangeEmail/UpdateEmailMutation.ts | 0 .../{ => Settings}/ChangeEmail/index.ts | 0 .../tabs/Profile/Settings/ChangePassword.css | 3 + .../tabs/Profile/Settings/ChangePassword.tsx | 271 ++++--- .../ChangeUsernameContainer.css | 5 - .../ChangeUsernameContainer.tsx | 50 +- .../ChangeUsername/UpdateUsernameMutation.tsx | 0 .../{ => Settings}/ChangeUsername/index.ts | 0 .../DeleteAccount/DeleteAccountContainer.css | 6 +- .../DeleteAccount/DeleteAccountContainer.tsx | 114 +-- .../DeleteAccount/Pages/CompletionPage.tsx | 16 +- .../DeleteAccount/Pages/ConfirmPage.tsx | 14 +- .../DeleteAccount/Pages/DescriptionPage.tsx | 14 +- .../Pages/DownloadCommentsPage.tsx | 10 +- .../Settings/DeleteAccount/Pages/WhenPage.tsx | 14 +- .../Settings/DownloadCommentsContainer.css | 6 +- .../Settings/DownloadCommentsContainer.tsx | 104 +-- .../Settings/IgnoreUserSettingsContainer.tsx | 105 ++- .../NotificationSettingsContainer.tsx | 277 +++---- .../Profile/Settings/SettingsContainer.css | 3 - .../Profile/Settings/SettingsContainer.tsx | 57 -- .../stream/tabs/Profile/Settings/index.ts | 5 +- .../renderFeaturedStream.spec.tsx.snap | 16 +- .../__snapshots__/permalinkView.spec.tsx.snap | 174 ++--- ...permalinkViewLoadMoreParents.spec.tsx.snap | 142 ++-- .../__snapshots__/editComment.spec.tsx.snap | 144 ++-- .../__snapshots__/loadMore.spec.tsx.snap | 74 +- .../__snapshots__/postComment.spec.tsx.snap | 34 +- .../postLocalReply.spec.tsx.snap | 282 +++---- .../__snapshots__/postReply.spec.tsx.snap | 70 +- .../__snapshots__/reaction.spec.tsx.snap | 12 +- .../renderCommunityGuidelines.spec.tsx.snap | 70 +- .../renderMessageBox.spec.tsx.snap | 20 +- .../__snapshots__/renderReplies.spec.tsx.snap | 144 ++-- .../__snapshots__/renderStream.spec.tsx.snap | 72 +- .../showAllReplies.spec.tsx.snap | 34 +- .../showConversation.spec.tsx.snap | 36 +- .../__snapshots__/sortStream.spec.tsx.snap | 70 +- .../renderConfigure.spec.tsx.snap | 10 +- .../__snapshots__/account.spec.tsx.snap | 467 +++++++++++ .../__snapshots__/myComments.spec.tsx.snap | 119 +-- .../__snapshots__/settings.spec.tsx.snap | 722 ------------------ .../{settings.spec.tsx => account.spec.tsx} | 120 +-- .../stream/test/profile/changeEmail.spec.tsx | 2 +- .../test/profile/changeUsername.spec.tsx | 2 +- .../test/profile/deleteAccount.spec.tsx | 55 +- .../profile/notificationSettings.spec.tsx | 143 ++++ .../client/ui/components/Button/Button.css | 43 +- .../client/ui/components/Button/Button.tsx | 6 +- .../client/ui/components/CallOut/CallOut.css | 4 + .../client/ui/components/CallOut/CallOut.tsx | 16 +- .../ui/components/Dropdown/Dropdown.tsx | 3 +- src/core/client/ui/components/Tag/Tag.css | 6 +- src/core/client/ui/components/Tag/Tag.tsx | 1 + .../Tag/__snapshots__/Tag.spec.tsx.snap | 2 +- .../ui/components/Typography/Typography.css | 12 +- .../ui/components/Typography/Typography.tsx | 2 + src/core/client/ui/hocs/withStyles.ts | 2 + src/core/client/ui/shared/typography.css | 26 +- src/core/client/ui/theme/mixins.css | 2 +- src/core/client/ui/theme/variables.ts | 1 + .../server/graph/tenant/schema/schema.graphql | 8 +- src/locales/da/stream.ftl | 41 +- src/locales/en-US/stream.ftl | 149 ++-- src/locales/es/stream.ftl | 17 +- src/locales/nl-NL/stream.ftl | 23 +- src/locales/pt-BR/stream.ftl | 11 +- 109 files changed, 2620 insertions(+), 2451 deletions(-) create mode 100644 src/core/client/stream/tabs/Comments/Comment/ReplyButton.css create mode 100644 src/core/client/stream/tabs/Comments/Stream/AllCommentsTab/AllCommentsTabContainer.css create mode 100644 src/core/client/stream/tabs/Profile/Settings/AccountSettingsContainer.css create mode 100644 src/core/client/stream/tabs/Profile/Settings/AccountSettingsContainer.tsx rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeEmail/ChangeEmailContainer.css (96%) rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeEmail/ChangeEmailContainer.tsx (92%) rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeEmail/UpdateEmailMutation.ts (100%) rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeEmail/index.ts (100%) create mode 100644 src/core/client/stream/tabs/Profile/Settings/ChangePassword.css rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeUsername/ChangeUsernameContainer.css (86%) rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeUsername/ChangeUsernameContainer.tsx (91%) rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeUsername/UpdateUsernameMutation.tsx (100%) rename src/core/client/stream/tabs/Profile/{ => Settings}/ChangeUsername/index.ts (100%) delete mode 100644 src/core/client/stream/tabs/Profile/Settings/SettingsContainer.css delete mode 100644 src/core/client/stream/tabs/Profile/Settings/SettingsContainer.tsx create mode 100644 src/core/client/stream/test/profile/__snapshots__/account.spec.tsx.snap delete mode 100644 src/core/client/stream/test/profile/__snapshots__/settings.spec.tsx.snap rename src/core/client/stream/test/profile/{settings.spec.tsx => account.spec.tsx} (59%) create mode 100644 src/core/client/stream/test/profile/notificationSettings.spec.tsx diff --git a/src/core/client/admin/test/configure/__snapshots__/general.spec.tsx.snap b/src/core/client/admin/test/configure/__snapshots__/general.spec.tsx.snap index 6a99a82db..fb68bea1b 100644 --- a/src/core/client/admin/test/configure/__snapshots__/general.spec.tsx.snap +++ b/src/core/client/admin/test/configure/__snapshots__/general.spec.tsx.snap @@ -873,9 +873,9 @@ based on the needs of your community. Preview "} diff --git a/src/core/client/stream/common/UserBox/__snapshots__/UserBoxAuthenticated.spec.tsx.snap b/src/core/client/stream/common/UserBox/__snapshots__/UserBoxAuthenticated.spec.tsx.snap index 0ada6ef2c..84a96640f 100644 --- a/src/core/client/stream/common/UserBox/__snapshots__/UserBoxAuthenticated.spec.tsx.snap +++ b/src/core/client/stream/common/UserBox/__snapshots__/UserBoxAuthenticated.spec.tsx.snap @@ -11,6 +11,7 @@ exports[`renders correctly with logout button 1`] = ` id="general-userBoxAuthenticated-signedInAs" > @@ -20,16 +21,17 @@ exports[`renders correctly with logout button 1`] = ` } id="general-userBoxAuthenticated-notYou" > diff --git a/src/core/client/stream/local/local.graphql b/src/core/client/stream/local/local.graphql index fa3c4e873..f4518ceb9 100644 --- a/src/core/client/stream/local/local.graphql +++ b/src/core/client/stream/local/local.graphql @@ -11,7 +11,8 @@ enum TAB { enum PROFILE_TAB { MY_COMMENTS - SETTINGS + ACCOUNT + NOTIFICATIONS } enum COMMENTS_TAB { diff --git a/src/core/client/stream/shared/htmlContent.css b/src/core/client/stream/shared/htmlContent.css index 5340b0ee1..8fdee109f 100644 --- a/src/core/client/stream/shared/htmlContent.css +++ b/src/core/client/stream/shared/htmlContent.css @@ -1,5 +1,6 @@ .root { composes: bodyCopy from "coral-ui/shared/typography.css"; + color: var(--palette-text-dark); overflow-wrap: break-word; & * bold, diff --git a/src/core/client/stream/tabs/Comments/Comment/ButtonsBar.tsx b/src/core/client/stream/tabs/Comments/Comment/ButtonsBar.tsx index 706042ffa..031ac0072 100644 --- a/src/core/client/stream/tabs/Comments/Comment/ButtonsBar.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/ButtonsBar.tsx @@ -4,7 +4,7 @@ import { Flex } from "coral-ui/components"; const ButtonsBar: FunctionComponent = props => { return ( - + {props.children} ); diff --git a/src/core/client/stream/tabs/Comments/Comment/Comment.css b/src/core/client/stream/tabs/Comments/Comment/Comment.css index efcaee621..3e0b41e2c 100644 --- a/src/core/client/stream/tabs/Comments/Comment/Comment.css +++ b/src/core/client/stream/tabs/Comments/Comment/Comment.css @@ -1,5 +1,6 @@ .root { } + .highlight { background-color: var(--palette-primary-lightest); padding: var(--mini-unit); diff --git a/src/core/client/stream/tabs/Comments/Comment/Comment.tsx b/src/core/client/stream/tabs/Comments/Comment/Comment.tsx index a5b19bba3..b6c79312b 100644 --- a/src/core/client/stream/tabs/Comments/Comment/Comment.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/Comment.tsx @@ -27,9 +27,12 @@ export interface CommentProps { const Comment: FunctionComponent = props => { return ( -
= props => {
)} - + {props.body || ""} {props.footer} - + ); }; diff --git a/src/core/client/stream/tabs/Comments/Comment/InReplyTo.css b/src/core/client/stream/tabs/Comments/Comment/InReplyTo.css index 3f5a70f00..c734ab2b3 100644 --- a/src/core/client/stream/tabs/Comments/Comment/InReplyTo.css +++ b/src/core/client/stream/tabs/Comments/Comment/InReplyTo.css @@ -1,9 +1,7 @@ .icon { - color: var(--palette-grey-light); -} -.inReplyTo { - color: var(--palette-grey-light); -} -.username { - color: var(--palette-grey-dark); + color: var(--palette-text-dark); } + +.username {} + +.inReplyTo {} \ No newline at end of file diff --git a/src/core/client/stream/tabs/Comments/Comment/InReplyTo.tsx b/src/core/client/stream/tabs/Comments/Comment/InReplyTo.tsx index 2791dff71..85cbb8253 100644 --- a/src/core/client/stream/tabs/Comments/Comment/InReplyTo.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/InReplyTo.tsx @@ -14,8 +14,9 @@ interface Props { const InReplyTo: FunctionComponent = ({ username }) => { const Username = () => ( {username} diff --git a/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkButton.tsx b/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkButton.tsx index ff31f0b68..a703aa9a9 100644 --- a/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkButton.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkButton.tsx @@ -3,8 +3,8 @@ import React, { FunctionComponent } from "react"; import { Button, - ButtonIcon, ClickOutside, + Icon, MatchMedia, Popover, } from "coral-ui/components"; @@ -43,13 +43,14 @@ const Permalink: FunctionComponent = ({ onClick={toggleVisibility} aria-controls={popoverID} ref={ref} - variant="ghost" + variant="textUnderlined" active={visible} size="small" + color="primary" className={className} > - share + share Share diff --git a/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkPopover.css b/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkPopover.css index ccfbb0f64..21829859f 100644 --- a/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkPopover.css +++ b/src/core/client/stream/tabs/Comments/Comment/PermalinkButton/PermalinkPopover.css @@ -4,4 +4,4 @@ .textField { flex-grow: 1; -} +} \ No newline at end of file diff --git a/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.css b/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.css index e027c4445..a6656510d 100644 --- a/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.css +++ b/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.css @@ -3,3 +3,7 @@ color: var(--palette-text-primary) !important; opacity: 1 !important; } + +.button { + padding-left: 0; +} \ No newline at end of file diff --git a/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.tsx b/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.tsx index 8b1c4c8ee..2be159525 100644 --- a/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.tsx +++ b/src/core/client/stream/tabs/Comments/Comment/ReactionButton/ReactionButton.tsx @@ -1,7 +1,7 @@ import cn from "classnames"; import React from "react"; -import { Button, ButtonIcon, MatchMedia } from "coral-ui/components"; +import { Button, Icon, MatchMedia } from "coral-ui/components"; import { ButtonProps } from "coral-ui/components/Button"; import styles from "./ReactionButton.css"; @@ -24,20 +24,25 @@ class ReactionButton extends React.Component { const { totalReactions, reacted, readOnly, className } = this.props; return ( + +
+ )} + {showForm && ( + + + + + Change Password + + + + {({ + handleSubmit, + submitting, + submitError, + pristine, + submitSucceeded, + }) => ( + + + }> + + {({ input, meta }) => ( + }> + + + Old Password + + + + + + + + + + + + )} + + + {({ input, meta }) => ( + }> + + + New Password + + + + + + )} + + {submitError && ( + + {submitError} + + )} + {submitSucceeded && ( + + - Forgot your password? + Your password has been updated + + + )} + + + + + + - - )} - - - {({ input, meta }) => ( - }> - - - New Password - - - - - - )} - - {submitError && ( - - {submitError} - - )} - {submitSucceeded && ( - - - Your password has been updated - - - )} - - - - - - - - - )} - + + + + )} + + + + )} ); }; diff --git a/src/core/client/stream/tabs/Profile/ChangeUsername/ChangeUsernameContainer.css b/src/core/client/stream/tabs/Profile/Settings/ChangeUsername/ChangeUsernameContainer.css similarity index 86% rename from src/core/client/stream/tabs/Profile/ChangeUsername/ChangeUsernameContainer.css rename to src/core/client/stream/tabs/Profile/Settings/ChangeUsername/ChangeUsernameContainer.css index dd840b28d..1baef8d3a 100644 --- a/src/core/client/stream/tabs/Profile/ChangeUsername/ChangeUsernameContainer.css +++ b/src/core/client/stream/tabs/Profile/Settings/ChangeUsername/ChangeUsernameContainer.css @@ -1,5 +1,4 @@ .callOut { - max-width: 500px; } .footer { @@ -29,7 +28,3 @@ float: none; position: static; } - -.currentUsername { - color: var(--palette-grey-dark); -} \ No newline at end of file diff --git a/src/core/client/stream/tabs/Profile/ChangeUsername/ChangeUsernameContainer.tsx b/src/core/client/stream/tabs/Profile/Settings/ChangeUsername/ChangeUsernameContainer.tsx similarity index 91% rename from src/core/client/stream/tabs/Profile/ChangeUsername/ChangeUsernameContainer.tsx rename to src/core/client/stream/tabs/Profile/Settings/ChangeUsername/ChangeUsernameContainer.tsx index eb6363be0..568945886 100644 --- a/src/core/client/stream/tabs/Profile/ChangeUsername/ChangeUsernameContainer.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/ChangeUsername/ChangeUsernameContainer.tsx @@ -78,6 +78,9 @@ const ChangeUsernameContainer: FunctionComponent = ({ ]); const canChangeLocalAuth = useMemo(() => { + if (!settings.accountFeatures.changeUsername) { + return false; + } if ( !viewer.profiles.find(profile => profile.__typename === "LocalProfile") ) { @@ -168,14 +171,24 @@ const ChangeUsernameContainer: FunctionComponent = ({ )} {!showEditForm && ( - - - {viewer.username} - - {canChangeLocalAuth && settings.accountFeatures.changeUsername && ( + +
+ + + Username + + + {viewer.username} +
+ {canChangeLocalAuth && ( - - ) : ( - - )} + {deletionDate && ( + <> + + + You have already submitted a request to delete your account. + Your account will be deleted on {deletionDate}. You may cancel + the request until that time. + + + + + )} + + + {!deletionDate && ( + + + + )} +
); }; diff --git a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/CompletionPage.tsx b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/CompletionPage.tsx index d36d9fdc2..8f8f97048 100644 --- a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/CompletionPage.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/CompletionPage.tsx @@ -47,7 +47,7 @@ const CompletionPage: FunctionComponent = ({ justifyContent="center" className={cn(styles.header, CLASSES.deleteMyAccountModal.header)} > - + Account deletion requested @@ -56,7 +56,7 @@ const CompletionPage: FunctionComponent = ({
- + Your request has been submitted and a confirmation has been sent to the email address associated with your account. @@ -64,7 +64,7 @@ const CompletionPage: FunctionComponent = ({ @@ -72,13 +72,13 @@ const CompletionPage: FunctionComponent = ({ - + Changed your mind? } > @@ -87,13 +87,13 @@ const CompletionPage: FunctionComponent = ({ - + Tell us why. @@ -110,7 +110,7 @@ const CompletionPage: FunctionComponent = ({ onClick={onDoneClicked} className={CLASSES.deleteMyAccountModal.doneButton} > - + Done diff --git a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/ConfirmPage.tsx b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/ConfirmPage.tsx index 59a892e80..c6d9d85de 100644 --- a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/ConfirmPage.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/ConfirmPage.tsx @@ -99,7 +99,7 @@ const ConfirmPage: FunctionComponent = ({ justifyContent="center" className={cn(sharedStyles.header, CLASSES.deleteMyAccountModal.header)} > - + Confirm account deletion? @@ -108,7 +108,7 @@ const ConfirmPage: FunctionComponent = ({
- + = ({ Are you sure you want to delete your account? - + = ({ > {({ input, meta }) => ( - + To confirm, type phrase below: @@ -174,7 +174,7 @@ const ConfirmPage: FunctionComponent = ({ {({ input, meta }) => ( - + Enter your password: = ({
- + - + @@ -92,7 +92,7 @@ const DescriptionPage: FunctionComponent = ({ )} onClick={onCancelClicked} > - + Cancel diff --git a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/DownloadCommentsPage.tsx b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/DownloadCommentsPage.tsx index 11f7a3533..0d1184ec9 100644 --- a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/DownloadCommentsPage.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/DownloadCommentsPage.tsx @@ -34,7 +34,7 @@ const DownloadCommentsPage: FunctionComponent = ({ justifyContent="center" className={cn(styles.header, CLASSES.deleteMyAccountModal.header)} > - + Download my comments? @@ -43,14 +43,14 @@ const DownloadCommentsPage: FunctionComponent = ({
- + Before your account is deleted, we recommend you download your comment history for your records. After your account is deleted, you will be unable to request your comment history. - + My Profile > Download My Comment History @@ -66,7 +66,7 @@ const DownloadCommentsPage: FunctionComponent = ({ )} onClick={onProceedClicked} > - + Proceed @@ -78,7 +78,7 @@ const DownloadCommentsPage: FunctionComponent = ({ )} onClick={onCancelClicked} > - + Cancel diff --git a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/WhenPage.tsx b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/WhenPage.tsx index 31c762e84..8aa0ee7bf 100644 --- a/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/WhenPage.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/DeleteAccount/Pages/WhenPage.tsx @@ -30,7 +30,7 @@ const WhenPage: FunctionComponent = ({ step, onCancel, onProceed }) => { justifyContent="center" className={cn(styles.header, CLASSES.deleteMyAccountModal.header)} > - + Delete my account: When? @@ -39,23 +39,23 @@ const WhenPage: FunctionComponent = ({ step, onCancel, onProceed }) => {
- + When will my account be deleted? - + Your account will be deleted 24 hours after your request has been submitted. - + Can I still write comments until my account is deleted? - + No. Once you've requested account deletion, you can no longer write comments, reply to comments, or select reactions. @@ -72,7 +72,7 @@ const WhenPage: FunctionComponent = ({ step, onCancel, onProceed }) => { )} onClick={onProceedClicked} > - + Proceed @@ -84,7 +84,7 @@ const WhenPage: FunctionComponent = ({ step, onCancel, onProceed }) => { )} onClick={onCancelClicked} > - + Cancel diff --git a/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.css b/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.css index ee7529b6f..d28fc4a65 100644 --- a/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.css +++ b/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.css @@ -1,9 +1,11 @@ .root { - max-width: 500px; - margin-top: var(--spacing-2); } +.content { + max-width: 495px; +} + .title { margin-bottom: var(--spacing-2); } diff --git a/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.tsx b/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.tsx index cfb296140..cd2136318 100644 --- a/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/DownloadCommentsContainer.tsx @@ -9,7 +9,7 @@ import { useCoralContext } from "coral-framework/lib/bootstrap"; import { useMutation, withFragmentContainer } from "coral-framework/lib/relay"; import { DownloadCommentsContainer_viewer } from "coral-stream/__generated__/DownloadCommentsContainer_viewer.graphql"; import CLASSES from "coral-stream/classes"; -import { Button, CallOut, Icon, Typography } from "coral-ui/components"; +import { Button, CallOut, Flex, Icon, Typography } from "coral-ui/components"; import RequestCommentsDownloadMutation from "./RequestCommentsDownloadMutation"; @@ -52,68 +52,72 @@ const DownloadCommentsContainer: FunctionComponent = ({ viewer }) => { return (
- - - Download my comment history - - - } - > - - You will receive an email with a link to download your comment - history. You can make one download request every 14 days. - - - {lastDownloadedAt && ( - - - Your most recent request: {formatter.format(lastDownloadedAt)} - - - )} - {canDownload ? ( - - ) : ( + {lastDownloadedAt && ( + + + Your most recent request: {formatter.format(lastDownloadedAt)} + + + )} +
+
+ {canDownload && ( + + + + )} +
+ + {!canDownload && ( query_builder diff --git a/src/core/client/stream/tabs/Profile/Settings/IgnoreUserSettingsContainer.tsx b/src/core/client/stream/tabs/Profile/Settings/IgnoreUserSettingsContainer.tsx index 7e545eaa2..1927cfbb1 100644 --- a/src/core/client/stream/tabs/Profile/Settings/IgnoreUserSettingsContainer.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/IgnoreUserSettingsContainer.tsx @@ -1,5 +1,5 @@ import { Localized } from "fluent-react/compat"; -import React, { FunctionComponent } from "react"; +import React, { FunctionComponent, useCallback, useState } from "react"; import { graphql } from "react-relay"; import { useMutation, withFragmentContainer } from "coral-framework/lib/relay"; @@ -23,51 +23,76 @@ interface Props { const IgnoreUserSettingsContainer: FunctionComponent = ({ viewer }) => { const removeUserIgnore = useMutation(RemoveUserIgnoreMutation); + const [showManage, setShowManage] = useState(false); + const toggleManage = useCallback(() => setShowManage(!showManage), [ + showManage, + setShowManage, + ]); return (
- - Ignored Commenters - - -

- Once you ignore someone, all of their comments are hidden from you. - Commenters you ignore will still be able to see your comments. -

-
- - {viewer.ignoredUsers.map(user => ( - + + + Ignored Commenters + + + + - - ))} - {viewer.ignoredUsers.length === 0 && ( - -
- You are not currently ignoring anyone -
+ Manage + +
+ + {showManage && ( +
+ +

+ Once you ignore someone, all of their comments are hidden from + you. Commenters you ignore will still be able to see your + comments. +

- )} - + + {viewer.ignoredUsers.map(user => ( + + + {user.username} + + + + ))} + {viewer.ignoredUsers.length === 0 && ( + +
+ You are not currently ignoring anyone +
+
+ )} +
+
+ )}
); }; diff --git a/src/core/client/stream/tabs/Profile/Settings/NotificationSettingsContainer.tsx b/src/core/client/stream/tabs/Profile/Settings/NotificationSettingsContainer.tsx index eab0778f0..b88bdd090 100644 --- a/src/core/client/stream/tabs/Profile/Settings/NotificationSettingsContainer.tsx +++ b/src/core/client/stream/tabs/Profile/Settings/NotificationSettingsContainer.tsx @@ -8,6 +8,7 @@ import { InvalidRequestError } from "coral-framework/lib/errors"; import { useMutation, withFragmentContainer } from "coral-framework/lib/relay"; import { GQLDIGEST_FREQUENCY } from "coral-framework/schema"; import { NotificationSettingsContainer_viewer } from "coral-stream/__generated__/NotificationSettingsContainer_viewer.graphql"; +import CLASSES from "coral-stream/classes"; import { Button, CallOut, @@ -53,142 +54,150 @@ const NotificationSettingsContainer: FunctionComponent = ({ ); return ( - - - Email Notifications - - - Receive notifications when: - - - - {({ - handleSubmit, - submitting, - submitError, - pristine, - submitSucceeded, - }) => ( - - -
- - - {({ input }) => ( - - - My comment receives a reply - - - )} - - - - - {({ input }) => ( - - - My comment is featured - - - )} - - - - - {({ input }) => ( - - - A staff member replies to my comment - - - )} - - - - - {({ input }) => ( - - - My pending comment has been reviewed - - - )} - - - - - - - Send Notifications: - + + + {({ + handleSubmit, + submitting, + submitError, + pristine, + submitSucceeded, + }) => ( + + + + + + + Email Notifications + + + + + Receive notifications when: + + + + + + + +
+ + + {({ input }) => ( + + + My comment receives a reply + - - {({ values }) => ( - - {({ input }) => ( - - - - - - - - - - - - )} - - )} - - - -
- {submitError && ( - - {submitError} + )} + +
+ + + {({ input }) => ( + + + My comment is featured + + + )} + + + + + {({ input }) => ( + + + A staff member replies to my comment + + + )} + + + + + {({ input }) => ( + + + My pending comment has been reviewed + + + )} + + + + + + + Send Notifications: + + + + {({ values }) => ( + + {({ input }) => ( + + + + + + + + + + + + )} + + )} + + + +
+ {submitError && ( + + {submitError} + + )} + {submitSucceeded && ( + + + Your notification settings have been updated - )} - {submitSucceeded && ( - - - Your notification settings have been updated - - - )} - - - - - -
- - )} - -
+
+ )} + + + )} + ); }; diff --git a/src/core/client/stream/tabs/Profile/Settings/SettingsContainer.css b/src/core/client/stream/tabs/Profile/Settings/SettingsContainer.css deleted file mode 100644 index 07a86050e..000000000 --- a/src/core/client/stream/tabs/Profile/Settings/SettingsContainer.css +++ /dev/null @@ -1,3 +0,0 @@ -.root { - max-width: 440px; -} diff --git a/src/core/client/stream/tabs/Profile/Settings/SettingsContainer.tsx b/src/core/client/stream/tabs/Profile/Settings/SettingsContainer.tsx deleted file mode 100644 index 9c962c74f..000000000 --- a/src/core/client/stream/tabs/Profile/Settings/SettingsContainer.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { FunctionComponent } from "react"; -import { graphql } from "react-relay"; - -import { withFragmentContainer } from "coral-framework/lib/relay"; -import { SettingsContainer_settings } from "coral-stream/__generated__/SettingsContainer_settings.graphql"; -import { SettingsContainer_viewer } from "coral-stream/__generated__/SettingsContainer_viewer.graphql"; -import { HorizontalGutter } from "coral-ui/components"; - -import ChangePasswordContainer from "./ChangePasswordContainer"; -import DeleteAccountContainer from "./DeleteAccount/DeleteAccountContainer"; -import DownloadCommentsContainer from "./DownloadCommentsContainer"; -import IgnoreUserSettingsContainer from "./IgnoreUserSettingsContainer"; -import NotificationSettingsContainer from "./NotificationSettingsContainer"; - -import styles from "./SettingsContainer.css"; - -interface Props { - viewer: SettingsContainer_viewer; - settings: SettingsContainer_settings; -} - -const SettingsContainer: FunctionComponent = ({ viewer, settings }) => ( - - - - {settings.accountFeatures.downloadComments && ( - - )} - {settings.accountFeatures.deleteAccount && ( - - )} - - -); - -const enhanced = withFragmentContainer({ - viewer: graphql` - fragment SettingsContainer_viewer on User { - ...IgnoreUserSettingsContainer_viewer - ...DownloadCommentsContainer_viewer - ...DeleteAccountContainer_viewer - ...NotificationSettingsContainer_viewer - } - `, - settings: graphql` - fragment SettingsContainer_settings on Settings { - accountFeatures { - downloadComments - deleteAccount - } - ...ChangePasswordContainer_settings - ...DeleteAccountContainer_settings - } - `, -})(SettingsContainer); - -export default enhanced; diff --git a/src/core/client/stream/tabs/Profile/Settings/index.ts b/src/core/client/stream/tabs/Profile/Settings/index.ts index cf7260860..8b3a605be 100644 --- a/src/core/client/stream/tabs/Profile/Settings/index.ts +++ b/src/core/client/stream/tabs/Profile/Settings/index.ts @@ -1 +1,4 @@ -export { default, default as SettingsContainer } from "./SettingsContainer"; +export { + default, + default as AccountSettingsContainer, +} from "./AccountSettingsContainer"; diff --git a/src/core/client/stream/test/comments/featured/__snapshots__/renderFeaturedStream.spec.tsx.snap b/src/core/client/stream/test/comments/featured/__snapshots__/renderFeaturedStream.spec.tsx.snap index 130ec9484..3db318ea3 100644 --- a/src/core/client/stream/test/comments/featured/__snapshots__/renderFeaturedStream.spec.tsx.snap +++ b/src/core/client/stream/test/comments/featured/__snapshots__/renderFeaturedStream.spec.tsx.snap @@ -321,7 +321,7 @@ exports[`renders comment stream 1`] = ` type="button" > Markus @@ -355,9 +355,9 @@ exports[`renders comment stream 1`] = ` className="Box-root Flex-root coral coral-featuredComment-actionBar Flex-flex Flex-justifySpaceBetween Box-mt-2" >
+ + + +
+
+
+
+
+ Signed in as + + Passivo + + . +
+
+ + Not you?  + + +
+
+
+
    + + + +
+
+
+

+ Manage your account +

+
+
+
+
+

+ Username +

+

+ Passivo +

+
+ +
+
+
+
+
+

+ Email +

+
+

+ +   + +

+ (Unverified) +

+
+
+ +
+
+
+
+
+ +
+
+

+ Verify your email address +

+

+ An email has been sent to $email to verify your account. +You must verify your new email address before it can be used for +signing into your account or for email notifications. +

+ +
+
+
+
+
+
+
+

+ Password +

+ +
+
+
+
+

+ Ignored Commenters +

+ +
+
+
+
+
+

+ Download my comment history +

+

+ You will receive an email with a link to download your comment history. +You can make + + one download request every 14 days. + +

+
+
+ +
+
+
+
+
+
+

+ Delete My Account +

+

+ Deleting your account will permanently erase your profile and remove +all your comments from this site. +

+
+ +
+
+
+
+
+
+
+
+`; diff --git a/src/core/client/stream/test/profile/__snapshots__/myComments.spec.tsx.snap b/src/core/client/stream/test/profile/__snapshots__/myComments.spec.tsx.snap index 665911749..e415be247 100644 --- a/src/core/client/stream/test/profile/__snapshots__/myComments.spec.tsx.snap +++ b/src/core/client/stream/test/profile/__snapshots__/myComments.spec.tsx.snap @@ -5,41 +5,45 @@ exports[`renders profile 1`] = ` className="Box-root HorizontalGutter-root HorizontalGutter-double" data-testid="profile-commentHistory" > -

- Comment History -

-

- Story: title -

- -
+
+

+ Comment on: +

+

+ title +

+
+
+
+
+ /> +
-

- Story: title -

- -
+
+

+ Comment on: +

+

+ title +

+
+
+
+
+ /> +
- - - -
-
-
-
-
-

- Passivo -

- -
-
-
-
-

- -   - -

- (Unverified) -

- -
-
-
-
-
- -
-
-

- Verify your email address -

-

- An email has been sent to $email to verify your account. -You must verify your new email address before it can be used for -signing into your account or for email notifications. -

- -
-
-
-
-
-
-
    - - -
-
-
-
-

- Ignored Commenters -

-

- Once you ignore someone, all of their comments are hidden from you. -Commenters you ignore will still be able to see your comments. -

-
-
- You are not currently ignoring anyone -
-
-
-
-
-
-

- Change Password -

-
-
- -
-
- -
- -
-
-
-
- -
-
-
- -
-
- -
- -
-
-
-
-
- -
-
-
-
-
-
-

- Download my comment history -

-

- You will receive an email with a link to download your comment history. -You can make - - one download request every 14 days. - -

- -
-
-

- Delete My Account -

-

- Deleting your account will permanently erase your profile and remove -all your comments from this site. -

- -
-
-

- Email Notifications -

-

- Receive notifications when: -

-
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-

- Send Notifications: -

- - - - - - -
-
-
-
- -
-
-
-
-
-
-
-
-
-
-`; diff --git a/src/core/client/stream/test/profile/settings.spec.tsx b/src/core/client/stream/test/profile/account.spec.tsx similarity index 59% rename from src/core/client/stream/test/profile/settings.spec.tsx rename to src/core/client/stream/test/profile/account.spec.tsx index 8ce885421..24916348f 100644 --- a/src/core/client/stream/test/profile/settings.spec.tsx +++ b/src/core/client/stream/test/profile/account.spec.tsx @@ -39,7 +39,7 @@ async function createTestRenderer( params.resolvers ), initLocalState: (localRecord, source, environment) => { - localRecord.setValue("SETTINGS", "profileTab"); + localRecord.setValue("ACCOUNT", "profileTab"); if (params.initLocalState) { params.initLocalState(localRecord, source, environment); } @@ -47,13 +47,11 @@ async function createTestRenderer( }); const ignoredCommenters = await waitForElement(() => - within(testRenderer.root).queryByTestID( - "profile-settings-ignoredCommenters" - ) + within(testRenderer.root).queryByTestID("profile-account-ignoredCommenters") ); const changePassword = within(testRenderer.root).queryByTestID( - "profile-settings-changePassword" + "profile-account-changePassword" ); return { @@ -100,8 +98,13 @@ it("render password change form", async () => { }), }); const changePassword = await waitForElement(() => - within(testRenderer.root).getByTestID("profile-settings-changePassword") + within(testRenderer.root).getByTestID("profile-account-changePassword") ); + const editButton = within(changePassword).getByText("Edit"); + act(() => { + editButton.props.onClick(); + }); + const form = within(changePassword).getByType("form"); const oldPassword = await waitForElement(() => within(form).getByID("oldPassword", { exact: false }) @@ -141,6 +144,10 @@ it("render password change form", async () => { it("render empty ignored users list", async () => { const { ignoredCommenters } = await createTestRenderer(); + const editButton = within(ignoredCommenters).getByText("Manage"); + act(() => { + editButton.props.onClick(); + }); await waitForElement(() => within(ignoredCommenters).getByText( "You are not currently ignoring anyone", @@ -170,6 +177,10 @@ it("render ignored users list", async () => { }, }), }); + const editButton = within(ignoredCommenters).getByText("Manage"); + act(() => { + editButton.props.onClick(); + }); within(ignoredCommenters).getByText(commenters[0].username!); within(ignoredCommenters).getByText(commenters[1].username!); @@ -184,100 +195,3 @@ it("render ignored users list", async () => { ); within(ignoredCommenters).getByText(commenters[1].username!); }); - -it("render notifications form", async () => { - const updateNotificationSettings = sinon - .stub() - .callsFake((_: any, { input: { clientMutationId, ...notifications } }) => { - expectAndFail(notifications).toMatchObject({ - onReply: true, - onFeatured: true, - onStaffReplies: true, - onModeration: true, - digestFrequency: "HOURLY", - }); - return { - user: pureMerge(viewer, { - notifications, - }), - clientMutationId, - }; - }); - const { testRenderer } = await createTestRenderer({ - resolvers: createResolversStub({ - Mutation: { - updateNotificationSettings, - }, - }), - }); - const container = await waitForElement(() => - within(testRenderer.root).getByTestID("profile-settings-notifications") - ); - const form = within(container).getByType("form"); - - // Get the form fields. - const onReply = await waitForElement(() => - within(form).getByID("onReply", { exact: false }) - ); - const onStaffReplies = await waitForElement(() => - within(form).getByID("onStaffReplies", { exact: false }) - ); - const onModeration = await waitForElement(() => - within(form).getByID("onModeration", { exact: false }) - ); - const onFeatured = await waitForElement(() => - within(form).getByID("onFeatured", { exact: false }) - ); - const digestFrequency = await waitForElement(() => - within(form).getByID("digestFrequency", { exact: false }) - ); - const save = await waitForElement(() => within(form).getByType("button")); - - // The save button should be disabled for unchanged fields. - expect(save.props.disabled).toEqual(true); - - // The digest frequency select should be disabled with no options enabled. - expect(digestFrequency.props.disabled).toEqual(true); - - // Enable the options. - act(() => { - onReply.props.onChange(true); - onStaffReplies.props.onChange(true); - onModeration.props.onChange(true); - onFeatured.props.onChange(true); - }); - - // The digest frequency select should now be enabled. - expect(digestFrequency.props.disabled).toEqual(false); - - // Change the digest frequency. - act(() => { - digestFrequency.props.onChange("HOURLY"); - }); - - // Submit the form. - await act(async () => { - await form.props.onSubmit(); - }); - - // Ensure that the mutation was called and that the save button is now - // disabled. - expect(updateNotificationSettings.calledOnce).toEqual(true); - expect(save.props.disabled).toEqual(true); - - // Change a notification option. - act(() => { - onReply.props.onChange(false); - }); - - // The save button should now be enabled. - expect(save.props.disabled).toEqual(false); - - // Change a notification back (making it pristine). - act(() => { - onReply.props.onChange(true); - }); - - // The save button should now be disabled. - expect(save.props.disabled).toEqual(true); -}); diff --git a/src/core/client/stream/test/profile/changeEmail.spec.tsx b/src/core/client/stream/test/profile/changeEmail.spec.tsx index 61693e939..0d2e927e0 100644 --- a/src/core/client/stream/test/profile/changeEmail.spec.tsx +++ b/src/core/client/stream/test/profile/changeEmail.spec.tsx @@ -30,7 +30,7 @@ async function createTestRenderer( params.resolvers ), initLocalState: (localRecord, source, environment) => { - localRecord.setValue("SETTINGS", "profileTab"); + localRecord.setValue("ACCOUNT", "profileTab"); if (params.initLocalState) { params.initLocalState(localRecord, source, environment); } diff --git a/src/core/client/stream/test/profile/changeUsername.spec.tsx b/src/core/client/stream/test/profile/changeUsername.spec.tsx index 8bcc38373..984c411ae 100644 --- a/src/core/client/stream/test/profile/changeUsername.spec.tsx +++ b/src/core/client/stream/test/profile/changeUsername.spec.tsx @@ -38,7 +38,7 @@ async function createTestRenderer( params.resolvers ), initLocalState: (localRecord, source, environment) => { - localRecord.setValue("SETTINGS", "profileTab"); + localRecord.setValue("ACCOUNT", "profileTab"); if (params.initLocalState) { params.initLocalState(localRecord, source, environment); } diff --git a/src/core/client/stream/test/profile/deleteAccount.spec.tsx b/src/core/client/stream/test/profile/deleteAccount.spec.tsx index ad4763693..df5986820 100644 --- a/src/core/client/stream/test/profile/deleteAccount.spec.tsx +++ b/src/core/client/stream/test/profile/deleteAccount.spec.tsx @@ -31,7 +31,7 @@ async function createTestRenderer( params.resolvers ), initLocalState: (localRecord, source, environment) => { - localRecord.setValue("SETTINGS", "profileTab"); + localRecord.setValue("ACCOUNT", "profileTab"); if (params.initLocalState) { params.initLocalState(localRecord, source, environment); } @@ -65,24 +65,16 @@ describe("delete account steps", () => { }), }); testRenderer = setup.testRenderer; - - const settingsButton = await waitForElement(() => - within(testRenderer.root).getByText("Settings", { - selector: "button", - }) - ); - act(() => { - settingsButton.props.onClick(); - }); }); it("request account deletion button shows deletion modal", async () => { - const requestDeletionButton = within(testRenderer.root).getByText( - "Request account deletion", - { - selector: "button", - } + const deleteAccount = await waitForElement(() => + within(testRenderer.root).queryByTestID("profile-account-deleteAccount") ); + + const requestDeletionButton = within(deleteAccount).getByText("Request", { + selector: "button", + }); act(() => { requestDeletionButton.props.onClick(); }); @@ -95,12 +87,13 @@ describe("delete account steps", () => { }); it("schedules deletion if deletion steps are followed", async () => { - const requestDeletionButton = within(testRenderer.root).getByText( - "Request account deletion", - { - selector: "button", - } + const deleteAccount = await waitForElement(() => + within(testRenderer.root).queryByTestID("profile-account-deleteAccount") ); + + const requestDeletionButton = within(deleteAccount).getByText("Request", { + selector: "button", + }); act(() => { requestDeletionButton.props.onClick(); }); @@ -134,12 +127,13 @@ describe("delete account steps", () => { }); it("deletion confirmation is required during deletion steps", async () => { - const requestDeletionButton = within(testRenderer.root).getByText( - "Request account deletion", - { - selector: "button", - } + const deleteAccount = await waitForElement(() => + within(testRenderer.root).queryByTestID("profile-account-deleteAccount") ); + + const requestDeletionButton = within(deleteAccount).getByText("Request", { + selector: "button", + }); act(() => { requestDeletionButton.props.onClick(); }); @@ -171,12 +165,13 @@ describe("delete account steps", () => { }); it("password is required during deletion steps", async () => { - const requestDeletionButton = within(testRenderer.root).getByText( - "Request account deletion", - { - selector: "button", - } + const deleteAccount = await waitForElement(() => + within(testRenderer.root).queryByTestID("profile-account-deleteAccount") ); + + const requestDeletionButton = within(deleteAccount).getByText("Request", { + selector: "button", + }); act(() => { requestDeletionButton.props.onClick(); }); diff --git a/src/core/client/stream/test/profile/notificationSettings.spec.tsx b/src/core/client/stream/test/profile/notificationSettings.spec.tsx new file mode 100644 index 000000000..a75bc5af5 --- /dev/null +++ b/src/core/client/stream/test/profile/notificationSettings.spec.tsx @@ -0,0 +1,143 @@ +import sinon from "sinon"; + +import { pureMerge } from "coral-common/utils"; +import { GQLResolver } from "coral-framework/schema"; +import { + act, + createResolversStub, + CreateTestRendererParams, + waitForElement, + within, +} from "coral-framework/testHelpers"; + +import { settings, stories, viewerPassive } from "../fixtures"; +import create from "./create"; + +const story = stories[0]; +const viewer = viewerPassive; + +async function createTestRenderer( + params: CreateTestRendererParams = {} +) { + const { testRenderer, context } = create({ + ...params, + resolvers: pureMerge( + createResolversStub({ + Query: { + settings: () => settings, + viewer: () => viewer, + story: () => story, + }, + }), + params.resolvers + ), + initLocalState: (localRecord, source, environment) => { + localRecord.setValue("NOTIFICATIONS", "profileTab"); + if (params.initLocalState) { + params.initLocalState(localRecord, source, environment); + } + }, + }); + + return { + testRenderer, + context, + }; +} + +it("render notifications form", async () => { + const updateNotificationSettings = sinon + .stub() + .callsFake((_: any, { input: { clientMutationId, ...notifications } }) => { + expectAndFail(notifications).toMatchObject({ + onReply: true, + onFeatured: true, + onStaffReplies: true, + onModeration: true, + digestFrequency: "HOURLY", + }); + return { + user: pureMerge(viewer, { + notifications, + }), + clientMutationId, + }; + }); + const { testRenderer } = await createTestRenderer({ + resolvers: createResolversStub({ + Mutation: { + updateNotificationSettings, + }, + }), + }); + const container = await waitForElement(() => + within(testRenderer.root).getByTestID("profile-account-notifications") + ); + const form = within(container).getByType("form"); + + // Get the form fields. + const onReply = await waitForElement(() => + within(form).getByID("onReply", { exact: false }) + ); + const onStaffReplies = await waitForElement(() => + within(form).getByID("onStaffReplies", { exact: false }) + ); + const onModeration = await waitForElement(() => + within(form).getByID("onModeration", { exact: false }) + ); + const onFeatured = await waitForElement(() => + within(form).getByID("onFeatured", { exact: false }) + ); + const digestFrequency = await waitForElement(() => + within(form).getByID("digestFrequency", { exact: false }) + ); + const save = await waitForElement(() => within(form).getByType("button")); + + // The save button should be disabled for unchanged fields. + expect(save.props.disabled).toEqual(true); + + // The digest frequency select should be disabled with no options enabled. + expect(digestFrequency.props.disabled).toEqual(true); + + // Enable the options. + act(() => { + onReply.props.onChange(true); + onStaffReplies.props.onChange(true); + onModeration.props.onChange(true); + onFeatured.props.onChange(true); + }); + + // The digest frequency select should now be enabled. + expect(digestFrequency.props.disabled).toEqual(false); + + // Change the digest frequency. + act(() => { + digestFrequency.props.onChange("HOURLY"); + }); + + // Submit the form. + await act(async () => { + await form.props.onSubmit(); + }); + + // Ensure that the mutation was called and that the save button is now + // disabled. + expect(updateNotificationSettings.calledOnce).toEqual(true); + expect(save.props.disabled).toEqual(true); + + // Change a notification option. + act(() => { + onReply.props.onChange(false); + }); + + // The save button should now be enabled. + expect(save.props.disabled).toEqual(false); + + // Change a notification back (making it pristine). + act(() => { + onReply.props.onChange(true); + }); + + // The save button should now be disabled. + expect(save.props.disabled).toEqual(true); +}); diff --git a/src/core/client/ui/components/Button/Button.css b/src/core/client/ui/components/Button/Button.css index 50d60f23b..645b714e5 100644 --- a/src/core/client/ui/components/Button/Button.css +++ b/src/core/client/ui/components/Button/Button.css @@ -131,7 +131,7 @@ } } -.variantFilled { +.variantFilled, .variantOutlineFilled.mouseHover { color: var(--palette-text-light); &.colorRegular { background-color: var(--palette-grey-main); @@ -151,7 +151,13 @@ &.colorDark { background-color: var(--palette-text-primary); } +} +.variantOutlineFilled.mouseHover { + border: 1px solid transparent; /* prevent jumping between outlined and filled on hover */ +} + +.variantFilled { &:not(.disabled) { &.colorRegular { &.mouseHover { @@ -211,7 +217,7 @@ } } -.variantOutlined { +.variantOutlined, .variantOutlineFilled:not(.mouseHover) { border: 1px solid transparent; &.colorRegular { color: var(--palette-grey-main); @@ -237,7 +243,8 @@ color: var(--palette-text-primary); border: 1px solid currentColor; } - +} +.variantOutlined { &:not(.disabled) { &.colorRegular { &.mouseHover { @@ -573,3 +580,33 @@ } } } + +.variantTextUnderlined { + font-weight: 700; + &:not(.disabled) { + &.colorPrimary { + &.mouseHover { + color: var(--palette-primary-main); + & > span { + text-decoration: underline; + } + } + &.active, + &:active { + color: var(--palette-primary-main); + } + } + &.colorError { + &.mouseHover { + color: var(--palette-error-main); + & > span { + text-decoration: underline; + } + } + &.active, + &:active { + color: var(--palette-error-main); + } + } + } +} \ No newline at end of file diff --git a/src/core/client/ui/components/Button/Button.tsx b/src/core/client/ui/components/Button/Button.tsx index 5a6f6c75f..a6c45aa4e 100644 --- a/src/core/client/ui/components/Button/Button.tsx +++ b/src/core/client/ui/components/Button/Button.tsx @@ -40,7 +40,9 @@ interface Props extends Omit { | "outlined" | "ghost" | "underlined" - | "adornment"; + | "adornment" + | "textUnderlined" + | "outlineFilled"; /** If set renders a full width button */ fullWidth?: boolean; @@ -94,6 +96,8 @@ export class Button extends React.Component { [classes.variantGhost]: variant === "ghost", [classes.variantAdornment]: variant === "adornment", [classes.variantUnderlined]: variant === "underlined", + [classes.variantTextUnderlined]: variant === "textUnderlined", + [classes.variantOutlineFilled]: variant === "outlineFilled", [classes.fullWidth]: fullWidth, [classes.active]: active, [classes.disabled]: disabled, diff --git a/src/core/client/ui/components/CallOut/CallOut.css b/src/core/client/ui/components/CallOut/CallOut.css index 4928968d6..31ae21acf 100644 --- a/src/core/client/ui/components/CallOut/CallOut.css +++ b/src/core/client/ui/components/CallOut/CallOut.css @@ -11,6 +11,10 @@ word-break: break-word; } +.borderless { + border-style: none; +} + .colorRegular { background-color: var(--palette-grey-lightest); border-color: var(--palette-grey-light); diff --git a/src/core/client/ui/components/CallOut/CallOut.tsx b/src/core/client/ui/components/CallOut/CallOut.tsx index 75a193777..284db3256 100644 --- a/src/core/client/ui/components/CallOut/CallOut.tsx +++ b/src/core/client/ui/components/CallOut/CallOut.tsx @@ -27,10 +27,23 @@ export interface CallOutProps { * If set renders a full width CallOut */ fullWidth?: boolean; + + /* + * If set removes border + */ + borderless?: boolean; } const CallOut: FunctionComponent = props => { - const { className, classes, color, fullWidth, children, ...rest } = props; + const { + borderless, + className, + classes, + color, + fullWidth, + children, + ...rest + } = props; const rootClassName = cn( classes.root, @@ -39,6 +52,7 @@ const CallOut: FunctionComponent = props => { [classes.colorError]: color === "error", [classes.colorPrimary]: color === "primary", [classes.colorSuccess]: color === "success", + [classes.borderless]: borderless, [classes.fullWidth]: fullWidth, }, className diff --git a/src/core/client/ui/components/Dropdown/Dropdown.tsx b/src/core/client/ui/components/Dropdown/Dropdown.tsx index 2becf1724..c3da8b50b 100644 --- a/src/core/client/ui/components/Dropdown/Dropdown.tsx +++ b/src/core/client/ui/components/Dropdown/Dropdown.tsx @@ -1,3 +1,4 @@ +import cn from "classnames"; import React, { FunctionComponent } from "react"; import { withStyles } from "coral-ui/hocs"; @@ -17,7 +18,7 @@ const Dropdown: FunctionComponent = ({ ...rest }) => { return ( -
+
{children}
); diff --git a/src/core/client/ui/components/Tag/Tag.css b/src/core/client/ui/components/Tag/Tag.css index 1220b9828..c4c9a8a31 100644 --- a/src/core/client/ui/components/Tag/Tag.css +++ b/src/core/client/ui/components/Tag/Tag.css @@ -4,7 +4,7 @@ line-height: 1; padding: var(--spacing-1); white-space: nowrap; - border-radius: 1px; + border-radius: 2px; display: inline-block; } @@ -44,3 +44,7 @@ color: var(--palette-error-dark); } } + +.uppercase { + text-transform: uppercase; +} \ No newline at end of file diff --git a/src/core/client/ui/components/Tag/Tag.tsx b/src/core/client/ui/components/Tag/Tag.tsx index fc97f7972..cc946d9ba 100644 --- a/src/core/client/ui/components/Tag/Tag.tsx +++ b/src/core/client/ui/components/Tag/Tag.tsx @@ -26,6 +26,7 @@ const Tag: FunctionComponent = props => { [classes.colorError]: color === "error", [classes.colorGrey]: color === "grey", [classes.colorDarkest]: color === "dark", + [classes.uppercase]: variant !== "pill", }); return ( diff --git a/src/core/client/ui/components/Tag/__snapshots__/Tag.spec.tsx.snap b/src/core/client/ui/components/Tag/__snapshots__/Tag.spec.tsx.snap index 4ce1aa74a..e28a88335 100644 --- a/src/core/client/ui/components/Tag/__snapshots__/Tag.spec.tsx.snap +++ b/src/core/client/ui/components/Tag/__snapshots__/Tag.spec.tsx.snap @@ -2,7 +2,7 @@ exports[`renders correctly 1`] = ` Staff diff --git a/src/core/client/ui/components/Typography/Typography.css b/src/core/client/ui/components/Typography/Typography.css index a9d7abf43..f30033a1c 100644 --- a/src/core/client/ui/components/Typography/Typography.css +++ b/src/core/client/ui/components/Typography/Typography.css @@ -60,10 +60,6 @@ composes: buttonLarge from "coral-ui/shared/typography.css"; } -.inputLabel { - composes: inputLabel from "coral-ui/shared/typography.css"; -} - .detail { composes: detail from "coral-ui/shared/typography.css"; } @@ -114,6 +110,10 @@ color: var(--palette-text-secondary); } +.colorTextDark { + color: var(--palette-text-dark); +} + .colorTextLight { color: var(--palette-text-light); } @@ -133,3 +133,7 @@ .colorSuccess { color: var(--palette-success-darkest); } + +.inputLabel { + composes: inputLabel from "coral-ui/shared/typography.css"; +} \ No newline at end of file diff --git a/src/core/client/ui/components/Typography/Typography.tsx b/src/core/client/ui/components/Typography/Typography.tsx index ba1db8842..14f98cbf4 100644 --- a/src/core/client/ui/components/Typography/Typography.tsx +++ b/src/core/client/ui/components/Typography/Typography.tsx @@ -60,6 +60,7 @@ interface Props extends PropTypesOf { | "warning" | "error" | "errorDark" + | "textDark" | "success"; /** * The container used for the root node. @@ -118,6 +119,7 @@ const Typography: FunctionComponent = props => { [classes.colorTextSecondary]: color === "textSecondary", [classes.colorTextLight]: color === "textLight", [classes.colorPrimary]: color === "primary", + [classes.colorTextDark]: color === "textDark", [classes.colorError]: color === "error", [classes.colorErrorDark]: color === "errorDark", [classes.colorSuccess]: color === "success", diff --git a/src/core/client/ui/hocs/withStyles.ts b/src/core/client/ui/hocs/withStyles.ts index f0c27e3c0..128cac169 100644 --- a/src/core/client/ui/hocs/withStyles.ts +++ b/src/core/client/ui/hocs/withStyles.ts @@ -18,6 +18,8 @@ function withStyles( Object.keys(props.classes).forEach(k => { if (classes[k]) { resolvedClasses[k] += ` ${props.classes[k]}`; + } else if (process.env.NODE_ENV === "test") { + throw new Error(`Extending non existent className ${k}`); } else if (process.env.NODE_ENV !== "production") { // tslint:disable:next-line: no-console console.warn("Extending non existent className", k); diff --git a/src/core/client/ui/shared/typography.css b/src/core/client/ui/shared/typography.css index abd184eb5..360853186 100644 --- a/src/core/client/ui/shared/typography.css +++ b/src/core/client/ui/shared/typography.css @@ -164,7 +164,7 @@ .timestamp { color: var(--palette-text-secondary); font-family: var(--font-family-sans-serif); - font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-regular); font-size: calc(14rem / var(--rem-base)); line-height: calc(18em / 14); letter-spacing: 0; @@ -188,15 +188,6 @@ color: var(--palette-text-primary); } -.inputLabel { - font-size: calc(18rem / var(--rem-base)); - font-weight: var(--font-weight-medium); - font-family: var(--font-family-serif); - line-height: calc(18em / 18); - letter-spacing: calc(0.2em / 18); - color: var(--palette-text-primary); -} - .detail { font-size: calc(14rem / var(--rem-base)); font-weight: var(--font-weight-regular); @@ -274,9 +265,9 @@ .tagText { font-family: var(--font-family-sans-serif); - font-weight: var(--font-weight-regular); - font-size: calc(14rem / var(--rem-base)); - letter-spacing: calc(-0.2em / 14); + font-weight: var(--font-weight-medium); + font-size: calc(12rem / var(--rem-base)); + letter-spacing: calc(-0.2em / 12); } .sideNavigationItem { @@ -312,3 +303,12 @@ line-height: calc(14em / 14); color: var(--palette-grey-dark); } + +.inputLabel { + font-size: calc(18rem / var(--rem-base)); + font-weight: var(--font-weight-medium); + font-family: var(--font-family-serif); + line-height: calc(18em / 18); + letter-spacing: calc(0.2em / 18); + color: var(--palette-text-dark); +} diff --git a/src/core/client/ui/theme/mixins.css b/src/core/client/ui/theme/mixins.css index 90ec7e3dc..c69c0b9c4 100644 --- a/src/core/client/ui/theme/mixins.css +++ b/src/core/client/ui/theme/mixins.css @@ -2,7 +2,7 @@ font-size: calc(16rem / var(--rem-base)); font-weight: var(--font-weight-regular); font-family: var(--font-family-sans-serif); - line-height: calc(20em / 16); + line-height: calc(22em / 16); letter-spacing: calc(0.2em / 16); color: var(--palette-text-primary); } diff --git a/src/core/client/ui/theme/variables.ts b/src/core/client/ui/theme/variables.ts index 11412b552..10a9c706b 100644 --- a/src/core/client/ui/theme/variables.ts +++ b/src/core/client/ui/theme/variables.ts @@ -56,6 +56,7 @@ const variables = { primary: "#3B4A53", secondary: "#787D80", light: "#fff", + dark: "#14171A", }, /* Background colors */ background: { diff --git a/src/core/server/graph/tenant/schema/schema.graphql b/src/core/server/graph/tenant/schema/schema.graphql index 5075f1527..c33fdb3b8 100644 --- a/src/core/server/graph/tenant/schema/schema.graphql +++ b/src/core/server/graph/tenant/schema/schema.graphql @@ -1723,7 +1723,7 @@ type User { notifications stores the notification settings for the given User. """ notifications: UserNotificationSettings! - @auth(userIDField: "id", permit: [SUSPENDED, BANNED]) + @auth(userIDField: "id", permit: [SUSPENDED, BANNED, PENDING_DELETION]) """ createdAt is the time that the User was created at. @@ -5049,7 +5049,7 @@ type Mutation { """ cancelAccountDeletion( input: CancelAccountDeletionInput! - ): CancelAccountDeletionPayload! @auth(permit: [PENDING_DELETION]) + ): CancelAccountDeletionPayload! @auth(permit: [SUSPENDED, BANNED, PENDING_DELETION]) """ createToken allows an administrator to create a Token based on the current @@ -5137,14 +5137,14 @@ type Mutation { ignoreUser will mark the given User as ignored by the current logged in User. """ ignoreUser(input: IgnoreUserInput!): IgnoreUserPayload! - @auth(permit: [SUSPENDED, BANNED]) + @auth(permit: [SUSPENDED, BANNED, PENDING_DELETION]) """ removeUserIgnore will remove the given User from the ignored user list from the current logged in User. """ removeUserIgnore(input: RemoveUserIgnoreInput!): RemoveUserIgnorePayload! - @auth(permit: [SUSPENDED, BANNED]) + @auth(permit: [SUSPENDED, BANNED, PENDING_DELETION]) """ requestCommentsDownload allows a user to request to download their comments. diff --git a/src/locales/da/stream.ftl b/src/locales/da/stream.ftl index b3034b72a..f2025eaac 100644 --- a/src/locales/da/stream.ftl +++ b/src/locales/da/stream.ftl @@ -113,8 +113,8 @@ comments-userPopover-ignore = Ignorere comments-userIgnorePopover-ignoreUser = Ignorerer {$username}? comments-userIgnorePopover-description = - Når du ignorerer en kommentator, vil alle kommentarer, - de skrev på webstedet, være skjult for dig. Du kan fortryde + Når du ignorerer en kommentator, vil alle kommentarer, + de skrev på webstedet, være skjult for dig. Du kan fortryde dette senere fra Min profil. comments-userIgnorePopover-ignore = Ignorerer comments-userIgnorePopover-cancel = Afbestille @@ -144,7 +144,6 @@ comments-featured-replies = Svar ## Profile Tab profile-myCommentsTab = Mine kommentarer -profile-settingsTab = Indstillinger ### Comment History profile-historyComment-viewConversation = Se samtale @@ -158,19 +157,19 @@ profile-commentHistory-empty = Du har ikke skrevet nogen kommentarer profile-commentHistory-empty-subheading = En historie med dine kommentarer vises her ### Settings -profile-settings-ignoredCommenters = Ignorerede kommentarer -profile-settings-description = +profile-account-ignoredCommenters = Ignorerede kommentarer +profile-account-ignoredCommenters-description = Når du ignorerer nogen, er alle deres kommentarer skjult for dig. Kommentarer, du ignorerer, kan stadig se dine kommentarer. -profile-settings-empty = Du ignorerer i øjeblikket ingen -profile-settings-stopIgnoring = Stop med at ignorere +profile-account-ignoredCommenters-empty = Du ignorerer i øjeblikket ingen +profile-account-ignoredCommenters-stopIgnoring = Stop med at ignorere -profile-settings-changePassword = Skift kodeord -profile-settings-changePassword-oldPassword = Gammelt kodeord -profile-settings-changePassword-forgotPassword = Glemt din adgangskode? -profile-settings-changePassword-newPassword = Nyt kodeord -profile-settings-changePassword-button = Skift kodeord -profile-settings-changePassword-updated = +profile-account-changePassword = Skift kodeord +profile-account-changePassword-oldPassword = Gammelt kodeord +profile-account-changePassword-forgotPassword = Glemt din adgangskode? +profile-account-changePassword-newPassword = Nyt kodeord +profile-account-changePassword-button = Skift kodeord +profile-account-changePassword-updated = Din adgangskode er blevet opdateret ## Report Comment Popover @@ -224,8 +223,8 @@ configure-liveUpdates-description = configure-messageBox-title = Aktivér meddelelsesboks til denne stream configure-messageBox-description = - Tilføj en besked øverst i kommentarfeltet for dine læsere. Brug dette til at stille et emne, - stille et spørgsmål eller offentliggøre meddelelser vedrørende denne historie. + Tilføj en besked øverst i kommentarfeltet for dine læsere. Brug dette til at stille et emne, + stille et spørgsmål eller offentliggøre meddelelser vedrørende denne historie. configure-messageBox-preview = Forhåndsvisning configure-messageBox-selectAnIcon = Vælg et ikon configure-messageBox-noIcon = Intet ikon @@ -233,8 +232,8 @@ configure-messageBox-writeAMessage = Skriv en besked configure-closeStream-title = Luk kommentarer configure-closeStream-description = - Kommentarerne er i øjeblikket åbne. - Ved at lukke kommentarerne kan der ikke indsendes nye kommentarer, + Kommentarerne er i øjeblikket åbne. + Ved at lukke kommentarerne kan der ikke indsendes nye kommentarer, og alle tidligere indsendte kommentarer vises stadig. configure-closeStream-closeStream = Luk kommentarer @@ -247,8 +246,8 @@ configure-openStream-openStream = Åbn kommentarer comments-tombstone-ignore = Denne kommentar er skjult, fordi du ignorerede {$username} suspendInfo-heading = Din konto er midlertidigt suspenderet for at kommentere. -suspendInfo-info = - I overensstemmelse med fællesskabsretningslinjerne for { $organization} - er din konto midlertidigt suspenderet. Mens du er suspenderet, - kan du ikke kommentere, respektere eller rapportere kommentarer. +suspendInfo-info = + I overensstemmelse med fællesskabsretningslinjerne for { $organization} + er din konto midlertidigt suspenderet. Mens du er suspenderet, + kan du ikke kommentere, respektere eller rapportere kommentarer. Gå igen med til samtalen på { $until }. diff --git a/src/locales/en-US/stream.ftl b/src/locales/en-US/stream.ftl index a121923e2..0ffc5b589 100644 --- a/src/locales/en-US/stream.ftl +++ b/src/locales/en-US/stream.ftl @@ -169,7 +169,10 @@ comments-featured-replies = Replies ## Profile Tab profile-myCommentsTab = My Comments -profile-settingsTab = Settings +profile-myCommentsTab-comments = My comments +profile-accountTab = Account + +accountSettings-manage-account = Manage your account ### Account Deletion @@ -183,130 +186,141 @@ profile-historyComment-viewConversation = View Conversation profile-historyComment-replies = Replies {$replyCount} profile-historyComment-commentHistory = Comment History profile-historyComment-story = Story: {$title} +profile-historyComment-comment-on = Comment on: profile-profileQuery-errorLoadingProfile = Error loading profile profile-profileQuery-storyNotFound = Story not found profile-commentHistory-loadMore = Load More profile-commentHistory-empty = You have not written any comments profile-commentHistory-empty-subheading = A history of your comments will appear here -### Settings -profile-settings-ignoredCommenters = Ignored Commenters -profile-settings-description = +### Account +profile-account-ignoredCommenters = Ignored Commenters +profile-account-ignoredCommenters-description = Once you ignore someone, all of their comments are hidden from you. Commenters you ignore will still be able to see your comments. -profile-settings-empty = You are not currently ignoring anyone -profile-settings-stopIgnoring = Stop ignoring +profile-account-ignoredCommenters-empty = You are not currently ignoring anyone +profile-account-ignoredCommenters-stopIgnoring = Stop ignoring +profile-account-ignoredCommenters-manage = Manage +profile-account-ignoredCommenters-cancel = Cancel -profile-settings-changePassword = Change Password -profile-settings-changePassword-oldPassword = Old Password -profile-settings-changePassword-forgotPassword = Forgot your password? -profile-settings-changePassword-newPassword = New Password -profile-settings-changePassword-button = Change Password -profile-settings-changePassword-updated = +profile-account-changePassword-cancel = Cancel +profile-account-changePassword = Change Password +profile-account-changePassword-oldPassword = Old Password +profile-account-changePassword-forgotPassword = Forgot your password? +profile-account-changePassword-newPassword = New Password +profile-account-changePassword-button = Change Password +profile-account-changePassword-updated = Your password has been updated +profile-account-changePassword-password = Password -profile-settings-download-comments-title = Download my comment history -profile-settings-download-comments-description = +profile-account-download-comments-title = Download my comment history +profile-account-download-comments-description = You will receive an email with a link to download your comment history. You can make one download request every 14 days. -profile-settings-download-comments-request = +profile-account-download-comments-request = Request comment history -profile-settings-download-comments-request-icon = +profile-account-download-comments-request-icon = .title = Request comment history -profile-settings-download-comments-recentRequest = +profile-account-download-comments-recentRequest = Your most recent request: { $timeStamp } -profile-settings-download-comments-timeOut = +profile-account-download-comments-timeOut = You can submit another request in { framework-timeago-time } +profile-account-download-comments-request-button = Request ## Delete Account -profile-settings-deleteAccount-title = Delete My Account -profile-settings-deleteAccount-description = +profile-account-deleteAccount-title = Delete My Account +profile-account-deleteAccount-description = Deleting your account will permanently erase your profile and remove all your comments from this site. -profile-settings-deleteAccount-requestDelete = Request account deletion +profile-account-deleteAccount-requestDelete = Request account deletion -profile-settings-deleteAccount-cancelDelete-description = +profile-account-deleteAccount-cancelDelete-description = You have already submitted a request to delete your account. Your account will be deleted on { $date }. You may cancel the request until that time. -profile-settings-deleteAccount-cancelDelete = Cancel account deletion request +profile-account-deleteAccount-cancelDelete = Cancel account deletion request -profile-settings-deleteAccount-pages-deleteButton = Delete my account -profile-settings-deleteAccount-pages-cancel = Cancel -profile-settings-deleteAccount-pages-proceed = Proceed -profile-settings-deleteAccount-pages-done = Done +profile-account-deleteAccount-request = Request +profile-account-deleteAccount-cancel = Cancel +profile-account-deleteAccount-pages-deleteButton = Delete my account +profile-account-deleteAccount-pages-cancel = Cancel +profile-account-deleteAccount-pages-proceed = Proceed +profile-account-deleteAccount-pages-done = Done -profile-settings-deleteAccount-pages-descriptionHeader = Delete my account? -profile-settings-deleteAccount-pages-descriptionText = +profile-account-deleteAccount-pages-descriptionHeader = Delete my account? +profile-account-deleteAccount-pages-descriptionText = You are attempting to delete your account. This means: -profile-settings-deleteAccount-pages-allCommentsRemoved = +profile-account-deleteAccount-pages-allCommentsRemoved = All of your comments are removed from this site -profile-settings-deleteAccount-pages-allCommentsDeleted = +profile-account-deleteAccount-pages-allCommentsDeleted = All of your comments are deleted from our database -profile-settings-deleteAccount-pages-emailRemoved = +profile-account-deleteAccount-pages-emailRemoved = Your email address is removed from our system -profile-settings-deleteAccount-pages-whenHeader = Delete my account: When? -profile-settings-deleteAccount-pages-whenSec1Header = +profile-account-deleteAccount-pages-whenHeader = Delete my account: When? +profile-account-deleteAccount-pages-whenSec1Header = When will my account be deleted? -profile-settings-deleteAccount-pages-whenSec1Content = +profile-account-deleteAccount-pages-whenSec1Content = Your account will be deleted 24 hours after your request has been submitted. -profile-settings-deleteAccount-pages-whenSec2Header = +profile-account-deleteAccount-pages-whenSec2Header = Can I still write comments until my account is deleted? -profile-settings-deleteAccount-pages-whenSec2Content = +profile-account-deleteAccount-pages-whenSec2Content = No. Once you've requested account deletion, you can no longer write comments, reply to comments, or select reactions. -profile-settings-deleteAccount-pages-downloadCommentHeader = Download my comments? -profile-settings-deleteAccount-pages-downloadCommentsDesc = +profile-account-deleteAccount-pages-downloadCommentHeader = Download my comments? +profile-account-deleteAccount-pages-downloadCommentsDesc = Before your account is deleted, we recommend you download your comment history for your records. After your account is deleted, you will be unable to request your comment history. -profile-settings-deleteAccount-pages-downloadCommentsPath = +profile-account-deleteAccount-pages-downloadCommentsPath = My Profile > Download My Comment History -profile-settings-deleteAccount-pages-confirmHeader = Confirm account deletion? -profile-settings-deleteAccount-pages-confirmDescHeader = +profile-account-deleteAccount-pages-confirmHeader = Confirm account deletion? +profile-account-deleteAccount-pages-confirmDescHeader = Are you sure you want to delete your account? -profile-settings-deleteAccount-confirmDescContent = +profile-account-deleteAccount-confirmDescContent = To confirm you would like to delete your account please type in the following phrase into the text box below: -profile-settings-deleteAccount-pages-confirmPhraseLabel = +profile-account-deleteAccount-pages-confirmPhraseLabel = To confirm, type phrase below: -profile-settings-deleteAccount-pages-confirmPasswordLabel = +profile-account-deleteAccount-pages-confirmPasswordLabel = Enter your password: -profile-settings-deleteAccount-pages-completeHeader = Account deletion requested -profile-settings-deleteAccount-pages-completeDescript = +profile-account-deleteAccount-pages-completeHeader = Account deletion requested +profile-account-deleteAccount-pages-completeDescript = Your request has been submitted and a confirmation has been sent to the email address associated with your account. -profile-settings-deleteAccount-pages-completeTimeHeader = +profile-account-deleteAccount-pages-completeTimeHeader = Your account will be deleted on: { $date } -profile-settings-deleteAccount-pages-completeChangeYourMindHeader = Changed your mind? -profile-settings-deleteAccount-pages-completeSignIntoYourAccount = +profile-account-deleteAccount-pages-completeChangeYourMindHeader = Changed your mind? +profile-account-deleteAccount-pages-completeSignIntoYourAccount = Simply sign in to your account again before this time and select Cancel Account Deletion Request. -profile-settings-deleteAccount-pages-completeTellUsWhy = Tell us why. -profile-settings-deleteAccount-pages-completeWhyDeleteAccount = +profile-account-deleteAccount-pages-completeTellUsWhy = Tell us why. +profile-account-deleteAccount-pages-completeWhyDeleteAccount = We'd like to know why you chose to delete your account. Send us feedback on our comment system by emailing { $email }. +profile-account-changePassword-edit = Edit + ## Notifications - -profile-settings-notifications-emailNotifications = E-Mail Notifications -profile-settings-notifications-emailNotifications = Email Notifications -profile-settings-notifications-receiveWhen = Receive notifications when: -profile-settings-notifications-onReply = My comment receives a reply -profile-settings-notifications-onFeatured = My comment is featured -profile-settings-notifications-onStaffReplies = A staff member replies to my comment -profile-settings-notifications-onModeration = My pending comment has been reviewed -profile-settings-notifications-sendNotifications = Send Notifications: -profile-settings-notifications-sendNotifications-immediately = Immediately -profile-settings-notifications-sendNotifications-daily = Daily -profile-settings-notifications-sendNotifications-hourly = Hourly -profile-settings-notifications-updated = Your notification settings have been updated -profile-settings-notifications-button = Update Notification Settings +profile-notificationsTab = Notifications +profile-account-notifications-emailNotifications = E-Mail Notifications +profile-account-notifications-emailNotifications = Email Notifications +profile-account-notifications-receiveWhen = Receive notifications when: +profile-account-notifications-onReply = My comment receives a reply +profile-account-notifications-onFeatured = My comment is featured +profile-account-notifications-onStaffReplies = A staff member replies to my comment +profile-account-notifications-onModeration = My pending comment has been reviewed +profile-account-notifications-sendNotifications = Send Notifications: +profile-account-notifications-sendNotifications-immediately = Immediately +profile-account-notifications-sendNotifications-daily = Daily +profile-account-notifications-sendNotifications-hourly = Hourly +profile-account-notifications-updated = Your notification settings have been updated +profile-account-notifications-button = Update Notification Settings +profile-account-notifications-button-update = Update ## Report Comment Popover comments-reportPopover = @@ -342,10 +356,12 @@ configure-configureQuery-errorLoadingProfile = Error loading configure configure-configureQuery-storyNotFound = Story not found ## Change username +profile-changeUsername-username = Username profile-changeUsername-success = Your username has been successfully updated profile-changeUsername-edit = Edit profile-changeUsername-heading = Edit your username profile-changeUsername-desc = Change the username that will appear on all of your past and future comments. Usernames can be changed once every { framework-timeago-time }. +profile-changeUsername-desc-text = Change the username that will appear on all of your past and future comments. Usernames can be changed once every { framework-timeago-time }. profile-changeUsername-current = Current username profile-changeUsername-newUsername-label = New username profile-changeUsername-confirmNewUsername-label = Confirm new username @@ -420,3 +436,4 @@ profile-changeEmail-password-input = .placeholder = Password profile-changeEmail-cancel = Cancel profile-changeEmail-submit = Save +profile-changeEmail-email = Email diff --git a/src/locales/es/stream.ftl b/src/locales/es/stream.ftl index 519f8494c..e574180e2 100644 --- a/src/locales/es/stream.ftl +++ b/src/locales/es/stream.ftl @@ -114,7 +114,7 @@ comments-userPopover-ignore = Ignorar comments-userIgnorePopover-ignoreUser = ¿Ignorar a {$username}? comments-userIgnorePopover-description = Cuando ignora a un comentarista, se le ocultarán - todos los comentarios que escribieron en el sitio. + todos los comentarios que escribieron en el sitio. Puede deshacer esto más tarde desde Mi perfil. comments-userIgnorePopover-ignore = Ignorar comments-userIgnorePopover-cancel = Cancelar @@ -144,7 +144,6 @@ comments-featured-replies = Respuestas ## Profile Tab profile-myCommentsTab = Mis comentarios -profile-settingsTab = Ajustes ### Comment History profile-historyComment-viewConversation = Ver conversación @@ -156,12 +155,12 @@ profile-profileQuery-storyNotFound = Historia no encontrada profile-commentHistory-loadMore = Carga más ### Settings -profile-settings-ignoredCommenters = Comentaristas ignorados -profile-settings-description = +profile-account-ignoredCommenters = Comentaristas ignorados +profile-account-ignoredCommenters-description = Una vez que ignoras a alguien, todos sus comentarios están ocultos para ti. Los comentaristas que ignores podrán ver tus comentarios. -profile-settings-empty = Actualmente no estás ignorando a nadie -profile-settings-stopIgnoring = Deja de ignorar +profile-account-ignoredCommenters-empty = Actualmente no estás ignorando a nadie +profile-account-ignoredCommenters-stopIgnoring = Deja de ignorar ## Report Comment Popover @@ -215,7 +214,7 @@ configure-liveUpdates-description = configure-messageBox-title = Habilitar campo de mensaje para esta secuencia configure-messageBox-description = - Agregue un mensaje en la parte superior del campo de comentarios para sus lectores. + Agregue un mensaje en la parte superior del campo de comentarios para sus lectores. Use esto para plantear un tema, hacer una pregunta o hacer anuncios relacionados con esta historia. configure-messageBox-preview = Avance @@ -225,14 +224,14 @@ configure-messageBox-writeAMessage = Escribe un mensaje configure-closeStream-title = Cerrar los comentarios configure-closeStream-description = - Los comentarios están actualmente abiertos. Al cerrar los comentarios, + Los comentarios están actualmente abiertos. Al cerrar los comentarios, no se pueden enviar nuevos comentarios y todos los comentarios enviados anteriormente se seguirán mostrando. configure-closeStream-closeStream = Cerrar los comentarios configure-openStream-title = Abrir los comentarios configure-openStream-description = - Los comentarios están actualmente cerrados. + Los comentarios están actualmente cerrados. Al abrir los comentarios, se pueden enviar y mostrar nuevos comentarios. configure-openStream-openStream = Abrir los comentarios diff --git a/src/locales/nl-NL/stream.ftl b/src/locales/nl-NL/stream.ftl index 2ba4e3039..1d9f7bf99 100644 --- a/src/locales/nl-NL/stream.ftl +++ b/src/locales/nl-NL/stream.ftl @@ -113,8 +113,8 @@ comments-userPopover-ignore = Negeren comments-userIgnorePopover-ignoreUser = Negeer {$username}? comments-userIgnorePopover-description = - Wanneer u een gebruiker negeert, dan worden - alle reacties van deze gebruiker niet meer zichtbaar voor u. + Wanneer u een gebruiker negeert, dan worden + alle reacties van deze gebruiker niet meer zichtbaar voor u. U kunt dit later ongedaan maken in uw profiel. comments-userIgnorePopover-ignore = Negeren comments-userIgnorePopover-cancel = Annuleren @@ -144,7 +144,6 @@ comments-featured-replies = Antwoorden ## Profile Tab profile-myCommentsTab = Mijn reacties -profile-settingsTab = Instellingen ### Comment History profile-historyComment-viewConversation = Bekijk gesprek @@ -156,13 +155,13 @@ profile-profileQuery-storyNotFound = Bericht niet gevonden profile-commentHistory-loadMore = Meer laden ### Settings -profile-settings-ignoredCommenters = Genegeerde gebruikers -profile-settings-description = - Als je een gebruiker negeert, dan worden alle reacties van deze gebruiker +profile-account-ignoredCommenters = Genegeerde gebruikers +profile-account-ignoredCommenters-description = + Als je een gebruiker negeert, dan worden alle reacties van deze gebruiker niet meer zichtbaar voor jou. Gebruikers die jij negeert kunnen nog wel jouw reacties zien. -profile-settings-empty = U negeert niemand -profile-settings-stopIgnoring = Stop met negeren +profile-account-ignoredCommenters-empty = U negeert niemand +profile-account-ignoredCommenters-stopIgnoring = Stop met negeren ## Report Comment Popover @@ -216,7 +215,7 @@ configure-liveUpdates-description = configure-messageBox-title = Inschakelen bericht box voor deze reactiestroom configure-messageBox-description = - Voeg voor je lezers bovenaan de reactie box een bericht toe. Gebruik dit om een vraag te stellen of + Voeg voor je lezers bovenaan de reactie box een bericht toe. Gebruik dit om een vraag te stellen of een mededeling te doen gerelateerd aan dit bericht configure-messageBox-preview = Voorbeeld configure-messageBox-selectAnIcon = Selecteer een icon @@ -225,14 +224,14 @@ configure-messageBox-writeAMessage = Schrijf een bericht configure-closeStream-title = Sluit reactiestroom configure-closeStream-description = - Deze reactiestroom is open. Door het sluiten van deze reactiestroom - kunnen er geen nieuwe reacties toegevoegd worden + Deze reactiestroom is open. Door het sluiten van deze reactiestroom + kunnen er geen nieuwe reacties toegevoegd worden en alle reeds toegevoegde reacties zullen zichtbaar blijven. configure-closeStream-closeStream = Sluit reactiestroom configure-openStream-title = Open reactiestroom configure-openStream-description = - Deze reactiestroom is gesloten. Door het openen van deze reactiestroom + Deze reactiestroom is gesloten. Door het openen van deze reactiestroom kunnen nieuwe reacties worden toegevoegd en weergegeven. configure-openStream-openStream = Open reactiestroom diff --git a/src/locales/pt-BR/stream.ftl b/src/locales/pt-BR/stream.ftl index b064b9e95..9c473d7a8 100644 --- a/src/locales/pt-BR/stream.ftl +++ b/src/locales/pt-BR/stream.ftl @@ -114,7 +114,7 @@ comments-userPopover-ignore = Ignorar comments-userIgnorePopover-ignoreUser = Ignorar {$username}? comments-userIgnorePopover-description = Quando você ignora um usuário, todos os comentários -  que ele escreveu no site será escondido de você. Você +  que ele escreveu no site será escondido de você. Você pode desfazer isso mais tarde em Meu perfil. comments-userIgnorePopover-ignore = Ignorar comments-userIgnorePopover-cancel = Cancelar @@ -144,7 +144,6 @@ comments-featured-replies = Respostas ## Profile Tab profile-myCommentsTab = Meus comentários -profile-settingsTab = Configurações ### Comment History profile-historyComment-viewConversation = Ver conversa @@ -156,12 +155,12 @@ profile-profileQuery-storyNotFound = História não encontrada profile-commentHistory-loadMore = Carregar Mais ### Settings -profile-settings-ignoredCommenters = Usuários ignorados -profile-settings-description = +profile-account-ignoredCommenters = Usuários ignorados +profile-account-ignoredCommenters-description = Depois de ignorar alguém, todos os seus comentários ficam ocultos de você.   Usuários que você ignora ainda poderão ver seus comentários. -profile-settings-empty = Você não está ignorando ninguém -profile-settings-stopIgnoring = Parar de ignorar +profile-account-ignoredCommenters-empty = Você não está ignorando ninguém +profile-account-ignoredCommenters-stopIgnoring = Parar de ignorar ## Report Comment Popover