From f444354f16084c03ba10bc007c3e125faf104d61 Mon Sep 17 00:00:00 2001 From: Eleazar Resendez Date: Wed, 31 Jan 2024 12:43:58 -0600 Subject: [PATCH 1/6] Applying eslint changes --- .../Http/Controllers/TemplateController.php | 3 + .../mixins/wizardHelperProcessModal.js | 273 +++++++++--------- resources/views/templates/assets.blade.php | 35 +-- 3 files changed, 155 insertions(+), 156 deletions(-) diff --git a/ProcessMaker/Http/Controllers/TemplateController.php b/ProcessMaker/Http/Controllers/TemplateController.php index 5b3c0ca76f..3169bf11a3 100644 --- a/ProcessMaker/Http/Controllers/TemplateController.php +++ b/ProcessMaker/Http/Controllers/TemplateController.php @@ -59,6 +59,9 @@ public function show(Request $request) return view('processes.modeler.showTemplate')->with('id', $response['id']); } + /** + * Renders the view for choosing template assets. + */ public function chooseTemplateAssets() { return view('templates.assets'); diff --git a/resources/js/components/templates/mixins/wizardHelperProcessModal.js b/resources/js/components/templates/mixins/wizardHelperProcessModal.js index ed8050b46a..1a7cb553a7 100644 --- a/resources/js/components/templates/mixins/wizardHelperProcessModal.js +++ b/resources/js/components/templates/mixins/wizardHelperProcessModal.js @@ -1,147 +1,142 @@ export default { - data() { - return { - task: null, - currentUserId: null, - formData: {}, - } - }, - methods: { - getHelperProcessStartEvent(triggeredBy = null) { - if (triggeredBy === 'wizard-details-modal') { - this.startEvents = this.template.process.start_events.filter(event => !event.eventDefinitions || event.eventDefinitions.length === 0); - this.helperProcessId = this.template.process.id; + data() { + return { + task: null, + currentUserId: null, + formData: {}, + }; + }, + methods: { + getHelperProcessStartEvent(triggeredBy = null) { + if (triggeredBy === "wizard-details-modal") { + this.startEvents = this.template.process.start_events + .filter((event) => !event.eventDefinitions || event.eventDefinitions.length === 0); + this.helperProcessId = this.template.process.id; - this.triggerHelperProcessStartEvent(); - } else { - if (this.wizardTemplateUuid !== null) { - ProcessMaker.apiClient.get(`wizard-templates/${this.wizardTemplateUuid}/get-helper-process`) - .then(response => { - if (response.data) { - this.helperProcessId = response.data.helper_process_id; - this.startEvents = JSON.parse(response.data.start_events).filter(event => !event.eventDefinitions || event.eventDefinitions.length === 0); + this.triggerHelperProcessStartEvent(); + } else if (this.wizardTemplateUuid !== null) { + ProcessMaker.apiClient.get(`wizard-templates/${this.wizardTemplateUuid}/get-helper-process`) + .then((response) => { + if (response.data) { + this.helperProcessId = response.data.helper_process_id; + this.startEvents = JSON.parse(response.data.start_events) + .filter((event) => !event.eventDefinitions || event.eventDefinitions.length === 0); - this.triggerHelperProcessStartEvent(); - } - }); - } + this.triggerHelperProcessStartEvent(); } - }, - triggerHelperProcessStartEvent() { - const startEventId = this.startEvents[0].id; - const url = `/process_events/${this.helperProcessId}?event=${startEventId}`; + }); + } + }, + triggerHelperProcessStartEvent() { + const startEventId = this.startEvents[0].id; + const url = `/process_events/${this.helperProcessId}?event=${startEventId}`; - // Start the helper process - window.ProcessMaker.apiClient.post(url).then(response => { - const processRequestId = response.data.id; - this.getFirstTask(processRequestId); - }).catch(error => { - console.error('Error: ', error); - ProcessMaker.alert(error.message, 'danger'); - }) - }, - getFirstTask(processRequestId) { - ProcessMaker.apiClient.get(`tasks`, { - params: { - page: 1, - include: 'user,assignableUsers', - process_request_id: processRequestId, - status: 'ACTIVE', - per_page: 10, - order_by: 'due_at', - order_direction: 'asc' - } - }).then(response => { - const taskData = response.data.data; - if (taskData.length > 0) { - this.task = taskData[0]; - this.currentUserId = parseInt(document.head.querySelector('meta[name="user-id"]').content); - this.$bvModal.show('processWizard'); - this.showHelperProcess = true; - } else { - // No task found close modal - this.showHelperProcess = false; - this.close(); - } - }).catch(error => { - console.error(error); - ProcessMaker.alert(error.message, 'danger'); - }); - }, - close() { - this.$bvModal.hide('processWizard'); - // Cancels the associated process request to prevent orphaned processes. - this.cancelHelperProcessRequest(); - }, - cancelHelperProcessRequest() { - const {process_request_id: processRequestId } = this.task; - ProcessMaker.apiClient.put(`requests/${processRequestId}`, { - status: "CANCELED" - }).then(response => { - this.showHelperProcess = false; - }).catch(error => { - console.error('Error: ', error); - ProcessMaker.alert(error.message, 'danger'); - }); - }, - taskUpdated(task) { - this.task = task; - }, - completed() { - if (this.shouldImportProcessTemplate) { - this.importProcessTemplate(); - } else { - this.showHelperProcess = false; - this.close(); - } - }, - submit(task) { - const { id: taskId } = task; - ProcessMaker.apiClient.put(`tasks/${taskId}`, { - status: "COMPLETED", - data: this.formData - }).catch(error => { - console.error('Error: ', error); - ProcessMaker.alert(error.message, 'danger'); - }); - }, - importProcessTemplate() { - ProcessMaker.apiClient.post(`template/create/process/${this.template.process_template_id}`, { - name: this.template.name, - description: this.template.description, - version: '1.0.0', // TODO: Wizards should have a versions property - process_category_id: this.template.process.process_category_id, - projects: null, - wizardTemplateUuid: this.template.uuid, - }).then(response => { - if (response.data?.existingAssets) { - this.handleExistingAssets(response.data); - } else { - // redirect to the new process launchpad - window.location = `/processes-catalogue/${response.data.processId}`; - } - }).catch(error => { - console.error('Error: ', error); - ProcessMaker.alert(error.message, 'danger'); - }); + // Start the helper process + window.ProcessMaker.apiClient.post(url).then((response) => { + const processRequestId = response.data.id; + this.getFirstTask(processRequestId); + }).catch((error) => { + ProcessMaker.alert(error.message, "danger"); + }); + }, + getFirstTask(processRequestId) { + ProcessMaker.apiClient.get("tasks", { + params: { + page: 1, + include: "user,assignableUsers", + process_request_id: processRequestId, + status: "ACTIVE", + per_page: 10, + order_by: "due_at", + order_direction: "asc", }, - handleExistingAssets(data) { - const assets = JSON.stringify(data.existingAssets); - const responseId = data.id; - const request = JSON.stringify(data.request); - window.history.pushState( - { - assets, - name: this.template.name, - responseId, - request, - redirectTo: 'process-launchpad', - wizardTemplateUuid: this.template.uuid, - }, - "", - "/template/assets", - ); - window.location = "/template/assets"; + }).then((response) => { + const [firstTask] = response.data.data; + if (firstTask) { + this.task = firstTask; + this.currentUserId = parseInt(document.head.querySelector("meta[name=\"user-id\"]").content, 10); + this.$bvModal.show("processWizard"); + this.showHelperProcess = true; + } else { + // No task found close modal + this.showHelperProcess = false; + this.close(); } + }).catch((error) => { + ProcessMaker.alert(error.message, "danger"); + }); + }, + close() { + this.$bvModal.hide("processWizard"); + // Cancels the associated process request to prevent orphaned processes. + this.cancelHelperProcessRequest(); + }, + cancelHelperProcessRequest() { + const { process_request_id: processRequestId } = this.task; + ProcessMaker.apiClient.put(`requests/${processRequestId}`, { + status: "CANCELED", + }).then(() => { + this.showHelperProcess = false; + }).catch((error) => { + ProcessMaker.alert(error.message, "danger"); + }); + }, + taskUpdated(task) { + this.task = task; + }, + completed() { + if (this.shouldImportProcessTemplate) { + this.importProcessTemplate(); + } else { + this.showHelperProcess = false; + this.close(); + } + }, + submit(task) { + const { id: taskId } = task; + ProcessMaker.apiClient.put(`tasks/${taskId}`, { + status: "COMPLETED", + data: this.formData, + }).catch((error) => { + ProcessMaker.alert(error.message, "danger"); + }); + }, + importProcessTemplate() { + ProcessMaker.apiClient.post(`template/create/process/${this.template.process_template_id}`, { + name: this.template.name, + description: this.template.description, + version: "1.0.0", // TODO: Wizards should have a versions property + process_category_id: this.template.process.process_category_id, + projects: null, + wizardTemplateUuid: this.template.uuid, + }).then((response) => { + if (response.data?.existingAssets) { + this.handleExistingAssets(response.data); + } else { + // redirect to the new process launchpad + window.location = `/processes-catalogue/${response.data.processId}`; + } + }).catch((error) => { + ProcessMaker.alert(error.message, "danger"); + }); + }, + handleExistingAssets(data) { + const assets = JSON.stringify(data.existingAssets); + const responseId = data.id; + const request = JSON.stringify(data.request); + window.history.pushState( + { + assets, + name: this.template.name, + responseId, + request, + redirectTo: "process-launchpad", + wizardTemplateUuid: this.template.uuid, + }, + "", + "/template/assets", + ); + window.location = "/template/assets"; }, -} \ No newline at end of file + }, +}; diff --git a/resources/views/templates/assets.blade.php b/resources/views/templates/assets.blade.php index 1089897347..217b76a227 100644 --- a/resources/views/templates/assets.blade.php +++ b/resources/views/templates/assets.blade.php @@ -1,34 +1,35 @@ @extends('layouts.layout') @section('title') - {{__('Template Assets')}} + {{ __('Template Assets') }} @endsection @section('sidebar') - @include('layouts.sidebar', ['sidebar'=> Menu::get('sidebar_processes')]) + @include('layouts.sidebar', ['sidebar' => Menu::get('sidebar_processes')]) @endsection @section('breadcrumbs') - @include('shared.breadcrumbs', ['routes' => [ - __('Designer') => route('processes.index'), - __('Processes') => route('processes.index') - ]]) + @include('shared.breadcrumbs', [ + 'routes' => [ + __('Designer') => route('processes.index'), + __('Processes') => route('processes.index'), + ], + ]) @endsection @section('content') -
+
- -
+ :assets="assets" + :name="name" + :responseId="responseId" + :request="request" + :redirectTo="redirectTo" + :wizardTemplateUuid="wizardTemplateUuid" + /> +
@endsection @section('js') - + @endsection From 0208f2cc95c88e24440e933d351c694a9bc153a3 Mon Sep 17 00:00:00 2001 From: Eleazar Resendez Date: Wed, 31 Jan 2024 12:47:18 -0600 Subject: [PATCH 2/6] Use localStorage instead of window.history --- .../mixins/wizardHelperProcessModal.js | 27 +++++++++---------- resources/js/templates/assets.js | 17 +++++++----- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/resources/js/components/templates/mixins/wizardHelperProcessModal.js b/resources/js/components/templates/mixins/wizardHelperProcessModal.js index 1a7cb553a7..083105da3f 100644 --- a/resources/js/components/templates/mixins/wizardHelperProcessModal.js +++ b/resources/js/components/templates/mixins/wizardHelperProcessModal.js @@ -121,21 +121,18 @@ export default { }); }, handleExistingAssets(data) { - const assets = JSON.stringify(data.existingAssets); - const responseId = data.id; - const request = JSON.stringify(data.request); - window.history.pushState( - { - assets, - name: this.template.name, - responseId, - request, - redirectTo: "process-launchpad", - wizardTemplateUuid: this.template.uuid, - }, - "", - "/template/assets", - ); + // Use local storage to pass the data to the assets page. + const stateData = { + assets: JSON.stringify(data.existingAssets), + name: this.template.name, + responseId: data.id, + request: JSON.stringify(data.request), + redirectTo: "process-launchpad", + wizardTemplateUuid: this.template.uuid, + }; + localStorage.setItem("templateAssetsState", JSON.stringify(stateData)); + + // Redirect to the assets page. window.location = "/template/assets"; }, }, diff --git a/resources/js/templates/assets.js b/resources/js/templates/assets.js index bc695cb314..dd17a9fa04 100644 --- a/resources/js/templates/assets.js +++ b/resources/js/templates/assets.js @@ -2,7 +2,7 @@ import Vue from "vue"; import TemplateAssetsView from "../components/templates/TemplateAssetsView.vue"; new Vue({ - el: '#template-asset-manager', + el: "#template-asset-manager", components: { TemplateAssetsView }, props: [], data() { @@ -16,13 +16,16 @@ new Vue({ }; }, mounted() { - this.name = window.history.state.name; - this.assets = JSON.parse(window.history.state.assets); - this.responseId = window.history.state.responseId; - this.request = window.history.state.request; + if (localStorage.getItem("templateAssetsState")) { + const stateData = JSON.parse(localStorage.getItem("templateAssetsState")); + this.name = stateData.name; + this.assets = JSON.parse(stateData.assets); + this.responseId = stateData.responseId; + this.request = stateData.request; + } - window.addEventListener('popstate', function(event) { - window.location.href = '/processes'; + window.addEventListener("popstate", (event) => { + window.location.href = "/processes"; }); }, }); From 1455f55ed281f928c45ada1f5121e766a9a770e8 Mon Sep 17 00:00:00 2001 From: Eleazar Resendez Date: Wed, 31 Jan 2024 12:50:45 -0600 Subject: [PATCH 3/6] Fix Do not use 'new' for side effects - eslintno-new --- resources/js/templates/assets.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/js/templates/assets.js b/resources/js/templates/assets.js index dd17a9fa04..cc32c4c3cd 100644 --- a/resources/js/templates/assets.js +++ b/resources/js/templates/assets.js @@ -1,7 +1,7 @@ import Vue from "vue"; import TemplateAssetsView from "../components/templates/TemplateAssetsView.vue"; -new Vue({ +const app = new Vue({ el: "#template-asset-manager", components: { TemplateAssetsView }, props: [], @@ -24,8 +24,10 @@ new Vue({ this.request = stateData.request; } - window.addEventListener("popstate", (event) => { + window.addEventListener("popstate", () => { window.location.href = "/processes"; }); }, }); + +export default app; From b377be9630714f6e9856740bdae6e321c0f10cf5 Mon Sep 17 00:00:00 2001 From: Eleazar Resendez Date: Wed, 31 Jan 2024 13:07:36 -0600 Subject: [PATCH 4/6] Applying eslint in TemplateAssetsView.vue component --- .../templates/TemplateAssetsView.vue | 100 +++++++++++------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/resources/js/components/templates/TemplateAssetsView.vue b/resources/js/components/templates/TemplateAssetsView.vue index c1c8a2e0ce..d995fb4220 100644 --- a/resources/js/components/templates/TemplateAssetsView.vue +++ b/resources/js/components/templates/TemplateAssetsView.vue @@ -1,19 +1,32 @@ @@ -56,7 +67,24 @@ const uniqIdsMixin = createUniqIdsMixin(); export default { components: { TemplateAssetTable, AssetConfirmationModal, AssetLoadingModal }, mixins: [uniqIdsMixin], - props: ['assets', 'name', 'responseId', 'request'], + props: { + assets: { + type: Array, + required: true, + }, + name: { + type: String, + required: true, + }, + responseId: { + type: String, + required: true, + }, + request: { + type: String, + required: true, + }, + }, data() { return { templateAssets: [], @@ -81,7 +109,7 @@ export default { this.templateAssets = this.assets; this.templateName = this.name; this.redirectTo = window.history.state?.redirectTo; - this.wizardTemplateUuid = window.history.state?.wizardTemplateUuid; + this.wizardTemplateUuid = window.history.state?.wizardTemplateUuid; }, methods: { reload() { @@ -91,15 +119,15 @@ export default { this.$refs.assetLoadingModal.show(); }, submitAssets() { - let formData = new FormData(); + const formData = new FormData(); formData.append("id", this.$root.responseId); formData.append("request", this.request); formData.append("existingAssets", JSON.stringify(this.updatedAssets)); if (this.wizardTemplateUuid !== null) { formData.append("wizardTemplateUuid", this.wizardTemplateUuid); - } - ProcessMaker.apiClient.post("/template/create/" + this.assetType + "/" + this.$root.responseId, formData) - .then(response => { + } + ProcessMaker.apiClient.post(`/template/create/${this.assetType}/${this.$root.responseId}`, formData) + .then((response) => { this.$nextTick(() => { this.$refs.assetLoadingModal.close(); }); @@ -107,7 +135,7 @@ export default { this.submitResponse = response.data; this.postComplete = true; this.$refs.assetConfirmationModal.show(); - }).catch(error => { + }).catch((error) => { const message = error.response?.data?.error; ProcessMaker.alert(this.$t(message), "danger"); }); @@ -131,9 +159,7 @@ export default { return this.$t("A new blank asset will be created for the new process, without modifying the previously existing one."); }, updateAssets(assets) { - const formattedAssets = assets.reduce((accumulator, group) => { - return accumulator.concat(group.items); - }, []); + const formattedAssets = assets.reduce((accumulator, group) => accumulator.concat(group.items), []); this.updatedAssets = formattedAssets; }, @@ -141,12 +167,12 @@ export default { }; - + strong { + font-weight: 700; + } + From fa95aff67d2ccd82dbb91bae40e97f23903c83e3 Mon Sep 17 00:00:00 2001 From: Eleazar Resendez Date: Wed, 31 Jan 2024 13:14:08 -0600 Subject: [PATCH 5/6] Refactor TemplateAssetsView component and assets.js This commit refactors the TemplateAssetsView component and assets.js file. It adds new props to the TemplateAssetsView component, including "request", "redirectTo", and "wizardTemplateUuid". It also updates the usage of these props in the component. In assets.js, it updates the initialization of the "responseId" and "redirectTo" variables. --- .../templates/TemplateAssetsView.vue | 19 +++++++++++-------- resources/js/templates/assets.js | 8 +++++--- resources/views/templates/assets.blade.php | 6 +++--- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/resources/js/components/templates/TemplateAssetsView.vue b/resources/js/components/templates/TemplateAssetsView.vue index d995fb4220..d0decdf8b6 100644 --- a/resources/js/components/templates/TemplateAssetsView.vue +++ b/resources/js/components/templates/TemplateAssetsView.vue @@ -81,9 +81,18 @@ export default { required: true, }, request: { + type: Object, + required: true, + }, + redirectTo: { type: String, required: true, }, + wizardTemplateUuid: { + type: String, + required: false, + default: null, + }, }, data() { return { @@ -94,12 +103,8 @@ export default { submitResponse: {}, postComplete: false, processName: "", - redirectTo: null, - wizardTemplateUuid: null, }; }, - computed: { - }, watch: { assets() { this.templateAssets = this.assets; @@ -108,8 +113,6 @@ export default { mounted() { this.templateAssets = this.assets; this.templateName = this.name; - this.redirectTo = window.history.state?.redirectTo; - this.wizardTemplateUuid = window.history.state?.wizardTemplateUuid; }, methods: { reload() { @@ -120,13 +123,13 @@ export default { }, submitAssets() { const formData = new FormData(); - formData.append("id", this.$root.responseId); + formData.append("id", this.responseId); formData.append("request", this.request); formData.append("existingAssets", JSON.stringify(this.updatedAssets)); if (this.wizardTemplateUuid !== null) { formData.append("wizardTemplateUuid", this.wizardTemplateUuid); } - ProcessMaker.apiClient.post(`/template/create/${this.assetType}/${this.$root.responseId}`, formData) + ProcessMaker.apiClient.post(`/template/create/${this.assetType}/${this.responseId}`, formData) .then((response) => { this.$nextTick(() => { this.$refs.assetLoadingModal.close(); diff --git a/resources/js/templates/assets.js b/resources/js/templates/assets.js index cc32c4c3cd..78e963dfd6 100644 --- a/resources/js/templates/assets.js +++ b/resources/js/templates/assets.js @@ -9,9 +9,9 @@ const app = new Vue({ return { assets: [], name: "", - responseId: null, + responseId: "", request: {}, - redirectTo: null, + redirectTo: "", wizardTemplateUuid: null, }; }, @@ -21,7 +21,9 @@ const app = new Vue({ this.name = stateData.name; this.assets = JSON.parse(stateData.assets); this.responseId = stateData.responseId; - this.request = stateData.request; + this.request = JSON.parse(stateData.request); + this.redirectTo = stateData.redirectTo; + this.wizardTemplateUuid = stateData.wizardTemplateUuid; } window.addEventListener("popstate", () => { diff --git a/resources/views/templates/assets.blade.php b/resources/views/templates/assets.blade.php index 217b76a227..fa79f66b2d 100644 --- a/resources/views/templates/assets.blade.php +++ b/resources/views/templates/assets.blade.php @@ -22,10 +22,10 @@ @endsection From 6ebf3c6b0a8b9e17ce1dfc21cf55a1c4ce4d2ad2 Mon Sep 17 00:00:00 2001 From: Eleazar Resendez Date: Wed, 31 Jan 2024 13:23:55 -0600 Subject: [PATCH 6/6] Update request param in submitAssets function and remove state from localStorage --- resources/js/components/templates/TemplateAssetsView.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/js/components/templates/TemplateAssetsView.vue b/resources/js/components/templates/TemplateAssetsView.vue index d0decdf8b6..5d11c7e4d5 100644 --- a/resources/js/components/templates/TemplateAssetsView.vue +++ b/resources/js/components/templates/TemplateAssetsView.vue @@ -124,7 +124,7 @@ export default { submitAssets() { const formData = new FormData(); formData.append("id", this.responseId); - formData.append("request", this.request); + formData.append("request", JSON.stringify(this.request)); formData.append("existingAssets", JSON.stringify(this.updatedAssets)); if (this.wizardTemplateUuid !== null) { formData.append("wizardTemplateUuid", this.wizardTemplateUuid); @@ -134,6 +134,9 @@ export default { this.$nextTick(() => { this.$refs.assetLoadingModal.close(); }); + // Remove the state from local storage. + localStorage.removeItem("templateAssetsState"); + this.processName = response.data.processName; this.submitResponse = response.data; this.postComplete = true;