From a8dfaf4de4bb282f9b568dee8e3df904b2e220bf Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Mon, 31 Aug 2020 17:29:28 +0000 Subject: [PATCH] --- ayanova/src/router.js | 2 +- ayanova/src/views/ay-report-edit.vue | 466 +++++++++++++++++++++++++-- 2 files changed, 447 insertions(+), 21 deletions(-) diff --git a/ayanova/src/router.js b/ayanova/src/router.js index 378b6f34..53cff86b 100644 --- a/ayanova/src/router.js +++ b/ayanova/src/router.js @@ -521,7 +521,7 @@ export default new Router({ import(/* webpackChunkName: "ay-common" */ "./views/ay-report.vue") }, { - path: "/report-edit/:reportid", + path: "/report-edit/:recordid", name: "ay-report-edit", component: () => import( diff --git a/ayanova/src/views/ay-report-edit.vue b/ayanova/src/views/ay-report-edit.vue index c9ddc834..6128109a 100644 --- a/ayanova/src/views/ay-report-edit.vue +++ b/ayanova/src/views/ay-report-edit.vue @@ -60,31 +60,82 @@ import * as monaco from "monaco-editor"; //https://github.com/egoist/vue-monaco/blob/master/src/MonacoEditor.js const FORM_KEY = "ay-report-edit"; +let JUST_DELETED = false; export default { + async created() { + let vm = this; + try { + await initForm(vm); + + vm.rights = window.$gz.role.getRights(window.$gz.type.Report); + vm.formState.readOnly = !vm.rights.change; + window.$gz.eventBus.$on("menu-click", clickHandler); + + //id 0 means create a new record don't load one + if (vm.$route.params.recordid != 0) { + //is there already an obj from a prior operation? + if (this.$route.params.obj) { + //yes, no need to fetch it + this.obj = this.$route.params.obj; + window.$gz.form.setFormState({ + vm: vm, + loading: false + }); + } else { + await vm.getDataFromApi(vm.$route.params.recordid); //let getdata handle loading + } + } else { + window.$gz.form.setFormState({ + vm: vm, + loading: false + }); + } + window.$gz.form.setFormState({ + vm: vm, + dirty: false, + valid: true + }); + + generateMenu(vm); + } catch (error) { + window.$gz.errorHandler.handleFormError(error, vm); + } finally { + vm.formState.ready = true; + } + }, mounted() { - let monacoOptions = { - value: 'console.log("Hello, world");', - theme: "vs", - language: "javascript" - }; - this.editor = monaco.editor.create( - document.getElementById("editContainer"), - null - ); - this.showEditor = false; + /* + data.js.model = monaco.editor.createModel('console.log("hi")', 'javascript'); + data.css.model = monaco.editor.createModel('css', 'css'); + data.html.model = monaco.editor.createModel('html', 'html'); + + editor = monaco.editor.create(editorContainer, { + model: data.js.model, + minimap: { + enabled: false + } + }); + */ + + // let monacoOptions = { + // value: 'console.log("Hello, world");', + // theme: "vs", + // language: "javascript" + // }; + let vm = this; + vm.editData.template.model = monaco.editor.createModel("", "javascript"); + vm.editData.style.model = monaco.editor.createModel("css", "css"); + vm.editData.jsPrerender.model = monaco.editor.createModel("", "javascript"); + vm.editData.jsHelpers.model = monaco.editor.createModel("", "javascript"); + vm.editor = monaco.editor.create(document.getElementById("editContainer"), { + model: vm.editData.template.model + }); + vm.showEditor = false; }, beforeDestroy() { this.editor && this.editor.dispose(); }, - beforeCreate() { - window.$gz.eventBus.$emit("menu-change", { - isMain: false, - icon: "fa-drafting-compass", - title: "ReportDesignReport", - helpUrl: "form-ay-report-edit" - }); - }, - created() {}, + data() { return { search: "", @@ -99,6 +150,24 @@ export default { activeTab: "properties", lastTab: "properties", showEditor: true, + editData: { + template: { + model: null, + state: null + }, + style: { + model: null, + state: null + }, + jsPrerender: { + model: null, + state: null + }, + jsHelpers: { + model: null, + state: null + } + }, obj: { id: 0, concurrency: 0, @@ -161,7 +230,7 @@ import router from "./router"; // console.log(`Switching from ${vm.lastTab} to ${vm.activeTab}`); // console.log("editor", editor); - todo: use function below for inspiration to save editor state and contents as necessary and switch views + //todo: use function below for inspiration to save editor state and contents as necessary and switch views //Note that properties tab doesn't mean need to dump editor as user could be switching back and forth //so really the lasttab needs to be the last edited tab because we don't need to save when going to properties from script and back again @@ -235,7 +304,364 @@ import router from "./router"; if (this.editor != null) { this.editor.layout(); } + }, + canSave: function() { + return this.formState.valid && this.formState.dirty; + }, + canDuplicate: function() { + return this.formState.valid && !this.formState.dirty; + }, + ayaTypes: function() { + return window.$gz.type; + }, + form() { + return window.$gz.form; + }, + fieldValueChanged(ref) { + if ( + this.formState.ready && + !this.formState.loading && + !this.formState.readOnly + ) { + window.$gz.form.fieldValueChanged(this, ref); + } + }, + async getDataFromApi(recordId) { + let vm = this; + window.$gz.form.setFormState({ + vm: vm, + loading: true + }); + if (!recordId) { + throw FORM_KEY + "::getDataFromApi -> Missing recordID!"; + } + let url = "report/" + recordId; + try { + window.$gz.form.deleteAllErrorBoxErrors(vm); + + let res = await window.$gz.api.get(url); + + if (res.error) { + //Not found? + if (res.error.code == "2010") { + //notify not found error then navigate backwards + window.$gz.eventBus.$emit("notify-error", vm.$ay.t("ErrorAPI2010")); + // navigate backwards + window.$gz._.delay(function() { + vm.$router.go(-1); + }, 2000); + } + vm.formState.serverError = res.error; + window.$gz.form.setErrorBoxErrors(vm); + } else { + vm.obj = res.data; + //modify the menu as necessary + generateMenu(vm); + //Update the form status + window.$gz.form.setFormState({ + vm: vm, + dirty: false, + valid: true, + loading: false + }); + } + } catch (error) { + window.$gz.errorHandler.handleFormError(error, vm); + } finally { + window.$gz.form.setFormState({ + vm: vm, + loading: false + }); + } + }, + async submit() { + let vm = this; + if (vm.canSave == false) { + return; + } + + try { + window.$gz.form.setFormState({ + vm: vm, + loading: true + }); + let url = "report/"; // + vm.$route.params.recordid; + //clear any errors vm might be around from previous submit + window.$gz.form.deleteAllErrorBoxErrors(vm); + + let res = await window.$gz.api.upsert(url, vm.obj); + + if (res.error) { + vm.formState.serverError = res.error; + window.$gz.form.setErrorBoxErrors(vm); + } else { + //Logic for detecting if a post or put: if id then it was a post, if no id then it was a put + if (res.data.id) { + //POST - whole new object returned + vm.obj = res.data; + //Change URL to new record + //NOTE: will not cause a page re-render, almost nothing does unless forced with a KEY property or using router.GO() + + this.$router.push({ + name: "widget-edit", + params: { + recordid: res.data.id, + obj: res.data // Pass data object to new form + } + }); + } else { + //PUT - only concurrency token is returned (**warning, if server changes object other fields then this needs to act more like POST above but is more efficient this way**) + //Handle "put" of an existing record (UPDATE) + vm.obj.concurrency = res.data.concurrency; + } + //Update the form status + window.$gz.form.setFormState({ + vm: vm, + dirty: false, + valid: true + }); + } + } catch (ex) { + window.$gz.errorHandler.handleFormError(ex, vm); + } finally { + window.$gz.form.setFormState({ + vm: vm, + loading: false + }); + } + }, + async remove() { + let vm = this; + try { + let dialogResult = await window.$gz.dialog.confirmDelete(); + if (dialogResult != true) { + return; + } + + //do the delete + window.$gz.form.setFormState({ + vm: vm, + loading: true + }); + //No need to delete a new record, just abandon it... + if (vm.$route.params.recordid == 0) { + //this should not get offered for delete but to be safe and clear just in case: + JUST_DELETED = true; + // navigate backwards + vm.$router.go(-1); + } else { + let url = "report/" + vm.$route.params.recordid; + + window.$gz.form.deleteAllErrorBoxErrors(vm); + let res = await window.$gz.api.remove(url); + if (res.error) { + vm.formState.serverError = res.error; + window.$gz.form.setErrorBoxErrors(vm); + } else { + //workaround to prevent warning about leaving dirty record + //For some reason I couldn't just reset isdirty in formstate + JUST_DELETED = true; + // navigate backwards + vm.$router.go(-1); + } + } + } catch (error) { + //Update the form status + window.$gz.form.setFormState({ + vm: vm, + loading: false + }); + window.$gz.errorHandler.handleFormError(error, vm); + } + }, + async duplicate() { + let vm = this; + if (!vm.canDuplicate || vm.$route.params.recordid == 0) { + return; + } + window.$gz.form.setFormState({ + vm: vm, + loading: true + }); + let url = "report/duplicate/" + vm.$route.params.recordid; + + try { + window.$gz.form.deleteAllErrorBoxErrors(vm); + let res = await window.$gz.api.upsert(url); + if (res.error) { + vm.formState.serverError = res.error; + window.$gz.form.setErrorBoxErrors(vm); + } else { + //Navigate to new record + this.$router.push({ + name: "widget-edit", + params: { + recordid: res.data.id, + obj: res.data // Pass data object to new form + } + }); + } + } catch (ex) { + window.$gz.errorHandler.handleFormError(ex, vm); + } finally { + window.$gz.form.setFormState({ + vm: vm, + loading: false + }); + } } } }; + +///////////////////////////// +// +// +async function clickHandler(menuItem) { + if (!menuItem) { + return; + } + let m = window.$gz.menu.parseMenuItem(menuItem); + if (m.owner == FORM_KEY && !m.disabled) { + switch (m.key) { + case "save": + m.vm.submit(); + break; + case "delete": + m.vm.remove(); + break; + case "new": + m.vm.$router.push({ + name: "widget-edit", + params: { recordid: 0, new: true } + }); + break; + case "duplicate": + m.vm.duplicate(); + break; + case "report": + if (m.id != null) { + //last report selected + m.vm.$router.push({ + name: "ay-report", + params: { recordid: m.id, ayatype: window.$gz.type.Widget } + }); + } else { + //general report selector chosen + let res = await m.vm.$refs.reportSelector.open(); + + //if null for no selection + //just bail out + if (res == null) { + return; + } + //persist last report selected + window.$gz.form.setLastReport(FORM_KEY, res); + + //Now open the report viewer... + m.vm.$router.push({ + name: "ay-report", + params: { recordid: res.id, ayatype: window.$gz.type.Widget } + }); + } + break; + default: + window.$gz.eventBus.$emit( + "notify-warning", + FORM_KEY + "::context click: [" + m.key + "]" + ); + } + } +} + +////////////////////// +// +// +function generateMenu(vm) { + let menuOptions = { + isMain: false, + icon: "fa-drafting-compass", + title: "ReportDesignReport", + helpUrl: "form-ay-report-edit", + formData: { + ayaType: window.$gz.type.Report, + recordId: vm.$route.params.recordid + }, + menuItems: [] + }; + + if (vm.rights.change) { + menuOptions.menuItems.push({ + title: "Save", + icon: "fa-save", + surface: true, + key: FORM_KEY + ":save", + vm: vm + }); + } + + if (vm.rights.delete && vm.$route.params.recordid != 0) { + menuOptions.menuItems.push({ + title: "Delete", + icon: "fa-trash-alt", + surface: true, + key: FORM_KEY + ":delete", + vm: vm + }); + } + + // //STUB REPORTS + // //Report not Print, print is a further option + // menuOptions.menuItems.push({ + // title: "Report", + // icon: "fa-file-alt", + // key: FORM_KEY + ":report", + // vm: vm + // }); + + // //get last report selected + // let lastReport = window.$gz.form.getLastReport(FORM_KEY); + // if (lastReport != null) { + // menuOptions.menuItems.push({ + // title: lastReport.name, + // icon: "fa-file-alt", + // key: FORM_KEY + ":report:" + lastReport.id, + // vm: vm + // }); + // } + + if (vm.rights.change) { + menuOptions.menuItems.push({ + title: "New", + icon: "fa-plus", + key: FORM_KEY + ":new", + vm: vm + }); + } + + if (vm.rights.change) { + menuOptions.menuItems.push({ + title: "Duplicate", + icon: "fa-clone", + key: FORM_KEY + ":duplicate", + vm: vm + }); + } + + window.$gz.eventBus.$emit("menu-change", menuOptions); +} +///////////////////////////////// +// +// +async function initForm(vm) { + await fetchTranslatedText(vm); + // await populateSelectionLists(vm); +} + +////////////////////////////////////////////////////////// +// +// Ensures UI translated text is available +// +async function fetchTranslatedText(vm) { + await window.$gz.translation.cacheTranslations(["ReportDesignReport"]); +}