mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 18:30:26 -06:00
DEV: Support category, float, group and tag inputs for objects theme setting (#26113)
Continue from https://github.com/discourse/discourse/pull/25673 and https://github.com/discourse/discourse/pull/25811. This PR adds support for category, float, group and tag types for schema theme settings.
This commit is contained in:
parent
de00c9a3d3
commit
3a4f4abdc9
@ -1,8 +1,12 @@
|
||||
import Component from "@glimmer/component";
|
||||
import BooleanField from "./types/boolean";
|
||||
import CategoryField from "./types/category";
|
||||
import EnumField from "./types/enum";
|
||||
import FloatField from "./types/float";
|
||||
import GroupField from "./types/group";
|
||||
import IntegerField from "./types/integer";
|
||||
import StringField from "./types/string";
|
||||
import TagField from "./types/tag";
|
||||
|
||||
export default class SchemaThemeSettingField extends Component {
|
||||
get component() {
|
||||
@ -11,10 +15,18 @@ export default class SchemaThemeSettingField extends Component {
|
||||
return StringField;
|
||||
case "integer":
|
||||
return IntegerField;
|
||||
case "float":
|
||||
return FloatField;
|
||||
case "boolean":
|
||||
return BooleanField;
|
||||
case "enum":
|
||||
return EnumField;
|
||||
case "category":
|
||||
return CategoryField;
|
||||
case "tag":
|
||||
return TagField;
|
||||
case "group":
|
||||
return GroupField;
|
||||
default:
|
||||
throw new Error("unknown type");
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { hash } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import CategoryChooser from "select-kit/components/category-chooser";
|
||||
|
||||
export default class SchemaThemeSettingTypeCategory extends Component {
|
||||
@tracked value = this.args.value;
|
||||
|
||||
@action
|
||||
onInput(newVal) {
|
||||
this.value = newVal;
|
||||
this.args.onChange(newVal);
|
||||
}
|
||||
|
||||
<template>
|
||||
<CategoryChooser
|
||||
@value={{this.value}}
|
||||
@onChange={{this.onInput}}
|
||||
@options={{hash allowUncategorized=false}}
|
||||
/>
|
||||
</template>
|
||||
}
|
@ -4,12 +4,7 @@ import { action } from "@ember/object";
|
||||
import ComboBox from "select-kit/components/combo-box";
|
||||
|
||||
export default class SchemaThemeSettingTypeEnum extends Component {
|
||||
@tracked value;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.value = this.args.value;
|
||||
}
|
||||
@tracked value = this.args.value;
|
||||
|
||||
get content() {
|
||||
return this.args.spec.choices.map((choice) => {
|
||||
|
@ -0,0 +1,20 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { Input } from "@ember/component";
|
||||
import { on } from "@ember/modifier";
|
||||
import { action } from "@ember/object";
|
||||
|
||||
export default class SchemaThemeSettingTypeFloat extends Component {
|
||||
@action
|
||||
onInput(event) {
|
||||
this.args.onChange(parseFloat(event.currentTarget.value));
|
||||
}
|
||||
|
||||
<template>
|
||||
<Input
|
||||
@value={{@value}}
|
||||
{{on "input" this.onInput}}
|
||||
@type="number"
|
||||
step="0.1"
|
||||
/>
|
||||
</template>
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { hash } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import Group from "discourse/models/group";
|
||||
import GroupChooser from "select-kit/components/group-chooser";
|
||||
|
||||
export default class SchemaThemeSettingTypeGroup extends Component {
|
||||
@tracked value = this.args.value;
|
||||
@tracked groups = Group.findAll().then((groups) => {
|
||||
this.groups = groups;
|
||||
});
|
||||
|
||||
@action
|
||||
onInput(newVal) {
|
||||
this.value = newVal[0];
|
||||
this.args.onChange(newVal[0]);
|
||||
}
|
||||
|
||||
<template>
|
||||
<GroupChooser
|
||||
@content={{this.groups}}
|
||||
@value={{this.value}}
|
||||
@onChange={{this.onInput}}
|
||||
@options={{hash maximum=1}}
|
||||
/>
|
||||
</template>
|
||||
}
|
@ -6,7 +6,7 @@ import { action } from "@ember/object";
|
||||
export default class SchemaThemeSettingTypeInteger extends Component {
|
||||
@action
|
||||
onInput(event) {
|
||||
this.args.onChange(event.currentTarget.value);
|
||||
this.args.onChange(parseInt(event.currentTarget.value, 10));
|
||||
}
|
||||
|
||||
<template>
|
||||
|
@ -0,0 +1,23 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { hash } from "@ember/helper";
|
||||
import { action } from "@ember/object";
|
||||
import TagChooser from "select-kit/components/tag-chooser";
|
||||
|
||||
export default class SchemaThemeSettingTypeTag extends Component {
|
||||
@tracked value = this.args.value;
|
||||
|
||||
@action
|
||||
onInput(newVal) {
|
||||
this.value = newVal;
|
||||
this.args.onChange(newVal);
|
||||
}
|
||||
|
||||
<template>
|
||||
<TagChooser
|
||||
@tags={{this.value}}
|
||||
@onChange={{this.onInput}}
|
||||
@options={{hash allowAny=false}}
|
||||
/>
|
||||
</template>
|
||||
}
|
@ -172,12 +172,24 @@ export default function schemaAndData(version = 1) {
|
||||
integer_field: {
|
||||
type: "integer",
|
||||
},
|
||||
float_field: {
|
||||
type: "float",
|
||||
},
|
||||
boolean_field: {
|
||||
type: "boolean",
|
||||
},
|
||||
enum_field: {
|
||||
type: "enum",
|
||||
choices: ["nice", "awesome", "cool"]
|
||||
},
|
||||
category_field: {
|
||||
type: "category",
|
||||
},
|
||||
group_field: {
|
||||
type: "group",
|
||||
},
|
||||
tag_field: {
|
||||
type: "tag",
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ import { click, fillIn, render } from "@ember/test-helpers";
|
||||
import { module, test } from "qunit";
|
||||
import schemaAndData from "discourse/tests/fixtures/theme-setting-schema-data";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import pretender, { response } from "discourse/tests/helpers/create-pretender";
|
||||
import { queryAll } from "discourse/tests/helpers/qunit-helpers";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
import I18n from "discourse-i18n";
|
||||
@ -292,6 +293,47 @@ module(
|
||||
);
|
||||
});
|
||||
|
||||
test("input fields are rendered even if they're not present in the data", async function (assert) {
|
||||
const schema = {
|
||||
name: "something",
|
||||
identifier: "id",
|
||||
properties: {
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
name: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
};
|
||||
const data = [
|
||||
{
|
||||
id: "bu1",
|
||||
name: "Big U",
|
||||
},
|
||||
{
|
||||
id: "fi2",
|
||||
},
|
||||
];
|
||||
await render(<template>
|
||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
||||
</template>);
|
||||
|
||||
const inputFields = new InputFieldsFromDOM();
|
||||
|
||||
assert.strictEqual(inputFields.count, 2);
|
||||
assert.dom(inputFields.fields.id.inputElement).hasValue("bu1");
|
||||
assert.dom(inputFields.fields.name.inputElement).hasValue("Big U");
|
||||
|
||||
const tree = new TreeFromDOM();
|
||||
await click(tree.nodes[1].element);
|
||||
inputFields.refresh();
|
||||
|
||||
assert.strictEqual(inputFields.count, 2);
|
||||
assert.dom(inputFields.fields.id.inputElement).hasValue("fi2");
|
||||
assert.dom(inputFields.fields.name.inputElement).hasNoValue();
|
||||
});
|
||||
|
||||
test("input fields for items at different levels", async function (assert) {
|
||||
const setting = schemaAndData(2);
|
||||
|
||||
@ -371,6 +413,36 @@ module(
|
||||
.hasValue("922229");
|
||||
});
|
||||
|
||||
test("input fields of type float", async function (assert) {
|
||||
const [schema, data] = schemaAndData(3);
|
||||
await render(<template>
|
||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
||||
</template>);
|
||||
|
||||
const inputFields = new InputFieldsFromDOM();
|
||||
assert
|
||||
.dom(inputFields.fields.float_field.labelElement)
|
||||
.hasText("float_field");
|
||||
assert.dom(inputFields.fields.float_field.inputElement).hasValue("");
|
||||
|
||||
await fillIn(inputFields.fields.float_field.inputElement, "6934.24");
|
||||
|
||||
const tree = new TreeFromDOM();
|
||||
await click(tree.nodes[1].element);
|
||||
|
||||
inputFields.refresh();
|
||||
|
||||
assert.dom(inputFields.fields.float_field.inputElement).hasValue("");
|
||||
|
||||
tree.refresh();
|
||||
await click(tree.nodes[0].element);
|
||||
inputFields.refresh();
|
||||
|
||||
assert
|
||||
.dom(inputFields.fields.float_field.inputElement)
|
||||
.hasValue("6934.24");
|
||||
});
|
||||
|
||||
test("input fields of type boolean", async function (assert) {
|
||||
const setting = schemaAndData(3);
|
||||
|
||||
@ -428,6 +500,103 @@ module(
|
||||
assert.strictEqual(enumSelector.header().value(), "nice");
|
||||
});
|
||||
|
||||
test("input fields of type category", async function (assert) {
|
||||
const [schema, data] = schemaAndData(3);
|
||||
await render(<template>
|
||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
||||
</template>);
|
||||
|
||||
const inputFields = new InputFieldsFromDOM();
|
||||
const categorySelector = selectKit(
|
||||
`${inputFields.fields.category_field.selector} .select-kit`
|
||||
);
|
||||
|
||||
assert.strictEqual(categorySelector.header().value(), null);
|
||||
|
||||
await categorySelector.expand();
|
||||
await categorySelector.selectRowByIndex(1);
|
||||
|
||||
const selectedCategoryId = categorySelector.header().value();
|
||||
assert.ok(selectedCategoryId);
|
||||
|
||||
const tree = new TreeFromDOM();
|
||||
await click(tree.nodes[1].element);
|
||||
assert.strictEqual(categorySelector.header().value(), null);
|
||||
|
||||
tree.refresh();
|
||||
|
||||
await click(tree.nodes[0].element);
|
||||
assert.strictEqual(categorySelector.header().value(), selectedCategoryId);
|
||||
});
|
||||
|
||||
test("input fields of type tag", async function (assert) {
|
||||
const [schema, data] = schemaAndData(3);
|
||||
await render(<template>
|
||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
||||
</template>);
|
||||
|
||||
const inputFields = new InputFieldsFromDOM();
|
||||
const tagSelector = selectKit(
|
||||
`${inputFields.fields.tag_field.selector} .select-kit`
|
||||
);
|
||||
|
||||
assert.strictEqual(tagSelector.header().value(), null);
|
||||
|
||||
await tagSelector.expand();
|
||||
await tagSelector.selectRowByIndex(1);
|
||||
await tagSelector.selectRowByIndex(3);
|
||||
|
||||
assert.strictEqual(tagSelector.header().value(), "gazelle,cat");
|
||||
|
||||
const tree = new TreeFromDOM();
|
||||
await click(tree.nodes[1].element);
|
||||
assert.strictEqual(tagSelector.header().value(), null);
|
||||
|
||||
tree.refresh();
|
||||
|
||||
await click(tree.nodes[0].element);
|
||||
assert.strictEqual(tagSelector.header().value(), "gazelle,cat");
|
||||
});
|
||||
|
||||
test("input fields of type group", async function (assert) {
|
||||
pretender.get("/groups/search.json", () => {
|
||||
return response(200, [
|
||||
{ id: 23, name: "testers" },
|
||||
{ id: 74, name: "devs" },
|
||||
{ id: 89, name: "customers" },
|
||||
]);
|
||||
});
|
||||
|
||||
const [schema, data] = schemaAndData(3);
|
||||
await render(<template>
|
||||
<AdminSchemaThemeSettingEditor @schema={{schema}} @data={{data}} />
|
||||
</template>);
|
||||
|
||||
const inputFields = new InputFieldsFromDOM();
|
||||
const groupSelector = selectKit(
|
||||
`${inputFields.fields.group_field.selector} .select-kit`
|
||||
);
|
||||
|
||||
assert.strictEqual(groupSelector.header().value(), null);
|
||||
|
||||
await groupSelector.expand();
|
||||
await groupSelector.selectRowByValue(74);
|
||||
assert.strictEqual(groupSelector.header().value(), "74");
|
||||
|
||||
const tree = new TreeFromDOM();
|
||||
await click(tree.nodes[1].element);
|
||||
|
||||
assert.strictEqual(groupSelector.header().value(), null);
|
||||
await groupSelector.expand();
|
||||
await groupSelector.selectRowByValue(23);
|
||||
assert.strictEqual(groupSelector.header().value(), "23");
|
||||
|
||||
tree.refresh();
|
||||
|
||||
await click(tree.nodes[0].element);
|
||||
assert.strictEqual(groupSelector.header().value(), "74");
|
||||
});
|
||||
|
||||
test("identifier field instantly updates in the navigation tree when the input field is changed", async function (assert) {
|
||||
const setting = schemaAndData(2);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user