diff --git a/client/coral-admin/src/routes/Community/components/People.css b/client/coral-admin/src/routes/Community/components/People.css
index c4561ace1..669da480d 100644
--- a/client/coral-admin/src/routes/Community/components/People.css
+++ b/client/coral-admin/src/routes/Community/components/People.css
@@ -130,3 +130,12 @@ th.header:nth-child(2), th.header:nth-child(3) {
.loadMore {
margin-top: 24px;
}
+
+.roleDropdown {
+ width: 150px;
+}
+
+.roleOption {
+ min-width: 100px;
+}
+
diff --git a/client/coral-admin/src/routes/Community/components/People.js b/client/coral-admin/src/routes/Community/components/People.js
index 1f5e4bab8..5645f88f1 100644
--- a/client/coral-admin/src/routes/Community/components/People.js
+++ b/client/coral-admin/src/routes/Community/components/People.js
@@ -200,24 +200,31 @@ class People extends React.Component {
setUserRole(user.id, role)}
>
diff --git a/client/coral-admin/src/routes/Stories/components/Stories.css b/client/coral-admin/src/routes/Stories/components/Stories.css
index 63a05ab6a..28f67151d 100644
--- a/client/coral-admin/src/routes/Stories/components/Stories.css
+++ b/client/coral-admin/src/routes/Stories/components/Stories.css
@@ -89,3 +89,12 @@
display: inline-block;
}
}
+
+.statusDropdown {
+ width: 150px;
+}
+
+.statusDropdownOption {
+ min-width: 100px;
+}
+
diff --git a/client/coral-admin/src/routes/Stories/components/Stories.js b/client/coral-admin/src/routes/Stories/components/Stories.js
index f94685fe8..ad2c7c5fc 100644
--- a/client/coral-admin/src/routes/Stories/components/Stories.js
+++ b/client/coral-admin/src/routes/Stories/components/Stories.js
@@ -22,11 +22,20 @@ class Stories extends Component {
const closed = !!(closedAt && new Date(closedAt).getTime() < Date.now());
return (
this.props.onStatusChange(value, id)}
>
-
-
+
+
);
};
diff --git a/client/coral-framework/components/TalkProvider.js b/client/coral-framework/components/TalkProvider.js
index 343d559ea..9caba7fb8 100644
--- a/client/coral-framework/components/TalkProvider.js
+++ b/client/coral-framework/components/TalkProvider.js
@@ -10,6 +10,7 @@ class TalkProvider extends React.Component {
plugins: this.props.plugins,
rest: this.props.rest,
graphql: this.props.graphql,
+ introspection: this.props.introspection,
notification: this.props.notification,
localStorage: this.props.localStorage,
sessionStorage: this.props.sessionStorage,
@@ -29,6 +30,7 @@ class TalkProvider extends React.Component {
TalkProvider.childContextTypes = {
pym: PropTypes.object,
+ introspection: PropTypes.object,
eventEmitter: PropTypes.object,
plugins: PropTypes.object,
rest: PropTypes.func,
diff --git a/client/coral-framework/hocs/index.js b/client/coral-framework/hocs/index.js
index 5e2e3dd40..7ed114b73 100644
--- a/client/coral-framework/hocs/index.js
+++ b/client/coral-framework/hocs/index.js
@@ -11,6 +11,7 @@ export { default as withSignUp } from './withSignUp';
export { default as withForgotPassword } from './withForgotPassword';
export { default as withSetUsername } from './withSetUsername';
export { default as withPopupAuthHandler } from './withPopupAuthHandler';
+export { default as withEnumValues } from './withEnumValues';
export {
default as withResendEmailConfirmation,
} from './withResendEmailConfirmation';
diff --git a/client/coral-framework/hocs/withEnumValues.js b/client/coral-framework/hocs/withEnumValues.js
new file mode 100644
index 000000000..ea5cef922
--- /dev/null
+++ b/client/coral-framework/hocs/withEnumValues.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import hoistStatics from 'recompose/hoistStatics';
+import PropTypes from 'prop-types';
+
+/**
+ * WithEnumValues inject given property name for given enum.
+ */
+export default (enumName, propName) =>
+ hoistStatics(WrappedComponent => {
+ class WithEnumValues extends React.Component {
+ static contextTypes = {
+ introspection: PropTypes.object,
+ };
+
+ render() {
+ const inject = {
+ [propName]: this.context.introspection.getEnumValues(enumName),
+ };
+ return ;
+ }
+ }
+
+ return WithEnumValues;
+ });
diff --git a/client/coral-framework/services/introspection.js b/client/coral-framework/services/introspection.js
index 8e3160aa7..e4636a339 100644
--- a/client/coral-framework/services/introspection.js
+++ b/client/coral-framework/services/introspection.js
@@ -19,6 +19,16 @@ class Introspection {
isValidEnumValue(name, value) {
return this._enums[name] && this._enums[name].indexOf(value) >= 0;
}
+
+ /**
+ * getEnumValues returns array of possible values.
+ * @param {string} name
+ * @param {string} value
+ * @return {array}
+ */
+ getEnumValues(name) {
+ return this._enums[name];
+ }
}
/**
diff --git a/client/coral-ui/components/Dropdown.css b/client/coral-ui/components/Dropdown.css
index 794955220..0b221490d 100644
--- a/client/coral-ui/components/Dropdown.css
+++ b/client/coral-ui/components/Dropdown.css
@@ -1,20 +1,27 @@
.dropdown {
position: relative;
- width: 150px;
height: 34px;
background: #2c2c2c;
box-sizing: border-box;
color: white;
border-radius: 3px;
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
+ line-height: 20px;
font-size: 0.98em;
border-radius: 3px;
+ cursor: pointer;
+
+ &.disabled {
+ color: #e5e5e5;
+ background: #888;
+ cursor: default;
+ pointer-events: none;
+ }
}
.toggle {
- padding: 8px 15px;
- cursor: pointer;
+ padding: 8px 45px 8px 15px;
outline: none;
&:focus {
@@ -38,7 +45,6 @@
border-radius: 2px;
background: white;
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
- width: 100%;
list-style: none;
padding: 0;
margin: 0;
diff --git a/client/coral-ui/components/Dropdown.js b/client/coral-ui/components/Dropdown.js
index fe852d265..bf885477f 100644
--- a/client/coral-ui/components/Dropdown.js
+++ b/client/coral-ui/components/Dropdown.js
@@ -13,6 +13,12 @@ class Dropdown extends React.Component {
isOpen: false,
};
+ componentWillReceiveProps(nextProps) {
+ if (this.state.isOpen && nextProps.disabled) {
+ this.toggle();
+ }
+ }
+
componentDidUpdate(_, prevState) {
if (!this.state.isOpen && prevState.isOpen) {
// Refocus on the toggle element when menu closes.
@@ -69,6 +75,10 @@ class Dropdown extends React.Component {
};
toggle = () => {
+ if (this.props.disabled) {
+ return false;
+ }
+
this.setState({
isOpen: !this.state.isOpen,
});
@@ -135,11 +145,21 @@ class Dropdown extends React.Component {
containerClassName,
toggleClassName,
toggleOpenClassName,
+ disabled,
+ className,
} = this.props;
return (
{this.props.icon && (
@@ -206,6 +226,7 @@ class Dropdown extends React.Component {
}
Dropdown.propTypes = {
+ className: PropTypes.string,
containerClassName: PropTypes.string,
toggleClassName: PropTypes.string,
toggleOpenClassName: PropTypes.string,
@@ -213,6 +234,7 @@ Dropdown.propTypes = {
icon: PropTypes.string,
onChange: PropTypes.func.isRequired,
children: PropTypes.node.isRequired,
+ disabled: PropTypes.bool,
value: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string,
diff --git a/client/coral-ui/components/Option.css b/client/coral-ui/components/Option.css
index 1e7627681..6894d26a4 100644
--- a/client/coral-ui/components/Option.css
+++ b/client/coral-ui/components/Option.css
@@ -2,6 +2,7 @@
padding: 10px;
text-transform: capitalize;
outline: none;
+ white-space: nowrap;
&:focus, &:hover {
background-color: #ccc;
diff --git a/plugin-api/beta/client/hocs/index.js b/plugin-api/beta/client/hocs/index.js
index 8b91c83de..35899a418 100644
--- a/plugin-api/beta/client/hocs/index.js
+++ b/plugin-api/beta/client/hocs/index.js
@@ -12,6 +12,7 @@ export {
withSignUp,
withResendEmailConfirmation,
withSetUsername,
+ withEnumValues,
} from 'coral-framework/hocs';
export {
withIgnoreUser,
diff --git a/plugins/talk-plugin-notifications-digest-daily/client/.eslintrc.json b/plugins/talk-plugin-notifications-digest-daily/client/.eslintrc.json
new file mode 100644
index 000000000..c8a6db18a
--- /dev/null
+++ b/plugins/talk-plugin-notifications-digest-daily/client/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@coralproject/eslint-config-talk/client"
+}
diff --git a/plugins/talk-plugin-notifications-digest-daily/client/index.js b/plugins/talk-plugin-notifications-digest-daily/client/index.js
new file mode 100644
index 000000000..6f418c825
--- /dev/null
+++ b/plugins/talk-plugin-notifications-digest-daily/client/index.js
@@ -0,0 +1,5 @@
+import translations from './translations.yml';
+
+export default {
+ translations,
+};
diff --git a/plugins/talk-plugin-notifications-digest-daily/client/translations.yml b/plugins/talk-plugin-notifications-digest-daily/client/translations.yml
new file mode 100644
index 000000000..1744918ec
--- /dev/null
+++ b/plugins/talk-plugin-notifications-digest-daily/client/translations.yml
@@ -0,0 +1,4 @@
+en:
+ talk-plugin-notifications:
+ digest_enum:
+ DAILY: In a daily digest
diff --git a/plugins/talk-plugin-notifications-digest-hourly/client/.eslintrc.json b/plugins/talk-plugin-notifications-digest-hourly/client/.eslintrc.json
new file mode 100644
index 000000000..c8a6db18a
--- /dev/null
+++ b/plugins/talk-plugin-notifications-digest-hourly/client/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@coralproject/eslint-config-talk/client"
+}
diff --git a/plugins/talk-plugin-notifications-digest-hourly/client/index.js b/plugins/talk-plugin-notifications-digest-hourly/client/index.js
new file mode 100644
index 000000000..6f418c825
--- /dev/null
+++ b/plugins/talk-plugin-notifications-digest-hourly/client/index.js
@@ -0,0 +1,5 @@
+import translations from './translations.yml';
+
+export default {
+ translations,
+};
diff --git a/plugins/talk-plugin-notifications-digest-hourly/client/translations.yml b/plugins/talk-plugin-notifications-digest-hourly/client/translations.yml
new file mode 100644
index 000000000..da4bad14f
--- /dev/null
+++ b/plugins/talk-plugin-notifications-digest-hourly/client/translations.yml
@@ -0,0 +1,4 @@
+en:
+ talk-plugin-notifications:
+ digest_enum:
+ HOURLY: In an hourly digest
diff --git a/plugins/talk-plugin-notifications/client/components/Settings.css b/plugins/talk-plugin-notifications/client/components/Settings.css
index c4d43fd9a..dd3526dc0 100644
--- a/plugins/talk-plugin-notifications/client/components/Settings.css
+++ b/plugins/talk-plugin-notifications/client/components/Settings.css
@@ -30,3 +30,16 @@
.disabled {
color: #e5e5e5;
}
+
+.digest {
+ display: flex;
+ align-items: center;
+}
+
+.titleDigest {
+ width: 100%;
+}
+
+.digestDropDown {
+ flex-shrink: 0;
+}
diff --git a/plugins/talk-plugin-notifications/client/components/Settings.js b/plugins/talk-plugin-notifications/client/components/Settings.js
index 010422491..431c0c2fd 100644
--- a/plugins/talk-plugin-notifications/client/components/Settings.js
+++ b/plugins/talk-plugin-notifications/client/components/Settings.js
@@ -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;
return (
@@ -51,14 +59,37 @@ class Settings extends React.Component {
updateNotificationSettings={updateNotificationSettings}
disabled={needEmailVerification}
/>
-
- {t('talk-plugin-notifications.turn_off_all')}
-
+
+
+ {t('talk-plugin-notifications.digest_option')}
+
+
+ {digestFrequencyValues.map(v => (
+
+ ))}
+
+
+
+ {t('talk-plugin-notifications.turn_off_all')}
+
);
@@ -72,9 +103,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;
diff --git a/plugins/talk-plugin-notifications/client/containers/Settings.js b/plugins/talk-plugin-notifications/client/containers/Settings.js
index 76a03462d..6c3245dae 100644
--- a/plugins/talk-plugin-notifications/client/containers/Settings.js
+++ b/plugins/talk-plugin-notifications/client/containers/Settings.js
@@ -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';
@@ -39,6 +43,11 @@ class SettingsContainer extends React.Component {
);
}
+ setDigestFrequency(val) {
+ // TODO: implement mutation.
+ console.log(val);
+ }
+
render() {
return (
);
}
@@ -61,6 +76,7 @@ SettingsContainer.propTypes = {
data: PropTypes.object,
root: PropTypes.object,
updateNotificationSettings: PropTypes.func.isRequired,
+ digestFrequencyValues: PropTypes.array.isRequired,
};
const enhance = compose(
@@ -70,6 +86,9 @@ const enhance = compose(
__typename
${getSlotFragmentSpreads(slots, 'root')}
me {
+ notificationSettings {
+ digestFrequency
+ }
email
profiles {
provider
@@ -85,7 +104,8 @@ const enhance = compose(
props =>
!props.root.me.profiles.some(profile => profile.provider === 'local')
),
- withUpdateNotificationSettings
+ withUpdateNotificationSettings,
+ withEnumValues('DIGEST_FREQUENCY', 'digestFrequencyValues')
);
export default enhance(SettingsContainer);
diff --git a/plugins/talk-plugin-notifications/client/translations.yml b/plugins/talk-plugin-notifications/client/translations.yml
index 0d74114d2..0fccc3afc 100644
--- a/plugins/talk-plugin-notifications/client/translations.yml
+++ b/plugins/talk-plugin-notifications/client/translations.yml
@@ -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: I want to receive notifications
+ digest_enum:
+ NONE: Immediately
|