diff --git a/ProcessMaker/Http/Controllers/Api/ProcessController.php b/ProcessMaker/Http/Controllers/Api/ProcessController.php index a133c85064..cd1efe76c1 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessController.php @@ -998,6 +998,49 @@ public function import(Process $process, Request $request) ]); } + /** + * Download the BPMN definition of a process + * + * @param $process + * + * @return Response + * + * @OA\Get( + * path="/processes/{processId}/bpmn", + * summary="Download the BPMN definition of a process", + * operationId="processBpmn", + * tags={"Processes"}, + * @OA\Parameter( + * description="ID of process", + * in="path", + * name="processId", + * required=true, + * @OA\Schema( + * type="integer", + * ) + * ), + * @OA\Response( + * response=200, + * description="Successfully built the process for export", + * @OA\JsonContent( + * type="object", + * @OA\Property( + * property="url", + * type="string", + * ), + * ), + * ), + * ) + */ + public function downloadBpmn(Request $request, Process $process) + { + $bpmn = $process->bpmn; + $filename = 'bpmnProcess.bpmn'; + return response()->streamDownload(function () use ($bpmn) { + echo $bpmn; + }, $filename); + } + /** * Check if the import is ready * diff --git a/resources/js/components/shared/EllipsisMenu.vue b/resources/js/components/shared/EllipsisMenu.vue index c9dca6791f..6057c3399c 100644 --- a/resources/js/components/shared/EllipsisMenu.vue +++ b/resources/js/components/shared/EllipsisMenu.vue @@ -56,21 +56,24 @@
- -
- - {{ $t(action.content) }} -
-
+
+ + +
+ + {{ $t(action.content) }} +
+
+ +
diff --git a/resources/js/processes/components/ProcessesListing.vue b/resources/js/processes/components/ProcessesListing.vue index 0a9f1cb8f1..6ab1c8d833 100644 --- a/resources/js/processes/components/ProcessesListing.vue +++ b/resources/js/processes/components/ProcessesListing.vue @@ -51,7 +51,7 @@ :permission="permission" :data="props.rowData" :is-documenter-installed="isDocumenterInstalled" - :divider="true" + :divider="false" /> @@ -95,9 +95,11 @@ { value: "create-pm-block", content: "Save as PM Block", permission: "create-pm-blocks", icon: "fas nav-icon fa-cube" }, { value: "edit-item", content: "Configure", link: true, href:"/processes/{{id}}/edit", permission: "edit-processes", icon: "fas fa-cog", conditional: "if(status == 'ACTIVE' or status == 'INACTIVE', true, false)"}, { value: "view-documentation", content: "View Documentation", link: true, href:"/modeler/{{id}}/print", permission: "view-processes", icon: "fas fa-sign", conditional: "isDocumenterInstalled"}, + { value: "remove-item", content: "Archive", permission: "archive-processes", icon: "fas fa-archive", conditional: "if(status == 'ACTIVE' or status == 'INACTIVE', true, false)" }, + { value: "divider" }, { value: "export-item", content: "Export", link: true, href:"/processes/{{id}}/export", permission: "export-processes", icon: "fas fa-file-export"}, - { value: "remove-item", content: "Archive", permission: "archive-processes", icon: "fas fa-download", conditional: "if(status == 'ACTIVE' or status == 'INACTIVE', true, false)" }, { value: "restore-item", content: "Restore", permission: "archive-processes", icon: "fas fa-upload", conditional: "if(status == 'ARCHIVED', true, false)" }, + { value: "download-bpmn", content: "Download BPMN", permission: "view-processes", icon: "fas fa-file-download"}, ], orderBy: "name", processId: null, @@ -235,6 +237,33 @@ } ); break; + + case "download-bpmn": + ProcessMaker.confirmModal( + this.$t("Caution!"), + this.$t("Are you sure you want to download the BPMN definition of the process?"), + "", + () => { + ProcessMaker.apiClient + .get("processes/" + data.id + "/bpmn") + .then(response => { + + const link = document.createElement("a"); + const file = new Blob([response.data], { type: 'text/plain' }); + + link.href = URL.createObjectURL(file); + link.download = "bpmnProcess.xml"; + link.click(); + URL.revokeObjectURL(link.href); + + ProcessMaker.alert( + this.$t("The process BPMN has been downloaded."), + "success" + ); + }); + } + ); + break; } }, formatStatus(status) { diff --git a/resources/js/processes/modeler/components/ModelerApp.vue b/resources/js/processes/modeler/components/ModelerApp.vue index 428839886c..d0baa89850 100644 --- a/resources/js/processes/modeler/components/ModelerApp.vue +++ b/resources/js/processes/modeler/components/ModelerApp.vue @@ -15,6 +15,7 @@ ref="modeler" :owner="self" :decorations="decorations" + :validationBar="validationBar" @validate="validationErrors = $event" @warnings="warnings = $event" @saveBpmn="emitSaveEvent" @@ -25,22 +26,12 @@ @set-xml-manager="xmlManager = $event" /> - - - - - + /> name('processes.index')->middleware('can:view-processes'); Route::get('processes/{process}', [ProcessController::class, 'show'])->name('processes.show')->middleware('can:view-processes'); Route::post('processes/{process}/export', [ProcessController::class, 'export'])->name('processes.export')->middleware('can:export-processes'); + Route::get('processes/{process}/bpmn', [ProcessController::class, 'downloadBpmn'])->name('processes.export')->middleware('can:view-processes'); Route::post('processes/import', [ProcessController::class, 'import'])->name('processes.import')->middleware('can:import-processes'); Route::post('processes/import/validation', [ProcessController::class, 'preimportValidation'])->name('processes.preimportValidation')->middleware('can:import-processes'); Route::get('processes/import/{code}/is_ready', [ProcessController::class, 'import_ready'])->name('processes.import_is_ready')->middleware('can:import-processes');