From 2adec1bc344137ba2383b62820c70c30542658ec Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 18 Apr 2018 13:13:41 -0600 Subject: [PATCH 001/133] added deletion graph endpoints --- graph/mutators/user.js | 5 +- perms/constants/mutation.js | 2 +- perms/reducers/mutation.js | 1 + plugin-api/beta/server/getReactionConfig.js | 15 +--- plugins/talk-plugin-profile-data/package.json | 1 + .../server/connect.js | 88 ++++++++++++++++++- .../talk-plugin-profile-data/server/errors.js | 27 +++++- .../server/mutators.js | 64 ++++++++++++-- .../server/resolvers.js | 18 ++++ .../server/typeDefs.graphql | 38 ++++++++ 10 files changed, 235 insertions(+), 24 deletions(-) diff --git a/graph/mutators/user.js b/graph/mutators/user.js index 6c673111b7..0343e1f2e8 100644 --- a/graph/mutators/user.js +++ b/graph/mutators/user.js @@ -8,7 +8,7 @@ const { SET_USER_BAN_STATUS, SET_USER_SUSPENSION_STATUS, UPDATE_USER_ROLES, - DELETE_USER, + DELETE_OTHER_USER, } = require('../../perms/constants'); const setUserUsernameStatus = async (ctx, id, status) => { @@ -155,6 +155,7 @@ module.exports = ctx => { setUsername: () => Promise.reject(new ErrNotAuthorized()), stopIgnoringUser: () => Promise.reject(new ErrNotAuthorized()), del: () => Promise.reject(new ErrNotAuthorized()), + delSelf: () => Promise.reject(new ErrNotAuthorized()), }, }; @@ -191,7 +192,7 @@ module.exports = ctx => { setUserSuspensionStatus(ctx, id, until, message); } - if (ctx.user.can(DELETE_USER)) { + if (ctx.user.can(DELETE_OTHER_USER)) { mutators.User.del = id => delUser(ctx, id); } } diff --git a/perms/constants/mutation.js b/perms/constants/mutation.js index d2ebe73f19..dba126ceb0 100644 --- a/perms/constants/mutation.js +++ b/perms/constants/mutation.js @@ -18,5 +18,5 @@ module.exports = { UPDATE_ASSET_SETTINGS: 'UPDATE_ASSET_SETTINGS', UPDATE_ASSET_STATUS: 'UPDATE_ASSET_STATUS', UPDATE_SETTINGS: 'UPDATE_SETTINGS', - DELETE_USER: 'DELETE_USER', + DELETE_OTHER_USER: 'DELETE_OTHER_USER', }; diff --git a/perms/reducers/mutation.js b/perms/reducers/mutation.js index 73ee7ef28f..7e23b274bd 100644 --- a/perms/reducers/mutation.js +++ b/perms/reducers/mutation.js @@ -36,6 +36,7 @@ module.exports = (user, perm) => { case types.UPDATE_USER_ROLES: case types.CREATE_TOKEN: case types.REVOKE_TOKEN: + case types.DELETE_OTHER_USER: return check(user, ['ADMIN']); default: diff --git a/plugin-api/beta/server/getReactionConfig.js b/plugin-api/beta/server/getReactionConfig.js index da075d76cc..b6e0a5c1d3 100644 --- a/plugin-api/beta/server/getReactionConfig.js +++ b/plugin-api/beta/server/getReactionConfig.js @@ -2,24 +2,11 @@ const { SEARCH_OTHER_USERS } = require('../../../perms/constants'); const { ErrNotFound, ErrAlreadyExists } = require('../../../errors'); const pluralize = require('pluralize'); const sc = require('snake-case'); -// const { CREATE_MONGO_INDEXES } = require('../../../config'); function getReactionConfig(reaction) { + // Ensure that the reaction is a lowercase string. reaction = reaction.toLowerCase(); - // if (CREATE_MONGO_INDEXES) { - // // Create the index on the comment model based on the reaction config. - // CommentModel.collection.createIndex( - // { - // created_at: 1, - // [`action_counts.${sc(reaction)}`]: 1, - // }, - // { - // background: true, - // } - // ); - // } - const reactionPlural = pluralize(reaction); const Reaction = reaction.charAt(0).toUpperCase() + reaction.slice(1); const REACTION = reaction.toUpperCase(); diff --git a/plugins/talk-plugin-profile-data/package.json b/plugins/talk-plugin-profile-data/package.json index ed5a290506..4329aba7ef 100644 --- a/plugins/talk-plugin-profile-data/package.json +++ b/plugins/talk-plugin-profile-data/package.json @@ -7,6 +7,7 @@ "private": false, "dependencies": { "archiver": "^2.1.1", + "cron": "^1.3.0", "csv-stringify": "^3.0.0" } } diff --git a/plugins/talk-plugin-profile-data/server/connect.js b/plugins/talk-plugin-profile-data/server/connect.js index f09b2dc7b5..eab76828fb 100644 --- a/plugins/talk-plugin-profile-data/server/connect.js +++ b/plugins/talk-plugin-profile-data/server/connect.js @@ -1,7 +1,13 @@ const path = require('path'); +const moment = require('moment'); +const { CronJob } = require('cron'); module.exports = connectors => { - const { services: { Mailer } } = connectors; + const { + services: { Mailer }, + models: { User }, + graph: { Context }, + } = connectors; // Setup the mail templates. ['txt', 'html'].forEach(format => { @@ -11,4 +17,84 @@ module.exports = connectors => { format ); }); + + // Setup the cron job that will scan for accounts to delete every 30 minutes. + new CronJob({ + cronTime: '0,30 * * * *', + timeZone: 'America/New_York', + start: true, + runOnInit: true, + onTick: async () => { + // Create the context we'll use to perform user deletions. + const ctx = Context.forSystem(); + + // rescheduledDeletionDate is the date in the future that we'll set the + // user's account to be deleted on if this delete fails. + const rescheduledDeletionDate = moment() + .add(1, 'hours') + .toDate(); + + try { + // Keep running for each user we can pull. + while (true) { + // We'll find any user that has an account deletion date before now + // and update the user such that their deletion time is 1 hour from + // now. This will ensure that only one instance can pull the same + // user at a time, and if the delete fails, it will be retried an + // hour from now. If the deletion was successful, well, it can't be + // retried because the reference to the scheduledDeletionDate will + // get deleted along with the user. + const user = await User.findOneAndUpdate( + { + 'metadata.scheduledDeletionDate': { $lte: new Date() }, + }, + { + $set: { + 'metadata.scheduledDeletionDate': rescheduledDeletionDate, + }, + } + ); + if (!user) { + // There are no more users that meet the search criteria! We're + // done! + ctx.log.info('no more users are scheduled for deletion'); + break; + } + + ctx.log.info( + { + userID: user.id, + scheduledDeletionDate: user.metadata.scheduledDeletionDate, + }, + 'starting user delete' + ); + + // Delete the user using the existing graph call. + const { data, errors } = await ctx.graphql( + ` + mutation DeleteUser($user_id: ID!) { + delUser(id: $user_id) { + errors { + translation_key + } + } + } + `, + { user_id: user.id } + ); + if (errors) { + throw errors; + } + + if (data.errors) { + throw data.errors; + } + + ctx.log.info({ userID: user.id }, 'user was deleted successfully'); + } + } catch (err) { + ctx.log.error({ err }, 'could not handle user deletions'); + } + }, + }); }; diff --git a/plugins/talk-plugin-profile-data/server/errors.js b/plugins/talk-plugin-profile-data/server/errors.js index 6261ebe897..f205c1f6e9 100644 --- a/plugins/talk-plugin-profile-data/server/errors.js +++ b/plugins/talk-plugin-profile-data/server/errors.js @@ -15,4 +15,29 @@ class ErrDownloadToken extends TalkError { } } -module.exports = { ErrDownloadToken }; +// ErrDeletionAlreadyScheduled is returned when a user requests that their +// account get deleted when their account is already scheduled for deletion. +class ErrDeletionAlreadyScheduled extends TalkError { + constructor() { + super('Deletion is already scheduled', { + translation_key: 'DELETION_ALREADY_SCHEDULED', + status: 400, + }); + } +} +// ErrDeletionNotScheduled is returned when a user requests that their +// account deletion to be canceled when it was not scheduled for deletion. +class ErrDeletionNotScheduled extends TalkError { + constructor() { + super('Deletion was not scheduled', { + translation_key: 'DELETION_NOT_SCHEDULED', + status: 400, + }); + } +} + +module.exports = { + ErrDownloadToken, + ErrDeletionAlreadyScheduled, + ErrDeletionNotScheduled, +}; diff --git a/plugins/talk-plugin-profile-data/server/mutators.js b/plugins/talk-plugin-profile-data/server/mutators.js index 5a897a2e11..dafc7dc42b 100644 --- a/plugins/talk-plugin-profile-data/server/mutators.js +++ b/plugins/talk-plugin-profile-data/server/mutators.js @@ -1,6 +1,12 @@ +const { get } = require('lodash'); const moment = require('moment'); const uuid = require('uuid/v4'); const { DOWNLOAD_LINK_SUBJECT } = require('./constants'); +const { + ErrDeletionAlreadyScheduled, + ErrDeletionNotScheduled, +} = require('./errors'); +const { ErrNotAuthorized } = require('errors'); async function sendDownloadLink({ user, @@ -66,8 +72,56 @@ async function sendDownloadLink({ ); } -module.exports = ctx => ({ - User: { - requestDownloadLink: () => sendDownloadLink(ctx), - }, -}); +// requestDeletion will schedule the current user to have their account deleted +// by setting the `scheduledDeletionDate` on the user 12 hours from now. +async function requestDeletion({ user, connectors: { models: { User } } }) { + // Ensure the user doesn't already have a deletion scheduled. + if (get(user, 'metadata.scheduledDeletionDate')) { + throw new ErrDeletionAlreadyScheduled(); + } + + // Get the date in the future 12 hours from now. + const scheduledDeletionDate = moment() + .add(12, 'hours') + .toDate(); + + // Amend the scheduledDeletionDate on the user. + await User.update( + { id: user.id }, + { $set: { 'metadata.scheduledDeletionDate': scheduledDeletionDate } } + ); + + return scheduledDeletionDate; +} + +// cancelDeletion will unset the scheduled deletion date on the user account +// that is used to indicate that the user was scheduled for deletion. +async function cancelDeletion({ user, connectors: { models: { User } } }) { + // Ensure the user has a deletion scheduled. + if (!get(user, 'metadata.scheduledDeletionDate', null)) { + throw new ErrDeletionNotScheduled(); + } + + // Amend the scheduledDeletionDate on the user. + await User.update( + { id: user.id }, + { $unset: { 'metadata.scheduledDeletionDate': 1 } } + ); +} + +module.exports = ctx => + ctx.user + ? { + User: { + requestDownloadLink: () => sendDownloadLink(ctx), + requestDeletion: () => requestDeletion(ctx), + cancelDeletion: () => cancelDeletion(ctx), + }, + } + : { + User: { + requestDownloadLink: () => Promise.reject(new ErrNotAuthorized()), + requestDeletion: () => Promise.reject(new ErrNotAuthorized()), + cancelDeletion: () => Promise.reject(new ErrNotAuthorized()), + }, + }; diff --git a/plugins/talk-plugin-profile-data/server/resolvers.js b/plugins/talk-plugin-profile-data/server/resolvers.js index 691907f8c1..a90c617e20 100644 --- a/plugins/talk-plugin-profile-data/server/resolvers.js +++ b/plugins/talk-plugin-profile-data/server/resolvers.js @@ -5,6 +5,12 @@ module.exports = { requestDownloadLink: async (_, args, { mutators: { User } }) => { await User.requestDownloadLink(); }, + requestAccountDeletion: async (_, args, { mutators: { User } }) => ({ + scheduledDeletionDate: await User.requestDeletion(), + }), + cancelAccountDeletion: async (_, args, { mutators: { User } }) => { + await User.cancelDeletion(); + }, }, User: { lastAccountDownload: (user, args, { user: currentUser }) => { @@ -16,5 +22,17 @@ module.exports = { return get(user, 'metadata.lastAccountDownload', null); }, + scheduledDeletionDate: (user, args, { user: currentUser }) => { + // If the current user is not the requesting user, and the user is not + // an admin or a moderator, return nothing. + if ( + user.id !== currentUser.id && + !['ADMIN', 'MODERATOR'].includes(user.role) + ) { + return null; + } + + return get(user, 'metadata.scheduledDeletionDate', null); + }, }, }; diff --git a/plugins/talk-plugin-profile-data/server/typeDefs.graphql b/plugins/talk-plugin-profile-data/server/typeDefs.graphql index 0029111c32..c785fb2cc9 100644 --- a/plugins/talk-plugin-profile-data/server/typeDefs.graphql +++ b/plugins/talk-plugin-profile-data/server/typeDefs.graphql @@ -3,17 +3,55 @@ type User { # lastAccountDownload is the date that the user last requested a comment # download. lastAccountDownload: Date + + # scheduledDeletionDate is the data for which the user account will be deleted + # after. The account may be deleted up to half an hour after this date because + # the job responsible for deleting the scheduled account will only run once + # every half hour. + scheduledDeletionDate: Date } +# RequestDownloadLinkResponse contains the account download errors relating to +# the request for an account download. type RequestDownloadLinkResponse implements Response { # An array of errors relating to the mutation that occurred. errors: [UserError!] } +# RequestAccountDeletionResponse contains the account deletion schedule errors +# relating to schedulding an account for deletion. +type RequestAccountDeletionResponse implements Response { + + # scheduledDeletionDate is the data for which the user account will be deleted + # after. The account may be deleted up to half an hour after this date because + # the job responsible for deleting the scheduled account will only run once + # every half hour. + scheduledDeletionDate: Date + + # An array of errors relating to the mutation that occurred. + errors: [UserError!] +} + +# CancelAccountDeletionResponse contains the account deletion errors relating to +# canceling an account deletion that was scheduled. +type CancelAccountDeletionResponse implements Response { + + # An array of errors relating to the mutation that occurred. + errors: [UserError!] +} + type RootMutation { # requestDownloadLink will request a download link be sent to the primary # users email address. requestDownloadLink: RequestDownloadLinkResponse + + # requestAccountDeletion requests that the current account get deleted. The + # mutation will return the date that the account is scheduled to be deleted. + requestAccountDeletion: RequestAccountDeletionResponse + + # cancelAccountDeletion will cancel a pending account deletion that was + # previously scheduled. + cancelAccountDeletion: CancelAccountDeletionResponse } From 8e34fd1925fe23c745de480c773aa4bdab11af80 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 18 Apr 2018 17:22:39 -0600 Subject: [PATCH 002/133] implemented tombstoning --- .../src/tabs/stream/components/Comment.js | 11 +++- .../stream/components/CommentTombstone.js | 2 + client/coral-framework/utils/index.js | 8 +++ graph/mutators/user.js | 53 +++++++++++-------- graph/resolvers/comment.js | 6 ++- graph/typeDefs.graphql | 5 +- locales/en.yml | 1 + models/schema/comment.js | 8 ++- perms/constants/query.js | 1 + perms/reducers/query.js | 1 + services/migration/helpers.js | 10 +++- 11 files changed, 75 insertions(+), 31 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/components/Comment.js b/client/coral-embed-stream/src/tabs/stream/components/Comment.js index 5df119fbc6..e60756f392 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Comment.js +++ b/client/coral-embed-stream/src/tabs/stream/components/Comment.js @@ -27,6 +27,7 @@ import { getActionSummary, iPerformedThisAction, isCommentActive, + isCommentDeleted, getShallowChanges, } from 'coral-framework/utils'; import t from 'coral-framework/services/i18n'; @@ -742,8 +743,14 @@ export default class Comment extends React.Component { return (
- {this.renderComment()} - {activeReplyBox === comment.id && this.renderReplyBox()} + {isCommentDeleted(comment) ? ( + + ) : ( +
+ {this.renderComment()} + {activeReplyBox === comment.id && this.renderReplyBox()} +
+ )} {this.renderRepliesContainer()}
); diff --git a/client/coral-embed-stream/src/tabs/stream/components/CommentTombstone.js b/client/coral-embed-stream/src/tabs/stream/components/CommentTombstone.js index a103698505..95184dffd6 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/CommentTombstone.js +++ b/client/coral-embed-stream/src/tabs/stream/components/CommentTombstone.js @@ -13,6 +13,8 @@ class CommentTombstone extends React.Component { return t('framework.comment_is_ignored'); case 'reject': return t('framework.comment_is_rejected'); + case 'deleted': + return t('framework.comment_is_deleted'); default: return t('framework.comment_is_hidden'); } diff --git a/client/coral-framework/utils/index.js b/client/coral-framework/utils/index.js index 66792b9b35..f69e83bdc8 100644 --- a/client/coral-framework/utils/index.js +++ b/client/coral-framework/utils/index.js @@ -1,6 +1,7 @@ import { gql } from 'react-apollo'; import t from 'coral-framework/services/i18n'; import union from 'lodash/union'; +import get from 'lodash/get'; import { capitalize } from 'coral-framework/helpers/strings'; import assignWith from 'lodash/assignWith'; import mapValues from 'lodash/mapValues'; @@ -221,6 +222,13 @@ export function isCommentActive(commentStatus) { return ['NONE', 'ACCEPTED'].indexOf(commentStatus) >= 0; } +export function isCommentDeleted(comment) { + return ( + get(comment, 'body', null) === null || + get(comment, 'deleted_at', null) !== null + ); +} + export function getShallowChanges(a, b) { return union(Object.keys(a), Object.keys(b)).filter(key => a[key] !== b[key]); } diff --git a/graph/mutators/user.js b/graph/mutators/user.js index 0343e1f2e8..f5bf3c9308 100644 --- a/graph/mutators/user.js +++ b/graph/mutators/user.js @@ -92,7 +92,7 @@ const delUser = async (ctx, id) => { updateBatchSize: 10000, }); - // Remove all actions against comments. + // Remove all actions against this users comments. await transformSingleWithCursor( Action.collection.find({ user_id: user.id, item_type: 'COMMENTS' }), actionDecrTransformer, @@ -111,34 +111,41 @@ const delUser = async (ctx, id) => { .setOptions({ multi: true }) .remove(); - // Removes all the user's reply counts on each of the comments that they - // have commented on. + // For each comment that the user has authored, purge the comment data from it + // and unset their id from those comments. await transformSingleWithCursor( - Comment.collection.aggregate([ - { $match: { author_id: user.id } }, - { - $group: { - _id: '$parent_id', - count: { $sum: 1 }, - }, - }, - ]), - ({ _id: parent_id, count }) => ({ - query: { id: parent_id }, - update: { - $inc: { - reply_count: -1 * count, - }, + Comment.collection.find({ author_id: user.id }), + ({ + id, + asset_id, + status, + parent_id, + reply_count, + created_at, + updated_at, + }) => ({ + query: { id }, + replace: { + id, + body: null, + body_history: [], + asset_id, + author_id: null, + status_history: [], + status, + parent_id, + reply_count, + action_counts: {}, + tags: [], + metadata: {}, + deleted_at: new Date(), + created_at, + updated_at, }, }), Comment ); - // Remove all the user's comments. - await Comment.where({ author_id: user.id }) - .setOptions({ multi: true }) - .remove(); - // Remove the user. await user.remove(); }; diff --git a/graph/resolvers/comment.js b/graph/resolvers/comment.js index 064835f8fe..e562c062c1 100644 --- a/graph/resolvers/comment.js +++ b/graph/resolvers/comment.js @@ -4,6 +4,7 @@ const { SEARCH_ACTIONS, SEARCH_COMMENT_STATUS_HISTORY, VIEW_BODY_HISTORY, + VIEW_COMMENT_DELETED_AT, } = require('../../perms/constants'); const { decorateWithTags, @@ -23,7 +24,9 @@ const Comment = { return Comments.get.load(parent_id); }, user({ author_id }, _, { loaders: { Users } }) { - return Users.getByID.load(author_id); + if (author_id) { + return Users.getByID.load(author_id); + } }, replies({ id, asset_id, reply_count }, { query }, { loaders: { Comments } }) { // Don't bother looking up replies if there aren't any there! @@ -83,6 +86,7 @@ decorateWithTags(Comment); decorateWithPermissionCheck(Comment, { actions: [SEARCH_ACTIONS], status_history: [SEARCH_COMMENT_STATUS_HISTORY], + deleted_at: [VIEW_COMMENT_DELETED_AT], }); // Protect privileged fields. diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql index f94322344b..9a03e2729d 100644 --- a/graph/typeDefs.graphql +++ b/graph/typeDefs.graphql @@ -503,7 +503,7 @@ type Comment { id: ID! # The actual comment data. - body: String! + body: String # The body history of the comment. Requires the `ADMIN` or `MODERATOR` role or # the author. @@ -537,6 +537,9 @@ type Comment { # The status history of the comment. Requires the `ADMIN` or `MODERATOR` role. status_history: [CommentStatusHistory!] + # The date that the comment was deleted at if it was. + deleted_at: Date + # The time when the comment was created created_at: Date! diff --git a/locales/en.yml b/locales/en.yml index 50845b96fb..f4c477710b 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -258,6 +258,7 @@ en: comment: comment comment_is_ignored: "This comment is hidden because you ignored this user." comment_is_rejected: "You have rejected this comment." + comment_is_deleted: "This comment was deleted." comment_is_hidden: "This comment is not available." comments: comments configure_stream: "Configure" diff --git a/models/schema/comment.js b/models/schema/comment.js index 6ef5434d56..985f5c3991 100644 --- a/models/schema/comment.js +++ b/models/schema/comment.js @@ -58,8 +58,6 @@ const Comment = new Schema( }, body: { type: String, - required: [true, 'The body is required.'], - minlength: 2, }, body_history: [BodyHistoryItemSchema], asset_id: String, @@ -89,6 +87,12 @@ const Comment = new Schema( // Tags are added by the self or by administrators. tags: [TagLinkSchema], + // deleted_at stores the date that the given comment was deleted. + deleted_at: { + type: Date, + default: null, + }, + // Additional metadata stored on the field. metadata: { default: {}, diff --git a/perms/constants/query.js b/perms/constants/query.js index 197c5d9f97..0c7f4024d6 100644 --- a/perms/constants/query.js +++ b/perms/constants/query.js @@ -11,4 +11,5 @@ module.exports = { VIEW_USER_ROLE: 'VIEW_USER_ROLE', VIEW_USER_EMAIL: 'VIEW_USER_EMAIL', VIEW_BODY_HISTORY: 'VIEW_BODY_HISTORY', + VIEW_COMMENT_DELETED_AT: 'VIEW_COMMENT_DELETED_AT', }; diff --git a/perms/reducers/query.js b/perms/reducers/query.js index ed507139da..5c8b17307b 100644 --- a/perms/reducers/query.js +++ b/perms/reducers/query.js @@ -14,6 +14,7 @@ module.exports = (user, perm) => { case types.VIEW_USER_ROLE: case types.VIEW_USER_EMAIL: case types.VIEW_BODY_HISTORY: + case types.VIEW_COMMENT_DELETED_AT: return check(user, ['ADMIN', 'MODERATOR']); case types.LIST_OWN_TOKENS: return check(user, ['ADMIN']); diff --git a/services/migration/helpers.js b/services/migration/helpers.js index 5eb33aadf7..49acc78aa5 100644 --- a/services/migration/helpers.js +++ b/services/migration/helpers.js @@ -10,8 +10,14 @@ const processUpdates = async (model, updates) => { // Create a new batch operation. const bulk = model.collection.initializeUnorderedBulkOp(); - for (const { query, update } of updates) { - bulk.find(query).updateOne(update); + for (const { query, update, replace } of updates) { + if (update) { + bulk.find(query).updateOne(update); + } else if (replace) { + bulk.find(query).replaceOne(replace); + } else { + throw new Error('invalid update object provided'); + } } // Execute the bulk update operation. From 68461308c68c1cedd3810bc6336daa9c65dd95b2 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 19 Apr 2018 13:37:14 -0600 Subject: [PATCH 003/133] pull ignored users from db --- graph/mutators/user.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/graph/mutators/user.js b/graph/mutators/user.js index f5bf3c9308..68112e7324 100644 --- a/graph/mutators/user.js +++ b/graph/mutators/user.js @@ -111,6 +111,15 @@ const delUser = async (ctx, id) => { .setOptions({ multi: true }) .remove(); + // Remove the user from all other user's ignore lists. + await User.update( + { ignoresUsers: user.id }, + { + $pull: { ignoresUsers: user.id }, + }, + { multi: true } + ); + // For each comment that the user has authored, purge the comment data from it // and unset their id from those comments. await transformSingleWithCursor( From 2e013c33ac1e834bbae94bd470f64cbf18390f21 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 19 Apr 2018 17:19:14 -0600 Subject: [PATCH 004/133] GDPR Email Support - Email and password can be used to create a new local profile - Email can be changed with accounts that already have a local profile --- plugins/talk-plugin-auth/README.md | 1 + plugins/talk-plugin-auth/index.js | 12 +- plugins/talk-plugin-auth/server/errors.js | 25 +++ plugins/talk-plugin-auth/server/mutators.js | 158 ++++++++++++++++++ plugins/talk-plugin-auth/server/resolvers.js | 10 ++ .../talk-plugin-auth/server/translations.yml | 8 + .../talk-plugin-auth/server/typeDefs.graphql | 47 ++++++ plugins/talk-plugin-auth/server/typeDefs.js | 7 + 8 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 plugins/talk-plugin-auth/server/errors.js create mode 100644 plugins/talk-plugin-auth/server/mutators.js create mode 100644 plugins/talk-plugin-auth/server/resolvers.js create mode 100644 plugins/talk-plugin-auth/server/translations.yml create mode 100644 plugins/talk-plugin-auth/server/typeDefs.graphql create mode 100644 plugins/talk-plugin-auth/server/typeDefs.js diff --git a/plugins/talk-plugin-auth/README.md b/plugins/talk-plugin-auth/README.md index fd5218365a..0a00db5ea2 100644 --- a/plugins/talk-plugin-auth/README.md +++ b/plugins/talk-plugin-auth/README.md @@ -7,6 +7,7 @@ plugin: default: true provides: - Client + - Server --- This provides the base plugin that is the basis for all auth based plugins that diff --git a/plugins/talk-plugin-auth/index.js b/plugins/talk-plugin-auth/index.js index f053ebf797..7e4ee6a3c3 100644 --- a/plugins/talk-plugin-auth/index.js +++ b/plugins/talk-plugin-auth/index.js @@ -1 +1,11 @@ -module.exports = {}; +const typeDefs = require('./server/typeDefs'); +const resolvers = require('./server/resolvers'); +const mutators = require('./server/mutators'); +const path = require('path'); + +module.exports = { + translations: path.join(__dirname, 'server', 'translations.yml'), + typeDefs, + mutators, + resolvers, +}; diff --git a/plugins/talk-plugin-auth/server/errors.js b/plugins/talk-plugin-auth/server/errors.js new file mode 100644 index 0000000000..808ceb3a6b --- /dev/null +++ b/plugins/talk-plugin-auth/server/errors.js @@ -0,0 +1,25 @@ +const { TalkError } = require('errors'); + +// ErrNoLocalProfile is returned when there is no existing local profile +// attached to a user. +class ErrNoLocalProfile extends TalkError { + constructor() { + super('No local profile associated with account', { + translation_key: 'NO_LOCAL_PROFILE', + status: 400, + }); + } +} + +// ErrLocalProfile is returned when a profile is already attached to a user and +// the user is trying to attach a new profile to it. +class ErrLocalProfile extends TalkError { + constructor() { + super('Local profile already associated with account', { + translation_key: 'LOCAL_PROFILE', + status: 400, + }); + } +} + +module.exports = { ErrLocalProfile, ErrNoLocalProfile }; diff --git a/plugins/talk-plugin-auth/server/mutators.js b/plugins/talk-plugin-auth/server/mutators.js new file mode 100644 index 0000000000..9fe0dd0db3 --- /dev/null +++ b/plugins/talk-plugin-auth/server/mutators.js @@ -0,0 +1,158 @@ +const { + ErrNotAuthorized, + ErrPasswordTooShort, + ErrNotFound, + ErrEmailTaken, +} = require('errors'); +const { ErrNoLocalProfile, ErrLocalProfile } = require('./errors'); +const { get } = require('lodash'); +const bcrypt = require('bcryptjs'); + +function hasLocalProfile(user) { + return Boolean( + get(user, 'profiles', []).find(({ provider }) => provider === 'local') + ); +} + +// updateUserEmailAddress will verify that the user has sent the correct +// password followed by executing the email change and notifying the emails +// about that change. +async function updateUserEmailAddress(ctx, email, confirmPassword) { + const { + user, + loaders: { Settings }, + connectors: { models: { User }, services: { Mailer, I18n, Users } }, + } = ctx; + + // Ensure that the user has a local profile associated with their account. + if (!hasLocalProfile(user)) { + throw new ErrNoLocalProfile(); + } + + // Ensure that the password provided matches what we have on file. + if (!await user.verifyPassword(confirmPassword)) { + throw new ErrNotAuthorized(); + } + + // Cleanup the email address. + email = email.toLowerCase().trim(); + + // Update the Users email address. + await User.update( + { + id: user.id, + profiles: { $elemMatch: { provider: 'local' } }, + }, + { + $set: { 'profiles.$.id': email }, + } + ); + + // Get some context for the email to be sent. + const { organizationContactEmail } = await Settings.load([ + 'organizationContactEmail', + ]); + + // Send off the email to the old email address that we have changed it. + await Mailer.send({ + email: user.firstEmail, + template: 'plain', + locals: { + body: I18n.t( + 'email.email_change_original.body', + user.email, + email, + organizationContactEmail + ), + }, + subject: I18n.t('email.email_change_original.subject'), + }); + + // Send off the email to the new email address that we need to verify the new + // address. + await Users.sendEmailConfirmation(user, email); +} + +// attachUserLocalAuth will attach a new local profile to an existing user. +async function attachUserLocalAuth(ctx, email, password) { + const { user, connectors: { models: { User }, services: { Users } } } = ctx; + + // Ensure that the current user doesn't already have a local account + // associated with them. + if (hasLocalProfile(user)) { + throw new ErrLocalProfile(); + } + + // Cleanup the email address. + email = email.toLowerCase().trim(); + + // Validate the password. + if (!password || password.length < 8) { + throw new ErrPasswordTooShort(); + } + + // Hash the new password. + const hashedPassword = await bcrypt.hash(password, 10); + + try { + // Associate the account with the user. + const updatedUser = await User.findOneAndUpdate( + { + id: user.id, + 'profiles.provider': { $ne: 'local' }, + }, + { + $push: { + profiles: { + provider: 'local', + id: email, + }, + }, + $set: { + password: hashedPassword, + }, + }, + { new: true } + ); + if (!updatedUser) { + const foundUser = await User.findOne({ id: user.id }); + if (foundUser === null) { + throw new ErrNotFound(); + } + + if (hasLocalProfile(foundUser)) { + throw new ErrLocalProfile(); + } + + throw new Error('local auth attachment failed due to unexpected reason'); + } + + // Send off the email to the new email address that we need to verify the + // new address. + await Users.sendEmailConfirmation(updatedUser, email); + } catch (err) { + if (err.code === 11000) { + throw new ErrEmailTaken(); + } + throw err; + } +} + +module.exports = ctx => { + const mutators = { + User: { + updateEmailAddress: () => Promise.reject(new ErrNotAuthorized()), + attachLocalAuth: () => Promise.reject(new ErrNotAuthorized()), + }, + }; + + if (ctx.user) { + mutators.User.updateEmailAddress = ({ email, confirmPassword }) => + updateUserEmailAddress(ctx, email, confirmPassword); + + mutators.User.attachLocalAuth = ({ email, password }) => + attachUserLocalAuth(ctx, email, password); + } + + return mutators; +}; diff --git a/plugins/talk-plugin-auth/server/resolvers.js b/plugins/talk-plugin-auth/server/resolvers.js new file mode 100644 index 0000000000..23815de00b --- /dev/null +++ b/plugins/talk-plugin-auth/server/resolvers.js @@ -0,0 +1,10 @@ +module.exports = { + RootMutation: { + updateEmailAddress: async (root, { input }, { mutators: { User } }) => { + await User.updateEmailAddress(input); + }, + attachLocalAuth: async (root, { input }, { mutators: { User } }) => { + await User.attachLocalAuth(input); + }, + }, +}; diff --git a/plugins/talk-plugin-auth/server/translations.yml b/plugins/talk-plugin-auth/server/translations.yml new file mode 100644 index 0000000000..d35b025251 --- /dev/null +++ b/plugins/talk-plugin-auth/server/translations.yml @@ -0,0 +1,8 @@ +en: + email: + email_change_original: + subject: Email change + body: Your email address has been changed from {0} to {1}. If you did not initiate this change, please contact {2}. + error: + NO_LOCAL_PROFILE: No existing email address is associated with this account. + LOCAL_PROFILE: An email address is already associated with this account. diff --git a/plugins/talk-plugin-auth/server/typeDefs.graphql b/plugins/talk-plugin-auth/server/typeDefs.graphql new file mode 100644 index 0000000000..6202e88426 --- /dev/null +++ b/plugins/talk-plugin-auth/server/typeDefs.graphql @@ -0,0 +1,47 @@ +# UpdateEmailAddressInput provides input for changing a users email address +# associated with their account. +input UpdateEmailAddressInput { + + # email is the Users email address that they want to update to. + email: String! + + # confirmPassword is the Users current password. + confirmPassword: String! +} + +# UpdateEmailAddressResponse is returned when you try to update a users email +# address. +type UpdateEmailAddressResponse implements Response { + + # An array of errors relating to the mutation that occurred. + errors: [UserError!] +} + +# AttachLocalAuthInput provides the input for attaching a new local +# authentication profile. +input AttachLocalAuthInput { + + # email is the Users email address that they want to add. + email: String! + + # password is the Users password that they want to add. + password: String! +} + +# AttachLocalAuthResponse returns any errors for when the user attempts to +# attach a new local authentication profile. +type AttachLocalAuthResponse implements Response { + + # An array of errors relating to the mutation that occurred. + errors: [UserError!] +} + +type RootMutation { + + # updateEmailAddress changes the email address of the current logged in user. + updateEmailAddress(input: UpdateEmailAddressInput!): UpdateEmailAddressResponse + + # attachLocalAuth will attach a new local authentication profile to an + # account. + attachLocalAuth(input: AttachLocalAuthInput!): AttachLocalAuthResponse +} diff --git a/plugins/talk-plugin-auth/server/typeDefs.js b/plugins/talk-plugin-auth/server/typeDefs.js new file mode 100644 index 0000000000..7ab1954e17 --- /dev/null +++ b/plugins/talk-plugin-auth/server/typeDefs.js @@ -0,0 +1,7 @@ +const fs = require('fs'); +const path = require('path'); + +module.exports = fs.readFileSync( + path.join(__dirname, 'typeDefs.graphql'), + 'utf8' +); From 7d644115d1fc79fe70886e04b1325918f40917ca Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 20 Apr 2018 13:11:35 -0600 Subject: [PATCH 005/133] cleanups --- plugins/talk-plugin-auth/server/mutators.js | 25 +++++++------------ .../talk-plugin-auth/server/translations.yml | 2 +- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/plugins/talk-plugin-auth/server/mutators.js b/plugins/talk-plugin-auth/server/mutators.js index 9fe0dd0db3..fb866b92c6 100644 --- a/plugins/talk-plugin-auth/server/mutators.js +++ b/plugins/talk-plugin-auth/server/mutators.js @@ -1,18 +1,12 @@ -const { - ErrNotAuthorized, - ErrPasswordTooShort, - ErrNotFound, - ErrEmailTaken, -} = require('errors'); +const { ErrNotAuthorized, ErrNotFound, ErrEmailTaken } = require('errors'); const { ErrNoLocalProfile, ErrLocalProfile } = require('./errors'); const { get } = require('lodash'); const bcrypt = require('bcryptjs'); -function hasLocalProfile(user) { - return Boolean( - get(user, 'profiles', []).find(({ provider }) => provider === 'local') - ); -} +// hasLocalProfile checks a user's profiles to see if they already have a local +// profile associated with their account. +const hasLocalProfile = user => + get(user, 'profiles', []).some(({ provider }) => provider === 'local'); // updateUserEmailAddress will verify that the user has sent the correct // password followed by executing the email change and notifying the emails @@ -60,7 +54,7 @@ async function updateUserEmailAddress(ctx, email, confirmPassword) { locals: { body: I18n.t( 'email.email_change_original.body', - user.email, + user.firstEmail, email, organizationContactEmail ), @@ -87,9 +81,7 @@ async function attachUserLocalAuth(ctx, email, password) { email = email.toLowerCase().trim(); // Validate the password. - if (!password || password.length < 8) { - throw new ErrPasswordTooShort(); - } + await Users.isValidPassword(password); // Hash the new password. const hashedPassword = await bcrypt.hash(password, 10); @@ -116,10 +108,11 @@ async function attachUserLocalAuth(ctx, email, password) { ); if (!updatedUser) { const foundUser = await User.findOne({ id: user.id }); - if (foundUser === null) { + if (!foundUser) { throw new ErrNotFound(); } + // Check to see if this was the result of a race. if (hasLocalProfile(foundUser)) { throw new ErrLocalProfile(); } diff --git a/plugins/talk-plugin-auth/server/translations.yml b/plugins/talk-plugin-auth/server/translations.yml index d35b025251..7df3d7b882 100644 --- a/plugins/talk-plugin-auth/server/translations.yml +++ b/plugins/talk-plugin-auth/server/translations.yml @@ -2,7 +2,7 @@ en: email: email_change_original: subject: Email change - body: Your email address has been changed from {0} to {1}. If you did not initiate this change, please contact {2}. + body: Your email address has been changed from {0} to {1}. If you did not initiate this change, please contact {2}. # TODO: update translation error: NO_LOCAL_PROFILE: No existing email address is associated with this account. LOCAL_PROFILE: An email address is already associated with this account. From 10d27357f49fcb688a2de9d54c3db87dca23faea Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 20 Apr 2018 13:17:57 -0600 Subject: [PATCH 006/133] reorganized --- .gitignore | 5 +++-- plugins.default.json | 11 +++++----- plugins/talk-plugin-auth/README.md | 1 - plugins/talk-plugin-auth/index.js | 12 +---------- plugins/talk-plugin-local-auth/README.md | 20 +++++++++++++++++++ plugins/talk-plugin-local-auth/index.js | 11 ++++++++++ .../server/errors.js | 0 .../server/mutators.js | 0 .../server/resolvers.js | 0 .../server/translations.yml | 0 .../server/typeDefs.graphql | 0 .../server/typeDefs.js | 0 12 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 plugins/talk-plugin-local-auth/README.md create mode 100644 plugins/talk-plugin-local-auth/index.js rename plugins/{talk-plugin-auth => talk-plugin-local-auth}/server/errors.js (100%) rename plugins/{talk-plugin-auth => talk-plugin-local-auth}/server/mutators.js (100%) rename plugins/{talk-plugin-auth => talk-plugin-local-auth}/server/resolvers.js (100%) rename plugins/{talk-plugin-auth => talk-plugin-local-auth}/server/translations.yml (100%) rename plugins/{talk-plugin-auth => talk-plugin-local-auth}/server/typeDefs.graphql (100%) rename plugins/{talk-plugin-auth => talk-plugin-local-auth}/server/typeDefs.js (100%) diff --git a/.gitignore b/.gitignore index e8cb92653e..9373b18930 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ plugins/* !plugins/talk-plugin-google-auth !plugins/talk-plugin-ignore-user !plugins/talk-plugin-like +!plugins/talk-plugin-local-auth !plugins/talk-plugin-love !plugins/talk-plugin-member-since !plugins/talk-plugin-mod @@ -50,10 +51,11 @@ 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-profile-settings !plugins/talk-plugin-remember-sort !plugins/talk-plugin-respect +!plugins/talk-plugin-rich-text !plugins/talk-plugin-slack-notifications !plugins/talk-plugin-sort-most-downvoted !plugins/talk-plugin-sort-most-liked @@ -67,7 +69,6 @@ plugins/* !plugins/talk-plugin-toxic-comments !plugins/talk-plugin-upvote !plugins/talk-plugin-viewing-options -!plugins/talk-plugin-rich-text **/node_modules/* yarn-error.log diff --git a/plugins.default.json b/plugins.default.json index e1011aa872..0fbc6e6587 100644 --- a/plugins.default.json +++ b/plugins.default.json @@ -1,9 +1,9 @@ { "server": [ - "talk-plugin-auth", "talk-plugin-featured-comments", - "talk-plugin-respect", - "talk-plugin-profile-data" + "talk-plugin-local-auth", + "talk-plugin-profile-data", + "talk-plugin-respect" ], "client": [ "talk-plugin-auth", @@ -11,15 +11,16 @@ "talk-plugin-featured-comments", "talk-plugin-flag-details", "talk-plugin-ignore-user", + "talk-plugin-local-auth", "talk-plugin-member-since", "talk-plugin-moderation-actions", "talk-plugin-permalink", + "talk-plugin-profile-data", "talk-plugin-respect", "talk-plugin-sort-most-replied", "talk-plugin-sort-most-respected", "talk-plugin-sort-newest", "talk-plugin-sort-oldest", - "talk-plugin-viewing-options", - "talk-plugin-profile-data" + "talk-plugin-viewing-options" ] } diff --git a/plugins/talk-plugin-auth/README.md b/plugins/talk-plugin-auth/README.md index 0a00db5ea2..fd5218365a 100644 --- a/plugins/talk-plugin-auth/README.md +++ b/plugins/talk-plugin-auth/README.md @@ -7,7 +7,6 @@ plugin: default: true provides: - Client - - Server --- This provides the base plugin that is the basis for all auth based plugins that diff --git a/plugins/talk-plugin-auth/index.js b/plugins/talk-plugin-auth/index.js index 7e4ee6a3c3..f053ebf797 100644 --- a/plugins/talk-plugin-auth/index.js +++ b/plugins/talk-plugin-auth/index.js @@ -1,11 +1 @@ -const typeDefs = require('./server/typeDefs'); -const resolvers = require('./server/resolvers'); -const mutators = require('./server/mutators'); -const path = require('path'); - -module.exports = { - translations: path.join(__dirname, 'server', 'translations.yml'), - typeDefs, - mutators, - resolvers, -}; +module.exports = {}; diff --git a/plugins/talk-plugin-local-auth/README.md b/plugins/talk-plugin-local-auth/README.md new file mode 100644 index 0000000000..ee5a6b8806 --- /dev/null +++ b/plugins/talk-plugin-local-auth/README.md @@ -0,0 +1,20 @@ +--- +title: talk-plugin-local-auth +permalink: /plugin/talk-plugin-local-auth/ +layout: plugin +plugin: + name: talk-plugin-local-auth + default: true + provides: + - Client + - Server +--- + +This plugin will eventually contain all the local authentication code that is +responsible for creating, resetting, and managing accounts provided locally +through an email and password based login. + +## Features + +- *Email Change*: Allows users to change their existing email address on their account. +- *Local Account Association*: Allows users that have signed up with an external auth strategy (such as Google) the ability to associate a email address and password for login. **Note: Existing users with external authentication will be prompted to setup a local account when they sign in and when new users create an account.** diff --git a/plugins/talk-plugin-local-auth/index.js b/plugins/talk-plugin-local-auth/index.js new file mode 100644 index 0000000000..7e4ee6a3c3 --- /dev/null +++ b/plugins/talk-plugin-local-auth/index.js @@ -0,0 +1,11 @@ +const typeDefs = require('./server/typeDefs'); +const resolvers = require('./server/resolvers'); +const mutators = require('./server/mutators'); +const path = require('path'); + +module.exports = { + translations: path.join(__dirname, 'server', 'translations.yml'), + typeDefs, + mutators, + resolvers, +}; diff --git a/plugins/talk-plugin-auth/server/errors.js b/plugins/talk-plugin-local-auth/server/errors.js similarity index 100% rename from plugins/talk-plugin-auth/server/errors.js rename to plugins/talk-plugin-local-auth/server/errors.js diff --git a/plugins/talk-plugin-auth/server/mutators.js b/plugins/talk-plugin-local-auth/server/mutators.js similarity index 100% rename from plugins/talk-plugin-auth/server/mutators.js rename to plugins/talk-plugin-local-auth/server/mutators.js diff --git a/plugins/talk-plugin-auth/server/resolvers.js b/plugins/talk-plugin-local-auth/server/resolvers.js similarity index 100% rename from plugins/talk-plugin-auth/server/resolvers.js rename to plugins/talk-plugin-local-auth/server/resolvers.js diff --git a/plugins/talk-plugin-auth/server/translations.yml b/plugins/talk-plugin-local-auth/server/translations.yml similarity index 100% rename from plugins/talk-plugin-auth/server/translations.yml rename to plugins/talk-plugin-local-auth/server/translations.yml diff --git a/plugins/talk-plugin-auth/server/typeDefs.graphql b/plugins/talk-plugin-local-auth/server/typeDefs.graphql similarity index 100% rename from plugins/talk-plugin-auth/server/typeDefs.graphql rename to plugins/talk-plugin-local-auth/server/typeDefs.graphql diff --git a/plugins/talk-plugin-auth/server/typeDefs.js b/plugins/talk-plugin-local-auth/server/typeDefs.js similarity index 100% rename from plugins/talk-plugin-auth/server/typeDefs.js rename to plugins/talk-plugin-local-auth/server/typeDefs.js From 8e21857a529bef586bcd3f2a1abb656a9bc740ec Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 20 Apr 2018 13:20:11 -0600 Subject: [PATCH 007/133] added new plugin to registry --- docs/source/_data/plugins.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/_data/plugins.yml b/docs/source/_data/plugins.yml index a5621b0d6e..35d88cb141 100644 --- a/docs/source/_data/plugins.yml +++ b/docs/source/_data/plugins.yml @@ -3,7 +3,12 @@ tags: - moderation - name: talk-plugin-auth - description: Enables internal authentication from Coral. + description: Enables internal sign-in authentication. + tags: + - default + - auth +- name: talk-plugin-local-auth + description: Enables email and password based authentication. tags: - default - auth From 94710261622363b4d3bdaa2531a59d7490793f3e Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 20 Apr 2018 13:20:55 -0600 Subject: [PATCH 008/133] Referenced new plugin --- docs/source/plugin/talk-plugin-local-auth.md | 1 + 1 file changed, 1 insertion(+) create mode 120000 docs/source/plugin/talk-plugin-local-auth.md diff --git a/docs/source/plugin/talk-plugin-local-auth.md b/docs/source/plugin/talk-plugin-local-auth.md new file mode 120000 index 0000000000..918f29118a --- /dev/null +++ b/docs/source/plugin/talk-plugin-local-auth.md @@ -0,0 +1 @@ +../../../plugins/talk-plugin-local-auth/README.md \ No newline at end of file From c27c60346e62482c1c303737c97c77d16dccd417 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 20 Apr 2018 13:27:03 -0600 Subject: [PATCH 009/133] fixed client building --- plugins/talk-plugin-local-auth/client/.eslintrc.json | 3 +++ plugins/talk-plugin-local-auth/client/index.js | 1 + 2 files changed, 4 insertions(+) create mode 100644 plugins/talk-plugin-local-auth/client/.eslintrc.json create mode 100644 plugins/talk-plugin-local-auth/client/index.js diff --git a/plugins/talk-plugin-local-auth/client/.eslintrc.json b/plugins/talk-plugin-local-auth/client/.eslintrc.json new file mode 100644 index 0000000000..c8a6db18aa --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "@coralproject/eslint-config-talk/client" +} diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js new file mode 100644 index 0000000000..ff8b4c5632 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -0,0 +1 @@ +export default {}; From b8d435fb07df7c57ee0bf693ff51525a5e513a6e Mon Sep 17 00:00:00 2001 From: Jero Date: Thu, 26 Apr 2018 18:29:25 -0300 Subject: [PATCH 010/133] Added missing spanish translations --- locales/es.yml | 123 +++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/locales/es.yml b/locales/es.yml index dd85b588ea..702f6b9e0b 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -16,26 +16,27 @@ es: send: "Enviar" notify_ban_headline: "Notificar al usuario de la suspensión" notify_ban_description: "Esto notificará al usuario por email que fueron suspendidos de la comunidad" - email_message_ban: "Dear {0},\n\nSomeone with access to your account has violated our community guidelines. As a result, your account has been banned. You will no longer be able to comment, like or report comments. if you think this has been done in error, please contact our community team." + email_message_ban: "Estimado/a {0},\n\nUsted o alguien con acceso a su cuenta a violado los lineamientos de nuestra comunidad. Como consecuencia de esto, su cuenta fue bloqueada. No podrá realizar ni reportar más comentarios. Si usted piensa que esto ha sido un error, por favor contáctese con nosotros." bio_offensive: "Esta biografia es ofensiva" cancel: Cancelar confirm_email: - click_to_confirm: "Click below to confirm your email address" - confirm: "Confirm" + click_to_confirm: "Haga click debajo para confirmar su dirección de email" + confirm: "Confirmar" password_reset: - set_new_password: "Change Your Password" - new_password: "New Password" - new_password_help: "Password must be at least 8 characters" - confirm_new_password: "Confirm New Password" - change_password: "Change Password" - characters_remaining: "carácteres restantes" + mail_sent: 'Si tiene una cuenta registrada, un enlace para resetear su clave ha sido enviado a esa dirección de correo.' + set_new_password: "Cambie su contraseña" + new_password: "Nueva contraseña" + new_password_help: "La contraseña debe tener al menos 8 caracteres" + confirm_new_password: "Confirme su nueva contraseña" + change_password: "Cambio de contraseña" + characters_remaining: "caracteres restantes" comment: anon: Anónimo - undo_reject: "Undo" + undo_reject: "Deshacer" ban_user: "Usuario Suspendido" comment: "Publicar un comentario" edited: Editado - flagged: reportado + flagged: Reportado view_context: "Ver contexto" comment_box: post: "Publicar" @@ -62,16 +63,16 @@ es: reactions: 'reacciones' story: 'Artículo' flagged_usernames: - notify_approved: '{0} approved username {1}' - notify_rejected: '{0} rejected username {1}' - notify_flagged: '{0} reported username {1}' - notify_changed: 'user {0} changed their username to {1}' + notify_approved: '{0} nombre de usuario aprobado {1}' + notify_rejected: '{0} nombre de usuario rechazado {1}' + notify_flagged: '{0} nombre de usuario reportado {1}' + notify_changed: 'El usuario {0} cambio su nombre de usuario por {1}' community: account_creation_date: "Fecha de creación de la cuenta" active: Activa admin: Administrator - ads_marketing: "This looks like an ad/marketing" - are_you_sure: "¿Estas segura que quieres suspender a {0}?" + ads_marketing: "Esto parece ser un ad/marketing" + are_you_sure: "¿Estás segura que quieres suspender a {0}?" ban_user: "¿Quieres suspender al Usuario?" banned: Suspendido banned_user: "Usuario Suspendido" @@ -193,10 +194,10 @@ es: minutes_plural: "minutos" email: suspended: - subject: "Your account has been suspended" + subject: "Su cuenta fue suspendida" banned: - subject: "Your account has been banned" - body: "In accordance with The Coral Project’s community guidelines, your account has been banned. You are now longer allowed to comment, flag or engage with our community." + subject: "Su cuenta fue bloqueada" + body: "De acuerdo con las guías de comunidad de The Coral Project, su cuenta a sido bloqueada. No podrá hacer comentarios, reportar o entrar en contacto con nuestra comunidad." confirm: has_been_requested: "Un correo de confirmación ha sido pedido para la siguiente cuenta:" to_confirm: "Para confirmar la cuenta, por favor visitar el siguiente enlace:" @@ -211,8 +212,8 @@ es: copy: "Copiar al portapapeles" error: COMMENT_PARENT_NOT_VISIBLE: "El comentario a la que estás contestando ha sido eliminado o no existe." - EMAIL_VERIFICATION_TOKEN_INVALID: "Email verification token is invalid." - PASSWORD_RESET_TOKEN_INVALID: "Your password reset link is invalid." + EMAIL_VERIFICATION_TOKEN_INVALID: "El token de verificación de su cuenta de correo es inválido." + PASSWORD_RESET_TOKEN_INVALID: "El enlace para resetear su clave es inválido." COMMENT_TOO_SHORT: "Tu comentario debe tener algo escrito" NOT_AUTHORIZED: "Acción no autorizada." NO_SPECIAL_CHARACTERS: "Los nombres pueden contener letras números y _" @@ -221,19 +222,19 @@ es: RATE_LIMIT_EXCEEDED: "Rate limit exceeded" USERNAME_IN_USE: "Este nombre ya está siendo usado." USERNAME_REQUIRED: "Debe ingresar un nombre" - EMAIL_NOT_VERIFIED: "E-mail address not verified" - EDIT_WINDOW_ENDED:: "No puedes editar este comentario. El tiempo de edición ha expirado." + EMAIL_NOT_VERIFIED: "La cuenta de email no ha sido verificada." + EDIT_WINDOW_ENDED: "No puedes editar este comentario. El tiempo de edición ha expirado." EDIT_USERNAME_NOT_AUTHORIZED: "No tiene permiso para editar el nombre de usuario." - SAME_USERNAME_PROVIDED: "You must submit a different username." + SAME_USERNAME_PROVIDED: "Debe proporcinar un nombre de usuario diferente." EMAIL_IN_USE: "Este correo se encuentra en uso" EMAIL_REQUIRED: "Se requiere un correo" LOGIN_MAXIMUM_EXCEEDED: "Ha realizado demasiados intentos fallidos de usar la contraseña. Por favor espere." PASSWORD_REQUIRED: "Debe ingresar la contraseña" COMMENTING_CLOSED: "Los comentarios ya estan cerrados" NOT_FOUND: "Recurso no encontrado" - ALREADY_EXISTS: "Resource already exists" + ALREADY_EXISTS: "El recurso ya existe" INVALID_ASSET_URL: "La URL del articulo no es valida" - CANNOT_IGNORE_STAFF: "Cannot ignore Staff members." + CANNOT_IGNORE_STAFF: "No puede ignorar a miembros del Staff." email: "No es un correo válido" confirm_password: "Las contraseñas no coinciden. Inténtelo nuevamente" network_error: "Error al conectar con el servidor. Compruebe su conexión a Internet y vuelva a intentarlo." @@ -243,8 +244,8 @@ es: password: "La contraseña debe tener por lo menos 8 caracteres" username: "Los nombres pueden contener letras números y _" required_field: "Este campo es requerido" - unexpected: "Lo siento. Ha habido un error no previsto." - temporarily_suspended: "Your account is currently suspended. It will be reactivated {0}. Please contact us if you have any questions." + unexpected: "Lo siento. Ha ocurrido un error no previsto." + temporarily_suspended: "Su cuenta fue suspendida. Será reactivada {0}. Si tiene preguntas, por favor contáctese con nosotros." flag_comment: "Reportar este comentario" flag_reason: "Razón por la que hacer este reporte (Opcional)" flag_username: "Reportar el nombre de usuario" @@ -264,7 +265,7 @@ es: label: "Nuevo Nombre" msg: "Tu cuenta está suspendida porque tu nombre de usuario ha sido considerado no apropiado para el espacio. Para recuperar la cuenta, por favor ingresar un nuevo nombre de usuario. Contáctanos si tienes alguna pregunta." changed_name: - msg: "Your username change is under review by our moderation team." + msg: "El cambio en su nombre de usuario está siendo revisado por nuestro equipo de moderación." my_comments: "Mis Comentarios" my_profile: "Mi perfil" new_count: "Ver {0} más {1} " @@ -295,9 +296,9 @@ es: comment_spam: "Contiene spam" comment_noagree: "No está de acuerdo" comment_other: "Otra razón" - suspect_word: "Suspect Word" - banned_word: "Banned Word" - body_count: "Body exceeds max length" + suspect_word: "Palabra sospechosa" + banned_word: "Palabra prohibida" + body_count: "El texto exede el límite permitido" trust: "Trust" links: "Link" modqueue: @@ -305,14 +306,14 @@ es: actions: Acciones all: todos all_streams: "Todos los Hilos" - notify_edited: '{0} edited comment "{1}"' - notify_accepted: '{0} accepted comment "{1}"' - notify_rejected: '{0} rejected comment "{1}"' - notify_flagged: '{0} flagged comment "{1}"' - notify_reset: '{0} reset status of comment "{1}"' + notify_edited: '{0} comentarios editados "{1}"' + notify_accepted: '{0} comentarios aceptados "{1}"' + notify_rejected: '{0} comentarios rechazados "{1}"' + notify_flagged: '{0} comentarios reportados "{1}"' + notify_reset: '{0} resetear el status de comentarios "{1}"' approve: "Aprobar" approved: "Aprobado" - ban_user: "Ban" + ban_user: "Bloquear" billion: B close: Cerrar empty_queue: "¡No hay más comentarios para moderar! Tiempo para un ☕️" @@ -352,7 +353,7 @@ es: no_agree_comment: "No estoy de acuerdo con este comentario" no_like_bio: "No me gusta esta biografia" no_like_username: "No me gusta este nombre de usuario" - already_flagged_username: "You have already flagged this username." + already_flagged_username: "Usted ya reportó a este usuario." other: Otro permalink: Compartir personal_info: "Este comentario muestra información personal" @@ -428,28 +429,28 @@ es: user_bio: "Bio de Usuario" username_flags: "reportes para este nombre de usuario" user_detail: - remove_suspension: "Remove Suspension" - suspend: "Suspend User" - remove_ban: "Remove Ban" - ban: "Ban User" - member_since: "Member Since" + remove_suspension: "Cancelar suspensión" + suspend: "Suspender usuario" + remove_ban: "Cancelar bloqueo" + ban: "Bloquear usuario" + member_since: "Miembro desde" email: "Email" - total_comments: "Total Comments" + total_comments: "Comentarios totales" reject_rate: "Reject Rate" - reports: "Reports" - all: "All" - rejected: "Rejected" - user_history: "User History" + reports: "Reportes" + all: "Todo" + rejected: "Rechazar" + user_history: "Historial del usuario" user_history: - user_banned: "User banned" - ban_removed: "Ban removed" - username_status: "Username {0}" - suspended: "Suspended, {0}" - suspension_removed: "Suspension removed" - system: "System" - date: "Date" - action: "Action" - taken_by: "Taken By" + user_banned: "Usuario bloqueado" + ban_removed: "Bloqueo cancelado" + username_status: "Nombre de usuario {0}" + suspended: "Suspendido, {0}" + suspension_removed: "Suspensión cancelada" + system: "Sistema" + date: "Fecha" + action: "Acción" + taken_by: "Está en uso" user_impersonating: "Este usuario suplanta a alguien" user_no_comment: "No has dejado aún ningún comentario. ¡Únete a la conversación!" username_offensive: "Este nombre de usuario es ofensivo" @@ -477,5 +478,5 @@ es: launch: "Iniciar Talk" close: "Cerrar este instalador" admin_sidebar: - view_options: "View Options" - sort_comments: "Sort Comments" + view_options: "Ver opciones" + sort_comments: "Ordenar comentarios" From e67d68267c6791d1f7d98f489ddb7612edfac202 Mon Sep 17 00:00:00 2001 From: okbel Date: Sun, 29 Apr 2018 22:00:42 -0300 Subject: [PATCH 011/133] Adding Change Email --- .../components/ChangeEmailDialog.css | 77 +++++++++++++++ .../components/ChangeEmailDialog.js | 98 +++++++++++++++++++ .../components/ChangeUsername.js | 96 ++++++++++++++---- .../talk-plugin-auth/client/translations.yml | 11 +++ 4 files changed, 264 insertions(+), 18 deletions(-) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.css new file mode 100644 index 0000000000..a57c3662b1 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.css @@ -0,0 +1,77 @@ +.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; +} + +.bottomActions { + text-align: right; +} + +.emailChange { + 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/ChangeEmailDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.js new file mode 100644 index 0000000000..844b900e7e --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.js @@ -0,0 +1,98 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import styles from './ChangeUsernameDialog.css'; +import InputField from './InputField'; +import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; +import { t } from 'plugin-api/beta/client/services'; + +class ChangeEmailDialog extends React.Component { + state = { + showError: false, + errors: { + passowrd: '', + }, + }; + + showError = () => { + this.setState({ + showError: true, + }); + }; + + confirmChanges = async () => { + if (this.formHasError()) { + this.showError(); + } else { + await this.props.saveChanges(); + this.props.closeDialog(); + } + }; + + render() { + return ( + + + × + +

+ {t('talk-plugin-auth.change_email.confirm_email_change')} +

+
+

+ {t('talk-plugin-auth.change_email.description')} +

+
+ + {t('talk-plugin-auth.change_email.old_email')}: {this.props.email} + + + {t('talk-plugin-auth.change_email.new_email')}:{' '} + {this.props.formData.newEmail} + +
+
+ + +
+ + +
+
+
+ ); + } +} + +ChangeEmailDialog.propTypes = { + saveChanges: PropTypes.func, + closeDialog: PropTypes.func, + showDialog: PropTypes.bool, + onChange: PropTypes.func, + email: PropTypes.string, + formData: PropTypes.object, +}; + +export default ChangeEmailDialog; 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 df8b3a641e..d9f020491e 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -4,14 +4,18 @@ import PropTypes from 'prop-types'; import styles from './ChangeUsername.css'; import { Button } from 'plugin-api/beta/client/components/ui'; import ChangeUsernameDialog from './ChangeUsernameDialog'; +import ChangeEmailDialog from './ChangeEmailDialog'; import { t } from 'plugin-api/beta/client/services'; import InputField from './InputField'; import { getErrorMessages } from 'coral-framework/utils'; +import validate from 'coral-framework/helpers/validate'; +import errorMsj from 'coral-framework/helpers/error'; const initialState = { editing: false, showDialog: false, formData: {}, + errors: {}, }; class ChangeUsername extends React.Component { @@ -69,23 +73,72 @@ class ChangeUsername extends React.Component { this.disableEditing(); }; - onChange = e => { - const { name, value } = e.target; - - this.setState(state => ({ - formData: { - ...state.formData, - [name]: value, - }, + addError = err => { + this.setState(({ errors }) => ({ + errors: { ...errors, ...err }, })); }; + removeError = errKey => { + this.setState(state => { + const { [errKey]: _, ...errors } = state.errors; + return { + errors, + }; + }); + }; + + 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); + } + }; + + onChange = e => { + const { name, value, type, dataset } = e.target; + const validationType = dataset.validationType || type; + + this.setState( + state => ({ + formData: { + ...state.formData, + [name]: value, + }, + }), + () => { + this.fieldValidation(value, validationType, name); + } + ); + }; + closeDialog = () => { this.setState({ showDialog: false, }); }; + hasError = err => { + return Object.keys(this.state.errors).indexOf(err) !== -1; + }; + + isSaveEnabled = () => { + const formHasErrors = !!Object.keys(this.state.errors).length; + const validUsername = + this.state.formData.newUsername && + this.state.formData.newUsername !== this.props.username; + const validEmail = + this.state.formData.newEmail && + this.state.formData.newEmail !== this.props.emailAddress; + + return !formHasErrors && (validUsername || validEmail); + }; + render() { const { username, emailAddress } = this.props; const { editing } = this.state; @@ -105,6 +158,15 @@ class ChangeUsername extends React.Component { saveChanges={this.saveChanges} /> + + {editing ? (
@@ -114,8 +176,8 @@ class ChangeUsername extends React.Component { name="newUsername" onChange={this.onChange} defaultValue={username} - columnDisplay validationType="username" + columnDisplay > {t('talk-plugin-auth.change_username.change_username_note')} @@ -123,11 +185,12 @@ class ChangeUsername extends React.Component {
@@ -145,10 +208,7 @@ class ChangeUsername extends React.Component { className={cn(styles.button, styles.saveButton)} icon="save" onClick={this.onSave} - disabled={ - !this.state.formData.newUsername || - this.state.formData.newUsername === username - } + disabled={!this.isSaveEnabled()} > {t('talk-plugin-auth.change_username.save')} diff --git a/plugins/talk-plugin-auth/client/translations.yml b/plugins/talk-plugin-auth/client/translations.yml index 3cfb46a955..4ac5ae4e68 100644 --- a/plugins/talk-plugin-auth/client/translations.yml +++ b/plugins/talk-plugin-auth/client/translations.yml @@ -152,6 +152,17 @@ en: bottom_note: "Note: You will not be able to change your username again for 14 days" confirm_changes: "Confirm Changes" username_does_not_match: "Username does not match" + cant_be_equal: "Your new {0} must be different to your current one" + change_email: + confirm_email_change: "Confirm Email Address Change" + description: "You are attempting to change your email address. Your new email address will be used for your login and to receive account notifications." + old_email: "Old Email Address" + new_email: "New Email Address" + enter_password: "Enter Password" + incorrect_password: "Incorrect Password" + confirm_change: "Confirm Change" + cancel: "Cancel" + change_email_msg: "Email Address Changed - Your email address has been successfully changed. This email address will now be used for signing in and email notifications" de: talk-plugin-auth: login: From 8df9a1e66e37b904fe90aa7ab04ae23b631c0a9f Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 30 Apr 2018 13:47:15 -0300 Subject: [PATCH 012/133] wip --- plugins/talk-plugin-auth/client/index.js | 4 +-- ...ialog.css => ChangeEmailContentDialog.css} | 0 ...lDialog.js => ChangeEmailContentDialog.js} | 22 ++++++------- ...og.css => ChangeUsernameContentDialog.css} | 11 ------- ...alog.js => ChangeUsernameContentDialog.js} | 18 +++++------ .../components/ConfirmChangesDialog.css | 10 ++++++ .../components/ConfirmChangesDialog.js | 22 +++++++++++++ .../{ChangeUsername.css => Profile.css} | 0 .../{ChangeUsername.js => Profile.js} | 31 +++++++++---------- .../{ChangeUsername.js => Profile.js} | 4 +-- 10 files changed, 67 insertions(+), 55 deletions(-) rename plugins/talk-plugin-auth/client/profile-settings/components/{ChangeEmailDialog.css => ChangeEmailContentDialog.css} (100%) rename plugins/talk-plugin-auth/client/profile-settings/components/{ChangeEmailDialog.js => ChangeEmailContentDialog.js} (83%) rename plugins/talk-plugin-auth/client/profile-settings/components/{ChangeUsernameDialog.css => ChangeUsernameContentDialog.css} (75%) rename plugins/talk-plugin-auth/client/profile-settings/components/{ChangeUsernameDialog.js => ChangeUsernameContentDialog.js} (86%) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js rename plugins/talk-plugin-auth/client/profile-settings/components/{ChangeUsername.css => Profile.css} (100%) rename plugins/talk-plugin-auth/client/profile-settings/components/{ChangeUsername.js => Profile.js} (90%) rename plugins/talk-plugin-auth/client/profile-settings/containers/{ChangeUsername.js => Profile.js} (85%) diff --git a/plugins/talk-plugin-auth/client/index.js b/plugins/talk-plugin-auth/client/index.js index 8fedb8033b..6341dc7c9d 100644 --- a/plugins/talk-plugin-auth/client/index.js +++ b/plugins/talk-plugin-auth/client/index.js @@ -5,7 +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'; +import Profile from './profile-settings/containers/Profile'; export default { reducer, @@ -13,7 +13,7 @@ export default { slots: { stream: [UserBox, SignInButton, SetUsernameDialog], login: [Login], - profileHeader: [ChangeUsername], + profileHeader: [Profile], profileSettings: [ChangePassword], }, }; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.css rename to plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js similarity index 83% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.js rename to plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js index 844b900e7e..1bb8f74101 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js @@ -1,12 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import cn from 'classnames'; -import styles from './ChangeUsernameDialog.css'; +import styles from './ChangeEmailContentDialog.css'; import InputField from './InputField'; -import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; +import { Button } from 'plugin-api/beta/client/components/ui'; import { t } from 'plugin-api/beta/client/services'; -class ChangeEmailDialog extends React.Component { +class ChangeEmailContentDialog extends React.Component { state = { showError: false, errors: { @@ -31,10 +30,7 @@ class ChangeEmailDialog extends React.Component { render() { return ( - +
× @@ -56,9 +52,9 @@ class ChangeEmailDialog extends React.Component {
-
+ ); } } -ChangeEmailDialog.propTypes = { +ChangeEmailContentDialog.propTypes = { saveChanges: PropTypes.func, closeDialog: PropTypes.func, showDialog: PropTypes.bool, @@ -95,4 +91,4 @@ ChangeEmailDialog.propTypes = { formData: PropTypes.object, }; -export default ChangeEmailDialog; +export default ChangeEmailContentDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.css similarity index 75% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css rename to plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.css index af681d5967..2f3cdd14df 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.css @@ -1,14 +1,3 @@ -.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; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.js similarity index 86% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js rename to plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.js index 3ebf6ff027..4cf75a8a7a 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.js @@ -1,12 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import cn from 'classnames'; -import styles from './ChangeUsernameDialog.css'; +import styles from './ChangeUsernameContentDialog.css'; import InputField from './InputField'; -import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; +import { Button } from 'plugin-api/beta/client/components/ui'; import { t } from 'plugin-api/beta/client/services'; -class ChangeUsernameDialog extends React.Component { +class ChangeUsernameContentDialog extends React.Component { state = { showError: false, }; @@ -31,10 +30,7 @@ class ChangeUsernameDialog extends React.Component { render() { return ( - +
× @@ -89,12 +85,12 @@ class ChangeUsernameDialog extends React.Component {
-
+ ); } } -ChangeUsernameDialog.propTypes = { +ChangeUsernameContentDialog.propTypes = { saveChanges: PropTypes.func, closeDialog: PropTypes.func, showDialog: PropTypes.bool, @@ -103,4 +99,4 @@ ChangeUsernameDialog.propTypes = { formData: PropTypes.object, }; -export default ChangeUsernameDialog; +export default ChangeUsernameContentDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.css new file mode 100644 index 0000000000..daa8844046 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.css @@ -0,0 +1,10 @@ +.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; +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js new file mode 100644 index 0000000000..4b6fa82219 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js @@ -0,0 +1,22 @@ +import React from 'react'; +import cn from 'classnames'; +import styles from './ConfirmChangesDialog.css'; +import { Dialog } from 'plugin-api/beta/client/components/ui'; +import ChangeUsernameContentDialog from './ChangeUsernameContentDialog'; +import ChangeEmailContentDialog from './ChangeEmailContentDialog'; + +class ConfirmChangesDialog extends React.Component { + render() { + return ( + + + + + ); + } +} + +export default ConfirmChangesDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css b/plugins/talk-plugin-auth/client/profile-settings/components/Profile.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css rename to plugins/talk-plugin-auth/client/profile-settings/components/Profile.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/components/Profile.js similarity index 90% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js rename to plugins/talk-plugin-auth/client/profile-settings/components/Profile.js index d9f020491e..642917f009 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/Profile.js @@ -1,15 +1,14 @@ import React from 'react'; import cn from 'classnames'; import PropTypes from 'prop-types'; -import styles from './ChangeUsername.css'; +import styles from './Profile.css'; import { Button } from 'plugin-api/beta/client/components/ui'; -import ChangeUsernameDialog from './ChangeUsernameDialog'; -import ChangeEmailDialog from './ChangeEmailDialog'; import { t } from 'plugin-api/beta/client/services'; import InputField from './InputField'; import { getErrorMessages } from 'coral-framework/utils'; import validate from 'coral-framework/helpers/validate'; import errorMsj from 'coral-framework/helpers/error'; +import ConfirmChangesDialog from './ConfirmChangesDialog'; const initialState = { editing: false, @@ -18,7 +17,7 @@ const initialState = { errors: {}, }; -class ChangeUsername extends React.Component { +class Profile extends React.Component { state = initialState; clearForm = () => { @@ -89,6 +88,7 @@ class ChangeUsername extends React.Component { }; fieldValidation = (value, type, name) => { + console.log(value, type, name); if (!value.length) { this.addError({ [name]: t('talk-plugin-auth.change_password.required_field'), @@ -136,6 +136,13 @@ class ChangeUsername extends React.Component { this.state.formData.newEmail && this.state.formData.newEmail !== this.props.emailAddress; + // const res = !formHasErrors && (!!validUsername || !!validEmail); + // console.log('formHasErrors:', formHasErrors); + // console.log('validUsername:', validUsername); + // console.log('validEmail:', validEmail); + // console.log('res:', res); + // console.log(this.state.errors); + return !formHasErrors && (validUsername || validEmail); }; @@ -149,20 +156,12 @@ class ChangeUsername extends React.Component { [styles.editing]: editing, })} > - - - @@ -232,11 +231,11 @@ class ChangeUsername extends React.Component { } } -ChangeUsername.propTypes = { +Profile.propTypes = { changeUsername: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, username: PropTypes.string, emailAddress: PropTypes.string, }; -export default ChangeUsername; +export default Profile; diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/containers/Profile.js similarity index 85% rename from plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js rename to plugins/talk-plugin-auth/client/profile-settings/containers/Profile.js index 87e1e18b55..5495888b08 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js +++ b/plugins/talk-plugin-auth/client/profile-settings/containers/Profile.js @@ -1,12 +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 Profile from '../components/Profile'; 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 + Profile ); From be86b70b24cdbb896d634d97f8c7625987a886dc Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 30 Apr 2018 16:01:35 -0300 Subject: [PATCH 013/133] WIP: Steps --- .../components/ChangeEmailContentDialog.js | 23 +++----- .../components/ChangeUsernameContentDialog.js | 10 ++-- .../components/ConfirmChangesDialog.js | 56 +++++++++++++++++-- .../profile-settings/components/Profile.js | 24 ++++---- 4 files changed, 74 insertions(+), 39 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js index 1bb8f74101..e0452601a8 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js @@ -8,9 +8,7 @@ import { t } from 'plugin-api/beta/client/services'; class ChangeEmailContentDialog extends React.Component { state = { showError: false, - errors: { - passowrd: '', - }, + errors: {}, }; showError = () => { @@ -20,18 +18,13 @@ class ChangeEmailContentDialog extends React.Component { }; confirmChanges = async () => { - if (this.formHasError()) { - this.showError(); - } else { - await this.props.saveChanges(); - this.props.closeDialog(); - } + await this.props.saveChanges(); }; render() { return (
- + ×

@@ -43,7 +36,8 @@ class ChangeEmailContentDialog extends React.Component {

- {t('talk-plugin-auth.change_email.old_email')}: {this.props.email} + {t('talk-plugin-auth.change_email.old_email')}:{' '} + {this.props.emailAddress} {t('talk-plugin-auth.change_email.new_email')}:{' '} @@ -66,7 +60,7 @@ class ChangeEmailContentDialog extends React.Component { />
- +
+ ); + } +} + +export default DeleteMyAccount; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js new file mode 100644 index 0000000000..2f64a3e2e1 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js @@ -0,0 +1,10 @@ +import React from 'react'; +import { Dialog } from 'plugin-api/beta/client/components/ui'; + +class DeleteMyAccount extends React.Component { + render() { + return Holaa; + } +} + +export default DeleteMyAccount; From 876eb1e413d0048996388ad72d54aae52f7a482a Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 00:17:57 -0300 Subject: [PATCH 019/133] wip --- .../components/DeleteMyAccount.js | 2 +- .../components/DeleteMyAccountDialog.css | 95 +++++++++++++++++++ .../components/DeleteMyAccountDialog.js | 67 ++++++++++++- .../components/StepProgress.css | 9 ++ .../components/StepProgress.js | 17 ++++ 5 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js index 4b48e15cef..95b11ab495 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js @@ -24,7 +24,7 @@ class DeleteMyAccount extends React.Component { render() { return (
- +

i.itemIcon { + font-size: 1.3em; + } +} + + + + + +/** Step **/ + diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js index 2f64a3e2e1..fd0b1e255e 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js @@ -1,10 +1,69 @@ import React from 'react'; -import { Dialog } from 'plugin-api/beta/client/components/ui'; +import cn from 'classnames'; +import PropTypes from 'prop-types'; +import styles from './DeleteMyAccountDialog.css'; +import { Button, Dialog, Icon } from 'plugin-api/beta/client/components/ui'; +import StepProgress from './StepProgress'; + +const initialState = { step: 0 }; + +class DeleteMyAccountDialog extends React.Component { + state = initialState; + + goToNextStep = () => { + this.setState(state => ({ + step: state.step + 1, + })); + }; + + clear = () => { + this.setState(initialState); + }; -class DeleteMyAccount extends React.Component { render() { - return Holaa; + return ( + + + × + +

Delete My Account

+ +
+

+ You are attempting to delete your account. This means: +

+
    +
  • + + + All of your comments are removed from this site + +
  • +
  • + + + All of your comments are deleted from our database + +
  • +
  • + + + Your username and email address are removed from our system + +
  • +
+
+
+ + +
+
+ ); } } -export default DeleteMyAccount; +DeleteMyAccountDialog.propTypes = { + closeDialog: PropTypes.func.isRequired, +}; + +export default DeleteMyAccountDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css new file mode 100644 index 0000000000..90a8a558c8 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css @@ -0,0 +1,9 @@ +.step { + &.current { + color: rgba(0, 205, 115, 0.3); + } + + &.completed { + color: #00CD73; + } +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js new file mode 100644 index 0000000000..c0c2d97122 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js @@ -0,0 +1,17 @@ +import React from 'react'; +import styles from './StepProgress.css'; +import { Icon } from 'plugin-api/beta/client/components/ui'; + +class StepProgress extends React.Component { + render() { + return ( +
+ + + +
+ ); + } +} + +export default StepProgress; From b2988e540e4a8370839e31bffcd67cf7559170fc Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 1 May 2018 16:48:52 +0200 Subject: [PATCH 020/133] Move mutation logic to coral-admin --- client/coral-admin/src/graphql/index.js | 31 +++++++++++++++++++++ client/coral-framework/graphql/mutations.js | 31 --------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/client/coral-admin/src/graphql/index.js b/client/coral-admin/src/graphql/index.js index 95595c265d..3874e6c942 100644 --- a/client/coral-admin/src/graphql/index.js +++ b/client/coral-admin/src/graphql/index.js @@ -291,5 +291,36 @@ export default { }, }, }), + SetCommentStatus: ({ variables: { status } }) => ({ + updateQueries: { + CoralAdmin_UserDetail: prev => { + const increment = { + rejectedComments: { + $apply: count => (count < prev.totalComments ? count + 1 : count), + }, + }; + + const decrement = { + rejectedComments: { + $apply: count => (count > 0 ? count - 1 : 0), + }, + }; + + // If rejected then increment rejectedComments by one + if (status === 'REJECTED') { + const updated = update(prev, increment); + return updated; + } + + // If approved then decrement rejectedComments by one + if (status === 'ACCEPTED') { + const updated = update(prev, decrement); + return updated; + } + + return prev; + }, + }, + }), }, }; diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index 228911d4ae..995ca17209 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -1,6 +1,5 @@ import { gql } from 'react-apollo'; import withMutation from '../hocs/withMutation'; -import update from 'immutability-helper'; function convertItemType(item_type) { switch (item_type) { @@ -168,36 +167,6 @@ export const withSetCommentStatus = withMutation( errors: null, }, }, - updateQueries: { - CoralAdmin_UserDetail: prev => { - const increment = { - rejectedComments: { - $apply: count => - count < prev.totalComments ? count + 1 : count, - }, - }; - - const decrement = { - rejectedComments: { - $apply: count => (count > 0 ? count - 1 : 0), - }, - }; - - // If rejected then increment rejectedComments by one - if (status === 'REJECTED') { - const updated = update(prev, increment); - return updated; - } - - // If approved then decrement rejectedComments by one - if (status === 'ACCEPTED') { - const updated = update(prev, decrement); - return updated; - } - - return prev; - }, - }, update: proxy => { const fragment = gql` fragment Talk_SetCommentStatus_Comment on Comment { From d07b77b8f7ab6e07cf1e53ef43c0140eb0f3f29c Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 1 May 2018 16:49:44 +0200 Subject: [PATCH 021/133] Remove forgotten console.log --- client/coral-admin/src/components/UserDetail.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/coral-admin/src/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js index e45e3f0957..5dabc5b6f4 100644 --- a/client/coral-admin/src/components/UserDetail.js +++ b/client/coral-admin/src/components/UserDetail.js @@ -96,8 +96,6 @@ class UserDetail extends React.Component { bulkReject, } = this.props; - console.log(rejectedComments, totalComments); - // if totalComments is 0, you're dividing by zero let rejectedPercent = rejectedComments / totalComments * 100; From 867523140c3f70a9cf2161113948f90559f1665c Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 14:09:43 -0300 Subject: [PATCH 022/133] Adding StepProgress component, and all the steps --- .../components/DeleteMyAccountDialog.css | 60 +----------------- .../components/DeleteMyAccountDialog.js | 51 ++++++---------- .../components/DeleteMyAccountFinalStep.js | 40 ++++++++++++ .../components/DeleteMyAccountStep.css | 61 +++++++++++++++++++ .../components/DeleteMyAccountStep0.js | 43 +++++++++++++ .../components/DeleteMyAccountStep1.js | 30 +++++++++ .../components/DeleteMyAccountStep2.js | 27 ++++++++ .../components/DeleteMyAccountStep3.js | 31 ++++++++++ .../components/StepProgress.css | 23 +++++++ .../components/StepProgress.js | 39 ++++++++++-- 10 files changed, 312 insertions(+), 93 deletions(-) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css index 802b631972..db44ebf6d0 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css @@ -1,7 +1,7 @@ .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; + width: 380px; top: 10px; font-family: Helvetica, 'Helvetica Neue', Verdana, sans-serif; font-size: 14px; @@ -26,7 +26,7 @@ } .title { - font-size: 1.3em; + font-size: 1.2em; margin-bottom: 8px; } @@ -36,60 +36,4 @@ margin: 0; } -.button { - color: #787D80; - border-radius: 2px; - background-color: transparent; - height: 30px; - font-size: 0.9em; - line-height: normal; - - &:hover { - background-color: #eaeaea; - } - - &.cancel { - background-color: transparent; - color: #787D80; - } - - &.proceed { - background-color: #3498DB; - color: white; - } -} - -.actions { - text-align: right; -} - -.list { - padding: 0; - margin: 10px 0; - list-style: none; -} - -.item { - display: flex; - margin-bottom: 10px; - - .itemIcon { - flex-grow: 0; - } - - .text { - flex-grow: 1; - padding-left: 10px; - } - - > i.itemIcon { - font-size: 1.3em; - } -} - - - - - -/** Step **/ diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js index fd0b1e255e..599816e2d3 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js @@ -1,9 +1,13 @@ import React from 'react'; -import cn from 'classnames'; import PropTypes from 'prop-types'; import styles from './DeleteMyAccountDialog.css'; -import { Button, Dialog, Icon } from 'plugin-api/beta/client/components/ui'; +import { Dialog } from 'plugin-api/beta/client/components/ui'; import StepProgress from './StepProgress'; +import DeleteMyAccountStep0 from './DeleteMyAccountStep0'; +import DeleteMyAccountStep1 from './DeleteMyAccountStep1'; +import DeleteMyAccountStep2 from './DeleteMyAccountStep2'; +import DeleteMyAccountStep3 from './DeleteMyAccountStep3'; +import DeleteMyAccountFinalStep from './DeleteMyAccountFinalStep'; const initialState = { step: 0 }; @@ -21,6 +25,7 @@ class DeleteMyAccountDialog extends React.Component { }; render() { + const { step } = this.state; return ( @@ -28,35 +33,19 @@ class DeleteMyAccountDialog extends React.Component {

Delete My Account

-
-

- You are attempting to delete your account. This means: -

-
    -
  • - - - All of your comments are removed from this site - -
  • -
  • - - - All of your comments are deleted from our database - -
  • -
  • - - - Your username and email address are removed from our system - -
  • -
-
-
- - -
+ {step === 0 && ( + + )} + {step === 1 && ( + + )} + {step === 2 && ( + + )} + {step === 3 && ( + + )} + {step === 4 && }
); } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js new file mode 100644 index 0000000000..004270f4de --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js @@ -0,0 +1,40 @@ +import React from 'react'; +import cn from 'classnames'; +import { Button, Icon } from 'plugin-api/beta/client/components/ui'; +import styles from './DeleteMyAccountStep.css'; + +const DeleteMyAccountFinalStep = () => ( +
+

+ Your request has been submitted and confirmation has been sent to the + email address associated with your account. +

+ Your account is scheduled to be deleted at: + + Account Deletion Date and Time + +

+ Changed your mind? Simply sign in to your account again + before this time and click “ + Cancel Account Deletion Request. + ” +

+

+ Tell us why. Wed like to know why you chose to delete + your account. Send us feedback on our comment system by emailing. +

+
+ + + Note: You will be immediately signed out of your account. + +
+
+); + +export default DeleteMyAccountFinalStep; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css new file mode 100644 index 0000000000..8984bf7acb --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css @@ -0,0 +1,61 @@ +.list { + padding: 0; + margin: 20px 0; + list-style: none; +} + +.item { + display: flex; + margin-bottom: 20px; + + .itemIcon { + flex-grow: 0; + } + + .text { + flex-grow: 1; + padding-left: 10px; + } + + > i.itemIcon { + font-size: 1.3em; + } +} + +.button { + color: #787D80; + border-radius: 2px; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; + + &:hover { + background-color: #eaeaea; + } + + &.cancel { + background-color: transparent; + color: #787D80; + } + + &.proceed { + background-color: #3498DB; + color: white; + } +} + +.actions { + text-align: right; +} + +.title { + font-size: 1.2em; + margin-bottom: 8px; +} + +.description { + font-size: 1em; + line-height: 20px; + margin: 0; +} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js new file mode 100644 index 0000000000..ddddf7141f --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js @@ -0,0 +1,43 @@ +import React from 'react'; +import cn from 'classnames'; +import { Button, Icon } from 'plugin-api/beta/client/components/ui'; +import styles from './DeleteMyAccountStep.css'; + +const DeleteMyAccountStep0 = () => ( +
+

+ You are attempting to delete your account. This means: +

+
    +
  • + + + All of your comments are removed from this site + +
  • +
  • + + + All of your comments are deleted from our database + +
  • +
  • + + + Your username and email address are removed from our system + +
  • +
+
+ + +
+
+); + +export default DeleteMyAccountStep0; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js new file mode 100644 index 0000000000..602bb33b7b --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js @@ -0,0 +1,30 @@ +import React from 'react'; +import cn from 'classnames'; +import { Button } from 'plugin-api/beta/client/components/ui'; +import styles from './DeleteMyAccountStep.css'; + +const DeleteMyAccountStep1 = () => ( +
+

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 youve requested account deletion, you can no longer write + comments, reply to comments, or select reactions. +

+
+ + +
+
+); + +export default DeleteMyAccountStep1; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js new file mode 100644 index 0000000000..7b069ca3d5 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js @@ -0,0 +1,27 @@ +import React from 'react'; +import cn from 'classnames'; +import { Button } from 'plugin-api/beta/client/components/ui'; +import styles from './DeleteMyAccountStep.css'; + +const DeleteMyAccountStep1 = () => ( +
+

+ 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. +

+

To download your comment history go to:

+ My Profile Download My Comment History +
+ + +
+
+); + +export default DeleteMyAccountStep1; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js new file mode 100644 index 0000000000..bf3dea674f --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js @@ -0,0 +1,31 @@ +import React from 'react'; +import cn from 'classnames'; +import { Button } from 'plugin-api/beta/client/components/ui'; +import styles from './DeleteMyAccountStep.css'; + +const DeleteMyAccountStep1 = () => ( +
+

Are you sure you want to delete your account?

+

+ To confirm you would like to delete your account please type in the + following phrase into the text box below: +

+ +
+ + +
+
+); + +export default DeleteMyAccountStep1; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css index 90a8a558c8..68fab06a92 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css @@ -1,4 +1,9 @@ .step { + color: #BBBEBF; + background-color: white; + padding: 6px; + z-index: 10; + &.current { color: rgba(0, 205, 115, 0.3); } @@ -6,4 +11,22 @@ &.completed { color: #00CD73; } +} + +.line { + position: absolute; + border: solid 2px #BBBEBF; + width: 100%; + box-sizing: border-box; + margin: 0; + padding: 0; +} + +.container { + display: flex; + position: relative; + justify-content: space-between; + align-items: center; + height: 50px; + margin: 0 20px; } \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js index c0c2d97122..e11bf46d54 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js @@ -1,17 +1,48 @@ import React from 'react'; +import cn from 'classnames'; +import PropTypes from 'prop-types'; import styles from './StepProgress.css'; import { Icon } from 'plugin-api/beta/client/components/ui'; +const CheckItem = ({ current = false, completed = false }) => ( + + + +); + +CheckItem.propTypes = { + current: PropTypes.bool.isRequired, + completed: PropTypes.bool.isRequired, +}; + +const Line = () =>
; + class StepProgress extends React.Component { render() { + const { currentStep, totalSteps } = this.props; return ( -
- - - +
+ {Array.from({ length: totalSteps }).map((_, i) => ( + + ))} +
); } } +StepProgress.propTypes = { + currentStep: PropTypes.number.isRequired, + totalSteps: PropTypes.number.isRequired, +}; + export default StepProgress; From f4cb16e56eb7bdf681f68f35c2af3a853ca1e625 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 14:14:43 -0300 Subject: [PATCH 023/133] styles wip --- .../profile-settings/components/DeleteMyAccountStep0.js | 4 ++-- .../profile-settings/components/DeleteMyAccountStep1.js | 4 ++-- .../profile-settings/components/DeleteMyAccountStep2.js | 4 ++-- .../profile-settings/components/DeleteMyAccountStep3.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js index ddddf7141f..f81d912ea9 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js @@ -3,7 +3,7 @@ import cn from 'classnames'; import { Button, Icon } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep0 = () => ( +const DeleteMyAccountStep0 = props => (

You are attempting to delete your account. This means: @@ -32,7 +32,7 @@ const DeleteMyAccountStep0 = () => ( diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js index 602bb33b7b..d3b399f442 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js @@ -3,7 +3,7 @@ import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep1 = () => ( +const DeleteMyAccountStep1 = props => (

When will my account be deleted?

@@ -19,7 +19,7 @@ const DeleteMyAccountStep1 = () => ( diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js index 7b069ca3d5..47c89e4c1e 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js @@ -3,7 +3,7 @@ import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep1 = () => ( +const DeleteMyAccountStep1 = props => (

Before your account is deleted, we recommend you download your comment @@ -16,7 +16,7 @@ const DeleteMyAccountStep1 = () => ( diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js index bf3dea674f..534ea9db8d 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js @@ -3,7 +3,7 @@ import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep1 = () => ( +const DeleteMyAccountStep1 = props => (

Are you sure you want to delete your account?

@@ -20,7 +20,7 @@ const DeleteMyAccountStep1 = () => ( From bd21d9a1a14a2febf10115f8f5d1be4aa6fdc8a0 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 14:19:43 -0300 Subject: [PATCH 024/133] fix b --- .../client/profile-settings/components/ConfirmChangesDialog.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js index 59eac894f2..0031bcb71a 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js @@ -44,7 +44,8 @@ class ConfirmChangesDialog extends React.Component { goToNextStep: this.goToNextStep, clear: this.clear, cancel: this.cancel, - next: this.state.step === steps.length ? this.finish : this.continue, + next: + this.state.step === steps.length - 1 ? this.finish : this.continue, }); }); }; From 3bb91f683320f706af312edb7863258c35dbdabd Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 15:43:10 -0300 Subject: [PATCH 025/133] Adding withRequestAccountDeletion, withRequestDownloadLink, withCancelAccountDeletion --- client/coral-framework/graphql/fragments.js | 5 +- client/coral-framework/graphql/mutations.js | 51 +++++++++++++++++++ .../components/DeleteMyAccountDialog.css | 4 +- .../components/DeleteMyAccountFinalStep.js | 24 ++++++--- .../components/DeleteMyAccountStep.css | 47 +++++++++++++++++ .../components/DeleteMyAccountStep1.js | 6 ++- .../components/DeleteMyAccountStep2.js | 8 ++- .../components/DeleteMyAccountStep3.js | 6 ++- 8 files changed, 134 insertions(+), 17 deletions(-) diff --git a/client/coral-framework/graphql/fragments.js b/client/coral-framework/graphql/fragments.js index a62fd6d924..f30cb1e63f 100644 --- a/client/coral-framework/graphql/fragments.js +++ b/client/coral-framework/graphql/fragments.js @@ -25,6 +25,9 @@ export default { 'UnsuspendUserResponse', 'UpdateAssetSettingsResponse', 'UpdateAssetStatusResponse', - 'UpdateSettingsResponse' + 'UpdateSettingsResponse', + 'RequestAccountDeletionResponse', + 'RequestDownloadLinkResponse', + 'CancelAccountDeletionResponse' ), }; diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index bd31be6305..bf412b1898 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -623,6 +623,57 @@ export const withUpdateSettings = withMutation( } ); +export const withRequestAccountDeletion = withMutation( + gql` + mutation RequestAccountDeletion { + requestAccountDeletion { + ...RequestAccountDeletionResponse + } + } + `, + { + props: ({ mutate }) => ({ + requestAccountDeletion: () => { + return mutate(); + }, + }), + } +); + +export const withRequestDownloadLink = withMutation( + gql` + mutation RequestDownloadLink { + requestDownloadLink { + ...RequestDownloadLinkResponse + } + } + `, + { + props: ({ mutate }) => ({ + requestDownloadLink: () => { + return mutate(); + }, + }), + } +); + +export const withCancelAccountDeletion = withMutation( + gql` + mutation RequestDownloadLink { + cancelAccountDeletion { + ...CancelAccountDeletionResponse + } + } + `, + { + props: ({ mutate }) => ({ + cancelAccountDeletion: () => { + return mutate(); + }, + }), + } +); + export const withUpdateAssetSettings = withMutation( gql` mutation UpdateAssetSettings($id: ID!, $input: AssetSettingsInput!) { diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css index db44ebf6d0..44dcad0cf8 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css @@ -34,6 +34,4 @@ font-size: 1em; line-height: 20px; margin: 0; -} - - +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js index 004270f4de..22cf476e54 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js @@ -9,30 +9,40 @@ const DeleteMyAccountFinalStep = () => ( Your request has been submitted and confirmation has been sent to the email address associated with your account.

- Your account is scheduled to be deleted at: - - Account Deletion Date and Time - + +
+ + Your account is scheduled to be deleted at: + + + + Account Deletion Date and Time + +
+

Changed your mind? Simply sign in to your account again before this time and click “ Cancel Account Deletion Request.

+

Tell us why. Wed like to know why you chose to delete your account. Send us feedback on our comment system by emailing.

-
+ +
- + Note: You will be immediately signed out of your account. - +
); diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css index 8984bf7acb..98b73f376e 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css @@ -43,10 +43,22 @@ background-color: #3498DB; color: white; } + + &.danger { + background-color: #FA4643; + color: white; + } } .actions { text-align: right; + padding-top: 20px; + + &.columnView { + display: flex; + flex-direction: column; + align-items: center; + } } .title { @@ -58,4 +70,39 @@ font-size: 1em; line-height: 20px; margin: 0; + margin-bottom: 15px; +} + +.box { + display: flex; + flex-direction: column; + margin-bottom: 15px; +} + +.note { + margin: 10px 0; +} + +.subTitle { + font-size: 1em; + margin-bottom: 8px; +} + +.textBox { + background-color: #F1F2F2; + border: none; + width: 100%; + padding: 15px; + box-sizing: border-box; + color: #3B4A53; + font-size: 1em; +} + +.block { + display: block; + margin-top: 2px; +} + +.step { + padding-top: 20px; } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js index d3b399f442..1d26190bc8 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js @@ -5,12 +5,14 @@ import styles from './DeleteMyAccountStep.css'; const DeleteMyAccountStep1 = props => (
-

When will my account be deleted?

+

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?

+

+ Can I still write comments until my account is deleted?{' '} +

No. Once youve requested account deletion, you can no longer write comments, reply to comments, or select reactions. diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js index 47c89e4c1e..3337c0b940 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js @@ -10,8 +10,12 @@ const DeleteMyAccountStep1 = props => ( history for your records. After your account is deleted, you will be unable to request your comment history.

-

To download your comment history go to:

- My Profile Download My Comment History +

+ To download your comment history go to: + + My Profile {`>`} Download My Comment History + +

+ {scheduledDeletionDate ? ( + + ) : ( + + )}
); } @@ -63,6 +98,7 @@ DeleteMyAccount.propTypes = { requestAccountDeletion: PropTypes.func.isRequired, cancelAccountDeletion: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, + root: PropTypes.object.isRequired, }; export default DeleteMyAccount; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js index 599816e2d3..7c7c47d0b2 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js @@ -24,28 +24,45 @@ class DeleteMyAccountDialog extends React.Component { this.setState(initialState); }; + cancel = () => { + this.clear(); + this.closeDialog(); + }; + render() { const { step } = this.state; return ( - + ×

Delete My Account

{step === 0 && ( - + )} {step === 1 && ( - + )} {step === 2 && ( - + )} {step === 3 && ( - + )} - {step === 4 && } + {step === 4 && }
); } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js index 22cf476e54..764dae302b 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js @@ -1,9 +1,10 @@ import React from 'react'; import cn from 'classnames'; +import PropTypes from 'prop-types'; import { Button, Icon } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountFinalStep = () => ( +const DeleteMyAccountFinalStep = props => (

Your request has been submitted and confirmation has been sent to the @@ -35,7 +36,7 @@ const DeleteMyAccountFinalStep = () => (

); +DeleteMyAccountFinalStep.propTypes = { + finish: PropTypes.func.isRequired, +}; + export default DeleteMyAccountFinalStep; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js index f81d912ea9..901466d3b8 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button, Icon } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; @@ -29,7 +30,12 @@ const DeleteMyAccountStep0 = props => (
- +
); +DeleteMyAccountStep0.propTypes = { + goToNextStep: PropTypes.func.isRequired, + cancel: PropTypes.func.isRequired, +}; + export default DeleteMyAccountStep0; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js index 1d26190bc8..e74611b05b 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; @@ -18,7 +19,12 @@ const DeleteMyAccountStep1 = props => ( comments, reply to comments, or select reactions.

- +
); +DeleteMyAccountStep1.propTypes = { + goToNextStep: PropTypes.func.isRequired, + cancel: PropTypes.func.isRequired, +}; + export default DeleteMyAccountStep1; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js index 3337c0b940..8ef14445e9 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js @@ -1,9 +1,10 @@ import React from 'react'; +import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep1 = props => ( +const DeleteMyAccountStep2 = props => (

Before your account is deleted, we recommend you download your comment @@ -17,7 +18,12 @@ const DeleteMyAccountStep1 = props => (

- +
); -export default DeleteMyAccountStep1; +DeleteMyAccountStep2.propTypes = { + goToNextStep: PropTypes.func.isRequired, + cancel: PropTypes.func.isRequired, +}; + +export default DeleteMyAccountStep2; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js index 8cff542c1e..f91ca42c7f 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js @@ -1,9 +1,10 @@ import React from 'react'; +import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep1 = props => ( +const DeleteMyAccountStep3 = props => (

Are you sure you want to delete your account? @@ -19,7 +20,12 @@ const DeleteMyAccountStep1 = props => ( value="delete" />
- +
); -export default DeleteMyAccountStep1; +DeleteMyAccountStep3.propTypes = { + goToNextStep: PropTypes.func.isRequired, + cancel: PropTypes.func.isRequired, +}; + +export default DeleteMyAccountStep3; diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/DeleteMyAccount.js b/plugins/talk-plugin-auth/client/profile-settings/containers/DeleteMyAccount.js index b88780f1fb..a9c0338530 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/containers/DeleteMyAccount.js +++ b/plugins/talk-plugin-auth/client/profile-settings/containers/DeleteMyAccount.js @@ -12,7 +12,7 @@ const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); const withData = withFragments({ root: gql` - fragment TalkIgnoreUser_IgnoredUserSection_root on RootQuery { + fragment Talk_DeleteMyAccount_root on RootQuery { me { scheduledDeletionDate } From 5eead8b7ee0edb3545b9940284252085bbaa0d97 Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 16:32:42 -0300 Subject: [PATCH 028/133] Adding AccountDeletionRequestedSign.js --- .../AccountDeletionRequestedSign.css | 23 ++++++ .../AccountDeletionRequestedSign.js | 26 +++++++ .../components/DeleteMyAccountDialog.js | 2 + .../components/DeleteMyAccountFinalStep.js | 4 +- .../components/DeleteMyAccountStep.css | 7 ++ .../components/DeleteMyAccountStep3.js | 72 +++++++++++-------- 6 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css b/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css new file mode 100644 index 0000000000..413a3852b9 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css @@ -0,0 +1,23 @@ +.container { + border : solid 1px #F26563; + border-radius: 2px; + color: #3B4A53; +} + +.button { + color: #787D80; + border-radius: 2px; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; + + &:hover { + background-color: #eaeaea; + } + + &.secondary { + background-color: #787D80; + color: white; + } +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js b/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js new file mode 100644 index 0000000000..7d1941fa73 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js @@ -0,0 +1,26 @@ +import React from 'react'; +import cn from 'classnames'; +import { Button, Icon } from 'plugin-api/beta/client/components/ui'; +import styles from './AccountDeletionRequestedSign.css'; + +class AccountDeletionRequestedSign extends React.Component { + render() { + return ( +
+

+ Account Deletion Requested +

+

+ A request to delete your account was received on. If you would like to + continue leaving comments, replies or reactions, you may cancel your + request to delete your account below before +

+ +
+ ); + } +} + +export default AccountDeletionRequestedSign; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js index 7c7c47d0b2..4e3a1aa99c 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js @@ -60,6 +60,7 @@ class DeleteMyAccountDialog extends React.Component { )} {step === 4 && } @@ -70,6 +71,7 @@ class DeleteMyAccountDialog extends React.Component { DeleteMyAccountDialog.propTypes = { closeDialog: PropTypes.func.isRequired, + requestAccountDeletion: PropTypes.func.isRequired, }; export default DeleteMyAccountDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js index 764dae302b..ccbbf61faa 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js @@ -11,12 +11,12 @@ const DeleteMyAccountFinalStep = props => ( email address associated with your account.

-
+
Your account is scheduled to be deleted at: - + Account Deletion Date and Time
diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css index 98b73f376e..53d8ecef84 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css @@ -106,3 +106,10 @@ .step { padding-top: 20px; } + +.scheduledDeletion { + i.timeIcon { + font-size: 1.2em; + padding: 4px; + } +} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js index f91ca42c7f..54f49f3752 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js @@ -4,40 +4,50 @@ import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -const DeleteMyAccountStep3 = props => ( -
-

- Are you sure you want to delete your account? -

-

- To confirm you would like to delete your account please type in the - following phrase into the text box below: -

- -
- - -
-
-); +class DeleteMyAccountStep3 extends React.Component { + deleteAndContinue = () => { + this.props.requestAccountDeletion(); + this.props.goToNextStep(); + }; + + render() { + return ( +
+

+ Are you sure you want to delete your account? +

+

+ To confirm you would like to delete your account please type in the + following phrase into the text box below: +

+ +
+ + +
+
+ ); + } +} DeleteMyAccountStep3.propTypes = { goToNextStep: PropTypes.func.isRequired, + requestAccountDeletion: PropTypes.func.isRequired, cancel: PropTypes.func.isRequired, }; From ff7ee2aefc61522cbef173e4e5d3a31fcf7ff3fa Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 17:18:58 -0300 Subject: [PATCH 029/133] Updating cache --- client/coral-framework/graphql/mutations.js | 58 ++++++++++++++++++- locales/en.yml | 1 + plugins/talk-plugin-auth/client/index.js | 8 ++- .../AccountDeletionRequestedSign.css | 23 -------- .../AccountDeletionRequestedSign.js | 26 --------- .../components/DeleteMyAccount.css | 10 ++++ .../components/DeleteMyAccount.js | 17 +++++- .../components/DeleteMyAccountDialog.js | 5 +- .../components/DeleteMyAccountStep3.js | 2 +- .../AccountDeletionRequestedSign.css | 44 ++++++++++++++ .../AccountDeletionRequestedSign.js | 55 ++++++++++++++++++ .../AccountDeletionRequestedSign.js | 25 ++++++++ 12 files changed, 216 insertions(+), 58 deletions(-) delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js create mode 100644 plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.css create mode 100644 plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.js create mode 100644 plugins/talk-plugin-auth/client/stream/containers/AccountDeletionRequestedSign.js diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index bf412b1898..89ffd1130b 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -634,7 +634,32 @@ export const withRequestAccountDeletion = withMutation( { props: ({ mutate }) => ({ requestAccountDeletion: () => { - return mutate(); + return mutate({ + variables: {}, + update: proxy => { + const CancelAccountDeletionQuery = gql` + query Talk_CancelAccountDeletion { + me { + id + scheduledDeletionDate + } + } + `; + + const prev = proxy.readQuery({ query: CancelAccountDeletionQuery }); + + const data = update(prev, { + me: { + scheduledDeletionDate: { $set: new Date() }, + }, + }); + + proxy.writeQuery({ + query: CancelAccountDeletionQuery, + data, + }); + }, + }); }, }), } @@ -651,7 +676,9 @@ export const withRequestDownloadLink = withMutation( { props: ({ mutate }) => ({ requestDownloadLink: () => { - return mutate(); + return mutate({ + variables: {}, + }); }, }), } @@ -668,7 +695,32 @@ export const withCancelAccountDeletion = withMutation( { props: ({ mutate }) => ({ cancelAccountDeletion: () => { - return mutate(); + return mutate({ + variables: {}, + update: proxy => { + const CancelAccountDeletionQuery = gql` + query Talk_CancelAccountDeletion { + me { + id + scheduledDeletionDate + } + } + `; + + const prev = proxy.readQuery({ query: CancelAccountDeletionQuery }); + + const data = update(prev, { + me: { + scheduledDeletionDate: { $set: null }, + }, + }); + + proxy.writeQuery({ + query: CancelAccountDeletionQuery, + data, + }); + }, + }); }, }), } diff --git a/locales/en.yml b/locales/en.yml index 04fbc0bcbd..5806976a41 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -246,6 +246,7 @@ en: ALREADY_EXISTS: "Resource already exists" INVALID_ASSET_URL: "Assert URL is invalid" CANNOT_IGNORE_STAFF: "Cannot ignore Staff members." + DELETION_NOT_SCHEDULED: "Deletion was not scheduled" 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." diff --git a/plugins/talk-plugin-auth/client/index.js b/plugins/talk-plugin-auth/client/index.js index b432b05b20..98da589f8a 100644 --- a/plugins/talk-plugin-auth/client/index.js +++ b/plugins/talk-plugin-auth/client/index.js @@ -5,12 +5,18 @@ import translations from './translations.yml'; import Login from './login/containers/Main'; import reducer from './login/reducer'; import DeleteMyAccount from './profile-settings/containers/DeleteMyAccount'; +import AccountDeletionRequestedSign from './stream/containers/AccountDeletionRequestedSign'; export default { reducer, translations, slots: { - stream: [UserBox, SignInButton, SetUsernameDialog], + stream: [ + AccountDeletionRequestedSign, + UserBox, + SignInButton, + SetUsernameDialog, + ], login: [Login], profileSettings: [DeleteMyAccount], }, diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css b/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css deleted file mode 100644 index 413a3852b9..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.css +++ /dev/null @@ -1,23 +0,0 @@ -.container { - border : solid 1px #F26563; - border-radius: 2px; - color: #3B4A53; -} - -.button { - color: #787D80; - border-radius: 2px; - background-color: transparent; - height: 30px; - font-size: 0.9em; - line-height: normal; - - &:hover { - background-color: #eaeaea; - } - - &.secondary { - background-color: #787D80; - color: white; - } -} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js b/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js deleted file mode 100644 index 7d1941fa73..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/AccountDeletionRequestedSign.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import cn from 'classnames'; -import { Button, Icon } from 'plugin-api/beta/client/components/ui'; -import styles from './AccountDeletionRequestedSign.css'; - -class AccountDeletionRequestedSign extends React.Component { - render() { - return ( -
-

- Account Deletion Requested -

-

- A request to delete your account was received on. If you would like to - continue leaving comments, replies or reactions, you may cancel your - request to delete your account below before -

- -
- ); - } -} - -export default AccountDeletionRequestedSign; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.css b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.css index 2fe139d520..e524d990a8 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.css +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.css @@ -10,4 +10,14 @@ &:hover { background-color: #eaeaea; } + + &.secondary { + background-color: #787D80; + color: white; + } + + > i { + font-size: 1.2em; + vertical-align: middle; + } } \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js index 0fc06f3260..9bc5573a14 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import cn from 'classnames'; +import moment from 'moment'; import styles from './DeleteMyAccount.css'; import { Button } from 'plugin-api/beta/client/components/ui'; import DeleteMyAccountDialog from './DeleteMyAccountDialog'; @@ -52,6 +53,7 @@ class DeleteMyAccount extends React.Component {

Delete My Account

+

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

{scheduledDeletionDate && `You have already submitted a request to delete your account. - Your account will be deleted on ${scheduledDeletionDate}. You may + Your account will be deleted on ${moment( + scheduledDeletionDate + ).format('MMM Do YYYY, h:mm:ss a')}. You may cancel the request until that time`}

{scheduledDeletionDate ? ( diff --git a/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.css b/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.css new file mode 100644 index 0000000000..0dada08b51 --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.css @@ -0,0 +1,44 @@ +.container { + border: 1px solid #f26563; + border-radius: 2px; + color: #3b4a53; + padding: 20px 10px; + background-color: rgba(242, 101, 99, 0.1); + margin: 20px 0; +} + +.button { + color: #787D80; + border-radius: 2px; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; + + &:hover { + background-color: #eaeaea; + } + + &.secondary { + background-color: #787D80; + color: white; + } +} + +.title { + margin: 0; + i.icon { + font-size: 1em; + padding: 4px; + } +} + +.description { + margin: 0; + padding-left: 22px; + padding-bottom: 15px; +} + +.actions { + text-align: center; +} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.js b/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.js new file mode 100644 index 0000000000..a26d28d214 --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.js @@ -0,0 +1,55 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import { Button, Icon } from 'plugin-api/beta/client/components/ui'; +import styles from './AccountDeletionRequestedSign.css'; +import { getErrorMessages } from 'coral-framework/utils'; + +class AccountDeletionRequestedSign extends React.Component { + cancelAccountDeletion = async () => { + const { cancelAccountDeletion, notify } = this.props; + try { + await cancelAccountDeletion(); + notify( + 'success', + 'Account Deletion Request Cancelled - Your request to delete your account has been cancelled. You may now write comments, reply to comments, and select reactions.' + ); + } catch (err) { + notify('error', getErrorMessages(err)); + } + }; + + render() { + return ( +
+

+ Account Deletion + Requested +

+

+ A request to delete your account was received on. +

+

+ If you would like to continue leaving comments, replies or reactions, + you may cancel your request to delete your account below before +

+
+ +
+
+ ); + } +} + +AccountDeletionRequestedSign.propTypes = { + cancelAccountDeletion: PropTypes.func.isRequired, + notify: PropTypes.func.isRequired, + root: PropTypes.object.isRequired, +}; + +export default AccountDeletionRequestedSign; diff --git a/plugins/talk-plugin-auth/client/stream/containers/AccountDeletionRequestedSign.js b/plugins/talk-plugin-auth/client/stream/containers/AccountDeletionRequestedSign.js new file mode 100644 index 0000000000..d842ec43fb --- /dev/null +++ b/plugins/talk-plugin-auth/client/stream/containers/AccountDeletionRequestedSign.js @@ -0,0 +1,25 @@ +import { compose, gql } from 'react-apollo'; +import { bindActionCreators } from 'redux'; +import { connect, withFragments, excludeIf } from 'plugin-api/beta/client/hocs'; +import AccountDeletionRequestedSign from '../components/AccountDeletionRequestedSign'; +import { notify } from 'coral-framework/actions/notification'; +import { withCancelAccountDeletion } from 'plugin-api/beta/client/hocs'; + +const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); + +const withData = withFragments({ + root: gql` + fragment Talk_AccountDeletionRequestedSignIn_root on RootQuery { + me { + scheduledDeletionDate + } + } + `, +}); + +export default compose( + connect(null, mapDispatchToProps), + withCancelAccountDeletion, + withData, + excludeIf(props => !props.root.me.scheduledDeletionDate) +)(AccountDeletionRequestedSign); From 49fcc1ea43ab948480ed70919ef60110f57fe97c Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 17:30:57 -0300 Subject: [PATCH 030/133] Adding missing slot --- client/coral-embed-stream/src/tabs/stream/containers/Stream.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 0a7a1951c5..17d3132eae 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -372,6 +372,7 @@ const slots = [ 'streamTabsPrepend', 'streamTabPanes', 'streamFilter', + 'stream', ]; const fragments = { From d5fa7455e5d905aff4126d7fa6b2902ee6fd547e Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 1 May 2018 17:55:01 -0300 Subject: [PATCH 031/133] Adding InputField --- .../client/components/ErrorMessage.css | 8 + .../client/components/ErrorMessage.js | 17 ++ .../client/components/InputField.css | 80 +++++++ .../client/components/InputField.js | 94 ++++++++ .../components/ChangePassword.css | 87 +++++++ .../components/ChangePassword.js | 223 ++++++++++++++++++ .../components/ChangeUsername.css | 122 ++++++++++ .../components/ChangeUsername.js | 188 +++++++++++++++ .../components/ChangeUsernameDialog.css | 84 +++++++ .../components/ChangeUsernameDialog.js | 117 +++++++++ .../components/DeleteMyAccountDialog.js | 15 +- .../components/DeleteMyAccountStep3.js | 48 +++- .../components/ErrorMessage.css | 8 + .../components/ErrorMessage.js | 17 ++ .../components/InputField.css | 80 +++++++ .../profile-settings/components/InputField.js | 94 ++++++++ .../containers/ChangePassword.js | 12 + .../containers/ChangeUsername.js | 12 + 18 files changed, 1302 insertions(+), 4 deletions(-) create mode 100644 plugins/talk-plugin-auth/client/components/ErrorMessage.css create mode 100644 plugins/talk-plugin-auth/client/components/ErrorMessage.js create mode 100644 plugins/talk-plugin-auth/client/components/InputField.css create mode 100644 plugins/talk-plugin-auth/client/components/InputField.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js 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/components/ChangeUsernameDialog.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/InputField.css create mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/InputField.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js create mode 100644 plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js diff --git a/plugins/talk-plugin-auth/client/components/ErrorMessage.css b/plugins/talk-plugin-auth/client/components/ErrorMessage.css new file mode 100644 index 0000000000..039ffae305 --- /dev/null +++ b/plugins/talk-plugin-auth/client/components/ErrorMessage.css @@ -0,0 +1,8 @@ +.errorMsg { + color: #FA4643; + font-size: 0.9em; +} + +.warningIcon { + color: #FA4643; +} diff --git a/plugins/talk-plugin-auth/client/components/ErrorMessage.js b/plugins/talk-plugin-auth/client/components/ErrorMessage.js new file mode 100644 index 0000000000..f39a8fc084 --- /dev/null +++ b/plugins/talk-plugin-auth/client/components/ErrorMessage.js @@ -0,0 +1,17 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styles from './ErrorMessage.css'; +import { Icon } from 'plugin-api/beta/client/components/ui'; + +const ErrorMessage = ({ children }) => ( +
+ + {children} +
+); + +ErrorMessage.propTypes = { + children: PropTypes.node, +}; + +export default ErrorMessage; diff --git a/plugins/talk-plugin-auth/client/components/InputField.css b/plugins/talk-plugin-auth/client/components/InputField.css new file mode 100644 index 0000000000..3442befdeb --- /dev/null +++ b/plugins/talk-plugin-auth/client/components/InputField.css @@ -0,0 +1,80 @@ + +.detailItem { + margin-bottom: 12px; +} + +.detailItemContainer { + display: flex; +} + +.columnDisplay { + flex-direction: column; + + .detailItemMessage { + padding: 4px 0 0; + } +} + +.detailItemContent { + border: solid 1px #787D80; + border-radius: 2px; + background-color: white; + height: 30px; + display: inline-block; + width: 230px; + display: flex; + box-sizing: border-box; + + > .detailIcon { + font-size: 1.2em; + padding: 0 5px; + color: #787D80; + line-height: 30px; + } + + &.error { + border: solid 2px #FA4643; + } + + &.disabled { + background-color: #E0E0E0; + } +} + +.detailLabel { + color: #4C4C4D; + font-size: 1em; + display: block; + margin-bottom: 4px; +} + +.detailValue { + background: transparent; + border: none; + font-size: 1em; + color: #000; + outline: none; + flex: 1; + height: 100%; + box-sizing: border-box; +} + +.detailItemMessage { + flex-grow: 1; + display: flex; + align-items: center; + padding-left: 6px; + padding-top: 16px; + + .warningIcon, .checkIcon { + font-size: 17px; + } +} + +.checkIcon { + color: #00CD73; +} + +.warningIcon { + color: #FA4643; +} diff --git a/plugins/talk-plugin-auth/client/components/InputField.js b/plugins/talk-plugin-auth/client/components/InputField.js new file mode 100644 index 0000000000..26937d5b95 --- /dev/null +++ b/plugins/talk-plugin-auth/client/components/InputField.js @@ -0,0 +1,94 @@ +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'; + +const InputField = ({ + id = '', + label = '', + type = 'text', + name = '', + onChange = () => {}, + showError = true, + hasError = false, + errorMsg = '', + children, + columnDisplay = false, + showSuccess = false, + validationType = '', + icon = '', + value = '', + defaultValue = '', + disabled = false, +}) => { + const inputValue = { + ...(value ? { value } : {}), + ...(defaultValue ? { defaultValue } : {}), + }; + + return ( +
+
+ {label && ( + + )} +
+ {icon && } + +
+
+ {!hasError && + showSuccess && + value && } + {hasError && showError && {errorMsg}} +
+
+ {children} +
+ ); +}; + +InputField.propTypes = { + id: PropTypes.string, + disabled: PropTypes.bool, + 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, + children: PropTypes.node, + columnDisplay: PropTypes.bool, + showSuccess: PropTypes.bool, + validationType: PropTypes.string, +}; + +export default InputField; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css new file mode 100644 index 0000000000..6c7f9ae41f --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css @@ -0,0 +1,87 @@ +.container { + position: relative; + color: #202020; + padding: 10px; + border-radius: 2px; + border: solid 1px transparent; + box-sizing: border-box; + justify-content: space-between; + + &.editing { + border-color: #979797; + background-color: #EDEDED; + } +} + +.actions { + position: absolute; + top: 10px; + right: 10px; + display: flex; + flex-direction: column; + align-items: center; +} + +.title { + color: #202020; + margin: 0 0 20px; +} + +.detailBottomBox { + display: block; + padding-top: 4px; + text-align: right; + width: 280px; +} + +.detailLink { + color: #00538A; + text-decoration: none; + font-size: 0.9em; + &:hover { + cursor: pointer; + } +} + +.button { + border: 1px solid #787d80; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; +} + +.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; + } +} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js new file mode 100644 index 0000000000..90940728dd --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js @@ -0,0 +1,223 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import styles from './ChangePassword.css'; +import { Button } from 'plugin-api/beta/client/components/ui'; +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 InputField from './InputField'; +import { getErrorMessages } from 'coral-framework/utils'; + +const initialState = { + editing: false, + showErrors: true, + errors: {}, + formData: {}, +}; + +class ChangePassword extends React.Component { + state = initialState; + validKeys = ['oldPassword', 'newPassword', 'confirmNewPassword']; + + onChange = e => { + const { name, value, type } = e.target; + this.setState( + state => ({ + formData: { + ...state.formData, + [name]: value, + }, + }), + () => { + this.fieldValidation(value, type, name); + + // Perform equality validation if password fields have changed + if (name === 'newPassword' || name === 'confirmNewPassword') { + this.equalityValidation('newPassword', 'confirmNewPassword'); + } + } + ); + }; + + equalityValidation = (field, field2) => { + const cond = this.state.formData[field] === this.state.formData[field2]; + if (!cond) { + this.addError({ + [field2]: t('talk-plugin-auth.change_password.passwords_dont_match'), + }); + } else { + this.removeError(field2); + } + return cond; + }; + + 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 }, + })); + }; + + removeError = errKey => { + this.setState(state => { + const { [errKey]: _, ...errors } = state.errors; + return { + errors, + }; + }); + }; + + enableEditing = () => { + this.setState({ + editing: true, + }); + }; + + isSubmitBlocked = () => { + const formHasErrors = !!Object.keys(this.state.errors).length; + const formIncomplete = !isEqual( + Object.keys(this.state.formData), + this.validKeys + ); + return formHasErrors || formIncomplete; + }; + + clearForm = () => { + this.setState(initialState); + }; + + onSave = async () => { + const { oldPassword, newPassword } = this.state.formData; + + try { + await this.props.changePassword({ + oldPassword, + newPassword, + }); + this.props.notify( + 'success', + t('talk-plugin-auth.change_password.changed_password_msg') + ); + } catch (err) { + this.props.notify('error', getErrorMessages(err)); + } + + this.clearForm(); + this.disableEditing(); + }; + + disableEditing = () => { + this.setState({ + editing: false, + }); + }; + + cancel = () => { + this.clearForm(); + this.disableEditing(); + }; + + render() { + const { editing, errors } = this.state; + + return ( +
+

+ {t('talk-plugin-auth.change_password.change_password')} +

+ {editing && ( +
+ + + + {t('talk-plugin-auth.change_password.forgot_password')} + + + + + + + )} + {editing ? ( +
+ + + {t('talk-plugin-auth.change_password.cancel')} + +
+ ) : ( +
+ +
+ )} +
+ ); + } +} + +ChangePassword.propTypes = { + changePassword: PropTypes.func.isRequired, + notify: PropTypes.func.isRequired, +}; + +export default 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 0000000000..5b4631ecf9 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css @@ -0,0 +1,122 @@ +.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 { + margin-bottom: 4px; +} + +.button { + border: 1px solid #787d80; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; +} + +.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; +} + +.detailList { + list-style: none; + margin: 0; + padding: 0; +} + +.detailItem { + 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 new file mode 100644 index 0000000000..8188bdfbe1 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js @@ -0,0 +1,188 @@ +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 ChangeUsernameDialog from './ChangeUsernameDialog'; +import { t } from 'plugin-api/beta/client/services'; +import InputField from './InputField'; +import { getErrorMessages } from 'coral-framework/utils'; +import { canUsernameBeUpdated } from 'coral-framework/utils/user'; + +const initialState = { + editing: false, + showDialog: false, + formData: {}, +}; + +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(); + }; + + saveChanges = async () => { + const { newUsername } = this.state.formData; + const { changeUsername } = this.props; + + try { + await changeUsername(newUsername); + this.props.notify( + 'success', + t('talk-plugin-auth.change_username.changed_username_success_msg') + ); + } catch (err) { + this.props.notify('error', getErrorMessages(err)); + } + + this.clearForm(); + this.disableEditing(); + }; + + onChange = e => { + const { name, value } = e.target; + + this.setState(state => ({ + formData: { + ...state.formData, + [name]: value, + }, + })); + }; + + closeDialog = () => { + this.setState({ + showDialog: false, + }); + }; + + render() { + const { + username, + emailAddress, + root: { me: { state: { status } } }, + notify, + } = this.props; + const { editing, formData, showDialog } = this.state; + + return ( +
+ + + {editing ? ( +
+
+ + + {t('talk-plugin-auth.change_username.change_username_note')} + + + +
+
+ ) : ( +
+

{username}

+ {emailAddress ? ( +

{emailAddress}

+ ) : null} +
+ )} + {editing ? ( +
+ + + {t('talk-plugin-auth.change_username.cancel')} + +
+ ) : ( +
+ +
+ )} +
+ ); + } +} + +ChangeUsername.propTypes = { + root: PropTypes.object.isRequired, + changeUsername: PropTypes.func.isRequired, + notify: PropTypes.func.isRequired, + username: PropTypes.string, + emailAddress: PropTypes.string, +}; + +export default ChangeUsername; 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 0000000000..af681d5967 --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css @@ -0,0 +1,84 @@ +.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; + padding-top: 10px; + display: block; +} + +.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 0000000000..321b36926c --- /dev/null +++ b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js @@ -0,0 +1,117 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import styles from './ChangeUsernameDialog.css'; +import InputField from './InputField'; +import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; +import { t } from 'plugin-api/beta/client/services'; + +class ChangeUsernameDialog extends React.Component { + state = { + showError: false, + }; + + showError = () => { + this.setState({ + showError: true, + }); + }; + + confirmChanges = async () => { + if (this.formHasError()) { + this.showError(); + return; + } + + if (!this.props.canUsernameBeUpdated) { + this.props.notify( + 'error', + t('talk-plugin-auth.change_username.change_username_attempt') + ); + return; + } + + await this.props.saveChanges(); + this.props.closeDialog(); + }; + + formHasError = () => + this.props.formData.confirmNewUsername !== this.props.formData.newUsername; + + render() { + return ( + + + × + +

+ {t('talk-plugin-auth.change_username.confirm_username_change')} +

+
+

+ {t('talk-plugin-auth.change_username.description')} +

+
+ + {t('talk-plugin-auth.change_username.old_username')}:{' '} + {this.props.username} + + + {t('talk-plugin-auth.change_username.new_username')}:{' '} + {this.props.formData.newUsername} + +
+
+ + + {t('talk-plugin-auth.change_username.bottom_note')} + + +
+
+ + +
+
+
+ ); + } +} + +ChangeUsernameDialog.propTypes = { + saveChanges: PropTypes.func, + closeDialog: PropTypes.func, + showDialog: PropTypes.bool, + onChange: PropTypes.func, + username: PropTypes.string, + formData: PropTypes.object, + canUsernameBeUpdated: PropTypes.bool.isRequired, + notify: PropTypes.func.isRequired, +}; + +export default ChangeUsernameDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js index b9a1bfc9d0..35069384c5 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js @@ -9,7 +9,7 @@ import DeleteMyAccountStep2 from './DeleteMyAccountStep2'; import DeleteMyAccountStep3 from './DeleteMyAccountStep3'; import DeleteMyAccountFinalStep from './DeleteMyAccountFinalStep'; -const initialState = { step: 0 }; +const initialState = { step: 0, formData: {} }; class DeleteMyAccountDialog extends React.Component { state = initialState; @@ -29,6 +29,17 @@ class DeleteMyAccountDialog extends React.Component { this.props.closeDialog(); }; + onChange = e => { + const { name, value } = e.target; + + this.setState(state => ({ + formData: { + ...state.formData, + [name]: value, + }, + })); + }; + render() { const { step } = this.state; return ( @@ -58,9 +69,11 @@ class DeleteMyAccountDialog extends React.Component { )} {step === 3 && ( )} {step === 4 && } diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js index 63a00243b0..45dca8f977 100644 --- a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js @@ -3,13 +3,41 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; +import InputField from '../../components/InputField'; + +const initialState = { + showError: false, +}; class DeleteMyAccountStep3 extends React.Component { - deleteAndContinue = () => { - this.props.requestAccountDeletion(); + state = initialState; + phrase = 'delete'; + + showError = () => { + this.setState({ + showError: true, + }); + }; + + clear = () => { + this.setState(initialState); + }; + + deleteAndContinue = async () => { + if (this.formHasError()) { + this.showError(); + return; + } + + await this.props.requestAccountDeletion(); + this.clear(); this.props.goToNextStep(); }; + formHasError = () => + !this.props.formData.confirmPhrase || + this.props.formData.confirmPhrase !== this.phrase; + render() { return (
@@ -24,7 +52,19 @@ class DeleteMyAccountStep3 extends React.Component { className={styles.textBox} disabled={true} readOnly={true} - value="delete" + value={this.phrase} + /> +
- - {t('talk-plugin-auth.change_username.cancel')} - -
- ) : ( -
- -
- )} - - ); - } -} - -ChangeUsername.propTypes = { - root: PropTypes.object.isRequired, - changeUsername: PropTypes.func.isRequired, - notify: 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 deleted file mode 100644 index 87e1e18b55..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js +++ /dev/null @@ -1,12 +0,0 @@ -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 -); diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.css b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.css rename to plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeEmailContentDialog.js rename to plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css b/plugins/talk-plugin-local-auth/client/components/ChangePassword.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css rename to plugins/talk-plugin-local-auth/client/components/ChangePassword.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js rename to plugins/talk-plugin-local-auth/client/components/ChangePassword.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.css b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.css rename to plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameContentDialog.js rename to plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css rename to plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js rename to plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.css b/plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.css rename to plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js b/plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ConfirmChangesDialog.js rename to plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css b/plugins/talk-plugin-local-auth/client/components/ErrorMessage.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css rename to plugins/talk-plugin-local-auth/client/components/ErrorMessage.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js b/plugins/talk-plugin-local-auth/client/components/ErrorMessage.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js rename to plugins/talk-plugin-local-auth/client/components/ErrorMessage.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css b/plugins/talk-plugin-local-auth/client/components/InputField.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/InputField.css rename to plugins/talk-plugin-local-auth/client/components/InputField.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js b/plugins/talk-plugin-local-auth/client/components/InputField.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/InputField.js rename to plugins/talk-plugin-local-auth/client/components/InputField.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/Profile.css b/plugins/talk-plugin-local-auth/client/components/Profile.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/Profile.css rename to plugins/talk-plugin-local-auth/client/components/Profile.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/Profile.js b/plugins/talk-plugin-local-auth/client/components/Profile.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/Profile.js rename to plugins/talk-plugin-local-auth/client/components/Profile.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js b/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js rename to plugins/talk-plugin-local-auth/client/containers/ChangePassword.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/Profile.js b/plugins/talk-plugin-local-auth/client/containers/Profile.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/containers/Profile.js rename to plugins/talk-plugin-local-auth/client/containers/Profile.js diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js index ff8b4c5632..01f3f71233 100644 --- a/plugins/talk-plugin-local-auth/client/index.js +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -1 +1,9 @@ -export default {}; +import ChangePassword from './containers/ChangePassword'; +import Profile from './containers/Profile'; + +export default { + slots: { + profileHeader: [Profile], + profileSettings: [ChangePassword], + }, +}; From c57acddfc01547a1fc3d7842a0366d272022e78c Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 14:01:03 -0300 Subject: [PATCH 039/133] Moving gdpr to `talk-plugin-profile-data` --- plugins/talk-plugin-auth/client/index.js | 13 +- .../components/ChangePassword.css | 87 ------- .../components/ChangePassword.js | 223 ------------------ .../components/ChangeUsername.css | 122 ---------- .../components/ChangeUsername.js | 188 --------------- .../components/ChangeUsernameDialog.css | 84 ------- .../components/ChangeUsernameDialog.js | 117 --------- .../components/ErrorMessage.css | 8 - .../components/ErrorMessage.js | 17 -- .../components/InputField.css | 80 ------- .../profile-settings/components/InputField.js | 94 -------- .../containers/ChangePassword.js | 12 - .../containers/ChangeUsername.js | 12 - .../AccountDeletionRequestedSign.css | 0 .../AccountDeletionRequestedSign.js | 0 .../client}/components/DeleteMyAccount.css | 0 .../client}/components/DeleteMyAccount.js | 0 .../components/DeleteMyAccountDialog.css | 0 .../components/DeleteMyAccountDialog.js | 0 .../components/DeleteMyAccountFinalStep.js | 0 .../components/DeleteMyAccountStep.css | 0 .../components/DeleteMyAccountStep0.js | 0 .../components/DeleteMyAccountStep1.js | 0 .../components/DeleteMyAccountStep2.js | 0 .../components/DeleteMyAccountStep3.js | 0 .../client/components/ErrorMessage.css | 0 .../client/components/ErrorMessage.js | 0 .../client/components/InputField.css | 0 .../client/components/InputField.js | 0 .../client}/components/StepProgress.css | 0 .../client}/components/StepProgress.js | 0 .../AccountDeletionRequestedSign.js | 0 .../client}/containers/DeleteMyAccount.js | 0 .../talk-plugin-profile-data/client/index.js | 5 +- 34 files changed, 5 insertions(+), 1057 deletions(-) delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/InputField.css delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/components/InputField.js delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js delete mode 100644 plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js rename plugins/{talk-plugin-auth/client/stream => talk-plugin-profile-data/client}/components/AccountDeletionRequestedSign.css (100%) rename plugins/{talk-plugin-auth/client/stream => talk-plugin-profile-data/client}/components/AccountDeletionRequestedSign.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccount.css (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccount.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountDialog.css (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountDialog.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountFinalStep.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountStep.css (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountStep0.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountStep1.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountStep2.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/DeleteMyAccountStep3.js (100%) rename plugins/{talk-plugin-auth => talk-plugin-profile-data}/client/components/ErrorMessage.css (100%) rename plugins/{talk-plugin-auth => talk-plugin-profile-data}/client/components/ErrorMessage.js (100%) rename plugins/{talk-plugin-auth => talk-plugin-profile-data}/client/components/InputField.css (100%) rename plugins/{talk-plugin-auth => talk-plugin-profile-data}/client/components/InputField.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/StepProgress.css (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/components/StepProgress.js (100%) rename plugins/{talk-plugin-auth/client/stream => talk-plugin-profile-data/client}/containers/AccountDeletionRequestedSign.js (100%) rename plugins/{talk-plugin-auth/client/profile-settings => talk-plugin-profile-data/client}/containers/DeleteMyAccount.js (100%) diff --git a/plugins/talk-plugin-auth/client/index.js b/plugins/talk-plugin-auth/client/index.js index 0567497ae1..13abce1d99 100644 --- a/plugins/talk-plugin-auth/client/index.js +++ b/plugins/talk-plugin-auth/client/index.js @@ -4,23 +4,12 @@ import SetUsernameDialog from './stream/containers/SetUsernameDialog'; import translations from './translations.yml'; import Login from './login/containers/Main'; import reducer from './login/reducer'; -import DeleteMyAccount from './profile-settings/containers/DeleteMyAccount'; -import AccountDeletionRequestedSign from './stream/containers/AccountDeletionRequestedSign'; -import ChangePassword from './profile-settings/containers/ChangePassword'; -import ChangeUsername from './profile-settings/containers/ChangeUsername'; export default { reducer, translations, slots: { - stream: [ - AccountDeletionRequestedSign, - UserBox, - SignInButton, - SetUsernameDialog, - ], + stream: [UserBox, SignInButton, SetUsernameDialog], login: [Login], - profileHeader: [ChangeUsername], - profileSettings: [ChangePassword, DeleteMyAccount], }, }; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css deleted file mode 100644 index 6c7f9ae41f..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.css +++ /dev/null @@ -1,87 +0,0 @@ -.container { - position: relative; - color: #202020; - padding: 10px; - border-radius: 2px; - border: solid 1px transparent; - box-sizing: border-box; - justify-content: space-between; - - &.editing { - border-color: #979797; - background-color: #EDEDED; - } -} - -.actions { - position: absolute; - top: 10px; - right: 10px; - display: flex; - flex-direction: column; - align-items: center; -} - -.title { - color: #202020; - margin: 0 0 20px; -} - -.detailBottomBox { - display: block; - padding-top: 4px; - text-align: right; - width: 280px; -} - -.detailLink { - color: #00538A; - text-decoration: none; - font-size: 0.9em; - &:hover { - cursor: pointer; - } -} - -.button { - border: 1px solid #787d80; - background-color: transparent; - height: 30px; - font-size: 0.9em; - line-height: normal; -} - -.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; - } -} diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js b/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js deleted file mode 100644 index 90940728dd..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangePassword.js +++ /dev/null @@ -1,223 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import cn from 'classnames'; -import styles from './ChangePassword.css'; -import { Button } from 'plugin-api/beta/client/components/ui'; -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 InputField from './InputField'; -import { getErrorMessages } from 'coral-framework/utils'; - -const initialState = { - editing: false, - showErrors: true, - errors: {}, - formData: {}, -}; - -class ChangePassword extends React.Component { - state = initialState; - validKeys = ['oldPassword', 'newPassword', 'confirmNewPassword']; - - onChange = e => { - const { name, value, type } = e.target; - this.setState( - state => ({ - formData: { - ...state.formData, - [name]: value, - }, - }), - () => { - this.fieldValidation(value, type, name); - - // Perform equality validation if password fields have changed - if (name === 'newPassword' || name === 'confirmNewPassword') { - this.equalityValidation('newPassword', 'confirmNewPassword'); - } - } - ); - }; - - equalityValidation = (field, field2) => { - const cond = this.state.formData[field] === this.state.formData[field2]; - if (!cond) { - this.addError({ - [field2]: t('talk-plugin-auth.change_password.passwords_dont_match'), - }); - } else { - this.removeError(field2); - } - return cond; - }; - - 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 }, - })); - }; - - removeError = errKey => { - this.setState(state => { - const { [errKey]: _, ...errors } = state.errors; - return { - errors, - }; - }); - }; - - enableEditing = () => { - this.setState({ - editing: true, - }); - }; - - isSubmitBlocked = () => { - const formHasErrors = !!Object.keys(this.state.errors).length; - const formIncomplete = !isEqual( - Object.keys(this.state.formData), - this.validKeys - ); - return formHasErrors || formIncomplete; - }; - - clearForm = () => { - this.setState(initialState); - }; - - onSave = async () => { - const { oldPassword, newPassword } = this.state.formData; - - try { - await this.props.changePassword({ - oldPassword, - newPassword, - }); - this.props.notify( - 'success', - t('talk-plugin-auth.change_password.changed_password_msg') - ); - } catch (err) { - this.props.notify('error', getErrorMessages(err)); - } - - this.clearForm(); - this.disableEditing(); - }; - - disableEditing = () => { - this.setState({ - editing: false, - }); - }; - - cancel = () => { - this.clearForm(); - this.disableEditing(); - }; - - render() { - const { editing, errors } = this.state; - - return ( -
-

- {t('talk-plugin-auth.change_password.change_password')} -

- {editing && ( -
- - - - {t('talk-plugin-auth.change_password.forgot_password')} - - - - - - - )} - {editing ? ( -
- - - {t('talk-plugin-auth.change_password.cancel')} - -
- ) : ( -
- -
- )} -
- ); - } -} - -ChangePassword.propTypes = { - changePassword: PropTypes.func.isRequired, - notify: PropTypes.func.isRequired, -}; - -export default 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 deleted file mode 100644 index 5b4631ecf9..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.css +++ /dev/null @@ -1,122 +0,0 @@ -.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 { - margin-bottom: 4px; -} - -.button { - border: 1px solid #787d80; - background-color: transparent; - height: 30px; - font-size: 0.9em; - line-height: normal; -} - -.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; -} - -.detailList { - list-style: none; - margin: 0; - padding: 0; -} - -.detailItem { - 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 deleted file mode 100644 index 8188bdfbe1..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsername.js +++ /dev/null @@ -1,188 +0,0 @@ -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 ChangeUsernameDialog from './ChangeUsernameDialog'; -import { t } from 'plugin-api/beta/client/services'; -import InputField from './InputField'; -import { getErrorMessages } from 'coral-framework/utils'; -import { canUsernameBeUpdated } from 'coral-framework/utils/user'; - -const initialState = { - editing: false, - showDialog: false, - formData: {}, -}; - -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(); - }; - - saveChanges = async () => { - const { newUsername } = this.state.formData; - const { changeUsername } = this.props; - - try { - await changeUsername(newUsername); - this.props.notify( - 'success', - t('talk-plugin-auth.change_username.changed_username_success_msg') - ); - } catch (err) { - this.props.notify('error', getErrorMessages(err)); - } - - this.clearForm(); - this.disableEditing(); - }; - - onChange = e => { - const { name, value } = e.target; - - this.setState(state => ({ - formData: { - ...state.formData, - [name]: value, - }, - })); - }; - - closeDialog = () => { - this.setState({ - showDialog: false, - }); - }; - - render() { - const { - username, - emailAddress, - root: { me: { state: { status } } }, - notify, - } = this.props; - const { editing, formData, showDialog } = this.state; - - return ( -
- - - {editing ? ( -
-
- - - {t('talk-plugin-auth.change_username.change_username_note')} - - - -
-
- ) : ( -
-

{username}

- {emailAddress ? ( -

{emailAddress}

- ) : null} -
- )} - {editing ? ( -
- - - {t('talk-plugin-auth.change_username.cancel')} - -
- ) : ( -
- -
- )} -
- ); - } -} - -ChangeUsername.propTypes = { - root: PropTypes.object.isRequired, - changeUsername: PropTypes.func.isRequired, - notify: PropTypes.func.isRequired, - username: PropTypes.string, - emailAddress: PropTypes.string, -}; - -export default ChangeUsername; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css b/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css deleted file mode 100644 index af681d5967..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.css +++ /dev/null @@ -1,84 +0,0 @@ -.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; - padding-top: 10px; - display: block; -} - -.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 deleted file mode 100644 index 321b36926c..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ChangeUsernameDialog.js +++ /dev/null @@ -1,117 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import cn from 'classnames'; -import styles from './ChangeUsernameDialog.css'; -import InputField from './InputField'; -import { Button, Dialog } from 'plugin-api/beta/client/components/ui'; -import { t } from 'plugin-api/beta/client/services'; - -class ChangeUsernameDialog extends React.Component { - state = { - showError: false, - }; - - showError = () => { - this.setState({ - showError: true, - }); - }; - - confirmChanges = async () => { - if (this.formHasError()) { - this.showError(); - return; - } - - if (!this.props.canUsernameBeUpdated) { - this.props.notify( - 'error', - t('talk-plugin-auth.change_username.change_username_attempt') - ); - return; - } - - await this.props.saveChanges(); - this.props.closeDialog(); - }; - - formHasError = () => - this.props.formData.confirmNewUsername !== this.props.formData.newUsername; - - render() { - return ( - - - × - -

- {t('talk-plugin-auth.change_username.confirm_username_change')} -

-
-

- {t('talk-plugin-auth.change_username.description')} -

-
- - {t('talk-plugin-auth.change_username.old_username')}:{' '} - {this.props.username} - - - {t('talk-plugin-auth.change_username.new_username')}:{' '} - {this.props.formData.newUsername} - -
-
- - - {t('talk-plugin-auth.change_username.bottom_note')} - - -
-
- - -
-
-
- ); - } -} - -ChangeUsernameDialog.propTypes = { - saveChanges: PropTypes.func, - closeDialog: PropTypes.func, - showDialog: PropTypes.bool, - onChange: PropTypes.func, - username: PropTypes.string, - formData: PropTypes.object, - canUsernameBeUpdated: PropTypes.bool.isRequired, - notify: PropTypes.func.isRequired, -}; - -export default ChangeUsernameDialog; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css b/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css deleted file mode 100644 index abcf692fe5..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.css +++ /dev/null @@ -1,8 +0,0 @@ -.errorMsg { - color: #FA4643; - font-size: 0.9em; -} - -.warningIcon { - color: #FA4643; -} \ No newline at end of file diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js b/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js deleted file mode 100644 index f39a8fc084..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/ErrorMessage.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import styles from './ErrorMessage.css'; -import { Icon } from 'plugin-api/beta/client/components/ui'; - -const ErrorMessage = ({ children }) => ( -
- - {children} -
-); - -ErrorMessage.propTypes = { - children: PropTypes.node, -}; - -export default ErrorMessage; diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css b/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css deleted file mode 100644 index cd6015e479..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.css +++ /dev/null @@ -1,80 +0,0 @@ - -.detailItem { - margin-bottom: 12px; -} - -.detailItemContainer { - display: flex; -} - -.columnDisplay { - flex-direction: column; - - .detailItemMessage { - padding: 4px 0 0; - } -} - -.detailItemContent { - border: solid 1px #787D80; - border-radius: 2px; - background-color: white; - height: 30px; - display: inline-block; - width: 230px; - display: flex; - box-sizing: border-box; - - > .detailIcon { - font-size: 1.2em; - padding: 0 5px; - color: #787D80; - line-height: 30px; - } - - &.error { - border: solid 2px #FA4643; - } - - &.disabled { - background-color: #E0E0E0; - } -} - -.detailLabel { - color: #4C4C4D; - font-size: 1em; - display: block; - margin-bottom: 4px; -} - -.detailValue { - background: transparent; - border: none; - font-size: 1em; - color: #000; - outline: none; - flex: 1; - height: 100%; - box-sizing: border-box; -} - -.detailItemMessage { - flex-grow: 1; - display: flex; - align-items: center; - padding-left: 6px; - padding-top: 16px; - - .warningIcon, .checkIcon { - font-size: 17px; - } -} - -.checkIcon { - color: #00CD73; -} - -.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 deleted file mode 100644 index 34c314c20e..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/components/InputField.js +++ /dev/null @@ -1,94 +0,0 @@ -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'; - -const InputField = ({ - id = '', - label = '', - type = 'text', - name = '', - onChange = () => {}, - showError = true, - hasError = false, - errorMsg = '', - children, - columnDisplay = false, - showSuccess = false, - validationType = '', - icon = '', - value = '', - defaultValue = '', - disabled = false, -}) => { - const inputValue = { - ...(value ? { value } : {}), - ...(defaultValue ? { defaultValue } : {}), - }; - - return ( -
-
- {label && ( - - )} -
- {icon && } - -
-
- {!hasError && - showSuccess && - value && } - {hasError && showError && {errorMsg}} -
-
- {children} -
- ); -}; - -InputField.propTypes = { - id: PropTypes.string, - disabled: PropTypes.bool, - 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, - children: PropTypes.node, - columnDisplay: PropTypes.bool, - showSuccess: PropTypes.bool, - validationType: PropTypes.string, -}; - -export default InputField; diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js b/plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js deleted file mode 100644 index 1322a2940b..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangePassword.js +++ /dev/null @@ -1,12 +0,0 @@ -import { compose } from 'react-apollo'; -import { bindActionCreators } from 'redux'; -import { connect } from 'plugin-api/beta/client/hocs'; -import ChangePassword from '../components/ChangePassword'; -import { notify } from 'coral-framework/actions/notification'; -import { withChangePassword } from 'plugin-api/beta/client/hocs'; - -const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); - -export default compose(connect(null, mapDispatchToProps), withChangePassword)( - ChangePassword -); diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js b/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js deleted file mode 100644 index 87e1e18b55..0000000000 --- a/plugins/talk-plugin-auth/client/profile-settings/containers/ChangeUsername.js +++ /dev/null @@ -1,12 +0,0 @@ -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 -); diff --git a/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.css b/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.css similarity index 100% rename from plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.css rename to plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.css diff --git a/plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.js b/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js similarity index 100% rename from plugins/talk-plugin-auth/client/stream/components/AccountDeletionRequestedSign.js rename to plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.css b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.css rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccount.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.css rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountDialog.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountFinalStep.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep.css rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep0.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep0.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep0.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep1.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep2.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep2.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep2.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/DeleteMyAccountStep3.js rename to plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js diff --git a/plugins/talk-plugin-auth/client/components/ErrorMessage.css b/plugins/talk-plugin-profile-data/client/components/ErrorMessage.css similarity index 100% rename from plugins/talk-plugin-auth/client/components/ErrorMessage.css rename to plugins/talk-plugin-profile-data/client/components/ErrorMessage.css diff --git a/plugins/talk-plugin-auth/client/components/ErrorMessage.js b/plugins/talk-plugin-profile-data/client/components/ErrorMessage.js similarity index 100% rename from plugins/talk-plugin-auth/client/components/ErrorMessage.js rename to plugins/talk-plugin-profile-data/client/components/ErrorMessage.js diff --git a/plugins/talk-plugin-auth/client/components/InputField.css b/plugins/talk-plugin-profile-data/client/components/InputField.css similarity index 100% rename from plugins/talk-plugin-auth/client/components/InputField.css rename to plugins/talk-plugin-profile-data/client/components/InputField.css diff --git a/plugins/talk-plugin-auth/client/components/InputField.js b/plugins/talk-plugin-profile-data/client/components/InputField.js similarity index 100% rename from plugins/talk-plugin-auth/client/components/InputField.js rename to plugins/talk-plugin-profile-data/client/components/InputField.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css b/plugins/talk-plugin-profile-data/client/components/StepProgress.css similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.css rename to plugins/talk-plugin-profile-data/client/components/StepProgress.css diff --git a/plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js b/plugins/talk-plugin-profile-data/client/components/StepProgress.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/components/StepProgress.js rename to plugins/talk-plugin-profile-data/client/components/StepProgress.js diff --git a/plugins/talk-plugin-auth/client/stream/containers/AccountDeletionRequestedSign.js b/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js similarity index 100% rename from plugins/talk-plugin-auth/client/stream/containers/AccountDeletionRequestedSign.js rename to plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js diff --git a/plugins/talk-plugin-auth/client/profile-settings/containers/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js similarity index 100% rename from plugins/talk-plugin-auth/client/profile-settings/containers/DeleteMyAccount.js rename to plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js diff --git a/plugins/talk-plugin-profile-data/client/index.js b/plugins/talk-plugin-profile-data/client/index.js index fee9f21299..91664ac23c 100644 --- a/plugins/talk-plugin-profile-data/client/index.js +++ b/plugins/talk-plugin-profile-data/client/index.js @@ -1,10 +1,13 @@ import DownloadCommentHistory from './containers/DownloadCommentHistory'; +import DeleteMyAccount from './containers/DeleteMyAccount'; +import AccountDeletionRequestedSign from './AccountDeletionRequestedSign'; import translations from './translations.yml'; import graphql from './graphql'; export default { slots: { - profileSettings: [DownloadCommentHistory], + stream: [AccountDeletionRequestedSign], + profileSettings: [DownloadCommentHistory, DeleteMyAccount], }, translations, ...graphql, From 58cc078d256c8e6242f61490b888a99ae18c0549 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 14:03:21 -0300 Subject: [PATCH 040/133] Moving gdpr to `talk-plugin-profile-data` --- .../client/components/DeleteMyAccountStep3.js | 2 +- plugins/talk-plugin-profile-data/client/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js index 45dca8f977..3205cd2252 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; -import InputField from '../../components/InputField'; +import InputField from './InputField'; const initialState = { showError: false, diff --git a/plugins/talk-plugin-profile-data/client/index.js b/plugins/talk-plugin-profile-data/client/index.js index 91664ac23c..bbd30b6605 100644 --- a/plugins/talk-plugin-profile-data/client/index.js +++ b/plugins/talk-plugin-profile-data/client/index.js @@ -1,6 +1,6 @@ import DownloadCommentHistory from './containers/DownloadCommentHistory'; import DeleteMyAccount from './containers/DeleteMyAccount'; -import AccountDeletionRequestedSign from './AccountDeletionRequestedSign'; +import AccountDeletionRequestedSign from './containers/AccountDeletionRequestedSign'; import translations from './translations.yml'; import graphql from './graphql'; From 8dcaf8ea4caf34dcad7eb065032f702dfa229f97 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 14:08:29 -0300 Subject: [PATCH 041/133] Moving the translations too --- .../components/ChangeEmailContentDialog.js | 18 +++--- .../client/components/ChangePassword.js | 30 +++++---- .../components/ChangeUsernameContentDialog.js | 18 +++--- .../client/components/ChangeUsernameDialog.js | 23 ++++--- .../client/components/ConfirmChangesDialog.js | 5 +- .../client/components/Profile.js | 26 +++++--- .../client/translations.yml | 62 +++++++++++++++++++ 7 files changed, 132 insertions(+), 50 deletions(-) create mode 100644 plugins/talk-plugin-local-auth/client/translations.yml diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js index e3796f80e8..02d02680ec 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js @@ -28,26 +28,26 @@ class ChangeEmailContentDialog extends React.Component { ×

- {t('talk-plugin-auth.change_email.confirm_email_change')} + {t('talk-plugin-local-auth.change_email.confirm_email_change')}

- {t('talk-plugin-auth.change_email.description')} + {t('talk-plugin-local-auth.change_email.description')}

- {t('talk-plugin-auth.change_email.old_email')}:{' '} + {t('talk-plugin-local-auth.change_email.old_email')}:{' '} {this.props.emailAddress} - {t('talk-plugin-auth.change_email.new_email')}:{' '} + {t('talk-plugin-local-auth.change_email.new_email')}:{' '} {this.props.formData.newEmail}
diff --git a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js index 90940728dd..e5535b8ba9 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js @@ -45,7 +45,9 @@ class ChangePassword extends React.Component { const cond = this.state.formData[field] === this.state.formData[field2]; if (!cond) { this.addError({ - [field2]: t('talk-plugin-auth.change_password.passwords_dont_match'), + [field2]: t( + 'talk-plugin-local-auth.change_password.passwords_dont_match' + ), }); } else { this.removeError(field2); @@ -56,7 +58,7 @@ class ChangePassword extends React.Component { fieldValidation = (value, type, name) => { if (!value.length) { this.addError({ - [name]: t('talk-plugin-auth.change_password.required_field'), + [name]: t('talk-plugin-local-auth.change_password.required_field'), }); } else if (!validate[type](value)) { this.addError({ [name]: errorMsj[type] }); @@ -113,7 +115,7 @@ class ChangePassword extends React.Component { }); this.props.notify( 'success', - t('talk-plugin-auth.change_password.changed_password_msg') + t('talk-plugin-local-auth.change_password.changed_password_msg') ); } catch (err) { this.props.notify('error', getErrorMessages(err)); @@ -139,15 +141,19 @@ class ChangePassword extends React.Component { return (

- {t('talk-plugin-auth.change_password.change_password')} + {t('talk-plugin-local-auth.change_password.change_password')}

{editing && ( - + - {t('talk-plugin-auth.change_password.forgot_password')} + {t('talk-plugin-local-auth.change_password.forgot_password')} @@ -197,16 +203,16 @@ class ChangePassword extends React.Component { onClick={this.onSave} disabled={this.isSubmitBlocked()} > - {t('talk-plugin-auth.change_password.save')} + {t('talk-plugin-local-auth.change_password.save')} - {t('talk-plugin-auth.change_password.cancel')} + {t('talk-plugin-local-auth.change_password.cancel')}
) : (
)} diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js index 408f3d836c..894bdcbd66 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js @@ -25,7 +25,7 @@ class ChangeUsernameContentDialog extends React.Component { if (!this.props.canUsernameBeUpdated) { this.props.notify( 'error', - t('talk-plugin-auth.change_username.change_username_attempt') + t('talk-plugin-local-auth.change_username.change_username_attempt') ); return; } @@ -44,19 +44,19 @@ class ChangeUsernameContentDialog extends React.Component { ×

- {t('talk-plugin-auth.change_username.confirm_username_change')} + {t('talk-plugin-local-auth.change_username.confirm_username_change')}

- {t('talk-plugin-auth.change_username.description')} + {t('talk-plugin-local-auth.change_username.description')}

- {t('talk-plugin-auth.change_username.old_username')}:{' '} + {t('talk-plugin-local-auth.change_username.old_username')}:{' '} {this.props.username} - {t('talk-plugin-auth.change_username.new_username')}:{' '} + {t('talk-plugin-local-auth.change_username.new_username')}:{' '} {this.props.formData.newUsername}
@@ -70,7 +70,7 @@ class ChangeUsernameContentDialog extends React.Component { defaultValue="" hasError={this.formHasError() && this.state.showError} errorMsg={t( - 'talk-plugin-auth.change_username.username_does_not_match' + 'talk-plugin-local-auth.change_username.username_does_not_match' )} showError={this.state.showError} columnDisplay @@ -78,19 +78,19 @@ class ChangeUsernameContentDialog extends React.Component { validationType="username" > - {t('talk-plugin-auth.change_username.bottom_note')} + {t('talk-plugin-local-auth.change_username.bottom_note')}
diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.js index 321b36926c..097168b06f 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameDialog.js @@ -26,7 +26,7 @@ class ChangeUsernameDialog extends React.Component { if (!this.props.canUsernameBeUpdated) { this.props.notify( 'error', - t('talk-plugin-auth.change_username.change_username_attempt') + t('talk-plugin-local-auth.change_username.change_username_attempt') ); return; } @@ -42,25 +42,28 @@ class ChangeUsernameDialog extends React.Component { return ( ×

- {t('talk-plugin-auth.change_username.confirm_username_change')} + {t('talk-plugin-local-auth.change_username.confirm_username_change')}

- {t('talk-plugin-auth.change_username.description')} + {t('talk-plugin-local-auth.change_username.description')}

- {t('talk-plugin-auth.change_username.old_username')}:{' '} + {t('talk-plugin-local-auth.change_username.old_username')}:{' '} {this.props.username} - {t('talk-plugin-auth.change_username.new_username')}:{' '} + {t('talk-plugin-local-auth.change_username.new_username')}:{' '} {this.props.formData.newUsername}
@@ -74,7 +77,7 @@ class ChangeUsernameDialog extends React.Component { defaultValue="" hasError={this.formHasError() && this.state.showError} errorMsg={t( - 'talk-plugin-auth.change_username.username_does_not_match' + 'talk-plugin-local-auth.change_username.username_does_not_match' )} showError={this.state.showError} columnDisplay @@ -82,19 +85,19 @@ class ChangeUsernameDialog extends React.Component { validationType="username" > - {t('talk-plugin-auth.change_username.bottom_note')} + {t('talk-plugin-local-auth.change_username.bottom_note')}
diff --git a/plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.js b/plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.js index 0031bcb71a..35995f6545 100644 --- a/plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ConfirmChangesDialog.js @@ -54,7 +54,10 @@ class ConfirmChangesDialog extends React.Component { return ( {this.renderSteps()} diff --git a/plugins/talk-plugin-local-auth/client/components/Profile.js b/plugins/talk-plugin-local-auth/client/components/Profile.js index 3d8f10698c..84474dbe39 100644 --- a/plugins/talk-plugin-local-auth/client/components/Profile.js +++ b/plugins/talk-plugin-local-auth/client/components/Profile.js @@ -72,7 +72,7 @@ class Profile extends React.Component { fieldValidation = (value, type, name) => { if (!value.length) { this.addError({ - [name]: t('talk-plugin-auth.change_password.required_field'), + [name]: t('talk-plugin-local-auth.change_password.required_field'), }); } else if (!validate[type](value)) { this.addError({ [name]: errorMsj[type] }); @@ -127,7 +127,7 @@ class Profile extends React.Component { await changeUsername(this.props.root.me.id, newUsername); this.props.notify( 'success', - t('talk-plugin-auth.change_username.changed_username_success_msg') + t('talk-plugin-local-auth.change_username.changed_username_success_msg') ); } catch (err) { this.props.notify('error', getErrorMessages(err)); @@ -144,7 +144,7 @@ class Profile extends React.Component { }); this.props.notify( 'success', - t('talk-plugin-auth.change_email.change_email_msg') + t('talk-plugin-local-auth.change_email.change_email_msg') ); } catch (err) { this.props.notify('error', getErrorMessages(err)); @@ -167,9 +167,13 @@ class Profile extends React.Component { return (
- {t('talk-plugin-auth.change_username.change_username_note')} + {t( + 'talk-plugin-local-auth.change_username.change_username_note' + )} - {t('talk-plugin-auth.change_username.save')} + {t('talk-plugin-local-auth.change_username.save')} - {t('talk-plugin-auth.change_username.cancel')} + {t('talk-plugin-local-auth.change_username.cancel')}
) : ( @@ -250,7 +256,7 @@ class Profile extends React.Component { icon="settings" onClick={this.enableEditing} > - {t('talk-plugin-auth.change_username.edit_profile')} + {t('talk-plugin-local-auth.change_username.edit_profile')}
)} diff --git a/plugins/talk-plugin-local-auth/client/translations.yml b/plugins/talk-plugin-local-auth/client/translations.yml new file mode 100644 index 0000000000..d3b323f546 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/translations.yml @@ -0,0 +1,62 @@ +en: + talk-plugin-local-auth: + change_password: + change_password: "Change Password" + passwords_dont_match: "Passwords don`t match" + required_field: "This field is required" + forgot_password: "Forgot your password?" + save: "Save" + cancel: "Cancel" + edit: "Edit" + changed_password_msg: "Changed Password - Your password has been successfully changed" + change_username: + change_username_note: "Usernames can be changed every 14 days" + 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" + username_does_not_match: "Username does not match" + cant_be_equal: "Your new {0} must be different to your current one" + change_username_attempt: "Username can't be updated. Usernames can be changed every 14 days" + change_email: + confirm_email_change: "Confirm Email Address Change" + description: "You are attempting to change your email address. Your new email address will be used for your login and to receive account notifications." + old_email: "Old Email Address" + new_email: "New Email Address" + enter_password: "Enter Password" + incorrect_password: "Incorrect Password" + confirm_change: "Confirm Change" + cancel: "Cancel" + change_email_msg: "Email Address Changed - Your email address has been successfully changed. This email address will now be used for signing in and email notifications." + changed_username_success_msg: "Username Changed - Your username has been successfully changed. You will not be able to change your user name for 14 days." + change_username_attempt: "Username can't be updated. Usernames can only be changed every 14 days." +es: + talk-plugin-local-auth: + change_password: + change_password: "Cambiar Contraseña" + passwords_dont_match: "Las contraseñas no coinciden" + required_field: "Este campo es requerido" + forgot_password: "Olvidaste tu contraseña?" + save: "Guardar" + cancel: "Cancelar" + edit: "Editar" + changed_password_msg: "Contraseña Actualizada - Tu contraseña ha sido exitosamente actualizada" + change_username: + change_username_note: "El usuario puede ser cambiado cada 14 días" + save: "Guardar" + edit_profile: "Editar Perfil" + cancel: "Cancelar" + confirm_username_change: "Confirmar Cambio de Usuario" + description: "Estás intentando cambiar tu usuario. Tu nuevo usuario aparecerá en todos tus pasados y futuros comentarios." + old_username: "Usuario viejo" + new_username: "Usuario nuevo" + bottom_note: "Nota: No podrás cambiar tu usuario por 14 días" + confirm_changes: "Confirmar Cambios" + username_does_not_match: "El usuario no coincide" + changed_username_success_msg: "Usuario Actualizado - Tu usuario ha sido exitosamente actualizado. No podrás cambiar el usuario por 14 días." + change_username_attempt: "El usuario no puede ser actualizado. Los usuarios pueden ser cambiados cada 14 días." \ No newline at end of file From 48a78735bd4d099a40fdb33a7dc531d9d9390014 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 14:11:11 -0300 Subject: [PATCH 042/133] Importing translations --- plugins/talk-plugin-local-auth/client/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js index 01f3f71233..c669effaa8 100644 --- a/plugins/talk-plugin-local-auth/client/index.js +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -1,7 +1,9 @@ import ChangePassword from './containers/ChangePassword'; import Profile from './containers/Profile'; +import translations from './translations.yml'; export default { + translations, slots: { profileHeader: [Profile], profileSettings: [ChangePassword], From c8e5678c9c7eb4d67d64a8a958ddf3af62127bc8 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 14:18:40 -0300 Subject: [PATCH 043/133] Using fragments :) --- .../client/containers/Profile.js | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/containers/Profile.js b/plugins/talk-plugin-local-auth/client/containers/Profile.js index d47f4af387..bebf127fda 100644 --- a/plugins/talk-plugin-local-auth/client/containers/Profile.js +++ b/plugins/talk-plugin-local-auth/client/containers/Profile.js @@ -1,6 +1,6 @@ -import { compose } from 'react-apollo'; +import { compose, gql } from 'react-apollo'; import { bindActionCreators } from 'redux'; -import { connect } from 'plugin-api/beta/client/hocs'; +import { connect, withFragments } from 'plugin-api/beta/client/hocs'; import Profile from '../components/Profile'; import { notify } from 'coral-framework/actions/notification'; import { @@ -10,8 +10,30 @@ import { const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); +const withData = withFragments({ + root: gql` + fragment TalkPluginLocalAuth_Profile_root on RootQuery { + me { + id + state { + status { + username { + status + history { + status + created_at + } + } + } + } + } + } + `, +}); + export default compose( connect(null, mapDispatchToProps), withChangeUsername, - withUpdateEmailAddress + withUpdateEmailAddress, + withData )(Profile); From cb9b02c1801e73109da40454c33850646363c7f7 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Wed, 2 May 2018 14:20:19 -0400 Subject: [PATCH 044/133] remove profile-settings from gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9373b18930..24022b9d7f 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,6 @@ plugins/* !plugins/talk-plugin-offtopic !plugins/talk-plugin-permalink !plugins/talk-plugin-profile-data -!plugins/talk-plugin-profile-settings !plugins/talk-plugin-remember-sort !plugins/talk-plugin-respect !plugins/talk-plugin-rich-text From 0159918049790875f727d0541a5155ab00bf6cad Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 2 May 2018 13:03:59 -0600 Subject: [PATCH 045/133] docs updates --- docs/_config.yml | 4 +- docs/source/03-08-gdpr.md | 43 +++++++++++++++++++++ docs/source/_data/plugins.yml | 2 + docs/source/plugins/overview.md | 19 +++++++-- docs/source/plugins/plugins-directory.md | 3 +- docs/themes/coral/layout/plugins.swig | 9 +++-- docs/themes/coral/source/css/talk.scss | 14 +++++++ docs/themes/coral/source/js/plugins.js | 17 ++++++++ plugins/talk-plugin-auth/README.md | 6 +++ plugins/talk-plugin-facebook-auth/README.md | 8 +++- plugins/talk-plugin-google-auth/README.md | 6 +++ plugins/talk-plugin-local-auth/README.md | 6 +++ plugins/talk-plugin-profile-data/README.md | 11 +++++- 13 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 docs/source/03-08-gdpr.md diff --git a/docs/_config.yml b/docs/_config.yml index 6c0da733b9..ac90dbc96e 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -41,7 +41,7 @@ relative_link: false future: true highlight: enable: false - + # Home page setting # path: Root path for your blogs index page. (default = '') # per_page: Posts displayed per page. (0 = disable pagination) @@ -114,6 +114,8 @@ sidebar: url: /integrating/styling-css/ - title: Translations and i18n url: /integrating/translations-i18n/ + - title: GDPR Compliance + url: /integrating/gdpr/ - title: Product Guide children: - title: How Talk Works diff --git a/docs/source/03-08-gdpr.md b/docs/source/03-08-gdpr.md new file mode 100644 index 0000000000..187920bbcb --- /dev/null +++ b/docs/source/03-08-gdpr.md @@ -0,0 +1,43 @@ +--- +title: GDPR Compliance +permalink: /integrating/gdpr/ +--- + +In order to facilitate compliance with the +[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), you +can enable the following plugins: + +- [talk-plugin-auth](/talk/plugin/talk-plugin-auth) - to facilitate username and password changes +- [talk-plugin-local-auth](/talk/plugin/talk-plugin-local-auth) - to facilitate email changes and email association +- [talk-plugin-profile-data](/talk/plugin/talk-plugin-profile-data) - to facilitate account download and deletion + +Even if you don't reside in a location where GDPR will apply, it is recommended +to enable these features anyways to provide your users with control over their +own data. + +## Custom Authentication Solutions + +As many of the newsrooms who have integrated Talk have followed our guides on +[Integrating Authentication](/talk/integrating/authentication/), we have also +provided tools for those newsrooms to integrate GDPR features into their +existing workflows. + +### Account Data + +Through the [talk-plugin-profile-data](/talk/plugin/talk-plugin-profile-data) +plugin we allow users to download and delete their account data easily. For +custom integrations, this isn't always possible, so we instead provide some +GraphQL mutations designed to allow you to integrate it into your existing user +interfaces or exports. + +- `downloadUser(id: ID!)` - lets you grab the direct link to download a users + account in a zip format. From there, you can integrate it into your existing + data export or simply proxy it to the user to allow them to download it + elsewhere in your UI. +- `delUser(id: ID!)` - lets you delete the specified user + +**Note: These mutations require an administrative token** + +If you would prefer to write your own user interfaces or integrate it into your +own, you can disable the client plugin for [talk-plugin-profile-data](/talk/plugin/talk-plugin-profile-data) +but keep the server side plugin active (See [Server and Client Plugins](/talk/plugins/#server-and-client-plugins) for more information). diff --git a/docs/source/_data/plugins.yml b/docs/source/_data/plugins.yml index 35d88cb141..0e09de2107 100644 --- a/docs/source/_data/plugins.yml +++ b/docs/source/_data/plugins.yml @@ -7,11 +7,13 @@ tags: - default - auth + - gdpr - name: talk-plugin-local-auth description: Enables email and password based authentication. tags: - default - auth + - gdpr - name: talk-plugin-author-menu description: Enables the comment author name plugin area. tags: diff --git a/docs/source/plugins/overview.md b/docs/source/plugins/overview.md index 26230dc001..046f4db875 100644 --- a/docs/source/plugins/overview.md +++ b/docs/source/plugins/overview.md @@ -9,11 +9,16 @@ functionality. We provide methods to inject behavior into the server side and the client side application to affect different parts of the application life cycle. -## Recipes +## Server and Client Plugins -Recipes are plugin templates provided by the Coral Core team. Developers can use -these recipes to build their own plugins. You can find all the Talk recipes -here: [github.com/coralproject/talk-recipes](https://github.com/coralproject/talk-recipes/). +When you're adding a plugin to Talk, you can specify it in the `client` and/or +the `server` section. If you only want to enable the server side component of a +plugin, you simply only specify the plugin in the `server` section. If you only +want the client side plugin, the `client` section. + +Plugins listed in the [Plugins Directory](/talk/plugins-directory/) will +indicate if they have/support a client/server plugin, and should be activated +accordingly. ## Plugin Registration @@ -117,3 +122,9 @@ assets inside the image as well. For more information on the onbuild image, refer to the [Installation from Docker](/talk/installation-from-docker/) documentation. + +## Recipes + +Recipes are plugin templates provided by the Coral Core team. Developers can use +these recipes to build their own plugins. You can find all the Talk recipes +here: [github.com/coralproject/talk-recipes](https://github.com/coralproject/talk-recipes/). diff --git a/docs/source/plugins/plugins-directory.md b/docs/source/plugins/plugins-directory.md index ca9b26734a..9161d0d68b 100644 --- a/docs/source/plugins/plugins-directory.md +++ b/docs/source/plugins/plugins-directory.md @@ -3,8 +3,9 @@ title: Plugins Directory permalink: /plugins-directory/ layout: plugins data: plugins +class: plugins --- Talk provides a growing ecosystem of plugins that interact with our extensive Server and Client API's. Below you can search for a plugin to use with Talk and -discover what their requirements and configuration are. \ No newline at end of file +discover what their requirements and configuration are. diff --git a/docs/themes/coral/layout/plugins.swig b/docs/themes/coral/layout/plugins.swig index 9599081050..adb60be307 100644 --- a/docs/themes/coral/layout/plugins.swig +++ b/docs/themes/coral/layout/plugins.swig @@ -4,9 +4,9 @@

{{ page.title }}


{% endif %} - + {{ page.content }} - +
@@ -15,6 +15,7 @@ Enter a few keywords about the plugin to filter the list
+
{% for plugin in _.sortBy(site.data[page.data], 'name') %}
@@ -25,7 +26,7 @@ {% if plugin.tags %}

{% for tag in plugin.tags %} - {{ tag }} + {{ tag }} {% endfor %}

{% endif %} @@ -35,4 +36,4 @@ {% endfor %} - \ No newline at end of file + diff --git a/docs/themes/coral/source/css/talk.scss b/docs/themes/coral/source/css/talk.scss index 391337876e..afbd6f3af0 100644 --- a/docs/themes/coral/source/css/talk.scss +++ b/docs/themes/coral/source/css/talk.scss @@ -448,3 +448,17 @@ a.brand { .plugin { display: none; } + +.badge-tag { + font-family: monospace; +} + +.badge-tag-default { + background: #28a745; + color: #fff; +} + +.badge-tag-gdpr { + background: rgb(0, 102, 176); + color: #fff; +} diff --git a/docs/themes/coral/source/js/plugins.js b/docs/themes/coral/source/js/plugins.js index 83f14d3565..26f7707c36 100644 --- a/docs/themes/coral/source/js/plugins.js +++ b/docs/themes/coral/source/js/plugins.js @@ -1,6 +1,17 @@ /* global lunr */ /* eslint-env browser */ +// Sourced from https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript +function getParameterByName(name, url) { + if (!url) url = window.location.href; + name = name.replace(/[\[\]]/g, '\\$&'); + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), + results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); +} + // Sourced from https://github.com/hexojs/site/blob/8e8ed4901769abbf76263125f82832df76ced58b/themes/navy/source/js/plugins.js. (function() { 'use strict'; @@ -60,6 +71,12 @@ updateCount(elements.length); } + var searchParam = getParameterByName('q'); + if (searchParam && searchParam.length > 0) { + $input.value = searchParam; + search(searchParam); + } + $input.addEventListener('input', function() { var value = this.value; diff --git a/plugins/talk-plugin-auth/README.md b/plugins/talk-plugin-auth/README.md index fd5218365a..c09dc218b4 100644 --- a/plugins/talk-plugin-auth/README.md +++ b/plugins/talk-plugin-auth/README.md @@ -14,3 +14,9 @@ utilize our internal authentication system. To sync Talk auth with your own auth systems, you can use this plugin as a template. + +## GDPR Compliance + +In order to facilitate compliance with the +[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), you +should review our [GDPR Compliance](/talk/integrating/gdpr/) guidelines. diff --git a/plugins/talk-plugin-facebook-auth/README.md b/plugins/talk-plugin-facebook-auth/README.md index 19d0031505..08780adda5 100644 --- a/plugins/talk-plugin-facebook-auth/README.md +++ b/plugins/talk-plugin-facebook-auth/README.md @@ -27,4 +27,10 @@ Configuration: or by visiting the [Creating an App ID](https://developers.facebook.com/docs/apps/register) guide. This is only required while the `talk-plugin-facebook-auth` plugin is - enabled. \ No newline at end of file + enabled. + +## GDPR Compliance + +In order to facilitate compliance with the +[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), you +should review our [GDPR Compliance](/talk/integrating/gdpr/) guidelines. diff --git a/plugins/talk-plugin-google-auth/README.md b/plugins/talk-plugin-google-auth/README.md index f68b56c325..15eb5cef7c 100644 --- a/plugins/talk-plugin-google-auth/README.md +++ b/plugins/talk-plugin-google-auth/README.md @@ -27,3 +27,9 @@ Configuration: - `TALK_GOOGLE_CLIENT_SECRET` (**required**) - The Google OAuth2 client ID for your Google login web app. You can learn more about getting a Google Client ID at the [Google API Console](https://console.developers.google.com/apis/). + +## GDPR Compliance + +In order to facilitate compliance with the +[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), you +should review our [GDPR Compliance](/talk/integrating/gdpr/) guidelines. diff --git a/plugins/talk-plugin-local-auth/README.md b/plugins/talk-plugin-local-auth/README.md index ee5a6b8806..5fabe0d718 100644 --- a/plugins/talk-plugin-local-auth/README.md +++ b/plugins/talk-plugin-local-auth/README.md @@ -18,3 +18,9 @@ through an email and password based login. - *Email Change*: Allows users to change their existing email address on their account. - *Local Account Association*: Allows users that have signed up with an external auth strategy (such as Google) the ability to associate a email address and password for login. **Note: Existing users with external authentication will be prompted to setup a local account when they sign in and when new users create an account.** + +## GDPR Compliance + +In order to facilitate compliance with the +[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), you +should review our [GDPR Compliance](/talk/integrating/gdpr/) guidelines. diff --git a/plugins/talk-plugin-profile-data/README.md b/plugins/talk-plugin-profile-data/README.md index 1d019a79b6..c4fcbb4562 100644 --- a/plugins/talk-plugin-profile-data/README.md +++ b/plugins/talk-plugin-profile-data/README.md @@ -21,4 +21,13 @@ that contains a download link. Only one link can be generated every 7 days, and the link will be valid for 24 hours. The downloaded zip file will contain all the users comments in a CSV format -including those that have been rejected, withheld, or still in premod. +including those that have been rejected, withheld, or still in pre-moderation. + +## GDPR Compliance + +In order to facilitate compliance with the +[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), you +should review our [GDPR Compliance](/talk/integrating/gdpr/) guidelines. This +plugin can work with its client plugin disabled and then directly integrated +with existing workflows for an organization of any size through use of the API +that this plugin provides. From c1492d10658d1dad16b2f2409006e5ad6a9966eb Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 2 May 2018 13:22:15 -0600 Subject: [PATCH 046/133] Added incorrect password error --- plugins/talk-plugin-local-auth/server/errors.js | 12 +++++++++++- plugins/talk-plugin-local-auth/server/mutators.js | 8 ++++++-- .../talk-plugin-local-auth/server/translations.yml | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/plugins/talk-plugin-local-auth/server/errors.js b/plugins/talk-plugin-local-auth/server/errors.js index 808ceb3a6b..0f0653c19e 100644 --- a/plugins/talk-plugin-local-auth/server/errors.js +++ b/plugins/talk-plugin-local-auth/server/errors.js @@ -22,4 +22,14 @@ class ErrLocalProfile extends TalkError { } } -module.exports = { ErrLocalProfile, ErrNoLocalProfile }; +// ErrIncorrectPassword is returned when the password passed was incorrect. +class ErrIncorrectPassword extends TalkError { + constructor() { + super('Password was incorrect', { + translation_key: 'INCORRECT_PASSWORD', + status: 400, + }); + } +} + +module.exports = { ErrLocalProfile, ErrNoLocalProfile, ErrIncorrectPassword }; diff --git a/plugins/talk-plugin-local-auth/server/mutators.js b/plugins/talk-plugin-local-auth/server/mutators.js index fb866b92c6..cb34bed7a9 100644 --- a/plugins/talk-plugin-local-auth/server/mutators.js +++ b/plugins/talk-plugin-local-auth/server/mutators.js @@ -1,5 +1,9 @@ const { ErrNotAuthorized, ErrNotFound, ErrEmailTaken } = require('errors'); -const { ErrNoLocalProfile, ErrLocalProfile } = require('./errors'); +const { + ErrNoLocalProfile, + ErrLocalProfile, + ErrIncorrectPassword, +} = require('./errors'); const { get } = require('lodash'); const bcrypt = require('bcryptjs'); @@ -25,7 +29,7 @@ async function updateUserEmailAddress(ctx, email, confirmPassword) { // Ensure that the password provided matches what we have on file. if (!await user.verifyPassword(confirmPassword)) { - throw new ErrNotAuthorized(); + throw new ErrIncorrectPassword(); } // Cleanup the email address. diff --git a/plugins/talk-plugin-local-auth/server/translations.yml b/plugins/talk-plugin-local-auth/server/translations.yml index 7df3d7b882..d81de6c6d5 100644 --- a/plugins/talk-plugin-local-auth/server/translations.yml +++ b/plugins/talk-plugin-local-auth/server/translations.yml @@ -6,3 +6,4 @@ en: error: NO_LOCAL_PROFILE: No existing email address is associated with this account. LOCAL_PROFILE: An email address is already associated with this account. + INCORRECT_PASSWORD: Provided password was incorrect. From 45c75f3c48ded2b393cfa7453e95e0362cad5084 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Wed, 2 May 2018 15:22:17 -0400 Subject: [PATCH 047/133] Update version to 4.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7e9a78c1c..9fe31aa398 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "talk", - "version": "4.3.2", + "version": "4.4.0", "description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net", "main": "app.js", "private": true, From c7db780582a3c2fc9af25ec0138ab5bbce5b58ab Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 16:46:20 -0300 Subject: [PATCH 048/133] Updating the cache with data from the fragment --- .../src/tabs/profile/containers/Profile.js | 2 +- client/coral-framework/graphql/mutations.js | 23 +++++++++++++++++++ .../components/ChangeEmailContentDialog.js | 4 ++-- .../client/components/Profile.js | 14 ++++------- .../client/containers/Profile.js | 2 ++ 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/profile/containers/Profile.js b/client/coral-embed-stream/src/tabs/profile/containers/Profile.js index 0272c15355..4a84f18107 100644 --- a/client/coral-embed-stream/src/tabs/profile/containers/Profile.js +++ b/client/coral-embed-stream/src/tabs/profile/containers/Profile.js @@ -46,7 +46,7 @@ ProfileContainer.propTypes = { currentUser: PropTypes.object, }; -const slots = ['profileSections']; +const slots = ['profileSections', 'profileSettings', 'profileHeader']; const withProfileQuery = withQuery( gql` diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index 15596e9a7e..29ec3fc965 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -336,6 +336,29 @@ export const withUpdateEmailAddress = withMutation( variables: { input, }, + update: proxy => { + const UpdateEmailAddressQuery = gql` + query Talk_UpdateEmailAddress { + me { + id + email + } + } + `; + + const prev = proxy.readQuery({ query: UpdateEmailAddressQuery }); + + const data = update(prev, { + me: { + email: { $set: input.email }, + }, + }); + + proxy.writeQuery({ + query: UpdateEmailAddressQuery, + data, + }); + }, }); }, }), diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js index 02d02680ec..4bc15757e6 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js @@ -37,7 +37,7 @@ class ChangeEmailContentDialog extends React.Component {
{t('talk-plugin-local-auth.change_email.old_email')}:{' '} - {this.props.emailAddress} + {this.props.email} {t('talk-plugin-local-auth.change_email.new_email')}:{' '} @@ -86,7 +86,7 @@ ChangeEmailContentDialog.propTypes = { cancel: PropTypes.func, onChange: PropTypes.func, formData: PropTypes.object, - emailAddress: PropTypes.string, + email: PropTypes.string, }; export default ChangeEmailContentDialog; diff --git a/plugins/talk-plugin-local-auth/client/components/Profile.js b/plugins/talk-plugin-local-auth/client/components/Profile.js index 84474dbe39..949923e77c 100644 --- a/plugins/talk-plugin-local-auth/client/components/Profile.js +++ b/plugins/talk-plugin-local-auth/client/components/Profile.js @@ -158,9 +158,7 @@ class Profile extends React.Component { render() { const { - username, - emailAddress, - root: { me: { state: { status } } }, + root: { me: { username, email, state: { status } } }, notify, } = this.props; const { editing, formData, showDialog } = this.state; @@ -193,8 +191,8 @@ class Profile extends React.Component { save={this.saveEmail} onChange={this.onChange} formData={this.state.formData} - emailAddress={emailAddress} - enable={formData.newEmail && emailAddress !== formData.newEmail} + email={email} + enable={formData.newEmail && email !== formData.newEmail} /> @@ -221,7 +219,7 @@ class Profile extends React.Component { id="newEmail" name="newEmail" onChange={this.onChange} - defaultValue={emailAddress} + defaultValue={email} validationType="email" columnDisplay /> @@ -230,9 +228,7 @@ class Profile extends React.Component { ) : (

{username}

- {emailAddress ? ( -

{emailAddress}

- ) : null} + {email ?

{email}

: null}
)} {editing ? ( diff --git a/plugins/talk-plugin-local-auth/client/containers/Profile.js b/plugins/talk-plugin-local-auth/client/containers/Profile.js index bebf127fda..2393045356 100644 --- a/plugins/talk-plugin-local-auth/client/containers/Profile.js +++ b/plugins/talk-plugin-local-auth/client/containers/Profile.js @@ -15,6 +15,8 @@ const withData = withFragments({ fragment TalkPluginLocalAuth_Profile_root on RootQuery { me { id + email + username state { status { username { From bfb4b790d42b166a15c57f4a46021c5b3fa4ad75 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 16:49:56 -0300 Subject: [PATCH 049/133] Adding error --- locales/en.yml | 1 + locales/es.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/locales/en.yml b/locales/en.yml index 393d01e23c..045d37c460 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -250,6 +250,7 @@ en: ALREADY_EXISTS: "Resource already exists" INVALID_ASSET_URL: "Assert URL is invalid" CANNOT_IGNORE_STAFF: "Cannot ignore Staff members." + INCORRECT_PASSWORD: "Incorrect Password" email: "Please enter a valid email." confirm_password: "Passwords don't match. Please check again" network_error: "Failed to connect to server. Check your internet connection and try again." diff --git a/locales/es.yml b/locales/es.yml index 628dd8faa6..41e337df87 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -243,6 +243,7 @@ es: ALREADY_EXISTS: "Resource already exists" INVALID_ASSET_URL: "La URL del articulo no es valida" CANNOT_IGNORE_STAFF: "Cannot ignore Staff members." + INCORRECT_PASSWORD: "Contraseña Incorrecta" email: "No es un correo válido" confirm_password: "Las contraseñas no coinciden. Inténtelo nuevamente" network_error: "Error al conectar con el servidor. Compruebe su conexión a Internet y vuelva a intentarlo." From b04fc1faf896242ea128f78d731850d885908694 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 18:15:04 -0300 Subject: [PATCH 050/133] wip --- client/coral-framework/graphql/mutations.js | 44 +++++ plugin-api/beta/client/hocs/index.js | 1 + .../client/components/ErrorMessage.css | 8 + .../client/components/ErrorMessage.js | 17 ++ .../client/components/InputField.css | 80 ++++++++ .../client/components/InputField.js | 94 ++++++++++ .../components/AddEmailAddressDialog.css | 74 ++++++++ .../components/AddEmailAddressDialog.js | 177 ++++++++++++++++++ .../containers/AddEmailAddressDialog.js | 26 +++ .../talk-plugin-local-auth/client/index.js | 2 + 10 files changed, 523 insertions(+) create mode 100644 plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.css create mode 100644 plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.js create mode 100644 plugins/talk-plugin-facebook-auth/client/components/InputField.css create mode 100644 plugins/talk-plugin-facebook-auth/client/components/InputField.js create mode 100644 plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css create mode 100644 plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js create mode 100644 plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index 29ec3fc965..dd54d0438c 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -321,6 +321,50 @@ const SetUsernameFragment = gql` } `; +export const withAttachLocalAuth = withMutation( + gql` + mutation AttachLocalAuth($input: AttachLocalAuthInput!) { + attachLocalAuth(input: $input) { + ...AttachLocalAuthResponse + } + } + `, + { + props: ({ mutate }) => ({ + attachLocalAuth: input => { + return mutate({ + variables: { + input, + }, + update: proxy => { + const AttachLocalAuthQuery = gql` + query Talk_AttachLocalAuth { + me { + id + email + } + } + `; + + const prev = proxy.readQuery({ query: AttachLocalAuthQuery }); + + const data = update(prev, { + me: { + email: { $set: input.email }, + }, + }); + + proxy.writeQuery({ + query: AttachLocalAuthQuery, + data, + }); + }, + }); + }, + }), + } +); + export const withUpdateEmailAddress = withMutation( gql` mutation UpdateEmailAddress($input: UpdateEmailAddressInput!) { diff --git a/plugin-api/beta/client/hocs/index.js b/plugin-api/beta/client/hocs/index.js index d33e7acc99..9109692270 100644 --- a/plugin-api/beta/client/hocs/index.js +++ b/plugin-api/beta/client/hocs/index.js @@ -28,5 +28,6 @@ export { withChangePassword, withChangeUsername, withUpdateEmailAddress, + withAttachLocalAuth, } from 'coral-framework/graphql/mutations'; export { compose } from 'recompose'; diff --git a/plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.css b/plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.css new file mode 100644 index 0000000000..039ffae305 --- /dev/null +++ b/plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.css @@ -0,0 +1,8 @@ +.errorMsg { + color: #FA4643; + font-size: 0.9em; +} + +.warningIcon { + color: #FA4643; +} diff --git a/plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.js b/plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.js new file mode 100644 index 0000000000..f39a8fc084 --- /dev/null +++ b/plugins/talk-plugin-facebook-auth/client/components/ErrorMessage.js @@ -0,0 +1,17 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styles from './ErrorMessage.css'; +import { Icon } from 'plugin-api/beta/client/components/ui'; + +const ErrorMessage = ({ children }) => ( +
+ + {children} +
+); + +ErrorMessage.propTypes = { + children: PropTypes.node, +}; + +export default ErrorMessage; diff --git a/plugins/talk-plugin-facebook-auth/client/components/InputField.css b/plugins/talk-plugin-facebook-auth/client/components/InputField.css new file mode 100644 index 0000000000..3442befdeb --- /dev/null +++ b/plugins/talk-plugin-facebook-auth/client/components/InputField.css @@ -0,0 +1,80 @@ + +.detailItem { + margin-bottom: 12px; +} + +.detailItemContainer { + display: flex; +} + +.columnDisplay { + flex-direction: column; + + .detailItemMessage { + padding: 4px 0 0; + } +} + +.detailItemContent { + border: solid 1px #787D80; + border-radius: 2px; + background-color: white; + height: 30px; + display: inline-block; + width: 230px; + display: flex; + box-sizing: border-box; + + > .detailIcon { + font-size: 1.2em; + padding: 0 5px; + color: #787D80; + line-height: 30px; + } + + &.error { + border: solid 2px #FA4643; + } + + &.disabled { + background-color: #E0E0E0; + } +} + +.detailLabel { + color: #4C4C4D; + font-size: 1em; + display: block; + margin-bottom: 4px; +} + +.detailValue { + background: transparent; + border: none; + font-size: 1em; + color: #000; + outline: none; + flex: 1; + height: 100%; + box-sizing: border-box; +} + +.detailItemMessage { + flex-grow: 1; + display: flex; + align-items: center; + padding-left: 6px; + padding-top: 16px; + + .warningIcon, .checkIcon { + font-size: 17px; + } +} + +.checkIcon { + color: #00CD73; +} + +.warningIcon { + color: #FA4643; +} diff --git a/plugins/talk-plugin-facebook-auth/client/components/InputField.js b/plugins/talk-plugin-facebook-auth/client/components/InputField.js new file mode 100644 index 0000000000..26937d5b95 --- /dev/null +++ b/plugins/talk-plugin-facebook-auth/client/components/InputField.js @@ -0,0 +1,94 @@ +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'; + +const InputField = ({ + id = '', + label = '', + type = 'text', + name = '', + onChange = () => {}, + showError = true, + hasError = false, + errorMsg = '', + children, + columnDisplay = false, + showSuccess = false, + validationType = '', + icon = '', + value = '', + defaultValue = '', + disabled = false, +}) => { + const inputValue = { + ...(value ? { value } : {}), + ...(defaultValue ? { defaultValue } : {}), + }; + + return ( +
+
+ {label && ( + + )} +
+ {icon && } + +
+
+ {!hasError && + showSuccess && + value && } + {hasError && showError && {errorMsg}} +
+
+ {children} +
+ ); +}; + +InputField.propTypes = { + id: PropTypes.string, + disabled: PropTypes.bool, + 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, + children: PropTypes.node, + columnDisplay: PropTypes.bool, + showSuccess: PropTypes.bool, + validationType: PropTypes.string, +}; + +export default InputField; diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css new file mode 100644 index 0000000000..7fa3ce78ce --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css @@ -0,0 +1,74 @@ +.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: 400px; + top: 50%; + transform: translateY(-50%); + padding: 20px; + border-radius: 4px; + font-family: Helvetica,Helvetica Neue,Verdana,sans-serif; +} + +.title { + font-size: 1.2em; + margin-bottom: 8px; +} + +.description { + font-size: 1em; + line-height: 20px; + margin: 0; + margin-bottom: 15px; +} + +.list { + padding: 0; + margin: 20px 0; + list-style: none; +} + +.item { + display: flex; + margin-bottom: 20px; + + .itemIcon { + flex-grow: 0; + } + + .text { + flex-grow: 1; + padding-left: 10px; + } + + > i.itemIcon { + font-size: 1.3em; + } +} + +.button { + color: #787D80; + border-radius: 2px; + background-color: transparent; + height: 30px; + font-size: 0.9em; + line-height: normal; + + &:hover { + background-color: #eaeaea; + } + + &.cancel { + background-color: transparent; + color: #787D80; + } + + &.proceed { + background-color: #3498DB; + color: white; + } + + &.danger { + background-color: #FA4643; + color: white; + } +} \ No newline at end of file diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js new file mode 100644 index 0000000000..4468d78656 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js @@ -0,0 +1,177 @@ +import React from 'react'; +import isEqual from 'lodash/isEqual'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import styles from './AddEmailAddressDialog.css'; +import { Button, Dialog, Icon } from 'plugin-api/beta/client/components/ui'; +import validate from 'coral-framework/helpers/validate'; +import errorMsj from 'coral-framework/helpers/error'; +import InputField from './InputField'; +import { getErrorMessages } from 'coral-framework/utils'; + +const initialState = { + showErrors: false, + errors: {}, + formData: {}, +}; + +class AddEmailAddressDialog extends React.Component { + state = initialState; + validKeys = ['emailAddress', 'confirmEmailAddress']; + + onChange = e => { + const { name, value, type } = e.target; + this.setState( + state => ({ + formData: { + ...state.formData, + [name]: value, + }, + }), + () => { + this.fieldValidation(value, type, name); + } + ); + }; + + fieldValidation = (value, type, name) => { + if (!value.length) { + this.addError({ + [name]: 'Field is required', + }); + } else if (!validate[type](value)) { + this.addError({ [name]: errorMsj[type] }); + } else { + this.removeError(name); + } + }; + + addError = err => { + this.setState(({ errors }) => ({ + errors: { ...errors, ...err }, + })); + }; + + removeError = errKey => { + this.setState(state => { + const { [errKey]: _, ...errors } = state.errors; + return { + errors, + }; + }); + }; + + hasError = err => { + return Object.keys(this.state.errors).indexOf(err) !== -1; + }; + + formHasError = () => { + const formHasErrors = !!Object.keys(this.state.errors).length; + const formIncomplete = !isEqual( + Object.keys(this.state.formData), + this.validKeys + ); + return formHasErrors || formIncomplete; + }; + + showError = () => { + this.setState({ + showError: true, + }); + }; + + confirmChanges = async () => { + if (this.formHasError()) { + this.showError(); + return; + } + + const { emailAddress } = this.state.formData; + const { attachLocalAuth } = this.props; + + try { + await attachLocalAuth({ + email: emailAddress, + }); + this.props.notify('success', 'Email Added!'); + } catch (err) { + this.props.notify('error', getErrorMessages(err)); + } + }; + + render() { + const { errors, formData, showErrors } = this.state; + return ( + +

Add an Email Address

+

+ For your added security, we require users to add an email address to + their accounts. Your email address will be used to: +

+
    +
  • + + + Receive updates regarding any changes to your account (email + address, username, password, etc.) + +
  • +
  • + + + Allow you to download your comments. + +
  • +
  • + + + Send comment notifications that you have chosen to receive. + +
  • +
+ + + +
+ ); + } +} + +AddEmailAddressDialog.propTypes = { + attachLocalAuth: PropTypes.func.isRequired, + notify: PropTypes.func.isRequired, +}; + +export default AddEmailAddressDialog; diff --git a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js new file mode 100644 index 0000000000..639236ea52 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js @@ -0,0 +1,26 @@ +import { compose, gql } from 'react-apollo'; +import { bindActionCreators } from 'redux'; +import { connect, withFragments } from 'plugin-api/beta/client/hocs'; +import AddEmailAddressDialog from '../components/AddEmailAddressDialog'; +import { notify } from 'coral-framework/actions/notification'; + +import { withAttachLocalAuth } from 'plugin-api/beta/client/hocs'; + +const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); + +const withData = withFragments({ + root: gql` + fragment TalkPluginLocalAuth_AddEmailAddressDialog_root on RootQuery { + me { + id + email + } + } + `, +}); + +export default compose( + connect(null, mapDispatchToProps), + withAttachLocalAuth, + withData +)(AddEmailAddressDialog); diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js index c669effaa8..ce5816583c 100644 --- a/plugins/talk-plugin-local-auth/client/index.js +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -1,4 +1,5 @@ import ChangePassword from './containers/ChangePassword'; +import AddEmailAddressDialog from './containers/AddEmailAddressDialog'; import Profile from './containers/Profile'; import translations from './translations.yml'; @@ -7,5 +8,6 @@ export default { slots: { profileHeader: [Profile], profileSettings: [ChangePassword], + stream: [AddEmailAddressDialog], }, }; From 3b2deeb00772611a75bb37e23d51d70b4bbca8d2 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 18:35:15 -0300 Subject: [PATCH 051/133] Checking if email verification is required --- .../components/AddEmailAddressDialog.js | 106 ++++++------------ .../client/components/AddEmailContent.js | 84 ++++++++++++++ .../client/components/EmailAddressAdded.js | 18 +++ .../client/components/VerifyEmailAddress.js | 20 ++++ .../containers/AddEmailAddressDialog.js | 3 + 5 files changed, 160 insertions(+), 71 deletions(-) create mode 100644 plugins/talk-plugin-local-auth/client/components/AddEmailContent.js create mode 100644 plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js create mode 100644 plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js index 4468d78656..b801a70dab 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js @@ -1,15 +1,18 @@ import React from 'react'; import isEqual from 'lodash/isEqual'; import PropTypes from 'prop-types'; -import cn from 'classnames'; -import styles from './AddEmailAddressDialog.css'; -import { Button, Dialog, Icon } from 'plugin-api/beta/client/components/ui'; +import { Dialog } from 'plugin-api/beta/client/components/ui'; import validate from 'coral-framework/helpers/validate'; import errorMsj from 'coral-framework/helpers/error'; -import InputField from './InputField'; import { getErrorMessages } from 'coral-framework/utils'; +import styles from './AddEmailAddressDialog.css'; + +import AddEmailContent from './AddEmailContent'; +import VerifyEmailAddress from './VerifyEmailAddress'; +import EmailAddressAdded from './EmailAddressAdded'; const initialState = { + step: 0, showErrors: false, errors: {}, formData: {}, @@ -17,7 +20,7 @@ const initialState = { class AddEmailAddressDialog extends React.Component { state = initialState; - validKeys = ['emailAddress', 'confirmEmailAddress']; + validKeys = ['emailAddress', 'confirmEmailAddress', 'confirmPassword']; onChange = e => { const { name, value, type } = e.target; @@ -74,96 +77,56 @@ class AddEmailAddressDialog extends React.Component { return formHasErrors || formIncomplete; }; - showError = () => { + showErrors = () => { this.setState({ - showError: true, + showErrors: true, }); }; confirmChanges = async () => { if (this.formHasError()) { - this.showError(); + this.showErrors(); return; } - const { emailAddress } = this.state.formData; + const { emailAddress, confirmPassword } = this.state.formData; const { attachLocalAuth } = this.props; try { await attachLocalAuth({ email: emailAddress, + password: confirmPassword, }); this.props.notify('success', 'Email Added!'); + this.goToNextStep(); } catch (err) { this.props.notify('error', getErrorMessages(err)); } }; + goToNextStep = () => { + this.setState(({ step }) => ({ + step: step + 1, + })); + }; + render() { - const { errors, formData, showErrors } = this.state; + const { errors, formData, showErrors, step } = this.state; + const { root: { settings } } = this.props; return ( -

Add an Email Address

-

- For your added security, we require users to add an email address to - their accounts. Your email address will be used to: -

-
    -
  • - - - Receive updates regarding any changes to your account (email - address, username, password, etc.) - -
  • -
  • - - - Allow you to download your comments. - -
  • -
  • - - - Send comment notifications that you have chosen to receive. - -
  • -
- - - + {step === 0 && ( + + )} + {step === 1 && !settings.requireEmailConfirmation ? ( + + ) : ( + + )}
); } @@ -172,6 +135,7 @@ class AddEmailAddressDialog extends React.Component { AddEmailAddressDialog.propTypes = { attachLocalAuth: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, + root: PropTypes.func.isRequired, }; export default AddEmailAddressDialog; diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js new file mode 100644 index 0000000000..a2b14c5fd6 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js @@ -0,0 +1,84 @@ +import React from 'react'; +import styles from './AddEmailAddressDialog.css'; +import { Button, Icon } from 'plugin-api/beta/client/components/ui'; +import cn from 'classnames'; +import InputField from './InputField'; + +const AddEmailContent = ({ formData, errors, showErrors }) => ( +
+

Add an Email Address

+

+ For your added security, we require users to add an email address to their + accounts. Your email address will be used to: +

+
    +
  • + + + Receive updates regarding any changes to your account (email address, + username, password, etc.) + +
  • +
  • + + + Allow you to download your comments. + +
  • +
  • + + + Send comment notifications that you have chosen to receive. + +
  • +
+ + + + +
+); + +export default AddEmailContent; diff --git a/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js b/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js new file mode 100644 index 0000000000..9d3e875d5b --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js @@ -0,0 +1,18 @@ +import React from 'react'; +import styles from './AddEmailAddressDialog.css'; + +const EmailAddressAdded = () => ( +
+

Email Address Added

+

+ Your email address has been added to your account. +

+ Need to change your email address? +

+ You can change your account settings by visiting{' '} + My Profile {'>'} Settings. +

+
+); + +export default EmailAddressAdded; diff --git a/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js b/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js new file mode 100644 index 0000000000..8d9d207b74 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js @@ -0,0 +1,20 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styles from './AddEmailAddressDialog.css'; + +const VerifyEmailAddress = ({ emailAddress }) => ( +
+

Verify Your Email Address

+

+ We’ve sent an email to {emailAddress} to verify your account. You must + verify your email address so that it can be used for account change + confirmations and notifications. +

+
+); + +VerifyEmailAddress.propTypes = { + emailAddress: PropTypes.string, +}; + +export default VerifyEmailAddress; diff --git a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js index 639236ea52..9732383ce4 100644 --- a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js @@ -15,6 +15,9 @@ const withData = withFragments({ id email } + settings { + requireEmailConfirmation + } } `, }); From 1bf440c4a6f0f652682ae6cd1ea01079525bec19 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 18:43:06 -0300 Subject: [PATCH 052/133] Changes --- .../components/AddEmailAddressDialog.js | 14 ++- .../client/components/AddEmailContent.js | 107 ++++++++++-------- 2 files changed, 68 insertions(+), 53 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js index b801a70dab..e5226eae0a 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js @@ -120,13 +120,15 @@ class AddEmailAddressDialog extends React.Component { formData={formData} errors={errors} showErrors={showErrors} + confirmChanges={this.confirmChanges} /> )} - {step === 1 && !settings.requireEmailConfirmation ? ( - - ) : ( - - )} + {step === 1 && + !settings.requireEmailConfirmation && } + {step === 1 && + settings.requireEmailConfirmation && ( + + )} ); } @@ -135,7 +137,7 @@ class AddEmailAddressDialog extends React.Component { AddEmailAddressDialog.propTypes = { attachLocalAuth: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, - root: PropTypes.func.isRequired, + root: PropTypes.object.isRequired, }; export default AddEmailAddressDialog; diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js index a2b14c5fd6..cb127520f2 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js @@ -1,10 +1,11 @@ import React from 'react'; +import PropTypes from 'prop-types'; import styles from './AddEmailAddressDialog.css'; import { Button, Icon } from 'plugin-api/beta/client/components/ui'; import cn from 'classnames'; import InputField from './InputField'; -const AddEmailContent = ({ formData, errors, showErrors }) => ( +const AddEmailContent = ({ formData, errors, showErrors, confirmChanges }) => (

Add an Email Address

@@ -32,53 +33,65 @@ const AddEmailContent = ({ formData, errors, showErrors }) => ( - - - - +

+ + + + +
); +AddEmailContent.propTypes = { + formData: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, + showErrors: PropTypes.bool.isRequired, + confirmChanges: PropTypes.func.isRequired, +}; + export default AddEmailContent; From 09d20257acc71172d8cd727dfaf23a447758eaae Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 18:46:41 -0300 Subject: [PATCH 053/133] Changes --- .../client/components/AddEmailAddressDialog.css | 6 ++++++ .../client/components/AddEmailContent.js | 10 +++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css index 7fa3ce78ce..1e711f5cb7 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css @@ -52,9 +52,15 @@ height: 30px; font-size: 0.9em; line-height: normal; + width: 100%; + display: inline-block; + text-align: center; + line-height: 30px; + font-size: 1em; &:hover { background-color: #eaeaea; + cursor: pointer; } &.cancel { diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js index cb127520f2..dcd0d9496d 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styles from './AddEmailAddressDialog.css'; -import { Button, Icon } from 'plugin-api/beta/client/components/ui'; +import { Icon } from 'plugin-api/beta/client/components/ui'; import cn from 'classnames'; import InputField from './InputField'; @@ -76,13 +76,9 @@ const AddEmailContent = ({ formData, errors, showErrors, confirmChanges }) => ( columnDisplay showSuccess={false} /> - +
); From cdae2796a5dcfa61fe2e06ba1039f0b74548337a Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 18:48:52 -0300 Subject: [PATCH 054/133] Changes --- .../talk-plugin-local-auth/client/components/AddEmailContent.js | 2 +- plugins/talk-plugin-local-auth/client/components/InputField.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js index dcd0d9496d..8ff5db6891 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js @@ -42,7 +42,7 @@ const AddEmailContent = ({ formData, errors, showErrors, confirmChanges }) => ( onChange={this.onChange} defaultValue="" hasError={!formData.emailAddress || errors.emailAddress} - errorMsg={errors.emailAddress} + errorMsg={'Invalid email address'} showError={showErrors} columnDisplay showSuccess={false} diff --git a/plugins/talk-plugin-local-auth/client/components/InputField.js b/plugins/talk-plugin-local-auth/client/components/InputField.js index 34c314c20e..26937d5b95 100644 --- a/plugins/talk-plugin-local-auth/client/components/InputField.js +++ b/plugins/talk-plugin-local-auth/client/components/InputField.js @@ -43,7 +43,7 @@ const InputField = ({
From ccb62263c190432135a9878ea55de60415cee099 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 20:08:29 -0300 Subject: [PATCH 055/133] checking me null --- .../client/containers/AccountDeletionRequestedSign.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js b/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js index d842ec43fb..9ac152743f 100644 --- a/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js +++ b/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js @@ -21,5 +21,5 @@ export default compose( connect(null, mapDispatchToProps), withCancelAccountDeletion, withData, - excludeIf(props => !props.root.me.scheduledDeletionDate) + excludeIf(({ root: { me } }) => !me || !me.scheduledDeletionDate) )(AccountDeletionRequestedSign); From 478770f6c6a0c1836a0b8eef8fb2819337aef7b1 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 20:41:32 -0300 Subject: [PATCH 056/133] Changes --- client/coral-framework/graphql/fragments.js | 3 ++- .../client/components/AddEmailAddressDialog.js | 13 +++++++++---- .../client/components/AddEmailContent.js | 18 +++++++++++++----- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/client/coral-framework/graphql/fragments.js b/client/coral-framework/graphql/fragments.js index bf75fa1a81..778214b8b8 100644 --- a/client/coral-framework/graphql/fragments.js +++ b/client/coral-framework/graphql/fragments.js @@ -27,6 +27,7 @@ export default { 'UpdateAssetStatusResponse', 'UpdateSettingsResponse', 'ChangePasswordResponse', - 'UpdateEmailAddressResponse' + 'UpdateEmailAddressResponse', + 'AttachLocalAuthResponse' ), }; diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js index e5226eae0a..c5b816e851 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js @@ -1,5 +1,6 @@ import React from 'react'; -import isEqual from 'lodash/isEqual'; +import isMatch from 'lodash/isEqual'; +import isEqualWith from 'lodash/isEqual'; import PropTypes from 'prop-types'; import { Dialog } from 'plugin-api/beta/client/components/ui'; import validate from 'coral-framework/helpers/validate'; @@ -20,7 +21,7 @@ const initialState = { class AddEmailAddressDialog extends React.Component { state = initialState; - validKeys = ['emailAddress', 'confirmEmailAddress', 'confirmPassword']; + validKeys = ['emailAddress', 'confirmPassword', 'confirmEmailAddress']; onChange = e => { const { name, value, type } = e.target; @@ -70,10 +71,12 @@ class AddEmailAddressDialog extends React.Component { formHasError = () => { const formHasErrors = !!Object.keys(this.state.errors).length; - const formIncomplete = !isEqual( + const formIncomplete = !isEqualWith( Object.keys(this.state.formData), - this.validKeys + this.validKeys, + isMatch ); + return formHasErrors || formIncomplete; }; @@ -113,6 +116,7 @@ class AddEmailAddressDialog extends React.Component { render() { const { errors, formData, showErrors, step } = this.state; const { root: { settings } } = this.props; + return ( {step === 0 && ( @@ -121,6 +125,7 @@ class AddEmailAddressDialog extends React.Component { errors={errors} showErrors={showErrors} confirmChanges={this.confirmChanges} + onChange={this.onChange} /> )} {step === 1 && diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js index 8ff5db6891..40edeea2a8 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js @@ -5,7 +5,13 @@ import { Icon } from 'plugin-api/beta/client/components/ui'; import cn from 'classnames'; import InputField from './InputField'; -const AddEmailContent = ({ formData, errors, showErrors, confirmChanges }) => ( +const AddEmailContent = ({ + formData, + errors, + showErrors, + confirmChanges, + onChange, +}) => (

Add an Email Address

@@ -33,13 +39,14 @@ const AddEmailContent = ({ formData, errors, showErrors, confirmChanges }) => ( -

+ + ( label="Confirm Email Address:" name="confirmEmailAddress" type="email" - onChange={this.onChange} + onChange={onChange} defaultValue="" hasError={ !formData.emailAddress || @@ -68,7 +75,7 @@ const AddEmailContent = ({ formData, errors, showErrors, confirmChanges }) => ( label="Insert Password" name="confirmPassword" type="password" - onChange={this.onChange} + onChange={onChange} defaultValue="" hasError={!formData.confirmPassword} errorMsg={'Confirm Password'} @@ -88,6 +95,7 @@ AddEmailContent.propTypes = { errors: PropTypes.object.isRequired, showErrors: PropTypes.bool.isRequired, confirmChanges: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, }; export default AddEmailContent; From 59cac9db8b3c08791354722f18c4af6e3389688e Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 20:58:34 -0300 Subject: [PATCH 057/133] Adding reducer --- .../talk-plugin-local-auth/client/actions.js | 9 ++++++++ .../components/AddEmailAddressDialog.css | 8 ++++--- .../components/AddEmailAddressDialog.js | 14 ++++++++---- .../client/components/AddEmailContent.js | 13 +++++++---- .../client/components/EmailAddressAdded.js | 13 ++++++++++- .../client/components/InputField.css | 3 ++- .../client/components/VerifyEmailAddress.js | 11 ++++++++-- .../client/constants.js | 4 ++++ .../containers/AddEmailAddressDialog.js | 6 ++++- .../talk-plugin-local-auth/client/index.js | 2 ++ .../talk-plugin-local-auth/client/reducer.js | 22 +++++++++++++++++++ 11 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 plugins/talk-plugin-local-auth/client/actions.js create mode 100644 plugins/talk-plugin-local-auth/client/constants.js create mode 100644 plugins/talk-plugin-local-auth/client/reducer.js diff --git a/plugins/talk-plugin-local-auth/client/actions.js b/plugins/talk-plugin-local-auth/client/actions.js new file mode 100644 index 0000000000..4786b92c8d --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/actions.js @@ -0,0 +1,9 @@ +import * as actions from './constants'; + +export const showAddEmailDialog = () => ({ + type: actions.SHOW_ADD_EMAIL_DIALOG, +}); + +export const hideAddEmailDialog = () => ({ + type: actions.HIDE_ADD_EMAIL_DIALOG, +}); diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css index 1e711f5cb7..41b5311474 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.css @@ -1,17 +1,19 @@ .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: 400px; + width: 320px; top: 50%; transform: translateY(-50%); padding: 20px; border-radius: 4px; font-family: Helvetica,Helvetica Neue,Verdana,sans-serif; + color:#3B4A53; } .title { - font-size: 1.2em; - margin-bottom: 8px; + font-size: 1.3em; + margin: 15px 0; + text-align: center; } .description { diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js index c5b816e851..253e3ac620 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js @@ -115,10 +115,10 @@ class AddEmailAddressDialog extends React.Component { render() { const { errors, formData, showErrors, step } = this.state; - const { root: { settings } } = this.props; + const { root: { settings }, showAddEmailDialog } = this.props; return ( - + {step === 0 && ( )} {step === 1 && - !settings.requireEmailConfirmation && } + !settings.requireEmailConfirmation && ( + {}} /> + )} {step === 1 && settings.requireEmailConfirmation && ( - + {}} + /> )} ); @@ -143,6 +148,7 @@ AddEmailAddressDialog.propTypes = { attachLocalAuth: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, root: PropTypes.object.isRequired, + showAddEmailDialog: PropTypes.bool.isRequired, }; export default AddEmailAddressDialog; diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js index 40edeea2a8..0d3411ff38 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailContent.js @@ -72,7 +72,7 @@ const AddEmailContent = ({ /> - - Add Email Address - +
); diff --git a/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js b/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js index 9d3e875d5b..ef74f4b8b3 100644 --- a/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js +++ b/plugins/talk-plugin-local-auth/client/components/EmailAddressAdded.js @@ -1,7 +1,9 @@ import React from 'react'; +import cn from 'classnames'; +import PropTypes from 'prop-types'; import styles from './AddEmailAddressDialog.css'; -const EmailAddressAdded = () => ( +const EmailAddressAdded = ({ done }) => (

Email Address Added

@@ -12,7 +14,16 @@ const EmailAddressAdded = () => ( You can change your account settings by visiting{' '} My Profile {'>'} Settings.

+
); +EmailAddressAdded.propTypes = { + done: PropTypes.func.isRequired, +}; + export default EmailAddressAdded; diff --git a/plugins/talk-plugin-local-auth/client/components/InputField.css b/plugins/talk-plugin-local-auth/client/components/InputField.css index cd6015e479..befc94f185 100644 --- a/plugins/talk-plugin-local-auth/client/components/InputField.css +++ b/plugins/talk-plugin-local-auth/client/components/InputField.css @@ -42,10 +42,11 @@ } .detailLabel { - color: #4C4C4D; + color: #4c4c4d; font-size: 1em; display: block; margin-bottom: 4px; + font-weight: bold; } .detailValue { diff --git a/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js b/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js index 8d9d207b74..9a3e6ae89e 100644 --- a/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js +++ b/plugins/talk-plugin-local-auth/client/components/VerifyEmailAddress.js @@ -1,8 +1,9 @@ import React from 'react'; +import cn from 'classnames'; import PropTypes from 'prop-types'; import styles from './AddEmailAddressDialog.css'; -const VerifyEmailAddress = ({ emailAddress }) => ( +const VerifyEmailAddress = ({ emailAddress, done }) => (

Verify Your Email Address

@@ -10,11 +11,17 @@ const VerifyEmailAddress = ({ emailAddress }) => ( verify your email address so that it can be used for account change confirmations and notifications.

+
); VerifyEmailAddress.propTypes = { - emailAddress: PropTypes.string, + emailAddress: PropTypes.string.isRequired, + done: PropTypes.func.isRequired, }; export default VerifyEmailAddress; diff --git a/plugins/talk-plugin-local-auth/client/constants.js b/plugins/talk-plugin-local-auth/client/constants.js new file mode 100644 index 0000000000..927816e0e4 --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/constants.js @@ -0,0 +1,4 @@ +const prefix = 'TALK_AUTH_LOCAL'; + +export const SHOW_ADD_EMAIL_DIALOG = `${prefix}_SHOW_ADD_EMAIL_DIALOG`; +export const HIDE_ADD_EMAIL_DIALOG = `${prefix}_HIDE_ADD_EMAIL_DIALOG`; diff --git a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js index 9732383ce4..62c637d715 100644 --- a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js @@ -22,8 +22,12 @@ const withData = withFragments({ `, }); +const mapStateToProps = ({ talkPluginLocalAuth: state }) => ({ + showAddEmailDialog: state.showAddEmailDialog, +}); + export default compose( - connect(null, mapDispatchToProps), + connect(mapStateToProps, mapDispatchToProps), withAttachLocalAuth, withData )(AddEmailAddressDialog); diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js index ce5816583c..126ea72c63 100644 --- a/plugins/talk-plugin-local-auth/client/index.js +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -2,8 +2,10 @@ import ChangePassword from './containers/ChangePassword'; import AddEmailAddressDialog from './containers/AddEmailAddressDialog'; import Profile from './containers/Profile'; import translations from './translations.yml'; +import reducer from './reducer'; export default { + reducer, translations, slots: { profileHeader: [Profile], diff --git a/plugins/talk-plugin-local-auth/client/reducer.js b/plugins/talk-plugin-local-auth/client/reducer.js new file mode 100644 index 0000000000..586bbf759d --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/reducer.js @@ -0,0 +1,22 @@ +import * as actions from './constants'; + +const initialState = { + showAddEmailDialog: true, +}; + +export default function reducer(state = initialState, action) { + switch (action.type) { + case actions.SHOW_ADD_EMAIL_DIALOG: + return { + ...state, + showAddEmailDialog: true, + }; + case actions.HIDE_ADD_EMAIL_DIALOG: + return { + ...state, + showAddEmailDialog: false, + }; + default: + return state; + } +} From a649bd8252528472985b0d35ae073928ee7fb008 Mon Sep 17 00:00:00 2001 From: okbel Date: Wed, 2 May 2018 21:01:08 -0300 Subject: [PATCH 058/133] done - but translations --- .../talk-plugin-local-auth/client/actions.js | 9 -------- .../client/constants.js | 4 ---- .../containers/AddEmailAddressDialog.js | 11 ++++------ .../talk-plugin-local-auth/client/index.js | 2 -- .../talk-plugin-local-auth/client/reducer.js | 22 ------------------- 5 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 plugins/talk-plugin-local-auth/client/actions.js delete mode 100644 plugins/talk-plugin-local-auth/client/constants.js delete mode 100644 plugins/talk-plugin-local-auth/client/reducer.js diff --git a/plugins/talk-plugin-local-auth/client/actions.js b/plugins/talk-plugin-local-auth/client/actions.js deleted file mode 100644 index 4786b92c8d..0000000000 --- a/plugins/talk-plugin-local-auth/client/actions.js +++ /dev/null @@ -1,9 +0,0 @@ -import * as actions from './constants'; - -export const showAddEmailDialog = () => ({ - type: actions.SHOW_ADD_EMAIL_DIALOG, -}); - -export const hideAddEmailDialog = () => ({ - type: actions.HIDE_ADD_EMAIL_DIALOG, -}); diff --git a/plugins/talk-plugin-local-auth/client/constants.js b/plugins/talk-plugin-local-auth/client/constants.js deleted file mode 100644 index 927816e0e4..0000000000 --- a/plugins/talk-plugin-local-auth/client/constants.js +++ /dev/null @@ -1,4 +0,0 @@ -const prefix = 'TALK_AUTH_LOCAL'; - -export const SHOW_ADD_EMAIL_DIALOG = `${prefix}_SHOW_ADD_EMAIL_DIALOG`; -export const HIDE_ADD_EMAIL_DIALOG = `${prefix}_HIDE_ADD_EMAIL_DIALOG`; diff --git a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js index 62c637d715..7ab887183f 100644 --- a/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/containers/AddEmailAddressDialog.js @@ -1,6 +1,6 @@ import { compose, gql } from 'react-apollo'; import { bindActionCreators } from 'redux'; -import { connect, withFragments } from 'plugin-api/beta/client/hocs'; +import { connect, withFragments, excludeIf } from 'plugin-api/beta/client/hocs'; import AddEmailAddressDialog from '../components/AddEmailAddressDialog'; import { notify } from 'coral-framework/actions/notification'; @@ -22,12 +22,9 @@ const withData = withFragments({ `, }); -const mapStateToProps = ({ talkPluginLocalAuth: state }) => ({ - showAddEmailDialog: state.showAddEmailDialog, -}); - export default compose( - connect(mapStateToProps, mapDispatchToProps), + connect(null, mapDispatchToProps), withAttachLocalAuth, - withData + withData, + excludeIf(({ root: { me } }) => !me || me.email) )(AddEmailAddressDialog); diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js index 126ea72c63..ce5816583c 100644 --- a/plugins/talk-plugin-local-auth/client/index.js +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -2,10 +2,8 @@ import ChangePassword from './containers/ChangePassword'; import AddEmailAddressDialog from './containers/AddEmailAddressDialog'; import Profile from './containers/Profile'; import translations from './translations.yml'; -import reducer from './reducer'; export default { - reducer, translations, slots: { profileHeader: [Profile], diff --git a/plugins/talk-plugin-local-auth/client/reducer.js b/plugins/talk-plugin-local-auth/client/reducer.js deleted file mode 100644 index 586bbf759d..0000000000 --- a/plugins/talk-plugin-local-auth/client/reducer.js +++ /dev/null @@ -1,22 +0,0 @@ -import * as actions from './constants'; - -const initialState = { - showAddEmailDialog: true, -}; - -export default function reducer(state = initialState, action) { - switch (action.type) { - case actions.SHOW_ADD_EMAIL_DIALOG: - return { - ...state, - showAddEmailDialog: true, - }; - case actions.HIDE_ADD_EMAIL_DIALOG: - return { - ...state, - showAddEmailDialog: false, - }; - default: - return state; - } -} From fff6e1c2317e581befdb1c252fde1ba56022ef5f Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 3 May 2018 10:24:43 -0300 Subject: [PATCH 059/133] Review changes --- client/coral-framework/graphql/mutations.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index 19d1338726..cc6b35fa6f 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -1,6 +1,7 @@ import { gql } from 'react-apollo'; import withMutation from '../hocs/withMutation'; import update from 'immutability-helper'; +import moment from 'moment'; function convertItemType(item_type) { switch (item_type) { @@ -658,7 +659,7 @@ export const withRequestAccountDeletion = withMutation( return mutate({ variables: {}, update: proxy => { - const CancelAccountDeletionQuery = gql` + const RequestAccountDeletionQuery = gql` query Talk_CancelAccountDeletion { me { id @@ -667,16 +668,22 @@ export const withRequestAccountDeletion = withMutation( } `; - const prev = proxy.readQuery({ query: CancelAccountDeletionQuery }); + const prev = proxy.readQuery({ + query: RequestAccountDeletionQuery, + }); + + const scheduledDeletionDate = moment() + .add(12, 'hours') + .toDate(); const data = update(prev, { me: { - scheduledDeletionDate: { $set: new Date() }, + scheduledDeletionDate: { $set: scheduledDeletionDate }, }, }); proxy.writeQuery({ - query: CancelAccountDeletionQuery, + query: RequestAccountDeletionQuery, data, }); }, From a9132c13539dc6ef2c6f401970ed5ea7865c2d26 Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 3 May 2018 11:07:58 -0300 Subject: [PATCH 060/133] stream fragment --- .../coral-embed-stream/src/tabs/stream/containers/Stream.js | 1 + .../client/components/AddEmailAddressDialog.js | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index 0a7a1951c5..17d3132eae 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -372,6 +372,7 @@ const slots = [ 'streamTabsPrepend', 'streamTabPanes', 'streamFilter', + 'stream', ]; const fragments = { diff --git a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js index 253e3ac620..691915c0f7 100644 --- a/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/AddEmailAddressDialog.js @@ -115,10 +115,10 @@ class AddEmailAddressDialog extends React.Component { render() { const { errors, formData, showErrors, step } = this.state; - const { root: { settings }, showAddEmailDialog } = this.props; + const { root: { settings } } = this.props; return ( - + {step === 0 && ( Date: Thu, 3 May 2018 08:39:34 -0600 Subject: [PATCH 061/133] merge bug --- .../server/mutators.js | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/plugins/talk-plugin-profile-data/server/mutators.js b/plugins/talk-plugin-profile-data/server/mutators.js index b1756a34b1..d3785c9513 100644 --- a/plugins/talk-plugin-profile-data/server/mutators.js +++ b/plugins/talk-plugin-profile-data/server/mutators.js @@ -129,6 +129,17 @@ async function cancelDeletion({ user, connectors: { models: { User } } }) { ); } +// downloadUser will return the download file url that can be used to directly +// download the archive. +async function downloadUser(ctx, userID) { + if (ctx.user.role !== 'ADMIN') { + throw new ErrNotAuthorized(); + } + + const { downloadFileURL } = await generateDownloadLinks(ctx, userID); + return downloadFileURL; +} + module.exports = ctx => ctx.user ? { @@ -136,6 +147,7 @@ module.exports = ctx => requestDownloadLink: () => sendDownloadLink(ctx), requestDeletion: () => requestDeletion(ctx), cancelDeletion: () => cancelDeletion(ctx), + download: userID => downloadUser(ctx, userID), }, } : { @@ -143,22 +155,6 @@ module.exports = ctx => requestDownloadLink: () => Promise.reject(new ErrNotAuthorized()), requestDeletion: () => Promise.reject(new ErrNotAuthorized()), cancelDeletion: () => Promise.reject(new ErrNotAuthorized()), + download: () => Promise.reject(new ErrNotAuthorized()), }, }; -// downloadUser will return the download file url that can be used to directly -// download the archive. -async function downloadUser(ctx, userID) { - const { downloadFileURL } = await generateDownloadLinks(ctx, userID); - return downloadFileURL; -} - -module.exports = ctx => ({ - User: { - requestDownloadLink: () => sendDownloadLink(ctx), - download: - // Only ADMIN users can execute an account download. - ctx.user && ctx.user.role === 'ADMIN' - ? userID => downloadUser(ctx, userID) - : () => Promise.reject(new ErrNotAuthorized()), - }, -}); From 225a04fed1473c60e98e37d68a67de4556da2f94 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Thu, 3 May 2018 10:53:16 -0400 Subject: [PATCH 062/133] Copy fixes --- .../client/components/DeleteMyAccountFinalStep.js | 9 ++------- .../client/components/DeleteMyAccountStep1.js | 2 +- .../client/components/DeleteMyAccountStep3.js | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js index ccbbf61faa..4cda903479 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js @@ -22,10 +22,8 @@ const DeleteMyAccountFinalStep = props => (

- Changed your mind? Simply sign in to your account again - before this time and click “ - Cancel Account Deletion Request. - ” + Changed your mind? Simply go to your account again before + this time and click “Cancel Account Deletion Request.

@@ -41,9 +39,6 @@ const DeleteMyAccountFinalStep = props => ( > Done - - Note: You will be immediately signed out of your account. -

); diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js index e74611b05b..ace020c659 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js @@ -15,7 +15,7 @@ const DeleteMyAccountStep1 = props => ( Can I still write comments until my account is deleted?{' '}

- No. Once youve requested account deletion, you can no longer write + No. Once you have requested account deletion, you can no longer write comments, reply to comments, or select reactions.

diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js index 3205cd2252..4c87bbcf2e 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js @@ -56,7 +56,7 @@ class DeleteMyAccountStep3 extends React.Component { /> Date: Thu, 3 May 2018 08:59:26 -0600 Subject: [PATCH 063/133] moved hoc's into plugin --- client/coral-framework/graphql/mutations.js | 110 ------------------ plugin-api/beta/client/hocs/index.js | 3 - .../AccountDeletionRequestedSign.js | 2 +- .../client/containers/DeleteMyAccount.js | 2 +- .../client/mutations.js | 104 ++++++++++++++++- 5 files changed, 101 insertions(+), 120 deletions(-) diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index cc6b35fa6f..228911d4ae 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -1,7 +1,6 @@ import { gql } from 'react-apollo'; import withMutation from '../hocs/withMutation'; import update from 'immutability-helper'; -import moment from 'moment'; function convertItemType(item_type) { switch (item_type) { @@ -645,115 +644,6 @@ export const withChangePassword = withMutation( } ); -export const withRequestAccountDeletion = withMutation( - gql` - mutation RequestAccountDeletion { - requestAccountDeletion { - ...RequestAccountDeletionResponse - } - } - `, - { - props: ({ mutate }) => ({ - requestAccountDeletion: () => { - return mutate({ - variables: {}, - update: proxy => { - const RequestAccountDeletionQuery = gql` - query Talk_CancelAccountDeletion { - me { - id - scheduledDeletionDate - } - } - `; - - const prev = proxy.readQuery({ - query: RequestAccountDeletionQuery, - }); - - const scheduledDeletionDate = moment() - .add(12, 'hours') - .toDate(); - - const data = update(prev, { - me: { - scheduledDeletionDate: { $set: scheduledDeletionDate }, - }, - }); - - proxy.writeQuery({ - query: RequestAccountDeletionQuery, - data, - }); - }, - }); - }, - }), - } -); - -export const withRequestDownloadLink = withMutation( - gql` - mutation RequestDownloadLink { - requestDownloadLink { - ...RequestDownloadLinkResponse - } - } - `, - { - props: ({ mutate }) => ({ - requestDownloadLink: () => { - return mutate({ - variables: {}, - }); - }, - }), - } -); - -export const withCancelAccountDeletion = withMutation( - gql` - mutation RequestDownloadLink { - cancelAccountDeletion { - ...CancelAccountDeletionResponse - } - } - `, - { - props: ({ mutate }) => ({ - cancelAccountDeletion: () => { - return mutate({ - variables: {}, - update: proxy => { - const CancelAccountDeletionQuery = gql` - query Talk_CancelAccountDeletion { - me { - id - scheduledDeletionDate - } - } - `; - - const prev = proxy.readQuery({ query: CancelAccountDeletionQuery }); - - const data = update(prev, { - me: { - scheduledDeletionDate: { $set: null }, - }, - }); - - proxy.writeQuery({ - query: CancelAccountDeletionQuery, - data, - }); - }, - }); - }, - }), - } -); - export const withUpdateAssetSettings = withMutation( gql` mutation UpdateAssetSettings($id: ID!, $input: AssetSettingsInput!) { diff --git a/plugin-api/beta/client/hocs/index.js b/plugin-api/beta/client/hocs/index.js index e86c966066..d7ca5fce9a 100644 --- a/plugin-api/beta/client/hocs/index.js +++ b/plugin-api/beta/client/hocs/index.js @@ -25,9 +25,6 @@ export { withUnbanUser, withStopIgnoringUser, withSetCommentStatus, - withRequestAccountDeletion, - withRequestDownloadLink, - withCancelAccountDeletion, withChangePassword, withChangeUsername, } from 'coral-framework/graphql/mutations'; diff --git a/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js b/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js index 9ac152743f..9866045a3b 100644 --- a/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js +++ b/plugins/talk-plugin-profile-data/client/containers/AccountDeletionRequestedSign.js @@ -3,7 +3,7 @@ import { bindActionCreators } from 'redux'; import { connect, withFragments, excludeIf } from 'plugin-api/beta/client/hocs'; import AccountDeletionRequestedSign from '../components/AccountDeletionRequestedSign'; import { notify } from 'coral-framework/actions/notification'; -import { withCancelAccountDeletion } from 'plugin-api/beta/client/hocs'; +import { withCancelAccountDeletion } from '../mutations'; const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); diff --git a/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js index a9c0338530..84d0b9a5cc 100644 --- a/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js +++ b/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js @@ -6,7 +6,7 @@ import { notify } from 'coral-framework/actions/notification'; import { withRequestAccountDeletion, withCancelAccountDeletion, -} from 'plugin-api/beta/client/hocs'; +} from '../mutations'; const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); diff --git a/plugins/talk-plugin-profile-data/client/mutations.js b/plugins/talk-plugin-profile-data/client/mutations.js index a370c9ff0d..d398028080 100644 --- a/plugins/talk-plugin-profile-data/client/mutations.js +++ b/plugins/talk-plugin-profile-data/client/mutations.js @@ -1,19 +1,113 @@ import { withMutation } from 'plugin-api/beta/client/hocs'; import { gql } from 'react-apollo'; +import update from 'immutability-helper'; +import moment from 'moment'; export const withRequestDownloadLink = withMutation( gql` - mutation DownloadCommentHistory { + mutation RequestDownloadLink { requestDownloadLink { - errors { - translation_key - } + ...RequestDownloadLinkResponse } } `, { props: ({ mutate }) => ({ - requestDownloadLink: () => mutate({ variables: {} }), + requestDownloadLink: () => { + return mutate({ + variables: {}, + }); + }, + }), + } +); + +export const withRequestAccountDeletion = withMutation( + gql` + mutation RequestAccountDeletion { + requestAccountDeletion { + ...RequestAccountDeletionResponse + } + } + `, + { + props: ({ mutate }) => ({ + requestAccountDeletion: () => { + return mutate({ + variables: {}, + update: proxy => { + const RequestAccountDeletionQuery = gql` + query Talk_CancelAccountDeletion { + me { + id + scheduledDeletionDate + } + } + `; + + const prev = proxy.readQuery({ + query: RequestAccountDeletionQuery, + }); + + const scheduledDeletionDate = moment() + .add(12, 'hours') + .toDate(); + + const data = update(prev, { + me: { + scheduledDeletionDate: { $set: scheduledDeletionDate }, + }, + }); + + proxy.writeQuery({ + query: RequestAccountDeletionQuery, + data, + }); + }, + }); + }, + }), + } +); + +export const withCancelAccountDeletion = withMutation( + gql` + mutation RequestDownloadLink { + cancelAccountDeletion { + ...CancelAccountDeletionResponse + } + } + `, + { + props: ({ mutate }) => ({ + cancelAccountDeletion: () => { + return mutate({ + variables: {}, + update: proxy => { + const CancelAccountDeletionQuery = gql` + query Talk_CancelAccountDeletion { + me { + id + scheduledDeletionDate + } + } + `; + + const prev = proxy.readQuery({ query: CancelAccountDeletionQuery }); + + const data = update(prev, { + me: { + scheduledDeletionDate: { $set: null }, + }, + }); + + proxy.writeQuery({ + query: CancelAccountDeletionQuery, + data, + }); + }, + }); + }, }), } ); From ee0f734705b1c423088457b85b0ecd7073667fea Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 09:13:44 -0600 Subject: [PATCH 064/133] cleaned up download mutations --- client/coral-framework/graphql/fragments.js | 3 --- plugin-api/beta/client/utils/index.js | 1 + .../components/DownloadCommentHistory.js | 22 ++++++++++++++----- .../containers/DownloadCommentHistory.js | 9 +++++++- .../client/graphql.js | 10 ++++++++- .../client/mutations.js | 6 +---- 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/client/coral-framework/graphql/fragments.js b/client/coral-framework/graphql/fragments.js index 94021d1333..c5704f7196 100644 --- a/client/coral-framework/graphql/fragments.js +++ b/client/coral-framework/graphql/fragments.js @@ -26,9 +26,6 @@ export default { 'UpdateAssetSettingsResponse', 'UpdateAssetStatusResponse', 'UpdateSettingsResponse', - 'RequestAccountDeletionResponse', - 'RequestDownloadLinkResponse', - 'CancelAccountDeletionResponse', 'ChangePasswordResponse' ), }; diff --git a/plugin-api/beta/client/utils/index.js b/plugin-api/beta/client/utils/index.js index 3fe742569c..aeb9841f94 100644 --- a/plugin-api/beta/client/utils/index.js +++ b/plugin-api/beta/client/utils/index.js @@ -8,4 +8,5 @@ export { getErrorMessages, getDefinitionName, getShallowChanges, + createDefaultResponseFragments, } from 'coral-framework/utils'; diff --git a/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js b/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js index 06fa1fa897..398e2a640e 100644 --- a/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js +++ b/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { t } from 'plugin-api/beta/client/services'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DownloadCommentHistory.css'; +import { getErrorMessages } from 'coral-framework/utils'; export const readableDuration = durAsHours => { const durAsDays = Math.ceil(durAsHours / 24); @@ -19,14 +20,25 @@ export const readableDuration = durAsHours => { class DownloadCommentHistory extends Component { static propTypes = { requestDownloadLink: PropTypes.func.isRequired, + notify: PropTypes.func.isRequired, root: PropTypes.object.isRequired, }; + requestDownloadLink = async () => { + const { requestDownloadLink, notify } = this.props; + try { + await requestDownloadLink(); + notify( + 'success', + 'Account Download Preparing - Check your email shortly for a download link' + ); + } catch (err) { + notify('error', getErrorMessages(err)); + } + }; + render() { - const { - root: { me: { lastAccountDownload } }, - requestDownloadLink, - } = this.props; + const { root: { me: { lastAccountDownload } } } = this.props; const now = new Date(); const lastAccountDownloadDate = @@ -52,7 +64,7 @@ class DownloadCommentHistory extends Component {

)} {canRequestDownload ? ( -
diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js index 9bc5573a14..28ead86de9 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js @@ -6,6 +6,7 @@ import styles from './DeleteMyAccount.css'; import { Button } from 'plugin-api/beta/client/components/ui'; import DeleteMyAccountDialog from './DeleteMyAccountDialog'; import { getErrorMessages } from 'coral-framework/utils'; +import { t } from 'plugin-api/beta/client/services'; const initialState = { showDialog: false }; @@ -30,7 +31,7 @@ class DeleteMyAccount extends React.Component { await cancelAccountDeletion(); notify( 'success', - 'Account Deletion Request Cancelled - Your request to delete your account has been cancelled. You may now write comments, reply to comments, and select reactions.' + t('talk-plugin-profile-data.delete_request.account_deletion_requested') ); } catch (err) { notify('error', getErrorMessages(err)); @@ -41,7 +42,10 @@ class DeleteMyAccount extends React.Component { const { requestAccountDeletion, notify } = this.props; try { await requestAccountDeletion(); - notify('success', 'Account Deletion Requested'); + notify( + 'success', + t('talk-plugin-profile-data.delete_request.account_deletion_requested') + ); } catch (err) { notify('error', getErrorMessages(err)); } @@ -62,7 +66,7 @@ class DeleteMyAccount extends React.Component { 'talk-plugin-auth--delete-my-account-description' )} > - Delete My Account + {t('talk-plugin-profile-data.delete_request.delete_my_account')}

- Deleting your account will permanently erase your profile and remove - all your comments from this site. + {t( + 'talk-plugin-profile-data.delete_request.delete_my_account_description' + )}

{scheduledDeletionDate && - `You have already submitted a request to delete your account. - Your account will be deleted on ${moment( - scheduledDeletionDate - ).format('MMM Do YYYY, h:mm:ss a')}. You may - cancel the request until that time`} + t( + 'talk-plugin-profile-data.delete_request.already_submitted_request_description', + moment(scheduledDeletionDate).format('MMM Do YYYY, h:mm:ss a') + )}

{scheduledDeletionDate ? ( ) : ( )}
diff --git a/plugins/talk-plugin-profile-data/client/translations.yml b/plugins/talk-plugin-profile-data/client/translations.yml index ee6dc4e513..e0b2752249 100644 --- a/plugins/talk-plugin-profile-data/client/translations.yml +++ b/plugins/talk-plugin-profile-data/client/translations.yml @@ -10,3 +10,13 @@ en: days: "{0} days" hour: "{0} hour" day: "{0} day" + delete_request: + account_deletion_cancelled: 'Account Deletion Request Cancelled - Your request to delete your account has been cancelled. You may now write comments, reply to comments, and select reactions.' + account_deletion_requested: 'Account Deletion Requested' + received_on: "A request to delete your account was received on " + cancel_request_description: "If you would like to continue leaving comments, replies or reactions, you may cancel your request to delete your account below" + before: "before" + cancel_account_deletion_request: "Cancel Account Deletion Request" + delete_my_account: "Delete My Account" + delete_my_account_description: "Deleting your account will permanently erase your profile and remove all your comments from this site." + already_submitted_request_description: "You have already submitted a request to delete your account. Your account will be deleted on {0}. You may cancel the request until that time" \ No newline at end of file From 0caa82c1c4ba14783808fc8a5741803f0da3048b Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Thu, 3 May 2018 11:59:27 -0400 Subject: [PATCH 071/133] Typo --- .../client/components/DeleteMyAccountFinalStep.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js index d3604d1ae2..ebf7200b69 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js @@ -30,8 +30,8 @@ const DeleteMyAccountFinalStep = props => (

- Tell us why. Wed like to know why you chose to delete - your account. Send us feedback on our comment system by emailing. + Tell us why. We would like to know why you chose to + delete your account. Send us feedback on our comment system by emailing.

From 8b35f2300a184254758c79f86debc85348275038 Mon Sep 17 00:00:00 2001 From: Cristian Date: Thu, 3 May 2018 13:06:47 -0300 Subject: [PATCH 072/133] Added TALK_ prefix to constants RECAPTCHA_WINDOW and RECAPTCHA_INCORRECT_TRIGGER --- config.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config.js b/config.js index 7eb7f9280d..6a1f999a71 100644 --- a/config.js +++ b/config.js @@ -213,10 +213,11 @@ const CONFIG = { RECAPTCHA_SECRET: process.env.TALK_RECAPTCHA_SECRET, // RECAPTCHA_WINDOW is the rate limit's time interval - RECAPTCHA_WINDOW: process.env.RECAPTCHA_WINDOW || '10m', + RECAPTCHA_WINDOW: process.env.TALK_RECAPTCHA_WINDOW || '10m', // After RECAPTCHA_INCORRECT_TRIGGER incorrect attempts, recaptcha will be required. - RECAPTCHA_INCORRECT_TRIGGER: process.env.RECAPTCHA_INCORRECT_TRIGGER || 5, + RECAPTCHA_INCORRECT_TRIGGER: + process.env.TALK_RECAPTCHA_INCORRECT_TRIGGER || 5, // WEBSOCKET_LIVE_URI is the absolute url to the live endpoint. WEBSOCKET_LIVE_URI: process.env.TALK_WEBSOCKET_LIVE_URI || null, From 6485b1f080e4c0b81d05ddf5c9ed1e9df000c262 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 10:02:33 -0600 Subject: [PATCH 073/133] added email to final step --- .../src/routes/Configure/components/OrganizationSettings.js | 2 +- .../client/components/DeleteMyAccount.js | 6 +++++- .../client/components/DeleteMyAccountDialog.js | 4 +++- .../client/components/DeleteMyAccountFinalStep.js | 6 +++++- .../client/containers/DeleteMyAccount.js | 3 +++ plugins/talk-plugin-profile-data/client/mutations.js | 1 - 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/client/coral-admin/src/routes/Configure/components/OrganizationSettings.js b/client/coral-admin/src/routes/Configure/components/OrganizationSettings.js index f3daeffc29..3505ef7b59 100644 --- a/client/coral-admin/src/routes/Configure/components/OrganizationSettings.js +++ b/client/coral-admin/src/routes/Configure/components/OrganizationSettings.js @@ -57,7 +57,7 @@ class OrganizationSettings extends React.Component { } const updater = { organizationContactEmail: { $set: email } }; - const errorUpdater = { organizationEmail: { $set: error } }; + const errorUpdater = { organizationContactEmail: { $set: error } }; this.props.updatePending({ updater, errorUpdater }); }; diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js index 982437de0c..dc95c4b9e3 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js @@ -48,7 +48,10 @@ class DeleteMyAccount extends React.Component { }; render() { - const { me: { scheduledDeletionDate } } = this.props.root; + const { + me: { scheduledDeletionDate }, + settings: { organizationContactEmail }, + } = this.props.root; return (

@@ -81,6 +81,7 @@ class DeleteMyAccountDialog extends React.Component { {step === 4 && ( )} @@ -94,6 +95,7 @@ DeleteMyAccountDialog.propTypes = { closeDialog: PropTypes.func.isRequired, requestAccountDeletion: PropTypes.func.isRequired, scheduledDeletionDate: PropTypes.string, + organizationContactEmail: PropTypes.string.isRequired, }; export default DeleteMyAccountDialog; diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js index ebf7200b69..75a0b3aeb5 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountFinalStep.js @@ -31,7 +31,10 @@ const DeleteMyAccountFinalStep = props => (

Tell us why. We would like to know why you chose to - delete your account. Send us feedback on our comment system by emailing. + delete your account. Send us feedback on our comment system by emailing{' '} + + {props.organizationContactEmail} + .

@@ -49,6 +52,7 @@ const DeleteMyAccountFinalStep = props => ( DeleteMyAccountFinalStep.propTypes = { finish: PropTypes.func.isRequired, scheduledDeletionDate: PropTypes.string.isRequired, + organizationContactEmail: PropTypes.string.isRequired, }; export default DeleteMyAccountFinalStep; diff --git a/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js index 84d0b9a5cc..0a81107f57 100644 --- a/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js +++ b/plugins/talk-plugin-profile-data/client/containers/DeleteMyAccount.js @@ -16,6 +16,9 @@ const withData = withFragments({ me { scheduledDeletionDate } + settings { + organizationContactEmail + } } `, }); diff --git a/plugins/talk-plugin-profile-data/client/mutations.js b/plugins/talk-plugin-profile-data/client/mutations.js index d2a8881b8c..c7ca689506 100644 --- a/plugins/talk-plugin-profile-data/client/mutations.js +++ b/plugins/talk-plugin-profile-data/client/mutations.js @@ -32,7 +32,6 @@ export const withRequestAccountDeletion = withMutation( return mutate({ variables: {}, update: proxy => { - debugger; const RequestAccountDeletionQuery = gql` query Talk_CancelAccountDeletion { me { From 375f1bb6b1ab2413977ee7bcd711705db39e509c Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 10:07:27 -0600 Subject: [PATCH 074/133] copy fixes --- .../AccountDeletionRequestedSign.js | 4 +-- .../client/components/DeleteMyAccount.js | 26 +++++++++---------- .../components/DeleteMyAccountFinalStep.js | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js b/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js index 31f65ffa76..f1d85e4e67 100644 --- a/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js +++ b/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js @@ -24,11 +24,11 @@ class AccountDeletionRequestedSign extends React.Component { const { me: { scheduledDeletionDate } } = this.props.root; const deletionScheduledFor = moment(scheduledDeletionDate).format( - 'MMM Do YYYY, h:mm:ss a' + 'MMM Do YYYY, h:mm a' ); const deletionScheduledOn = moment(scheduledDeletionDate) .subtract(24, 'hours') - .format('MMM Do YYYY, h:mm:ss a'); + .format('MMM Do YYYY, h:mm a'); return (
diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js index dc95c4b9e3..1c7c12d16a 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccount.js @@ -78,19 +78,19 @@ class DeleteMyAccount extends React.Component { Deleting your account will permanently erase your profile and remove all your comments from this site.

-

- {scheduledDeletionDate && - `You have already submitted a request to delete your account. - Your account will be deleted on ${moment( - scheduledDeletionDate - ).format('MMM Do YYYY, h:mm:ss a')}. You may - cancel the request until that time`} -

+ {scheduledDeletionDate && ( +

+ You have already submitted a request to delete your account. Your + account will be deleted on{' '} + {moment(scheduledDeletionDate).format('MMM Do YYYY, h:mm a')}. You + may cancel the request until that time. +

+ )} {scheduledDeletionDate ? (
From f6d3f4cb14a8ebb24657bc686068222c550f3fb2 Mon Sep 17 00:00:00 2001 From: okbel Date: Thu, 3 May 2018 13:32:52 -0300 Subject: [PATCH 075/133] translations --- .../components/DeleteMyAccountDialog.js | 5 ++- .../components/DeleteMyAccountFinalStep.js | 31 +++++++++++++------ .../client/components/DeleteMyAccountStep0.js | 13 ++++---- .../client/components/DeleteMyAccountStep1.js | 17 +++++----- .../client/components/DeleteMyAccountStep2.js | 13 ++++---- .../client/components/DeleteMyAccountStep3.js | 18 ++++++----- .../components/DownloadCommentHistory.js | 5 +-- .../client/translations.yml | 30 +++++++++++++++++- 8 files changed, 89 insertions(+), 43 deletions(-) diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.js index 35069384c5..f6ab9c2ce2 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountDialog.js @@ -8,6 +8,7 @@ import DeleteMyAccountStep1 from './DeleteMyAccountStep1'; import DeleteMyAccountStep2 from './DeleteMyAccountStep2'; import DeleteMyAccountStep3 from './DeleteMyAccountStep3'; import DeleteMyAccountFinalStep from './DeleteMyAccountFinalStep'; +import { t } from 'plugin-api/beta/client/services'; const initialState = { step: 0, formData: {} }; @@ -47,7 +48,9 @@ class DeleteMyAccountDialog extends React.Component { × -

Delete My Account

+

+ {t('talk-plugin-profile-data.delete_request.delete_my_account')} +

{step === 0 && ( (

- Your request has been submitted and confirmation has been sent to the - email address associated with your account. + {t( + 'talk-plugin-profile-data.delete_request.your_request_submitted_description' + )}

- Your account is scheduled to be deleted at: + {t( + 'talk-plugin-profile-data.delete_request.your_account_deletion_scheduled' + )} - Account Deletion Date and Time + {0}

- Changed your mind? Simply go to your account again before - this time and click “Cancel Account Deletion Request.” + + {' '} + {t('talk-plugin-profile-data.delete_request.changed_your_mind')} + {' '} + {t('talk-plugin-profile-data.delete_request.simply_go_to')} “ + {t( + 'talk-plugin-profile-data.delete_request.cancel_account_deletion_request' + )}. +

- Tell us why. Wed like to know why you chose to delete - your account. Send us feedback on our comment system by emailing. + + {t('talk-plugin-profile-data.delete_request.tell_us_why')}. + {' '} + {t('talk-plugin-profile-data.delete_request.feedback_copy')}

@@ -37,7 +50,7 @@ const DeleteMyAccountFinalStep = props => ( onClick={props.finish} full > - Done + {t('talk-plugin-profile-data.delete_request.done')}
diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep0.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep0.js index 901466d3b8..468c96e94f 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep0.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep0.js @@ -3,29 +3,30 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button, Icon } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; +import { t } from 'plugin-api/beta/client/services'; const DeleteMyAccountStep0 = props => (

- You are attempting to delete your account. This means: + {t('talk-plugin-profile-data.delete_request.you_are_attempting')}

  • - All of your comments are removed from this site + {t('talk-plugin-profile-data.delete_request.item_1')}
  • - All of your comments are deleted from our database + {t('talk-plugin-profile-data.delete_request.item_2')}
  • - Your username and email address are removed from our system + {t('talk-plugin-profile-data.delete_request.item_3')}
@@ -34,13 +35,13 @@ const DeleteMyAccountStep0 = props => ( className={cn(styles.button, styles.cancel)} onClick={props.cancel} > - Cancel + {t('talk-plugin-profile-data.delete_request.cancel')}
diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js index ace020c659..7408df688a 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js @@ -3,33 +3,34 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; +import { t } from 'plugin-api/beta/client/services'; const DeleteMyAccountStep1 = props => (
-

When will my account be deleted?

+

+ {t('talk-plugin-profile-data.delete_request.step1.subtitle')} +

- Your account will be deleted 24 hours after your request has been - submitted. + {t('talk-plugin-profile-data.delete_request.step1.description')}

- Can I still write comments until my account is deleted?{' '} + {t('talk-plugin-profile-data.delete_request.step1.subtitle_2')}

- No. Once you have requested account deletion, you can no longer write - comments, reply to comments, or select reactions. + {t('talk-plugin-profile-data.delete_request.step1.description_2')}

diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep2.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep2.js index 8ef14445e9..8976c7dcd1 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep2.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep2.js @@ -3,18 +3,17 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; +import { t } from 'plugin-api/beta/client/services'; const DeleteMyAccountStep2 = props => (

- 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. + {t('talk-plugin-profile-data.delete_request.step2.description')}

- To download your comment history go to: + {t('talk-plugin-profile-data.delete_request.step2.to_download')} - My Profile {`>`} Download My Comment History + {t('talk-plugin-profile-data.delete_request.step2.path')}

@@ -22,13 +21,13 @@ const DeleteMyAccountStep2 = props => ( className={cn(styles.button, styles.cancel)} onClick={props.cancel} > - Cancel + {t('talk-plugin-profile-data.delete_request.step2.cancel')}
diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js index 4c87bbcf2e..dfbe9bf1f2 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep3.js @@ -4,6 +4,7 @@ import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; import InputField from './InputField'; +import { t } from 'plugin-api/beta/client/services'; const initialState = { showError: false, @@ -42,11 +43,10 @@ class DeleteMyAccountStep3 extends React.Component { return (

- Are you sure you want to delete your account? + {t('talk-plugin-profile-data.delete_request.step3.subtitle')}

- To confirm you would like to delete your account please type in the - following phrase into the text box below: + {t('talk-plugin-profile-data.delete_request.step3.description')}

@@ -71,13 +75,13 @@ class DeleteMyAccountStep3 extends React.Component { className={cn(styles.button, styles.cancel)} onClick={this.props.cancel} > - Cancel + {t('talk-plugin-profile-data.delete_request.cancel')}

diff --git a/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js b/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js index 398e2a640e..feff6b582b 100644 --- a/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js +++ b/plugins/talk-plugin-profile-data/client/components/DownloadCommentHistory.js @@ -28,10 +28,7 @@ class DownloadCommentHistory extends Component { const { requestDownloadLink, notify } = this.props; try { await requestDownloadLink(); - notify( - 'success', - 'Account Download Preparing - Check your email shortly for a download link' - ); + notify('success', t('download_request.download_preparing')); } catch (err) { notify('error', getErrorMessages(err)); } diff --git a/plugins/talk-plugin-profile-data/client/translations.yml b/plugins/talk-plugin-profile-data/client/translations.yml index e0b2752249..8391544468 100644 --- a/plugins/talk-plugin-profile-data/client/translations.yml +++ b/plugins/talk-plugin-profile-data/client/translations.yml @@ -10,6 +10,7 @@ en: days: "{0} days" hour: "{0} hour" day: "{0} day" + download_preparing: "Account Download Preparing - Check your email shortly for a download link" delete_request: account_deletion_cancelled: 'Account Deletion Request Cancelled - Your request to delete your account has been cancelled. You may now write comments, reply to comments, and select reactions.' account_deletion_requested: 'Account Deletion Requested' @@ -19,4 +20,31 @@ en: cancel_account_deletion_request: "Cancel Account Deletion Request" delete_my_account: "Delete My Account" delete_my_account_description: "Deleting your account will permanently erase your profile and remove all your comments from this site." - already_submitted_request_description: "You have already submitted a request to delete your account. Your account will be deleted on {0}. You may cancel the request until that time" \ No newline at end of file + already_submitted_request_description: "You have already submitted a request to delete your account. Your account will be deleted on {0}. You may cancel the request until that time" + your_request_submitted_description: "Your request has been submitted and confirmation has been sent to the email address associated with your account." + your_account_deletion_scheduled: "Your account is scheduled to be deleted at:" + changed_your_mind: "Changed your mind?" + simply_go_to: "Simply go to your account again before this time and click" + tell_us_why: "Tell us why" + feedback_copy: "We'd like to know why you chose to delete your account. Send us feedback on our comment system by emailing." + done: "Done" + cancel: "Cancel" + proceed: "Proceed" + input_is_not_correct: "The input is not correct" + you_are_attempting: "You are attempting to delete your account. This means:" + item_1: "All of your comments are removed from this site" + item_2: "All of your comments are deleted from our database" + item_3: "Your username and email address are removed from our system" + step1: + subtitle: "When will my account be deleted?" + description: "Your account will be deleted 24 hours after your request has been submitted." + subtitle_2: "Can I still write comments until my account is deleted?" + description_2: "No. Once you have requested account deletion, you can no longer write comments, reply to comments, or select reactions." + step2: + description: "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." + to_download: "To download your comment history go to:" + path: "My Profile > Download My Comment History" + step3: + subtitle: "Are you sure you want to delete your account?" + description: "To confirm you would like to delete your account please type in the following phrase into the text box below:" + type_to_confirm: "Type phrase below to confirm" From 0e20ddb2fde76907314eca3aafde9968d5481160 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 10:40:06 -0600 Subject: [PATCH 076/133] added docs --- docs/source/02-02-advanced-configuration.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/source/02-02-advanced-configuration.md b/docs/source/02-02-advanced-configuration.md index b2ad29ad0c..5b638401df 100644 --- a/docs/source/02-02-advanced-configuration.md +++ b/docs/source/02-02-advanced-configuration.md @@ -316,6 +316,18 @@ default to providing only a time based lockout. Refer to [reCAPTCHA](https://www.google.com/recaptcha/intro/index.html) for information on getting an account setup. +## TALK_RECAPTCHA_WINDOW + +The rate limit time interval that there can be [TALK_RECAPTCHA_INCORRECT_TRIGGER](#talk_recaptcha_incorrect_trigger) incorrect attempts until the reCAPTCHA is +marked as required, parsed by +[ms](https://www.npmjs.com/package/ms). (Default `10m`) + +## TALK_RECAPTCHA_INCORRECT_TRIGGER + +The number of times that an incorrect login can be entered before within a time +perioud indicated by [TALK_RECAPTCHA_WINDOW](#talk_recaptcha_window) until the +reCAPTCHA is marked as required. (Default `5`) + ## TALK_REDIS_CLIENT_CONFIGURATION Configuration overrides for the redis client configuration in a JSON encoded @@ -531,4 +543,4 @@ Sets the logging level for the context logger (from [Bunyan](https://github.com/ A JSON string representing the configuration passed to the [fetch](https://www.npmjs.com/package/node-fetch) call for the scraper. It can be used to set an authorization header, or change the user agent. (Default -`{}`) \ No newline at end of file +`{}`) From 287cff289b8b66b121b99d7418bccf963843ce72 Mon Sep 17 00:00:00 2001 From: Kim Gardner Date: Thu, 3 May 2018 13:04:05 -0400 Subject: [PATCH 077/133] Update copy to reflect ability to take action up until account is deleted --- plugins/talk-plugin-profile-data/client/translations.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/talk-plugin-profile-data/client/translations.yml b/plugins/talk-plugin-profile-data/client/translations.yml index 2a0c9e334d..c5fbb8485f 100644 --- a/plugins/talk-plugin-profile-data/client/translations.yml +++ b/plugins/talk-plugin-profile-data/client/translations.yml @@ -12,10 +12,10 @@ en: day: "{0} day" download_preparing: "Account Download Preparing - Check your email shortly for a download link" delete_request: - account_deletion_cancelled: 'Account Deletion Request Cancelled - Your request to delete your account has been cancelled. You may now write comments, reply to comments, and select reactions.' + account_deletion_cancelled: 'Account Deletion Request Cancelled - Your request to delete your account has been cancelled."' account_deletion_requested: 'Account Deletion Requested' received_on: "A request to delete your account was received on " - cancel_request_description: "If you would like to continue leaving comments, replies or reactions, you may cancel your request to delete your account below" + cancel_request_description: "If you would like to reactivate your account, you may cancel your request to delete your account below" before: "before" cancel_account_deletion_request: "Cancel Account Deletion Request" delete_my_account: "Delete My Account" @@ -40,7 +40,7 @@ en: subtitle: "When will my account be deleted?" description: "Your account will be deleted 24 hours after your request has been submitted." subtitle_2: "Can I still write comments until my account is deleted?" - description_2: "No. Once you have requested account deletion, you can no longer write comments, reply to comments, or select reactions." + description_2: "Yes, you can still comment, reply, and react to comments until the 24 hours expires." step_2: description: "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." to_download: "To download your comment history go to:" From 06b08756e7b89fa7f8accea5bebc118026bb3b8a Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 11:36:07 -0600 Subject: [PATCH 078/133] added durations to configuration file --- .../AccountDeletionRequestedSign.js | 3 ++- .../client/components/DeleteMyAccountStep1.js | 5 ++-- .../components/DownloadCommentHistory.js | 6 +++-- .../client/translations.yml | 6 ++--- plugins/talk-plugin-profile-data/config.json | 4 +++ .../server/mutators.js | 26 +++++++++++++------ 6 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 plugins/talk-plugin-profile-data/config.json diff --git a/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js b/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js index 60e4d4bc6b..e0d5ab2554 100644 --- a/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js +++ b/plugins/talk-plugin-profile-data/client/components/AccountDeletionRequestedSign.js @@ -6,6 +6,7 @@ import moment from 'moment'; import { Button, Icon } from 'plugin-api/beta/client/components/ui'; import styles from './AccountDeletionRequestedSign.css'; import { getErrorMessages } from 'coral-framework/utils'; +import { scheduledDeletionDelayHours } from '../../config.json'; class AccountDeletionRequestedSign extends React.Component { cancelAccountDeletion = async () => { @@ -25,7 +26,7 @@ class AccountDeletionRequestedSign extends React.Component { 'MMM Do YYYY, h:mm a' ); const deletionScheduledOn = moment(scheduledDeletionDate) - .subtract(24, 'hours') + .subtract(scheduledDeletionDelayHours, 'hours') .format('MMM Do YYYY, h:mm a'); return ( diff --git a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js index dc137e41ed..491c962cfd 100644 --- a/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js +++ b/plugins/talk-plugin-profile-data/client/components/DeleteMyAccountStep1.js @@ -4,16 +4,17 @@ import cn from 'classnames'; import { Button } from 'plugin-api/beta/client/components/ui'; import styles from './DeleteMyAccountStep.css'; import { t } from 'plugin-api/beta/client/services'; +import { scheduledDeletionDelayHours } from '../../config.json'; const DeleteMyAccountStep1 = props => (

{t('delete_request.step_1.subtitle')}

- {t('delete_request.step_1.description')} + {t('delete_request.step_1.description', scheduledDeletionDelayHours)}

{t('delete_request.step_1.subtitle_2')}

- {t('delete_request.step_1.description_2')} + {t('delete_request.step_1.description_2', scheduledDeletionDelayHours)}

) : ( - )} diff --git a/plugins/talk-plugin-profile-data/client/graphql.js b/plugins/talk-plugin-profile-data/client/graphql.js index e0c459f7e8..9b3711bfc9 100644 --- a/plugins/talk-plugin-profile-data/client/graphql.js +++ b/plugins/talk-plugin-profile-data/client/graphql.js @@ -10,7 +10,7 @@ export default { ), }, mutations: { - RequestDownloadLink: () => ({ + DownloadCommentHistory: () => ({ updateQueries: { CoralEmbedStream_Profile: previousData => update(previousData, { From 949925586f414cb54dc4aa0621174b4ce1f2c838 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 17:50:53 -0600 Subject: [PATCH 107/133] handle confirmed email better --- .../talk-plugin-local-auth/client/graphql.js | 34 +++++++++++++++++++ .../talk-plugin-local-auth/client/index.js | 2 ++ .../talk-plugin-local-auth/server/mutators.js | 1 + services/users.js | 5 ++- 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 plugins/talk-plugin-local-auth/client/graphql.js diff --git a/plugins/talk-plugin-local-auth/client/graphql.js b/plugins/talk-plugin-local-auth/client/graphql.js new file mode 100644 index 0000000000..67fde246ac --- /dev/null +++ b/plugins/talk-plugin-local-auth/client/graphql.js @@ -0,0 +1,34 @@ +import update from 'immutability-helper'; +import get from 'lodash/get'; + +export default { + mutations: { + UpdateEmailAddress: () => ({ + updateQueries: { + CoralEmbedStream_Profile: previousData => { + // Find the local profile (if they have one). + const localIndex = get(previousData, 'me.profiles', []).indexOf( + ({ provider }) => provider === 'local' + ); + if (localIndex < 0) { + return previousData; + } + + // Mutate the confirmedAt, because we changed the email address, they + // can't possibly be confirmed now as well. + return update(previousData, { + me: { + profiles: { + [localIndex]: { + confirmedAt: { + $set: null, + }, + }, + }, + }, + }); + }, + }, + }), + }, +}; diff --git a/plugins/talk-plugin-local-auth/client/index.js b/plugins/talk-plugin-local-auth/client/index.js index c669effaa8..d5f9f86361 100644 --- a/plugins/talk-plugin-local-auth/client/index.js +++ b/plugins/talk-plugin-local-auth/client/index.js @@ -1,6 +1,7 @@ import ChangePassword from './containers/ChangePassword'; import Profile from './containers/Profile'; import translations from './translations.yml'; +import graphql from './graphql'; export default { translations, @@ -8,4 +9,5 @@ export default { profileHeader: [Profile], profileSettings: [ChangePassword], }, + ...graphql, }; diff --git a/plugins/talk-plugin-local-auth/server/mutators.js b/plugins/talk-plugin-local-auth/server/mutators.js index cb34bed7a9..6798584f57 100644 --- a/plugins/talk-plugin-local-auth/server/mutators.js +++ b/plugins/talk-plugin-local-auth/server/mutators.js @@ -43,6 +43,7 @@ async function updateUserEmailAddress(ctx, email, confirmPassword) { }, { $set: { 'profiles.$.id': email }, + $unset: { 'profiles.$.metadata.confirmed_at': 1 }, } ); diff --git a/services/users.js b/services/users.js index 1e84c8ff1a..d5486b3f8c 100644 --- a/services/users.js +++ b/services/users.js @@ -32,6 +32,7 @@ const i18n = require('./i18n'); const Wordlist = require('./wordlist'); const DomainList = require('./domain_list'); const Limit = require('./limit'); +const { get } = require('lodash'); const EMAIL_CONFIRM_JWT_SUBJECT = 'email_confirm'; const PASSWORD_RESET_JWT_SUBJECT = 'password_reset'; @@ -965,7 +966,9 @@ class Users { throw new ErrNotFound(); } - if (profile.metadata && profile.metadata.confirmed_at !== null) { + // Check to see if the profile has already been confirmed. + const confirmedAt = get(profile, 'metadata.confirmed_at', null); + if (confirmedAt && confirmedAt < Date.now()) { throw new ErrEmailAlreadyVerified(); } From 15df20e72056739c0a200db23cb81f87c751cda4 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 3 May 2018 17:57:09 -0600 Subject: [PATCH 108/133] fix --- plugins/talk-plugin-local-auth/client/graphql.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/graphql.js b/plugins/talk-plugin-local-auth/client/graphql.js index 67fde246ac..eddf583159 100644 --- a/plugins/talk-plugin-local-auth/client/graphql.js +++ b/plugins/talk-plugin-local-auth/client/graphql.js @@ -1,5 +1,6 @@ import update from 'immutability-helper'; import get from 'lodash/get'; +import findIndex from 'lodash/findIndex'; export default { mutations: { @@ -7,9 +8,9 @@ export default { updateQueries: { CoralEmbedStream_Profile: previousData => { // Find the local profile (if they have one). - const localIndex = get(previousData, 'me.profiles', []).indexOf( - ({ provider }) => provider === 'local' - ); + const localIndex = findIndex(get(previousData, 'me.profiles', []), { + provider: 'local', + }); if (localIndex < 0) { return previousData; } From eabcbc36c64cda59810a89967cb958fe55377a03 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Fri, 4 May 2018 13:34:20 -0300 Subject: [PATCH 109/133] forgot password --- .../client/components/ChangePassword.js | 23 ++++++++++++++- .../client/containers/ChangePassword.js | 29 +++++++++++++++---- .../client/translations.yml | 2 ++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js index e5535b8ba9..04d420d22d 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js @@ -125,6 +125,23 @@ class ChangePassword extends React.Component { this.disableEditing(); }; + onForgotPassword = async () => { + const { root: { me: { email } } } = this.props; + + try { + await this.props.forgotPassword(email); + this.props.notify( + 'success', + t('talk-plugin-local-auth.change_password.forgot_password_sent') + ); + } catch (err) { + this.props.notify('error', getErrorMessages(err)); + } + + this.clearForm(); + this.disableEditing(); + }; + disableEditing = () => { this.setState({ editing: false, @@ -166,7 +183,10 @@ class ChangePassword extends React.Component { showErrors > - + {t('talk-plugin-local-auth.change_password.forgot_password')} @@ -223,6 +243,7 @@ class ChangePassword extends React.Component { ChangePassword.propTypes = { changePassword: PropTypes.func.isRequired, + forgotPassword: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, }; diff --git a/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js b/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js index 1322a2940b..dfcf4a143c 100644 --- a/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js @@ -1,12 +1,29 @@ -import { compose } from 'react-apollo'; +import { compose, gql } from 'react-apollo'; import { bindActionCreators } from 'redux'; -import { connect } from 'plugin-api/beta/client/hocs'; +import { connect, withFragments } from 'plugin-api/beta/client/hocs'; import ChangePassword from '../components/ChangePassword'; import { notify } from 'coral-framework/actions/notification'; -import { withChangePassword } from 'plugin-api/beta/client/hocs'; +import { + withChangePassword, + withForgotPassword, +} from 'plugin-api/beta/client/hocs'; const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); -export default compose(connect(null, mapDispatchToProps), withChangePassword)( - ChangePassword -); +const withData = withFragments({ + root: gql` + fragment TalkPluginLocalAuth_ChangePassword_root on RootQuery { + me { + id + email + } + } + `, +}); + +export default compose( + connect(null, mapDispatchToProps), + withChangePassword, + withForgotPassword, + withData +)(ChangePassword); diff --git a/plugins/talk-plugin-local-auth/client/translations.yml b/plugins/talk-plugin-local-auth/client/translations.yml index d3b323f546..0c3216009c 100644 --- a/plugins/talk-plugin-local-auth/client/translations.yml +++ b/plugins/talk-plugin-local-auth/client/translations.yml @@ -9,6 +9,7 @@ en: cancel: "Cancel" edit: "Edit" changed_password_msg: "Changed Password - Your password has been successfully changed" + forgot_password_sent: "Forgot Password - We sent you an email to recover your password" change_username: change_username_note: "Usernames can be changed every 14 days" save: "Save" @@ -46,6 +47,7 @@ es: cancel: "Cancelar" edit: "Editar" changed_password_msg: "Contraseña Actualizada - Tu contraseña ha sido exitosamente actualizada" + forgot_password_sent: "Contraseña Olvidada - Te enviamos un email para recuperar tu contraseña" change_username: change_username_note: "El usuario puede ser cambiado cada 14 días" save: "Guardar" From 9a8f0e98a43afb16cfbf1f4961a127827c0902f1 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 4 May 2018 11:16:53 -0600 Subject: [PATCH 110/133] Username Change Fixes --- .../components/ChangeEmailContentDialog.js | 10 +- .../components/ChangeUsernameContentDialog.js | 25 ++- .../client/components/Profile.css | 28 ++-- .../client/components/Profile.js | 147 ++++++++++-------- .../client/containers/Profile.js | 4 +- .../client/translations.yml | 11 +- 6 files changed, 119 insertions(+), 106 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js index 4bc15757e6..438acc3988 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js @@ -16,7 +16,8 @@ class ChangeEmailContentDialog extends React.Component { }); }; - confirmChanges = async () => { + confirmChanges = async e => { + e.preventDefault(); await this.props.save(); this.props.next(); }; @@ -44,7 +45,7 @@ class ChangeEmailContentDialog extends React.Component { {this.props.formData.newEmail}
-
+ {t('talk-plugin-local-auth.change_email.cancel')} -
diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js index 894bdcbd66..917d77782e 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js @@ -16,7 +16,9 @@ class ChangeUsernameContentDialog extends React.Component { }); }; - confirmChanges = async () => { + confirmChanges = async e => { + e.preventDefault(); + if (this.formHasError()) { this.showError(); return; @@ -60,7 +62,7 @@ class ChangeUsernameContentDialog extends React.Component { {this.props.formData.newUsername}
- + +
+ + +
-
- - -

); diff --git a/plugins/talk-plugin-local-auth/client/components/Profile.css b/plugins/talk-plugin-local-auth/client/components/Profile.css index 5b4631ecf9..dcdbdd2aef 100644 --- a/plugins/talk-plugin-local-auth/client/components/Profile.css +++ b/plugins/talk-plugin-local-auth/client/components/Profile.css @@ -7,30 +7,38 @@ border-radius: 2px; box-sizing: border-box; justify-content: space-between; - - &.editing { + + &.editing { background-color: #EDEDED; } } +.wrapper { + display: flex; + position: relative; + box-sizing: inherit; + justify-content: inherit; + flex-grow: 1; +} + .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; @@ -48,7 +56,7 @@ > i { font-size: 17px; } - + &:hover { background-color: #399ee2; color: white; @@ -82,13 +90,13 @@ height: 30px; display: inline-block; width: 230px; - display: flex; + display: flex; > .detailLabelIcon { font-size: 1.2em; padding: 0 5px; color: #787D80; - line-height: 30px; + line-height: 30px; } &.disabled { @@ -115,7 +123,7 @@ list-style: none; margin: 0; padding: 0; -} +} .detailItem { margin-bottom: 12px; diff --git a/plugins/talk-plugin-local-auth/client/components/Profile.js b/plugins/talk-plugin-local-auth/client/components/Profile.js index 949923e77c..85c1f12954 100644 --- a/plugins/talk-plugin-local-auth/client/components/Profile.js +++ b/plugins/talk-plugin-local-auth/client/components/Profile.js @@ -50,8 +50,12 @@ class Profile extends React.Component { }); }; - onSave = async () => { - this.showDialog(); + onSave = async e => { + e.preventDefault(); + + if (this.isSaveEnabled()) { + this.showDialog(); + } }; addError = err => { @@ -121,10 +125,10 @@ class Profile extends React.Component { saveUsername = async () => { const { newUsername } = this.state.formData; - const { changeUsername } = this.props; + const { setUsername } = this.props; try { - await changeUsername(this.props.root.me.id, newUsername); + await setUsername(newUsername); this.props.notify( 'success', t('talk-plugin-local-auth.change_username.changed_username_success_msg') @@ -163,6 +167,8 @@ class Profile extends React.Component { } = this.props; const { editing, formData, showDialog } = this.state; + const usernameCanBeUpdated = canUsernameBeUpdated(status); + return (
- + {usernameCanBeUpdated && ( + + )} {editing ? ( -
-
- +
+
+ + + {t( + 'talk-plugin-local-auth.change_username.change_username_note' + )} + + + +
+
+
+ + + {t('talk-plugin-local-auth.change_username.cancel')} +
-
+ ) : ( -
-

{username}

- {email ?

{email}

: null} -
- )} - {editing ? ( -
- - - {t('talk-plugin-local-auth.change_username.cancel')} - -
- ) : ( -
- +
+
+

{username}

+ {email ?

{email}

: null} +
+
+ +
)}
@@ -263,9 +273,8 @@ class Profile extends React.Component { Profile.propTypes = { updateEmailAddress: PropTypes.func.isRequired, - changeUsername: PropTypes.func.isRequired, + setUsername: PropTypes.func.isRequired, root: PropTypes.object.isRequired, - changeUsername: PropTypes.func.isRequired, notify: PropTypes.func.isRequired, username: PropTypes.string, emailAddress: PropTypes.string, diff --git a/plugins/talk-plugin-local-auth/client/containers/Profile.js b/plugins/talk-plugin-local-auth/client/containers/Profile.js index e1ed99ef6b..ccfca72ae9 100644 --- a/plugins/talk-plugin-local-auth/client/containers/Profile.js +++ b/plugins/talk-plugin-local-auth/client/containers/Profile.js @@ -3,7 +3,7 @@ import { bindActionCreators } from 'redux'; import { connect, withFragments } from 'plugin-api/beta/client/hocs'; import Profile from '../components/Profile'; import { notify } from 'coral-framework/actions/notification'; -import { withChangeUsername } from 'plugin-api/beta/client/hocs'; +import { withSetUsername } from 'plugin-api/beta/client/hocs'; import { withUpdateEmailAddress } from '../hocs'; const mapDispatchToProps = dispatch => bindActionCreators({ notify }, dispatch); @@ -33,7 +33,7 @@ const withData = withFragments({ export default compose( connect(null, mapDispatchToProps), - withChangeUsername, + withSetUsername, withUpdateEmailAddress, withData )(Profile); diff --git a/plugins/talk-plugin-local-auth/client/translations.yml b/plugins/talk-plugin-local-auth/client/translations.yml index 2b46a04642..059e497dbe 100644 --- a/plugins/talk-plugin-local-auth/client/translations.yml +++ b/plugins/talk-plugin-local-auth/client/translations.yml @@ -22,19 +22,18 @@ en: confirm_changes: "Confirm Changes" username_does_not_match: "Username does not match" cant_be_equal: "Your new {0} must be different to your current one" - change_username_attempt: "Username can't be updated. Usernames can be changed every 14 days" + changed_username_success_msg: "Username Changed - Your username has been successfully changed. You will not be able to change your user name for 14 days." + change_username_attempt: "Username can't be updated. Usernames can only be changed every 14 days." change_email: confirm_email_change: "Confirm Email Address Change" description: "You are attempting to change your email address. Your new email address will be used for your login and to receive account notifications." - old_email: "Old Email Address" + old_email: "Old Email Address" new_email: "New Email Address" enter_password: "Enter Password" incorrect_password: "Incorrect Password" confirm_change: "Confirm Change" cancel: "Cancel" change_email_msg: "Email Address Changed - Your email address has been successfully changed. This email address will now be used for signing in and email notifications." - changed_username_success_msg: "Username Changed - Your username has been successfully changed. You will not be able to change your user name for 14 days." - change_username_attempt: "Username can't be updated. Usernames can only be changed every 14 days." add_email: add_email_address: "Add Email Address" enter_email_address: "Enter Email Address:" @@ -52,7 +51,7 @@ en: verify: title: "Verify Your Email Address" description: "We’ve sent an email to {0} to verify your account. You must verify your email address so that it can be used for account change confirmations and notifications." - added: + added: title: "Email Address Added" description: "Your email address has been added to your account." subtitle: "Need to change your email address?" @@ -82,4 +81,4 @@ es: confirm_changes: "Confirmar Cambios" username_does_not_match: "El usuario no coincide" changed_username_success_msg: "Usuario Actualizado - Tu usuario ha sido exitosamente actualizado. No podrás cambiar el usuario por 14 días." - change_username_attempt: "El usuario no puede ser actualizado. Los usuarios pueden ser cambiados cada 14 días." \ No newline at end of file + change_username_attempt: "El usuario no puede ser actualizado. Los usuarios pueden ser cambiados cada 14 días." From 4bc8a167a4a2446ecb334992b2d6fa6ff45fd702 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 4 May 2018 19:29:05 +0200 Subject: [PATCH 111/133] Styling tweaks --- .../client/components/ChangePassword.css | 9 ++++--- .../client/components/Profile.css | 27 ++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangePassword.css b/plugins/talk-plugin-local-auth/client/components/ChangePassword.css index 0df8eb4090..c1c6c9c7cd 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangePassword.css +++ b/plugins/talk-plugin-local-auth/client/components/ChangePassword.css @@ -5,22 +5,25 @@ border: solid 1px transparent; box-sizing: border-box; justify-content: space-between; + margin: 16px 0; &.editing { padding: 10px; - border-color: #979797; background-color: #EDEDED; .actions { top: 10px; right: 10px; } + .title { + margin-bottom: 1em; + } } } .actions { position: absolute; - top: 0px; + top: -6px; right: 0px; display: flex; flex-direction: column; @@ -29,7 +32,7 @@ .title { color: #202020; - margin: 0 0 20px; + margin: 0; } .detailBottomBox { diff --git a/plugins/talk-plugin-local-auth/client/components/Profile.css b/plugins/talk-plugin-local-auth/client/components/Profile.css index 5b4631ecf9..30b75f4514 100644 --- a/plugins/talk-plugin-local-auth/client/components/Profile.css +++ b/plugins/talk-plugin-local-auth/client/components/Profile.css @@ -1,36 +1,39 @@ .container { - margin-bottom: 20px; + margin-top: 6px; + margin-bottom: 12px; display: flex; position: relative; color: #202020; - padding: 10px; + padding: 5px; border-radius: 2px; box-sizing: border-box; justify-content: space-between; - - &.editing { + + &.editing { + padding: 10px; 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-top: 0; margin-bottom: 4px; -} +} .button { border: 1px solid #787d80; @@ -48,7 +51,7 @@ > i { font-size: 17px; } - + &:hover { background-color: #399ee2; color: white; @@ -82,13 +85,13 @@ height: 30px; display: inline-block; width: 230px; - display: flex; + display: flex; > .detailLabelIcon { font-size: 1.2em; padding: 0 5px; color: #787D80; - line-height: 30px; + line-height: 30px; } &.disabled { @@ -115,7 +118,7 @@ list-style: none; margin: 0; padding: 0; -} +} .detailItem { margin-bottom: 12px; From d41984f171e0b00dfdb1e4670b5340597b184136 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 4 May 2018 19:32:29 +0200 Subject: [PATCH 112/133] Remove unused field --- .../talk-plugin-local-auth/client/containers/ChangePassword.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js b/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js index dfcf4a143c..11bd5c5fb1 100644 --- a/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/containers/ChangePassword.js @@ -14,7 +14,6 @@ const withData = withFragments({ root: gql` fragment TalkPluginLocalAuth_ChangePassword_root on RootQuery { me { - id email } } From 2a5075f434d21394a86e6977e3c6ce895ecb4681 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 4 May 2018 11:33:06 -0600 Subject: [PATCH 113/133] Form update --- .../client/components/ChangePassword.js | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js index 04d420d22d..8f86fff484 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js @@ -105,7 +105,13 @@ class ChangePassword extends React.Component { this.setState(initialState); }; - onSave = async () => { + onSave = async e => { + e.preventDefault(); + + if (this.isSubmitBlocked()) { + return; + } + const { oldPassword, newPassword } = this.state.formData; try { @@ -169,8 +175,11 @@ class ChangePassword extends React.Component {

{t('talk-plugin-local-auth.change_password.change_password')}

- {editing && ( -
+ {editing ? ( + +
+ + + {t('talk-plugin-local-auth.change_password.cancel')} + +
- )} - {editing ? ( -
- - - {t('talk-plugin-local-auth.change_password.cancel')} - -
) : (
+ +
-
- - -
); From 7a7dcdd7c63744e577cd69e2407fd914f28d660b Mon Sep 17 00:00:00 2001 From: Jero Date: Fri, 4 May 2018 16:35:24 -0300 Subject: [PATCH 115/133] corrections in spanish translations --- locales/es.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/locales/es.yml b/locales/es.yml index 702f6b9e0b..a6d35ef0d6 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -63,10 +63,10 @@ es: reactions: 'reacciones' story: 'Artículo' flagged_usernames: - notify_approved: '{0} nombre de usuario aprobado {1}' - notify_rejected: '{0} nombre de usuario rechazado {1}' - notify_flagged: '{0} nombre de usuario reportado {1}' - notify_changed: 'El usuario {0} cambio su nombre de usuario por {1}' + notify_approved: '{0} ha aprobado el nombre de usuario {1}' + notify_rejected: '{0} ha rechazado el nombre de usuario {1}' + notify_flagged: '{0} ha reportado el nombre de usuario {1}' + notify_changed: 'El usuario {0} ha modificado su nombre de usuario por {1}' community: account_creation_date: "Fecha de creación de la cuenta" active: Activa @@ -194,9 +194,9 @@ es: minutes_plural: "minutos" email: suspended: - subject: "Su cuenta fue suspendida" + subject: "Su cuenta ha sido suspendida" banned: - subject: "Su cuenta fue bloqueada" + subject: "Su cuenta ha sido bloqueada" body: "De acuerdo con las guías de comunidad de The Coral Project, su cuenta a sido bloqueada. No podrá hacer comentarios, reportar o entrar en contacto con nuestra comunidad." confirm: has_been_requested: "Un correo de confirmación ha sido pedido para la siguiente cuenta:" @@ -306,11 +306,11 @@ es: actions: Acciones all: todos all_streams: "Todos los Hilos" - notify_edited: '{0} comentarios editados "{1}"' - notify_accepted: '{0} comentarios aceptados "{1}"' - notify_rejected: '{0} comentarios rechazados "{1}"' - notify_flagged: '{0} comentarios reportados "{1}"' - notify_reset: '{0} resetear el status de comentarios "{1}"' + notify_edited: '{0} ha editado el comentario "{1}"' + notify_accepted: '{0} ha aceptado el comentario "{1}"' + notify_rejected: '{0} ha rechazado el comentario "{1}"' + notify_flagged: '{0} ha reportado el comentario "{1}"' + notify_reset: '{0} ha reseteado el status del comentario "{1}"' approve: "Aprobar" approved: "Aprobado" ban_user: "Bloquear" From 4312b8d02468e7d235f832eddf09b398cf683d86 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Fri, 4 May 2018 17:49:40 -0300 Subject: [PATCH 116/133] bug --- .../client/components/ChangePassword.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js index 8f86fff484..1b7b97dfc8 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js @@ -160,7 +160,7 @@ class ChangePassword extends React.Component { }; render() { - const { editing, errors } = this.state; + const { editing, errors, showErrors } = this.state; return (
- + {t('talk-plugin-local-auth.change_password.cancel')} - +
) : ( diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js index 917d77782e..3e7107922e 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeUsernameContentDialog.js @@ -84,7 +84,11 @@ class ChangeUsernameContentDialog extends React.Component {
- - -
- - - ); - } -} - -ChangeUsernameDialog.propTypes = { - saveChanges: PropTypes.func, - closeDialog: PropTypes.func, - showDialog: PropTypes.bool, - onChange: PropTypes.func, - username: PropTypes.string, - formData: PropTypes.object, - canUsernameBeUpdated: PropTypes.bool.isRequired, - notify: PropTypes.func.isRequired, -}; - -export default ChangeUsernameDialog; diff --git a/plugins/talk-plugin-local-auth/client/components/Profile.js b/plugins/talk-plugin-local-auth/client/components/Profile.js index 85c1f12954..e5d0276c77 100644 --- a/plugins/talk-plugin-local-auth/client/components/Profile.js +++ b/plugins/talk-plugin-local-auth/client/components/Profile.js @@ -2,7 +2,7 @@ import React from 'react'; import cn from 'classnames'; import PropTypes from 'prop-types'; import styles from './Profile.css'; -import { Button } from 'plugin-api/beta/client/components/ui'; +import { Button, BareButton } from 'plugin-api/beta/client/components/ui'; import { t } from 'plugin-api/beta/client/services'; import InputField from './InputField'; import { getErrorMessages } from 'coral-framework/utils'; @@ -244,9 +244,13 @@ class Profile extends React.Component { > {t('talk-plugin-local-auth.change_username.save')} - + {t('talk-plugin-local-auth.change_username.cancel')} - + ) : ( From 06abccabb4de53832a12f504e7c1c01b3ef788d3 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Mon, 7 May 2018 18:26:37 +0200 Subject: [PATCH 121/133] Fix InputField controlled / uncontrolled mode --- .../client/components/ChangePassword.js | 6 +++++- .../client/components/InputField.js | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js index 8f86fff484..a375e90a44 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangePassword.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangePassword.js @@ -14,7 +14,11 @@ const initialState = { editing: false, showErrors: true, errors: {}, - formData: {}, + formData: { + oldPassword: '', + newPassword: '', + confirmNewPassword: '', + }, }; class ChangePassword extends React.Component { diff --git a/plugins/talk-plugin-local-auth/client/components/InputField.js b/plugins/talk-plugin-local-auth/client/components/InputField.js index 930c15582e..7dca221976 100644 --- a/plugins/talk-plugin-local-auth/client/components/InputField.js +++ b/plugins/talk-plugin-local-auth/client/components/InputField.js @@ -19,13 +19,13 @@ const InputField = ({ showSuccess = false, validationType = '', icon = '', - value = '', - defaultValue = '', + value, + defaultValue, disabled = false, }) => { const inputValue = { - ...(value ? { value } : {}), - ...(defaultValue ? { defaultValue } : {}), + ...(value !== undefined ? { value } : {}), + ...(defaultValue !== undefined ? { defaultValue } : {}), }; return ( From 46e5efbd559c02c6cae73589ef6e461de856f0f0 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Mon, 7 May 2018 15:00:55 -0300 Subject: [PATCH 122/133] validation for password input in change email --- .../components/ChangeEmailContentDialog.js | 19 ++++++++++++------- .../client/components/Profile.js | 7 +++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js index 1f17194440..b80529d82a 100644 --- a/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js +++ b/plugins/talk-plugin-local-auth/client/components/ChangeEmailContentDialog.js @@ -18,10 +18,18 @@ class ChangeEmailContentDialog extends React.Component { confirmChanges = async e => { e.preventDefault(); + + if (this.formHasError()) { + this.showError(); + return; + } + await this.props.save(); this.props.next(); }; + formHasError = () => this.props.hasError('confirmPassword'); + render() { return (
@@ -53,15 +61,10 @@ class ChangeEmailContentDialog extends React.Component { type="password" onChange={this.props.onChange} defaultValue="" - hasError={ - !this.props.formData.confirmPassword && this.state.showError - } - errorMsg={t( - 'talk-plugin-local-auth.change_email.incorrect_password' - )} + hasError={this.props.hasError('confirmPassword')} + errorMsg={this.props.getError('confirmPassword')} showError={this.state.showError} columnDisplay - showSuccess={false} />