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" />
|
||||
{{else if this.setting.json_schema}}
|
||||
<DButton
|
||||
@action={{action "launchJsonEditorModal"}}
|
||||
@action={{fn (mut this.showJsonEditorModal) true}}
|
||||
@icon="pencil-alt"
|
||||
@label="admin.site_settings.json_schema.edit"
|
||||
/>
|
||||
|
@ -13,4 +13,14 @@
|
|||
{{/if}}
|
||||
|
||||
<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 showModal from "discourse/lib/show-modal";
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
export default class String extends Component {}
|
||||
|
|
|
@ -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