From e3d96073d70bc6be5cdaf3fe90cf6d3264c99509 Mon Sep 17 00:00:00 2001 From: Alexandru Munteanu <alexandru.munt@gmail.com> Date: Tue, 17 Jul 2018 08:51:04 +0300 Subject: [PATCH] feat(email-subscriptions): subscribe and unsubscribe from emails --- packages/component-user-manager/src/Users.js | 33 +++++++++++++++ .../src/routes/users/subscriptions.js | 22 ++++++++++ .../components/UserProfile/AccountDetails.js | 2 +- .../UserProfile/AccountDetailsCard.js | 6 +-- .../UserProfile/AccountDetailsEdit.js | 2 +- .../UserProfile/EmailNotifications.js | 41 +++++++++++++++++-- .../components/UserProfile/UserProfilePage.js | 19 ++++++--- .../components-faraday/src/redux/users.js | 9 +++- packages/xpub-faraday/config/default.js | 2 +- packages/xpub-faraday/config/validations.js | 1 + 10 files changed, 120 insertions(+), 17 deletions(-) create mode 100644 packages/component-user-manager/src/routes/users/subscriptions.js diff --git a/packages/component-user-manager/src/Users.js b/packages/component-user-manager/src/Users.js index 95d064990..8b95b8c82 100644 --- a/packages/component-user-manager/src/Users.js +++ b/packages/component-user-manager/src/Users.js @@ -125,6 +125,39 @@ const Users = app => { require('./routes/users/changePassword')(app.locals.models), ) + /** + * @api {patch} /api/users/subscriptions Change user's email subscription flag + * @apiGroup Users + * @apiParamExample {json} Body + * { + * "isUnsubscribed": true, + * } + * @apiSuccessExample {json} Success + * HTTP/1.1 200 OK + * { + * "id": "a6184463-b17a-42f8-b02b-ae1d755cdc6b", + * "type": "user", + * "admin": false, + * "email": "email@example.com", + * "teams": [], + * "username": "email@example.com", + * "fragments": [], + * "collections": [], + * "isConfirmed": true, + * "editorInChief": false, + * "handlingEditor": false, + * "isUnsubscribed": true + * } + * @apiErrorExample {json} Reset password errors + * HTTP/1.1 400 Bad Request + * HTTP/1.1 404 Not Found + */ + app.patch( + '/api/users/subscriptions', + authBearer, + require('./routes/users/subscriptions')(app.locals.models), + ) + // register ORCID authentication strategy orcidRoutes(app) } diff --git a/packages/component-user-manager/src/routes/users/subscriptions.js b/packages/component-user-manager/src/routes/users/subscriptions.js new file mode 100644 index 000000000..7633fc64b --- /dev/null +++ b/packages/component-user-manager/src/routes/users/subscriptions.js @@ -0,0 +1,22 @@ +const { services } = require('pubsweet-component-helper-service') + +module.exports = models => async (req, res) => { + const { isUnsubscribed } = req.body + + if (!services.checkForUndefinedParams(isUnsubscribed)) + return res.status(400).json({ error: 'Missing required params.' }) + + let user + try { + user = await models.User.find(req.user) + user.isUnsubscribed = isUnsubscribed + user = await user.save() + + return res.status(200).json({ user }) + } catch (e) { + const notFoundError = await services.handleNotFoundError(e, 'User') + return res.status(notFoundError.status).json({ + error: notFoundError.message, + }) + } +} diff --git a/packages/components-faraday/src/components/UserProfile/AccountDetails.js b/packages/components-faraday/src/components/UserProfile/AccountDetails.js index 768c8a46e..81080db09 100644 --- a/packages/components-faraday/src/components/UserProfile/AccountDetails.js +++ b/packages/components-faraday/src/components/UserProfile/AccountDetails.js @@ -29,7 +29,7 @@ export default compose( withJournal, withState('isEdit', 'setEdit', false), withHandlers({ - setEditMode: ({ setEdit }) => value => setEdit(value), + setEditMode: ({ setEdit }) => value => () => setEdit(value), }), )(AccountDetails) diff --git a/packages/components-faraday/src/components/UserProfile/AccountDetailsCard.js b/packages/components-faraday/src/components/UserProfile/AccountDetailsCard.js index 22dadc2aa..7e085536a 100644 --- a/packages/components-faraday/src/components/UserProfile/AccountDetailsCard.js +++ b/packages/components-faraday/src/components/UserProfile/AccountDetailsCard.js @@ -3,10 +3,10 @@ import React, { Fragment } from 'react' import { Row, RowItem, - LabelHeader, + LinkText, LabelTitle, + LabelHeader, DefaultText, - LinkText, } from '../UIComponents/FormItems' import { getUserTitle } from '../utils' @@ -48,7 +48,7 @@ const AccountDetailsCard = ({ </Row> <Row noMargin> <RowItem> - <LinkText onClick={() => setEditMode(true)}>Edit details</LinkText> + <LinkText onClick={setEditMode(true)}>Edit details</LinkText> <LinkText onClick={() => history.push('/profile/change-password')}> Change Password </LinkText> diff --git a/packages/components-faraday/src/components/UserProfile/AccountDetailsEdit.js b/packages/components-faraday/src/components/UserProfile/AccountDetailsEdit.js index f247552c6..a88c42c6e 100644 --- a/packages/components-faraday/src/components/UserProfile/AccountDetailsEdit.js +++ b/packages/components-faraday/src/components/UserProfile/AccountDetailsEdit.js @@ -11,7 +11,7 @@ const AccountDetailsEdit = ({ journal, user, setEditMode, handleSubmit }) => ( <Root onSubmit={handleSubmit}> <EditUserForm journal={journal} title="Edit account details" user={user} /> <Row> - <Button onClick={() => setEditMode(false)}>Cancel</Button> + <Button onClick={setEditMode(false)}>Cancel</Button> <Button primary type="submit"> Save </Button> diff --git a/packages/components-faraday/src/components/UserProfile/EmailNotifications.js b/packages/components-faraday/src/components/UserProfile/EmailNotifications.js index 853c24047..7f20c07ec 100644 --- a/packages/components-faraday/src/components/UserProfile/EmailNotifications.js +++ b/packages/components-faraday/src/components/UserProfile/EmailNotifications.js @@ -1,9 +1,14 @@ import React from 'react' import styled from 'styled-components' +import { compose, withHandlers } from 'recompose' +import { + withModal, + ConfirmationModal, +} from 'pubsweet-component-modal/src/components' import { Row, RowItem, LabelHeader, LinkText } from '../UIComponents/FormItems' -const EmailNotifications = ({ subscribed = '' }) => ( +const EmailNotifications = ({ subscribed = '', subscribe, unsubscribe }) => ( <Root> <Row noMargin> <RowItem> @@ -13,20 +18,48 @@ const EmailNotifications = ({ subscribed = '' }) => ( {!subscribed ? ( <Row noMargin> <RowItem> - <LinkText>Re-subscribe</LinkText> + <LinkText onClick={subscribe}>Re-subscribe</LinkText> </RowItem> </Row> ) : ( <Row noMargin> <RowItem> - <LinkText>Unsubscribe</LinkText> + <LinkText onClick={unsubscribe}>Unsubscribe</LinkText> </RowItem> </Row> )} </Root> ) -export default EmailNotifications +export default compose( + withModal(props => ({ + modalComponent: ConfirmationModal, + })), + withHandlers({ + subscribe: ({ showModal, hideModal, changeEmailSubscription }) => () => { + showModal({ + title: 'Subscribe to emails', + subtitle: 'Are you sure you want to subscribe to emails?', + onConfirm: () => { + changeEmailSubscription(false) + hideModal() + }, + onCancel: hideModal, + }) + }, + unsubscribe: ({ showModal, hideModal, changeEmailSubscription }) => () => { + showModal({ + title: 'Unsubscribe from emails', + subtitle: 'Are you sure you want to unsubscribe from emails?', + onConfirm: () => { + changeEmailSubscription(true) + hideModal() + }, + onCancel: hideModal, + }) + }, + }), +)(EmailNotifications) // #region styles const Root = styled.div` diff --git a/packages/components-faraday/src/components/UserProfile/UserProfilePage.js b/packages/components-faraday/src/components/UserProfile/UserProfilePage.js index 462abc4c4..f45f86e3f 100644 --- a/packages/components-faraday/src/components/UserProfile/UserProfilePage.js +++ b/packages/components-faraday/src/components/UserProfile/UserProfilePage.js @@ -6,11 +6,12 @@ import styled from 'styled-components' import { selectCurrentUser } from 'xpub-selectors' import { BreadcrumbsHeader } from 'pubsweet-components-faraday/src/components' -import AccountDetails from './AccountDetails' import LinkOrcID from './LinkOrcID' +import AccountDetails from './AccountDetails' import EmailNotifications from './EmailNotifications' +import { changeEmailSubscription } from '../../redux/users' -const UserProfilePage = ({ history, user }) => ( +const UserProfilePage = ({ history, user, changeEmailSubscription }) => ( <Root> <BreadcrumbsHeader history={history} @@ -20,15 +21,21 @@ const UserProfilePage = ({ history, user }) => ( underlined /> <AccountDetails history={history} user={user} /> - <EmailNotifications subscribed={get(user, 'subscription')} /> + <EmailNotifications + changeEmailSubscription={changeEmailSubscription} + subscribed={!get(user, 'isUnsubscribed')} + /> <LinkOrcID id={get(user, 'id')} orcid={get(user, 'orcid')} /> </Root> ) export default compose( - connect(state => ({ - user: selectCurrentUser(state), - })), + connect( + state => ({ + user: selectCurrentUser(state), + }), + { changeEmailSubscription }, + ), )(UserProfilePage) // #region styles diff --git a/packages/components-faraday/src/redux/users.js b/packages/components-faraday/src/redux/users.js index a4e6d1a12..973675ef2 100644 --- a/packages/components-faraday/src/redux/users.js +++ b/packages/components-faraday/src/redux/users.js @@ -1,5 +1,6 @@ import { get } from 'lodash' -import { create } from 'pubsweet-client/src/helpers/api' +import { actions } from 'pubsweet-client' +import { create, update } from 'pubsweet-client/src/helpers/api' const LOGIN_SUCCESS = 'LOGIN_SUCCESS' @@ -20,3 +21,9 @@ export const confirmUser = (userId, confirmationToken) => dispatch => localStorage.setItem('token', user.token) return dispatch(loginSuccess(user)) }) + +export const changeEmailSubscription = isUnsubscribed => dispatch => { + update(`/users/subscriptions`, { + isUnsubscribed, + }).then(() => dispatch(actions.getCurrentUser())) +} diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js index 522a8f83e..37367502a 100644 --- a/packages/xpub-faraday/config/default.js +++ b/packages/xpub-faraday/config/default.js @@ -46,7 +46,7 @@ module.exports = { API_ENDPOINT: '/api', baseUrl: process.env.CLIENT_BASE_URL || 'http://localhost:3000', 'login-redirect': '/', - 'redux-log': false, + 'redux-log': true, theme: process.env.PUBSWEET_THEME, }, orcid: { diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js index 61e603fe9..f8ca55e07 100644 --- a/packages/xpub-faraday/config/validations.js +++ b/packages/xpub-faraday/config/validations.js @@ -131,6 +131,7 @@ module.exports = { confirmationToken: Joi.string().allow(''), agreeTC: Joi.boolean(), isActive: Joi.boolean().default(true), + isUnsubscribed: Joi.boolean(), }, team: { group: Joi.string(), -- GitLab