FEATURE: Allow the user to select a custom home page (#5268)
* Add user_home configuration option * Use the new user_home preference to actually show the right home page * Fix trailing whitespace * Update user_option_serializer.rb * Fix JavaScript default homepage tests * Use an object instead of a giant switch * Remove trailing whitespace * Make the default `user_home` set to `null` instead of `0` * Rename user_home to homepage_id
This commit is contained in:
parent
162932114e
commit
38b8d68c68
|
@ -1,8 +1,11 @@
|
||||||
import PreferencesTabController from "discourse/mixins/preferences-tab-controller";
|
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 { default as computed, observes } from "ember-addons/ember-computed-decorators";
|
||||||
import { currentThemeKey, listThemes, previewTheme, setLocalTheme } from 'discourse/lib/theme-selector';
|
import { currentThemeKey, listThemes, previewTheme, setLocalTheme } from 'discourse/lib/theme-selector';
|
||||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
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, {
|
export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
|
|
||||||
@computed("makeThemeDefault")
|
@computed("makeThemeDefault")
|
||||||
|
@ -14,6 +17,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
'enable_quoting',
|
'enable_quoting',
|
||||||
'disable_jump_reply',
|
'disable_jump_reply',
|
||||||
'automatically_unpin_topics',
|
'automatically_unpin_topics',
|
||||||
|
'allow_private_messages',
|
||||||
|
'homepage_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (makeDefault) {
|
if (makeDefault) {
|
||||||
|
@ -51,6 +56,19 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
||||||
previewTheme(key);
|
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: {
|
actions: {
|
||||||
save() {
|
save() {
|
||||||
this.set('saved', false);
|
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'));
|
setLocalTheme(this.get('themeKey'), this.get('model.user_option.theme_key_seq'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.homeChanged();
|
||||||
|
|
||||||
}).catch(popupAjaxError);
|
}).catch(popupAjaxError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { escape } from 'pretty-text/sanitizer';
|
import { escape } from 'pretty-text/sanitizer';
|
||||||
|
|
||||||
|
const homepageSelector = 'meta[name=discourse_current_homepage]';
|
||||||
|
|
||||||
export function translateSize(size) {
|
export function translateSize(size) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 'tiny': return 20;
|
case 'tiny': return 20;
|
||||||
|
@ -349,8 +351,22 @@ export function displayErrorForUpload(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function defaultHomepage() {
|
export function defaultHomepage() {
|
||||||
// the homepage is the first item of the 'top_menu' site setting
|
let homepage = null;
|
||||||
return Discourse.SiteSettings.top_menu.split("|")[0].split(",")[0];
|
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 }) {
|
export function determinePostReplaceSelection({ selection, needle, replacement }) {
|
||||||
|
|
|
@ -249,6 +249,7 @@ const User = RestModel.extend({
|
||||||
'include_tl0_in_digests',
|
'include_tl0_in_digests',
|
||||||
'theme_key',
|
'theme_key',
|
||||||
'allow_private_messages',
|
'allow_private_messages',
|
||||||
|
'homepage_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (fields) {
|
if (fields) {
|
||||||
|
|
|
@ -23,6 +23,13 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="control-group home">
|
||||||
|
<label class="control-label">{{i18n 'user.home'}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{combo-box content=userSelectableHome valueAttribute="value" value=model.user_option.homepage_id}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="control-group other">
|
<div class="control-group other">
|
||||||
<label class="control-label">{{i18n 'user.other_settings'}}</label>
|
<label class="control-label">{{i18n 'user.other_settings'}}</label>
|
||||||
|
|
||||||
|
|
|
@ -308,7 +308,7 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_homepage
|
def current_homepage
|
||||||
current_user ? SiteSetting.homepage : SiteSetting.anonymous_homepage
|
current_user&.user_option&.homepage || SiteSetting.anonymous_homepage
|
||||||
end
|
end
|
||||||
|
|
||||||
def serialize_data(obj, serializer, opts = nil)
|
def serialize_data(obj, serializer, opts = nil)
|
||||||
|
|
|
@ -347,6 +347,10 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_homepage
|
||||||
|
current_user&.user_option&.homepage || SiteSetting.anonymous_homepage
|
||||||
|
end
|
||||||
|
|
||||||
def build_plugin_html(name)
|
def build_plugin_html(name)
|
||||||
return "" unless allow_plugins?
|
return "" unless allow_plugins?
|
||||||
DiscoursePluginRegistry.build_html(name, controller) || ""
|
DiscoursePluginRegistry.build_html(name, controller) || ""
|
||||||
|
|
|
@ -128,6 +128,17 @@ class UserOption < ActiveRecord::Base
|
||||||
times.max
|
times.max
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def update_tracked_topics
|
def update_tracked_topics
|
||||||
|
@ -165,6 +176,7 @@ end
|
||||||
# theme_key :string
|
# theme_key :string
|
||||||
# theme_key_seq :integer default(0), not null
|
# theme_key_seq :integer default(0), not null
|
||||||
# allow_private_messages :boolean default(TRUE), not null
|
# allow_private_messages :boolean default(TRUE), not null
|
||||||
|
# homepage_id :integer default(null)
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -22,6 +22,7 @@ class UserOptionSerializer < ApplicationSerializer
|
||||||
:theme_key,
|
:theme_key,
|
||||||
:theme_key_seq,
|
:theme_key_seq,
|
||||||
:allow_private_messages,
|
:allow_private_messages,
|
||||||
|
:homepage_id,
|
||||||
|
|
||||||
def auto_track_topics_after_msecs
|
def auto_track_topics_after_msecs
|
||||||
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
||||||
|
|
|
@ -36,6 +36,7 @@ class UserUpdater
|
||||||
:include_tl0_in_digests,
|
:include_tl0_in_digests,
|
||||||
:theme_key,
|
:theme_key,
|
||||||
:allow_private_messages,
|
:allow_private_messages,
|
||||||
|
:homepage_id,
|
||||||
]
|
]
|
||||||
|
|
||||||
def initialize(actor, user)
|
def initialize(actor, user)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<title><%= content_for?(:title) ? yield(:title) : SiteSetting.title %></title>
|
<title><%= content_for?(:title) ? yield(:title) : SiteSetting.title %></title>
|
||||||
<meta name="description" content="<%= @description_meta || SiteSetting.site_description %>">
|
<meta name="description" content="<%= @description_meta || SiteSetting.site_description %>">
|
||||||
<meta name="discourse_theme_key" content="<%= theme_key %>">
|
<meta name="discourse_theme_key" content="<%= theme_key %>">
|
||||||
|
<meta name="discourse_current_homepage" content="<%= current_homepage %>">
|
||||||
<%= render partial: "layouts/head" %>
|
<%= render partial: "layouts/head" %>
|
||||||
<%= discourse_csrf_tags %>
|
<%= discourse_csrf_tags %>
|
||||||
|
|
||||||
|
|
|
@ -658,6 +658,7 @@ en:
|
||||||
undo_revoke_access: "Undo Revoke Access"
|
undo_revoke_access: "Undo Revoke Access"
|
||||||
api_approved: "Approved:"
|
api_approved: "Approved:"
|
||||||
theme: "Theme"
|
theme: "Theme"
|
||||||
|
home: "Default Home Page"
|
||||||
|
|
||||||
staff_counters:
|
staff_counters:
|
||||||
flags_given: "helpful flags"
|
flags_given: "helpful flags"
|
||||||
|
|
|
@ -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
|
|
@ -7,7 +7,7 @@ class HomePageConstraint
|
||||||
return @filter == 'finish_installation' if SiteSetting.has_login_hint?
|
return @filter == 'finish_installation' if SiteSetting.has_login_hint?
|
||||||
|
|
||||||
provider = Discourse.current_user_provider.new(request.env)
|
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
|
homepage == @filter
|
||||||
rescue Discourse::InvalidAccess
|
rescue Discourse::InvalidAccess
|
||||||
false
|
false
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
getRawSize,
|
getRawSize,
|
||||||
avatarImg,
|
avatarImg,
|
||||||
defaultHomepage,
|
defaultHomepage,
|
||||||
|
setDefaultHomepage,
|
||||||
validateUploadedFiles,
|
validateUploadedFiles,
|
||||||
getUploadMarkdown,
|
getUploadMarkdown,
|
||||||
caretRowCol,
|
caretRowCol,
|
||||||
|
@ -204,6 +205,22 @@ QUnit.test("allowsAttachments", assert => {
|
||||||
QUnit.test("defaultHomepage", assert => {
|
QUnit.test("defaultHomepage", assert => {
|
||||||
Discourse.SiteSettings.top_menu = "latest|top|hot";
|
Discourse.SiteSettings.top_menu = "latest|top|hot";
|
||||||
assert.equal(defaultHomepage(), "latest", "default homepage is the first item in the top_menu site setting");
|
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 <meta name=discourse_current_homepage>");
|
||||||
|
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 => {
|
QUnit.test("caretRowCol", assert => {
|
||||||
|
|
Loading…
Reference in New Issue