diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 index 002eaba949f..18dccd86858 100644 --- a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 @@ -1,8 +1,11 @@ import PreferencesTabController from "discourse/mixins/preferences-tab-controller"; +import { setDefaultHomepage } from "discourse/lib/utilities"; import { default as computed, observes } from "ember-addons/ember-computed-decorators"; import { currentThemeKey, listThemes, previewTheme, setLocalTheme } from 'discourse/lib/theme-selector'; import { popupAjaxError } from 'discourse/lib/ajax-error'; +const USER_HOMES = { 1: "latest", 2: "categories", 3: "unread", 4: "new", 5: "top" }; + export default Ember.Controller.extend(PreferencesTabController, { @computed("makeThemeDefault") @@ -14,6 +17,8 @@ export default Ember.Controller.extend(PreferencesTabController, { 'enable_quoting', 'disable_jump_reply', 'automatically_unpin_topics', + 'allow_private_messages', + 'homepage_id', ]; if (makeDefault) { @@ -51,6 +56,19 @@ export default Ember.Controller.extend(PreferencesTabController, { previewTheme(key); }, + homeChanged() { + const siteHome = Discourse.SiteSettings.top_menu.split("|")[0].split(",")[0]; + const userHome = USER_HOMES[this.get('model.user_option.homepage_id')]; + setDefaultHomepage(userHome || siteHome); + }, + + @computed() + userSelectableHome() { + return _.map(USER_HOMES, (name, num) => { + return {name: I18n.t('filters.' + name + '.title'), value: num}; + }); + }, + actions: { save() { this.set('saved', false); @@ -66,6 +84,8 @@ export default Ember.Controller.extend(PreferencesTabController, { setLocalTheme(this.get('themeKey'), this.get('model.user_option.theme_key_seq')); } + this.homeChanged(); + }).catch(popupAjaxError); } } diff --git a/app/assets/javascripts/discourse/lib/utilities.js.es6 b/app/assets/javascripts/discourse/lib/utilities.js.es6 index fe3616abb54..cba27615715 100644 --- a/app/assets/javascripts/discourse/lib/utilities.js.es6 +++ b/app/assets/javascripts/discourse/lib/utilities.js.es6 @@ -1,5 +1,7 @@ import { escape } from 'pretty-text/sanitizer'; +const homepageSelector = 'meta[name=discourse_current_homepage]'; + export function translateSize(size) { switch (size) { case 'tiny': return 20; @@ -349,8 +351,22 @@ export function displayErrorForUpload(data) { } export function defaultHomepage() { - // the homepage is the first item of the 'top_menu' site setting - return Discourse.SiteSettings.top_menu.split("|")[0].split(",")[0]; + let homepage = null; + let elem = _.first($(homepageSelector)); + if (elem) { + homepage = elem.content; + } + if (!homepage) { + homepage = Discourse.SiteSettings.top_menu.split("|")[0].split(",")[0]; + } + return homepage; +} + +export function setDefaultHomepage(homepage) { + let elem = _.first($(homepageSelector)); + if (elem) { + elem.content = homepage; + } } export function determinePostReplaceSelection({ selection, needle, replacement }) { diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6 index 17e7f9bfc11..82171ada01b 100644 --- a/app/assets/javascripts/discourse/models/user.js.es6 +++ b/app/assets/javascripts/discourse/models/user.js.es6 @@ -249,6 +249,7 @@ const User = RestModel.extend({ 'include_tl0_in_digests', 'theme_key', 'allow_private_messages', + 'homepage_id', ]; if (fields) { diff --git a/app/assets/javascripts/discourse/templates/preferences/interface.hbs b/app/assets/javascripts/discourse/templates/preferences/interface.hbs index 8e8d5852e90..f6db98b840c 100644 --- a/app/assets/javascripts/discourse/templates/preferences/interface.hbs +++ b/app/assets/javascripts/discourse/templates/preferences/interface.hbs @@ -23,6 +23,13 @@ {{/if}} +
+ +
+ {{combo-box content=userSelectableHome valueAttribute="value" value=model.user_option.homepage_id}} +
+
+
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 71d3e9e683c..05fbfdb733d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -308,7 +308,7 @@ class ApplicationController < ActionController::Base end def current_homepage - current_user ? SiteSetting.homepage : SiteSetting.anonymous_homepage + current_user&.user_option&.homepage || SiteSetting.anonymous_homepage end def serialize_data(obj, serializer, opts = nil) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de63356aa17..40bb8244436 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -347,6 +347,10 @@ module ApplicationHelper end end + def current_homepage + current_user&.user_option&.homepage || SiteSetting.anonymous_homepage + end + def build_plugin_html(name) return "" unless allow_plugins? DiscoursePluginRegistry.build_html(name, controller) || "" diff --git a/app/models/user_option.rb b/app/models/user_option.rb index 17eed6baa7f..a780a4015f2 100644 --- a/app/models/user_option.rb +++ b/app/models/user_option.rb @@ -128,6 +128,17 @@ class UserOption < ActiveRecord::Base times.max end + def homepage + case homepage_id + when 1 then "latest" + when 2 then "categories" + when 3 then "unread" + when 4 then "new" + when 5 then "top" + else SiteSetting.homepage + end + end + private def update_tracked_topics @@ -165,6 +176,7 @@ end # theme_key :string # theme_key_seq :integer default(0), not null # allow_private_messages :boolean default(TRUE), not null +# homepage_id :integer default(null) # # Indexes # diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb index 844f6c06b5c..6bccbe81766 100644 --- a/app/serializers/user_option_serializer.rb +++ b/app/serializers/user_option_serializer.rb @@ -22,6 +22,7 @@ class UserOptionSerializer < ApplicationSerializer :theme_key, :theme_key_seq, :allow_private_messages, + :homepage_id, def auto_track_topics_after_msecs object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb index 591a50a966f..305f96fddc1 100644 --- a/app/services/user_updater.rb +++ b/app/services/user_updater.rb @@ -36,6 +36,7 @@ class UserUpdater :include_tl0_in_digests, :theme_key, :allow_private_messages, + :homepage_id, ] def initialize(actor, user) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a6e1e707582..83c7bccf1cd 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,6 +5,7 @@ <%= content_for?(:title) ? yield(:title) : SiteSetting.title %> + <%= render partial: "layouts/head" %> <%= discourse_csrf_tags %> diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 2b28082280a..a3ec45596d3 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -658,6 +658,7 @@ en: undo_revoke_access: "Undo Revoke Access" api_approved: "Approved:" theme: "Theme" + home: "Default Home Page" staff_counters: flags_given: "helpful flags" diff --git a/db/migrate/20171026014317_add_user_option_home.rb b/db/migrate/20171026014317_add_user_option_home.rb new file mode 100644 index 00000000000..8724ec40e7f --- /dev/null +++ b/db/migrate/20171026014317_add_user_option_home.rb @@ -0,0 +1,5 @@ +class AddUserOptionHome < ActiveRecord::Migration[5.1] + def change + add_column :user_options, :homepage_id, :integer, null: true, default: nil + end +end diff --git a/lib/homepage_constraint.rb b/lib/homepage_constraint.rb index a5cfb347582..586581425c3 100644 --- a/lib/homepage_constraint.rb +++ b/lib/homepage_constraint.rb @@ -7,7 +7,7 @@ class HomePageConstraint return @filter == 'finish_installation' if SiteSetting.has_login_hint? provider = Discourse.current_user_provider.new(request.env) - homepage = provider.current_user ? SiteSetting.homepage : SiteSetting.anonymous_homepage + homepage = provider&.current_user&.user_option&.homepage || SiteSetting.anonymous_homepage homepage == @filter rescue Discourse::InvalidAccess false diff --git a/test/javascripts/lib/utilities-test.js.es6 b/test/javascripts/lib/utilities-test.js.es6 index e903b977923..8ef76a79fac 100644 --- a/test/javascripts/lib/utilities-test.js.es6 +++ b/test/javascripts/lib/utilities-test.js.es6 @@ -10,6 +10,7 @@ import { getRawSize, avatarImg, defaultHomepage, + setDefaultHomepage, validateUploadedFiles, getUploadMarkdown, caretRowCol, @@ -204,6 +205,22 @@ QUnit.test("allowsAttachments", assert => { QUnit.test("defaultHomepage", assert => { Discourse.SiteSettings.top_menu = "latest|top|hot"; assert.equal(defaultHomepage(), "latest", "default homepage is the first item in the top_menu site setting"); + var meta = document.createElement("meta"); + meta.name = "discourse_current_homepage"; + meta.content = "hot"; + document.body.appendChild(meta); + assert.equal(defaultHomepage(), "hot", "default homepage is pulled from "); + document.body.removeChild(meta); +}); + +QUnit.test("setDefaultHomepage", assert => { + var meta = document.createElement("meta"); + meta.name = "discourse_current_homepage"; + meta.content = "hot"; + document.body.appendChild(meta); + setDefaultHomepage("top"); + assert.equal(meta.content, "top", "default homepage set by setDefaultHomepage"); + document.body.removeChild(meta); }); QUnit.test("caretRowCol", assert => {