From ba9f034bfbba573e75000ed723cfb805cb83bec0 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Mon, 16 Apr 2018 17:37:08 -0600 Subject: [PATCH 01/44] Allow a user to change their own username --- models/action.js | 4 +- perms/reducers/mutation.js | 21 ++- services/users.js | 133 ++++++++++++------ test/server/graph/mutations/changeUsername.js | 2 +- test/server/services/users.js | 58 ++++++++ 5 files changed, 172 insertions(+), 46 deletions(-) diff --git a/models/action.js b/models/action.js index f3414f3ea..773bccf7e 100644 --- a/models/action.js +++ b/models/action.js @@ -22,8 +22,8 @@ const ActionSchema = new Schema( item_id: String, user_id: String, - // The element that summaries will additionally group on in addtion to their action_type, item_type, and - // item_id. + // The element that summaries will additionally group on in addition to + // their action_type, item_type, and item_id. group_id: String, // Additional metadata stored on the field. diff --git a/perms/reducers/mutation.js b/perms/reducers/mutation.js index d0841ef99..f063fe1c2 100644 --- a/perms/reducers/mutation.js +++ b/perms/reducers/mutation.js @@ -1,4 +1,5 @@ -const { isString } = require('lodash'); +const { get, isString } = require('lodash'); +const moment = require('moment'); const { check } = require('../utils'); const types = require('../constants'); @@ -12,8 +13,22 @@ module.exports = (user, perm) => { isString(user.password) && user.password.length > 0 ); - case types.CHANGE_USERNAME: - return user.status.username.status === 'REJECTED'; + + case types.CHANGE_USERNAME: { + // Only users who have their usernames rejected or those users who + // not changed their usernames within 14 days can change their usernames. + const now = moment(); + return ( + user.status.username.status === 'REJECTED' || + get(user, 'status.username.history', []) + .filter(({ status }) => status === 'CHANGED') + .every(({ created_at }) => + moment(created_at) + .add(14, 'days') + .isAfter(now) + ) + ); + } case types.SET_USERNAME: return user.status.username.status === 'UNSET'; diff --git a/services/users.js b/services/users.js index 657be737a..b860acfeb 100644 --- a/services/users.js +++ b/services/users.js @@ -1,4 +1,5 @@ const uuid = require('uuid'); +const moment = require('moment'); const bcrypt = require('bcryptjs'); const { ErrMaxRateLimit, @@ -234,57 +235,64 @@ class Users { return user; } - static async _setUsername( - id, - username, - fromStatus, - toStatus, - assignedBy, - resetAllowed = false - ) { + static async setUsername(id, username, assignedBy) { try { + const oldestEditTime = moment().subtract(14, 'days'); + + // A username can be set if: + // + // - The previous status was 'UNSET' + // - The username has not been changed within the last 14 days. const query = { id, - 'status.username.status': fromStatus, - }; - if (!resetAllowed) { - query.username = { $ne: username }; - } - - let user = await User.findOneAndUpdate( - query, - { - $set: { - username, - lowercaseUsername: username.toLowerCase(), - 'status.username.status': toStatus, + $or: [ + { + 'status.username.status': 'UNSET', }, - $push: { - 'status.username.history': { - status: toStatus, - assigned_by: assignedBy, - created_at: Date.now(), + { + 'status.username.status': { $in: ['APPROVED', 'SET'] }, + 'status.username.history.created_at': { + $not: { + $gte: oldestEditTime, + }, }, }, + ], + }; + + const update = { + $set: { + username, + lowercaseUsername: username.toLowerCase(), + 'status.username.status': 'SET', }, - { - new: true, - } - ); + $push: { + 'status.username.history': { + status: 'SET', + assigned_by: assignedBy, + created_at: Date.now(), + }, + }, + }; + + let user = await User.findOneAndUpdate(query, update, { + new: true, + }); if (!user) { user = await Users.findById(id); if (user === null) { throw new ErrNotFound(); } - if (user.status.username.status !== fromStatus) { + if ( + !['UNSET', 'APPROVED', 'SET'].includes(user.status.username.status) || + !user.status.username.history.every(({ created_at }) => + oldestEditTime.isAfter(created_at) + ) + ) { throw new ErrPermissionUpdateUsername(); } - if (!resetAllowed && user.username === username) { - throw new ErrSameUsernameProvided(); - } - throw new Error('edit username failed for an unexpected reason'); } @@ -298,12 +306,57 @@ class Users { } } - static async setUsername(id, username, assignedBy) { - return Users._setUsername(id, username, 'UNSET', 'SET', assignedBy, true); - } - static async changeUsername(id, username, assignedBy) { - return Users._setUsername(id, username, 'REJECTED', 'CHANGED', assignedBy); + try { + const query = { + id, + username: { $ne: username }, + 'status.username.status': 'REJECTED', + }; + + const update = { + $set: { + username, + lowercaseUsername: username.toLowerCase(), + 'status.username.status': 'CHANGED', + }, + $push: { + 'status.username.history': { + status: 'CHANGED', + assigned_by: assignedBy, + created_at: Date.now(), + }, + }, + }; + + let user = await User.findOneAndUpdate(query, update, { + new: true, + }); + if (!user) { + user = await Users.findById(id); + if (user === null) { + throw new ErrNotFound(); + } + + if (user.status.username.status !== 'REJECTED') { + throw new ErrPermissionUpdateUsername(); + } + + if (user.username === username) { + throw new ErrSameUsernameProvided(); + } + + throw new Error('edit username failed for an unexpected reason'); + } + + return user; + } catch (err) { + if (err.code === 11000) { + throw new ErrUsernameTaken(); + } + + throw err; + } } /** diff --git a/test/server/graph/mutations/changeUsername.js b/test/server/graph/mutations/changeUsername.js index eaff85434..a5c3daed8 100644 --- a/test/server/graph/mutations/changeUsername.js +++ b/test/server/graph/mutations/changeUsername.js @@ -89,7 +89,7 @@ describe('graph.mutations.changeUsername', () => { expect(res.data.changeUsername.errors).to.have.length(1); expect(res.data.changeUsername.errors[0]).to.have.property( 'translation_key', - 'NOT_AUTHORIZED' + 'EDIT_USERNAME_NOT_AUTHORIZED' ); // Set the user to the desired status. diff --git a/test/server/services/users.js b/test/server/services/users.js index e8a0172f7..a7d7475e9 100644 --- a/test/server/services/users.js +++ b/test/server/services/users.js @@ -2,6 +2,8 @@ const UsersService = require('../../../services/users'); const SettingsService = require('../../../services/settings'); const mailer = require('../../../services/mailer'); const Context = require('../../../graph/context'); +const timekeeper = require('timekeeper'); +const moment = require('moment'); const chai = require('chai'); chai.use(require('chai-as-promised')); @@ -303,6 +305,62 @@ describe('services.UsersService', () => { } }); }); + + if (func === 'setUsername') { + it('should let a user set their username from UNSET', async () => { + const user = mockUsers[0]; + + // Set the user to the desired status. + await UsersService.setUsernameStatus(user.id, 'UNSET'); + await UsersService.setUsername(user.id, 'new_username', null); + }); + + describe('time based', () => { + afterEach(() => { + timekeeper.reset(); + }); + + ['SET', 'APPROVED'].forEach(status => { + it(`should not allow users to change their username if it was changed within 14 of today from ${status}`, async () => { + const user = mockUsers[0]; + + // Set the user to the desired status. + await UsersService.setUsernameStatus(user.id, status); + + timekeeper.travel( + moment() + .add(5, 'days') + .toDate() + ); + + try { + await UsersService.setUsername(user.id, 'new_username', null); + throw new Error('edit was processed successfully'); + } catch (err) { + expect(err).have.property( + 'translation_key', + 'EDIT_USERNAME_NOT_AUTHORIZED' + ); + } + }); + + it(`allows users to change their username if it was changed 14 days before today from ${status}`, async () => { + const user = mockUsers[0]; + + // Set the user to the desired status. + await UsersService.setUsernameStatus(user.id, status); + + timekeeper.travel( + moment() + .add(15, 'days') + .toDate() + ); + + await UsersService.setUsername(user.id, 'new_username', null); + }); + }); + }); + } }); describe('#isValidUsername', () => { From b60e62f9769bf78f47d09d684d69180537bb624c Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 19 Apr 2018 09:21:12 -0600 Subject: [PATCH 02/44] small fixes for db logic --- services/users.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/users.js b/services/users.js index b860acfeb..a3301be10 100644 --- a/services/users.js +++ b/services/users.js @@ -237,7 +237,9 @@ class Users { static async setUsername(id, username, assignedBy) { try { - const oldestEditTime = moment().subtract(14, 'days'); + const oldestEditTime = moment() + .subtract(14, 'days') + .toDate(); // A username can be set if: // @@ -252,9 +254,7 @@ class Users { { 'status.username.status': { $in: ['APPROVED', 'SET'] }, 'status.username.history.created_at': { - $not: { - $gte: oldestEditTime, - }, + $lte: oldestEditTime, }, }, ], From 15817712c07af7d22d9082d98c81e37c3f4aa3c3 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 24 Apr 2018 13:58:28 -0300 Subject: [PATCH 03/44] Introducing profileHeader slot --- .../src/tabs/profile/components/Profile.js | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/profile/components/Profile.js b/client/coral-embed-stream/src/tabs/profile/components/Profile.js index 0bc90be0a..e73ebe455 100644 --- a/client/coral-embed-stream/src/tabs/profile/components/Profile.js +++ b/client/coral-embed-stream/src/tabs/profile/components/Profile.js @@ -4,13 +4,31 @@ import Slot from 'coral-framework/components/Slot'; import styles from './Profile.css'; import TabPanel from '../containers/TabPanel'; +const DefaultProfileHeader = ({ username, emailAddress }) => ( +
+

{username}

+ {emailAddress ?

{emailAddress}

: null} +
+); + +DefaultProfileHeader.propTypes = { + username: PropTypes.string, + emailAddress: PropTypes.string, +}; + const Profile = ({ username, emailAddress, root, slotPassthrough }) => { return (
-
-

{username}

- {emailAddress ?

{emailAddress}

: null} -
+
From 89114ecd13aad5fde9b19eae618bc6ec2daabe56 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 24 Apr 2018 14:13:24 -0300 Subject: [PATCH 04/44] Adding withChangeUsername to plugin hocs, wip and more --- plugin-api/beta/client/hocs/index.js | 1 + plugins/talk-plugin-auth/client/index.js | 2 + .../components/ChangeUsername.css | 20 ++++++++ .../components/ChangeUsername.js | 51 +++++++++++++++++++ .../containers/ChangeUsername.js | 12 +++++ 5 files changed, 86 insertions(+) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js diff --git a/plugin-api/beta/client/hocs/index.js b/plugin-api/beta/client/hocs/index.js index 41ede8445..d7ca5fce9 100644 --- a/plugin-api/beta/client/hocs/index.js +++ b/plugin-api/beta/client/hocs/index.js @@ -26,5 +26,6 @@ export { withStopIgnoringUser, withSetCommentStatus, withChangePassword, + withChangeUsername, } from 'coral-framework/graphql/mutations'; export { compose } from 'recompose'; diff --git a/plugins/talk-plugin-auth/client/index.js b/plugins/talk-plugin-auth/client/index.js index 039f0f936..8fedb8033 100644 --- a/plugins/talk-plugin-auth/client/index.js +++ b/plugins/talk-plugin-auth/client/index.js @@ -5,6 +5,7 @@ import translations from './translations.yml'; import Login from './login/containers/Main'; import reducer from './login/reducer'; import ChangePassword from './profile-settings/containers/ChangePassword'; +import ChangeUsername from './profile-settings/containers/ChangeUsername'; export default { reducer, @@ -12,6 +13,7 @@ export default { slots: { stream: [UserBox, SignInButton, SetUsernameDialog], login: [Login], + profileHeader: [ChangeUsername], profileSettings: [ChangePassword], }, }; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css new file mode 100644 index 000000000..c28cc163c --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css @@ -0,0 +1,20 @@ +.container { + margin-bottom: 20px; +} + +.email { + margin: 0; +} + +.username { + margin-bottom: 4px; +} + +.actions { + position: absolute; + top: 10px; + right: 10px; + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js new file mode 100644 index 000000000..59eadb1c4 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -0,0 +1,51 @@ +import React from 'react'; +import cn from 'classnames'; +import PropTypes from 'prop-types'; +import styles from './ChangeUsername.css'; +import { Button } from 'plugin-api/beta/client/components/ui'; + +const initialState = { + editing: false, +}; + +class ChangeUsername extends React.Component { + state = initialState; + + render() { + const { username, emailAddress } = this.props; + return ( +
+
+

{username}

+ {emailAddress ?

{emailAddress}

: null} +
+
+ + + Cancel + +
+
+ +
+
+ ); + } +} + +ChangeUsername.propTypes = { + changeUsername: PropTypes.func.isRequired, + username: PropTypes.string, + emailAddress: PropTypes.string, +}; + +export default ChangeUsername; diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js new file mode 100644 index 000000000..87e1e18b5 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js @@ -0,0 +1,12 @@ +import { compose } from 'react-apollo'; +import { bindActionCreators } from 'redux'; +import { connect } from 'plugin-api/beta/client/hocs'; +import ChangeUsername from '../components/ChangeUsername'; +import { notify } from 'coral-framework/actions/notification'; +import { withChangeUsername } from 'plugin-api/beta/client/hocs'; + +const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); + +export default compose(connect(null, mapDispatchToProps), withChangeUsername)( + ChangeUsername +); From 3bd2d0b3fcfd89e63c2f62cb0a2bcf91262d2ab2 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Tue, 24 Apr 2018 17:17:57 -0400 Subject: [PATCH 05/44] Small fix --- docs/source/03-03-product-guide-moderator-features.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/03-03-product-guide-moderator-features.md b/docs/source/03-03-product-guide-moderator-features.md index 9fbda6a18..abb2c454a 100644 --- a/docs/source/03-03-product-guide-moderator-features.md +++ b/docs/source/03-03-product-guide-moderator-features.md @@ -170,8 +170,9 @@ moderators. All your team and commenters show in the People sub-tab. From here, you can manage your team members’ roles (Admins, Moderators, Staff), as well as search -for commenters and take action on them (e.g. Ban/Un-ban, Suspend, etc.). ### -Configure +for commenters and take action on them (e.g. Ban/Un-ban, Suspend, etc.). + +### Configure See [Configuring Talk](/talk/configuring-talk/). From 2bc6687957214611a22fc85aaa1d74cf71eba710 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Wed, 25 Apr 2018 11:09:54 -0400 Subject: [PATCH 06/44] Use email vs e-mail --- locales/en.yml | 8 ++++---- plugins/talk-plugin-auth/client/translations.yml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/locales/en.yml b/locales/en.yml index f8b9b9ce2..d7ad006cb 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -236,7 +236,7 @@ en: RATE_LIMIT_EXCEEDED: "Rate limit exceeded" USERNAME_IN_USE: "Username already in use" USERNAME_REQUIRED: "Must input a username" - EMAIL_NOT_VERIFIED: "E-mail address not verified" + EMAIL_NOT_VERIFIED: "Email address not verified" EDIT_WINDOW_ENDED: "You can no longer edit this comment. The time window to do so has expired." EDIT_USERNAME_NOT_AUTHORIZED: "You do not have permission to update your username." SAME_USERNAME_PROVIDED: "You must submit a different username." @@ -252,8 +252,8 @@ en: email: "Not a valid E-Mail" confirm_password: "Passwords don't match. Please check again" network_error: "Failed to connect to server. Check your internet connection and try again." - email_not_verified: "E-mail address {0} not verified." - email_password: "E-mail and/or password combination incorrect." + email_not_verified: "Email address {0} not verified." + email_password: "Email and/or password combination incorrect." organization_name: "Organization name must only contain letters or numbers." organization_contact_email: "Organization email is not valid." password: "Password must be at least 8 characters" @@ -441,7 +441,7 @@ en: title_reject: "We noticed you rejected a username" suspend_user: "Suspend User" yes_suspend: "Yes suspend" - email_message_reject: "Another member of the community recently flagged your username for review. Because of its content your user was rejected. This means you can no longer comment, like, or flag content until you rewrite your username. Please e-mail us if you have any questions or concerns." + email_message_reject: "Another member of the community recently flagged your username for review. Because of its content your user was rejected. This means you can no longer comment, like, or flag content until you rewrite your username. Please email us if you have any questions or concerns." write_message: "Write a message" send: Send thank_you: "We value your safety and feedback. A moderator will review your report." diff --git a/plugins/talk-plugin-auth/client/translations.yml b/plugins/talk-plugin-auth/client/translations.yml index 915aee1c7..73c10b867 100644 --- a/plugins/talk-plugin-auth/client/translations.yml +++ b/plugins/talk-plugin-auth/client/translations.yml @@ -58,7 +58,7 @@ da: sign_in: "Sign in" sign_in_to_join: "Sign in to join the conversation" or: "Or" - email: "E-mail Address" + email: "Email Address" password: "Password" forgot_your_pass: "Forgot your password?" need_an_account: "Need an account?" @@ -101,7 +101,7 @@ en: sign_in: "Sign in" sign_in_to_join: "Sign in to join the conversation" or: "Or" - email: "E-mail Address" + email: "Email Address" password: "Password" forgot_your_pass: "Forgot your password?" need_an_account: "Need an account?" @@ -342,7 +342,7 @@ pt_BR: sign_in: "Sign in" sign_in_to_join: "Sign in to join the conversation" or: "Or" - email: "E-mail Address" + email: "Email Address" password: "Password" forgot_your_pass: "Forgot your password?" need_an_account: "Need an account?" From 754b5c5fbb6216e8344e744a7fb10ba49e9af1e7 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 25 Apr 2018 12:20:51 -0300 Subject: [PATCH 07/44] Adding Dialog, styles and more --- .../components/ChangePassword.css | 2 +- .../components/ChangeUsername.css | 121 ++++++++++++- .../components/ChangeUsername.js | 170 +++++++++++++++--- .../components/ChangeUsernameDialog.css | 82 +++++++++ .../components/ChangeUsernameDialog.js | 57 ++++++ 5 files changed, 398 insertions(+), 34 deletions(-) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css index e94247ac1..6c7f9ae41 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css @@ -47,7 +47,7 @@ border: 1px solid #787d80; background-color: transparent; height: 30px; - font-size: 1em; + font-size: 0.9em; line-height: normal; } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css index c28cc163c..8ab9eb5cd 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css @@ -1,20 +1,123 @@ .container { margin-bottom: 20px; + display: flex; + position: relative; + color: #202020; + padding: 10px; + border-radius: 2px; + box-sizing: border-box; + justify-content: space-between; + + &.editing { + background-color: #EDEDED; + } } +.content { + flex-grow: 1; +} + +.actions { + flex-grow: 0; + display: flex; + flex-direction: column; + align-items: center; +} + .email { margin: 0; } -.username { +.username { margin-bottom: 4px; +} + +.button { + border: 1px solid #787d80; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; } -.actions { - position: absolute; - top: 10px; - right: 10px; - display: flex; - flex-direction: column; - align-items: center; -} \ No newline at end of file +.saveButton { + background-color: #3498DB; + border-color: #3498DB; + color: white; + + > i { + font-size: 17px; + } + + &:hover { + background-color: #399ee2; + color: white; + } + + &:disabled { + border-color: #e0e0e0; + + &:hover { + background-color: #e0e0e0; + color: #4f5c67; + cursor: default; + } + } +} + +.cancelButton { + color:#787D80; + margin-top: 6px; + font-size: 0.9em; + + &:hover { + cursor: pointer; + } +} + +.detailLabel { + border: solid 1px #787D80; + border-radius: 2px; + background-color: white; + height: 30px; + display: inline-block; + width: 230px; + display: flex; + + > .detailLabelIcon { + font-size: 1.2em; + padding: 0 5px; + color: #787D80; + line-height: 30px; + } + + &.disabled { + background-color: #E0E0E0; + } +} + +.detailValue { + background: transparent; + border: none; + font-size: 1em; + color: #000; + height: 30px; + outline: none; + flex: 1; +} + +.bottomText { + color: #474747; + font-size: 0.9em; + display: block; +} + +.detailList { + list-style: none; + margin: 0; + padding: 0; +} + +.detailItem { + margin-bottom: 8px; +} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index 59eadb1c4..42349e3e9 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -2,41 +2,163 @@ import React from 'react'; import cn from 'classnames'; import PropTypes from 'prop-types'; import styles from './ChangeUsername.css'; -import { Button } from 'plugin-api/beta/client/components/ui'; +import { Icon, Button } from 'plugin-api/beta/client/components/ui'; +import ChangeUsernameDialog from './ChangeUsernameDialog'; const initialState = { editing: false, + formData: {}, + showDialog: false, }; class ChangeUsername extends React.Component { state = initialState; + clearForm = () => { + this.setState(initialState); + }; + + enableEditing = () => { + this.setState({ + editing: true, + }); + }; + + disableEditing = () => { + this.setState({ + editing: false, + }); + }; + + cancel = () => { + this.clearForm(); + this.disableEditing(); + }; + + showDialog = () => { + this.setState({ + showDialog: true, + }); + }; + + onSave = async () => { + this.showDialog(); + // this.clearForm(); + // this.disableEditing(); + }; + + onChange = e => { + const { name, value } = e.target; + this.setState( + state => ({ + formData: { + ...state.formData, + [name]: value, + }, + }), + () => { + console.log(this.state.formData); + // Validation + // this.fieldValidation(value, type, name); + // // Perform equality validation if password fields have changed + // if (name === 'newPassword' || name === 'confirmNewPassword') { + // this.equalityValidation('newPassword', 'confirmNewPassword'); + // } + } + ); + }; + + closeDialog = () => { + this.setState({ + showDialog: false, + }); + }; + render() { const { username, emailAddress } = this.props; + const { editing } = this.state; + + console.log('loading xxxx'); + return ( -
-
-

{username}

- {emailAddress ?

{emailAddress}

: null} -
-
- - - Cancel - -
-
- -
+
+ + + {editing ? ( +
+
    +
  • + + + Usernames can be changed every 14 days + +
  • +
  • + +
  • +
+
+ ) : ( +
+

{username}

+ {emailAddress ? ( +

{emailAddress}

+ ) : null} +
+ )} + + {editing ? ( +
+ + + Cancel + +
+ ) : ( +
+ +
+ )}
); } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css new file mode 100644 index 000000000..b3c4524fe --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css @@ -0,0 +1,82 @@ +.dialog { + border: none; + box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2); + width: 320px; + top: 10px; + font-family: Helvetica, 'Helvetica Neue', Verdana, sans-serif; + font-size: 14px; + border-radius: 4px; + padding: 12px 20px; +} + +.close { + font-size: 20px; + line-height: 14px; + top: 10px; + right: 10px; + position: absolute; + display: block; + font-weight: bold; + color: #363636; + cursor: pointer; + + &:hover { + color: #6b6b6b; + } +} + +.title { + font-size: 1.3em; + margin-bottom: 8px; +} + +.description { + font-size: 1em; + line-height: 20px; + margin: 0; +} + +.item { + display: block; + color: #4C4C4D; + font-size: 1em; + margin-bottom: 2px; +} + +.bottomNote { + font-size: 0.9em; + line-height: 20px; +} + +.bottomActions { + text-align: right; +} + +.usernamesChange { + margin: 18px 0; +} + +.cancel { + border: 1px solid #787d80; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; + + &:hover { + background-color: #eaeaea; + } +} + +.confirmChanges { + background-color: #3498DB; + border-color: #3498DB; + color: white; + height: 30px; + font-size: 0.9em; + + &:hover { + background-color: #3ba3ec; + color: white; + } +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js new file mode 100644 index 000000000..e0c08ec3e --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js @@ -0,0 +1,57 @@ +import React from 'react'; +import cn from 'classnames'; +import styles from './ChangeUsernameDialog.css'; +import InputField from './InputField'; +import Form from './Form'; +import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; + +class ChangeUsernameDialog extends React.Component { + render() { + return ( + + + × + +

Confirm Username Change

+
+

+ You are attempting to change your username. Your new username will + appear on all of your past and future comments. +

+
+ + Old Username: {this.props.username} + + + New Username: {this.props.formData.newUsername} + +
+
+ + + Note: You will not be able to change your username again for 14 + days + + +
+
+ + +
+
+
+ ); + } +} + +export default ChangeUsernameDialog; From a79d71da7d78b634c8095303e4adfe03db8c967b Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 25 Apr 2018 12:53:03 -0300 Subject: [PATCH 08/44] Full functionality, needs translation --- .../components/ChangeUsername.css | 3 +- .../components/ChangeUsername.js | 11 +++--- .../components/ChangeUsernameDialog.css | 2 ++ .../components/ChangeUsernameDialog.js | 34 ++++++++++++++++++- .../components/ErrorMessage.css | 1 - .../components/InputField.css | 16 +++++++-- .../profile-settings/components/InputField.js | 14 ++++++-- 7 files changed, 68 insertions(+), 13 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css index 8ab9eb5cd..5b4631ecf 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css @@ -109,7 +109,6 @@ .bottomText { color: #474747; font-size: 0.9em; - display: block; } .detailList { @@ -119,5 +118,5 @@ } .detailItem { - margin-bottom: 8px; + margin-bottom: 12px; } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index 42349e3e9..a146ea5f9 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -43,8 +43,10 @@ class ChangeUsername extends React.Component { onSave = async () => { this.showDialog(); - // this.clearForm(); - // this.disableEditing(); + }; + + saveChanges = async () => { + // savechanges }; onChange = e => { @@ -78,8 +80,6 @@ class ChangeUsername extends React.Component { const { username, emailAddress } = this.props; const { editing } = this.state; - console.log('loading xxxx'); - return (
Save diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css index b3c4524fe..af681d596 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css @@ -46,6 +46,8 @@ .bottomNote { font-size: 0.9em; line-height: 20px; + padding-top: 10px; + display: block; } .bottomActions { diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js index e0c08ec3e..b337af007 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js @@ -6,6 +6,28 @@ import Form from './Form'; import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; class ChangeUsernameDialog extends React.Component { + state = { + showErrors: false, + }; + + showErrors = () => { + this.setState({ + showErrors: true, + }); + }; + + confirmChanges = async () => { + if (this.formHasError()) { + this.showErrors(); + } else { + // await this.props.saveChanges + this.props.closeDialog(); + } + }; + + formHasError = () => + this.props.formData.confirmNewUsername !== this.props.formData.newUsername; + render() { return ( Note: You will not be able to change your username again for 14 @@ -46,7 +73,12 @@ class ChangeUsernameDialog extends React.Component {
- +
diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css b/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css index d7a1b6d45..abcf692fe 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css @@ -1,6 +1,5 @@ .errorMsg { color: #FA4643; - padding-left: 4px; font-size: 0.9em; } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css index be25a44b9..b2648e116 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css @@ -7,6 +7,14 @@ display: flex; } +.columnDisplay { + flex-direction: column; + + .detailItemMessage { + padding: 4px 0 0; + } +} + .detailItemContent { min-width: 280px; } @@ -28,13 +36,17 @@ color: #979797; box-sizing: border-box; width: 100%; + + &.error { + border-color: #FA4643; + } } .detailItemMessage { flex-grow: 1; display: flex; align-items: center; - padding-left: 2px; + padding-left: 6px; padding-top: 16px; .warningIcon, .checkIcon { @@ -48,4 +60,4 @@ .warningIcon { color: #FA4643; -} +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js index ed9c394ee..5818bfd2c 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import cn from 'classnames'; import styles from './InputField.css'; import ErrorMessage from './ErrorMessage'; import { Icon } from 'plugin-api/beta/client/components/ui'; @@ -15,10 +16,16 @@ const InputField = ({ hasError = false, errorMsg = '', children, + columnDisplay = false, + showSuccess = true, }) => { return (
  • -
    +
    {!hasError && + showSuccess && value && } {hasError && showError && {errorMsg}}
    @@ -55,6 +63,8 @@ InputField.propTypes = { hasError: PropTypes.bool, errorMsg: PropTypes.string, children: PropTypes.node, + columnDisplay: PropTypes.bool, + showSuccess: PropTypes.bool, }; export default InputField; From aefac2056edb1037444a7f80b6f4a8b02cc85e95 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 25 Apr 2018 13:36:00 -0300 Subject: [PATCH 09/44] wip more validations --- .../components/ChangeUsername.js | 61 ++++++++++++++++--- .../components/ChangeUsernameDialog.js | 1 + .../profile-settings/components/InputField.js | 5 +- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index a146ea5f9..d9f2fc15d 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -4,11 +4,15 @@ import PropTypes from 'prop-types'; import styles from './ChangeUsername.css'; import { Icon, Button } from 'plugin-api/beta/client/components/ui'; import ChangeUsernameDialog from './ChangeUsernameDialog'; +import validate from 'coral-framework/helpers/validate'; +import errorMsj from 'coral-framework/helpers/error'; +import { t } from 'plugin-api/beta/client/services'; const initialState = { editing: false, - formData: {}, showDialog: false, + errors: {}, + formData: {}, }; class ChangeUsername extends React.Component { @@ -49,8 +53,50 @@ class ChangeUsername extends React.Component { // savechanges }; + fieldValidation = (value, type, name) => { + if (!value.length) { + this.addError({ + [name]: t('talk-plugin-auth.change_password.required_field'), + }); + } else if (!validate[type](value)) { + this.addError({ [name]: errorMsj[type] }); + } else { + this.removeError(name); + } + }; + + hasError = err => { + return Object.keys(this.state.errors).indexOf(err) !== -1; + }; + + addError = err => { + this.setState( + ({ errors }) => ({ + errors: { ...errors, ...err }, + }), + () => { + console.log(this.state); + } + ); + }; + + removeError = errKey => { + this.setState( + state => { + const { [errKey]: _, ...errors } = state.errors; + return { + errors, + }; + }, + () => { + console.log(this.state); + } + ); + }; + onChange = e => { - const { name, value } = e.target; + const { name, value, type, dataset: { validationType } } = e.target; + this.setState( state => ({ formData: { @@ -59,13 +105,9 @@ class ChangeUsername extends React.Component { }, }), () => { - console.log(this.state.formData); - // Validation - // this.fieldValidation(value, type, name); - // // Perform equality validation if password fields have changed - // if (name === 'newPassword' || name === 'confirmNewPassword') { - // this.equalityValidation('newPassword', 'confirmNewPassword'); - // } + const fieldType = !validationType ? type : validationType; + this.fieldValidation(value, fieldType, name); + // the username cannot be the same } ); }; @@ -103,6 +145,7 @@ class ChangeUsername extends React.Component { Note: You will not be able to change your username again for 14 diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js index 5818bfd2c..511b89227 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js @@ -18,6 +18,7 @@ const InputField = ({ children, columnDisplay = false, showSuccess = true, + validationType = '', }) => { return (
  • @@ -34,10 +35,11 @@ const InputField = ({ id={id} type={type} name={name} - className={cn(styles.detailValue, styles.error)} + className={cn(styles.detailValue, { [styles.error]: hasError })} onChange={onChange} value={value} autoComplete="off" + data-validation-type={validationType} />
    @@ -65,6 +67,7 @@ InputField.propTypes = { children: PropTypes.node, columnDisplay: PropTypes.bool, showSuccess: PropTypes.bool, + validationType: PropTypes.string, }; export default InputField; From dd9a9d5882577a8360f7e902d5aaba2034fe4224 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Wed, 25 Apr 2018 15:30:40 -0400 Subject: [PATCH 10/44] Remove refs to talk-plugin-profile-settings --- .gitignore | 1 - docs/source/api/slots.md | 3 +-- docs/source/integrating/configuring-comment-stream.md | 4 ---- docs/source/integrating/notifications.md | 4 ---- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index e8cb92653..0cab02aeb 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,6 @@ plugins/* !plugins/talk-plugin-notifications-digest-hourly !plugins/talk-plugin-offtopic !plugins/talk-plugin-permalink -!plugins/talk-plugin-profile-settings !plugins/talk-plugin-profile-data !plugins/talk-plugin-remember-sort !plugins/talk-plugin-respect diff --git a/docs/source/api/slots.md b/docs/source/api/slots.md index da57c0ad6..a2e7cc04d 100644 --- a/docs/source/api/slots.md +++ b/docs/source/api/slots.md @@ -33,8 +33,7 @@ By default, Talk has various plugins provided by default. We can see this in `pl "talk-plugin-sort-most-respected", "talk-plugin-sort-newest", "talk-plugin-sort-oldest", - "talk-plugin-viewing-options", - "talk-plugin-profile-settings" + "talk-plugin-viewing-options" ] } ``` diff --git a/docs/source/integrating/configuring-comment-stream.md b/docs/source/integrating/configuring-comment-stream.md index 110560de0..613535a13 100644 --- a/docs/source/integrating/configuring-comment-stream.md +++ b/docs/source/integrating/configuring-comment-stream.md @@ -65,10 +65,6 @@ First, you'll enable `talk-plugin-author-menu`, as this houses the Ignore button And then we will enable the Ignore User plugin: `talk-plugin-ignore-user`. -And finally, we will need to enable Profile Settings; this is the tab on My Profile > Settings where commenters can manage their Ignored Users list. - -`talk-plugin-profile-settings` - ### Featured Comments To enable the featuring of comments, you'll need to activate `talk-plugin-featured-comments`. If you would like the Featured Comments tab to be the default tab you land on for the stream, you will need to set the default tab ENV variable: diff --git a/docs/source/integrating/notifications.md b/docs/source/integrating/notifications.md index 470632907..a5f625083 100644 --- a/docs/source/integrating/notifications.md +++ b/docs/source/integrating/notifications.md @@ -36,10 +36,6 @@ Adding the `talk-plugin-notifications` plugin will also enable the `notification See https://github.com/coralproject/talk/blob/8b669a31c551a042f0f079d8cfc16825673eb8f0/plugins/talk-plugin-notifications-reply/index.js for an example. -### Commenter Notification Settings - -Note that notifications REQUIRE the `talk-plugin-profile-settings` plugin; this is where on My Profile commenters will enable and manage their notification settings. - ### Notification Categories Talk currently supports the following Notifications options out of the box: From 8f6691f7a4ea9448d55675fc74a5414f46ecfb0e Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 26 Apr 2018 11:15:18 -0300 Subject: [PATCH 11/44] InputField refactor --- .../components/ChangeUsername.js | 44 ++++++++----------- .../components/ChangeUsernameDialog.js | 12 ++--- .../components/InputField.css | 39 ++++++++++------ .../profile-settings/components/InputField.js | 41 ++++++++++++----- 4 files changed, 81 insertions(+), 55 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index d9f2fc15d..b5bd8916b 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -7,6 +7,7 @@ import ChangeUsernameDialog from './ChangeUsernameDialog'; import validate from 'coral-framework/helpers/validate'; import errorMsj from 'coral-framework/helpers/error'; import { t } from 'plugin-api/beta/client/services'; +import InputField from './InputField'; const initialState = { editing: false, @@ -139,34 +140,27 @@ class ChangeUsername extends React.Component { {editing ? (
      -
    • - + Usernames can be changed every 14 days -
    • -
    • - -
    • + +
    ) : ( diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js index d5e50b4e8..22c74bce3 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js @@ -7,18 +7,18 @@ import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; class ChangeUsernameDialog extends React.Component { state = { - showErrors: false, + showError: false, }; - showErrors = () => { + showError = () => { this.setState({ - showErrors: true, + showError: true, }); }; confirmChanges = async () => { if (this.formHasError()) { - this.showErrors(); + this.showError(); } else { // await this.props.saveChanges this.props.closeDialog(); @@ -59,9 +59,9 @@ class ChangeUsernameDialog extends React.Component { type="text" onChange={this.props.onChange} value={this.props.formData.confirmNewUsername} - hasError={this.formHasError() && this.state.showErrors} + hasError={this.formHasError() && this.state.showError} errorMsg={'Username does not match'} - showErrors={this.state.showErrors} + showError={this.state.showError} columnDisplay showSuccess={false} validationType="username" diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css index b2648e116..f76970045 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css @@ -16,7 +16,24 @@ } .detailItemContent { - min-width: 280px; + border: solid 1px #787D80; + border-radius: 2px; + background-color: white; + height: 30px; + display: inline-block; + width: 230px; + display: flex; + + > .detailIcon { + font-size: 1.2em; + padding: 0 5px; + color: #787D80; + line-height: 30px; + } + + &.disabled { + background-color: #E0E0E0; + } } .detailLabel { @@ -27,19 +44,13 @@ } .detailValue { - padding: 6px 2px; - border: solid 1px #979797; - display: block; - font-size: 1.1em; - border-radius: 2px; - background-color: #ffffff; - color: #979797; - box-sizing: border-box; - width: 100%; - - &.error { - border-color: #FA4643; - } + background: transparent; + border: none; + font-size: 1em; + color: #000; + height: 30px; + outline: none; + flex: 1; } .detailItemMessage { diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js index 511b89227..7fa9a368a 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js @@ -11,35 +11,53 @@ const InputField = ({ type = 'text', name = '', onChange = () => {}, - value = '', showError = true, hasError = false, errorMsg = '', children, columnDisplay = false, - showSuccess = true, + showSuccess = false, validationType = '', + icon = '', + value = '', + defaultValue = '', + disabled = false, }) => { + const inputValue = { + ...(value ? { value } : {}), + ...(defaultValue ? { defaultValue } : {}), + }; + return ( -
  • +
    -
    + {label && ( + )} +
    + {icon && }
    @@ -50,17 +68,20 @@ const InputField = ({
    {children} -
  • + ); }; InputField.propTypes = { - id: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - type: PropTypes.string.isRequired, + id: PropTypes.string, + disabled: PropTypes.boolean, + label: PropTypes.string, + type: PropTypes.string, name: PropTypes.string.isRequired, onChange: PropTypes.func, value: PropTypes.string, + defaultValue: PropTypes.string, + icon: PropTypes.string, showError: PropTypes.bool, hasError: PropTypes.bool, errorMsg: PropTypes.string, From 2db9489646a9f87de1a68d6c809ef4d9d3b2c2cc Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 26 Apr 2018 11:15:35 -0300 Subject: [PATCH 12/44] Adding translations --- .../components/ChangePassword.js | 5 +- .../components/ChangeUsername.js | 79 ++++--------------- .../components/ChangeUsernameDialog.js | 14 +++- .../profile-settings/components/Form.css | 5 -- .../profile-settings/components/Form.js | 16 ---- .../talk-plugin-auth/client/translations.yml | 7 ++ 6 files changed, 34 insertions(+), 92 deletions(-) delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/Form.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/Form.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js index 3479b5dd9..90940728d 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js @@ -7,7 +7,6 @@ import validate from 'coral-framework/helpers/validate'; import errorMsj from 'coral-framework/helpers/error'; import isEqual from 'lodash/isEqual'; import { t } from 'plugin-api/beta/client/services'; -import Form from './Form'; import InputField from './InputField'; import { getErrorMessages } from 'coral-framework/utils'; @@ -148,7 +147,7 @@ class ChangePassword extends React.Component { {t('talk-plugin-auth.change_password.change_password')} {editing && ( -
    + - + )} {editing ? (
    diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index b5bd8916b..4fcca70fd 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -2,17 +2,14 @@ import React from 'react'; import cn from 'classnames'; import PropTypes from 'prop-types'; import styles from './ChangeUsername.css'; -import { Icon, Button } from 'plugin-api/beta/client/components/ui'; +import { Button } from 'plugin-api/beta/client/components/ui'; import ChangeUsernameDialog from './ChangeUsernameDialog'; -import validate from 'coral-framework/helpers/validate'; -import errorMsj from 'coral-framework/helpers/error'; import { t } from 'plugin-api/beta/client/services'; import InputField from './InputField'; const initialState = { editing: false, showDialog: false, - errors: {}, formData: {}, }; @@ -54,63 +51,15 @@ class ChangeUsername extends React.Component { // savechanges }; - fieldValidation = (value, type, name) => { - if (!value.length) { - this.addError({ - [name]: t('talk-plugin-auth.change_password.required_field'), - }); - } else if (!validate[type](value)) { - this.addError({ [name]: errorMsj[type] }); - } else { - this.removeError(name); - } - }; - - hasError = err => { - return Object.keys(this.state.errors).indexOf(err) !== -1; - }; - - addError = err => { - this.setState( - ({ errors }) => ({ - errors: { ...errors, ...err }, - }), - () => { - console.log(this.state); - } - ); - }; - - removeError = errKey => { - this.setState( - state => { - const { [errKey]: _, ...errors } = state.errors; - return { - errors, - }; - }, - () => { - console.log(this.state); - } - ); - }; - onChange = e => { - const { name, value, type, dataset: { validationType } } = e.target; + const { name, value } = e.target; - this.setState( - state => ({ - formData: { - ...state.formData, - [name]: value, - }, - }), - () => { - const fieldType = !validationType ? type : validationType; - this.fieldValidation(value, fieldType, name); - // the username cannot be the same - } - ); + this.setState(state => ({ + formData: { + ...state.formData, + [name]: value, + }, + })); }; closeDialog = () => { @@ -139,7 +88,7 @@ class ChangeUsername extends React.Component { {editing ? (
    -
      +
      - Usernames can be changed every 14 days + {t('talk-plugin-auth.change_username.change_username_note')} -
    +
    ) : (
    @@ -180,10 +129,10 @@ class ChangeUsername extends React.Component { onClick={this.onSave} disabled={!this.state.formData.newUsername} > - Save + {t('talk-plugin-auth.change_username.save')} - Cancel + {t('talk-plugin-auth.change_username.cancel')}
    ) : ( @@ -193,7 +142,7 @@ class ChangeUsername extends React.Component { icon="settings" onClick={this.enableEditing} > - Edit Profile + {t('talk-plugin-auth.change_username.edit_profile')} )} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js index 22c74bce3..a561106c9 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js @@ -1,8 +1,8 @@ import React from 'react'; +import PropTypes from 'prop-types'; import cn from 'classnames'; import styles from './ChangeUsernameDialog.css'; import InputField from './InputField'; -import Form from './Form'; import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; class ChangeUsernameDialog extends React.Component { @@ -51,7 +51,7 @@ class ChangeUsernameDialog extends React.Component { New Username: {this.props.formData.newUsername} -
    + -
    +
    diff --git a/plugins/talk-plugin-auth/client/translations.yml b/plugins/talk-plugin-auth/client/translations.yml index 84dc4e320..0d05d45c5 100644 --- a/plugins/talk-plugin-auth/client/translations.yml +++ b/plugins/talk-plugin-auth/client/translations.yml @@ -145,6 +145,12 @@ en: save: "Save" edit_profile: "Edit Profile" cancel: "Cancel" + confirm_username_change: "Confirm Username Change" + description: "You are attempting to change your username. Your new username will appear on all of your past and future comments." + old_username: "Old Username" + new_username: "New Username" + bottom_note: "Note: You will not be able to change your username again for 14 days" + confirm_changes: "Confirm Changes" de: talk-plugin-auth: login: From ba7de6bf81f2cb96095a5a5061119451aee2fec8 Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 26 Apr 2018 11:25:40 -0300 Subject: [PATCH 14/44] Translations --- .../client/profile-settings/components/ChangeUsername.js | 5 ++++- .../profile-settings/components/ChangeUsernameDialog.js | 2 +- .../client/profile-settings/components/InputField.css | 4 ++++ .../client/profile-settings/components/InputField.js | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index 4fcca70fd..fbc8bfb1b 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -127,7 +127,10 @@ class ChangeUsername extends React.Component { className={cn(styles.button, styles.saveButton)} icon="save" onClick={this.onSave} - disabled={!this.state.formData.newUsername} + disabled={ + !this.state.formData.newUsername && + this.state.formData.newUsername !== username + } > {t('talk-plugin-auth.change_username.save')} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js index 244dba00a..5bcc43241 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js @@ -92,7 +92,7 @@ class ChangeUsernameDialog extends React.Component { ChangeUsernameDialog.propTypes = { closeDialog: PropTypes.func, - showDialog: PropTypes.func, + showDialog: PropTypes.bool, onChange: PropTypes.func, username: PropTypes.string, formData: PropTypes.object, diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css index f76970045..ff0b47cf1 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css @@ -31,6 +31,10 @@ line-height: 30px; } + &.error { + border: solid 2px #FA4643; + } + &.disabled { background-color: #E0E0E0; } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js index 7fa9a368a..34c314c20 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js @@ -74,7 +74,7 @@ const InputField = ({ InputField.propTypes = { id: PropTypes.string, - disabled: PropTypes.boolean, + disabled: PropTypes.bool, label: PropTypes.string, type: PropTypes.string, name: PropTypes.string.isRequired, From 8643b1fbf2b49dcc93b2307451c8e93a23b94375 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Thu, 26 Apr 2018 17:52:03 +0200 Subject: [PATCH 15/44] Decrease font-size and padding in Flag Comment popup a bit. --- client/coral-embed-stream/style/default.css | 4 ++-- client/coral-ui/components/PopupMenu.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index 98416d68d..b9330ba62 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -177,8 +177,8 @@ button.comment__action-button[disabled], } .talk-plugin-flags-popup-header { - font-weight: bolder; - font-size: 1.33rem; + font-weight: bold; + font-size: 1rem; margin-bottom: 10px; } diff --git a/client/coral-ui/components/PopupMenu.css b/client/coral-ui/components/PopupMenu.css index 35544fbad..e6a084736 100644 --- a/client/coral-ui/components/PopupMenu.css +++ b/client/coral-ui/components/PopupMenu.css @@ -9,7 +9,7 @@ box-sizing: border-box; background: white; border-radius: 3px; - padding: 20px 10px; + padding: 10px 10px; z-index: 300; right: 1%; } From ab02b1b6ca5ecce778f2f7bb785a34120c1a3c47 Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 26 Apr 2018 17:00:08 -0300 Subject: [PATCH 16/44] No empty username, no same username --- .../client/profile-settings/components/ChangeUsername.js | 5 ++--- .../client/profile-settings/components/InputField.css | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js index fbc8bfb1b..8423ed403 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -120,7 +120,6 @@ class ChangeUsername extends React.Component { ) : null} )} - {editing ? (
    +