diff --git a/app/scenes/Settings/Notifications.js b/app/scenes/Settings/Notifications.js index daf2e16c2..69dbd7790 100644 --- a/app/scenes/Settings/Notifications.js +++ b/app/scenes/Settings/Notifications.js @@ -2,10 +2,12 @@ import * as React from 'react'; import { debounce } from 'lodash'; import { observer, inject } from 'mobx-react'; +import styled from 'styled-components'; import CenteredContent from 'components/CenteredContent'; import PageTitle from 'components/PageTitle'; import HelpText from 'components/HelpText'; import NotificationListItem from './components/NotificationListItem'; +import Notice from 'shared/components/Notice'; import UiStore from 'stores/UiStore'; import NotificationSettingsStore from 'stores/NotificationSettingsStore'; @@ -31,6 +33,20 @@ const options = [ title: 'Collection created', description: 'Receive a notification whenever a new collection is created', }, + { + separator: true, + }, + { + event: 'emails.onboarding', + title: 'Getting started', + description: + 'Tips on getting started with Outline`s features and functionality', + }, + { + event: 'emails.features', + title: 'New features', + description: 'Receive an email when new features of note are added', + }, ]; @observer @@ -60,9 +76,16 @@ class Notifications extends React.Component { render() { const { notificationSettings } = this.props; + const showSuccessNotice = window.location.search === '?success'; return ( + {showSuccessNotice && ( + + Unsubscription successful. Your notification settings were updated + + )} +

Notifications

@@ -71,6 +94,8 @@ class Notifications extends React.Component { {options.map(option => { + if (option.separator) return ; + const setting = notificationSettings.getByEvent(option.event); return ( @@ -90,4 +115,8 @@ class Notifications extends React.Component { } } +const Separator = styled.hr` + padding-bottom: 12px; +`; + export default inject('notificationSettings', 'ui')(Notifications); diff --git a/server/api/notificationSettings.js b/server/api/notificationSettings.js index 7ef09c845..c91d01f57 100644 --- a/server/api/notificationSettings.js +++ b/server/api/notificationSettings.js @@ -57,4 +57,21 @@ router.post('notificationSettings.delete', auth(), async ctx => { }; }); +router.post('notificationSettings.unsubscribe', async ctx => { + const { id, token } = ctx.body; + ctx.assertPresent(id, 'id is required'); + ctx.assertPresent(token, 'token is required'); + + const setting = await NotificationSetting.findById(id); + if (setting) { + if (token !== setting.unsubscribeToken) { + ctx.redirect(`${process.env.URL}?notice=invalid-auth`); + } + + await setting.destroy(); + } + + ctx.redirect(`${process.env.URL}/settings/notifications?success`); +}); + export default router; diff --git a/server/emails/CollectionNotificationEmail.js b/server/emails/CollectionNotificationEmail.js index f7fde6124..b5a0238fa 100644 --- a/server/emails/CollectionNotificationEmail.js +++ b/server/emails/CollectionNotificationEmail.js @@ -13,6 +13,7 @@ export type Props = { actor: User, collection: Collection, eventName: string, + unsubscribeUrl: string, }; export const collectionNotificationEmailText = ({ @@ -20,7 +21,7 @@ export const collectionNotificationEmailText = ({ collection, eventName = 'created', }: Props) => ` -"${document.title}" ${eventName} +${collection.name} ${actor.name} ${eventName} the collection "${collection.name}" @@ -31,17 +32,16 @@ export const CollectionNotificationEmail = ({ actor, collection, eventName = 'created', + unsubscribeUrl, }: Props) => { return (
- - "{collection.name}" {eventName} - + {collection.name}

- {actor.name} {eventName} the collection "{collection.title}". + {actor.name} {eventName} the collection "{collection.name}".

@@ -51,7 +51,7 @@ export const CollectionNotificationEmail = ({

-