diff --git a/framework/core/js/src/common/components/Checkbox.js b/framework/core/js/src/common/components/Checkbox.js index ce4b0ef8b..f9c29789b 100644 --- a/framework/core/js/src/common/components/Checkbox.js +++ b/framework/core/js/src/common/components/Checkbox.js @@ -10,23 +10,14 @@ import icon from '../helpers/icon'; * - `state` Whether or not the checkbox is checked. * - `className` The class name for the root element. * - `disabled` Whether or not the checkbox is disabled. + * - `loading` Whether or not the checkbox is loading. * - `onchange` A callback to run when the checkbox is checked/unchecked. * - `children` A text label to display next to the checkbox. */ export default class Checkbox extends Component { - init() { - /** - * Whether or not the checkbox's value is in the process of being saved. - * - * @type {Boolean} - * @public - */ - this.loading = false; - } - view() { let className = 'Checkbox ' + (this.props.state ? 'on' : 'off') + ' ' + (this.props.className || ''); - if (this.loading) className += ' loading'; + if (this.props.loading) className += ' loading'; if (this.props.disabled) className += ' disabled'; return ( @@ -45,7 +36,7 @@ export default class Checkbox extends Component { * @protected */ getDisplay() { - return this.loading ? LoadingIndicator.component({ size: 'tiny' }) : icon(this.props.state ? 'fas fa-check' : 'fas fa-times'); + return this.props.loading ? LoadingIndicator.component({ size: 'tiny' }) : icon(this.props.state ? 'fas fa-check' : 'fas fa-times'); } /** diff --git a/framework/core/js/src/common/components/Switch.js b/framework/core/js/src/common/components/Switch.js index 13eba730a..8d58dfab4 100644 --- a/framework/core/js/src/common/components/Switch.js +++ b/framework/core/js/src/common/components/Switch.js @@ -12,6 +12,6 @@ export default class Switch extends Checkbox { } getDisplay() { - return this.loading ? super.getDisplay() : ''; + return this.props.loading ? super.getDisplay() : ''; } } diff --git a/framework/core/js/src/forum/components/NotificationGrid.js b/framework/core/js/src/forum/components/NotificationGrid.js index 5ff9047af..e97a6a7d1 100644 --- a/framework/core/js/src/forum/components/NotificationGrid.js +++ b/framework/core/js/src/forum/components/NotificationGrid.js @@ -21,12 +21,11 @@ export default class NotificationGrid extends Component { this.methods = this.notificationMethods().toArray(); /** - * A map of notification type-method combinations to the checkbox instances - * that represent them. + * A map of which notification checkboxes are loading. * * @type {Object} */ - this.inputs = {}; + this.loading = {}; /** * Information about the available notification types. @@ -34,24 +33,11 @@ export default class NotificationGrid extends Component { * @type {Array} */ this.types = this.notificationTypes().toArray(); - - // For each of the notification type-method combinations, create and store a - // new checkbox component instance, which we will render in the view. - this.types.forEach((type) => { - this.methods.forEach((method) => { - const key = this.preferenceKey(type.name, method.name); - const preference = this.props.user.preferences()[key]; - - this.inputs[key] = new Checkbox({ - state: !!preference, - disabled: typeof preference === 'undefined', - onchange: () => this.toggle([key]), - }); - }); - }); } view() { + const preferences = this.props.user.preferences(); + return ( @@ -71,9 +57,20 @@ export default class NotificationGrid extends Component { - {this.methods.map((method) => ( - - ))} + {this.methods.map((method) => { + const key = this.preferenceKey(type.name, method.name); + + return ( + + ); + })} ))} @@ -112,16 +109,14 @@ export default class NotificationGrid extends Component { const enabled = !preferences[keys[0]]; keys.forEach((key) => { - const control = this.inputs[key]; - - control.loading = true; - preferences[key] = control.props.state = enabled; + this.loading[key] = true; + preferences[key] = enabled; }); m.redraw(); user.save({ preferences }).then(() => { - keys.forEach((key) => (this.inputs[key].loading = false)); + keys.forEach((key) => (this.loading[key] = false)); m.redraw(); }); @@ -133,7 +128,7 @@ export default class NotificationGrid extends Component { * @param {String} method */ toggleMethod(method) { - const keys = this.types.map((type) => this.preferenceKey(type.name, method)).filter((key) => !this.inputs[key].props.disabled); + const keys = this.types.map((type) => this.preferenceKey(type.name, method)).filter((key) => key in this.props.user.preferences()); this.toggle(keys); } @@ -144,7 +139,7 @@ export default class NotificationGrid extends Component { * @param {String} type */ toggleType(type) { - const keys = this.methods.map((method) => this.preferenceKey(type, method.name)).filter((key) => !this.inputs[key].props.disabled); + const keys = this.methods.map((method) => this.preferenceKey(type, method.name)).filter((key) => key in this.props.user.preferences()); this.toggle(keys); } diff --git a/framework/core/js/src/forum/components/SettingsPage.js b/framework/core/js/src/forum/components/SettingsPage.js index 439e40753..0bd3ea1d0 100644 --- a/framework/core/js/src/forum/components/SettingsPage.js +++ b/framework/core/js/src/forum/components/SettingsPage.js @@ -109,6 +109,8 @@ export default class SettingsPage extends UserPage { } /** + * @deprecated beta 14, remove in beta 15. + * * Generate a callback that will save a value to the given preference. * * @param {String} key @@ -116,11 +118,11 @@ export default class SettingsPage extends UserPage { */ preferenceSaver(key) { return (value, component) => { - if (component) component.loading = true; + if (component) component.props.loading = true; m.redraw(); this.user.savePreferences({ [key]: value }).then(() => { - if (component) component.loading = false; + if (component) component.props.loading = false; m.redraw(); }); }; @@ -139,10 +141,15 @@ export default class SettingsPage extends UserPage { Switch.component({ children: app.translator.trans('core.forum.settings.privacy_disclose_online_label'), state: this.user.preferences().discloseOnline, - onchange: (value, component) => { - this.user.pushAttributes({ lastSeenAt: null }); - this.preferenceSaver('discloseOnline')(value, component); + onchange: (value) => { + this.discloseOnlineLoading = true; + + this.user.savePreferences({ discloseOnline: value }).then(() => { + this.discloseOnlineLoading = false; + m.redraw(); + }); }, + loading: this.discloseOnlineLoading, }) );
{icon(type.icon)} {type.label} {this.inputs[this.preferenceKey(type.name, method.name)].render()} + {Checkbox.component({ + state: !!preferences[key], + loading: this.loading[key], + disabled: !(key in preferences), + onchange: () => this.toggle([key]), + })} +