diff --git a/app/assets/javascripts/discourse/controllers/preferences.js.es6 b/app/assets/javascripts/discourse/controllers/preferences.js.es6 index ac848d3ea29..d4180e8b6b4 100644 --- a/app/assets/javascripts/discourse/controllers/preferences.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences.js.es6 @@ -1,230 +1,3 @@ -import { setting } from 'discourse/lib/computed'; -import CanCheckEmails from 'discourse/mixins/can-check-emails'; -import { popupAjaxError } from 'discourse/lib/ajax-error'; -import { default as computed, observes } from "ember-addons/ember-computed-decorators"; -import { cook } from 'discourse/lib/text'; -import { NotificationLevels } from 'discourse/lib/notification-levels'; -import { listThemes, selectDefaultTheme, previewTheme } from 'discourse/lib/theme-selector'; - -export default Ember.Controller.extend(CanCheckEmails, { - - userSelectableThemes: function(){ - return listThemes(this.site); - }.property(), - - @observes("selectedTheme") - themeKeyChanged() { - let key = this.get("selectedTheme"); - previewTheme(key); - }, - - @computed("model.watchedCategories", "model.trackedCategories", "model.mutedCategories") - selectedCategories(watched, tracked, muted) { - return [].concat(watched, tracked, muted); - }, - - // By default we haven't saved anything - saved: false, - - newNameInput: null, - - @computed("model.user_fields.@each.value") - userFields() { - let siteUserFields = this.site.get('user_fields'); - if (!Ember.isEmpty(siteUserFields)) { - const userFields = this.get('model.user_fields'); - - // Staff can edit fields that are not `editable` - if (!this.get('currentUser.staff')) { - siteUserFields = siteUserFields.filterBy('editable', true); - } - return siteUserFields.sortBy('position').map(function(field) { - const value = userFields ? userFields[field.get('id').toString()] : null; - return Ember.Object.create({ value, field }); - }); - } - }, - - cannotDeleteAccount: Em.computed.not('currentUser.can_delete_account'), - deleteDisabled: Em.computed.or('model.isSaving', 'deleting', 'cannotDeleteAccount'), - - canEditName: setting('enable_names'), - - @computed() - nameInstructions() { - return I18n.t(this.siteSettings.full_name_required ? 'user.name.instructions_required' : 'user.name.instructions'); - }, - - @computed("model.has_title_badges") - canSelectTitle(hasTitleBadges) { - return this.siteSettings.enable_badges && hasTitleBadges; - }, - - @computed("model.can_change_bio") - canChangeBio(canChangeBio) - { - return canChangeBio; - }, - - @computed() - canChangePassword() { - return !this.siteSettings.enable_sso && this.siteSettings.enable_local_logins; - }, - - @computed() - availableLocales() { - return this.siteSettings.available_locales.split('|').map(s => ({ name: s, value: s })); - }, - - @computed() - frequencyEstimate() { - var estimate = this.get('model.mailing_list_posts_per_day'); - if (!estimate || estimate < 2) { - return I18n.t('user.mailing_list_mode.few_per_day'); - } else { - return I18n.t('user.mailing_list_mode.many_per_day', { dailyEmailEstimate: estimate }); - } - }, - - @computed() - mailingListModeOptions() { - return [ - {name: I18n.t('user.mailing_list_mode.daily'), value: 0}, - {name: this.get('frequencyEstimate'), value: 1}, - {name: I18n.t('user.mailing_list_mode.individual_no_echo'), value: 2} - ]; - }, - - previousRepliesOptions: [ - {name: I18n.t('user.email_previous_replies.always'), value: 0}, - {name: I18n.t('user.email_previous_replies.unless_emailed'), value: 1}, - {name: I18n.t('user.email_previous_replies.never'), value: 2} - ], - - digestFrequencies: [{ name: I18n.t('user.email_digests.every_30_minutes'), value: 30 }, - { name: I18n.t('user.email_digests.every_hour'), value: 60 }, - { name: I18n.t('user.email_digests.daily'), value: 1440 }, - { name: I18n.t('user.email_digests.every_three_days'), value: 4320 }, - { name: I18n.t('user.email_digests.weekly'), value: 10080 }, - { name: I18n.t('user.email_digests.every_two_weeks'), value: 20160 }], - - likeNotificationFrequencies: [{ name: I18n.t('user.like_notification_frequency.always'), value: 0 }, - { name: I18n.t('user.like_notification_frequency.first_time_and_daily'), value: 1 }, - { name: I18n.t('user.like_notification_frequency.first_time'), value: 2 }, - { name: I18n.t('user.like_notification_frequency.never'), value: 3 }], - - autoTrackDurations: [{ name: I18n.t('user.auto_track_options.never'), value: -1 }, - { name: I18n.t('user.auto_track_options.immediately'), value: 0 }, - { name: I18n.t('user.auto_track_options.after_30_seconds'), value: 30000 }, - { name: I18n.t('user.auto_track_options.after_1_minute'), value: 60000 }, - { name: I18n.t('user.auto_track_options.after_2_minutes'), value: 120000 }, - { name: I18n.t('user.auto_track_options.after_3_minutes'), value: 180000 }, - { name: I18n.t('user.auto_track_options.after_4_minutes'), value: 240000 }, - { name: I18n.t('user.auto_track_options.after_5_minutes'), value: 300000 }, - { name: I18n.t('user.auto_track_options.after_10_minutes'), value: 600000 }], - - notificationLevelsForReplying: [{ name: I18n.t('topic.notifications.watching.title'), value: NotificationLevels.WATCHING }, - { name: I18n.t('topic.notifications.tracking.title'), value: NotificationLevels.TRACKING }, - { name: I18n.t('topic.notifications.regular.title'), value: NotificationLevels.REGULAR }], - - - considerNewTopicOptions: [{ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 }, - { name: I18n.t('user.new_topic_duration.after_1_day'), value: 60 * 24 }, - { name: I18n.t('user.new_topic_duration.after_2_days'), value: 60 * 48 }, - { name: I18n.t('user.new_topic_duration.after_1_week'), value: 7 * 60 * 24 }, - { name: I18n.t('user.new_topic_duration.after_2_weeks'), value: 2 * 7 * 60 * 24 }, - { name: I18n.t('user.new_topic_duration.last_here'), value: -2 }], - - @computed("model.isSaving") - saveButtonText(isSaving) { - return isSaving ? I18n.t('saving') : I18n.t('save'); - }, - - reset() { - this.setProperties({ - passwordProgress: null - }); - }, - - passwordProgress: null, - - actions: { - - save() { - this.set('saved', false); - - const model = this.get('model'); - - const userFields = this.get('userFields'); - - // Update the user fields - if (!Ember.isEmpty(userFields)) { - const modelFields = model.get('user_fields'); - if (!Ember.isEmpty(modelFields)) { - userFields.forEach(function(uf) { - modelFields[uf.get('field.id').toString()] = uf.get('value'); - }); - } - } - - // Cook the bio for preview - model.set('name', this.get('newNameInput')); - return model.save().then(() => { - if (Discourse.User.currentProp('id') === model.get('id')) { - Discourse.User.currentProp('name', model.get('name')); - } - model.set('bio_cooked', cook(model.get('bio_raw'))); - selectDefaultTheme(this.get('selectedTheme')); - this.set('saved', true); - }).catch(popupAjaxError); - }, - - changePassword() { - if (!this.get('passwordProgress')) { - this.set('passwordProgress', I18n.t("user.change_password.in_progress")); - return this.get('model').changePassword().then(() => { - // password changed - this.setProperties({ - changePasswordProgress: false, - passwordProgress: I18n.t("user.change_password.success") - }); - }).catch(() => { - // password failed to change - this.setProperties({ - changePasswordProgress: false, - passwordProgress: I18n.t("user.change_password.error") - }); - }); - } - }, - - delete() { - this.set('deleting', true); - const self = this, - message = I18n.t('user.delete_account_confirm'), - model = this.get('model'), - buttons = [ - { label: I18n.t("cancel"), - class: "cancel-inline", - link: true, - callback: () => { this.set('deleting', false); } - }, - { label: ' ' + I18n.t("user.delete_account"), - class: "btn btn-danger", - callback() { - model.delete().then(function() { - bootbox.alert(I18n.t('user.deleted_yourself'), function() { - window.location.pathname = Discourse.getURL('/'); - }); - }, function() { - bootbox.alert(I18n.t('user.delete_yourself_not_allowed')); - self.set('deleting', false); - }); - } - } - ]; - bootbox.dialog(message, buttons, {"classes": "delete-account"}); - } - } - +export default Ember.Controller.extend({ + application: Ember.inject.controller() }); diff --git a/app/assets/javascripts/discourse/controllers/preferences/account.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/account.js.es6 new file mode 100644 index 00000000000..a5cd50edc97 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/account.js.es6 @@ -0,0 +1,71 @@ +import CanCheckEmails from 'discourse/mixins/can-check-emails'; +import { default as computed } from "ember-addons/ember-computed-decorators"; +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; + +export default Ember.Controller.extend(CanCheckEmails, PreferencesTabController, { + + passwordProgress: null, + + cannotDeleteAccount: Em.computed.not('currentUser.can_delete_account'), + deleteDisabled: Em.computed.or('model.isSaving', 'deleting', 'cannotDeleteAccount'), + + reset() { + this.setProperties({ + passwordProgress: null + }); + }, + + @computed() + canChangePassword() { + return !this.siteSettings.enable_sso && this.siteSettings.enable_local_logins; + }, + + actions: { + changePassword() { + if (!this.get('passwordProgress')) { + this.set('passwordProgress', I18n.t("user.change_password.in_progress")); + return this.get('model').changePassword().then(() => { + // password changed + this.setProperties({ + changePasswordProgress: false, + passwordProgress: I18n.t("user.change_password.success") + }); + }).catch(() => { + // password failed to change + this.setProperties({ + changePasswordProgress: false, + passwordProgress: I18n.t("user.change_password.error") + }); + }); + } + }, + + delete() { + this.set('deleting', true); + const self = this, + message = I18n.t('user.delete_account_confirm'), + model = this.get('model'), + buttons = [ + { label: I18n.t("cancel"), + class: "cancel-inline", + link: true, + callback: () => { this.set('deleting', false); } + }, + { label: ' ' + I18n.t("user.delete_account"), + class: "btn btn-danger", + callback() { + model.delete().then(function() { + bootbox.alert(I18n.t('user.deleted_yourself'), function() { + window.location.pathname = Discourse.getURL('/'); + }); + }, function() { + bootbox.alert(I18n.t('user.delete_yourself_not_allowed')); + self.set('deleting', false); + }); + } + } + ]; + bootbox.dialog(message, buttons, {"classes": "delete-account"}); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/categories.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/categories.js.es6 new file mode 100644 index 00000000000..66aa5ccc685 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/categories.js.es6 @@ -0,0 +1,20 @@ +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Ember.Controller.extend(PreferencesTabController, { + saveAttrNames: [ + 'muted_category_ids', + 'watched_category_ids', + 'tracked_category_ids', + 'watched_first_post_category_ids' + ], + + actions: { + save() { + this.set('saved', false); + return this.get('model').save(this.get('saveAttrNames')).then(() => { + this.set('saved', true); + }).catch(popupAjaxError); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/emails.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/emails.js.es6 new file mode 100644 index 00000000000..db25accf5a1 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/emails.js.es6 @@ -0,0 +1,62 @@ +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { default as computed } from "ember-addons/ember-computed-decorators"; +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Ember.Controller.extend(PreferencesTabController, { + + saveAttrNames: [ + 'email_always', + 'mailing_list_mode', + 'mailing_list_mode_frequency', + 'email_digests', + 'email_direct', + 'email_in_reply_to', + 'email_private_messages', + 'email_previous_replies', + 'digest_after_minutes', + 'include_tl0_in_digests' + ], + + @computed() + frequencyEstimate() { + var estimate = this.get('model.mailing_list_posts_per_day'); + if (!estimate || estimate < 2) { + return I18n.t('user.mailing_list_mode.few_per_day'); + } else { + return I18n.t('user.mailing_list_mode.many_per_day', { dailyEmailEstimate: estimate }); + } + }, + + @computed() + mailingListModeOptions() { + return [ + {name: I18n.t('user.mailing_list_mode.daily'), value: 0}, + {name: this.get('frequencyEstimate'), value: 1}, + {name: I18n.t('user.mailing_list_mode.individual_no_echo'), value: 2} + ]; + }, + + previousRepliesOptions: [ + {name: I18n.t('user.email_previous_replies.always'), value: 0}, + {name: I18n.t('user.email_previous_replies.unless_emailed'), value: 1}, + {name: I18n.t('user.email_previous_replies.never'), value: 2} + ], + + digestFrequencies: [ + { name: I18n.t('user.email_digests.every_30_minutes'), value: 30 }, + { name: I18n.t('user.email_digests.every_hour'), value: 60 }, + { name: I18n.t('user.email_digests.daily'), value: 1440 }, + { name: I18n.t('user.email_digests.every_three_days'), value: 4320 }, + { name: I18n.t('user.email_digests.weekly'), value: 10080 }, + { name: I18n.t('user.email_digests.every_two_weeks'), value: 20160 } + ], + + actions: { + save() { + this.set('saved', false); + return this.get('model').save(this.get('saveAttrNames')).then(() => { + this.set('saved', true); + }).catch(popupAjaxError); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 new file mode 100644 index 00000000000..324c3da7d2b --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 @@ -0,0 +1,45 @@ +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { default as computed, observes } from "ember-addons/ember-computed-decorators"; +import { listThemes, previewTheme } from 'discourse/lib/theme-selector'; +import { popupAjaxError } from 'discourse/lib/ajax-error'; +import { selectDefaultTheme } from 'discourse/lib/theme-selector'; + +export default Ember.Controller.extend(PreferencesTabController, { + + saveAttrNames: [ + 'locale', + 'external_links_in_new_tab', + 'dynamic_favicon', + 'enable_quoting', + 'disable_jump_reply', + 'automatically_unpin_topics' + ], + + preferencesController: Ember.inject.controller('preferences'), + + @computed() + availableLocales() { + return this.siteSettings.available_locales.split('|').map(s => ({ name: s, value: s })); + }, + + userSelectableThemes: function(){ + return listThemes(this.site); + }.property(), + + @observes("selectedTheme") + themeKeyChanged() { + let key = this.get("selectedTheme"); + this.get('preferencesController').set('selectedTheme', key); + previewTheme(key); + }, + + actions: { + save() { + this.set('saved', false); + return this.get('model').save(this.get('saveAttrNames')).then(() => { + this.set('saved', true); + selectDefaultTheme(this.get('selectedTheme')); + }).catch(popupAjaxError); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/notifications.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/notifications.js.es6 new file mode 100644 index 00000000000..8129641b5dc --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/notifications.js.es6 @@ -0,0 +1,56 @@ +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { default as computed } from "ember-addons/ember-computed-decorators"; +import { NotificationLevels } from 'discourse/lib/notification-levels'; +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Ember.Controller.extend(PreferencesTabController, { + + saveAttrNames:[ + 'muted_usernames', + 'new_topic_duration_minutes', + 'auto_track_topics_after_msecs', + 'notification_level_when_replying', + 'like_notification_frequency' + ], + + @computed("model.watchedCategories", "model.trackedCategories", "model.mutedCategories") + selectedCategories(watched, tracked, muted) { + return [].concat(watched, tracked, muted); + }, + + likeNotificationFrequencies: [{ name: I18n.t('user.like_notification_frequency.always'), value: 0 }, + { name: I18n.t('user.like_notification_frequency.first_time_and_daily'), value: 1 }, + { name: I18n.t('user.like_notification_frequency.first_time'), value: 2 }, + { name: I18n.t('user.like_notification_frequency.never'), value: 3 }], + + autoTrackDurations: [{ name: I18n.t('user.auto_track_options.never'), value: -1 }, + { name: I18n.t('user.auto_track_options.immediately'), value: 0 }, + { name: I18n.t('user.auto_track_options.after_30_seconds'), value: 30000 }, + { name: I18n.t('user.auto_track_options.after_1_minute'), value: 60000 }, + { name: I18n.t('user.auto_track_options.after_2_minutes'), value: 120000 }, + { name: I18n.t('user.auto_track_options.after_3_minutes'), value: 180000 }, + { name: I18n.t('user.auto_track_options.after_4_minutes'), value: 240000 }, + { name: I18n.t('user.auto_track_options.after_5_minutes'), value: 300000 }, + { name: I18n.t('user.auto_track_options.after_10_minutes'), value: 600000 }], + + notificationLevelsForReplying: [{ name: I18n.t('topic.notifications.watching.title'), value: NotificationLevels.WATCHING }, + { name: I18n.t('topic.notifications.tracking.title'), value: NotificationLevels.TRACKING }, + { name: I18n.t('topic.notifications.regular.title'), value: NotificationLevels.REGULAR }], + + considerNewTopicOptions: [{ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 }, + { name: I18n.t('user.new_topic_duration.after_1_day'), value: 60 * 24 }, + { name: I18n.t('user.new_topic_duration.after_2_days'), value: 60 * 48 }, + { name: I18n.t('user.new_topic_duration.after_1_week'), value: 7 * 60 * 24 }, + { name: I18n.t('user.new_topic_duration.after_2_weeks'), value: 2 * 7 * 60 * 24 }, + { name: I18n.t('user.new_topic_duration.last_here'), value: -2 }], + + actions: { + save() { + this.set('saved', false); + return this.get('model').save(this.get('saveAttrNames')).then(() => { + this.set('saved', true); + }).catch(popupAjaxError); + } + } + +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 new file mode 100644 index 00000000000..2cdfd8e6940 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/profile.js.es6 @@ -0,0 +1,84 @@ +import { default as computed } from "ember-addons/ember-computed-decorators"; +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { setting } from 'discourse/lib/computed'; +import { popupAjaxError } from 'discourse/lib/ajax-error'; +import { cook } from 'discourse/lib/text'; + +export default Ember.Controller.extend(PreferencesTabController, { + + saveAttrNames: [ + 'name', + 'bio_raw', + 'website', + 'location', + 'custom_fields', + 'user_fields', + 'profile_background', + 'card_background', + 'date_of_birth' + ], + + canEditName: setting('enable_names'), + + newNameInput: null, + + @computed() + nameInstructions() { + return I18n.t(this.siteSettings.full_name_required ? 'user.name.instructions_required' : 'user.name.instructions'); + }, + + @computed("model.has_title_badges") + canSelectTitle(hasTitleBadges) { + return this.siteSettings.enable_badges && hasTitleBadges; + }, + + @computed("model.user_fields.@each.value") + userFields() { + let siteUserFields = this.site.get('user_fields'); + if (!Ember.isEmpty(siteUserFields)) { + const userFields = this.get('model.user_fields'); + + // Staff can edit fields that are not `editable` + if (!this.get('currentUser.staff')) { + siteUserFields = siteUserFields.filterBy('editable', true); + } + return siteUserFields.sortBy('position').map(function(field) { + const value = userFields ? userFields[field.get('id').toString()] : null; + return Ember.Object.create({ value, field }); + }); + } + }, + + @computed("model.can_change_bio") + canChangeBio(canChangeBio) + { + return canChangeBio; + }, + + actions: { + + save() { + this.set('saved', false); + + const model = this.get('model'), + userFields = this.get('userFields'); + + model.set('name', this.get('newNameInput')); + + // Update the user fields + if (!Ember.isEmpty(userFields)) { + const modelFields = model.get('user_fields'); + if (!Ember.isEmpty(modelFields)) { + userFields.forEach(function(uf) { + modelFields[uf.get('field.id').toString()] = uf.get('value'); + }); + } + } + + return model.save(this.get('saveAttrNames')).then(() => { + model.set('bio_cooked', cook(model.get('bio_raw'))); + this.set('saved', true); + }).catch(popupAjaxError); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/preferences/tags.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/tags.js.es6 new file mode 100644 index 00000000000..6264d42b2de --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/preferences/tags.js.es6 @@ -0,0 +1,21 @@ +import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Ember.Controller.extend(PreferencesTabController, { + + saveAttrNames: [ + 'muted_tags', + 'tracked_tags', + 'watched_tags', + 'watching_first_post_tags' + ], + + actions: { + save() { + this.set('saved', false); + return this.get('model').save(this.get('saveAttrNames')).then(() => { + this.set('saved', true); + }).catch(popupAjaxError); + } + } +}); diff --git a/app/assets/javascripts/discourse/mixins/preferences-tab-controller.js.es6 b/app/assets/javascripts/discourse/mixins/preferences-tab-controller.js.es6 new file mode 100644 index 00000000000..a866ba3de63 --- /dev/null +++ b/app/assets/javascripts/discourse/mixins/preferences-tab-controller.js.es6 @@ -0,0 +1,10 @@ +import { default as computed } from "ember-addons/ember-computed-decorators"; + +export default Ember.Mixin.create({ + saved: false, + + @computed("model.isSaving") + saveButtonText(isSaving) { + return isSaving ? I18n.t('saving') : I18n.t('save'); + } +}); diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6 index 6b45997078f..17fb983eaa7 100644 --- a/app/assets/javascripts/discourse/models/user.js.es6 +++ b/app/assets/javascripts/discourse/models/user.js.es6 @@ -201,8 +201,9 @@ const User = RestModel.extend({ return Discourse.User.create(this.getProperties(Object.keys(this))); }, - save() { - const data = this.getProperties( + save(fields) { + + let userFields = [ 'bio_raw', 'website', 'location', @@ -217,43 +218,55 @@ const User = RestModel.extend({ 'tracked_tags', 'watched_tags', 'watching_first_post_tags', - 'date_of_birth'); + 'date_of_birth' + ]; - ['email_always', - 'mailing_list_mode', - 'mailing_list_mode_frequency', - 'external_links_in_new_tab', - 'email_digests', - 'email_direct', - 'email_in_reply_to', - 'email_private_messages', - 'email_previous_replies', - 'dynamic_favicon', - 'enable_quoting', - 'disable_jump_reply', - 'automatically_unpin_topics', - 'digest_after_minutes', - 'new_topic_duration_minutes', - 'auto_track_topics_after_msecs', - 'notification_level_when_replying', - 'like_notification_frequency', - 'include_tl0_in_digests' - ].forEach(s => { + const data = this.getProperties(fields ? _.intersection(userFields, fields) : userFields); + + let userOptionFields = [ + 'email_always', + 'mailing_list_mode', + 'mailing_list_mode_frequency', + 'external_links_in_new_tab', + 'email_digests', + 'email_direct', + 'email_in_reply_to', + 'email_private_messages', + 'email_previous_replies', + 'dynamic_favicon', + 'enable_quoting', + 'disable_jump_reply', + 'automatically_unpin_topics', + 'digest_after_minutes', + 'new_topic_duration_minutes', + 'auto_track_topics_after_msecs', + 'notification_level_when_replying', + 'like_notification_frequency', + 'include_tl0_in_digests' + ]; + + if (fields) { + userOptionFields = _.intersection(userOptionFields, fields); + } + + userOptionFields.forEach(s => { data[s] = this.get(`user_option.${s}`); }); var updatedState = {}; ['muted','watched','tracked','watched_first_post'].forEach(s => { - let prop = s === "watched_first_post" ? "watchedFirstPostCategories" : s + "Categories"; - let cats = this.get(prop); - if (cats) { - let cat_ids = cats.map(c => c.get('id')); - updatedState[s + '_category_ids'] = cat_ids; + if (fields === undefined || fields.includes(s + '_category_ids')) { + let prop = s === "watched_first_post" ? "watchedFirstPostCategories" : s + "Categories"; + let cats = this.get(prop); + if (cats) { + let cat_ids = cats.map(c => c.get('id')); + updatedState[s + '_category_ids'] = cat_ids; - // HACK: denote lack of categories - if (cats.length === 0) { cat_ids = [-1]; } - data[s + '_category_ids'] = cat_ids; + // HACK: denote lack of categories + if (cats.length === 0) { cat_ids = [-1]; } + data[s + '_category_ids'] = cat_ids; + } } }); diff --git a/app/assets/javascripts/discourse/routes/app-route-map.js.es6 b/app/assets/javascripts/discourse/routes/app-route-map.js.es6 index 11852502028..7b6e59a8953 100644 --- a/app/assets/javascripts/discourse/routes/app-route-map.js.es6 +++ b/app/assets/javascripts/discourse/routes/app-route-map.js.es6 @@ -97,6 +97,15 @@ export default function() { }); this.route('preferences', { resetNamespace: true }, function() { + this.route('account'); + this.route('profile'); + this.route('emails'); + this.route('notifications'); + this.route('categories'); + this.route('tags'); + this.route('interface'); + this.route('apps'); + this.route('username'); this.route('email'); this.route('about', { path: '/about-me' }); diff --git a/app/assets/javascripts/discourse/routes/preferences-account.js.es6 b/app/assets/javascripts/discourse/routes/preferences-account.js.es6 new file mode 100644 index 00000000000..32be645d4f3 --- /dev/null +++ b/app/assets/javascripts/discourse/routes/preferences-account.js.es6 @@ -0,0 +1,8 @@ +import RestrictedUserRoute from "discourse/routes/restricted-user"; + +export default RestrictedUserRoute.extend({ + setupController(controller, user) { + controller.reset(); + controller.setProperties({ model: user }); + } +}); diff --git a/app/assets/javascripts/discourse/routes/preferences-index.js.es6 b/app/assets/javascripts/discourse/routes/preferences-index.js.es6 index bb568ff6729..3006f4b8533 100644 --- a/app/assets/javascripts/discourse/routes/preferences-index.js.es6 +++ b/app/assets/javascripts/discourse/routes/preferences-index.js.es6 @@ -1,7 +1,7 @@ import RestrictedUserRoute from "discourse/routes/restricted-user"; export default RestrictedUserRoute.extend({ - renderTemplate: function() { - this.render('preferences', { into: 'user', controller: 'preferences' }); + redirect() { + this.transitionTo('preferences.account'); } }); diff --git a/app/assets/javascripts/discourse/routes/preferences-interface.js.es6 b/app/assets/javascripts/discourse/routes/preferences-interface.js.es6 new file mode 100644 index 00000000000..16f0ba0ca23 --- /dev/null +++ b/app/assets/javascripts/discourse/routes/preferences-interface.js.es6 @@ -0,0 +1,11 @@ +import RestrictedUserRoute from "discourse/routes/restricted-user"; +import { currentThemeKey } from 'discourse/lib/theme-selector'; + +export default RestrictedUserRoute.extend({ + setupController(controller, user) { + controller.setProperties({ + model: user, + selectedTheme: $.cookie('theme_key') || currentThemeKey() + }); + } +}); diff --git a/app/assets/javascripts/discourse/routes/preferences-profile.js.es6 b/app/assets/javascripts/discourse/routes/preferences-profile.js.es6 new file mode 100644 index 00000000000..2f7c61b128d --- /dev/null +++ b/app/assets/javascripts/discourse/routes/preferences-profile.js.es6 @@ -0,0 +1,10 @@ +import RestrictedUserRoute from "discourse/routes/restricted-user"; + +export default RestrictedUserRoute.extend({ + setupController(controller, user) { + controller.setProperties({ + model: user, + newNameInput: user.get('name') + }); + } +}); diff --git a/app/assets/javascripts/discourse/routes/preferences.js.es6 b/app/assets/javascripts/discourse/routes/preferences.js.es6 index 3ff42ca52ea..e1cc50fc5cc 100644 --- a/app/assets/javascripts/discourse/routes/preferences.js.es6 +++ b/app/assets/javascripts/discourse/routes/preferences.js.es6 @@ -1,7 +1,6 @@ import RestrictedUserRoute from "discourse/routes/restricted-user"; import showModal from 'discourse/lib/show-modal'; import { popupAjaxError } from 'discourse/lib/ajax-error'; -import { currentThemeKey } from 'discourse/lib/theme-selector'; export default RestrictedUserRoute.extend({ model() { @@ -9,11 +8,8 @@ export default RestrictedUserRoute.extend({ }, setupController(controller, user) { - controller.reset(); controller.setProperties({ - model: user, - newNameInput: user.get('name'), - selectedTheme: $.cookie('theme_key') || currentThemeKey() + model: user }); }, diff --git a/app/assets/javascripts/discourse/templates/components/user-fields/text.hbs b/app/assets/javascripts/discourse/templates/components/user-fields/text.hbs index f008167a800..78621b55de8 100644 --- a/app/assets/javascripts/discourse/templates/components/user-fields/text.hbs +++ b/app/assets/javascripts/discourse/templates/components/user-fields/text.hbs @@ -1,6 +1,6 @@ - +
{{{field.description}}}
++
{{i18n "user.api_approved"}} {{bound-date key.created_at}}
+