Merge branch 'master' into refactor-graph

This commit is contained in:
Chi Vinh Le
2018-03-09 19:27:35 +01:00
59 changed files with 1060 additions and 289 deletions
@@ -1,6 +1,6 @@
.root {
margin-bottom: 20px;
width: 380px;
width: 350px;
}
.innerSettings {
@@ -30,3 +30,16 @@
.disabled {
color: #e5e5e5;
}
.digest {
display: flex;
align-items: center;
}
.titleDigest {
width: 100%;
}
.digestDropDown {
flex-shrink: 0;
}
@@ -4,7 +4,11 @@ import { IfSlotIsNotEmpty } from 'plugin-api/beta/client/components';
import { Slot } from 'plugin-api/beta/client/components';
import { t } from 'plugin-api/beta/client/services';
import styles from './Settings.css';
import { BareButton } from 'plugin-api/beta/client/components/ui';
import {
BareButton,
Dropdown,
Option,
} from 'plugin-api/beta/client/components/ui';
import EmailVerificationBanner from '../containers/EmailVerificationBanner';
import cn from 'classnames';
@@ -24,9 +28,13 @@ class Settings extends React.Component {
setTurnOffInputFragment,
updateNotificationSettings,
turnOffAll,
turnOffButtonDisabled,
needEmailVerification,
email,
digestFrequencyValues,
digestFrequency,
disableDigest,
disableTurnoffButton,
onChangeDigestFrequency,
} = this.props;
const slotPassthrough = {
@@ -37,10 +45,15 @@ class Settings extends React.Component {
};
return (
<IfSlotIsNotEmpty slot="notificationSettings" passthrough={slotPassthrough}>
<IfSlotIsNotEmpty
slot="notificationSettings"
passthrough={slotPassthrough}
>
<div className={styles.root}>
<h3>{t('talk-plugin-notifications.settings_title')}</h3>
{needEmailVerification && <EmailVerificationBanner email={email} />}
<div className={styles.bannerContainer}>
{needEmailVerification && <EmailVerificationBanner email={email} />}
</div>
<h4
className={cn(styles.subtitle, {
[styles.disabled]: needEmailVerification,
@@ -55,14 +68,39 @@ class Settings extends React.Component {
childFactory={this.childFactory}
passthrough={slotPassthrough}
/>
<BareButton
className={styles.turnOffButton}
onClick={turnOffAll}
disabled={turnOffButtonDisabled}
>
{t('talk-plugin-notifications.turn_off_all')}
</BareButton>
</div>
{digestFrequencyValues.length > 1 && (
<div className={styles.digest}>
<h4
className={cn(styles.titleDigest, {
[styles.disabled]: disableDigest,
})}
>
{t('talk-plugin-notifications.digest_option')}
</h4>
<Dropdown
className={styles.digestDropDown}
value={digestFrequency}
onChange={onChangeDigestFrequency}
disabled={disableDigest}
>
{digestFrequencyValues.map(v => (
<Option
value={v}
key={v}
label={t(`talk-plugin-notifications.digest_enum.${v}`)}
/>
))}
</Dropdown>
</div>
)}
<BareButton
className={styles.turnOffButton}
onClick={turnOffAll}
disabled={disableTurnoffButton}
>
{t('talk-plugin-notifications.turn_off_all')}
</BareButton>
</div>
</IfSlotIsNotEmpty>
);
@@ -76,9 +114,13 @@ Settings.propTypes = {
setTurnOffInputFragment: PropTypes.func.isRequired,
updateNotificationSettings: PropTypes.func.isRequired,
turnOffAll: PropTypes.func.isRequired,
turnOffButtonDisabled: PropTypes.bool.isRequired,
disableTurnoffButton: PropTypes.bool.isRequired,
disableDigest: PropTypes.bool.isRequired,
needEmailVerification: PropTypes.bool.isRequired,
email: PropTypes.string,
digestFrequencyValues: PropTypes.array.isRequired,
digestFrequency: PropTypes.string.isRequired,
onChangeDigestFrequency: PropTypes.func.isRequired,
};
export default Settings;
@@ -2,7 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { compose, gql } from 'react-apollo';
import Settings from '../components/Settings';
import { withFragments, excludeIf } from 'plugin-api/beta/client/hocs';
import {
withFragments,
excludeIf,
withEnumValues,
} from 'plugin-api/beta/client/hocs';
import { getSlotFragmentSpreads } from 'plugin-api/beta/client/utils';
import { withUpdateNotificationSettings } from '../mutations';
@@ -33,6 +37,10 @@ class SettingsContainer extends React.Component {
this.props.updateNotificationSettings(this.state.turnOffInput);
};
setDigestFrequency = digestFrequency => {
this.props.updateNotificationSettings({ digestFrequency });
};
getNeedEmailVerification() {
return !this.props.root.me.profiles.some(
profile => profile.provider === 'local' && profile.confirmedAt
@@ -49,9 +57,15 @@ class SettingsContainer extends React.Component {
setTurnOffInputFragment={this.setTurnOffInputFragment}
updateNotificationSettings={this.props.updateNotificationSettings}
turnOffAll={this.turnOffAll}
turnOffButtonDisabled={this.state.hasNotifications.length === 0}
needEmailVerification={this.getNeedEmailVerification()}
email={this.props.root.me.email}
digestFrequencyValues={this.props.digestFrequencyValues}
digestFrequency={
this.props.root.me.notificationSettings.digestFrequency
}
disableDigest={this.state.hasNotifications.length === 0}
disableTurnoffButton={this.state.hasNotifications.length === 0}
onChangeDigestFrequency={this.setDigestFrequency}
/>
);
}
@@ -61,6 +75,7 @@ SettingsContainer.propTypes = {
data: PropTypes.object,
root: PropTypes.object,
updateNotificationSettings: PropTypes.func.isRequired,
digestFrequencyValues: PropTypes.array.isRequired,
};
const enhance = compose(
@@ -70,6 +85,9 @@ const enhance = compose(
__typename
${getSlotFragmentSpreads(slots, 'root')}
me {
notificationSettings {
digestFrequency
}
email
profiles {
provider
@@ -85,7 +103,8 @@ const enhance = compose(
props =>
!props.root.me.profiles.some(profile => profile.provider === 'local')
),
withUpdateNotificationSettings
withUpdateNotificationSettings,
withEnumValues('DIGEST_FREQUENCY', 'digestFrequencyValues')
);
export default enhance(SettingsContainer);
@@ -11,13 +11,38 @@ export default {
`,
},
mutations: {
UpdateNotificationSettings: () => ({
UpdateNotificationSettings: ({
variables: { input },
state: { auth: { user: { id } } },
}) => ({
optimisticResponse: {
updateNotificationSettings: {
__typename: 'UpdateNotificationSettingsResponse',
errors: null,
},
},
update: proxy => {
if (input.digestFrequency === undefined) {
return;
}
const fragment = gql`
fragment TalkNotificationsCategoryReply_User_Fragment on User {
notificationSettings {
digestFrequency
}
}
`;
const fragmentId = `User_${id}`;
const data = {
__typename: 'User',
notificationSettings: {
__typename: 'NotificationSettings',
digestFrequency: input.digestFrequency,
},
};
proxy.writeFragment({ fragment, id: fragmentId, data });
},
}),
},
};
@@ -13,3 +13,6 @@ en:
banner_error:
title: Error
text: There has been an error sending your verification email. Please try again later.
digest_option: Send notifications
digest_enum:
NONE: Immediately