mirror of
https://github.com/wassname/talk.git
synced 2026-07-27 11:28:12 +08:00
Implemented notification frontend functionality
This commit is contained in:
@@ -6,6 +6,7 @@ export {
|
||||
withEmit,
|
||||
excludeIf,
|
||||
withFragments,
|
||||
withMutation,
|
||||
withForgotPassword,
|
||||
withSignIn,
|
||||
withSignUp,
|
||||
|
||||
@@ -6,12 +6,12 @@ import styles from './Toggle.css';
|
||||
|
||||
class Toggle extends React.Component {
|
||||
render() {
|
||||
const { checked } = this.props;
|
||||
const { checked, onChange } = this.props;
|
||||
return (
|
||||
<div className={styles.toggle}>
|
||||
<div className={styles.description}>
|
||||
{t('talk-plugin-notifications-category-reply.toggle_description')}
|
||||
<Checkbox checked={checked} />
|
||||
<Checkbox checked={checked} onChange={onChange} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -20,6 +20,7 @@ class Toggle extends React.Component {
|
||||
|
||||
Toggle.propTypes = {
|
||||
checked: PropTypes.bool,
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Toggle;
|
||||
|
||||
@@ -5,14 +5,46 @@ import Toggle from '../components/Toggle';
|
||||
import { withFragments } from 'plugin-api/beta/client/hocs';
|
||||
|
||||
class ToggleContainer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
props.setTurnOffInputFragment({ onReply: false });
|
||||
|
||||
if (this.getOnReplySetting()) {
|
||||
props.indicateOn();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const prevSetting = this.getOnReplySetting(this.props);
|
||||
const nextSetting = this.getOnReplySetting(nextProps);
|
||||
if (prevSetting && !nextSetting) {
|
||||
nextProps.indicateOff();
|
||||
} else if (!prevSetting && nextSetting) {
|
||||
nextProps.indicateOn();
|
||||
}
|
||||
}
|
||||
|
||||
getOnReplySetting = (props = this.props) =>
|
||||
props.root.me.notificationSettings.onReply;
|
||||
|
||||
toggle = () => {
|
||||
this.props.updateNotificationSettings({
|
||||
onReply: !this.getOnReplySetting(),
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return <Toggle checked={this.props.root.me.notificationSettings.onReply} />;
|
||||
return <Toggle checked={this.getOnReplySetting()} onChange={this.toggle} />;
|
||||
}
|
||||
}
|
||||
|
||||
ToggleContainer.propTypes = {
|
||||
data: PropTypes.object,
|
||||
root: PropTypes.object,
|
||||
indicateOn: PropTypes.func.isRequired,
|
||||
indicateOff: PropTypes.func.isRequired,
|
||||
setTurnOffInputFragment: PropTypes.func.isRequired,
|
||||
updateNotificationSettings: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const enhance = compose(
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { gql } from 'react-apollo';
|
||||
|
||||
export default {
|
||||
mutations: {
|
||||
UpdateNotificationSettings: ({
|
||||
variables: { input },
|
||||
state: { auth: { user: { id } } },
|
||||
}) => ({
|
||||
update: proxy => {
|
||||
if (input.onReply === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fragment = gql`
|
||||
fragment TalkNotifications_User_Fragment on User {
|
||||
notificationSettings {
|
||||
onReply
|
||||
}
|
||||
}
|
||||
`;
|
||||
const fragmentId = `User_${id}`;
|
||||
const data = {
|
||||
__typename: 'User',
|
||||
notificationSettings: {
|
||||
__typename: 'NotificationSettings',
|
||||
onReply: input.onReply,
|
||||
},
|
||||
};
|
||||
proxy.writeFragment({ fragment, id: fragmentId, data });
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -1,9 +1,11 @@
|
||||
import Toggle from './containers/Toggle';
|
||||
import translations from './translations.yml';
|
||||
import graphql from './graphql';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
notificationSettings: [Toggle],
|
||||
},
|
||||
translations,
|
||||
...graphql,
|
||||
};
|
||||
|
||||
@@ -4,10 +4,27 @@ 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';
|
||||
|
||||
class Settings extends React.Component {
|
||||
childFactory = el => {
|
||||
const pluginName = el.type.talkPluginName;
|
||||
const props = {
|
||||
indicateOn: () => this.props.indicateOn(pluginName),
|
||||
indicateOff: () => this.props.indicateOff(pluginName),
|
||||
};
|
||||
return React.cloneElement(el, props);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { root } = this.props;
|
||||
const {
|
||||
root,
|
||||
setTurnOffInputFragment,
|
||||
updateNotificationSettings,
|
||||
turnOffAll,
|
||||
turnOffButtonDisabled,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<IfSlotIsNotEmpty slot="notificationSettings" queryData={{ root }}>
|
||||
<div>
|
||||
@@ -16,7 +33,17 @@ class Settings extends React.Component {
|
||||
{t('talk-plugin-notifications.settings_subtitle')}
|
||||
</h4>
|
||||
<div className={styles.innerSettings}>
|
||||
<Slot fill="notificationSettings" queryData={{ root }} />
|
||||
<Slot
|
||||
fill="notificationSettings"
|
||||
queryData={{ root }}
|
||||
childFactory={this.childFactory}
|
||||
setTurnOffInputFragment={setTurnOffInputFragment}
|
||||
updateNotificationSettings={updateNotificationSettings}
|
||||
/>
|
||||
<BareButton onClick={turnOffAll} disabled={turnOffButtonDisabled}>
|
||||
{' '}
|
||||
Turn Off All{' '}
|
||||
</BareButton>
|
||||
</div>
|
||||
</div>
|
||||
</IfSlotIsNotEmpty>
|
||||
@@ -26,6 +53,12 @@ class Settings extends React.Component {
|
||||
|
||||
Settings.propTypes = {
|
||||
root: PropTypes.object,
|
||||
indicateOn: PropTypes.func.isRequired,
|
||||
indicateOff: PropTypes.func.isRequired,
|
||||
setTurnOffInputFragment: PropTypes.func.isRequired,
|
||||
updateNotificationSettings: PropTypes.func.isRequired,
|
||||
turnOffAll: PropTypes.func.isRequired,
|
||||
turnOffButtonDisabled: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
|
||||
@@ -4,18 +4,53 @@ import { compose, gql } from 'react-apollo';
|
||||
import Settings from '../components/Settings';
|
||||
import { withFragments } from 'plugin-api/beta/client/hocs';
|
||||
import { getSlotFragmentSpreads } from 'plugin-api/beta/client/utils';
|
||||
import { withUpdateNotificationSettings } from '../mutations';
|
||||
|
||||
const slots = ['notificationSettings'];
|
||||
|
||||
class SettingsContainer extends React.Component {
|
||||
state = {
|
||||
hasNotifications: [],
|
||||
turnOffInput: {},
|
||||
};
|
||||
|
||||
indicateOn = plugin =>
|
||||
this.setState({
|
||||
hasNotifications: this.state.hasNotifications.concat(plugin),
|
||||
});
|
||||
indicateOff = plugin =>
|
||||
this.setState({
|
||||
hasNotifications: this.state.hasNotifications.filter(i => i !== plugin),
|
||||
});
|
||||
setTurnOffInputFragment = fragment =>
|
||||
this.setState({
|
||||
turnOffInput: { ...this.state.turnOffInput, ...fragment },
|
||||
});
|
||||
|
||||
turnOffAll = () => {
|
||||
this.props.updateNotificationSettings(this.state.turnOffInput);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <Settings data={this.props.data} root={this.props.root} />;
|
||||
return (
|
||||
<Settings
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
indicateOn={this.indicateOn}
|
||||
indicateOff={this.indicateOff}
|
||||
setTurnOffInputFragment={this.setTurnOffInputFragment}
|
||||
updateNotificationSettings={this.props.updateNotificationSettings}
|
||||
turnOffAll={this.turnOffAll}
|
||||
turnOffButtonDisabled={this.state.hasNotifications.length === 0}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SettingsContainer.propTypes = {
|
||||
data: PropTypes.object,
|
||||
root: PropTypes.object,
|
||||
updateNotificationSettings: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const enhance = compose(
|
||||
@@ -26,7 +61,8 @@ const enhance = compose(
|
||||
${getSlotFragmentSpreads(slots, 'root')}
|
||||
}
|
||||
`,
|
||||
})
|
||||
}),
|
||||
withUpdateNotificationSettings
|
||||
);
|
||||
|
||||
export default enhance(SettingsContainer);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'react-apollo';
|
||||
|
||||
export default {
|
||||
fragments: {
|
||||
UpdateNotificationSettingsResponse: gql`
|
||||
fragment Talk_UpdateNotificationSettingsResponse on UpdateNotificationSettingsResponse {
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
mutations: {
|
||||
UpdateNotificationSettings: () => ({
|
||||
optimisticResponse: {
|
||||
updateNotificationSettings: {
|
||||
__typename: 'UpdateNotificationSettingsResponse',
|
||||
errors: null,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -1,9 +1,11 @@
|
||||
import Settings from './containers/Settings';
|
||||
import translations from './translations.yml';
|
||||
import graphql from './graphql';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
profileSettings: [Settings],
|
||||
},
|
||||
translations,
|
||||
...graphql,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { withMutation } from 'plugin-api/beta/client/hocs';
|
||||
import { gql } from 'react-apollo';
|
||||
|
||||
export const withUpdateNotificationSettings = withMutation(
|
||||
gql`
|
||||
mutation UpdateNotificationSettings($input: NotificationSettingsInput!) {
|
||||
updateNotificationSettings(input: $input) {
|
||||
...UpdateNotificationSettingsResponse
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
props: ({ mutate }) => ({
|
||||
updateNotificationSettings: input => {
|
||||
return mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user