mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Add save button to editing typed objects theme setting route (#26133)
Why this change? This is still a work in progress but allows objects type theme setting to be saved.
This commit is contained in:
committed by
GitHub
parent
a24c16c911
commit
5b8652965a
@@ -3,7 +3,12 @@ import { cached, tracked } from "@glimmer/tracking";
|
|||||||
import { fn } from "@ember/helper";
|
import { fn } from "@ember/helper";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
|
import { LinkTo } from "@ember/routing";
|
||||||
|
import { service } from "@ember/service";
|
||||||
import DButton from "discourse/components/d-button";
|
import DButton from "discourse/components/d-button";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
import i18n from "discourse-common/helpers/i18n";
|
||||||
|
import { cloneJSON } from "discourse-common/lib/object";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
import FieldInput from "./field";
|
import FieldInput from "./field";
|
||||||
|
|
||||||
@@ -29,14 +34,19 @@ class Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class SchemaThemeSettingEditor extends Component {
|
export default class SchemaThemeSettingEditor extends Component {
|
||||||
|
@service router;
|
||||||
@tracked activeIndex = 0;
|
@tracked activeIndex = 0;
|
||||||
@tracked backButtonText;
|
@tracked backButtonText;
|
||||||
|
@tracked saveButtonDisabled = false;
|
||||||
|
|
||||||
|
data = cloneJSON(this.args.setting.value);
|
||||||
history = [];
|
history = [];
|
||||||
|
schema = this.args.setting.objects_schema;
|
||||||
|
|
||||||
@cached
|
@cached
|
||||||
get tree() {
|
get tree() {
|
||||||
let schema = this.args.schema;
|
let schema = this.schema;
|
||||||
let data = this.args.data;
|
let data = this.data;
|
||||||
|
|
||||||
for (const point of this.history) {
|
for (const point of this.history) {
|
||||||
data = data[point.node.index][point.propertyName];
|
data = data[point.node.index][point.propertyName];
|
||||||
@@ -52,14 +62,18 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
object,
|
object,
|
||||||
text: object[schema.identifier],
|
text: object[schema.identifier],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (index === this.activeIndex) {
|
if (index === this.activeIndex) {
|
||||||
node.active = true;
|
node.active = true;
|
||||||
|
|
||||||
const childObjectsProperties = this.findChildObjectsProperties(
|
const childObjectsProperties = this.findChildObjectsProperties(
|
||||||
schema.properties
|
schema.properties
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const childObjectsProperty of childObjectsProperties) {
|
for (const childObjectsProperty of childObjectsProperties) {
|
||||||
const subtree = new Tree();
|
const subtree = new Tree();
|
||||||
subtree.propertyName = childObjectsProperty.name;
|
subtree.propertyName = childObjectsProperty.name;
|
||||||
|
|
||||||
data[index][childObjectsProperty.name].forEach(
|
data[index][childObjectsProperty.name].forEach(
|
||||||
(childObj, childIndex) => {
|
(childObj, childIndex) => {
|
||||||
subtree.nodes.push(
|
subtree.nodes.push(
|
||||||
@@ -72,11 +86,14 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
node.trees.push(subtree);
|
node.trees.push(subtree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.nodes.push(node);
|
tree.nodes.push(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,21 +107,25 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
get fields() {
|
get fields() {
|
||||||
const node = this.activeNode;
|
const node = this.activeNode;
|
||||||
const list = [];
|
const list = [];
|
||||||
|
|
||||||
for (const [name, spec] of Object.entries(node.schema.properties)) {
|
for (const [name, spec] of Object.entries(node.schema.properties)) {
|
||||||
if (spec.type === "objects") {
|
if (spec.type === "objects") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name,
|
name,
|
||||||
spec,
|
spec,
|
||||||
value: node.object[name],
|
value: node.object[name],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
findChildObjectsProperties(properties) {
|
findChildObjectsProperties(properties) {
|
||||||
const list = [];
|
const list = [];
|
||||||
|
|
||||||
for (const [name, spec] of Object.entries(properties)) {
|
for (const [name, spec] of Object.entries(properties)) {
|
||||||
if (spec.type === "objects") {
|
if (spec.type === "objects") {
|
||||||
list.push({
|
list.push({
|
||||||
@@ -113,9 +134,28 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
saveChanges() {
|
||||||
|
this.saveButtonDisabled = true;
|
||||||
|
|
||||||
|
this.args.setting
|
||||||
|
.updateSetting(this.args.themeId, this.data)
|
||||||
|
.then((result) => {
|
||||||
|
this.args.setting.set("value", result[this.args.setting.setting]);
|
||||||
|
|
||||||
|
this.router.transitionTo(
|
||||||
|
"adminCustomizeThemes.show",
|
||||||
|
this.args.themeId
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(popupAjaxError)
|
||||||
|
.finally(() => (this.saveButtonDisabled = false));
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
onClick(node) {
|
onClick(node) {
|
||||||
this.activeIndex = node.index;
|
this.activeIndex = node.index;
|
||||||
@@ -127,9 +167,11 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
propertyName: tree.propertyName,
|
propertyName: tree.propertyName,
|
||||||
node: parentNode,
|
node: parentNode,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.backButtonText = I18n.t("admin.customize.theme.schema.back_button", {
|
this.backButtonText = I18n.t("admin.customize.theme.schema.back_button", {
|
||||||
name: parentNode.text,
|
name: parentNode.text,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.activeIndex = node.index;
|
this.activeIndex = node.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +179,7 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
backButtonClick() {
|
backButtonClick() {
|
||||||
const historyPoint = this.history.pop();
|
const historyPoint = this.history.pop();
|
||||||
this.activeIndex = historyPoint.node.index;
|
this.activeIndex = historyPoint.node.index;
|
||||||
|
|
||||||
if (this.history.length > 0) {
|
if (this.history.length > 0) {
|
||||||
this.backButtonText = I18n.t("admin.customize.theme.schema.back_button", {
|
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].node.text,
|
||||||
@@ -151,6 +194,7 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
if (field.name === this.activeNode.schema.identifier) {
|
if (field.name === this.activeNode.schema.identifier) {
|
||||||
this.activeNode.text = newVal;
|
this.activeNode.text = newVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activeNode.object[field.name] = newVal;
|
this.activeNode.object[field.name] = newVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +208,7 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
class="back-button"
|
class="back-button"
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<ul class="tree">
|
<ul class="tree">
|
||||||
{{#each this.tree.nodes as |node|}}
|
{{#each this.tree.nodes as |node|}}
|
||||||
<div class="item-container">
|
<div class="item-container">
|
||||||
@@ -191,6 +236,7 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{{#each this.fields as |field|}}
|
{{#each this.fields as |field|}}
|
||||||
<FieldInput
|
<FieldInput
|
||||||
@name={{field.name}}
|
@name={{field.name}}
|
||||||
@@ -200,5 +246,20 @@ export default class SchemaThemeSettingEditor extends Component {
|
|||||||
/>
|
/>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<DButton
|
||||||
|
@disabled={{this.saveButtonDisabled}}
|
||||||
|
@action={{this.saveChanges}}
|
||||||
|
@label="save"
|
||||||
|
class="btn-primary"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinkTo
|
||||||
|
@route="adminCustomizeThemes.show"
|
||||||
|
@model={{@themeId}}
|
||||||
|
class="btn-transparent"
|
||||||
|
>
|
||||||
|
{{i18n "cancel"}}
|
||||||
|
</LinkTo>
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<DButton class="ok" @action={{this.update}} @icon="check" />
|
<DButton class="ok" @action={{this.update}} @icon="check" />
|
||||||
<DButton class="cancel" @action={{this.cancel}} @icon="times" />
|
<DButton class="cancel" @action={{this.cancel}} @icon="times" />
|
||||||
</div>
|
</div>
|
||||||
{{else if this.setting.overridden}}
|
{{else if this.overridden}}
|
||||||
{{#if this.setting.secret}}
|
{{#if this.setting.secret}}
|
||||||
<DButton @action={{this.toggleSecret}} @icon="far-eye-slash" />
|
<DButton @action={{this.toggleSecret}} @icon="far-eye-slash" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import JsonSchemaEditorModal from "discourse/components/modal/json-schema-editor
|
|||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { fmt, propertyNotEqual } from "discourse/lib/computed";
|
import { fmt, propertyNotEqual } from "discourse/lib/computed";
|
||||||
import { splitString } from "discourse/lib/utilities";
|
import { splitString } from "discourse/lib/utilities";
|
||||||
|
import { deepEqual } from "discourse-common/lib/object";
|
||||||
import discourseComputed, { bind } from "discourse-common/utils/decorators";
|
import discourseComputed, { bind } from "discourse-common/utils/decorators";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
import SiteSettingDefaultCategoriesModal from "../components/modal/site-setting-default-categories";
|
import SiteSettingDefaultCategoriesModal from "../components/modal/site-setting-default-categories";
|
||||||
@@ -111,7 +112,7 @@ export default Mixin.create({
|
|||||||
settingVal = "";
|
settingVal = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return bufferVal.toString() !== settingVal.toString();
|
return !deepEqual(bufferVal, settingVal);
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("setting", "buffered.value")
|
@discourseComputed("setting", "buffered.value")
|
||||||
@@ -278,7 +279,7 @@ export default Mixin.create({
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
resetDefault() {
|
resetDefault() {
|
||||||
this.set("buffered.value", this.get("setting.default"));
|
this.set("buffered.value", this.setting.default);
|
||||||
},
|
},
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { computed } from "@ember/object";
|
|||||||
import { readOnly } from "@ember/object/computed";
|
import { readOnly } from "@ember/object/computed";
|
||||||
import Mixin from "@ember/object/mixin";
|
import Mixin from "@ember/object/mixin";
|
||||||
import { isPresent } from "@ember/utils";
|
import { isPresent } from "@ember/utils";
|
||||||
|
import { deepEqual } from "discourse-common/lib/object";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ export default Mixin.create({
|
|||||||
defaultVal = "";
|
defaultVal = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return val.toString() !== defaultVal.toString();
|
return !deepEqual(val, defaultVal);
|
||||||
},
|
},
|
||||||
|
|
||||||
computedValueProperty: computed(
|
computedValueProperty: computed(
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ export default class AdminCustomizeThemesShowSchemaRoute extends Route {
|
|||||||
const setting = theme.settings.findBy("setting", params.setting_name);
|
const setting = theme.settings.findBy("setting", params.setting_name);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: setting.value,
|
theme,
|
||||||
schema: setting.objects_schema,
|
setting,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<SchemaThemeSetting::Editor
|
<SchemaThemeSetting::Editor
|
||||||
@schema={{this.model.schema}}
|
@themeId={{@model.theme.id}}
|
||||||
@data={{this.model.data}}
|
@setting={{@model.setting}}
|
||||||
/>
|
/>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { computed } from "@ember/object";
|
import { computed } from "@ember/object";
|
||||||
import { htmlSafe as htmlSafeTemplateHelper } from "@ember/template";
|
import { htmlSafe as htmlSafeTemplateHelper } from "@ember/template";
|
||||||
import getURL from "discourse-common/lib/get-url";
|
import getURL from "discourse-common/lib/get-url";
|
||||||
|
import { deepEqual } from "discourse-common/lib/object";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
function addonFmt(str, formats) {
|
function addonFmt(str, formats) {
|
||||||
@@ -39,7 +40,7 @@ function addonFmt(str, formats) {
|
|||||||
|
|
||||||
export function propertyEqual(p1, p2) {
|
export function propertyEqual(p1, p2) {
|
||||||
return computed(p1, p2, function () {
|
return computed(p1, p2, function () {
|
||||||
return this.get(p1) === this.get(p2);
|
return deepEqual(this.get(p1), this.get(p2));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ export function propertyEqual(p1, p2) {
|
|||||||
**/
|
**/
|
||||||
export function propertyNotEqual(p1, p2) {
|
export function propertyNotEqual(p1, p2) {
|
||||||
return computed(p1, p2, function () {
|
return computed(p1, p2, function () {
|
||||||
return this.get(p1) !== this.get(p2);
|
return !deepEqual(this.get(p1), this.get(p2));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import ThemeSettings from "admin/models/theme-settings";
|
||||||
|
|
||||||
export default function schemaAndData(version = 1) {
|
export default function schemaAndData(version = 1) {
|
||||||
let schema, data;
|
let schema, data;
|
||||||
if (version === 1) {
|
if (version === 1) {
|
||||||
@@ -196,5 +198,10 @@ export default function schemaAndData(version = 1) {
|
|||||||
} else {
|
} else {
|
||||||
throw new Error("unknown fixture version");
|
throw new Error("unknown fixture version");
|
||||||
}
|
}
|
||||||
return [schema, data];
|
|
||||||
|
return ThemeSettings.create({
|
||||||
|
objects_schema: schema,
|
||||||
|
value: data,
|
||||||
|
setting: "objects_setting"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,9 +60,10 @@ module(
|
|||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("activates the first node by default", async function (assert) {
|
test("activates the first node by default", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(1);
|
const setting = schemaAndData(1);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const tree = new TreeFromDOM();
|
const tree = new TreeFromDOM();
|
||||||
@@ -73,9 +74,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("renders the 2nd level of nested items for the active item only", async function (assert) {
|
test("renders the 2nd level of nested items for the active item only", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(1);
|
const setting = schemaAndData(1);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const tree = new TreeFromDOM();
|
const tree = new TreeFromDOM();
|
||||||
@@ -114,9 +116,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("allows navigating through multiple levels of nesting", async function (assert) {
|
test("allows navigating through multiple levels of nesting", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(1);
|
const setting = schemaAndData(1);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const tree = new TreeFromDOM();
|
const tree = new TreeFromDOM();
|
||||||
@@ -191,9 +194,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("the back button is only shown when the navigation is at least one level deep", async function (assert) {
|
test("the back button is only shown when the navigation is at least one level deep", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(1);
|
const setting = schemaAndData(1);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
assert.dom(".back-button").doesNotExist();
|
assert.dom(".back-button").doesNotExist();
|
||||||
@@ -225,9 +229,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("the back button navigates to the index of the active element at the previous level", async function (assert) {
|
test("the back button navigates to the index of the active element at the previous level", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(1);
|
const setting = schemaAndData(1);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const tree = new TreeFromDOM();
|
const tree = new TreeFromDOM();
|
||||||
@@ -251,9 +256,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("the back button label includes the name of the item at the previous level", async function (assert) {
|
test("the back button label includes the name of the item at the previous level", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(1);
|
const setting = schemaAndData(1);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const tree = new TreeFromDOM();
|
const tree = new TreeFromDOM();
|
||||||
@@ -287,9 +293,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("input fields for items at different levels", async function (assert) {
|
test("input fields for items at different levels", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(2);
|
const setting = schemaAndData(2);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const inputFields = new InputFieldsFromDOM();
|
const inputFields = new InputFieldsFromDOM();
|
||||||
@@ -332,9 +339,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("input fields of type integer", async function (assert) {
|
test("input fields of type integer", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(3);
|
const setting = schemaAndData(3);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const inputFields = new InputFieldsFromDOM();
|
const inputFields = new InputFieldsFromDOM();
|
||||||
@@ -364,9 +372,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("input fields of type boolean", async function (assert) {
|
test("input fields of type boolean", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(3);
|
const setting = schemaAndData(3);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const inputFields = new InputFieldsFromDOM();
|
const inputFields = new InputFieldsFromDOM();
|
||||||
@@ -393,9 +402,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("input fields of type enum", async function (assert) {
|
test("input fields of type enum", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(3);
|
const setting = schemaAndData(3);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const inputFields = new InputFieldsFromDOM();
|
const inputFields = new InputFieldsFromDOM();
|
||||||
@@ -419,9 +429,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("identifier field instantly updates in the navigation tree when the input field is changed", async function (assert) {
|
test("identifier field instantly updates in the navigation tree when the input field is changed", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(2);
|
const setting = schemaAndData(2);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const inputFields = new InputFieldsFromDOM();
|
const inputFields = new InputFieldsFromDOM();
|
||||||
@@ -448,9 +459,10 @@ module(
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("edits are remembered when navigating between levels", async function (assert) {
|
test("edits are remembered when navigating between levels", async function (assert) {
|
||||||
const [schema, data] = schemaAndData(2);
|
const setting = schemaAndData(2);
|
||||||
|
|
||||||
await render(<template>
|
await render(<template>
|
||||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
<AdminSchemaThemeSettingEditor @themeId="1" @setting={{setting}} />
|
||||||
</template>);
|
</template>);
|
||||||
|
|
||||||
const inputFields = new InputFieldsFromDOM();
|
const inputFields = new InputFieldsFromDOM();
|
||||||
|
|||||||
@@ -83,70 +83,4 @@ describe "Admin Customize Themes", type: :system do
|
|||||||
expect(ace_content.text).to eq("console.log('test')")
|
expect(ace_content.text).to eq("console.log('test')")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when editing a theme setting of objects type" do
|
|
||||||
let(:objects_setting) do
|
|
||||||
theme.set_field(
|
|
||||||
target: :settings,
|
|
||||||
name: "yaml",
|
|
||||||
value: File.read("#{Rails.root}/spec/fixtures/theme_settings/objects_settings.yaml"),
|
|
||||||
)
|
|
||||||
|
|
||||||
theme.save!
|
|
||||||
theme.settings[:objects_setting]
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
|
||||||
SiteSetting.experimental_objects_type_for_theme_settings = true
|
|
||||||
objects_setting
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should allow admin to edit the theme setting of objecst type" do
|
|
||||||
visit("/admin/customize/themes/#{theme.id}")
|
|
||||||
|
|
||||||
admin_customize_themes_page.click_edit_objects_theme_setting_button("objects_setting")
|
|
||||||
|
|
||||||
expect(page).to have_current_path(
|
|
||||||
"/admin/customize/themes/#{theme.id}/schema/objects_setting",
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "allows an admin to edit a theme setting of objects type via the settings editor" do
|
|
||||||
visit "/admin/customize/themes/#{theme.id}"
|
|
||||||
|
|
||||||
theme_settings_editor = admin_customize_themes_page.click_theme_settings_editor_button
|
|
||||||
|
|
||||||
theme_settings_editor.fill_in(<<~SETTING)
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"setting": "objects_setting",
|
|
||||||
"value": [
|
|
||||||
{
|
|
||||||
"name": "new section",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"name": "new link",
|
|
||||||
"url": "https://example.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
SETTING
|
|
||||||
|
|
||||||
theme_settings_editor.save
|
|
||||||
|
|
||||||
try_until_success do
|
|
||||||
expect(theme.reload.settings[:objects_setting].value).to eq(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"links" => [{ "name" => "new link", "url" => "https://example.com" }],
|
|
||||||
"name" => "new section",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe "Admin editing objects type theme setting", type: :system do
|
||||||
|
fab!(:admin)
|
||||||
|
fab!(:theme)
|
||||||
|
|
||||||
|
let(:objects_setting) do
|
||||||
|
theme.set_field(
|
||||||
|
target: :settings,
|
||||||
|
name: "yaml",
|
||||||
|
value: File.read("#{Rails.root}/spec/fixtures/theme_settings/objects_settings.yaml"),
|
||||||
|
)
|
||||||
|
|
||||||
|
theme.save!
|
||||||
|
theme.settings[:objects_setting]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:admin_customize_themes_page) { PageObjects::Pages::AdminCustomizeThemes.new }
|
||||||
|
|
||||||
|
let(:admin_objects_theme_setting_editor_page) do
|
||||||
|
PageObjects::Pages::AdminObjectsThemeSettingEditor.new
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.experimental_objects_type_for_theme_settings = true
|
||||||
|
objects_setting
|
||||||
|
sign_in(admin)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when editing a theme setting of objects type" do
|
||||||
|
it "should allow admin to edit the theme setting of objects type" do
|
||||||
|
visit("/admin/customize/themes/#{theme.id}")
|
||||||
|
|
||||||
|
expect(admin_customize_themes_page).to have_no_overriden_setting("objects_setting")
|
||||||
|
|
||||||
|
admin_objects_theme_setting_editor =
|
||||||
|
admin_customize_themes_page.click_edit_objects_theme_setting_button("objects_setting")
|
||||||
|
|
||||||
|
expect(page).to have_current_path(
|
||||||
|
"/admin/customize/themes/#{theme.id}/schema/objects_setting",
|
||||||
|
)
|
||||||
|
|
||||||
|
admin_objects_theme_setting_editor.fill_in_field("name", "some new name").save
|
||||||
|
|
||||||
|
expect(admin_customize_themes_page).to have_overridden_setting("objects_setting")
|
||||||
|
|
||||||
|
admin_customize_themes_page.reset_overridden_setting("objects_setting")
|
||||||
|
|
||||||
|
admin_objects_theme_setting_editor =
|
||||||
|
admin_customize_themes_page.click_edit_objects_theme_setting_button("objects_setting")
|
||||||
|
|
||||||
|
expect(admin_objects_theme_setting_editor).to have_setting_field("name", "some new name")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows an admin to edit a theme setting of objects type via the settings editor" do
|
||||||
|
visit "/admin/customize/themes/#{theme.id}"
|
||||||
|
|
||||||
|
theme_settings_editor = admin_customize_themes_page.click_theme_settings_editor_button
|
||||||
|
|
||||||
|
theme_settings_editor.fill_in(<<~SETTING)
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"setting": "objects_setting",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"name": "new section",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"name": "new link",
|
||||||
|
"url": "https://example.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
SETTING
|
||||||
|
|
||||||
|
theme_settings_editor.save
|
||||||
|
|
||||||
|
try_until_success do
|
||||||
|
expect(theme.reload.settings[:objects_setting].value).to eq(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"links" => [{ "name" => "new link", "url" => "https://example.com" }],
|
||||||
|
"name" => "new section",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -15,6 +15,20 @@ module PageObjects
|
|||||||
has_css?(".select-inactive-mode")
|
has_css?(".select-inactive-mode")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_overridden_setting?(setting_name)
|
||||||
|
has_css?(overridden_setting_selector(setting_name))
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_no_overriden_setting?(setting_name)
|
||||||
|
has_no_css?(overridden_setting_selector(setting_name))
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_overridden_setting(setting_name)
|
||||||
|
setting_section = find("section.theme.settings .setting[data-setting=\"#{setting_name}\"]")
|
||||||
|
setting_section.click_button(I18n.t("admin_js.admin.settings.reset"))
|
||||||
|
setting_section.find(".setting-controls .ok").click
|
||||||
|
end
|
||||||
|
|
||||||
def click_select_inactive_mode
|
def click_select_inactive_mode
|
||||||
find(".select-inactive-mode").click
|
find(".select-inactive-mode").click
|
||||||
end
|
end
|
||||||
@@ -41,12 +55,19 @@ module PageObjects
|
|||||||
|
|
||||||
def click_edit_objects_theme_setting_button(setting_name)
|
def click_edit_objects_theme_setting_button(setting_name)
|
||||||
find(".theme-setting[data-setting=\"#{setting_name}\"] .setting-value-edit-button").click
|
find(".theme-setting[data-setting=\"#{setting_name}\"] .setting-value-edit-button").click
|
||||||
|
PageObjects::Pages::AdminObjectsThemeSettingEditor.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def click_theme_settings_editor_button
|
def click_theme_settings_editor_button
|
||||||
click_button(I18n.t("admin_js.admin.customize.theme.settings_editor"))
|
click_button(I18n.t("admin_js.admin.customize.theme.settings_editor"))
|
||||||
PageObjects::Components::AdminThemeSettingsEditor.new
|
PageObjects::Components::AdminThemeSettingsEditor.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def overridden_setting_selector(setting_name)
|
||||||
|
"section.theme.settings .setting.overridden[data-setting=\"#{setting_name}\"]"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module PageObjects
|
||||||
|
module Pages
|
||||||
|
class AdminObjectsThemeSettingEditor < PageObjects::Pages::Base
|
||||||
|
def has_setting_field?(field_name, value)
|
||||||
|
expect(input_field(field_name).value).to eq(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fill_in_field(field_name, value)
|
||||||
|
input_field(field_name).fill_in(with: value)
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
click_button(I18n.t("js.save"))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_field(field_name)
|
||||||
|
page.find(".schema-field[data-name=\"#{field_name}\"] input")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user