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/TemplateAssetsView.vue b/resources/js/components/templates/TemplateAssetsView.vue index c1c8a2e0ce..5d11c7e4d5 100644 --- a/resources/js/components/templates/TemplateAssetsView.vue +++ b/resources/js/components/templates/TemplateAssetsView.vue @@ -1,19 +1,32 @@ @@ -56,7 +67,33 @@ 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: Object, + required: true, + }, + redirectTo: { + type: String, + required: true, + }, + wizardTemplateUuid: { + type: String, + required: false, + default: null, + }, + }, data() { return { templateAssets: [], @@ -66,12 +103,8 @@ export default { submitResponse: {}, postComplete: false, processName: "", - redirectTo: null, - wizardTemplateUuid: null, }; }, - computed: { - }, watch: { assets() { this.templateAssets = this.assets; @@ -80,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() { @@ -91,23 +122,26 @@ export default { this.$refs.assetLoadingModal.show(); }, submitAssets() { - let formData = new FormData(); - formData.append("id", this.$root.responseId); - formData.append("request", this.request); + const formData = new FormData(); + formData.append("id", this.responseId); + formData.append("request", JSON.stringify(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.responseId}`, formData) + .then((response) => { 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; this.$refs.assetConfirmationModal.show(); - }).catch(error => { + }).catch((error) => { const message = error.response?.data?.error; ProcessMaker.alert(this.$t(message), "danger"); }); @@ -131,9 +165,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 +173,12 @@ export default { }; - + strong { + font-weight: 700; + } + diff --git a/resources/js/components/templates/mixins/wizardHelperProcessModal.js b/resources/js/components/templates/mixins/wizardHelperProcessModal.js index ed8050b46a..083105da3f 100644 --- a/resources/js/components/templates/mixins/wizardHelperProcessModal.js +++ b/resources/js/components/templates/mixins/wizardHelperProcessModal.js @@ -1,147 +1,139 @@ 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) { + // 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"; }, -} \ No newline at end of file + }, +}; diff --git a/resources/js/templates/assets.js b/resources/js/templates/assets.js index bc695cb314..78e963dfd6 100644 --- a/resources/js/templates/assets.js +++ b/resources/js/templates/assets.js @@ -1,28 +1,35 @@ import Vue from "vue"; import TemplateAssetsView from "../components/templates/TemplateAssetsView.vue"; -new Vue({ - el: '#template-asset-manager', +const app = new Vue({ + el: "#template-asset-manager", components: { TemplateAssetsView }, props: [], data() { return { assets: [], name: "", - responseId: null, + responseId: "", request: {}, - redirectTo: null, + redirectTo: "", wizardTemplateUuid: null, }; }, 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 = JSON.parse(stateData.request); + this.redirectTo = stateData.redirectTo; + this.wizardTemplateUuid = stateData.wizardTemplateUuid; + } - window.addEventListener('popstate', function(event) { - window.location.href = '/processes'; + window.addEventListener("popstate", () => { + window.location.href = "/processes"; }); }, }); + +export default app; diff --git a/resources/views/templates/assets.blade.php b/resources/views/templates/assets.blade.php index 1089897347..fa79f66b2d 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" + :response-id="responseId" + :request="request" + :redirect-to="redirectTo" + :wizard-template-uuid="wizardTemplateUuid" + /> +
@endsection @section('js') - + @endsection