mirror of
https://github.com/discourse/discourse.git
synced 2025-10-03 17:21:20 +08:00
DEV: Remove dual mode support for palettes and drop theme-owned palettes (#34467)
We're not going to finish/release dual-mode palettes and theme-owned palettes at this time, so we're cleaning up the code that we've already merged for these features. Internal topic: t/161279.
This commit is contained in:
parent
5cfda47b25
commit
7ee52c8f85
45 changed files with 208 additions and 1107 deletions
|
@ -186,33 +186,16 @@ export default class AdminConfigAreasColorPalette extends Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tags = document.querySelectorAll(`link[data-scheme-id="${id}"]`);
|
const tag = document.querySelector(`link[data-scheme-id="${id}"]`);
|
||||||
|
|
||||||
if (tags.length === 0) {
|
if (!tag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let darkTag;
|
|
||||||
let lightTag;
|
|
||||||
for (const tag of tags) {
|
|
||||||
if (tag.classList.contains("dark-scheme")) {
|
|
||||||
darkTag = tag;
|
|
||||||
} else if (tag.classList.contains("light-scheme")) {
|
|
||||||
lightTag = tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await ajax(`/color-scheme-stylesheet/${id}.json`, {
|
const data = await ajax(`/color-scheme-stylesheet/${id}.json`);
|
||||||
data: {
|
if (data?.new_href) {
|
||||||
include_dark_scheme: !!darkTag,
|
tag.href = data.new_href;
|
||||||
},
|
|
||||||
});
|
|
||||||
if (data?.new_href && lightTag) {
|
|
||||||
lightTag.href = data.new_href;
|
|
||||||
}
|
|
||||||
if (data?.new_dark_href && darkTag) {
|
|
||||||
darkTag.href = data.new_dark_href;
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
import { tracked } from "@glimmer/tracking";
|
|
||||||
import Controller from "@ember/controller";
|
|
||||||
import { TrackedSet } from "@ember-compat/tracked-built-ins";
|
|
||||||
|
|
||||||
class ChangeTracker {
|
|
||||||
@tracked dirtyLightColors = new TrackedSet();
|
|
||||||
@tracked dirtyDarkColors = new TrackedSet();
|
|
||||||
|
|
||||||
addDirtyLightColor(name) {
|
|
||||||
this.dirtyLightColors.add(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
addDirtyDarkColor(name) {
|
|
||||||
this.dirtyDarkColors.add(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeDirtyLightColor(name) {
|
|
||||||
this.dirtyLightColors.delete(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeDirtyDarkColor(name) {
|
|
||||||
this.dirtyDarkColors.delete(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this.dirtyLightColors.clear();
|
|
||||||
this.dirtyDarkColors.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
get dirtyColorsCount() {
|
|
||||||
return this.dirtyLightColors.size + this.dirtyDarkColors.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class AdminCustomizeThemesShowColorsController extends Controller {
|
|
||||||
colorPaletteChangeTracker = new ChangeTracker();
|
|
||||||
}
|
|
|
@ -70,12 +70,7 @@ export async function applyColorScheme(scheme, options = {}) {
|
||||||
|
|
||||||
const apiUrl = `/color-scheme-stylesheet/${id}.json`;
|
const apiUrl = `/color-scheme-stylesheet/${id}.json`;
|
||||||
|
|
||||||
const data = await ajax(apiUrl, {
|
const data = await ajax(apiUrl);
|
||||||
data: {
|
|
||||||
include_dark_scheme: !!darkTag,
|
|
||||||
},
|
|
||||||
dataType: "json",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data?.new_href && lightTag) {
|
if (data?.new_href && lightTag) {
|
||||||
lightTag.href = data.new_href;
|
lightTag.href = data.new_href;
|
||||||
|
@ -87,16 +82,6 @@ export async function applyColorScheme(scheme, options = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.new_dark_href && darkTag) {
|
|
||||||
darkTag.href = data.new_dark_href;
|
|
||||||
|
|
||||||
if (replace && id) {
|
|
||||||
darkTag.setAttribute("data-scheme-id", id);
|
|
||||||
} else if (replace && !id) {
|
|
||||||
darkTag.removeAttribute("data-scheme-id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
|
@ -7,10 +7,8 @@ import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
export default class ColorSchemeColor extends EmberObject {
|
export default class ColorSchemeColor extends EmberObject {
|
||||||
@tracked hex;
|
@tracked hex;
|
||||||
@tracked dark_hex;
|
|
||||||
|
|
||||||
@tracked originalHex;
|
@tracked originalHex;
|
||||||
@tracked originalDarkHex;
|
|
||||||
|
|
||||||
// Whether the current value is different than Discourse's default color scheme.
|
// Whether the current value is different than Discourse's default color scheme.
|
||||||
@propertyNotEqual("hex", "default_hex") overridden;
|
@propertyNotEqual("hex", "default_hex") overridden;
|
||||||
|
@ -18,19 +16,16 @@ export default class ColorSchemeColor extends EmberObject {
|
||||||
init(object) {
|
init(object) {
|
||||||
super.init(...arguments);
|
super.init(...arguments);
|
||||||
this.originalHex = object.hex;
|
this.originalHex = object.hex;
|
||||||
this.originalDarkHex = object.dark_hex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
discardColorChange() {
|
discardColorChange() {
|
||||||
this.hex = this.originalHex;
|
this.hex = this.originalHex;
|
||||||
this.dark_hex = this.originalDarkHex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@on("init")
|
@on("init")
|
||||||
startTrackingChanges() {
|
startTrackingChanges() {
|
||||||
this.set("originals", {
|
this.set("originals", {
|
||||||
hex: this.hex || "FFFFFF",
|
hex: this.hex || "FFFFFF",
|
||||||
darkHex: this.dark_hex,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// force changed property to be recalculated
|
// force changed property to be recalculated
|
||||||
|
@ -38,18 +33,14 @@ export default class ColorSchemeColor extends EmberObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether value has changed since it was last saved.
|
// Whether value has changed since it was last saved.
|
||||||
@discourseComputed("hex", "dark_hex")
|
@discourseComputed("hex")
|
||||||
changed(hex, darkHex) {
|
changed(hex) {
|
||||||
if (!this.originals) {
|
if (!this.originals) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (hex !== this.originals.hex) {
|
if (hex !== this.originals.hex) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (darkHex !== this.originals.darkHex) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,15 +11,10 @@ import ColorSchemeColor from "admin/models/color-scheme-color";
|
||||||
class ColorSchemes extends ArrayProxy {}
|
class ColorSchemes extends ArrayProxy {}
|
||||||
|
|
||||||
export default class ColorScheme extends EmberObject {
|
export default class ColorScheme extends EmberObject {
|
||||||
static findAll({ excludeThemeOwned = false } = {}) {
|
static findAll() {
|
||||||
const colorSchemes = ColorSchemes.create({ content: [], loading: true });
|
const colorSchemes = ColorSchemes.create({ content: [], loading: true });
|
||||||
|
|
||||||
const data = {};
|
return ajax("/admin/color_schemes").then((all) => {
|
||||||
if (excludeThemeOwned) {
|
|
||||||
data.exclude_theme_owned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ajax("/admin/color_schemes", { data }).then((all) => {
|
|
||||||
all.forEach((colorScheme) => {
|
all.forEach((colorScheme) => {
|
||||||
colorSchemes.pushObject(
|
colorSchemes.pushObject(
|
||||||
ColorScheme.create({
|
ColorScheme.create({
|
||||||
|
@ -89,14 +84,11 @@ export default class ColorScheme extends EmberObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
schemeObject() {
|
schemeObject() {
|
||||||
const extractColors = (property) =>
|
|
||||||
Object.fromEntries(
|
|
||||||
this.colors.map((color) => [color.name, color[property]])
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
dark: extractColors("dark_hex"),
|
light: Object.fromEntries(
|
||||||
light: extractColors("hex"),
|
this.colors.map((color) => [color.name, color.hex])
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,9 +107,7 @@ export default class ColorScheme extends EmberObject {
|
||||||
});
|
});
|
||||||
this.colors.forEach((c) => {
|
this.colors.forEach((c) => {
|
||||||
newScheme.colors.pushObject(
|
newScheme.colors.pushObject(
|
||||||
ColorSchemeColor.create(
|
ColorSchemeColor.create(c.getProperties("name", "hex", "default_hex"))
|
||||||
c.getProperties("name", "hex", "default_hex", "dark_hex")
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return newScheme;
|
return newScheme;
|
||||||
|
@ -172,7 +162,7 @@ export default class ColorScheme extends EmberObject {
|
||||||
data.colors = [];
|
data.colors = [];
|
||||||
this.colors.forEach((c) => {
|
this.colors.forEach((c) => {
|
||||||
if (!this.id || c.get("changed")) {
|
if (!this.id || c.get("changed")) {
|
||||||
data.colors.pushObject(c.getProperties("name", "hex", "dark_hex"));
|
data.colors.pushObject(c.getProperties("name", "hex"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import { tracked } from "@glimmer/tracking";
|
|
||||||
import { get } from "@ember/object";
|
import { get } from "@ember/object";
|
||||||
import { gt, or } from "@ember/object/computed";
|
import { gt, or } from "@ember/object/computed";
|
||||||
import { isBlank, isEmpty } from "@ember/utils";
|
import { isBlank, isEmpty } from "@ember/utils";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import discourseComputed from "discourse/lib/decorators";
|
import discourseComputed from "discourse/lib/decorators";
|
||||||
import RestModel from "discourse/models/rest";
|
import RestModel from "discourse/models/rest";
|
||||||
import { i18n } from "discourse-i18n";
|
import { i18n } from "discourse-i18n";
|
||||||
import ColorScheme from "admin/models/color-scheme";
|
|
||||||
import ThemeSettings from "admin/models/theme-settings";
|
import ThemeSettings from "admin/models/theme-settings";
|
||||||
import ThemeSiteSettings from "admin/models/theme-site-settings";
|
import ThemeSiteSettings from "admin/models/theme-site-settings";
|
||||||
|
|
||||||
|
@ -34,17 +31,9 @@ class Theme extends RestModel {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const palette =
|
|
||||||
json.owned_color_palette || json.color_scheme || json.base_palette;
|
|
||||||
if (palette) {
|
|
||||||
json.colorPalette = ColorScheme.create(palette);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@tracked colorPalette;
|
|
||||||
|
|
||||||
@or("default", "user_selectable") isActive;
|
@or("default", "user_selectable") isActive;
|
||||||
@gt("remote_theme.commits_behind", 0) isPendingUpdates;
|
@gt("remote_theme.commits_behind", 0) isPendingUpdates;
|
||||||
@gt("editedFields.length", 0) hasEditedFields;
|
@gt("editedFields.length", 0) hasEditedFields;
|
||||||
|
@ -192,34 +181,6 @@ class Theme extends RestModel {
|
||||||
return field ? field.error : "";
|
return field ? field.error : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeColors() {
|
|
||||||
const colors = [];
|
|
||||||
|
|
||||||
for (const color of this.colorPalette.colors) {
|
|
||||||
const colorPayload = {
|
|
||||||
name: color.name,
|
|
||||||
hex: color.hex,
|
|
||||||
dark_hex: color.dark_hex,
|
|
||||||
};
|
|
||||||
|
|
||||||
colors.push(colorPayload);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paletteData = await ajax(`/admin/themes/${this.id}/change-colors`, {
|
|
||||||
type: "PUT",
|
|
||||||
data: JSON.stringify({ colors }),
|
|
||||||
contentType: "application/json",
|
|
||||||
});
|
|
||||||
this.owned_color_palette = paletteData;
|
|
||||||
this.colorPalette = ColorScheme.create(paletteData);
|
|
||||||
}
|
|
||||||
|
|
||||||
discardColorChanges() {
|
|
||||||
for (const color of this.colorPalette.colors) {
|
|
||||||
color.discardColorChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getField(target, name) {
|
getField(target, name) {
|
||||||
if (target === "common" && name === "js") {
|
if (target === "common" && name === "js") {
|
||||||
target = "extra_js";
|
target = "extra_js";
|
||||||
|
|
|
@ -3,6 +3,6 @@ import ColorScheme from "admin/models/color-scheme";
|
||||||
|
|
||||||
export default class AdminConfigColorPalettesRoute extends DiscourseRoute {
|
export default class AdminConfigColorPalettesRoute extends DiscourseRoute {
|
||||||
model() {
|
model() {
|
||||||
return ColorScheme.findAll({ excludeThemeOwned: true });
|
return ColorScheme.findAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { action } from "@ember/object";
|
|
||||||
import { service } from "@ember/service";
|
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
|
||||||
import { i18n } from "discourse-i18n";
|
|
||||||
|
|
||||||
export default class AdminCustomizeThemesShowColorsRoute extends DiscourseRoute {
|
|
||||||
@service dialog;
|
|
||||||
|
|
||||||
@action
|
|
||||||
willTransition(transition) {
|
|
||||||
if (
|
|
||||||
this.controller.colorPaletteChangeTracker.dirtyColorsCount > 0 &&
|
|
||||||
transition.intent.name !== "adminCustomizeThemes.show.index"
|
|
||||||
) {
|
|
||||||
transition.abort();
|
|
||||||
this.dialog.yesNoConfirm({
|
|
||||||
message: i18n(
|
|
||||||
"admin.customize.theme.unsaved_colors_leave_route_confirmation"
|
|
||||||
),
|
|
||||||
didConfirm: () => {
|
|
||||||
this.controller.colorPaletteChangeTracker.clear();
|
|
||||||
transition.retry();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
titleToken() {
|
|
||||||
return i18n("admin.customize.theme.colors_title");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -69,7 +69,6 @@ export default function () {
|
||||||
function () {
|
function () {
|
||||||
this.route("show", { path: "/:theme_id" }, function () {
|
this.route("show", { path: "/:theme_id" }, function () {
|
||||||
this.route("schema", { path: "schema/:setting_name" });
|
this.route("schema", { path: "schema/:setting_name" });
|
||||||
this.route("colors");
|
|
||||||
});
|
});
|
||||||
this.route("edit", { path: "/:theme_id/:target/:field_name/edit" });
|
this.route("edit", { path: "/:theme_id/:target/:field_name/edit" });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
import Component from "@glimmer/component";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
import RouteTemplate from "ember-route-template";
|
|
||||||
import { gt } from "truth-helpers";
|
|
||||||
import { i18n } from "discourse-i18n";
|
|
||||||
import ChangesBanner from "admin/components/changes-banner";
|
|
||||||
import ColorPaletteEditor from "admin/components/color-palette-editor";
|
|
||||||
|
|
||||||
export default RouteTemplate(
|
|
||||||
class extends Component {
|
|
||||||
get pendingChangesBannerLabel() {
|
|
||||||
return i18n("admin.customize.theme.unsaved_colors", {
|
|
||||||
count: this.args.controller.colorPaletteChangeTracker.dirtyColorsCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
onColorChange(color, value) {
|
|
||||||
color.hex = value;
|
|
||||||
if (color.hex !== color.originalHex) {
|
|
||||||
this.args.controller.colorPaletteChangeTracker.addDirtyLightColor(
|
|
||||||
color.name
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.args.controller.colorPaletteChangeTracker.removeDirtyLightColor(
|
|
||||||
color.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
async save() {
|
|
||||||
await this.args.model.changeColors();
|
|
||||||
this.args.controller.colorPaletteChangeTracker.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
discard() {
|
|
||||||
this.args.model.discardColorChanges();
|
|
||||||
this.args.controller.colorPaletteChangeTracker.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ColorPaletteEditor
|
|
||||||
@colors={{@model.colorPalette.colors}}
|
|
||||||
@onColorChange={{this.onColorChange}}
|
|
||||||
@hideRevertButton={{true}}
|
|
||||||
@system={{@model.system}}
|
|
||||||
/>
|
|
||||||
{{#if (gt @controller.colorPaletteChangeTracker.dirtyColorsCount 0)}}
|
|
||||||
<ChangesBanner
|
|
||||||
@bannerLabel={{this.pendingChangesBannerLabel}}
|
|
||||||
@saveLabel={{i18n "admin.customize.theme.save_colors"}}
|
|
||||||
@discardLabel={{i18n "admin.customize.theme.discard_colors"}}
|
|
||||||
@save={{this.save}}
|
|
||||||
@discard={{this.discard}}
|
|
||||||
/>
|
|
||||||
{{/if}}
|
|
||||||
</template>
|
|
||||||
}
|
|
||||||
);
|
|
|
@ -119,114 +119,112 @@ export default RouteTemplate(
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#unless @controller.model.component}}
|
{{#unless @controller.model.component}}
|
||||||
{{#unless @controller.siteSettings.use_overhauled_theme_color_palette}}
|
<section
|
||||||
<section
|
class="form-horizontal theme settings control-unit theme-settings__light-color-scheme"
|
||||||
class="form-horizontal theme settings control-unit theme-settings__light-color-scheme"
|
>
|
||||||
>
|
<div class="row setting">
|
||||||
<div class="row setting">
|
<div class="setting-label">
|
||||||
<div class="setting-label">
|
{{i18n "admin.customize.theme.color_scheme"}}
|
||||||
{{i18n "admin.customize.theme.color_scheme"}}
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<div class="color-palette-input-group">
|
<div class="color-palette-input-group">
|
||||||
<ColorPalettePicker
|
<ColorPalettePicker
|
||||||
@content={{@controller.colorSchemes}}
|
@content={{@controller.colorSchemes}}
|
||||||
@value={{@controller.colorSchemeId}}
|
@value={{@controller.colorSchemeId}}
|
||||||
@icon="paintbrush"
|
@icon="paintbrush"
|
||||||
@options={{hash
|
@options={{hash
|
||||||
filterable=true
|
filterable=true
|
||||||
translatedNone=(i18n
|
translatedNone=(i18n
|
||||||
"admin.customize.theme.default_light_scheme"
|
"admin.customize.theme.default_light_scheme"
|
||||||
)
|
)
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="desc">{{i18n
|
|
||||||
"admin.customize.theme.color_scheme_select"
|
|
||||||
}}
|
}}
|
||||||
|
/>
|
||||||
{{#if @controller.colorSchemeId}}
|
|
||||||
<LinkTo
|
|
||||||
@route="adminCustomize.colors-show"
|
|
||||||
@model={{@controller.colorSchemeId}}
|
|
||||||
>
|
|
||||||
{{i18n "admin.customize.theme.edit_colors"}}
|
|
||||||
</LinkTo>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-controls">
|
<div class="desc">{{i18n
|
||||||
{{#if @controller.lightColorSchemeChanged}}
|
"admin.customize.theme.color_scheme_select"
|
||||||
<DButton
|
}}
|
||||||
@action={{@controller.changeLightScheme}}
|
|
||||||
@icon="check"
|
{{#if @controller.colorSchemeId}}
|
||||||
class="ok submit-light-edit"
|
<LinkTo
|
||||||
/>
|
@route="adminCustomize.colors-show"
|
||||||
<DButton
|
@model={{@controller.colorSchemeId}}
|
||||||
@action={{@controller.cancelChangeLightScheme}}
|
>
|
||||||
@icon="xmark"
|
{{i18n "admin.customize.theme.edit_colors"}}
|
||||||
class="cancel cancel-light-edit"
|
</LinkTo>
|
||||||
/>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
<section
|
<div class="setting-controls">
|
||||||
class="form-horizontal theme settings control-unit theme-settings__dark-color-scheme"
|
{{#if @controller.lightColorSchemeChanged}}
|
||||||
>
|
<DButton
|
||||||
<div class="row setting">
|
@action={{@controller.changeLightScheme}}
|
||||||
<div class="setting-label">
|
@icon="check"
|
||||||
{{i18n "admin.customize.theme.dark_color_scheme"}}
|
class="ok submit-light-edit"
|
||||||
|
/>
|
||||||
|
<DButton
|
||||||
|
@action={{@controller.cancelChangeLightScheme}}
|
||||||
|
@icon="xmark"
|
||||||
|
class="cancel cancel-light-edit"
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section
|
||||||
|
class="form-horizontal theme settings control-unit theme-settings__dark-color-scheme"
|
||||||
|
>
|
||||||
|
<div class="row setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
{{i18n "admin.customize.theme.dark_color_scheme"}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-value">
|
||||||
|
<div class="color-palette-input-group">
|
||||||
|
<ColorPalettePicker
|
||||||
|
@content={{@controller.colorSchemes}}
|
||||||
|
@value={{@controller.darkColorSchemeId}}
|
||||||
|
@icon="paintbrush"
|
||||||
|
@options={{hash
|
||||||
|
filterable=true
|
||||||
|
translatedNone=(i18n
|
||||||
|
"admin.customize.theme.default_light_scheme"
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="desc">
|
||||||
<div class="color-palette-input-group">
|
{{i18n "admin.customize.theme.dark_color_scheme_select"}}
|
||||||
<ColorPalettePicker
|
|
||||||
@content={{@controller.colorSchemes}}
|
|
||||||
@value={{@controller.darkColorSchemeId}}
|
|
||||||
@icon="paintbrush"
|
|
||||||
@options={{hash
|
|
||||||
filterable=true
|
|
||||||
translatedNone=(i18n
|
|
||||||
"admin.customize.theme.default_light_scheme"
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="desc">
|
{{#if @controller.darkColorSchemeId}}
|
||||||
{{i18n "admin.customize.theme.dark_color_scheme_select"}}
|
<LinkTo
|
||||||
|
@route="adminCustomize.colors-show"
|
||||||
{{#if @controller.darkColorSchemeId}}
|
@model={{@controller.darkColorSchemeId}}
|
||||||
<LinkTo
|
>
|
||||||
@route="adminCustomize.colors-show"
|
{{i18n "admin.customize.theme.edit_colors"}}
|
||||||
@model={{@controller.darkColorSchemeId}}
|
</LinkTo>
|
||||||
>
|
|
||||||
{{i18n "admin.customize.theme.edit_colors"}}
|
|
||||||
</LinkTo>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="setting-controls">
|
|
||||||
{{#if @controller.darkColorSchemeChanged}}
|
|
||||||
<DButton
|
|
||||||
@action={{@controller.changeDarkScheme}}
|
|
||||||
@icon="check"
|
|
||||||
class="ok submit-dark-edit"
|
|
||||||
/>
|
|
||||||
<DButton
|
|
||||||
@action={{@controller.cancelChangeDarkScheme}}
|
|
||||||
@icon="xmark"
|
|
||||||
class="cancel cancel-dark-edit"
|
|
||||||
/>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<div class="setting-controls">
|
||||||
{{/unless}}
|
{{#if @controller.darkColorSchemeChanged}}
|
||||||
|
<DButton
|
||||||
|
@action={{@controller.changeDarkScheme}}
|
||||||
|
@icon="check"
|
||||||
|
class="ok submit-dark-edit"
|
||||||
|
/>
|
||||||
|
<DButton
|
||||||
|
@action={{@controller.cancelChangeDarkScheme}}
|
||||||
|
@icon="xmark"
|
||||||
|
class="cancel cancel-dark-edit"
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
{{#if @controller.model.component}}
|
{{#if @controller.model.component}}
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { LinkTo } from "@ember/routing";
|
||||||
import { htmlSafe } from "@ember/template";
|
import { htmlSafe } from "@ember/template";
|
||||||
import RouteTemplate from "ember-route-template";
|
import RouteTemplate from "ember-route-template";
|
||||||
import DButton from "discourse/components/d-button";
|
import DButton from "discourse/components/d-button";
|
||||||
import DPageHeader from "discourse/components/d-page-header";
|
|
||||||
import NavItem from "discourse/components/nav-item";
|
|
||||||
import PluginOutlet from "discourse/components/plugin-outlet";
|
import PluginOutlet from "discourse/components/plugin-outlet";
|
||||||
import TextField from "discourse/components/text-field";
|
import TextField from "discourse/components/text-field";
|
||||||
import UserLink from "discourse/components/user-link";
|
import UserLink from "discourse/components/user-link";
|
||||||
|
@ -250,27 +248,6 @@ export default RouteTemplate(
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if @controller.siteSettings.use_overhauled_theme_color_palette}}
|
|
||||||
{{#unless @controller.model.component}}
|
|
||||||
<DPageHeader>
|
|
||||||
<:tabs>
|
|
||||||
<NavItem
|
|
||||||
class="admin-customize-theme-tabs__settings"
|
|
||||||
@route="adminCustomizeThemes.show.index"
|
|
||||||
@routeParam={{@controller.model.id}}
|
|
||||||
@label="admin.customize.theme.settings"
|
|
||||||
/>
|
|
||||||
<NavItem
|
|
||||||
class="admin-customize-theme-tabs__colors"
|
|
||||||
@route="adminCustomizeThemes.show.colors"
|
|
||||||
@routeParam={{@controller.model.id}}
|
|
||||||
@label="admin.customize.theme.colors"
|
|
||||||
/>
|
|
||||||
</:tabs>
|
|
||||||
</DPageHeader>
|
|
||||||
{{/unless}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -374,16 +374,6 @@ export default class AdminSidebarPanel extends BaseCustomSidebarPanel {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (siteSettings.use_overhauled_theme_color_palette) {
|
|
||||||
this.adminNavManager.overrideSectionLink(
|
|
||||||
"appearance",
|
|
||||||
"admin_color_palettes",
|
|
||||||
{
|
|
||||||
route: "adminConfig.colorPalettes",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [sectionName, additionalLinks] of Object.entries(
|
for (const [sectionName, additionalLinks] of Object.entries(
|
||||||
additionalAdminSidebarSectionLinks
|
additionalAdminSidebarSectionLinks
|
||||||
)) {
|
)) {
|
||||||
|
|
|
@ -57,7 +57,6 @@ acceptance("Admin - Customize - Themes - Show", function (needs) {
|
||||||
"/uploads/default/original/1X/f8a61b9a0bfac672daec9e401787812f8c5e28df.png",
|
"/uploads/default/original/1X/f8a61b9a0bfac672daec9e401787812f8c5e28df.png",
|
||||||
system: true,
|
system: true,
|
||||||
color_scheme: null,
|
color_scheme: null,
|
||||||
owned_color_palette: null,
|
|
||||||
user: {
|
user: {
|
||||||
id: -1,
|
id: -1,
|
||||||
username: "system",
|
username: "system",
|
||||||
|
|
|
@ -13,328 +13,246 @@ const example_scheme = {
|
||||||
hex: "F0ECD7",
|
hex: "F0ECD7",
|
||||||
default_hex: "F0ECD7",
|
default_hex: "F0ECD7",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "F0ECD7",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary_low",
|
name: "primary_low",
|
||||||
hex: "D6D8C7",
|
hex: "D6D8C7",
|
||||||
default_hex: "D6D8C7",
|
default_hex: "D6D8C7",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "D6D8C7",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary_low_mid",
|
name: "primary_low_mid",
|
||||||
hex: "A4AFA5",
|
hex: "A4AFA5",
|
||||||
default_hex: "A4AFA5",
|
default_hex: "A4AFA5",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "A4AFA5",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary_medium",
|
name: "primary_medium",
|
||||||
hex: "7E918C",
|
hex: "7E918C",
|
||||||
default_hex: "7E918C",
|
default_hex: "7E918C",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "7E918C",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary_high",
|
name: "primary_high",
|
||||||
hex: "4C6869",
|
hex: "4C6869",
|
||||||
default_hex: "4C6869",
|
default_hex: "4C6869",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "4C6869",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary",
|
name: "primary",
|
||||||
hex: "002B36",
|
hex: "002B36",
|
||||||
default_hex: "002B36",
|
default_hex: "002B36",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "002B36",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-50",
|
name: "primary-50",
|
||||||
hex: "F0EBDA",
|
hex: "F0EBDA",
|
||||||
default_hex: "F0EBDA",
|
default_hex: "F0EBDA",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "F0EBDA",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-100",
|
name: "primary-100",
|
||||||
hex: "DAD8CA",
|
hex: "DAD8CA",
|
||||||
default_hex: "DAD8CA",
|
default_hex: "DAD8CA",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "DAD8CA",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-200",
|
name: "primary-200",
|
||||||
hex: "B2B9B3",
|
hex: "B2B9B3",
|
||||||
default_hex: "B2B9B3",
|
default_hex: "B2B9B3",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "B2B9B3",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-300",
|
name: "primary-300",
|
||||||
hex: "839496",
|
hex: "839496",
|
||||||
default_hex: "839496",
|
default_hex: "839496",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "839496",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-400",
|
name: "primary-400",
|
||||||
hex: "76898C",
|
hex: "76898C",
|
||||||
default_hex: "76898C",
|
default_hex: "76898C",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "76898C",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-500",
|
name: "primary-500",
|
||||||
hex: "697F83",
|
hex: "697F83",
|
||||||
default_hex: "697F83",
|
default_hex: "697F83",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "697F83",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-600",
|
name: "primary-600",
|
||||||
hex: "627A7E",
|
hex: "627A7E",
|
||||||
default_hex: "627A7E",
|
default_hex: "627A7E",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "627A7E",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-700",
|
name: "primary-700",
|
||||||
hex: "556F74",
|
hex: "556F74",
|
||||||
default_hex: "556F74",
|
default_hex: "556F74",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "556F74",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-800",
|
name: "primary-800",
|
||||||
hex: "415F66",
|
hex: "415F66",
|
||||||
default_hex: "415F66",
|
default_hex: "415F66",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "415F66",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "primary-900",
|
name: "primary-900",
|
||||||
hex: "21454E",
|
hex: "21454E",
|
||||||
default_hex: "21454E",
|
default_hex: "21454E",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "21454E",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary_low",
|
name: "secondary_low",
|
||||||
hex: "325458",
|
hex: "325458",
|
||||||
default_hex: "325458",
|
default_hex: "325458",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "325458",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary_medium",
|
name: "secondary_medium",
|
||||||
hex: "6C8280",
|
hex: "6C8280",
|
||||||
default_hex: "6C8280",
|
default_hex: "6C8280",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "6C8280",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary_high",
|
name: "secondary_high",
|
||||||
hex: "97A59D",
|
hex: "97A59D",
|
||||||
default_hex: "97A59D",
|
default_hex: "97A59D",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "97A59D",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary_very_high",
|
name: "secondary_very_high",
|
||||||
hex: "E8E6D3",
|
hex: "E8E6D3",
|
||||||
default_hex: "E8E6D3",
|
default_hex: "E8E6D3",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "E8E6D3",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary",
|
name: "secondary",
|
||||||
hex: "FCF6E1",
|
hex: "FCF6E1",
|
||||||
default_hex: "FCF6E1",
|
default_hex: "FCF6E1",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "FCF6E1",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tertiary_low",
|
name: "tertiary_low",
|
||||||
hex: "D6E6DE",
|
hex: "D6E6DE",
|
||||||
default_hex: "D6E6DE",
|
default_hex: "D6E6DE",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "D6E6DE",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tertiary_medium",
|
name: "tertiary_medium",
|
||||||
hex: "7EBFD7",
|
hex: "7EBFD7",
|
||||||
default_hex: "7EBFD7",
|
default_hex: "7EBFD7",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "7EBFD7",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tertiary",
|
name: "tertiary",
|
||||||
hex: "0088cc",
|
hex: "0088cc",
|
||||||
default_hex: "0088cc",
|
default_hex: "0088cc",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "0088cc",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tertiary_high",
|
name: "tertiary_high",
|
||||||
hex: "329ED0",
|
hex: "329ED0",
|
||||||
default_hex: "329ED0",
|
default_hex: "329ED0",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "329ED0",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "quaternary",
|
name: "quaternary",
|
||||||
hex: "e45735",
|
hex: "e45735",
|
||||||
default_hex: "e45735",
|
default_hex: "e45735",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "e45735",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "header_background",
|
name: "header_background",
|
||||||
hex: "FCF6E1",
|
hex: "FCF6E1",
|
||||||
default_hex: "FCF6E1",
|
default_hex: "FCF6E1",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "FCF6E1",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "header_primary",
|
name: "header_primary",
|
||||||
hex: "002B36",
|
hex: "002B36",
|
||||||
default_hex: "002B36",
|
default_hex: "002B36",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "002B36",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "highlight_low",
|
name: "highlight_low",
|
||||||
hex: "FDF9AD",
|
hex: "FDF9AD",
|
||||||
default_hex: "FDF9AD",
|
default_hex: "FDF9AD",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "FDF9AD",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "highlight_medium",
|
name: "highlight_medium",
|
||||||
hex: "E3D0A3",
|
hex: "E3D0A3",
|
||||||
default_hex: "E3D0A3",
|
default_hex: "E3D0A3",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "E3D0A3",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "highlight",
|
name: "highlight",
|
||||||
hex: "F2F481",
|
hex: "F2F481",
|
||||||
default_hex: "F2F481",
|
default_hex: "F2F481",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "F2F481",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "highlight_high",
|
name: "highlight_high",
|
||||||
hex: "BCAA7F",
|
hex: "BCAA7F",
|
||||||
default_hex: "BCAA7F",
|
default_hex: "BCAA7F",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "BCAA7F",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "selected",
|
name: "selected",
|
||||||
hex: "E8E6D3",
|
hex: "E8E6D3",
|
||||||
default_hex: "E8E6D3",
|
default_hex: "E8E6D3",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "E8E6D3",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hover",
|
name: "hover",
|
||||||
hex: "F0EBDA",
|
hex: "F0EBDA",
|
||||||
default_hex: "F0EBDA",
|
default_hex: "F0EBDA",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "F0EBDA",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "danger_low",
|
name: "danger_low",
|
||||||
hex: "F8D9C2",
|
hex: "F8D9C2",
|
||||||
default_hex: "F8D9C2",
|
default_hex: "F8D9C2",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "F8D9C2",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "danger",
|
name: "danger",
|
||||||
hex: "e45735",
|
hex: "e45735",
|
||||||
default_hex: "e45735",
|
default_hex: "e45735",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "e45735",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "success_low",
|
name: "success_low",
|
||||||
hex: "CFE5B9",
|
hex: "CFE5B9",
|
||||||
default_hex: "CFE5B9",
|
default_hex: "CFE5B9",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "CFE5B9",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "success_medium",
|
name: "success_medium",
|
||||||
hex: "4CB544",
|
hex: "4CB544",
|
||||||
default_hex: "4CB544",
|
default_hex: "4CB544",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "4CB544",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "success",
|
name: "success",
|
||||||
hex: "009900",
|
hex: "009900",
|
||||||
default_hex: "009900",
|
default_hex: "009900",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "009900",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "love_low",
|
name: "love_low",
|
||||||
hex: "FCDDD2",
|
hex: "FCDDD2",
|
||||||
default_hex: "FCDDD2",
|
default_hex: "FCDDD2",
|
||||||
is_advanced: true,
|
is_advanced: true,
|
||||||
dark_hex: "FCDDD2",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "love",
|
name: "love",
|
||||||
hex: "fa6c8d",
|
hex: "fa6c8d",
|
||||||
default_hex: "fa6c8d",
|
default_hex: "fa6c8d",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "fa6c8d",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
is_dark: false,
|
is_dark: false,
|
||||||
|
|
|
@ -17,24 +17,18 @@ const DEFAULT_CONTENT = [
|
||||||
hex: "1a1a1a",
|
hex: "1a1a1a",
|
||||||
default_hex: "222",
|
default_hex: "222",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "1a1a1a",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary",
|
name: "secondary",
|
||||||
hex: "ffffff",
|
hex: "ffffff",
|
||||||
default_hex: "fff",
|
default_hex: "fff",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "ffffff",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tertiary",
|
name: "tertiary",
|
||||||
hex: "595bca",
|
hex: "595bca",
|
||||||
default_hex: "08c",
|
default_hex: "08c",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "595bca",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
is_dark: false,
|
is_dark: false,
|
||||||
|
@ -49,24 +43,18 @@ const DEFAULT_CONTENT = [
|
||||||
hex: "dddddd",
|
hex: "dddddd",
|
||||||
default_hex: "dddddd",
|
default_hex: "dddddd",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "dddddd",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "secondary",
|
name: "secondary",
|
||||||
hex: "222222",
|
hex: "222222",
|
||||||
default_hex: "222222",
|
default_hex: "222222",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "222222",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tertiary",
|
name: "tertiary",
|
||||||
hex: "099dd7",
|
hex: "099dd7",
|
||||||
default_hex: "099dd7",
|
default_hex: "099dd7",
|
||||||
is_advanced: false,
|
is_advanced: false,
|
||||||
dark_hex: "099dd7",
|
|
||||||
default_dark_hex: null,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
is_dark: true,
|
is_dark: true,
|
||||||
|
|
|
@ -4,10 +4,7 @@ class Admin::ColorSchemesController < Admin::AdminController
|
||||||
before_action :fetch_color_scheme, only: %i[update destroy]
|
before_action :fetch_color_scheme, only: %i[update destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
schemes =
|
schemes = ColorScheme.includes(:base_scheme).order("color_schemes.id ASC")
|
||||||
ColorScheme.without_theme_owned_palettes.includes(:base_scheme).order("color_schemes.id ASC")
|
|
||||||
|
|
||||||
schemes = schemes.where(theme_id: nil) if params[:exclude_theme_owned]
|
|
||||||
|
|
||||||
render_serialized(ColorScheme.base_color_schemes + schemes.to_a, ColorSchemeSerializer)
|
render_serialized(ColorScheme.base_color_schemes + schemes.to_a, ColorSchemeSerializer)
|
||||||
end
|
end
|
||||||
|
@ -38,13 +35,11 @@ class Admin::ColorSchemesController < Admin::AdminController
|
||||||
private
|
private
|
||||||
|
|
||||||
def fetch_color_scheme
|
def fetch_color_scheme
|
||||||
@color_scheme = ColorScheme.without_theme_owned_palettes.find(params[:id])
|
@color_scheme = ColorScheme.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def color_scheme_params
|
def color_scheme_params
|
||||||
params.permit(
|
params.permit(color_scheme: [:base_scheme_id, :name, :user_selectable, colors: %i[name hex]])[
|
||||||
color_scheme: [:base_scheme_id, :name, :user_selectable, colors: %i[name hex dark_hex]],
|
|
||||||
)[
|
|
||||||
:color_scheme
|
:color_scheme
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class Admin::Config::ColorPalettesController < Admin::AdminController
|
class Admin::Config::ColorPalettesController < Admin::AdminController
|
||||||
def index
|
def index
|
||||||
palettes = ColorScheme.without_theme_owned_palettes.to_a
|
palettes = ColorScheme.all.to_a
|
||||||
palettes.unshift(ColorScheme.base)
|
palettes.unshift(ColorScheme.base)
|
||||||
default_theme = Theme.find_default
|
default_theme = Theme.find_default
|
||||||
default_light_palette = default_theme&.color_scheme_id
|
default_light_palette = default_theme&.color_scheme_id
|
||||||
|
@ -55,10 +55,6 @@ class Admin::Config::ColorPalettesController < Admin::AdminController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
render_serialized(
|
render_serialized(ColorScheme.find(params[:id]), ColorSchemeSerializer, root: false)
|
||||||
ColorScheme.without_theme_owned_palettes.find(params[:id]),
|
|
||||||
ColorSchemeSerializer,
|
|
||||||
root: false,
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -176,7 +176,6 @@ class Admin::ThemesController < Admin::AdminController
|
||||||
ColorScheme
|
ColorScheme
|
||||||
.strict_loading
|
.strict_loading
|
||||||
.all
|
.all
|
||||||
.without_theme_owned_palettes
|
|
||||||
.includes(
|
.includes(
|
||||||
:theme,
|
:theme,
|
||||||
:base_scheme,
|
:base_scheme,
|
||||||
|
@ -402,20 +401,6 @@ class Admin::ThemesController < Admin::AdminController
|
||||||
render_serialized(theme_setting, ThemeObjectsSettingMetadataSerializer, root: false)
|
render_serialized(theme_setting, ThemeObjectsSettingMetadataSerializer, root: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_colors
|
|
||||||
raise Discourse::InvalidAccess if params[:id].to_i.negative?
|
|
||||||
theme = Theme.find_by(id: params[:id], component: false)
|
|
||||||
raise Discourse::NotFound if !theme
|
|
||||||
|
|
||||||
palette = theme.find_or_create_owned_color_palette
|
|
||||||
|
|
||||||
colors = params.permit(colors: %i[name hex dark_hex])
|
|
||||||
|
|
||||||
ColorSchemeRevisor.revise_existing_colors_only(palette, colors)
|
|
||||||
|
|
||||||
render_serialized(palette, ColorSchemeSerializer, root: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ban_in_allowlist_mode!
|
def ban_in_allowlist_mode!
|
||||||
|
|
|
@ -23,15 +23,9 @@ class StylesheetsController < ApplicationController
|
||||||
def color_scheme
|
def color_scheme
|
||||||
params.require("id")
|
params.require("id")
|
||||||
params.permit("theme_id")
|
params.permit("theme_id")
|
||||||
params.permit("include_dark_scheme")
|
|
||||||
|
|
||||||
manager = Stylesheet::Manager.new(theme_id: params[:theme_id])
|
manager = Stylesheet::Manager.new(theme_id: params[:theme_id])
|
||||||
stylesheet =
|
stylesheet = manager.color_scheme_stylesheet_details(params[:id], fallback_to_base: true)
|
||||||
manager.color_scheme_stylesheet_details(
|
|
||||||
params[:id],
|
|
||||||
fallback_to_base: true,
|
|
||||||
include_dark_scheme: !!params[:include_dark_scheme],
|
|
||||||
)
|
|
||||||
|
|
||||||
render json: stylesheet
|
render json: stylesheet
|
||||||
end
|
end
|
||||||
|
|
|
@ -575,10 +575,7 @@ module ApplicationHelper
|
||||||
return user_scheme_id if user_scheme_id
|
return user_scheme_id if user_scheme_id
|
||||||
return if theme_id.blank?
|
return if theme_id.blank?
|
||||||
|
|
||||||
if SiteSetting.use_overhauled_theme_color_palette
|
@scheme_id = Theme.where(id: theme_id).pick(:color_scheme_id)
|
||||||
@scheme_id = ThemeColorScheme.where(theme_id: theme_id).pick(:color_scheme_id)
|
|
||||||
end
|
|
||||||
@scheme_id ||= Theme.where(id: theme_id).pick(:color_scheme_id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_dark_scheme_id
|
def user_dark_scheme_id
|
||||||
|
@ -588,12 +585,8 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def dark_scheme_id
|
def dark_scheme_id
|
||||||
if SiteSetting.use_overhauled_theme_color_palette
|
user_dark_scheme_id ||
|
||||||
scheme_id
|
(theme_id ? Theme.find_by_id(theme_id) : Theme.find_default)&.dark_color_scheme_id || -1
|
||||||
else
|
|
||||||
user_dark_scheme_id ||
|
|
||||||
(theme_id ? Theme.find_by_id(theme_id) : Theme.find_default)&.dark_color_scheme_id || -1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_homepage
|
def current_homepage
|
||||||
|
@ -684,7 +677,6 @@ module ApplicationHelper
|
||||||
if dark_scheme_id != -1
|
if dark_scheme_id != -1
|
||||||
result << stylesheet_manager.color_scheme_stylesheet_preload_tag(
|
result << stylesheet_manager.color_scheme_stylesheet_preload_tag(
|
||||||
dark_scheme_id,
|
dark_scheme_id,
|
||||||
dark: SiteSetting.use_overhauled_theme_color_palette,
|
|
||||||
fallback_to_base: false,
|
fallback_to_base: false,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -702,7 +694,6 @@ module ApplicationHelper
|
||||||
dark_href =
|
dark_href =
|
||||||
stylesheet_manager.color_scheme_stylesheet_link_tag_href(
|
stylesheet_manager.color_scheme_stylesheet_link_tag_href(
|
||||||
dark_scheme_id,
|
dark_scheme_id,
|
||||||
dark: SiteSetting.use_overhauled_theme_color_palette,
|
|
||||||
fallback_to_base: false,
|
fallback_to_base: false,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -786,11 +777,7 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def dark_color_hex_for_name(name)
|
def dark_color_hex_for_name(name)
|
||||||
ColorScheme.hex_for_name(
|
ColorScheme.hex_for_name(name, dark_scheme_id)
|
||||||
name,
|
|
||||||
dark_scheme_id,
|
|
||||||
dark: SiteSetting.use_overhauled_theme_color_palette,
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def dark_elements_media_query
|
def dark_elements_media_query
|
||||||
|
|
|
@ -346,12 +346,6 @@ class ColorScheme < ActiveRecord::Base
|
||||||
belongs_to :theme
|
belongs_to :theme
|
||||||
belongs_to :base_scheme, class_name: "ColorScheme"
|
belongs_to :base_scheme, class_name: "ColorScheme"
|
||||||
|
|
||||||
has_one :theme_color_scheme, dependent: :destroy
|
|
||||||
has_one :owning_theme, class_name: "Theme", through: :theme_color_scheme, source: :theme
|
|
||||||
|
|
||||||
scope :without_theme_owned_palettes,
|
|
||||||
-> { where("color_schemes.id NOT IN (SELECT color_scheme_id FROM theme_color_schemes)") }
|
|
||||||
|
|
||||||
validates_associated :color_scheme_colors
|
validates_associated :color_scheme_colors
|
||||||
|
|
||||||
BASE_COLORS_FILE = "#{Rails.root}/app/assets/stylesheets/common/foundation/colors.scss"
|
BASE_COLORS_FILE = "#{Rails.root}/app/assets/stylesheets/common/foundation/colors.scss"
|
||||||
|
@ -450,18 +444,17 @@ class ColorScheme < ActiveRecord::Base
|
||||||
new_color_scheme
|
new_color_scheme
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.lookup_hex_for_name(name, scheme_id = nil, dark: false)
|
def self.lookup_hex_for_name(name, scheme_id = nil)
|
||||||
enabled_color_scheme = find_by(id: scheme_id) if scheme_id
|
enabled_color_scheme = find_by(id: scheme_id) if scheme_id
|
||||||
enabled_color_scheme ||= Theme.where(id: SiteSetting.default_theme_id).first&.color_scheme
|
enabled_color_scheme ||= Theme.where(id: SiteSetting.default_theme_id).first&.color_scheme
|
||||||
color_record = (enabled_color_scheme || base).colors.find { |c| c.name == name }
|
color_record = (enabled_color_scheme || base).colors.find { |c| c.name == name }
|
||||||
return if !color_record
|
return if !color_record
|
||||||
dark ? color_record.dark_hex || color_record.hex : color_record.hex
|
color_record.hex
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.hex_for_name(name, scheme_id = nil, dark: false)
|
def self.hex_for_name(name, scheme_id = nil)
|
||||||
cache_key = scheme_id ? "#{name}_#{scheme_id}" : name
|
cache_key = scheme_id ? "#{name}_#{scheme_id}" : name
|
||||||
cache_key += "_dark" if dark
|
hex_cache.defer_get_set(cache_key) { lookup_hex_for_name(name, scheme_id) }
|
||||||
hex_cache.defer_get_set(cache_key) { lookup_hex_for_name(name, scheme_id, dark:) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def colors=(arr)
|
def colors=(arr)
|
||||||
|
@ -501,16 +494,10 @@ class ColorScheme < ActiveRecord::Base
|
||||||
colors || (base_scheme_id ? {} : ColorScheme.base_colors)
|
colors || (base_scheme_id ? {} : ColorScheme.base_colors)
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolved_colors(dark: false)
|
def resolved_colors
|
||||||
from_base = ColorScheme.base_colors
|
from_base = ColorScheme.base_colors
|
||||||
from_custom_scheme = base_colors
|
from_custom_scheme = base_colors
|
||||||
from_db =
|
from_db = colors.map { |c| [c.name, c.hex] }.to_h
|
||||||
colors
|
|
||||||
.map do |c|
|
|
||||||
hex = dark ? (c.dark_hex || c.hex) : c.hex
|
|
||||||
[c.name, hex]
|
|
||||||
end
|
|
||||||
.to_h
|
|
||||||
|
|
||||||
resolved = from_base.merge(from_custom_scheme).except("hover", "selected").merge(from_db)
|
resolved = from_base.merge(from_custom_scheme).except("hover", "selected").merge(from_db)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ColorSchemeColor < ActiveRecord::Base
|
class ColorSchemeColor < ActiveRecord::Base
|
||||||
|
self.ignored_columns = [
|
||||||
|
"dark_hex", # TODO: Remove when 20250821155127_drop_dark_hex_from_color_scheme_color has been promoted to pre-deploy
|
||||||
|
]
|
||||||
|
|
||||||
belongs_to :color_scheme
|
belongs_to :color_scheme
|
||||||
|
|
||||||
validates :hex, format: { with: /\A([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\z/ }
|
validates :hex, format: { with: /\A([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\z/ }
|
||||||
validates :dark_hex, format: { with: /\A([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\z/ }, allow_nil: true
|
|
||||||
|
|
||||||
def hex_with_hash
|
def hex_with_hash
|
||||||
"##{hex}"
|
"##{hex}"
|
||||||
|
@ -16,12 +19,11 @@ end
|
||||||
# Table name: color_scheme_colors
|
# Table name: color_scheme_colors
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# name :string not null
|
|
||||||
# hex :string not null
|
# hex :string not null
|
||||||
# color_scheme_id :integer not null
|
# name :string not null
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# dark_hex :string(6)
|
# color_scheme_id :integer not null
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
class ColorSchemeSetting < EnumSiteSetting
|
class ColorSchemeSetting < EnumSiteSetting
|
||||||
def self.valid_value?(val)
|
def self.valid_value?(val)
|
||||||
val == -1 || ColorScheme.without_theme_owned_palettes.find_by_id(val)
|
val == -1 || ColorScheme.find_by_id(val)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.values
|
def self.values
|
||||||
values = [{ name: I18n.t("site_settings.dark_mode_none"), value: -1 }]
|
values = [{ name: I18n.t("site_settings.dark_mode_none"), value: -1 }]
|
||||||
ColorScheme.all.without_theme_owned_palettes.map { |c| values << { name: c.name, value: c.id } }
|
ColorScheme.all.map { |c| values << { name: c.name, value: c.id } }
|
||||||
values
|
values
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,13 +66,6 @@ class Theme < ActiveRecord::Base
|
||||||
-> { where(target_id: Theme.targets[:settings], name: "yaml") },
|
-> { where(target_id: Theme.targets[:settings], name: "yaml") },
|
||||||
class_name: "ThemeField"
|
class_name: "ThemeField"
|
||||||
has_one :javascript_cache, dependent: :destroy
|
has_one :javascript_cache, dependent: :destroy
|
||||||
has_one :theme_color_scheme, dependent: :destroy
|
|
||||||
has_one :owned_color_scheme,
|
|
||||||
class_name: "ColorScheme",
|
|
||||||
through: :theme_color_scheme,
|
|
||||||
source: :color_scheme
|
|
||||||
alias_method :owned_color_palette, :owned_color_scheme
|
|
||||||
alias_method :owned_color_palette=, :owned_color_scheme=
|
|
||||||
|
|
||||||
has_many :locale_fields,
|
has_many :locale_fields,
|
||||||
-> { filter_locale_fields(I18n.fallbacks[I18n.locale]) },
|
-> { filter_locale_fields(I18n.fallbacks[I18n.locale]) },
|
||||||
|
@ -129,7 +122,6 @@ class Theme < ActiveRecord::Base
|
||||||
:locale_fields,
|
:locale_fields,
|
||||||
:theme_translation_overrides,
|
:theme_translation_overrides,
|
||||||
color_scheme: %i[theme color_scheme_colors base_scheme],
|
color_scheme: %i[theme color_scheme_colors base_scheme],
|
||||||
owned_color_scheme: %i[theme color_scheme_colors base_scheme],
|
|
||||||
parent_themes: %i[color_scheme locale_fields theme_translation_overrides],
|
parent_themes: %i[color_scheme locale_fields theme_translation_overrides],
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -1089,40 +1081,6 @@ class Theme < ActiveRecord::Base
|
||||||
ThemeSiteSettingResolver.new(theme: self).resolved_theme_site_settings
|
ThemeSiteSettingResolver.new(theme: self).resolved_theme_site_settings
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_or_create_owned_color_palette
|
|
||||||
Theme.transaction do
|
|
||||||
next self.owned_color_palette if self.owned_color_palette
|
|
||||||
|
|
||||||
palette = self.color_palette || ColorScheme.base
|
|
||||||
|
|
||||||
copy = palette.dup
|
|
||||||
copy.theme_id = self.id
|
|
||||||
copy.base_scheme_id = nil
|
|
||||||
copy.user_selectable = false
|
|
||||||
copy.via_wizard = false
|
|
||||||
copy.save!
|
|
||||||
|
|
||||||
result =
|
|
||||||
ThemeColorScheme.insert_all(
|
|
||||||
[{ theme_id: self.id, color_scheme_id: copy.id }],
|
|
||||||
unique_by: :index_theme_color_schemes_on_theme_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
if result.rows.size == 0
|
|
||||||
# race condition, a palette has already been associated with this theme
|
|
||||||
copy.destroy!
|
|
||||||
self.reload.owned_color_palette
|
|
||||||
else
|
|
||||||
ColorSchemeColor.insert_all(
|
|
||||||
palette.colors.map do |color|
|
|
||||||
{ color_scheme_id: copy.id, name: color.name, hex: color.hex, dark_hex: color.dark_hex }
|
|
||||||
end,
|
|
||||||
)
|
|
||||||
copy.reload
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
attr_accessor :theme_setting_requests_refresh
|
attr_accessor :theme_setting_requests_refresh
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class ThemeColorScheme < ActiveRecord::Base
|
|
||||||
belongs_to :theme
|
|
||||||
belongs_to :color_scheme, dependent: :destroy
|
|
||||||
end
|
|
||||||
|
|
||||||
# == Schema Information
|
|
||||||
#
|
|
||||||
# Table name: theme_color_schemes
|
|
||||||
#
|
|
||||||
# id :bigint not null, primary key
|
|
||||||
# theme_id :integer not null
|
|
||||||
# color_scheme_id :integer not null
|
|
||||||
# created_at :datetime not null
|
|
||||||
# updated_at :datetime not null
|
|
||||||
#
|
|
||||||
# Indexes
|
|
||||||
#
|
|
||||||
# index_theme_color_schemes_on_color_scheme_id (color_scheme_id) UNIQUE
|
|
||||||
# index_theme_color_schemes_on_theme_id (theme_id) UNIQUE
|
|
||||||
#
|
|
|
@ -1,16 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ColorSchemeColorSerializer < ApplicationSerializer
|
class ColorSchemeColorSerializer < ApplicationSerializer
|
||||||
attributes :name, :hex, :default_hex, :is_advanced, :dark_hex, :default_dark_hex
|
attributes :name, :hex, :default_hex, :is_advanced
|
||||||
|
|
||||||
def hex
|
def hex
|
||||||
object.hex
|
object.hex
|
||||||
end
|
end
|
||||||
|
|
||||||
def dark_hex
|
|
||||||
object.dark_hex || object.hex
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_hex
|
def default_hex
|
||||||
# return the hex value of the color when it is already a base color or no base_scheme is set
|
# return the hex value of the color when it is already a base color or no base_scheme is set
|
||||||
if !object.color_scheme || object.color_scheme.base_scheme_id == 0
|
if !object.color_scheme || object.color_scheme.base_scheme_id == 0
|
||||||
|
@ -20,12 +16,6 @@ class ColorSchemeColorSerializer < ApplicationSerializer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_dark_hex
|
|
||||||
# TODO(osama) implement this when we add dark mode colors for built-in
|
|
||||||
# palettes
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_advanced
|
def is_advanced
|
||||||
!ColorScheme.base_colors.keys.include?(object.name)
|
!ColorScheme.base_colors.keys.include?(object.name)
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,8 +19,6 @@ class ThemeSerializer < BasicThemeSerializer
|
||||||
:system
|
:system
|
||||||
|
|
||||||
has_one :color_scheme, serializer: ColorSchemeSerializer, embed: :object
|
has_one :color_scheme, serializer: ColorSchemeSerializer, embed: :object
|
||||||
has_one :owned_color_palette, serializer: ColorSchemeSerializer, embed: :object
|
|
||||||
has_one :base_palette, serializer: ColorSchemeSerializer, embed: :object
|
|
||||||
has_one :user, serializer: UserNameSerializer, embed: :object
|
has_one :user, serializer: UserNameSerializer, embed: :object
|
||||||
has_one :disabled_by, serializer: UserNameSerializer, embed: :object
|
has_one :disabled_by, serializer: UserNameSerializer, embed: :object
|
||||||
|
|
||||||
|
@ -60,14 +58,6 @@ class ThemeSerializer < BasicThemeSerializer
|
||||||
object.parent_themes
|
object.parent_themes
|
||||||
end
|
end
|
||||||
|
|
||||||
def base_palette
|
|
||||||
ColorScheme.base
|
|
||||||
end
|
|
||||||
|
|
||||||
def include_base_palette?
|
|
||||||
object.color_scheme_id.blank? && object.owned_color_palette.blank?
|
|
||||||
end
|
|
||||||
|
|
||||||
def settings
|
def settings
|
||||||
object.settings.map do |_name, setting|
|
object.settings.map do |_name, setting|
|
||||||
ThemeSettingsSerializer.new(setting, scope:, root: false)
|
ThemeSettingsSerializer.new(setting, scope:, root: false)
|
||||||
|
|
|
@ -28,11 +28,7 @@ class ColorSchemeRevisor
|
||||||
if existing = @color_scheme.colors_by_name[c[:name]]
|
if existing = @color_scheme.colors_by_name[c[:name]]
|
||||||
existing.update(c)
|
existing.update(c)
|
||||||
elsif !update_existing_colors_only
|
elsif !update_existing_colors_only
|
||||||
@color_scheme.color_scheme_colors << ColorSchemeColor.new(
|
@color_scheme.color_scheme_colors << ColorSchemeColor.new(name: c[:name], hex: c[:hex])
|
||||||
name: c[:name],
|
|
||||||
hex: c[:hex],
|
|
||||||
dark_hex: c[:dark_hex],
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@color_scheme.clear_colors_cache
|
@color_scheme.clear_colors_cache
|
||||||
|
|
|
@ -7051,15 +7051,6 @@ en:
|
||||||
repo_unreachable: "Couldn't contact the Git repository of this theme. Error message:"
|
repo_unreachable: "Couldn't contact the Git repository of this theme. Error message:"
|
||||||
built_in_description: "This theme is preinstalled and can not be deleted or customized"
|
built_in_description: "This theme is preinstalled and can not be deleted or customized"
|
||||||
imported_from_archive: "This theme was imported from a .zip file"
|
imported_from_archive: "This theme was imported from a .zip file"
|
||||||
settings: "Settings"
|
|
||||||
colors: "Colors"
|
|
||||||
unsaved_colors:
|
|
||||||
one: "You have %{count} unsaved color"
|
|
||||||
other: "You have %{count} unsaved colors"
|
|
||||||
unsaved_colors_leave_route_confirmation: "You haven't saved your color palette changes yet. Are you sure you want to leave?"
|
|
||||||
save_colors: "Save colors"
|
|
||||||
discard_colors: "Discard"
|
|
||||||
colors_title: "Colors"
|
|
||||||
scss:
|
scss:
|
||||||
text: "CSS"
|
text: "CSS"
|
||||||
title: "Custom CSS rules with support for SCSS syntax"
|
title: "Custom CSS rules with support for SCSS syntax"
|
||||||
|
|
|
@ -254,7 +254,6 @@ Discourse::Application.routes.draw do
|
||||||
put "setting" => "themes#update_single_setting"
|
put "setting" => "themes#update_single_setting"
|
||||||
put "site-setting" => "themes#update_theme_site_setting"
|
put "site-setting" => "themes#update_theme_site_setting"
|
||||||
get "objects_setting_metadata/:setting_name" => "themes#objects_setting_metadata"
|
get "objects_setting_metadata/:setting_name" => "themes#objects_setting_metadata"
|
||||||
put "change-colors" => "themes#change_colors"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
collection do
|
collection do
|
||||||
|
@ -275,7 +274,6 @@ Discourse::Application.routes.draw do
|
||||||
get "components/:id" => "themes#index"
|
get "components/:id" => "themes#index"
|
||||||
get "components/:id/:target/:field_name/edit" => "themes#index"
|
get "components/:id/:target/:field_name/edit" => "themes#index"
|
||||||
get "themes/:id/export" => "themes#export"
|
get "themes/:id/export" => "themes#export"
|
||||||
get "themes/:id/colors" => "themes#index"
|
|
||||||
get "themes/:id/schema/:setting_name" => "themes#schema"
|
get "themes/:id/schema/:setting_name" => "themes#schema"
|
||||||
get "components/:id/schema/:setting_name" => "themes#schema"
|
get "components/:id/schema/:setting_name" => "themes#schema"
|
||||||
|
|
||||||
|
|
|
@ -4150,11 +4150,6 @@ experimental:
|
||||||
type: group_list
|
type: group_list
|
||||||
list_type: compact
|
list_type: compact
|
||||||
area: "group_permissions|experimental"
|
area: "group_permissions|experimental"
|
||||||
use_overhauled_theme_color_palette:
|
|
||||||
default: false
|
|
||||||
hidden: true
|
|
||||||
client: true
|
|
||||||
area: "experimental"
|
|
||||||
reviewable_ui_refresh:
|
reviewable_ui_refresh:
|
||||||
client: true
|
client: true
|
||||||
type: group_list
|
type: group_list
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RemoveUseOverhauledThemeColorPaletteSetting < ActiveRecord::Migration[8.0]
|
||||||
|
def up
|
||||||
|
execute "DELETE FROM site_settings WHERE name = 'use_overhauled_theme_color_palette'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropDarkHexFromColorSchemeColor < ActiveRecord::Migration[8.0]
|
||||||
|
DROPPED_COLUMNS = { color_scheme_colors: %i[dark_hex] }
|
||||||
|
|
||||||
|
def up
|
||||||
|
DROPPED_COLUMNS.each { |table, columns| Migration::ColumnDropper.execute_drop(table, columns) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
20
db/post_migrate/20250821155615_drop_theme_color_scheme.rb
Normal file
20
db/post_migrate/20250821155615_drop_theme_color_scheme.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropThemeColorScheme < ActiveRecord::Migration[8.0]
|
||||||
|
DROPPED_TABLES = %i[theme_color_schemes]
|
||||||
|
|
||||||
|
def up
|
||||||
|
delete_ids = DB.query_single("SELECT color_scheme_id FROM theme_color_schemes")
|
||||||
|
|
||||||
|
if delete_ids.length > 0
|
||||||
|
execute("DELETE FROM color_schemes WHERE id IN (#{delete_ids.join(",")})")
|
||||||
|
execute("DELETE FROM color_scheme_colors WHERE color_scheme_id IN (#{delete_ids.join(",")})")
|
||||||
|
end
|
||||||
|
|
||||||
|
DROPPED_TABLES.each { |table| Migration::TableDropper.execute_drop(table) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
|
@ -160,21 +160,19 @@ module Stylesheet
|
||||||
if @color_scheme_id
|
if @color_scheme_id
|
||||||
colors =
|
colors =
|
||||||
begin
|
begin
|
||||||
ColorScheme.find(@color_scheme_id).resolved_colors(dark: @dark)
|
ColorScheme.find(@color_scheme_id).resolved_colors
|
||||||
rescue StandardError
|
rescue StandardError
|
||||||
ColorScheme.base_colors
|
ColorScheme.base_colors
|
||||||
end
|
end
|
||||||
elsif (@theme_id && !theme.component)
|
elsif (@theme_id && !theme.component)
|
||||||
colors = theme&.color_scheme&.resolved_colors(dark: @dark) || ColorScheme.base_colors
|
colors = theme&.color_scheme&.resolved_colors || ColorScheme.base_colors
|
||||||
else
|
else
|
||||||
# this is a slightly ugly backwards compatibility fix,
|
# this is a slightly ugly backwards compatibility fix,
|
||||||
# we shouldn't be using the default theme color scheme for components
|
# we shouldn't be using the default theme color scheme for components
|
||||||
# (most components use CSS custom properties which work fine without this)
|
# (most components use CSS custom properties which work fine without this)
|
||||||
colors =
|
colors =
|
||||||
Theme
|
Theme.find_by_id(SiteSetting.default_theme_id)&.color_scheme&.resolved_colors ||
|
||||||
.find_by_id(SiteSetting.default_theme_id)
|
ColorScheme.base_colors
|
||||||
&.color_scheme
|
|
||||||
&.resolved_colors(dark: @dark) || ColorScheme.base_colors
|
|
||||||
end
|
end
|
||||||
|
|
||||||
colors.each { |n, hex| contents << "$#{n}: ##{hex} !default; " }
|
colors.each { |n, hex| contents << "$#{n}: ##{hex} !default; " }
|
||||||
|
@ -195,7 +193,6 @@ module Stylesheet
|
||||||
@theme = options[:theme]
|
@theme = options[:theme]
|
||||||
@theme_id = options[:theme_id]
|
@theme_id = options[:theme_id]
|
||||||
@color_scheme_id = options[:color_scheme_id]
|
@color_scheme_id = options[:color_scheme_id]
|
||||||
@dark = options[:dark]
|
|
||||||
|
|
||||||
if @theme && !@theme_id
|
if @theme && !@theme_id
|
||||||
# make up an id so other stuff does not bail out
|
# make up an id so other stuff does not bail out
|
||||||
|
|
|
@ -42,11 +42,10 @@ class Stylesheet::Manager
|
||||||
cache.clear_regex(/#{plugin}/)
|
cache.clear_regex(/#{plugin}/)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.color_scheme_cache_key(color_scheme, theme_id = nil, dark: false)
|
def self.color_scheme_cache_key(color_scheme, theme_id = nil)
|
||||||
color_scheme_name = Slug.for(color_scheme.name) + color_scheme&.id.to_s
|
color_scheme_name = Slug.for(color_scheme.name) + color_scheme&.id.to_s
|
||||||
theme_string = theme_id ? "_theme#{theme_id}" : ""
|
theme_string = theme_id ? "_theme#{theme_id}" : ""
|
||||||
dark_string = dark ? "_dark" : ""
|
"#{COLOR_SCHEME_STYLESHEET}_#{color_scheme_name}_#{theme_string}_#{Discourse.current_hostname}_#{GlobalSetting.relative_url_root}"
|
||||||
"#{COLOR_SCHEME_STYLESHEET}_#{color_scheme_name}_#{theme_string}_#{Discourse.current_hostname}_#{GlobalSetting.relative_url_root}_#{dark_string}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.precompile_css
|
def self.precompile_css
|
||||||
|
@ -117,17 +116,13 @@ class Stylesheet::Manager
|
||||||
theme_dark_color_scheme = ColorScheme.find_by_id(dark_color_scheme_id)
|
theme_dark_color_scheme = ColorScheme.find_by_id(dark_color_scheme_id)
|
||||||
theme = manager.get_theme(theme_id)
|
theme = manager.get_theme(theme_id)
|
||||||
[theme_color_scheme, theme_dark_color_scheme, *color_schemes].compact.uniq.each do |scheme|
|
[theme_color_scheme, theme_dark_color_scheme, *color_schemes].compact.uniq.each do |scheme|
|
||||||
[true, false].each do |dark|
|
$stderr.puts "precompile target: #{COLOR_SCHEME_STYLESHEET} #{theme.name} (#{scheme.name})"
|
||||||
mode = dark ? "dark" : "light"
|
Stylesheet::Manager::Builder.new(
|
||||||
$stderr.puts "precompile target: #{COLOR_SCHEME_STYLESHEET} #{theme.name} (#{scheme.name}) (#{mode})"
|
target: COLOR_SCHEME_STYLESHEET,
|
||||||
Stylesheet::Manager::Builder.new(
|
theme: theme,
|
||||||
target: COLOR_SCHEME_STYLESHEET,
|
color_scheme: scheme,
|
||||||
theme: theme,
|
manager: manager,
|
||||||
color_scheme: scheme,
|
).compile(force: true)
|
||||||
manager: manager,
|
|
||||||
dark:,
|
|
||||||
).compile(force: true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
clear_color_scheme_cache!
|
clear_color_scheme_cache!
|
||||||
|
@ -344,12 +339,7 @@ class Stylesheet::Manager
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def color_scheme_stylesheet_details(
|
def color_scheme_stylesheet_details(color_scheme_id = nil, fallback_to_base: true)
|
||||||
color_scheme_id = nil,
|
|
||||||
dark: false,
|
|
||||||
fallback_to_base: true,
|
|
||||||
include_dark_scheme: false
|
|
||||||
)
|
|
||||||
theme_id = @theme_id || SiteSetting.default_theme_id
|
theme_id = @theme_id || SiteSetting.default_theme_id
|
||||||
|
|
||||||
color_scheme = ColorScheme.find_by(id: color_scheme_id)
|
color_scheme = ColorScheme.find_by(id: color_scheme_id)
|
||||||
|
@ -361,10 +351,10 @@ class Stylesheet::Manager
|
||||||
|
|
||||||
target = COLOR_SCHEME_STYLESHEET.to_sym
|
target = COLOR_SCHEME_STYLESHEET.to_sym
|
||||||
current_hostname = Discourse.current_hostname
|
current_hostname = Discourse.current_hostname
|
||||||
cache_key = self.class.color_scheme_cache_key(color_scheme, theme_id, dark:)
|
cache_key = self.class.color_scheme_cache_key(color_scheme, theme_id)
|
||||||
|
|
||||||
cache.defer_get_set(cache_key) do
|
cache.defer_get_set(cache_key) do
|
||||||
stylesheet = { color_scheme_id: color_scheme.id, dark: }
|
stylesheet = { color_scheme_id: color_scheme.id }
|
||||||
|
|
||||||
theme = get_theme(theme_id)
|
theme = get_theme(theme_id)
|
||||||
|
|
||||||
|
@ -374,7 +364,6 @@ class Stylesheet::Manager
|
||||||
theme: get_theme(theme_id),
|
theme: get_theme(theme_id),
|
||||||
color_scheme: color_scheme,
|
color_scheme: color_scheme,
|
||||||
manager: self,
|
manager: self,
|
||||||
dark:,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
builder.compile unless File.exist?(builder.stylesheet_fullpath)
|
builder.compile unless File.exist?(builder.stylesheet_fullpath)
|
||||||
|
@ -382,27 +371,12 @@ class Stylesheet::Manager
|
||||||
href = builder.stylesheet_absolute_url
|
href = builder.stylesheet_absolute_url
|
||||||
stylesheet[:new_href] = href
|
stylesheet[:new_href] = href
|
||||||
|
|
||||||
if include_dark_scheme
|
|
||||||
dark_href =
|
|
||||||
self.color_scheme_stylesheet_link_tag_href(
|
|
||||||
color_scheme_id,
|
|
||||||
dark: true,
|
|
||||||
fallback_to_base: false,
|
|
||||||
)
|
|
||||||
|
|
||||||
stylesheet[:new_dark_href] = dark_href if dark_href
|
|
||||||
end
|
|
||||||
|
|
||||||
stylesheet.freeze
|
stylesheet.freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def color_scheme_stylesheet_preload_tag(
|
def color_scheme_stylesheet_preload_tag(color_scheme_id = nil, fallback_to_base: true)
|
||||||
color_scheme_id = nil,
|
stylesheet = color_scheme_stylesheet_details(color_scheme_id, fallback_to_base:)
|
||||||
dark: false,
|
|
||||||
fallback_to_base: true
|
|
||||||
)
|
|
||||||
stylesheet = color_scheme_stylesheet_details(color_scheme_id, dark:, fallback_to_base:)
|
|
||||||
|
|
||||||
return "" if !stylesheet
|
return "" if !stylesheet
|
||||||
|
|
||||||
|
@ -411,12 +385,8 @@ class Stylesheet::Manager
|
||||||
%[<link href="#{href}" rel="preload" as="style"/>].html_safe
|
%[<link href="#{href}" rel="preload" as="style"/>].html_safe
|
||||||
end
|
end
|
||||||
|
|
||||||
def color_scheme_stylesheet_link_tag_href(
|
def color_scheme_stylesheet_link_tag_href(color_scheme_id = nil, fallback_to_base: true)
|
||||||
color_scheme_id = nil,
|
stylesheet = color_scheme_stylesheet_details(color_scheme_id, fallback_to_base:)
|
||||||
dark: false,
|
|
||||||
fallback_to_base: true
|
|
||||||
)
|
|
||||||
stylesheet = color_scheme_stylesheet_details(color_scheme_id, dark:, fallback_to_base:)
|
|
||||||
|
|
||||||
return if !stylesheet
|
return if !stylesheet
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
class Stylesheet::Manager::Builder
|
class Stylesheet::Manager::Builder
|
||||||
attr_reader :theme
|
attr_reader :theme
|
||||||
|
|
||||||
def initialize(target: :desktop, theme: nil, color_scheme: nil, manager:, dark: false)
|
def initialize(target: :desktop, theme: nil, color_scheme: nil, manager:)
|
||||||
@target = target
|
@target = target
|
||||||
@theme = theme
|
@theme = theme
|
||||||
@color_scheme = color_scheme
|
@color_scheme = color_scheme
|
||||||
@manager = manager
|
@manager = manager
|
||||||
@dark = dark
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile(opts = {})
|
def compile(opts = {})
|
||||||
|
@ -47,7 +46,6 @@ class Stylesheet::Manager::Builder
|
||||||
source_map_file: source_map_url_relative_from_stylesheet,
|
source_map_file: source_map_url_relative_from_stylesheet,
|
||||||
color_scheme_id: @color_scheme&.id,
|
color_scheme_id: @color_scheme&.id,
|
||||||
load_paths: load_paths,
|
load_paths: load_paths,
|
||||||
dark: @dark,
|
|
||||||
strict_deprecations: %i[desktop mobile admin wizard].include?(@target),
|
strict_deprecations: %i[desktop mobile admin wizard].include?(@target),
|
||||||
)
|
)
|
||||||
rescue SassC::SyntaxError, SassC::NotRenderedError, DiscourseJsProcessor::TranspileError => e
|
rescue SassC::SyntaxError, SassC::NotRenderedError, DiscourseJsProcessor::TranspileError => e
|
||||||
|
@ -122,14 +120,13 @@ class Stylesheet::Manager::Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
def qualified_target
|
def qualified_target
|
||||||
dark_string = @dark ? "_dark" : ""
|
|
||||||
if is_theme?
|
if is_theme?
|
||||||
"#{@target}_#{theme&.id}"
|
"#{@target}_#{theme&.id}"
|
||||||
elsif @color_scheme
|
elsif @color_scheme
|
||||||
"#{@target}_#{scheme_slug}_#{@color_scheme&.id}_#{@theme&.id}#{dark_string}"
|
"#{@target}_#{scheme_slug}_#{@color_scheme&.id}_#{@theme&.id}"
|
||||||
else
|
else
|
||||||
scheme_string = theme&.color_scheme ? "_#{theme.color_scheme.id}" : ""
|
scheme_string = theme&.color_scheme ? "_#{theme.color_scheme.id}" : ""
|
||||||
"#{@target}#{scheme_string}#{dark_string}"
|
"#{@target}#{scheme_string}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -250,9 +247,8 @@ class Stylesheet::Manager::Builder
|
||||||
digest_string = "#{current_hostname}-"
|
digest_string = "#{current_hostname}-"
|
||||||
if cs
|
if cs
|
||||||
theme_color_defs = resolve_baked_field(:common, :color_definitions)
|
theme_color_defs = resolve_baked_field(:common, :color_definitions)
|
||||||
dark_string = @dark ? "-dark" : ""
|
|
||||||
digest_string +=
|
digest_string +=
|
||||||
"#{RailsMultisite::ConnectionManagement.current_db}-#{cs&.id}-#{cs&.version}-#{theme_color_defs}-#{Stylesheet::Manager.fs_asset_cachebuster}-#{fonts}#{dark_string}"
|
"#{RailsMultisite::ConnectionManagement.current_db}-#{cs&.id}-#{cs&.version}-#{theme_color_defs}-#{Stylesheet::Manager.fs_asset_cachebuster}-#{fonts}"
|
||||||
else
|
else
|
||||||
digest_string += "defaults-#{Stylesheet::Manager.fs_asset_cachebuster}-#{fonts}"
|
digest_string += "defaults-#{Stylesheet::Manager.fs_asset_cachebuster}-#{fonts}"
|
||||||
|
|
||||||
|
|
|
@ -956,20 +956,12 @@ RSpec.describe ApplicationHelper do
|
||||||
describe "#discourse_theme_color_meta_tags" do
|
describe "#discourse_theme_color_meta_tags" do
|
||||||
before do
|
before do
|
||||||
light = Fabricate(:color_scheme)
|
light = Fabricate(:color_scheme)
|
||||||
light.color_scheme_colors << ColorSchemeColor.new(
|
light.color_scheme_colors << ColorSchemeColor.new(name: "header_background", hex: "abcdef")
|
||||||
name: "header_background",
|
|
||||||
hex: "abcdef",
|
|
||||||
dark_hex: "fedcba",
|
|
||||||
)
|
|
||||||
light.save!
|
light.save!
|
||||||
helper.request.cookies["color_scheme_id"] = light.id
|
helper.request.cookies["color_scheme_id"] = light.id
|
||||||
|
|
||||||
dark = Fabricate(:color_scheme)
|
dark = Fabricate(:color_scheme)
|
||||||
dark.color_scheme_colors << ColorSchemeColor.new(
|
dark.color_scheme_colors << ColorSchemeColor.new(name: "header_background", hex: "defabc")
|
||||||
name: "header_background",
|
|
||||||
hex: "defabc",
|
|
||||||
dark_hex: "cbafed",
|
|
||||||
)
|
|
||||||
dark.save!
|
dark.save!
|
||||||
helper.request.cookies["dark_scheme_id"] = dark.id
|
helper.request.cookies["dark_scheme_id"] = dark.id
|
||||||
end
|
end
|
||||||
|
@ -989,17 +981,6 @@ RSpec.describe ApplicationHelper do
|
||||||
<meta name="theme-color" media="all" content="#abcdef">
|
<meta name="theme-color" media="all" content="#abcdef">
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when use_overhauled_theme_color_palette setting is true" do
|
|
||||||
before { SiteSetting.use_overhauled_theme_color_palette = true }
|
|
||||||
|
|
||||||
it "renders a light and dark theme-color meta tag using the light and dark palettes of the same color scheme record" do
|
|
||||||
expect(helper.discourse_theme_color_meta_tags).to eq(<<~HTML)
|
|
||||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#abcdef">
|
|
||||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#fedcba">
|
|
||||||
HTML
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#discourse_color_scheme_meta_tag" do
|
describe "#discourse_color_scheme_meta_tag" do
|
||||||
|
@ -1055,15 +1036,6 @@ RSpec.describe ApplicationHelper do
|
||||||
it "returns the value set in the dark_scheme_id cookie" do
|
it "returns the value set in the dark_scheme_id cookie" do
|
||||||
expect(helper.dark_scheme_id).to eq(dark_scheme.id)
|
expect(helper.dark_scheme_id).to eq(dark_scheme.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when use_overhauled_theme_color_palette is true" do
|
|
||||||
before { SiteSetting.use_overhauled_theme_color_palette = true }
|
|
||||||
|
|
||||||
it "returns the same value as #scheme_id" do
|
|
||||||
expect(helper.dark_scheme_id).to eq(helper.scheme_id)
|
|
||||||
expect(helper.scheme_id).to eq(light_scheme.id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#forced_light_mode?" do
|
describe "#forced_light_mode?" do
|
||||||
|
|
|
@ -688,81 +688,6 @@ RSpec.describe Stylesheet::Manager do
|
||||||
expect(href).to include("/stylesheets/color_definitions_funky-bunch_#{cs.id}_")
|
expect(href).to include("/stylesheets/color_definitions_funky-bunch_#{cs.id}_")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "generates the dark mode of a color scheme when the dark option is specified" do
|
|
||||||
scheme =
|
|
||||||
ColorScheme.create_from_base(
|
|
||||||
name: "Neutral",
|
|
||||||
base_scheme_id: ColorScheme::NAMES_TO_ID_MAP["Neutral"],
|
|
||||||
)
|
|
||||||
ColorSchemeRevisor.revise(
|
|
||||||
scheme,
|
|
||||||
colors: [{ name: "primary", hex: "CABFAF", dark_hex: "FAFCAB" }],
|
|
||||||
)
|
|
||||||
theme = Fabricate(:theme)
|
|
||||||
manager = manager(theme.id)
|
|
||||||
|
|
||||||
dark_stylesheet =
|
|
||||||
Stylesheet::Manager::Builder.new(
|
|
||||||
target: :color_definitions,
|
|
||||||
theme: theme,
|
|
||||||
color_scheme: scheme,
|
|
||||||
manager: manager,
|
|
||||||
dark: true,
|
|
||||||
).compile
|
|
||||||
light_stylesheet =
|
|
||||||
Stylesheet::Manager::Builder.new(
|
|
||||||
target: :color_definitions,
|
|
||||||
theme: theme,
|
|
||||||
color_scheme: scheme,
|
|
||||||
manager: manager,
|
|
||||||
).compile
|
|
||||||
|
|
||||||
expect(light_stylesheet).to include("--primary: #CABFAF;")
|
|
||||||
expect(light_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}")
|
|
||||||
expect(light_stylesheet).not_to include(
|
|
||||||
"color_definitions_neutral_#{scheme.id}_#{theme.id}_dark",
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(dark_stylesheet).to include("--primary: #FAFCAB;")
|
|
||||||
expect(dark_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}_dark")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "uses the light colors as fallback if the dark scheme doesn't define them" do
|
|
||||||
scheme =
|
|
||||||
ColorScheme.create_from_base(
|
|
||||||
name: "Neutral",
|
|
||||||
base_scheme_id: ColorScheme::NAMES_TO_ID_MAP["Neutral"],
|
|
||||||
)
|
|
||||||
ColorSchemeRevisor.revise(scheme, colors: [{ name: "primary", hex: "BACFAB", dark_hex: nil }])
|
|
||||||
theme = Fabricate(:theme)
|
|
||||||
manager = manager(theme.id)
|
|
||||||
|
|
||||||
dark_stylesheet =
|
|
||||||
Stylesheet::Manager::Builder.new(
|
|
||||||
target: :color_definitions,
|
|
||||||
theme: theme,
|
|
||||||
color_scheme: scheme,
|
|
||||||
manager: manager,
|
|
||||||
dark: true,
|
|
||||||
).compile
|
|
||||||
light_stylesheet =
|
|
||||||
Stylesheet::Manager::Builder.new(
|
|
||||||
target: :color_definitions,
|
|
||||||
theme: theme,
|
|
||||||
color_scheme: scheme,
|
|
||||||
manager: manager,
|
|
||||||
).compile
|
|
||||||
|
|
||||||
expect(light_stylesheet).to include("--primary: #BACFAB;")
|
|
||||||
expect(light_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}")
|
|
||||||
expect(light_stylesheet).not_to include(
|
|
||||||
"color_definitions_neutral_#{scheme.id}_#{theme.id}_dark",
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(dark_stylesheet).to include("--primary: #BACFAB;")
|
|
||||||
expect(dark_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}_dark")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "updates outputted colors when updating a color scheme" do
|
it "updates outputted colors when updating a color scheme" do
|
||||||
scheme =
|
scheme =
|
||||||
ColorScheme.create_from_base(
|
ColorScheme.create_from_base(
|
||||||
|
@ -1004,7 +929,7 @@ RSpec.describe Stylesheet::Manager do
|
||||||
|
|
||||||
# Ensure we force compile each theme only once
|
# Ensure we force compile each theme only once
|
||||||
expect(output.scan(/#{child_theme_with_css.name}/).length).to eq(2) # ltr/rtl
|
expect(output.scan(/#{child_theme_with_css.name}/).length).to eq(2) # ltr/rtl
|
||||||
expect(StylesheetCache.count).to eq(10) # (2 theme with rtl/ltr) + 8 color schemes (2 themes * 2 color schemes (1 base light palette + 1 theme scheme) * 2 (light and dark mode per scheme))
|
expect(StylesheetCache.count).to eq(6) # (2 theme with rtl/ltr) + 4 color schemes (2 themes * 2 color schemes (1 base light palette + 1 theme scheme))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "generates precompiled CSS - core and themes" do
|
it "generates precompiled CSS - core and themes" do
|
||||||
|
@ -1012,7 +937,7 @@ RSpec.describe Stylesheet::Manager do
|
||||||
Stylesheet::Manager.precompile_theme_css
|
Stylesheet::Manager.precompile_theme_css
|
||||||
|
|
||||||
results = StylesheetCache.pluck(:target)
|
results = StylesheetCache.pluck(:target)
|
||||||
expect(results.size).to eq(20) # 10 core targets + 2 theme (ltr/rtl) + 8 color schemes (light and dark mode per scheme)
|
expect(results.size).to eq(16) # 10 core targets + 2 theme (ltr/rtl) + 4 color schemes
|
||||||
|
|
||||||
expect(results.count { |target| target =~ /^common_theme_/ }).to eq(2) # ltr/rtl
|
expect(results.count { |target| target =~ /^common_theme_/ }).to eq(2) # ltr/rtl
|
||||||
end
|
end
|
||||||
|
@ -1024,7 +949,7 @@ RSpec.describe Stylesheet::Manager do
|
||||||
Stylesheet::Manager.precompile_theme_css
|
Stylesheet::Manager.precompile_theme_css
|
||||||
|
|
||||||
results = StylesheetCache.pluck(:target)
|
results = StylesheetCache.pluck(:target)
|
||||||
expect(results.size).to eq(24) # 10 core targets + 2 theme rtl/ltr + 12 color schemes (light and dark mode per scheme)
|
expect(results.size).to eq(18) # 10 core targets + 2 theme rtl/ltr + 6 color schemes
|
||||||
|
|
||||||
expect(results).to include("color_definitions_#{scheme1.name}_#{scheme1.id}_#{user_theme.id}")
|
expect(results).to include("color_definitions_#{scheme1.name}_#{scheme1.id}_#{user_theme.id}")
|
||||||
expect(results).to include(
|
expect(results).to include(
|
||||||
|
|
|
@ -1575,17 +1575,6 @@ HTML
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#owned_color_scheme" do
|
|
||||||
it "is destroyed when the theme is destroyed" do
|
|
||||||
scheme = Fabricate(:color_scheme, owning_theme: theme)
|
|
||||||
|
|
||||||
theme.destroy!
|
|
||||||
|
|
||||||
expect(ThemeColorScheme.exists?(color_scheme_id: scheme.id)).to eq(false)
|
|
||||||
expect(ColorScheme.unscoped.exists?(id: scheme.id)).to eq(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe ".include_basic_relations" do
|
describe ".include_basic_relations" do
|
||||||
fab!(:parent_theme_1) do
|
fab!(:parent_theme_1) do
|
||||||
Fabricate(
|
Fabricate(
|
||||||
|
@ -1705,51 +1694,6 @@ HTML
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#find_or_create_owned_color_palette" do
|
|
||||||
it "correctly associates a theme with its owned color palette" do
|
|
||||||
palette = theme.find_or_create_owned_color_palette
|
|
||||||
|
|
||||||
expect(palette.owning_theme).to eq(theme)
|
|
||||||
expect(theme.reload.owned_color_palette).to eq(palette)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "ensures owned color palette is not user selectable" do
|
|
||||||
palette = theme.find_or_create_owned_color_palette
|
|
||||||
|
|
||||||
expect(palette.user_selectable).to eq(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "copies colors from base or theme color scheme" do
|
|
||||||
theme_without_scheme = Fabricate(:theme, color_scheme: nil)
|
|
||||||
base_palette = theme_without_scheme.find_or_create_owned_color_palette
|
|
||||||
|
|
||||||
expect(base_palette.colors.length).to be > 0
|
|
||||||
expect(base_palette.colors.map(&:name).sort).to eq(ColorScheme.base.colors.map(&:name).sort)
|
|
||||||
|
|
||||||
custom_palette =
|
|
||||||
Fabricate(
|
|
||||||
:color_scheme,
|
|
||||||
colors: [ColorSchemeColor.new(name: "custom", hex: "11ccff", dark_hex: "ee9955")],
|
|
||||||
)
|
|
||||||
theme_with_scheme = Fabricate(:theme, color_scheme: custom_palette)
|
|
||||||
custom_palette = theme_with_scheme.find_or_create_owned_color_palette
|
|
||||||
|
|
||||||
expect(custom_palette.colors.length).to be > 0
|
|
||||||
expect(custom_palette.colors.map(&:name).sort).to eq(custom_palette.colors.map(&:name).sort)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns the existing palette if a race condition occurs and a theme-owned palette is created while it's executing" do
|
|
||||||
expect(theme.owned_color_palette).to eq(nil)
|
|
||||||
|
|
||||||
palette = Fabricate(:color_scheme)
|
|
||||||
ThemeColorScheme.create!(theme_id: theme.id, color_scheme_id: palette.id)
|
|
||||||
|
|
||||||
expect(theme.owned_color_palette).to eq(nil)
|
|
||||||
expect(theme.find_or_create_owned_color_palette.id).to eq(palette.id)
|
|
||||||
expect(theme.owned_color_palette).to eq(palette)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it "checks if fields can be updated for system themes" do
|
it "checks if fields can be updated for system themes" do
|
||||||
foundation_theme.update!(user_selectable: true)
|
foundation_theme.update!(user_selectable: true)
|
||||||
expect(foundation_theme.user_selectable).to be true
|
expect(foundation_theme.user_selectable).to be true
|
||||||
|
|
|
@ -45,45 +45,6 @@ RSpec.describe Admin::ColorSchemesController do
|
||||||
expect(scheme_colors[0]["name"]).to eq("primary")
|
expect(scheme_colors[0]["name"]).to eq("primary")
|
||||||
expect(scheme_colors[0]["hex"]).to eq(scheme.resolved_colors["primary"])
|
expect(scheme_colors[0]["hex"]).to eq(scheme.resolved_colors["primary"])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't list theme-owned color schemes" do
|
|
||||||
owned_scheme = Fabricate(:color_scheme, owning_theme: Fabricate(:theme))
|
|
||||||
scheme = Fabricate(:color_scheme)
|
|
||||||
|
|
||||||
get "/admin/color_schemes.json"
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
|
|
||||||
ids = response.parsed_body.map { |obj| obj["id"] }
|
|
||||||
expect(ids).to include(scheme.id)
|
|
||||||
expect(ids).not_to include(owned_scheme.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "filters out theme-owned color schemes when exclude_theme_owned is true" do
|
|
||||||
theme = Fabricate(:theme)
|
|
||||||
theme_owned_scheme = Fabricate(:color_scheme, name: "Theme Scheme")
|
|
||||||
|
|
||||||
ThemeColorScheme.create!(theme: theme, color_scheme: theme_owned_scheme)
|
|
||||||
|
|
||||||
owned_scheme = Fabricate(:color_scheme, name: "Directly Owned", theme: theme)
|
|
||||||
regular_scheme = Fabricate(:color_scheme, name: "Regular Scheme")
|
|
||||||
|
|
||||||
get "/admin/color_schemes.json", params: { exclude_theme_owned: true }
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
|
|
||||||
scheme_names = response.parsed_body.map { |scheme| scheme["name"] }
|
|
||||||
expect(scheme_names).to include("Regular Scheme")
|
|
||||||
expect(scheme_names).not_to include("Theme Scheme")
|
|
||||||
expect(scheme_names).not_to include("Directly Owned")
|
|
||||||
|
|
||||||
get "/admin/color_schemes.json"
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
scheme_names = response.parsed_body.map { |scheme| scheme["name"] }
|
|
||||||
expect(scheme_names).to include("Regular Scheme")
|
|
||||||
expect(scheme_names).to include("Directly Owned")
|
|
||||||
expect(scheme_names).not_to include("Theme Scheme")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples "color schemes inaccessible" do
|
shared_examples "color schemes inaccessible" do
|
||||||
|
@ -187,15 +148,6 @@ RSpec.describe Admin::ColorSchemesController do
|
||||||
expect(response.status).to eq(422)
|
expect(response.status).to eq(422)
|
||||||
expect(response.parsed_body["errors"]).to be_present
|
expect(response.parsed_body["errors"]).to be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't allow editing theme-owned schemes" do
|
|
||||||
color_scheme = Fabricate(:color_scheme, owning_theme: Fabricate(:theme))
|
|
||||||
|
|
||||||
put "/admin/color_schemes/#{color_scheme.id}.json", params: valid_params
|
|
||||||
expect(response.status).to eq(404)
|
|
||||||
color_scheme.reload
|
|
||||||
expect(color_scheme.name).not_to eq(valid_params[:color_scheme][:name])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples "color scheme update not allowed" do
|
shared_examples "color scheme update not allowed" do
|
||||||
|
@ -232,14 +184,6 @@ RSpec.describe Admin::ColorSchemesController do
|
||||||
}.by(-1)
|
}.by(-1)
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't allow deleting theme-owned schemes" do
|
|
||||||
color_scheme = Fabricate(:color_scheme, owning_theme: Fabricate(:theme))
|
|
||||||
|
|
||||||
delete "/admin/color_schemes/#{color_scheme.id}.json"
|
|
||||||
expect(response.status).to eq(404)
|
|
||||||
expect(color_scheme.reload).to be_persisted
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples "color scheme deletion not allowed" do
|
shared_examples "color scheme deletion not allowed" do
|
||||||
|
|
|
@ -1690,98 +1690,6 @@ RSpec.describe Admin::ThemesController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#change_colors" do
|
|
||||||
fab!(:theme)
|
|
||||||
|
|
||||||
before { sign_in(admin) }
|
|
||||||
|
|
||||||
context "with valid parameters" do
|
|
||||||
it "creates a theme-owned color palette if one doesn't exist" do
|
|
||||||
expect(theme.owned_color_palette).to be_nil
|
|
||||||
|
|
||||||
put "/admin/themes/#{theme.id}/change-colors.json",
|
|
||||||
params: {
|
|
||||||
colors: [{ name: "primary", hex: "ff0000", dark_hex: "0000ff" }],
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
|
|
||||||
theme.reload
|
|
||||||
expect(theme.owned_color_palette.id).to eq(response.parsed_body["id"])
|
|
||||||
|
|
||||||
color = theme.owned_color_palette.colors.find_by(name: "primary")
|
|
||||||
expect(color.hex).to eq("ff0000")
|
|
||||||
expect(color.dark_hex).to eq("0000ff")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "updates an existing theme-owned color palette" do
|
|
||||||
palette = theme.find_or_create_owned_color_palette
|
|
||||||
primary_color = palette.colors.find_by(name: "primary")
|
|
||||||
secondary_color = palette.colors.find_by(name: "secondary")
|
|
||||||
|
|
||||||
original_secondary_hex = secondary_color.hex
|
|
||||||
original_secondary_dark_hex = secondary_color.dark_hex
|
|
||||||
|
|
||||||
put "/admin/themes/#{theme.id}/change-colors.json",
|
|
||||||
params: {
|
|
||||||
colors: [{ name: "primary", hex: "aabbcc", dark_hex: "ccddee" }],
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
|
|
||||||
primary_color.reload
|
|
||||||
secondary_color.reload
|
|
||||||
|
|
||||||
expect(primary_color.hex).to eq("aabbcc")
|
|
||||||
expect(primary_color.dark_hex).to eq("ccddee")
|
|
||||||
|
|
||||||
expect(secondary_color.hex).to eq(original_secondary_hex)
|
|
||||||
expect(secondary_color.dark_hex).to eq(original_secondary_dark_hex)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns the updated palette in the response" do
|
|
||||||
put "/admin/themes/#{theme.id}/change-colors.json",
|
|
||||||
params: {
|
|
||||||
colors: [{ name: "primary", hex: "abcdef", dark_hex: "fedcba" }],
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
json = response.parsed_body
|
|
||||||
|
|
||||||
expect(json["colors"]).to be_present
|
|
||||||
primary_color = json["colors"].find { |c| c["name"] == "primary" }
|
|
||||||
expect(primary_color["hex"]).to eq("abcdef")
|
|
||||||
expect(primary_color["dark_hex"]).to eq("fedcba")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "with invalid parameters" do
|
|
||||||
it "returns 404 for non-existent theme" do
|
|
||||||
max_id = (Theme.maximum(:id) || 0) + 1
|
|
||||||
|
|
||||||
put "/admin/themes/#{max_id}/change-colors.json",
|
|
||||||
params: {
|
|
||||||
colors: [{ name: "primary", hex: "ff0000", dark_hex: "0000ff" }],
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when system theme" do
|
|
||||||
before { theme.update_columns(id: -10) }
|
|
||||||
|
|
||||||
it "returns invalid access" do
|
|
||||||
put "/admin/themes/#{theme.id}/change-colors.json",
|
|
||||||
params: {
|
|
||||||
colors: [{ name: "primary", hex: "ff0000", dark_hex: "0000ff" }],
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(response.status).to eq(403)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#show" do
|
describe "#show" do
|
||||||
let(:theme) { Fabricate(:theme) }
|
let(:theme) { Fabricate(:theme) }
|
||||||
|
|
||||||
|
|
|
@ -189,8 +189,6 @@ describe "Admin Color Palette Config Area Page", type: :system do
|
||||||
|
|
||||||
color_scheme.colors.each do |color|
|
color_scheme.colors.each do |color|
|
||||||
expect(color.hex).to eq(clipboard_scheme["light"][color.name])
|
expect(color.hex).to eq(clipboard_scheme["light"][color.name])
|
||||||
next if color.dark_hex.nil?
|
|
||||||
expect(color.dark_hex).to eq(clipboard_scheme["dark"][color.name])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -268,95 +268,6 @@ describe "Admin Customize Themes", type: :system do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "theme color palette editor" do
|
|
||||||
before { SiteSetting.use_overhauled_theme_color_palette = true }
|
|
||||||
|
|
||||||
it "allows editing colors of theme-owned palette" do
|
|
||||||
theme_page.visit(theme.id)
|
|
||||||
theme_page.colors_tab.click
|
|
||||||
|
|
||||||
expect(theme_page).to have_current_path("/admin/customize/themes/#{theme.id}/colors")
|
|
||||||
|
|
||||||
theme_page.color_palette_editor.change_color("primary", "#ff000e")
|
|
||||||
|
|
||||||
expect(theme_page.changes_banner).to be_visible
|
|
||||||
theme_page.changes_banner.click_save
|
|
||||||
|
|
||||||
page.refresh
|
|
||||||
expect(theme_page).to have_colors_tab_active
|
|
||||||
|
|
||||||
updated_color = theme_page.color_palette_editor.get_color_value("primary")
|
|
||||||
expect(updated_color).to eq("#ff000e")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "allows discarding unsaved color changes" do
|
|
||||||
theme_page.visit(theme.id)
|
|
||||||
theme_page.colors_tab.click
|
|
||||||
|
|
||||||
original_hex = theme_page.color_palette_editor.get_color_value("primary")
|
|
||||||
|
|
||||||
theme_page.color_palette_editor.change_color("primary", "#10ff00")
|
|
||||||
|
|
||||||
theme_page.changes_banner.click_discard
|
|
||||||
|
|
||||||
expect(theme_page.changes_banner).to be_hidden
|
|
||||||
|
|
||||||
updated_color = theme_page.color_palette_editor.get_color_value("primary")
|
|
||||||
expect(updated_color).to eq(original_hex)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "shows count of unsaved colors" do
|
|
||||||
theme_page.visit(theme.id)
|
|
||||||
theme_page.colors_tab.click
|
|
||||||
|
|
||||||
theme_page.color_palette_editor.change_color("primary", "#eeff80")
|
|
||||||
|
|
||||||
expect(theme_page.changes_banner).to have_label(
|
|
||||||
I18n.t("admin_js.admin.customize.theme.unsaved_colors", count: 1),
|
|
||||||
)
|
|
||||||
|
|
||||||
theme_page.color_palette_editor.change_color("secondary", "#ee30ab")
|
|
||||||
expect(theme_page.changes_banner).to have_label(
|
|
||||||
I18n.t("admin_js.admin.customize.theme.unsaved_colors", count: 2),
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "doesn't show colors tab or DPageHeader for components" do
|
|
||||||
component = Fabricate(:theme, component: true)
|
|
||||||
theme_page.visit(component.id)
|
|
||||||
expect(theme_page.header).to be_hidden
|
|
||||||
|
|
||||||
expect(theme_page).to have_no_color_scheme_selector
|
|
||||||
end
|
|
||||||
|
|
||||||
it "shows a confirmation dialog when leaving the page with unsaved changes" do
|
|
||||||
theme_page.visit(theme.id)
|
|
||||||
theme_page.colors_tab.click
|
|
||||||
|
|
||||||
theme_page.color_palette_editor.change_color("primary", "#eeff80")
|
|
||||||
|
|
||||||
expect(theme_page.changes_banner).to be_visible
|
|
||||||
|
|
||||||
find("#site-logo").click
|
|
||||||
|
|
||||||
expect(dialog).to be_open
|
|
||||||
expect(page).to have_content(
|
|
||||||
I18n.t("admin_js.admin.customize.theme.unsaved_colors_leave_route_confirmation"),
|
|
||||||
)
|
|
||||||
|
|
||||||
dialog.click_no
|
|
||||||
|
|
||||||
expect(dialog).to be_closed
|
|
||||||
expect(page).to have_current_path("/admin/customize/themes/#{theme.id}/colors")
|
|
||||||
|
|
||||||
find("#site-logo").click
|
|
||||||
expect(dialog).to be_open
|
|
||||||
|
|
||||||
dialog.click_yes
|
|
||||||
expect(page).to have_current_path("/")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "editing theme site settings" do
|
describe "editing theme site settings" do
|
||||||
it "shows all themeable site settings and allows editing values" do
|
it "shows all themeable site settings and allows editing values" do
|
||||||
theme_page.visit(theme.id)
|
theme_page.visit(theme.id)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue