FIX: Rename branding to logo and fonts (#32264)

Change branding page into logo and fonts.

In addition, icon for email setting and email appearance were changed.
This commit is contained in:
Krzysztof Kotlarek
2025-04-14 10:49:47 +08:00
committed by GitHub
parent 8b5da219d8
commit ee035582e2
24 changed files with 490 additions and 472 deletions

View File

@ -207,12 +207,12 @@ export default class AdminConfigAreasColorPalette extends Component {
/>
</div>
<form.Alert class="fonts-and-logos-hint">
<div class="admin-config-color-palettes__fonts-and-logos-hint">
<div class="admin-config-color-palettes__logo-and-fonts-hint">
<span>{{i18n
"admin.config_areas.color_palettes.fonts_and_logos_hint"
"admin.config_areas.color_palettes.logo_and_fonts_hint"
}}</span>
<LinkTo @route="adminConfig.branding">{{i18n
"admin.config_areas.color_palettes.go_to_branding"
<LinkTo @route="adminConfig.logo-and-fonts">{{i18n
"admin.config_areas.color_palettes.go_to_logo_and_fonts"
}}</LinkTo>
</div>
</form.Alert>

View File

@ -9,7 +9,7 @@ import { i18n } from "discourse-i18n";
import { MAIN_FONTS, MORE_FONTS } from "admin/lib/constants";
import eq from "truth-helpers/helpers/eq";
export default class AdminBrandingFontChooser extends Component {
export default class AdminFontChooser extends Component {
@tracked showMoreFonts = MORE_FONTS.map((font) => font.key).includes(
this.args.selectedFont
);
@ -53,9 +53,9 @@ export default class AdminBrandingFontChooser extends Component {
class="admin-fonts-form__more font"
>
{{#if this.showMoreFonts}}
{{i18n "admin.config.branding.fonts.form.less_fonts"}}
{{i18n "admin.config.logo_and_fonts.fonts.form.less_fonts"}}
{{else}}
{{i18n "admin.config.branding.fonts.form.more_fonts"}}
{{i18n "admin.config.logo_and_fonts.fonts.form.more_fonts"}}
{{/if}}
</DButton>
</@field.Custom>

View File

@ -10,11 +10,11 @@ import concatClass from "discourse/helpers/concat-class";
import { ajax } from "discourse/lib/ajax";
import { bind } from "discourse/lib/decorators";
import { i18n } from "discourse-i18n";
import AdminBrandingFontChooser from "admin/components/admin-branding-font-chooser";
import AdminFontChooser from "admin/components/admin-font-chooser";
import { DEFAULT_TEXT_SIZES } from "admin/lib/constants";
import eq from "truth-helpers/helpers/eq";
export default class AdminBrandingFontsForm extends Component {
export default class AdminFontsForm extends Component {
@service siteSettings;
@service siteSettingChangeTracker;
@service toasts;
@ -67,7 +67,7 @@ export default class AdminBrandingFontsForm extends Component {
@action
async #save(data) {
try {
await ajax("/admin/config/branding/fonts.json", {
await ajax("/admin/config/fonts.json", {
type: "PUT",
data: {
base_font: data.base_font,
@ -79,7 +79,7 @@ export default class AdminBrandingFontsForm extends Component {
this.toasts.success({
duration: 3000,
data: {
message: i18n("admin.config.branding.fonts.form.saved"),
message: i18n("admin.config.logo_and_fonts.fonts.form.saved"),
},
});
this.siteSettingChangeTracker.refreshPage();
@ -110,24 +110,26 @@ export default class AdminBrandingFontsForm extends Component {
>
<form.Field
@name="base_font"
@title={{i18n "admin.config.branding.fonts.form.base_font.title"}}
@title={{i18n "admin.config.logo_and_fonts.fonts.form.base_font.title"}}
@validation="required"
@format="full"
as |field|
>
<AdminBrandingFontChooser
<AdminFontChooser
@field={{field}}
@selectedFont={{transientData.base_font}}
/>
</form.Field>
<form.Field
@name="heading_font"
@title={{i18n "admin.config.branding.fonts.form.heading_font.title"}}
@title={{i18n
"admin.config.logo_and_fonts.fonts.form.heading_font.title"
}}
@validation="required"
@format="full"
as |field|
>
<AdminBrandingFontChooser
<AdminFontChooser
@field={{field}}
@selectedFont={{transientData.heading_font}}
/>
@ -135,10 +137,10 @@ export default class AdminBrandingFontsForm extends Component {
<form.Field
@name="default_text_size"
@title={{i18n
"admin.config.branding.fonts.form.default_text_size.title"
"admin.config.logo_and_fonts.fonts.form.default_text_size.title"
}}
@description={{i18n
"admin.config.branding.fonts.form.default_text_size.description"
"admin.config.logo_and_fonts.fonts.form.default_text_size.description"
}}
@validation="required"
@format="full"

View File

@ -12,7 +12,7 @@ import { i18n } from "discourse-i18n";
import AdminConfigAreaCardSection from "admin/components/admin-config-area-card-section";
import SimpleList from "admin/components/simple-list";
export default class AdminBrandingLogoForm extends Component {
export default class AdminLogoForm extends Component {
@service siteSettings;
@service siteSettingChangeTracker;
@service toasts;
@ -57,7 +57,7 @@ export default class AdminBrandingLogoForm extends Component {
@action
async save(data) {
try {
await ajax("/admin/config/branding/logo.json", {
await ajax("/admin/config/logo.json", {
type: "PUT",
data: {
logo: data.logo,
@ -79,7 +79,7 @@ export default class AdminBrandingLogoForm extends Component {
this.toasts.success({
duration: 3000,
data: {
message: i18n("admin.config.branding.logo.form.saved"),
message: i18n("admin.config.logo_and_fonts.logo.form.saved"),
},
});
this.siteSettingChangeTracker.refreshPage();
@ -131,11 +131,13 @@ export default class AdminBrandingLogoForm extends Component {
>
<form.Field
@name="logo"
@title={{i18n "admin.config.branding.logo.form.logo.title"}}
@title={{i18n "admin.config.logo_and_fonts.logo.form.logo.title"}}
@description={{i18n
"admin.config.branding.logo.form.logo.description"
"admin.config.logo_and_fonts.logo.form.logo.description"
}}
@helpText={{i18n
"admin.config.logo_and_fonts.logo.form.logo.help_text"
}}
@helpText={{i18n "admin.config.branding.logo.form.logo.help_text"}}
@onSet={{fn this.handleUpload "logo"}}
as |field|
>
@ -143,7 +145,9 @@ export default class AdminBrandingLogoForm extends Component {
</form.Field>
<form.Field
@name="logo_dark_required"
@title={{i18n "admin.config.branding.logo.form.logo_dark.required"}}
@title={{i18n
"admin.config.logo_and_fonts.logo.form.logo_dark.required"
}}
@format="full"
as |field|
>
@ -153,9 +157,11 @@ export default class AdminBrandingLogoForm extends Component {
<form.Section>
<form.Field
@name="logo_dark"
@title={{i18n "admin.config.branding.logo.form.logo_dark.title"}}
@title={{i18n
"admin.config.logo_and_fonts.logo.form.logo_dark.title"
}}
@helpText={{i18n
"admin.config.branding.logo.form.logo_dark.help_text"
"admin.config.logo_and_fonts.logo.form.logo_dark.help_text"
}}
@onSet={{fn this.handleUpload "logo_dark"}}
as |field|
@ -166,12 +172,14 @@ export default class AdminBrandingLogoForm extends Component {
{{/if}}
<form.Field
@name="large_icon"
@title={{i18n "admin.config.branding.logo.form.large_icon.title"}}
@title={{i18n
"admin.config.logo_and_fonts.logo.form.large_icon.title"
}}
@description={{i18n
"admin.config.branding.logo.form.large_icon.description"
"admin.config.logo_and_fonts.logo.form.large_icon.description"
}}
@helpText={{i18n
"admin.config.branding.logo.form.large_icon.help_text"
"admin.config.logo_and_fonts.logo.form.large_icon.help_text"
}}
@onSet={{fn this.handleUpload "large_icon"}}
@placeholderUrl={{this.placeholders.large_icon}}
@ -181,9 +189,9 @@ export default class AdminBrandingLogoForm extends Component {
</form.Field>
<form.Field
@name="favicon"
@title={{i18n "admin.config.branding.logo.form.favicon.title"}}
@title={{i18n "admin.config.logo_and_fonts.logo.form.favicon.title"}}
@description={{i18n
"admin.config.branding.logo.form.favicon.description"
"admin.config.logo_and_fonts.logo.form.favicon.description"
}}
@onSet={{fn this.handleUpload "favicon"}}
@placeholderUrl={{this.placeholders.favicon}}
@ -193,12 +201,14 @@ export default class AdminBrandingLogoForm extends Component {
</form.Field>
<form.Field
@name="logo_small"
@title={{i18n "admin.config.branding.logo.form.logo_small.title"}}
@title={{i18n
"admin.config.logo_and_fonts.logo.form.logo_small.title"
}}
@description={{i18n
"admin.config.branding.logo.form.logo_small.description"
"admin.config.logo_and_fonts.logo.form.logo_small.description"
}}
@helpText={{i18n
"admin.config.branding.logo.form.logo_small.help_text"
"admin.config.logo_and_fonts.logo.form.logo_small.help_text"
}}
@onSet={{fn this.handleUpload "logo_small"}}
as |field|
@ -208,7 +218,7 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="logo_small_dark_required"
@title={{i18n
"admin.config.branding.logo.form.logo_small_dark.required"
"admin.config.logo_and_fonts.logo.form.logo_small_dark.required"
}}
@format="full"
as |field|
@ -220,10 +230,10 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="logo_small_dark"
@title={{i18n
"admin.config.branding.logo.form.logo_small_dark.title"
"admin.config.logo_and_fonts.logo.form.logo_small_dark.title"
}}
@helpText={{i18n
"admin.config.branding.logo.form.logo_small_dark.help_text"
"admin.config.logo_and_fonts.logo.form.logo_small_dark.help_text"
}}
@onSet={{fn this.handleUpload "logo_small_dark"}}
as |field|
@ -234,7 +244,7 @@ export default class AdminBrandingLogoForm extends Component {
{{/if}}
<AdminConfigAreaCardSection
@heading={{i18n "admin.config.branding.logo.form.mobile"}}
@heading={{i18n "admin.config.logo_and_fonts.logo.form.mobile"}}
class="admin-logo-form__mobile-section"
@collapsable={{true}}
@collapsed={{true}}
@ -243,13 +253,13 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="mobile_logo"
@title={{i18n
"admin.config.branding.logo.form.mobile_logo.title"
"admin.config.logo_and_fonts.logo.form.mobile_logo.title"
}}
@description={{i18n
"admin.config.branding.logo.form.mobile_logo.description"
"admin.config.logo_and_fonts.logo.form.mobile_logo.description"
}}
@helpText={{i18n
"admin.config.branding.logo.form.mobile_logo.help_text"
"admin.config.logo_and_fonts.logo.form.mobile_logo.help_text"
}}
@onSet={{fn this.handleUpload "mobile_logo"}}
@placeholderUrl={{this.placeholders.mobile_logo}}
@ -260,7 +270,7 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="mobile_logo_dark_required"
@title={{i18n
"admin.config.branding.logo.form.mobile_logo_dark.required"
"admin.config.logo_and_fonts.logo.form.mobile_logo_dark.required"
}}
@format="full"
as |field|
@ -272,10 +282,10 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="mobile_logo_dark"
@title={{i18n
"admin.config.branding.logo.form.mobile_logo_dark.title"
"admin.config.logo_and_fonts.logo.form.mobile_logo_dark.title"
}}
@helpText={{i18n
"admin.config.branding.logo.form.mobile_logo_dark.help_text"
"admin.config.logo_and_fonts.logo.form.mobile_logo_dark.help_text"
}}
@onSet={{fn this.handleUpload "mobile_logo_dark"}}
as |field|
@ -287,13 +297,13 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="manifest_icon"
@title={{i18n
"admin.config.branding.logo.form.manifest_icon.title"
"admin.config.logo_and_fonts.logo.form.manifest_icon.title"
}}
@description={{i18n
"admin.config.branding.logo.form.manifest_icon.description"
"admin.config.logo_and_fonts.logo.form.manifest_icon.description"
}}
@helpText={{i18n
"admin.config.branding.logo.form.manifest_icon.help_text"
"admin.config.logo_and_fonts.logo.form.manifest_icon.help_text"
}}
@onSet={{fn this.handleUpload "manifest_icon"}}
as |field|
@ -303,10 +313,10 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="manifest_screenshots"
@title={{i18n
"admin.config.branding.logo.form.manifest_screenshots.title"
"admin.config.logo_and_fonts.logo.form.manifest_screenshots.title"
}}
@description={{i18n
"admin.config.branding.logo.form.manifest_screenshots.description"
"admin.config.logo_and_fonts.logo.form.manifest_screenshots.description"
}}
@format="full"
as |field|
@ -324,13 +334,13 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="apple_touch_icon"
@title={{i18n
"admin.config.branding.logo.form.apple_touch_icon.title"
"admin.config.logo_and_fonts.logo.form.apple_touch_icon.title"
}}
@description={{i18n
"admin.config.branding.logo.form.apple_touch_icon.description"
"admin.config.logo_and_fonts.logo.form.apple_touch_icon.description"
}}
@helpText={{i18n
"admin.config.branding.logo.form.apple_touch_icon.help_text"
"admin.config.logo_and_fonts.logo.form.apple_touch_icon.help_text"
}}
@onSet={{fn this.handleUpload "apple_touch_icon"}}
@placeholderUrl={{this.placeholders.apple_touch_icon}}
@ -341,7 +351,7 @@ export default class AdminBrandingLogoForm extends Component {
</:content>
</AdminConfigAreaCardSection>
<AdminConfigAreaCardSection
@heading={{i18n "admin.config.branding.logo.form.email"}}
@heading={{i18n "admin.config.logo_and_fonts.logo.form.email"}}
class="admin-logo-form__email-section"
@collapsable={{true}}
@collapsed={{true}}
@ -350,13 +360,13 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="digest_logo"
@title={{i18n
"admin.config.branding.logo.form.digest_logo.title"
"admin.config.logo_and_fonts.logo.form.digest_logo.title"
}}
@description={{i18n
"admin.config.branding.logo.form.digest_logo.description"
"admin.config.logo_and_fonts.logo.form.digest_logo.description"
}}
@helpText={{i18n
"admin.config.branding.logo.form.digest_logo.help_text"
"admin.config.logo_and_fonts.logo.form.digest_logo.help_text"
}}
@onSet={{fn this.handleUpload "digest_logo"}}
@placeholderUrl={{this.placeholders.digest_logo}}
@ -370,7 +380,7 @@ export default class AdminBrandingLogoForm extends Component {
</:content>
</AdminConfigAreaCardSection>
<AdminConfigAreaCardSection
@heading={{i18n "admin.config.branding.logo.form.social_media"}}
@heading={{i18n "admin.config.logo_and_fonts.logo.form.social_media"}}
class="admin-logo-form__social-media-section"
@collapsable={{true}}
@collapsed={{true}}
@ -379,10 +389,10 @@ export default class AdminBrandingLogoForm extends Component {
<form.Field
@name="opengraph_image"
@title={{i18n
"admin.config.branding.logo.form.opengraph_image.title"
"admin.config.logo_and_fonts.logo.form.opengraph_image.title"
}}
@description={{i18n
"admin.config.branding.logo.form.opengraph_image.description"
"admin.config.logo_and_fonts.logo.form.opengraph_image.description"
}}
@onSet={{fn this.handleUpload "opengraph_image"}}
@placeholderUrl={{this.placeholders.opengraph_image}}

View File

@ -1,8 +0,0 @@
import DiscourseRoute from "discourse/routes/discourse";
import { i18n } from "discourse-i18n";
export default class AdminConfigBrandingRoute extends DiscourseRoute {
titleToken() {
return i18n("admin.config.branding.title");
}
}

View File

@ -0,0 +1,8 @@
import DiscourseRoute from "discourse/routes/discourse";
import { i18n } from "discourse-i18n";
export default class AdminConfigLogoAndFontsRoute extends DiscourseRoute {
titleToken() {
return i18n("admin.config.logo_and_fonts.title");
}
}

View File

@ -353,7 +353,7 @@ export default function () {
this.route("developer", function () {
this.route("settings", { path: "/" });
});
this.route("branding");
this.route("logo-and-fonts");
this.route("navigation", function () {
this.route("settings", { path: "/" });
});

View File

@ -2,34 +2,34 @@ import RouteTemplate from "ember-route-template";
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
import DPageHeader from "discourse/components/d-page-header";
import { i18n } from "discourse-i18n";
import AdminBrandingFontsForm from "admin/components/admin-branding-fonts-form";
import AdminBrandingLogoForm from "admin/components/admin-branding-logo-form";
import AdminConfigAreaCard from "admin/components/admin-config-area-card";
import AdminFontsForm from "admin/components/admin-fonts-form";
import AdminLogoForm from "admin/components/admin-logo-form";
export default RouteTemplate(
<template>
<div class="admin-config-page">
<DPageHeader
@hideTabs={{true}}
@titleLabel={{i18n "admin.config.branding.title"}}
@titleLabel={{i18n "admin.config.logo_and_fonts.title"}}
>
<:breadcrumbs>
<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
<DBreadcrumbsItem
@path="/admin/config/branding"
@label={{i18n "admin.config.branding.title"}}
@path="/admin/config/logo-and-fonts"
@label={{i18n "admin.config.logo_and_fonts.title"}}
/>
</:breadcrumbs>
</DPageHeader>
<div class="admin-config-area">
<div class="admin-config-area__primary-content">
<AdminConfigAreaCard
@heading="admin.config.branding.logo.title"
@heading="admin.config.logo_and_fonts.logo.title"
@collapsable={{true}}
class="admin-config-area-branding__logo"
class="admin-config-area-logo-and-fonts__logo"
>
<:content>
<AdminBrandingLogoForm />
<AdminLogoForm />
</:content>
</AdminConfigAreaCard>
</div>
@ -37,12 +37,12 @@ export default RouteTemplate(
<div class="admin-config-area">
<div class="admin-config-area__primary-content">
<AdminConfigAreaCard
@heading="admin.config.branding.fonts.title"
@heading="admin.config.logo_and_fonts.fonts.title"
@collapsable={{true}}
class="admin-config-area-branding__fonts"
class="admin-config-area-logo-and-fonts__fonts"
>
<:content>
<AdminBrandingFontsForm />
<AdminFontsForm />
</:content>
</AdminConfigAreaCard>
</div>

View File

@ -19,24 +19,24 @@ export default class UpdateDefaultTextSize extends Component {
<template>
<DModal
@title={{i18n "admin.config.branding.fonts.backfill_modal.title"}}
@title={{i18n "admin.config.logo_and_fonts.fonts.backfill_modal.title"}}
@closeModal={{@closeModal}}
>
<:body>
{{i18n
"admin.config.branding.fonts.backfill_modal.description"
"admin.config.logo_and_fonts.fonts.backfill_modal.description"
count=@model.count
}}
</:body>
<:footer>
<DButton
@action={{this.updateExistingUsers}}
@label="admin.config.branding.fonts.backfill_modal.modal_yes"
@label="admin.config.logo_and_fonts.fonts.backfill_modal.modal_yes"
class="btn-primary"
/>
<DButton
@action={{this.cancel}}
@label="admin.config.branding.fonts.backfill_modal.modal_no"
@label="admin.config.logo_and_fonts.fonts.backfill_modal.modal_no"
/>
</:footer>
</DModal>

View File

@ -250,12 +250,11 @@ export const ADMIN_NAV_MAP = [
label: "admin.config_sections.appearance.title",
links: [
{
name: "admin_branding",
route: "adminConfig.branding",
label: "admin.config.branding.title",
description: "admin.config.branding.header_description",
name: "admin_logo_and_fonts",
route: "adminConfig.logo-and-fonts",
label: "admin.config.logo_and_fonts.title",
description: "admin.config.logo_and_fonts.header_description",
icon: "fab-discourse",
settings_category: "branding",
},
{
name: "admin_color_palettes",
@ -320,7 +319,7 @@ export const ADMIN_NAV_MAP = [
label: "admin.config.email.title",
description: "admin.config.email.header_description",
keywords: "admin.config.email.keywords",
icon: "far-envelope",
icon: "gear",
links: [
{
name: "admin_email_preview_summary",
@ -350,7 +349,7 @@ export const ADMIN_NAV_MAP = [
route: "adminCustomizeEmailStyle",
label: "admin.config.email_appearance.title",
description: "admin.config.email_appearance.header_description",
icon: "envelope",
icon: "palette",
},
{
name: "admin_email_logs",

View File

@ -14,7 +14,7 @@
margin-bottom: 1em;
}
&__fonts-and-logos-hint {
&__logo-and-fonts-hint {
display: flex;
justify-content: space-between;
}

View File

@ -1,73 +0,0 @@
# frozen_string_literal: true
class Admin::Config::BrandingController < Admin::AdminController
def index
end
def logo
settings =
%i[
logo
logo_dark
large_icon
favicon
logo_small
logo_small_dark
mobile_logo
mobile_logo_dark
manifest_icon
manifest_screenshots
apple_touch_icon
digest_logo
opengraph_image
x_summary_large_image
].map { |setting| { setting_name: setting, value: params[setting] } }
SiteSetting::Update.call(guardian:, params: { settings: }) do
on_success { render json: success_json }
on_failed_policy(:settings_are_visible) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_unshadowed_globally) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_configurable) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:values_are_valid) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
end
end
def fonts
previous_default_text_size = SiteSetting.default_text_size
SiteSetting::Update.call(
guardian:,
params: {
settings: [
{ setting_name: "base_font", value: params[:base_font] },
{ setting_name: "heading_font", value: params[:heading_font] },
{
setting_name: "default_text_size",
value: params[:default_text_size],
backfill: params[:update_existing_users] == "true",
},
],
},
) do
on_success { render json: success_json }
on_failed_policy(:settings_are_visible) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_unshadowed_globally) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_configurable) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:values_are_valid) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
end
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
class Admin::Config::FontsController < Admin::AdminController
def update
SiteSetting::Update.call(
guardian:,
params: {
settings: [
{ setting_name: "base_font", value: params[:base_font] },
{ setting_name: "heading_font", value: params[:heading_font] },
{
setting_name: "default_text_size",
value: params[:default_text_size],
backfill: params[:update_existing_users] == "true",
},
],
},
) do
on_success { render json: success_json }
on_failed_policy(:settings_are_visible) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_unshadowed_globally) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_configurable) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:values_are_valid) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
end
end
end

View File

@ -0,0 +1,41 @@
# frozen_string_literal: true
class Admin::Config::LogoController < Admin::AdminController
def index
end
def update
settings =
%i[
logo
logo_dark
large_icon
favicon
logo_small
logo_small_dark
mobile_logo
mobile_logo_dark
manifest_icon
manifest_screenshots
apple_touch_icon
digest_logo
opengraph_image
x_summary_large_image
].map { |setting| { setting_name: setting, value: params[setting] } }
SiteSetting::Update.call(guardian:, params: { settings: }) do
on_success { render json: success_json }
on_failed_policy(:settings_are_visible) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_unshadowed_globally) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:settings_are_configurable) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
on_failed_policy(:values_are_valid) do |policy|
raise Discourse::InvalidParameters, policy.reason
end
end
end
end

View File

@ -5257,8 +5257,8 @@ en:
login_and_authentication:
title: "Login & authentication"
header_description: "Configure how users log in and authenticate, secrets and keys, OAuth2 providers, and more"
branding:
title: "Branding"
logo_and_fonts:
title: "Logo & fonts"
header_description: "Customize the variations of your site logo and fonts"
logo:
title: "Logo"
@ -6276,8 +6276,8 @@ en:
toggle_description: "Color palette can be selected by users"
colors:
title: "Colors"
fonts_and_logos_hint: "Looking to update your fonts and logos?"
go_to_branding: "Go to Branding"
logo_and_fonts_hint: "Looking to update your logo and fonts?"
go_to_logo_and_fonts: "Go to Logo & fonts"
save_changes: "Save changes"
unsaved_changes: "You have unsaved changes"
copy_of: "Copy of %{name}"

View File

@ -5485,7 +5485,7 @@ en:
label: "Category boxes"
description: "Displays the categories and their description in a grid, ideal for members to see an overview of the sub-communities of your site"
branding:
logo_and_fonts:
title: "Site logo"
fields:
logo:

View File

@ -425,9 +425,9 @@ Discourse::Application.routes.draw do
get "experimental" => "site_settings#index"
get "trust-levels" => "site_settings#index"
get "group-permissions" => "site_settings#index"
get "branding" => "branding#index"
put "branding/logo" => "branding#logo"
put "branding/fonts" => "branding#fonts"
get "/logo-and-fonts" => "logo#index"
put "/logo" => "logo#update"
put "/fonts" => "fonts#update"
get "colors/:id" => "color_palettes#show"
resources :flags, only: %i[index new create update destroy] do

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
RSpec.describe Admin::Config::BrandingController do
RSpec.describe Admin::Config::FontsController do
fab!(:admin)
fab!(:moderator)
fab!(:user)
@ -9,7 +9,7 @@ RSpec.describe Admin::Config::BrandingController do
context "when logged in as an admin" do
before { sign_in(admin) }
it "updates the fonts and text size" do
put "/admin/config/branding/fonts.json",
put "/admin/config/fonts.json",
params: {
base_font: "helvetica",
heading_font: "roboto",
@ -23,7 +23,7 @@ RSpec.describe Admin::Config::BrandingController do
end
it "validates values" do
put "/admin/config/branding/fonts.json",
put "/admin/config/fonts.json",
params: {
base_font: "invalid_font",
heading_font: "invalid_font",
@ -39,7 +39,7 @@ RSpec.describe Admin::Config::BrandingController do
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "denies access with a 403 response" do
put "/admin/config/branding/fonts.json",
put "/admin/config/fonts.json",
params: {
base_font: "helvetica",
heading_font: "roboto",
@ -56,7 +56,7 @@ RSpec.describe Admin::Config::BrandingController do
before { sign_in(user) }
it "denies access with a 404 response" do
put "/admin/config/branding/fonts.json",
put "/admin/config/fonts.json",
params: {
base_font: "helvetica",
heading_font: "roboto",

View File

@ -1,272 +0,0 @@
# frozen_string_literal: true
describe "Admin Branding Page", type: :system do
fab!(:admin)
fab!(:image_upload)
let(:branding_page) { PageObjects::Pages::AdminBranding.new }
let(:image_file) { file_from_fixtures("logo.png", "images") }
let(:modal) { PageObjects::Modals::Base.new }
before { sign_in(admin) }
describe "logo" do
describe "primary section" do
let(:primary_section_logos) do
%i[logo logo_dark large_icon favicon logo_small logo_small_dark]
end
it "can upload images and dark versions" do
branding_page.visit
expect(branding_page.logo_form).to have_no_form_field(:logo_dark)
branding_page.logo_form.toggle_dark_mode(:logo_dark_required)
expect(branding_page.logo_form).to have_form_field(:logo_dark)
expect(branding_page.logo_form).to have_no_form_field(:logo_small_dark)
branding_page.logo_form.toggle_dark_mode(:logo_small_dark_required)
expect(branding_page.logo_form).to have_form_field(:logo_small_dark)
primary_section_logos.each do |image_type|
branding_page.logo_form.upload_image(image_type, image_file)
end
primary_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
visit("/")
branding_page.visit
expect(branding_page.logo_form).to have_form_field(:logo_dark)
expect(branding_page.logo_form).to have_form_field(:logo_small_dark)
primary_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
primary_section_logos.each { |image_type| SiteSetting.send("#{image_type}=", image_upload) }
branding_page.visit
primary_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
primary_section_logos.each { |image_type| branding_page.logo_form.remove_image(image_type) }
branding_page.logo_form.submit
expect(page).to have_css("#site-text-logo")
primary_section_logos.each { |image_type| expect(SiteSetting.send(image_type)).to eq(nil) }
end
end
describe "mobile section" do
let(:mobile_section_logos) { %i[mobile_logo mobile_logo_dark manifest_icon apple_touch_icon] }
it "can upload images and dark versions" do
branding_page.visit
branding_page.logo_form.expand_mobile_section
expect(branding_page.logo_form).to have_no_form_field(:mobile_logo_dark)
branding_page.logo_form.toggle_dark_mode(:mobile_logo_dark_required)
expect(branding_page.logo_form).to have_form_field(:mobile_logo_dark)
mobile_section_logos.each do |image_type|
branding_page.logo_form.upload_image(image_type, image_file)
end
mobile_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
visit("/")
branding_page.visit
branding_page.logo_form.expand_mobile_section
expect(branding_page.logo_form).to have_form_field(:mobile_logo_dark)
mobile_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
mobile_section_logos.each { |image_type| SiteSetting.send("#{image_type}=", image_upload) }
branding_page.visit
branding_page.logo_form.expand_mobile_section
mobile_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
mobile_section_logos.each { |image_type| branding_page.logo_form.remove_image(image_type) }
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
mobile_section_logos.each { |image_type| expect(SiteSetting.send(image_type)).to eq(nil) }
end
end
describe "email section" do
let(:email_section_logos) { %i[digest_logo] }
it "can upload images" do
branding_page.visit
branding_page.logo_form.expand_email_section
email_section_logos.each do |image_type|
branding_page.logo_form.upload_image(image_type, image_file)
end
email_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
visit("/")
branding_page.visit
branding_page.logo_form.expand_email_section
email_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
email_section_logos.each { |image_type| SiteSetting.send("#{image_type}=", image_upload) }
branding_page.visit
branding_page.logo_form.expand_email_section
email_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
email_section_logos.each { |image_type| branding_page.logo_form.remove_image(image_type) }
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
email_section_logos.each { |image_type| expect(SiteSetting.send(image_type)).to eq(nil) }
end
end
describe "social media section" do
let(:social_media_section_logos) { %i[opengraph_image] }
it "can upload images" do
branding_page.visit
branding_page.logo_form.expand_social_media_section
social_media_section_logos.each do |image_type|
branding_page.logo_form.upload_image(image_type, image_file)
end
social_media_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
visit("/")
branding_page.visit
branding_page.logo_form.expand_social_media_section
social_media_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
social_media_section_logos.each do |image_type|
SiteSetting.send("#{image_type}=", image_upload)
end
branding_page.visit
branding_page.logo_form.expand_social_media_section
social_media_section_logos.each do |image_type|
expect(branding_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
social_media_section_logos.each do |image_type|
branding_page.logo_form.remove_image(image_type)
end
branding_page.logo_form.submit
expect(branding_page.logo_form).to have_saved_successfully
social_media_section_logos.each do |image_type|
expect(SiteSetting.send(image_type)).to eq(nil)
end
end
end
end
describe "fonts" do
it "allows an admin to change the site's base font and heading font" do
branding_page.visit
branding_page.fonts_form.select_font("base", "helvetica")
expect(branding_page.fonts_form).to have_no_font("heading", "Oswald")
branding_page.fonts_form.show_more_fonts("heading")
branding_page.fonts_form.select_font("heading", "oswald")
branding_page.fonts_form.submit
expect(branding_page.fonts_form).to have_saved_successfully
branding_page.visit
expect(branding_page.fonts_form.active_font("base")).to eq("Helvetica")
expect(branding_page.fonts_form.active_font("heading")).to eq("Oswald")
end
it "allows an admin to change default text size and does not update existing users preferences" do
Jobs.run_immediately!
branding_page.visit
expect(page).to have_css("html.text-size-normal")
branding_page.fonts_form.select_default_text_size("larger")
branding_page.fonts_form.submit
expect(modal).to be_open
expect(modal.header).to have_content(
I18n.t("admin_js.admin.config.branding.fonts.backfill_modal.title"),
)
modal.close
expect(modal).to be_closed
expect(branding_page.fonts_form).to have_saved_successfully
visit "/"
expect(page).to have_css("html.text-size-normal")
end
it "allows an admin to change default text size and updates existing users preferences" do
Jobs.run_immediately!
branding_page.visit
expect(page).to have_css("html.text-size-normal")
branding_page.fonts_form.select_default_text_size("larger")
branding_page.fonts_form.submit
expect(modal).to be_open
expect(modal.header).to have_content(
I18n.t("admin_js.admin.config.branding.fonts.backfill_modal.title"),
)
modal.click_primary_button
expect(modal).to be_closed
expect(branding_page.fonts_form).to have_saved_successfully
visit "/"
expect(page).to have_css("html.text-size-larger")
end
end
end

View File

@ -0,0 +1,278 @@
# frozen_string_literal: true
describe "Admin Logo and Fonts Page", type: :system do
fab!(:admin)
fab!(:image_upload)
let(:logo_and_fonts_page) { PageObjects::Pages::AdminLogoAndFonts.new }
let(:image_file) { file_from_fixtures("logo.png", "images") }
let(:modal) { PageObjects::Modals::Base.new }
before { sign_in(admin) }
describe "logo" do
describe "primary section" do
let(:primary_section_logos) do
%i[logo logo_dark large_icon favicon logo_small logo_small_dark]
end
it "can upload images and dark versions" do
logo_and_fonts_page.visit
expect(logo_and_fonts_page.logo_form).to have_no_form_field(:logo_dark)
logo_and_fonts_page.logo_form.toggle_dark_mode(:logo_dark_required)
expect(logo_and_fonts_page.logo_form).to have_form_field(:logo_dark)
expect(logo_and_fonts_page.logo_form).to have_no_form_field(:logo_small_dark)
logo_and_fonts_page.logo_form.toggle_dark_mode(:logo_small_dark_required)
expect(logo_and_fonts_page.logo_form).to have_form_field(:logo_small_dark)
primary_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.upload_image(image_type, image_file)
end
primary_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
visit("/")
logo_and_fonts_page.visit
expect(logo_and_fonts_page.logo_form).to have_form_field(:logo_dark)
expect(logo_and_fonts_page.logo_form).to have_form_field(:logo_small_dark)
primary_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
primary_section_logos.each { |image_type| SiteSetting.send("#{image_type}=", image_upload) }
logo_and_fonts_page.visit
primary_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
primary_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.remove_image(image_type)
end
logo_and_fonts_page.logo_form.submit
expect(page).to have_css("#site-text-logo")
primary_section_logos.each { |image_type| expect(SiteSetting.send(image_type)).to eq(nil) }
end
end
describe "mobile section" do
let(:mobile_section_logos) { %i[mobile_logo mobile_logo_dark manifest_icon apple_touch_icon] }
it "can upload images and dark versions" do
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_mobile_section
expect(logo_and_fonts_page.logo_form).to have_no_form_field(:mobile_logo_dark)
logo_and_fonts_page.logo_form.toggle_dark_mode(:mobile_logo_dark_required)
expect(logo_and_fonts_page.logo_form).to have_form_field(:mobile_logo_dark)
mobile_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.upload_image(image_type, image_file)
end
mobile_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
visit("/")
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_mobile_section
expect(logo_and_fonts_page.logo_form).to have_form_field(:mobile_logo_dark)
mobile_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
mobile_section_logos.each { |image_type| SiteSetting.send("#{image_type}=", image_upload) }
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_mobile_section
mobile_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
mobile_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.remove_image(image_type)
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
mobile_section_logos.each { |image_type| expect(SiteSetting.send(image_type)).to eq(nil) }
end
end
describe "email section" do
let(:email_section_logos) { %i[digest_logo] }
it "can upload images" do
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_email_section
email_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.upload_image(image_type, image_file)
end
email_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
visit("/")
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_email_section
email_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
email_section_logos.each { |image_type| SiteSetting.send("#{image_type}=", image_upload) }
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_email_section
email_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
email_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.remove_image(image_type)
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
email_section_logos.each { |image_type| expect(SiteSetting.send(image_type)).to eq(nil) }
end
end
describe "social media section" do
let(:social_media_section_logos) { %i[opengraph_image] }
it "can upload images" do
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_social_media_section
social_media_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.upload_image(image_type, image_file)
end
social_media_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
visit("/")
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_social_media_section
social_media_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
end
it "can remove images" do
social_media_section_logos.each do |image_type|
SiteSetting.send("#{image_type}=", image_upload)
end
logo_and_fonts_page.visit
logo_and_fonts_page.logo_form.expand_social_media_section
social_media_section_logos.each do |image_type|
expect(logo_and_fonts_page.logo_form.image_uploader(image_type)).to have_uploaded_image
end
social_media_section_logos.each do |image_type|
logo_and_fonts_page.logo_form.remove_image(image_type)
end
logo_and_fonts_page.logo_form.submit
expect(logo_and_fonts_page.logo_form).to have_saved_successfully
social_media_section_logos.each do |image_type|
expect(SiteSetting.send(image_type)).to eq(nil)
end
end
end
end
describe "fonts" do
it "allows an admin to change the site's base font and heading font" do
logo_and_fonts_page.visit
logo_and_fonts_page.fonts_form.select_font("base", "helvetica")
expect(logo_and_fonts_page.fonts_form).to have_no_font("heading", "Oswald")
logo_and_fonts_page.fonts_form.show_more_fonts("heading")
logo_and_fonts_page.fonts_form.select_font("heading", "oswald")
logo_and_fonts_page.fonts_form.submit
expect(logo_and_fonts_page.fonts_form).to have_saved_successfully
logo_and_fonts_page.visit
expect(logo_and_fonts_page.fonts_form.active_font("base")).to eq("Helvetica")
expect(logo_and_fonts_page.fonts_form.active_font("heading")).to eq("Oswald")
end
it "allows an admin to change default text size and does not update existing users preferences" do
Jobs.run_immediately!
logo_and_fonts_page.visit
expect(page).to have_css("html.text-size-normal")
logo_and_fonts_page.fonts_form.select_default_text_size("larger")
logo_and_fonts_page.fonts_form.submit
expect(modal).to be_open
expect(modal.header).to have_content(
I18n.t("admin_js.admin.config.logo_and_fonts.fonts.backfill_modal.title"),
)
modal.close
expect(modal).to be_closed
expect(logo_and_fonts_page.fonts_form).to have_saved_successfully
visit "/"
expect(page).to have_css("html.text-size-normal")
end
it "allows an admin to change default text size and updates existing users preferences" do
Jobs.run_immediately!
logo_and_fonts_page.visit
expect(page).to have_css("html.text-size-normal")
logo_and_fonts_page.fonts_form.select_default_text_size("larger")
logo_and_fonts_page.fonts_form.submit
expect(modal).to be_open
expect(modal.header).to have_content(
I18n.t("admin_js.admin.config.logo_and_fonts.fonts.backfill_modal.title"),
)
modal.click_primary_button
expect(modal).to be_closed
expect(logo_and_fonts_page.fonts_form).to have_saved_successfully
visit "/"
expect(page).to have_css("html.text-size-larger")
end
end
end

View File

@ -2,7 +2,7 @@
module PageObjects
module Components
class AdminBrandingFontsForm < PageObjects::Components::Base
class AdminFontsForm < PageObjects::Components::Base
def select_font(section, font)
find(
"[data-name='#{section}_font'] .admin-fonts-form__button-option.body-font-#{font}",
@ -38,7 +38,7 @@ module PageObjects
def has_saved_successfully?
PageObjects::Components::Toasts.new.has_success?(
I18n.t("admin_js.admin.config.branding.fonts.form.saved"),
I18n.t("admin_js.admin.config.logo_and_fonts.fonts.form.saved"),
)
end

View File

@ -2,7 +2,7 @@
module PageObjects
module Components
class AdminBrandingLogoForm < PageObjects::Components::Base
class AdminLogoForm < PageObjects::Components::Base
def image_uploader(image_type)
PageObjects::Components::UppyImageUploader.new(
find(".form-kit__container[data-name='#{image_type}']"),
@ -49,7 +49,7 @@ module PageObjects
def has_saved_successfully?
PageObjects::Components::Toasts.new.has_success?(
I18n.t("admin_js.admin.config.branding.logo.form.saved"),
I18n.t("admin_js.admin.config.logo_and_fonts.logo.form.saved"),
)
end

View File

@ -1,19 +0,0 @@
# frozen_string_literal: true
module PageObjects
module Pages
class AdminBranding < PageObjects::Pages::Base
def visit
page.visit("/admin/config/branding")
end
def logo_form
@logo_form ||= PageObjects::Components::AdminBrandingLogoForm.new
end
def fonts_form
@fonts_form ||= PageObjects::Components::AdminBrandingFontsForm.new
end
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module PageObjects
module Pages
class AdminLogoAndFonts < PageObjects::Pages::Base
def visit
page.visit("/admin/config/logo-and-fonts")
end
def logo_form
@logo_form ||= PageObjects::Components::AdminLogoForm.new
end
def fonts_form
@fonts_form ||= PageObjects::Components::AdminFontsForm.new
end
end
end
end