From 03087679f05d9e216ec017088d3e7af7f3b7b34a Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 11 Jun 2014 15:50:37 +1000 Subject: [PATCH] FEATURE: Support custom preferences for users, injected by plugins --- .../javascripts/discourse/models/user.js | 3 +- .../discourse/routes/topic_route.js | 2 +- .../templates/user/preferences.js.handlebars | 1 + .../discourse/views/user/preferences_view.js | 29 +++++++++++++++++++ app/serializers/user_serializer.rb | 3 +- app/services/user_updater.rb | 4 +++ spec/controllers/users_controller_spec.rb | 8 +++-- 7 files changed, 45 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index 0ac262db28d..4d1b1fd3137 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -204,7 +204,8 @@ Discourse.User = Discourse.Model.extend({ 'external_links_in_new_tab', 'mailing_list_mode', 'enable_quoting', - 'disable_jump_reply'); + 'disable_jump_reply', + 'custom_fields'); _.each(['muted','watched','tracked'], function(s){ var cats = user.get(s + 'Categories').map(function(c){ return c.get('id')}); diff --git a/app/assets/javascripts/discourse/routes/topic_route.js b/app/assets/javascripts/discourse/routes/topic_route.js index cc45a2950cb..641269296bc 100644 --- a/app/assets/javascripts/discourse/routes/topic_route.js +++ b/app/assets/javascripts/discourse/routes/topic_route.js @@ -79,7 +79,7 @@ Discourse.TopicRoute = Discourse.Route.extend({ // Use replaceState to update the URL once it changes postChangedRoute: Discourse.debounce(function(currentPost) { // do nothing if we are transitioning to another route - if (this.get("isTransitioning")) { return; } + if (this.get("isTransitioning") || Discourse.TopicRoute.disableReplaceState) { return; } var topic = this.modelFor('topic'); if (topic && currentPost) { diff --git a/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars b/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars index 494613d2dc1..06673c850a9 100644 --- a/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars +++ b/app/assets/javascripts/discourse/templates/user/preferences.js.handlebars @@ -175,6 +175,7 @@ {{preference-checkbox labelKey="user.enable_quoting" checked=enable_quoting}} {{preference-checkbox labelKey="user.dynamic_favicon" checked=dynamic_favicon}} {{preference-checkbox labelKey="user.disable_jump_reply" checked=disable_jump_reply}} + {{view Discourse.CustomPreferences}}
diff --git a/app/assets/javascripts/discourse/views/user/preferences_view.js b/app/assets/javascripts/discourse/views/user/preferences_view.js index d0728d46f14..d672749266a 100644 --- a/app/assets/javascripts/discourse/views/user/preferences_view.js +++ b/app/assets/javascripts/discourse/views/user/preferences_view.js @@ -13,6 +13,9 @@ Discourse.PreferencesView = Discourse.View.extend({ uploading: false, uploadProgress: 0, + customPreferences: function(){ + }.property(), + didInsertElement: function() { var self = this; var $upload = $("#profile-background-input"); @@ -53,3 +56,29 @@ Discourse.PreferencesView = Discourse.View.extend({ $("#profile-background-input").fileupload("destroy"); } }); + +Discourse.PreferencesView.reopenClass({ + registerCustomSection: function(viewClass){ + var customSections = this.customSections; + if(!customSections){ + customSections = Em.A(); + this.customSections = customSections; + } + + customSections.addObject(viewClass); + } +}); + +Discourse.CustomPreferences = Discourse.ContainerView.extend({ + init: function(){ + this._super(); + var self = this; + + var sections = Discourse.PreferencesView.customSections; + if(sections){ + sections.forEach(function(view){ + self.pushObject(view.create({user: self.get('controller.model')})); + }); + } + } +}); diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb index c2d39e972b2..3ba2529234d 100644 --- a/app/serializers/user_serializer.rb +++ b/app/serializers/user_serializer.rb @@ -71,7 +71,8 @@ class UserSerializer < BasicUserSerializer :private_messages_stats, :disable_jump_reply, :gravatar_avatar_upload_id, - :custom_avatar_upload_id + :custom_avatar_upload_id, + :custom_fields def gravatar_avatar_upload_id object.user_avatar.try(:gravatar_upload_id) diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb index e6c90a390b8..47da2a52c4a 100644 --- a/app/services/user_updater.rb +++ b/app/services/user_updater.rb @@ -64,6 +64,10 @@ class UserUpdater user_profile.send("#{attribute.to_s}=", attributes[attribute]) end + if fields = attributes[:custom_fields] + user.custom_fields = fields + end + User.transaction do user_profile.save user.save diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 01c02468ffa..d1ea2af32c0 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -946,10 +946,14 @@ describe UsersController do user = Fabricate(:user, name: 'Billy Bob') log_in_user(user) - put :update, username: user.username, name: 'Jim Tom' + put :update, username: user.username, name: 'Jim Tom', custom_fields: {test: :it} expect(response).to be_success - expect(user.reload.name).to eq 'Jim Tom' + + user.reload + + expect(user.name).to eq 'Jim Tom' + expect(user.custom_fields['test']).to eq 'it' end it 'returns user JSON' do