From ec63f3e7826a95a5fb2f6b6cc6e7e3fb99f48c46 Mon Sep 17 00:00:00 2001 From: Osama Sayegh Date: Wed, 20 Mar 2024 08:41:12 +0300 Subject: [PATCH] FEATURE: Buttons to add and remove objects for schema theme settings (#26256) Continue from https://github.com/discourse/discourse/pull/25673. This feature adds new buttons for schema theme settings that add/remove objects from lists. --- .../schema-theme-setting/editor.gjs | 93 ++++++++- .../editor-test.gjs | 185 ++++++++++++++++++ .../admin/schema_theme_setting_editor.scss | 6 + 3 files changed, 277 insertions(+), 7 deletions(-) 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 bbdbf4efc14..0edeea5ef57 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 @@ -33,8 +33,10 @@ class Node { } class Tree { - propertyName = null; - nodes = []; + @tracked nodes = []; + data = []; + propertyName; + schema; } export default class SchemaThemeSettingEditor extends Component { @@ -52,11 +54,16 @@ export default class SchemaThemeSettingEditor extends Component { let schema = this.schema; let data = this.data; let tree = new Tree(); + tree.data = data; + tree.schema = schema; for (const point of this.history) { - tree.propertyName = point.propertyName; - data = data[point.node.index][point.propertyName]; + data = data[point.parentNode.index][point.propertyName]; schema = schema.properties[point.propertyName].schema; + + tree.propertyName = point.propertyName; + tree.schema = point.node.schema; + tree.data = data; } data.forEach((object, index) => { @@ -78,6 +85,8 @@ export default class SchemaThemeSettingEditor extends Component { for (const childObjectsProperty of childObjectsProperties) { const subtree = new Tree(); subtree.propertyName = childObjectsProperty.name; + subtree.schema = childObjectsProperty.schema; + subtree.data = data[index][childObjectsProperty.name]; data[index][childObjectsProperty.name]?.forEach( (childObj, childIndex) => { @@ -116,6 +125,10 @@ export default class SchemaThemeSettingEditor extends Component { const node = this.activeNode; const list = []; + if (!node) { + return list; + } + for (const [name, spec] of Object.entries(node.schema.properties)) { if (spec.type === "objects") { continue; @@ -174,7 +187,8 @@ export default class SchemaThemeSettingEditor extends Component { onChildClick(node, tree, parentNode) { this.history.push({ propertyName: tree.propertyName, - node: parentNode, + parentNode, + node, }); this.backButtonText = I18n.t("admin.customize.theme.schema.back_button", { @@ -187,11 +201,11 @@ export default class SchemaThemeSettingEditor extends Component { @action backButtonClick() { const historyPoint = this.history.pop(); - this.activeIndex = historyPoint.node.index; + this.activeIndex = historyPoint.parentNode.index; if (this.history.length > 0) { this.backButtonText = I18n.t("admin.customize.theme.schema.back_button", { - name: this.history[this.history.length - 1].node.text, + name: this.history[this.history.length - 1].parentNode.text, }); } else { this.backButtonText = null; @@ -207,6 +221,26 @@ export default class SchemaThemeSettingEditor extends Component { this.activeNode.object[field.name] = newVal; } + @action + addItem(tree) { + const schema = tree.schema; + const node = this.createNodeFromSchema(schema, tree); + tree.data.push(node.object); + tree.nodes = [...tree.nodes, node]; + } + + @action + removeItem() { + const data = this.activeNode.parentTree.data; + data.splice(this.activeIndex, 1); + this.tree.nodes = this.tree.nodes.filter((n, i) => i !== this.activeIndex); + if (data.length > 0) { + this.activeIndex = Math.max(this.activeIndex - 1, 0); + } else if (this.history.length > 0) { + this.backButtonClick(); + } + } + fieldDescription(fieldName) { const descriptions = this.args.setting.objects_schema_property_descriptions; @@ -225,6 +259,30 @@ export default class SchemaThemeSettingEditor extends Component { return descriptions[key]; } + createNodeFromSchema(schema, tree) { + const object = {}; + const index = tree.nodes.length; + const defaultName = `${schema.name} ${index + 1}`; + + if (schema.identifier) { + object[schema.identifier] = defaultName; + } + + for (const [name, spec] of Object.entries(schema.properties)) { + if (spec.type === "objects") { + object[name] = []; + } + } + + return new Node({ + schema, + object, + index, + text: defaultName, + parentTree: tree, + }); + } +