DEV: Update JSON Editor to Glimmer and use new modalAPI (#22421)
This commit is contained in:
parent
d458ca154c
commit
ad1b466cd4
|
@ -2,7 +2,7 @@
|
||||||
<Textarea @value={{this.value}} class="input-setting-textarea" />
|
<Textarea @value={{this.value}} class="input-setting-textarea" />
|
||||||
{{else if this.setting.json_schema}}
|
{{else if this.setting.json_schema}}
|
||||||
<DButton
|
<DButton
|
||||||
@action={{action "launchJsonEditorModal"}}
|
@action={{fn (mut this.showJsonEditorModal) true}}
|
||||||
@icon="pencil-alt"
|
@icon="pencil-alt"
|
||||||
@label="admin.site_settings.json_schema.edit"
|
@label="admin.site_settings.json_schema.edit"
|
||||||
/>
|
/>
|
||||||
|
@ -14,3 +14,13 @@
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
<SettingValidationMessage @message={{this.validationMessage}} />
|
||||||
<div class="desc">{{html-safe this.setting.description}}</div>
|
<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}}
|
|
@ -1,20 +1,3 @@
|
||||||
import { action } from "@ember/object";
|
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import showModal from "discourse/lib/show-modal";
|
|
||||||
|
|
||||||
export default class String extends Component {
|
export default class String extends Component {}
|
||||||
@action
|
|
||||||
launchJsonEditorModal() {
|
|
||||||
const schemaModal = showModal("json-schema-editor", {
|
|
||||||
model: {
|
|
||||||
value: this.value,
|
|
||||||
settingName: this.setting.setting,
|
|
||||||
jsonSchema: this.setting.json_schema,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
schemaModal.set("onClose", () => {
|
|
||||||
this.set("value", schemaModal.model.value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
<DModalBody
|
|
||||||
@rawTitle={{i18n
|
|
||||||
"admin.site_settings.json_schema.modal_title"
|
|
||||||
name=this.settingName
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div id="json-editor-holder"></div>
|
|
||||||
</DModalBody>
|
|
||||||
|
|
||||||
<div class="modal-footer">
|
|
||||||
<DButton
|
|
||||||
@class="btn-primary"
|
|
||||||
@action={{action "saveChanges"}}
|
|
||||||
@label="save"
|
|
||||||
/>
|
|
||||||
</div>
|
|
|
@ -1,91 +0,0 @@
|
||||||
import { action } from "@ember/object";
|
|
||||||
import Component from "@ember/component";
|
|
||||||
import { create } from "virtual-dom";
|
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
|
||||||
import { iconNode } from "discourse-common/lib/icon-library";
|
|
||||||
import loadScript from "discourse/lib/load-script";
|
|
||||||
import { schedule } from "@ember/runloop";
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
className: "json-editor-holder",
|
|
||||||
editor: null,
|
|
||||||
saveChangesCallback: null,
|
|
||||||
|
|
||||||
didInsertElement() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
loadScript("/javascripts/jsoneditor.js").then(() => {
|
|
||||||
schedule("afterRender", () => {
|
|
||||||
let { JSONEditor } = window;
|
|
||||||
|
|
||||||
JSONEditor.defaults.options.theme = "bootstrap4";
|
|
||||||
JSONEditor.defaults.iconlibs = {
|
|
||||||
discourseIcons: DiscourseJsonSchemaEditorIconlib,
|
|
||||||
};
|
|
||||||
JSONEditor.defaults.options.iconlib = "discourseIcons";
|
|
||||||
|
|
||||||
const el = document.querySelector("#json-editor-holder");
|
|
||||||
this.editor = new JSONEditor(el, {
|
|
||||||
schema: this.model.jsonSchema,
|
|
||||||
disable_array_delete_all_rows: true,
|
|
||||||
disable_array_delete_last_row: true,
|
|
||||||
disable_array_reorder: false,
|
|
||||||
disable_array_copy: false,
|
|
||||||
enable_array_copy: true,
|
|
||||||
disable_edit_json: true,
|
|
||||||
disable_properties: true,
|
|
||||||
disable_collapse: false,
|
|
||||||
remove_button_labels: true,
|
|
||||||
show_errors: "never",
|
|
||||||
startval: this.model.value ? JSON.parse(this.model.value) : null,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("model.settingName")
|
|
||||||
settingName(name) {
|
|
||||||
return name.replace(/\_/g, " ");
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
saveChanges() {
|
|
||||||
const errors = this.editor.validate();
|
|
||||||
if (!errors.length) {
|
|
||||||
const fieldValue = JSON.stringify(this.editor.getValue());
|
|
||||||
this.saveChangesCallback(fieldValue);
|
|
||||||
} else {
|
|
||||||
this.appEvents.trigger("modal-body:flash", {
|
|
||||||
text: errors.mapBy("message").join("\n"),
|
|
||||||
messageClass: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
willDestroyElement() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
this.editor?.destroy();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
class DiscourseJsonSchemaEditorIconlib {
|
|
||||||
constructor() {
|
|
||||||
this.mapping = {
|
|
||||||
delete: "trash-alt",
|
|
||||||
add: "plus",
|
|
||||||
moveup: "arrow-up",
|
|
||||||
movedown: "arrow-down",
|
|
||||||
copy: "copy",
|
|
||||||
collapse: "chevron-down",
|
|
||||||
expand: "chevron-up",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
getIcon(key) {
|
|
||||||
if (!this.mapping[key]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return create(iconNode(this.mapping[key]));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<DModal
|
||||||
|
@flash={{this.flash}}
|
||||||
|
@flashType={{this.flashType}}
|
||||||
|
@closeModal={{@closeModal}}
|
||||||
|
@title={{i18n
|
||||||
|
"admin.site_settings.json_schema.modal_title"
|
||||||
|
name=@settingName
|
||||||
|
}}
|
||||||
|
class="json-schema-editor-modal"
|
||||||
|
>
|
||||||
|
<:body>
|
||||||
|
<div
|
||||||
|
id="json-editor-holder"
|
||||||
|
{{did-insert this.buildJsonEditor}}
|
||||||
|
{{will-destroy this.teardownJsonEditor}}
|
||||||
|
></div>
|
||||||
|
</:body>
|
||||||
|
|
||||||
|
<:footer>
|
||||||
|
<DButton @class="btn-primary" @action={{this.saveChanges}} @label="save" />
|
||||||
|
</:footer>
|
||||||
|
</DModal>
|
|
@ -0,0 +1,91 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { afterRender } from "discourse-common/utils/decorators";
|
||||||
|
import { create } from "virtual-dom";
|
||||||
|
import { iconNode } from "discourse-common/lib/icon-library";
|
||||||
|
import loadScript from "discourse/lib/load-script";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
|
||||||
|
export default class JsonSchemaEditorModal extends Component {
|
||||||
|
@tracked editor = null;
|
||||||
|
@tracked value = this.args.value;
|
||||||
|
@tracked flash;
|
||||||
|
@tracked flashType;
|
||||||
|
|
||||||
|
get settingName() {
|
||||||
|
return this.args.settingName.replace(/\_/g, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
buildJsonEditor(editor) {
|
||||||
|
loadScript("/javascripts/jsoneditor.js").then(
|
||||||
|
this._loadEditor.bind(this, editor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
teardownJsonEditor() {
|
||||||
|
this.editor?.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
saveChanges() {
|
||||||
|
const errors = this.editor.validate();
|
||||||
|
|
||||||
|
if (!errors.length) {
|
||||||
|
this.value = JSON.stringify(this.editor.getValue());
|
||||||
|
this.args.updateValue(this.value);
|
||||||
|
this.args.closeModal();
|
||||||
|
} else {
|
||||||
|
this.flash = errors.mapBy("message").join("\n");
|
||||||
|
this.flashType = "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@afterRender
|
||||||
|
_loadEditor(editor) {
|
||||||
|
let { JSONEditor } = window;
|
||||||
|
|
||||||
|
JSONEditor.defaults.options.theme = "bootstrap4";
|
||||||
|
JSONEditor.defaults.iconlibs = {
|
||||||
|
discourseIcons: DiscourseJsonSchemaEditorIconlib,
|
||||||
|
};
|
||||||
|
JSONEditor.defaults.options.iconlib = "discourseIcons";
|
||||||
|
|
||||||
|
this.editor = new JSONEditor(editor, {
|
||||||
|
schema: this.args.jsonSchema,
|
||||||
|
disable_array_delete_all_rows: true,
|
||||||
|
disable_array_delete_last_row: true,
|
||||||
|
disable_array_reorder: false,
|
||||||
|
disable_array_copy: false,
|
||||||
|
enable_array_copy: true,
|
||||||
|
disable_edit_json: true,
|
||||||
|
disable_properties: true,
|
||||||
|
disable_collapse: false,
|
||||||
|
remove_button_labels: true,
|
||||||
|
show_errors: "never",
|
||||||
|
startval: this.value ? JSON.parse(this.value) : null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiscourseJsonSchemaEditorIconlib {
|
||||||
|
constructor() {
|
||||||
|
this.mapping = {
|
||||||
|
delete: "trash-alt",
|
||||||
|
add: "plus",
|
||||||
|
moveup: "arrow-up",
|
||||||
|
movedown: "arrow-down",
|
||||||
|
copy: "copy",
|
||||||
|
collapse: "chevron-down",
|
||||||
|
expand: "chevron-up",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getIcon(key) {
|
||||||
|
if (!this.mapping[key]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return create(iconNode(this.mapping[key]));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
import { action } from "@ember/object";
|
|
||||||
import Controller from "@ember/controller";
|
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
|
||||||
|
|
||||||
export default Controller.extend(ModalFunctionality, {
|
|
||||||
editor: null,
|
|
||||||
|
|
||||||
@action
|
|
||||||
saveChanges(value) {
|
|
||||||
this.set("model.value", value);
|
|
||||||
this.send("closeModal");
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
<JsonEditor
|
|
||||||
@model={{this.model}}
|
|
||||||
@saveChangesCallback={{action "saveChanges"}}
|
|
||||||
@tagName=""
|
|
||||||
/>
|
|
Loading…
Reference in New Issue