diff --git a/app/assets/javascripts/admin/addon/components/schema-theme-setting/editor.gjs b/app/assets/javascripts/admin/addon/components/schema-theme-setting/editor.gjs
index c7660b23d90..bbdbf4efc14 100644
--- a/app/assets/javascripts/admin/addon/components/schema-theme-setting/editor.gjs
+++ b/app/assets/javascripts/admin/addon/components/schema-theme-setting/editor.gjs
@@ -5,8 +5,10 @@ import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { LinkTo } from "@ember/routing";
import { service } from "@ember/service";
+import { gt } from "truth-helpers";
import DButton from "discourse/components/d-button";
import { popupAjaxError } from "discourse/lib/ajax-error";
+import dIcon from "discourse-common/helpers/d-icon";
import i18n from "discourse-common/helpers/i18n";
import { cloneJSON } from "discourse-common/lib/object";
import I18n from "discourse-i18n";
@@ -77,7 +79,7 @@ export default class SchemaThemeSettingEditor extends Component {
const subtree = new Tree();
subtree.propertyName = childObjectsProperty.name;
- data[index][childObjectsProperty.name].forEach(
+ data[index][childObjectsProperty.name]?.forEach(
(childObj, childIndex) => {
subtree.nodes.push(
new Node({
@@ -224,68 +226,99 @@ export default class SchemaThemeSettingEditor extends Component {
}
-
- {{#if this.backButtonText}}
-
- {{/if}}
-
-
-
-
-
-
- {{i18n "cancel"}}
-
}
diff --git a/app/assets/javascripts/admin/addon/templates/customize-themes-show-schema.hbs b/app/assets/javascripts/admin/addon/templates/customize-themes-show-schema.hbs
index 7ae2afb44fb..d8b3e2eaaad 100644
--- a/app/assets/javascripts/admin/addon/templates/customize-themes-show-schema.hbs
+++ b/app/assets/javascripts/admin/addon/templates/customize-themes-show-schema.hbs
@@ -1,3 +1,12 @@
+
+
{
- const li = container.querySelector(".parent.node");
- const active = li.classList.contains("active");
- const children = [...container.querySelectorAll(".node.child")].map(
- (child) => {
- return {
- text: child.textContent.trim(),
- element: child,
- };
- }
+ this.nodes = [
+ ...queryAll(
+ ".schema-theme-setting-editor__tree .schema-theme-setting-editor__tree-node.--parent"
+ ),
+ ].map((container, index) => {
+ const li = container;
+ const active = li.classList.contains("--active");
+
+ const children = [
+ ...queryAll(
+ `.schema-theme-setting-editor__tree-node.--child[data-test-parent-index="${index}"]:not(.--heading)`
+ ),
+ ].map((child) => {
+ return {
+ element: child,
+ textElement: child.querySelector(
+ ".schema-theme-setting-editor__tree-node-text"
+ ),
+ };
+ });
+
+ const childrenHeaderElement = query(
+ `.schema-theme-setting-editor__tree-node.--heading[data-test-parent-index="${index}"]`
);
return {
- text: li.textContent.trim(),
active,
children,
+ childrenHeaderElement,
element: li,
+ textElement: li.querySelector(
+ ".schema-theme-setting-editor__tree-node-text"
+ ),
};
});
}
@@ -85,6 +101,8 @@ module(
const tree = new TreeFromDOM();
assert.true(tree.nodes[0].active);
+ assert.dom(tree.nodes[0].childrenHeaderElement).hasText("children");
+
assert.strictEqual(
tree.nodes[0].children.length,
2,
@@ -127,12 +145,12 @@ module(
const tree = new TreeFromDOM();
assert.strictEqual(tree.nodes.length, 2);
- assert.strictEqual(tree.nodes[0].text, "item 1");
+ assert.dom(tree.nodes[0].textElement).hasText("item 1");
assert.strictEqual(tree.nodes[0].children.length, 2);
- assert.strictEqual(tree.nodes[0].children[0].text, "child 1-1");
- assert.strictEqual(tree.nodes[0].children[1].text, "child 1-2");
+ assert.dom(tree.nodes[0].children[0].textElement).hasText("child 1-1");
+ assert.dom(tree.nodes[0].children[1].textElement).hasText("child 1-2");
- assert.strictEqual(tree.nodes[1].text, "item 2");
+ assert.dom(tree.nodes[1].textElement).hasText("item 2");
assert.strictEqual(tree.nodes[1].children.length, 0);
await click(tree.nodes[1].element);
@@ -140,35 +158,47 @@ module(
tree.refresh();
assert.strictEqual(tree.nodes.length, 2);
- assert.strictEqual(tree.nodes[0].text, "item 1");
+ assert.dom(tree.nodes[0].textElement).hasText("item 1");
assert.false(tree.nodes[0].active);
assert.strictEqual(tree.nodes[0].children.length, 0);
- assert.strictEqual(tree.nodes[1].text, "item 2");
+ assert.dom(tree.nodes[1].textElement).hasText("item 2");
assert.true(tree.nodes[1].active);
assert.strictEqual(tree.nodes[1].children.length, 3);
- assert.strictEqual(tree.nodes[1].children[0].text, "child 2-1");
- assert.strictEqual(tree.nodes[1].children[1].text, "child 2-2");
- assert.strictEqual(tree.nodes[1].children[2].text, "child 2-3");
+ assert.dom(tree.nodes[1].children[0].textElement).hasText("child 2-1");
+ assert.dom(tree.nodes[1].children[1].textElement).hasText("child 2-2");
+ assert.dom(tree.nodes[1].children[2].textElement).hasText("child 2-3");
await click(tree.nodes[1].children[1].element);
tree.refresh();
assert.strictEqual(tree.nodes.length, 3);
- assert.strictEqual(tree.nodes[0].text, "child 2-1");
+ assert.dom(tree.nodes[0].textElement).hasText("child 2-1");
assert.false(tree.nodes[0].active);
assert.strictEqual(tree.nodes[0].children.length, 0);
- assert.strictEqual(tree.nodes[1].text, "child 2-2");
+ assert.dom(tree.nodes[1].textElement).hasText("child 2-2");
assert.true(tree.nodes[1].active);
assert.strictEqual(tree.nodes[1].children.length, 4);
- assert.strictEqual(tree.nodes[1].children[0].text, "grandchild 2-2-1");
- assert.strictEqual(tree.nodes[1].children[1].text, "grandchild 2-2-2");
- assert.strictEqual(tree.nodes[1].children[2].text, "grandchild 2-2-3");
- assert.strictEqual(tree.nodes[1].children[3].text, "grandchild 2-2-4");
- assert.strictEqual(tree.nodes[2].text, "child 2-3");
+ assert
+ .dom(tree.nodes[1].children[0].textElement)
+ .hasText("grandchild 2-2-1");
+
+ assert
+ .dom(tree.nodes[1].children[1].textElement)
+ .hasText("grandchild 2-2-2");
+
+ assert
+ .dom(tree.nodes[1].children[2].textElement)
+ .hasText("grandchild 2-2-3");
+
+ assert
+ .dom(tree.nodes[1].children[3].textElement)
+ .hasText("grandchild 2-2-4");
+
+ assert.dom(tree.nodes[2].textElement).hasText("child 2-3");
assert.false(tree.nodes[2].active);
assert.strictEqual(tree.nodes[2].children.length, 0);
@@ -178,19 +208,19 @@ module(
assert.strictEqual(tree.nodes.length, 4);
- assert.strictEqual(tree.nodes[0].text, "grandchild 2-2-1");
+ assert.dom(tree.nodes[0].textElement).hasText("grandchild 2-2-1");
assert.false(tree.nodes[0].active);
assert.strictEqual(tree.nodes[0].children.length, 0);
- assert.strictEqual(tree.nodes[1].text, "grandchild 2-2-2");
+ assert.dom(tree.nodes[1].textElement).hasText("grandchild 2-2-2");
assert.true(tree.nodes[1].active);
assert.strictEqual(tree.nodes[1].children.length, 0);
- assert.strictEqual(tree.nodes[2].text, "grandchild 2-2-3");
+ assert.dom(tree.nodes[2].textElement).hasText("grandchild 2-2-3");
assert.false(tree.nodes[2].active);
assert.strictEqual(tree.nodes[2].children.length, 0);
- assert.strictEqual(tree.nodes[3].text, "grandchild 2-2-4");
+ assert.dom(tree.nodes[3].textElement).hasText("grandchild 2-2-4");
assert.false(tree.nodes[3].active);
assert.strictEqual(tree.nodes[3].children.length, 0);
});
@@ -202,32 +232,36 @@ module(
);
- assert.dom(".back-button").doesNotExist();
+ assert
+ .dom(".schema-theme-setting-editor__tree-node--back-btn")
+ .doesNotExist();
const tree = new TreeFromDOM();
await click(tree.nodes[0].children[0].element);
- assert.dom(".back-button").exists();
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").exists();
tree.refresh();
- assert.strictEqual(tree.nodes[0].text, "child 1-1");
+ assert.dom(tree.nodes[0].textElement).hasText("child 1-1");
await click(tree.nodes[0].children[0].element);
tree.refresh();
- assert.strictEqual(tree.nodes[0].text, "grandchild 1-1-1");
- assert.dom(".back-button").exists();
+ assert.dom(tree.nodes[0].textElement).hasText("grandchild 1-1-1");
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").exists();
- await click(".back-button");
+ await click(".schema-theme-setting-editor__tree-node--back-btn");
tree.refresh();
- assert.strictEqual(tree.nodes[0].text, "child 1-1");
- assert.dom(".back-button").exists();
+ assert.dom(tree.nodes[0].textElement).hasText("child 1-1");
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").exists();
- await click(".back-button");
+ await click(".schema-theme-setting-editor__tree-node--back-btn");
tree.refresh();
- assert.strictEqual(tree.nodes[0].text, "item 1");
- assert.dom(".back-button").doesNotExist();
+ assert.dom(tree.nodes[0].textElement).hasText("item 1");
+ assert
+ .dom(".schema-theme-setting-editor__tree-node--back-btn")
+ .doesNotExist();
});
test("the back button navigates to the index of the active element at the previous level", async function (assert) {
@@ -243,16 +277,16 @@ module(
tree.refresh();
await click(tree.nodes[1].children[1].element);
- await click(".back-button");
+ await click(".schema-theme-setting-editor__tree-node--back-btn");
tree.refresh();
assert.strictEqual(tree.nodes.length, 2);
- assert.strictEqual(tree.nodes[0].text, "item 1");
+ assert.dom(tree.nodes[0].textElement).hasText("item 1");
assert.false(tree.nodes[0].active);
assert.strictEqual(tree.nodes[0].children.length, 0);
- assert.strictEqual(tree.nodes[1].text, "item 2");
+ assert.dom(tree.nodes[1].textElement).hasText("item 2");
assert.true(tree.nodes[1].active);
assert.strictEqual(tree.nodes[1].children.length, 3);
});
@@ -270,7 +304,7 @@ module(
tree.refresh();
await click(tree.nodes[1].children[1].element);
- assert.dom(".back-button").hasText(
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").hasText(
I18n.t("admin.customize.theme.schema.back_button", {
name: "item 2",
})
@@ -279,15 +313,15 @@ module(
tree.refresh();
await click(tree.nodes[1].children[0].element);
- assert.dom(".back-button").hasText(
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").hasText(
I18n.t("admin.customize.theme.schema.back_button", {
name: "child 2-2",
})
);
- await click(".back-button");
+ await click(".schema-theme-setting-editor__tree-node--back-btn");
- assert.dom(".back-button").hasText(
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").hasText(
I18n.t("admin.customize.theme.schema.back_button", {
name: "item 2",
})
@@ -377,11 +411,12 @@ module(
assert.dom(inputFields.fields.text.labelElement).hasText("text");
assert.dom(inputFields.fields.url.labelElement).hasText("url");
assert.dom(inputFields.fields.icon.labelElement).hasText("icon");
-
assert.dom(inputFields.fields.text.inputElement).hasValue("About");
+
assert
.dom(inputFields.fields.url.inputElement)
.hasValue("https://example.com/about");
+
assert.dom(inputFields.fields.icon.inputElement).hasValue("asterisk");
});
@@ -657,16 +692,16 @@ module(
const tree = new TreeFromDOM();
- assert.dom(tree.nodes[0].element).hasText("section 1");
- assert.dom(tree.nodes[0].children[0].element).hasText("link 1");
- assert.dom(tree.nodes[0].children[1].element).hasText("link 2");
- assert.dom(tree.nodes[1].element).hasText("section 2");
+ assert.dom(tree.nodes[0].textElement).hasText("section 1");
+ assert.dom(tree.nodes[0].children[0].textElement).hasText("link 1");
+ assert.dom(tree.nodes[0].children[1].textElement).hasText("link 2");
+ assert.dom(tree.nodes[1].textElement).hasText("section 2");
await click(tree.nodes[1].element);
tree.refresh();
- assert.dom(tree.nodes[1].children[0].element).hasText("link 1");
+ assert.dom(tree.nodes[1].children[0].textElement).hasText("link 1");
});
test("identifier field instantly updates in the navigation tree when the input field is changed", async function (assert) {
@@ -684,7 +719,9 @@ module(
"nice section is really nice"
);
- assert.dom(tree.nodes[0].element).hasText("nice section is really nice");
+ assert
+ .dom(tree.nodes[0].textElement)
+ .hasText("nice section is really nice");
await click(tree.nodes[0].children[0].element);
@@ -696,7 +733,9 @@ module(
"Security instead of Privacy"
);
- assert.dom(tree.nodes[0].element).hasText("Security instead of Privacy");
+ assert
+ .dom(tree.nodes[0].textElement)
+ .hasText("Security instead of Privacy");
});
test("edits are remembered when navigating between levels", async function (assert) {
@@ -729,26 +768,26 @@ module(
tree.refresh();
inputFields.refresh();
- assert.dom(".back-button").hasText(
+ assert.dom(".schema-theme-setting-editor__tree-node--back-btn").hasText(
I18n.t("admin.customize.theme.schema.back_button", {
name: "cool section is no longer cool",
})
);
await fillIn(inputFields.fields.text.inputElement, "Talk to us");
-
- await click(".back-button");
+ await click(".schema-theme-setting-editor__tree-node--back-btn");
tree.refresh();
inputFields.refresh();
- assert.dom(tree.nodes[0].element).hasText("changed section name");
+ assert.dom(tree.nodes[0].textElement).hasText("changed section name");
+
assert
- .dom(tree.nodes[1].element)
+ .dom(tree.nodes[1].textElement)
.hasText("cool section is no longer cool");
- assert.dom(tree.nodes[1].children[0].element).hasText("About");
- assert.dom(tree.nodes[1].children[1].element).hasText("Talk to us");
+ assert.dom(tree.nodes[1].children[0].textElement).hasText("About");
+ assert.dom(tree.nodes[1].children[1].textElement).hasText("Talk to us");
assert
.dom(inputFields.fields.name.inputElement)
diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss
index 441e88c6e16..1eb9c6a4062 100644
--- a/app/assets/stylesheets/common/admin/admin_base.scss
+++ b/app/assets/stylesheets/common/admin/admin_base.scss
@@ -1068,6 +1068,8 @@ a.inline-editable-field {
@import "common/admin/admin_intro";
@import "common/admin/admin_emojis";
@import "common/admin/mini_profiler";
+@import "common/admin/schema_theme_setting_editor";
+@import "common/admin/customize_themes_show_schema";
// EXPERIMENTAL: Revamped admin styles, probably can be split up later down the line.
@import "common/admin/admin_revamp";
diff --git a/app/assets/stylesheets/common/admin/customize_themes_show_schema.scss b/app/assets/stylesheets/common/admin/customize_themes_show_schema.scss
new file mode 100644
index 00000000000..47d4fe005dc
--- /dev/null
+++ b/app/assets/stylesheets/common/admin/customize_themes_show_schema.scss
@@ -0,0 +1,3 @@
+.customize-themes-show-schema__header {
+ margin-bottom: 1em;
+}
diff --git a/app/assets/stylesheets/common/admin/schema_theme_setting_editor.scss b/app/assets/stylesheets/common/admin/schema_theme_setting_editor.scss
new file mode 100644
index 00000000000..8d0df542b0c
--- /dev/null
+++ b/app/assets/stylesheets/common/admin/schema_theme_setting_editor.scss
@@ -0,0 +1,76 @@
+.schema-theme-setting-editor {
+ display: grid;
+ grid-template-columns: 0.2fr 0.8fr;
+
+ &__navigation {
+ margin-right: 2em;
+
+ ul {
+ list-style: none;
+ }
+
+ .schema-theme-setting-editor__tree {
+ margin: 0;
+
+ .schema-theme-setting-editor__tree-node--back-btn {
+ cursor: pointer;
+ width: 100%;
+ text-align: left;
+
+ .schema-theme-setting-editor__tree-node-text {
+ .d-icon {
+ margin-left: 0;
+ margin-right: 0.5em;
+ }
+ }
+ }
+
+ .schema-theme-setting-editor__tree-node-text {
+ padding: 0.5em;
+ color: var(--primary);
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ .d-icon {
+ margin-left: auto;
+ font-size: var(--font-down-3);
+ color: var(--primary-500);
+ }
+ }
+
+ .schema-theme-setting-editor__tree-node {
+ cursor: pointer;
+
+ &.--active {
+ > .schema-theme-setting-editor__tree-node-text {
+ background-color: var(--tertiary);
+ color: var(--secondary);
+
+ .d-icon {
+ color: var(--secondary);
+ }
+ }
+ }
+
+ &.--child {
+ margin-left: 0.5em;
+ border-left: 1.5px solid var(--primary-200);
+ }
+
+ &.--heading {
+ cursor: default;
+ margin-top: 0.5em;
+ font-weight: bold;
+ }
+ }
+ }
+ }
+
+ &__fields {
+ }
+
+ &__footer {
+ margin-top: 0.5em;
+ }
+}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index f4c5e5313c8..e724d53c0ee 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -5643,6 +5643,7 @@ en:
inactive_filter: "Inactive"
updates_available_filter: "Updates Available"
schema:
+ title: "Edit %{name} setting"
back_button: "Back to %{name}"
colors:
select_base:
diff --git a/spec/system/page_objects/pages/admin_objects_theme_setting_editor.rb b/spec/system/page_objects/pages/admin_objects_theme_setting_editor.rb
index 7aef609d92c..a4f26266ac0 100644
--- a/spec/system/page_objects/pages/admin_objects_theme_setting_editor.rb
+++ b/spec/system/page_objects/pages/admin_objects_theme_setting_editor.rb
@@ -17,7 +17,11 @@ module PageObjects
end
def click_link(name)
- find(".schema-editor-navigation .node", text: name).click
+ find(
+ ".schema-theme-setting-editor__navigation .schema-theme-setting-editor__tree-node",
+ text: name,
+ ).click
+
self
end