mirror of
https://github.com/discourse/discourse.git
synced 2024-11-21 16:38:15 -06:00
DEV: Open theme settings objects editor from admin customize theme page (#26006)
Why this change? The `/admin/customize/themes/:id/schema/name` route is a work in progress but we want to be able to start navigating to it from the `/admin/customize/themes/:id` route. What does this change do? 1. Move `adminCustomizeThemes.schema` to a child route of `adminCustomizeThemes.show`. This is because we need the model from the parent route and if it isn't a child route we end up having to load the theme model again from the server. 1. Add the `objects_schema` attribute to `ThemeSettingsSerializer` 1. Refactor `SiteSettingComponent` to be able to render a button so that we don't have to hardcode the button rendering into the `SiteSettings::String` component
This commit is contained in:
parent
81ede05005
commit
94b09f3331
@ -25,16 +25,25 @@
|
||||
</div>
|
||||
|
||||
<div class="setting-value">
|
||||
{{component
|
||||
this.componentName
|
||||
setting=this.setting
|
||||
value=this.buffered.value
|
||||
validationMessage=this.validationMessage
|
||||
preview=this.preview
|
||||
isSecret=this.isSecret
|
||||
allowAny=this.allowAny
|
||||
changeValueCallback=this.changeValueCallback
|
||||
}}
|
||||
{{#if this.settingEditButton}}
|
||||
<DButton
|
||||
@action={{this.settingEditButton.action}}
|
||||
@icon={{this.settingEditButton.icon}}
|
||||
@label={{this.settingEditButton.label}}
|
||||
class="setting-value-edit-button"
|
||||
/>
|
||||
{{else}}
|
||||
{{component
|
||||
this.componentName
|
||||
setting=this.setting
|
||||
value=this.buffered.value
|
||||
validationMessage=this.validationMessage
|
||||
preview=this.preview
|
||||
isSecret=this.isSecret
|
||||
allowAny=this.allowAny
|
||||
changeValueCallback=this.changeValueCallback
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if this.dirty}}
|
||||
|
@ -1,11 +1,5 @@
|
||||
{{#if this.setting.textarea}}
|
||||
<Textarea @value={{this.value}} class="input-setting-textarea" />
|
||||
{{else if this.setting.json_schema}}
|
||||
<DButton
|
||||
@action={{fn (mut this.showJsonEditorModal) true}}
|
||||
@icon="pencil-alt"
|
||||
@label="admin.site_settings.json_schema.edit"
|
||||
/>
|
||||
{{else if this.isSecret}}
|
||||
<Input @type="password" @value={{this.value}} class="input-setting-string" />
|
||||
{{else}}
|
||||
@ -13,14 +7,4 @@
|
||||
{{/if}}
|
||||
|
||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
||||
<div class="desc">{{html-safe this.setting.description}}</div>
|
||||
|
||||
{{#if this.showJsonEditorModal}}
|
||||
<Modal::JsonSchemaEditor
|
||||
@updateValue={{fn (mut this.value)}}
|
||||
@value={{this.value}}
|
||||
@settingName={{this.setting.setting}}
|
||||
@jsonSchema={{this.setting.json_schema}}
|
||||
@closeModal={{fn (mut this.showJsonEditorModal) false}}
|
||||
/>
|
||||
{{/if}}
|
||||
<div class="desc">{{html-safe this.setting.description}}</div>
|
@ -1,98 +0,0 @@
|
||||
import Controller from "@ember/controller";
|
||||
|
||||
export default class AdminCustomizeThemesSchemaController extends Controller {
|
||||
data = [
|
||||
{
|
||||
name: "item 1",
|
||||
width: 143,
|
||||
is_valid: true,
|
||||
enum_prop: 11,
|
||||
children: [
|
||||
{
|
||||
name: "child 1-1",
|
||||
grandchildren: [
|
||||
{
|
||||
name: "grandchild 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "child 1-2",
|
||||
grandchildren: [
|
||||
{
|
||||
name: "grandchild 1-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "item 2",
|
||||
width: 803,
|
||||
is_valid: false,
|
||||
enum_prop: 22,
|
||||
children: [
|
||||
{
|
||||
name: "child 2-1",
|
||||
grandchildren: [
|
||||
{
|
||||
name: "grandchild 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "child 2-2",
|
||||
grandchildren: [
|
||||
{
|
||||
name: "grandchild 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
schema = {
|
||||
name: "item",
|
||||
identifier: "name",
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
},
|
||||
width: {
|
||||
type: "integer",
|
||||
},
|
||||
is_valid: {
|
||||
type: "boolean",
|
||||
},
|
||||
enum_prop: {
|
||||
type: "enum",
|
||||
choices: [11, 22],
|
||||
},
|
||||
children: {
|
||||
type: "objects",
|
||||
schema: {
|
||||
name: "child",
|
||||
identifier: "name",
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
},
|
||||
grandchildren: {
|
||||
type: "objects",
|
||||
schema: {
|
||||
name: "grandchild",
|
||||
identifier: "name",
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
@ -5,6 +5,7 @@ import Mixin from "@ember/object/mixin";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { isNone } from "@ember/utils";
|
||||
import JsonSchemaEditorModal from "discourse/components/modal/json-schema-editor";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { fmt, propertyNotEqual } from "discourse/lib/computed";
|
||||
import { splitString } from "discourse/lib/utilities";
|
||||
@ -78,6 +79,7 @@ const DEFAULT_USER_PREFERENCES = [
|
||||
|
||||
export default Mixin.create({
|
||||
modal: service(),
|
||||
router: service(),
|
||||
site: service(),
|
||||
attributeBindings: ["setting.setting:data-setting"],
|
||||
classNameBindings: [":row", ":setting", "overridden", "typeClass"],
|
||||
@ -168,6 +170,39 @@ export default Mixin.create({
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed("setting")
|
||||
settingEditButton(setting) {
|
||||
if (setting.json_schema) {
|
||||
return {
|
||||
action: () => {
|
||||
this.modal.show(JsonSchemaEditorModal, {
|
||||
model: {
|
||||
updateValue: (value) => {
|
||||
this.buffered.set("value", value);
|
||||
},
|
||||
value: this.buffered.get("value"),
|
||||
settingName: setting.setting,
|
||||
jsonSchema: setting.json_schema,
|
||||
},
|
||||
});
|
||||
},
|
||||
label: "admin.site_settings.json_schema.edit",
|
||||
icon: "pencil-alt",
|
||||
};
|
||||
} else if (setting.objects_schema) {
|
||||
return {
|
||||
action: () => {
|
||||
this.router.transitionTo(
|
||||
"adminCustomizeThemes.show.schema",
|
||||
setting.setting
|
||||
);
|
||||
},
|
||||
label: "admin.customize.theme.edit_objects_theme_setting",
|
||||
icon: "pencil-alt",
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@action
|
||||
async update() {
|
||||
const key = this.buffered.get("setting");
|
||||
|
@ -1,8 +0,0 @@
|
||||
import Route from "@ember/routing/route";
|
||||
|
||||
export default class AdminCustomizeThemesSchemaRoute extends Route {
|
||||
setupController() {
|
||||
super.setupController(...arguments);
|
||||
this.controllerFor("adminCustomizeThemes").set("editingTheme", true);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
import Route from "@ember/routing/route";
|
||||
|
||||
export default class AdminCustomizeThemesShowSchemaRoute extends Route {
|
||||
model(params) {
|
||||
const theme = this.modelFor("adminCustomizeThemesShow");
|
||||
const setting = theme.settings.findBy("setting", params.setting_name);
|
||||
|
||||
return {
|
||||
data: setting.value,
|
||||
schema: setting.objects_schema,
|
||||
};
|
||||
}
|
||||
|
||||
setupController() {
|
||||
super.setupController(...arguments);
|
||||
this.controllerFor("adminCustomizeThemes").set("editingTheme", true);
|
||||
|
||||
this.controllerFor("adminCustomizeThemes.show").set(
|
||||
"editingThemeSetting",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.controllerFor("adminCustomizeThemes").set("editingTheme", false);
|
||||
|
||||
this.controllerFor("adminCustomizeThemes.show").set(
|
||||
"editingThemeSetting",
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
@ -40,6 +40,7 @@ export default class AdminCustomizeThemesShowRoute extends Route {
|
||||
colorSchemeId: model.get("color_scheme_id"),
|
||||
colorSchemes: parentController.get("model.extras.color_schemes"),
|
||||
editingName: false,
|
||||
editingThemeSetting: false,
|
||||
});
|
||||
|
||||
this.handleHighlight(model);
|
||||
|
@ -57,9 +57,10 @@ export default function () {
|
||||
"adminCustomizeThemes",
|
||||
{ path: "themes", resetNamespace: true },
|
||||
function () {
|
||||
this.route("show", { path: "/:theme_id" });
|
||||
this.route("show", { path: "/:theme_id" }, function () {
|
||||
this.route("schema", { path: "schema/:setting_name" });
|
||||
});
|
||||
this.route("edit", { path: "/:theme_id/:target/:field_name/edit" });
|
||||
this.route("schema", { path: "/:theme_id/schema/:setting_name" });
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
<SchemaThemeSetting::Editor @schema={{this.schema}} @data={{this.data}} />
|
@ -0,0 +1,4 @@
|
||||
<SchemaThemeSetting::Editor
|
||||
@schema={{this.model.schema}}
|
||||
@data={{this.model.data}}
|
||||
/>
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
@closeModal={{@closeModal}}
|
||||
@title={{i18n
|
||||
"admin.site_settings.json_schema.modal_title"
|
||||
name=@settingName
|
||||
name=@model.settingName
|
||||
}}
|
||||
class="json-schema-editor-modal"
|
||||
>
|
||||
|
@ -8,12 +8,12 @@ import { afterRender } from "discourse-common/utils/decorators";
|
||||
|
||||
export default class JsonSchemaEditorModal extends Component {
|
||||
@tracked editor = null;
|
||||
@tracked value = this.args.value;
|
||||
@tracked value = this.args.model.value;
|
||||
@tracked flash;
|
||||
@tracked flashType;
|
||||
|
||||
get settingName() {
|
||||
return this.args.settingName.replace(/\_/g, " ");
|
||||
return this.args.model.settingName.replace(/\_/g, " ");
|
||||
}
|
||||
|
||||
@action
|
||||
@ -34,7 +34,7 @@ export default class JsonSchemaEditorModal extends Component {
|
||||
|
||||
if (!errors.length) {
|
||||
this.value = JSON.stringify(this.editor.getValue());
|
||||
this.args.updateValue(this.value);
|
||||
this.args.model.updateValue(this.value);
|
||||
this.args.closeModal();
|
||||
} else {
|
||||
this.flash = errors.mapBy("message").join("\n");
|
||||
@ -53,7 +53,7 @@ export default class JsonSchemaEditorModal extends Component {
|
||||
JSONEditor.defaults.options.iconlib = "discourseIcons";
|
||||
|
||||
this.editor = new JSONEditor(editor, {
|
||||
schema: this.args.jsonSchema,
|
||||
schema: this.args.model.jsonSchema,
|
||||
disable_array_delete_all_rows: true,
|
||||
disable_array_delete_last_row: true,
|
||||
disable_array_reorder: false,
|
||||
|
@ -9,7 +9,8 @@ class ThemeSettingsSerializer < ApplicationSerializer
|
||||
:valid_values,
|
||||
:list_type,
|
||||
:textarea,
|
||||
:json_schema
|
||||
:json_schema,
|
||||
:objects_schema
|
||||
|
||||
def setting
|
||||
object.name
|
||||
@ -65,6 +66,14 @@ class ThemeSettingsSerializer < ApplicationSerializer
|
||||
object.type == ThemeSetting.types[:string]
|
||||
end
|
||||
|
||||
def objects_schema
|
||||
object.schema
|
||||
end
|
||||
|
||||
def include_objects_schema?
|
||||
object.type == ThemeSetting.types[:objects]
|
||||
end
|
||||
|
||||
def json_schema
|
||||
object.json_schema
|
||||
end
|
||||
|
@ -5485,6 +5485,7 @@ en:
|
||||
has_overwritten_history: "Current theme version no longer exists because the Git history has been overwritten by a force push."
|
||||
add: "Add"
|
||||
theme_settings: "Theme Settings"
|
||||
edit_objects_theme_setting: "Objects Setting Editor"
|
||||
overriden_settings_explanation: "Overridden settings are marked with a dot and have a highlighted color. To reset these settings to the default value, press the reset button next to them."
|
||||
no_settings: "This theme has no settings."
|
||||
theme_translations: "Theme Translations"
|
||||
|
@ -14,4 +14,8 @@ class ThemeSettingsManager::Objects < ThemeSettingsManager
|
||||
theme.reload
|
||||
record.json_value
|
||||
end
|
||||
|
||||
def schema
|
||||
@opts[:schema]
|
||||
end
|
||||
end
|
||||
|
22
spec/serializers/theme_settings_serializer_spec.rb
Normal file
22
spec/serializers/theme_settings_serializer_spec.rb
Normal file
@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe ThemeSettingsSerializer do
|
||||
fab!(:theme)
|
||||
|
||||
describe "#objects_schema" do
|
||||
let(:objects_setting) do
|
||||
yaml = File.read("#{Rails.root}/spec/fixtures/theme_settings/objects_settings.yaml")
|
||||
theme.set_field(target: :settings, name: "yaml", value: yaml)
|
||||
theme.save!
|
||||
theme.settings[:objects_setting]
|
||||
end
|
||||
|
||||
before { SiteSetting.experimental_objects_type_for_theme_settings = true }
|
||||
|
||||
it "should include the attribute when theme setting is typed objects" do
|
||||
payload = ThemeSettingsSerializer.new(objects_setting).as_json
|
||||
|
||||
expect(payload[:theme_settings][:objects_schema][:name]).to eq("sections")
|
||||
end
|
||||
end
|
||||
end
|
@ -5,12 +5,13 @@ describe "Admin Customize Themes", type: :system do
|
||||
fab!(:theme)
|
||||
fab!(:admin)
|
||||
|
||||
let(:admin_customize_themes_page) { PageObjects::Pages::AdminCustomizeThemes.new }
|
||||
|
||||
before { sign_in(admin) }
|
||||
|
||||
describe "when visiting the page to customize themes" do
|
||||
fab!(:theme_2) { Fabricate(:theme) }
|
||||
fab!(:theme_3) { Fabricate(:theme) }
|
||||
let(:admin_customize_themes_page) { PageObjects::Pages::AdminCustomizeThemes.new }
|
||||
let(:delete_themes_confirm_modal) { PageObjects::Modals::DeleteThemesConfirm.new }
|
||||
|
||||
it "should allow admin to bulk delete inactive themes" do
|
||||
@ -84,4 +85,32 @@ describe "Admin Customize Themes", type: :system do
|
||||
expect(ace_content.text).to eq("console.log('test')")
|
||||
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
|
||||
end
|
||||
end
|
||||
|
@ -38,6 +38,10 @@ module PageObjects
|
||||
def click_delete_themes_button
|
||||
find(".btn-delete").click
|
||||
end
|
||||
|
||||
def click_edit_objects_theme_setting_button(setting_name)
|
||||
find(".theme-setting[data-setting=\"#{setting_name}\"] .setting-value-edit-button").click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user