From ca982d495593f26a12aa730c90d5e6bef3e50570 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Fri, 23 Aug 2024 16:10:59 -0400 Subject: [PATCH 01/25] fix: remove htmlspecialchars from the elementDestination data --- ProcessMaker/ImportExport/Exporters/ProcessExporter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProcessMaker/ImportExport/Exporters/ProcessExporter.php b/ProcessMaker/ImportExport/Exporters/ProcessExporter.php index 01b30129e3..90a9d7d5b1 100644 --- a/ProcessMaker/ImportExport/Exporters/ProcessExporter.php +++ b/ProcessMaker/ImportExport/Exporters/ProcessExporter.php @@ -564,7 +564,7 @@ public function importElementDestination(): void // Set the new attribute value at the specified XPath Utils::setAttributeAtXPath( $this->model, $path, self::PM_ELEMENT_DESTINATION, - htmlspecialchars($newElementDestination, ENT_QUOTES) + $newElementDestination ); } } From 40c116a4c2dd53ef5a82e4240893956aee7be37b Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Mon, 26 Aug 2024 14:37:54 -0700 Subject: [PATCH 02/25] Remove and prevent duplicate default interstitials --- .../Http/Controllers/Api/ScreenController.php | 2 +- .../ImportExport/Exporters/ScreenExporter.php | 5 ++ .../components/inspector/ScreenSelect.vue | 6 ++- ..._08_26_205409_remove_interstitial_keys.php | 52 +++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 upgrades/2024_08_26_205409_remove_interstitial_keys.php diff --git a/ProcessMaker/Http/Controllers/Api/ScreenController.php b/ProcessMaker/Http/Controllers/Api/ScreenController.php index 2150391a83..ededcb33f8 100644 --- a/ProcessMaker/Http/Controllers/Api/ScreenController.php +++ b/ProcessMaker/Http/Controllers/Api/ScreenController.php @@ -419,7 +419,7 @@ public function duplicate(Screen $screen, Request $request) $request->validate(Screen::rules()); $newScreen = new Screen(); - $exclude = ['id', 'uuid', 'created_at', 'updated_at']; + $exclude = ['id', 'uuid', 'created_at', 'updated_at', 'key']; foreach ($screen->getAttributes() as $attribute => $value) { if (!in_array($attribute, $exclude)) { $newScreen->{$attribute} = $screen->{$attribute}; diff --git a/ProcessMaker/ImportExport/Exporters/ScreenExporter.php b/ProcessMaker/ImportExport/Exporters/ScreenExporter.php index 1219e11766..badc28a03f 100644 --- a/ProcessMaker/ImportExport/Exporters/ScreenExporter.php +++ b/ProcessMaker/ImportExport/Exporters/ScreenExporter.php @@ -66,6 +66,11 @@ public function import() : bool $this->associateCategories(ScreenCategory::class, 'screen_category_id'); $screen->watchers = $watchers; + // There should only be one default interstitial screen + if ($screen->key === 'interstitial') { + $screen->key = null; + } + $success = $screen->saveOrFail(); return $success; diff --git a/resources/js/processes/modeler/components/inspector/ScreenSelect.vue b/resources/js/processes/modeler/components/inspector/ScreenSelect.vue index bff4b29211..a4402ed070 100644 --- a/resources/js/processes/modeler/components/inspector/ScreenSelect.vue +++ b/resources/js/processes/modeler/components/inspector/ScreenSelect.vue @@ -183,7 +183,11 @@ export default { } ProcessMaker.apiClient - .get("screens", { params: { key: this.defaultKey } }) + .get("screens", { params: { + key: this.defaultKey, + order_by: "id", + order_direction: "ASC" + }}) .then(({ data }) => { this.content = data.data[0]; }); diff --git a/upgrades/2024_08_26_205409_remove_interstitial_keys.php b/upgrades/2024_08_26_205409_remove_interstitial_keys.php new file mode 100644 index 0000000000..82e2300cc1 --- /dev/null +++ b/upgrades/2024_08_26_205409_remove_interstitial_keys.php @@ -0,0 +1,52 @@ +orderBy('id', 'ASC')->first(); + if (!$firstInterstitial) { + return; + } + Screen::where('key', 'interstitial') + ->whereNot('id', $firstInterstitial->id) + ->update(['key' => null]); + } + + /** + * Reverse the upgrade migration. + * + * @return void + */ + public function down() + { + } +} From 7b8e11e49bfd872fc55ab3efce808e70e7a7c49a Mon Sep 17 00:00:00 2001 From: Sanja Date: Mon, 26 Aug 2024 14:42:10 -0700 Subject: [PATCH 03/25] Temporary solution: Prevent the endEvent Element destination redirect on GUIDED_HELPER_PROCESS asset types --- ProcessMaker/Events/ProcessCompleted.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ProcessMaker/Events/ProcessCompleted.php b/ProcessMaker/Events/ProcessCompleted.php index be95f14dae..b0f160a462 100644 --- a/ProcessMaker/Events/ProcessCompleted.php +++ b/ProcessMaker/Events/ProcessCompleted.php @@ -28,7 +28,10 @@ public function __construct(ProcessRequest $processRequest) { $this->payloadUrl = route('api.requests.show', ['request' => $processRequest->getKey()]); $this->processRequest = $processRequest; - $this->endEventDestination = $processRequest->getElementDestination(); + + if ($processRequest->asset_type !== 'GUIDED_HELPER_PROCESS') { + $this->endEventDestination = $processRequest->getElementDestination(); + } } /** From d197183496e7b87d961634ae242eb65e189d8da9 Mon Sep 17 00:00:00 2001 From: Sanja Date: Mon, 26 Aug 2024 14:55:55 -0700 Subject: [PATCH 04/25] Temp fix: Update conditional to include process->asset_type --- ProcessMaker/Events/ProcessCompleted.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProcessMaker/Events/ProcessCompleted.php b/ProcessMaker/Events/ProcessCompleted.php index b0f160a462..566fd59730 100644 --- a/ProcessMaker/Events/ProcessCompleted.php +++ b/ProcessMaker/Events/ProcessCompleted.php @@ -29,7 +29,7 @@ public function __construct(ProcessRequest $processRequest) $this->payloadUrl = route('api.requests.show', ['request' => $processRequest->getKey()]); $this->processRequest = $processRequest; - if ($processRequest->asset_type !== 'GUIDED_HELPER_PROCESS') { + if ($processRequest->process->asset_type !== 'GUIDED_HELPER_PROCESS') { $this->endEventDestination = $processRequest->getElementDestination(); } } From 1dbaaba1245f2659402a98de435f5a6f3cdbb120 Mon Sep 17 00:00:00 2001 From: Sanja Date: Mon, 26 Aug 2024 16:37:22 -0700 Subject: [PATCH 05/25] Remove interstitial key from guided template screens --- ProcessMaker/Jobs/SyncGuidedTemplates.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ProcessMaker/Jobs/SyncGuidedTemplates.php b/ProcessMaker/Jobs/SyncGuidedTemplates.php index edb3a69aab..46710f8004 100644 --- a/ProcessMaker/Jobs/SyncGuidedTemplates.php +++ b/ProcessMaker/Jobs/SyncGuidedTemplates.php @@ -8,6 +8,7 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\Http; use Illuminate\Support\Str; use Log; @@ -208,6 +209,10 @@ private function importProcess($payload, $assetType) 'Collections', 'DataConnector', 'ProcessTemplates'])) { $payload['export'][$key]['attributes']['asset_type'] = $assetType; } + + if (Arr::get($asset, 'type') === 'Screen' && Arr::get($asset, 'attributes.key') === 'interstitial') { + $payload['export'][$key]['attributes']['key'] = null; + } } $options = new Options($postOptions); From cb84cd96bf23ede0f3262ca640a6cc2d838c64c5 Mon Sep 17 00:00:00 2001 From: Sanja Date: Mon, 26 Aug 2024 17:08:39 -0700 Subject: [PATCH 06/25] Refactor: Update to use Arr::set --- ProcessMaker/Jobs/SyncGuidedTemplates.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProcessMaker/Jobs/SyncGuidedTemplates.php b/ProcessMaker/Jobs/SyncGuidedTemplates.php index 46710f8004..a0494fcaab 100644 --- a/ProcessMaker/Jobs/SyncGuidedTemplates.php +++ b/ProcessMaker/Jobs/SyncGuidedTemplates.php @@ -211,7 +211,7 @@ private function importProcess($payload, $assetType) } if (Arr::get($asset, 'type') === 'Screen' && Arr::get($asset, 'attributes.key') === 'interstitial') { - $payload['export'][$key]['attributes']['key'] = null; + Arr::set($payload, "export.{$key}.attributes.key", null); } } From 6a599370127b2f04ebd95925b2075836007ff14e Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Mon, 26 Aug 2024 17:08:58 -0700 Subject: [PATCH 07/25] Update to match description --- .../processes/modeler/components/inspector/ScreenSelect.vue | 3 ++- upgrades/2024_08_26_205409_remove_interstitial_keys.php | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/js/processes/modeler/components/inspector/ScreenSelect.vue b/resources/js/processes/modeler/components/inspector/ScreenSelect.vue index a4402ed070..93f9372fed 100644 --- a/resources/js/processes/modeler/components/inspector/ScreenSelect.vue +++ b/resources/js/processes/modeler/components/inspector/ScreenSelect.vue @@ -186,7 +186,8 @@ export default { .get("screens", { params: { key: this.defaultKey, order_by: "id", - order_direction: "ASC" + order_direction: "ASC", + per_page: 1, }}) .then(({ data }) => { this.content = data.data[0]; diff --git a/upgrades/2024_08_26_205409_remove_interstitial_keys.php b/upgrades/2024_08_26_205409_remove_interstitial_keys.php index 82e2300cc1..acb272fae5 100644 --- a/upgrades/2024_08_26_205409_remove_interstitial_keys.php +++ b/upgrades/2024_08_26_205409_remove_interstitial_keys.php @@ -32,7 +32,9 @@ public function preflightChecks() */ public function up() { - $firstInterstitial = Screen::where('key', 'interstitial')->orderBy('id', 'ASC')->first(); + $firstInterstitial = Screen::where('key', 'interstitial') + ->where('description', 'Screen for the interstitial') + ->orderBy('id', 'ASC')->first(); if (!$firstInterstitial) { return; } From 660d51de0b47066a3197566c655c766838bb57aa Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Mon, 26 Aug 2024 17:23:00 -0700 Subject: [PATCH 08/25] Reset name in case it changed --- upgrades/2024_08_26_205409_remove_interstitial_keys.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/upgrades/2024_08_26_205409_remove_interstitial_keys.php b/upgrades/2024_08_26_205409_remove_interstitial_keys.php index acb272fae5..75a4b9415f 100644 --- a/upgrades/2024_08_26_205409_remove_interstitial_keys.php +++ b/upgrades/2024_08_26_205409_remove_interstitial_keys.php @@ -41,6 +41,10 @@ public function up() Screen::where('key', 'interstitial') ->whereNot('id', $firstInterstitial->id) ->update(['key' => null]); + + $firstInterstitial->title = 'Screen Interstitial'; + $firstInterstitial->asset_type = null; + $firstInterstitial->save(); } /** From ec64205787c4028b3d9ab61a0716f6cf0c496353 Mon Sep 17 00:00:00 2001 From: Ryan Cooley Date: Mon, 26 Aug 2024 17:31:20 -0700 Subject: [PATCH 09/25] Update AI package --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 01b6bb0248..097dbae53e 100644 --- a/composer.json +++ b/composer.json @@ -146,7 +146,7 @@ "package-ab-testing": "1.3.0", "package-actions-by-email": "1.19.0", "package-advanced-user-manager": "1.11.0", - "package-ai": "1.11.0", + "package-ai": "1.11.1", "package-analytics-reporting": "1.9.0", "package-auth": "1.21.0", "package-cdata": "1.4.5", From 6c49ed878ce3e22ecee0c49fb475d7b586baa804 Mon Sep 17 00:00:00 2001 From: Ryan Cooley Date: Mon, 26 Aug 2024 17:32:35 -0700 Subject: [PATCH 10/25] Version 4.11.0-RC2 Build #41e4c495 --- composer.json | 4 ++-- composer.lock | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 097dbae53e..4ac319bcf8 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "processmaker/processmaker", - "version": "4.11.0-RC1", + "version": "4.11.0-RC2", "description": "BPM PHP Software", "keywords": [ "php bpm processmaker" @@ -104,7 +104,7 @@ "Gmail" ], "processmaker": { - "build": "bb755bdb", + "build": "41e4c495", "custom": { "package-ellucian-ethos": "1.16.0", "package-plaid": "1.6.0", diff --git a/composer.lock b/composer.lock index 2200892f45..ffd97051b4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ce0e8db183c19f5491de2eac2995c2f3", + "content-hash": "d9f106205cb406c93f16c43a84f90d43", "packages": [ { "name": "aws/aws-crt-php", diff --git a/package-lock.json b/package-lock.json index 28f042892a..600fd836a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@processmaker/processmaker", - "version": "4.11.0-RC1", + "version": "4.11.0-RC2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@processmaker/processmaker", - "version": "4.11.0-RC1", + "version": "4.11.0-RC2", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 78b8d26687..87822e1c51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@processmaker/processmaker", - "version": "4.11.0-RC1", + "version": "4.11.0-RC2", "description": "ProcessMaker 4", "author": "DevOps ", "license": "ISC", From 0273f866ead38f8ad300978ea781a3e9bb2d2bd9 Mon Sep 17 00:00:00 2001 From: Ryan Cooley Date: Tue, 27 Aug 2024 06:28:39 -0700 Subject: [PATCH 11/25] Version 4.11.0 Build #0f56de5a --- composer.json | 4 ++-- composer.lock | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 4ac319bcf8..eed71b3896 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "processmaker/processmaker", - "version": "4.11.0-RC2", + "version": "4.11.0", "description": "BPM PHP Software", "keywords": [ "php bpm processmaker" @@ -104,7 +104,7 @@ "Gmail" ], "processmaker": { - "build": "41e4c495", + "build": "0f56de5a", "custom": { "package-ellucian-ethos": "1.16.0", "package-plaid": "1.6.0", diff --git a/composer.lock b/composer.lock index ffd97051b4..997a2f25c1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d9f106205cb406c93f16c43a84f90d43", + "content-hash": "faa8eb9e40661694af24b1055b4c47cd", "packages": [ { "name": "aws/aws-crt-php", diff --git a/package-lock.json b/package-lock.json index 600fd836a2..5536409f0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@processmaker/processmaker", - "version": "4.11.0-RC2", + "version": "4.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@processmaker/processmaker", - "version": "4.11.0-RC2", + "version": "4.11.0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 87822e1c51..e6378bd2c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@processmaker/processmaker", - "version": "4.11.0-RC2", + "version": "4.11.0", "description": "ProcessMaker 4", "author": "DevOps ", "license": "ISC", From 5bcb6d6120b7b17ec2fe8bbd1a32f627eb19f020 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 27 Aug 2024 12:30:56 -0700 Subject: [PATCH 12/25] Add nodeId to event --- .../Listeners/HandleActivityAssignedInterstitialRedirect.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php b/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php index ca7c2719e1..8614212e35 100644 --- a/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php +++ b/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php @@ -6,7 +6,6 @@ class HandleActivityAssignedInterstitialRedirect extends HandleRedirectListener { - /** * Handle the event. */ @@ -23,7 +22,7 @@ public function handle(ActivityAssigned $event): void } else { $payloadUrl = route('requests.show', [ 'request' => $event->getProcessRequestToken() - ->getAttribute('process_request_id') + ->getAttribute('process_request_id'), ]); } $this->setRedirectTo($request, @@ -31,6 +30,7 @@ public function handle(ActivityAssigned $event): void [ 'payloadUrl' => $payloadUrl, 'tokenId' => $event->getProcessRequestToken()->id, + 'nodeId' => $event->getProcessRequestToken()->element_id, 'allowInterstitial' => $event->getProcessRequestToken()->getInterstitial()['allow_interstitial'], ] ); From 3a1d791bbafe6ca0285e99b30c3469fddb92ad51 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 27 Aug 2024 12:30:56 -0700 Subject: [PATCH 13/25] Add nodeId to event --- .../Listeners/HandleActivityAssignedInterstitialRedirect.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php b/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php index ca7c2719e1..8614212e35 100644 --- a/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php +++ b/ProcessMaker/Listeners/HandleActivityAssignedInterstitialRedirect.php @@ -6,7 +6,6 @@ class HandleActivityAssignedInterstitialRedirect extends HandleRedirectListener { - /** * Handle the event. */ @@ -23,7 +22,7 @@ public function handle(ActivityAssigned $event): void } else { $payloadUrl = route('requests.show', [ 'request' => $event->getProcessRequestToken() - ->getAttribute('process_request_id') + ->getAttribute('process_request_id'), ]); } $this->setRedirectTo($request, @@ -31,6 +30,7 @@ public function handle(ActivityAssigned $event): void [ 'payloadUrl' => $payloadUrl, 'tokenId' => $event->getProcessRequestToken()->id, + 'nodeId' => $event->getProcessRequestToken()->element_id, 'allowInterstitial' => $event->getProcessRequestToken()->getInterstitial()['allow_interstitial'], ] ); From 7b18e49c2c3d998c679dea3d167ce039a0c31621 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 27 Aug 2024 16:23:45 -0400 Subject: [PATCH 14/25] Add parent and child requests to the broadcast channel of the redirect event --- ProcessMaker/Events/RedirectToEvent.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ProcessMaker/Events/RedirectToEvent.php b/ProcessMaker/Events/RedirectToEvent.php index f1ac09c0c1..df05b8b010 100644 --- a/ProcessMaker/Events/RedirectToEvent.php +++ b/ProcessMaker/Events/RedirectToEvent.php @@ -43,8 +43,18 @@ public function broadcastAs() */ public function broadcastOn(): array { - return [ - new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->getKey()), + $channels = [ + // Current request + new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->getKey()) ]; + // include child requests if any + foreach($this->processRequest->childRequests()->pluck('id') as $childRequestId) { + $channels[] = new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $childRequestId); + } + // include parent request if any + if ($this->processRequest->parent_request_id) { + $channels[] = new PrivateChannel('ProcessMaker.Models.ProcessRequest.' . $this->processRequest->parent_request_id); + } + return $channels; } } From 75fa15e7107e35b03c0688d9d47fa694a6f66f2e Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 27 Aug 2024 16:25:29 -0400 Subject: [PATCH 15/25] Do not redirect to child request summary if there is a previous redirect --- ProcessMaker/Listeners/HandleEndEventRedirect.php | 6 +++++- ProcessMaker/Listeners/HandleRedirectListener.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ProcessMaker/Listeners/HandleEndEventRedirect.php b/ProcessMaker/Listeners/HandleEndEventRedirect.php index e88a682d8d..773d6f351b 100644 --- a/ProcessMaker/Listeners/HandleEndEventRedirect.php +++ b/ProcessMaker/Listeners/HandleEndEventRedirect.php @@ -17,9 +17,13 @@ public function handle(ProcessCompleted $event): void if (empty($request)) { return; } + // Do not redirect to child request summary if there is a previous redirect + if ($request->parent_request_id && self::$redirectionMethod !== '') { + return; + } $userId = Auth::id(); - $requestId = $event->getProcessRequest()->id; + $requestId = $request->id; $this->setRedirectTo($request, 'processCompletedRedirect', $event, $userId, $requestId); } } diff --git a/ProcessMaker/Listeners/HandleRedirectListener.php b/ProcessMaker/Listeners/HandleRedirectListener.php index 1bf044f9a9..bf86e71f57 100644 --- a/ProcessMaker/Listeners/HandleRedirectListener.php +++ b/ProcessMaker/Listeners/HandleRedirectListener.php @@ -9,7 +9,7 @@ class HandleRedirectListener { private static $processRequest = null; - private static $redirectionMethod = ''; + protected static $redirectionMethod = ''; private static $redirectionParams = []; From fe25477de7ace8dc20f299adb6c4359911af5968 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 27 Aug 2024 16:27:55 -0400 Subject: [PATCH 16/25] Test interstitial redirect events --- tests/Feature/InterstitialTest.php | 191 +++++++++++++++++++++++ tests/Fixtures/task_subprocess_task.json | 1 + 2 files changed, 192 insertions(+) create mode 100644 tests/Feature/InterstitialTest.php create mode 100644 tests/Fixtures/task_subprocess_task.json diff --git a/tests/Feature/InterstitialTest.php b/tests/Feature/InterstitialTest.php new file mode 100644 index 0000000000..5afb765ace --- /dev/null +++ b/tests/Feature/InterstitialTest.php @@ -0,0 +1,191 @@ +user + */ + private function loadProcess($file) + { + $data = []; + $data['bpmn'] = Process::getProcessTemplate($file); + return Process::factory()->create($data); + } + + /** + * @return Process[] + */ + private function importProcessPackage(string $file) + { + $maxId = Process::max('id') ?? 0; + $data = json_decode(file_get_contents(base_path('tests/Fixtures/' . $file)), true); + $this->import($data); + return Process::where('id', '>', $maxId)->get(); + } + + private function startProcess(Process $process, string $event, array $data = []) + { + $route = route('api.process_events.trigger', [$process->id, 'event' => $event]); + $response = $this->apiCall('POST', $route, $data); + return $response->json(); + } + + private function getActiveTasks() + { + //Get the active tasks of the request + $route = route('api.tasks.index', ['status' => 'ACTIVE']); + $response = $this->apiCall('GET', $route); + return $response->json('data'); + } + private function completeActiveTask(array $data = []) + { + //Get the active tasks of the request + $tasks = $this->getActiveTasks(); + //Complete the task + $route = route('api.tasks.update', [$tasks[0]['id'], 'status' => 'COMPLETED']); + $response = $this->apiCall('PUT', $route, ['data' => $data]); + return $response->json(); + } + + private function broadcastedTo(RedirectToEvent $event, array $expectedChannels): bool + { + $channels = $event->broadcastOn(); + foreach ($channels as $channel) { + if (!in_array($channel->name, $expectedChannels)) { + return false; + } + } + return true; + } + + /** + * Execute a process and check the interstitial redirects + */ + public function testExecuteProcessRedirects() + { + $processes = $this->importProcessPackage('task_subprocess_task.json'); + $process = $processes[0]; + //Start a process request + Event::fake([RedirectToEvent::class]); + $route = route('api.process_events.trigger', [$process->id, 'event' => 'node_1']); + $data = ['foo' => 'bar']; + $response = $this->apiCall('POST', $route, $data); + //Verify status + $response->assertStatus(201); + + // Check redirect to first task + $dispatched = []; + $tasks = $this->getActiveTasks(); + $expectedEvent = [ + 'method' => 'redirectToTask', + 'params' => [ + [ + 'tokenId' => $tasks[0]['id'], + 'nodeId' => $tasks[0]['element_id'], + ] + ], + ]; + $dispatched[] = $expectedEvent; + Event::assertDispatched(RedirectToEvent::class, function ($event) use ($expectedEvent) { + return $event->method === $expectedEvent['method'] + && $event->params[0]['tokenId'] === $expectedEvent['params'][0]['tokenId'] + && $event->params[0]['nodeId'] === $expectedEvent['params'][0]['nodeId']; + }); + + // Complete active task (Task 1) and check RedirectToEvent dispatched + $task = $this->completeActiveTask([]); + $tasks = $this->getActiveTasks(); + $expectedEvent = [ + 'method' => 'redirectToTask', + 'params' => [ + [ + 'tokenId' => $tasks[0]['id'], + ] + ], + ]; + $dispatched[] = $expectedEvent; + Event::assertDispatched(RedirectToEvent::class, function ($event) use ($expectedEvent) { + return $event->method === $expectedEvent['method'] + && $event->params[0]['tokenId'] === $expectedEvent['params'][0]['tokenId']; + + }); + + // Complete active task (sub process - Task 2) and check RedirectToEvent dispatched to next Task not to subprocess summary + $task = $this->completeActiveTask([]); + $tasks = $this->getActiveTasks(); + $expectedEvent = [ + 'method' => 'redirectToTask', + 'params' => [ + [ + 'tokenId' => $tasks[0]['id'], + ] + ], + 'broadcastTo' => [ + 'private-ProcessMaker.Models.ProcessRequest.' . $tasks[0]['process_request_id'], // active task: parent request + 'private-ProcessMaker.Models.ProcessRequest.' . $task['process_request_id'], // completed task: child request + ] + ]; + $dispatched[] = $expectedEvent; + Event::assertDispatched(RedirectToEvent::class, function ($event) use ($expectedEvent, $task) { + return $event->method === $expectedEvent['method'] + && $event->params[0]['tokenId'] === $expectedEvent['params'][0]['tokenId'] + && $this->broadcastedTo($event, $expectedEvent['broadcastTo']); + }); + + // Complete active task (Task 3) and check RedirectToEvent dispatched to parent process summary + $task = $this->completeActiveTask([]); + $tasks = $this->getActiveTasks(); + $expectedEvent = [ + 'method' => 'processCompletedRedirect', + 'params' => [ + [], + $task['user_id'], + $task['process_request_id'], + ], + ]; + $dispatched[] = $expectedEvent; + Event::assertDispatched(RedirectToEvent::class, function ($event) use ($expectedEvent) { + return $event->method === $expectedEvent['method'] + && $event->params[1] === $expectedEvent['params'][1] + && $event->params[2] === $expectedEvent['params'][2]; + }); + + Event::assertDispatched(RedirectToEvent::class, count($dispatched)); + } +} diff --git a/tests/Fixtures/task_subprocess_task.json b/tests/Fixtures/task_subprocess_task.json new file mode 100644 index 0000000000..2f178525c1 --- /dev/null +++ b/tests/Fixtures/task_subprocess_task.json @@ -0,0 +1 @@ +{"type":"process_package","version":"2","root":"9cdc747b-8cd5-45f6-985b-87f0e8e2db6f","name":"task subprocess task","export":{"9cdc747b-8cd5-45f6-985b-87f0e8e2db6f":{"exporter":"ProcessMaker\\ImportExport\\Exporters\\ProcessExporter","type":"Process","type_human":"Process","type_plural":"Processes","type_human_plural":"Processes","last_modified_by":"Admin User","last_modified_by_id":1,"model":"ProcessMaker\\Models\\Process","force_password_protect":false,"hidden":false,"mode":"update","saveAssetsMode":"saveAllAssets","explicit_discard":false,"dependents":[{"type":"user","uuid":"9ccdbd47-b67c-47f8-a8e7-1fcf3f43c4c9","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\UserExporter","modelClass":"ProcessMaker\\Models\\User","fallbackMatches":{"email":"paola.pellegrini@processmaker.com","username":"paola"},"name":"","discard":false},{"type":"manager","uuid":"9ccdbd47-b67c-47f8-a8e7-1fcf3f43c4c9","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\UserExporter","modelClass":"ProcessMaker\\Models\\User","fallbackMatches":{"email":"paola.pellegrini@processmaker.com","username":"paola"},"name":"","discard":false},{"type":"interstitial_screen","uuid":"9aa37b55-6fed-4982-b25c-9a5f2b012643","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:startEvent"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"Screen Interstitial 57"},"name":"Screen Interstitial 57","discard":false},{"type":"screens","uuid":"98de0484-72de-4b48-945f-cbd15a7efb69","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:task[1]"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"1Season"},"name":"1Season","discard":false},{"type":"interstitial_screen","uuid":"9aa37b55-6fed-4982-b25c-9a5f2b012643","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:task[1]"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"Screen Interstitial 57"},"name":"Screen Interstitial 57","discard":false},{"type":"screens","uuid":"9cdc6db8-6b84-4456-a233-533e90e5c85e","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:task[2]"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"screen simple spring 2"},"name":"screen simple spring 2","discard":false},{"type":"categories","uuid":"9966acef-cf73-47ee-9398-534b6df21fe1","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\CategoryExporter","modelClass":"ProcessMaker\\Models\\ProcessCategory","fallbackMatches":{"name":"catPaoProcess"},"name":"catPaoProcess","discard":false},{"type":"sub_processes","uuid":"9caa3816-941a-4e32-a54c-2b10d2e2dede","meta":"\/bpmn:definitions\/bpmn:process\/bpmn:callActivity","exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ProcessExporter","modelClass":"ProcessMaker\\Models\\Process","fallbackMatches":{"name":"subprocess 1"},"name":"subprocess 1","discard":false},{"type":"process_launchpad","uuid":"9cdc7504-16ae-48d7-b8d4-9f9625d5c087","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ProcessLaunchpadExporter","modelClass":"ProcessMaker\\Models\\ProcessLaunchpad","fallbackMatches":[],"name":"Setting","discard":false}],"name":"task subprocess task","description":"test pao","process_manager":"paola pellegrini","process_manager_id":114,"attributes":{"id":882,"uuid":"9cdc747b-8cd5-45f6-985b-87f0e8e2db6f","process_category_id":15,"user_id":114,"bpmn":"\n\n \n \n node_33<\/bpmn:outgoing>\n <\/bpmn:startEvent>\n \n node_33<\/bpmn:incoming>\n node_49<\/bpmn:outgoing>\n <\/bpmn:task>\n \n node_53<\/bpmn:incoming>\n node_57<\/bpmn:outgoing>\n <\/bpmn:task>\n \n node_57<\/bpmn:incoming>\n <\/bpmn:endEvent>\n \n \n \n node_49<\/bpmn:incoming>\n node_53<\/bpmn:outgoing>\n <\/bpmn:callActivity>\n \n \n <\/bpmn:process>\n \n \n \n \n <\/bpmndi:BPMNShape>\n \n \n <\/bpmndi:BPMNShape>\n \n \n <\/bpmndi:BPMNShape>\n \n \n <\/bpmndi:BPMNShape>\n \n \n \n <\/bpmndi:BPMNEdge>\n \n \n \n <\/bpmndi:BPMNEdge>\n \n \n <\/bpmndi:BPMNShape>\n \n \n \n <\/bpmndi:BPMNEdge>\n \n \n \n <\/bpmndi:BPMNEdge>\n <\/bpmndi:BPMNPlane>\n <\/bpmndi:BPMNDiagram>\n<\/bpmn:definitions>","description":"test pao","name":"task subprocess task","cancel_screen_id":null,"request_detail_screen_id":null,"status":"ACTIVE","is_valid":1,"package_key":null,"pause_timer_start":0,"deleted_at":null,"created_at":"2024-08-26 21:10:09","updated_at":"2024-08-27 02:36:30","updated_by":1,"start_events":"[{\"id\": \"node_1\", \"name\": \"Start Event\", \"config\": \"{\\\"web_entry\\\":null}\", \"ownerProcessId\": \"ProcessId\", \"eventDefinitions\": [], \"ownerProcessName\": \"ProcessName\", \"allowInterstitial\": \"true\", \"interstitialScreenRef\": \"1\"}]","warnings":null,"self_service_tasks":"[]","svg":"<\/marker><\/marker><\/marker><\/marker><\/defs>Start\u00a0Event<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>Form\u00a0Task<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>End\u00a0Event<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>Sub\u00a0Process<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>Form\u00a0Task<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>-<\/tspan><\/text><\/g><\/g><\/g>-<\/tspan><\/text><\/g><\/g><\/g>-<\/tspan><\/text><\/g><\/g><\/g>-<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g>
\\n
<\/div>\\n

We're getting the next task for you...<\/p>\\n<\/div>\", \"interactive\": true, \"renderVarHtml\": false}, \"component\": \"FormHtmlViewer\", \"inspector\": [{\"type\": \"FormTextArea\", \"field\": \"content\", \"config\": {\"rows\": 5, \"label\": \"Content\", \"value\": null, \"helper\": \"The HTML text to display\"}}, {\"type\": \"FormInput\", \"field\": \"conditionalHide\", \"config\": {\"label\": \"Visibility Rule\", \"helper\": \"This control is hidden until this expression is true\"}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}], \"editor-control\": \"FormHtmlEditor\", \"editor-component\": \"FormHtmlEditor\"}]}]","computed":null,"custom_css":null,"created_at":"2023-11-18 01:03:15","updated_at":"2024-08-27 10:10:32","status":"ACTIVE","key":null,"watchers":null,"translations":null,"is_template":0,"asset_type":null},"extraAttributes":{"translatedLanguages":[]},"references":{"uncategorized-category":true}},"98de0484-72de-4b48-945f-cbd15a7efb69":{"exporter":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","type":"Screen","type_human":"Screen","type_plural":"Screens","type_human_plural":"Screens","last_modified_by":"","last_modified_by_id":null,"model":"ProcessMaker\\Models\\Screen","force_password_protect":false,"hidden":false,"mode":"update","saveAssetsMode":"saveAllAssets","explicit_discard":false,"dependents":[],"name":"1Season","description":"1Season","process_manager":"","process_manager_id":null,"attributes":{"id":1462,"uuid":"98de0484-72de-4b48-945f-cbd15a7efb69","title":"1Season","description":"1Season","type":"FORM","config":"[{\"name\": \"1Season\", \"items\": [{\"label\": \"Textarea\", \"config\": {\"icon\": \"fas fa-paragraph\", \"name\": \"date\", \"rows\": 2, \"label\": \"New Textarea\", \"helper\": null, \"currency\": {\"code\": \"USD\", \"name\": \"US Dollar\", \"format\": \"#,###.##\", \"symbol\": \"$\"}, \"readonly\": true, \"richtext\": false, \"validation\": [], \"placeholder\": null}, \"component\": \"FormTextArea\", \"inspector\": [{\"type\": \"FormInput\", \"field\": \"name\", \"config\": {\"name\": \"Variable Name\", \"label\": \"Variable Name\", \"helper\": \"A variable name is a symbolic name to reference information.\", \"validation\": \"regex:\/^([a-zA-Z]([a-zA-Z0-9_]?)+\\\\.?)+(? Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####\", \"validation\": null}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}, {\"type\": \"FormInput\", \"field\": \"ariaLabel\", \"config\": {\"label\": \"Aria Label\", \"helper\": \"Attribute designed to help assistive technology (e.g. screen readers) attach a label\"}}, {\"type\": \"FormInput\", \"field\": \"tabindex\", \"config\": {\"label\": \"Tab Order\", \"helper\": \"Order in which a user will move focus from one control to another by pressing the Tab key\", \"validation\": \"regex: [0-9]*\"}}], \"editor-control\": \"FormTextArea\", \"editor-component\": \"FormTextArea\"}, {\"label\": \"Line Input\", \"config\": {\"icon\": \"far fa-square\", \"name\": \"season\", \"type\": \"text\", \"label\": \"_season\", \"helper\": null, \"readonly\": false, \"dataFormat\": \"string\", \"validation\": [], \"placeholder\": null}, \"component\": \"FormInput\", \"inspector\": [{\"type\": \"FormInput\", \"field\": \"name\", \"config\": {\"name\": \"Variable Name\", \"label\": \"Variable Name\", \"helper\": \"A variable name is a symbolic name to reference information.\", \"validation\": \"regex:\/^([a-zA-Z]([a-zA-Z0-9_]?)+\\\\.?)+(? Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####\", \"validation\": null}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}, {\"type\": \"FormInput\", \"field\": \"ariaLabel\", \"config\": {\"label\": \"Aria Label\", \"helper\": \"Attribute designed to help assistive technology (e.g. screen readers) attach a label\"}}, {\"type\": \"FormInput\", \"field\": \"tabindex\", \"config\": {\"label\": \"Tab Order\", \"helper\": \"Order in which a user will move focus from one control to another by pressing the Tab key\", \"validation\": \"regex: [0-9]*\"}}], \"editor-control\": \"FormInput\", \"editor-component\": \"FormInput\"}], [{\"label\": \"Line Input\", \"config\": {\"icon\": \"far fa-square\", \"name\": \"what\", \"type\": \"text\", \"label\": \"New Input\", \"helper\": null, \"readonly\": true, \"dataFormat\": \"string\", \"validation\": [], \"placeholder\": null}, \"component\": \"FormInput\", \"inspector\": [{\"type\": \"FormInput\", \"field\": \"name\", \"config\": {\"name\": \"Variable Name\", \"label\": \"Variable Name\", \"helper\": \"A variable name is a symbolic name to reference information.\", \"validation\": \"regex:\/^(?:[A-Za-z])(?:[0-9A-Z_.a-z])*[^.]$\/|required|not_in:null,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,const,enum,export,extends,import,super,true,false\"}}, {\"type\": \"FormInput\", \"field\": \"label\", \"config\": {\"label\": \"Label\", \"helper\": \"The label describes the field's name\"}}, {\"type\": \"FormMultiselect\", \"field\": \"dataFormat\", \"config\": {\"name\": \"Data Type\", \"label\": \"Data Type\", \"helper\": \"The data type specifies what kind of data is stored in the variable.\", \"options\": [{\"value\": \"string\", \"content\": \"Text\"}, {\"value\": \"int\", \"content\": \"Integer\"}, {\"value\": \"currency\", \"content\": \"Currency\"}, {\"value\": \"percentage\", \"content\": \"Percentage\"}, {\"value\": \"float\", \"content\": \"Decimal\"}, {\"value\": \"datetime\", \"content\": \"Datetime\"}, {\"value\": \"date\", \"content\": \"Date\"}, {\"value\": \"password\", \"content\": \"Password\"}], \"validation\": \"required\"}}, {\"type\": {\"_Ctor\": [], \"extends\": {\"_Ctor\": [], \"props\": {\"name\": {\"type\": null}, \"error\": {\"type\": null}, \"label\": {\"type\": null}, \"value\": {\"type\": null}, \"helper\": {\"type\": null}, \"options\": {\"type\": null}, \"selectedControl\": {\"type\": null}}, \"mixins\": [{\"props\": {\"validation\": {\"type\": null}, \"validationData\": {\"type\": null}, \"validationField\": {\"type\": null}, \"validationMessages\": {\"type\": null}}, \"watch\": {\"validationData\": {\"deep\": true, \"user\": true}}, \"methods\": [], \"computed\": []}], \"methods\": [], \"computed\": [], \"_compiled\": true, \"inheritAttrs\": false, \"staticRenderFns\": []}, \"computed\": [], \"_compiled\": true, \"staticRenderFns\": []}, \"field\": \"dataMask\", \"config\": {\"name\": \"Data Format\", \"label\": \"Data Format\", \"helper\": \"The data format for the selected type.\"}}, {\"type\": \"ValidationSelect\", \"field\": \"validation\", \"config\": {\"label\": \"Validation Rules\", \"helper\": \"The validation rules needed for this field\"}}, {\"type\": \"FormInput\", \"field\": \"placeholder\", \"config\": {\"label\": \"Placeholder Text\", \"helper\": \"The placeholder is what is shown in the field when no value is provided yet\"}}, {\"type\": \"FormInput\", \"field\": \"helper\", \"config\": {\"label\": \"Helper Text\", \"helper\": \"Help text is meant to provide additional guidance on the field's value\"}}, {\"type\": \"FormCheckbox\", \"field\": \"readonly\", \"config\": {\"label\": \"Read Only\", \"helper\": null}}, {\"type\": \"ColorSelect\", \"field\": \"color\", \"config\": {\"label\": \"Text Color\", \"helper\": \"Set the element's text color\", \"options\": [{\"value\": \"text-primary\", \"content\": \"primary\"}, {\"value\": \"text-secondary\", \"content\": \"secondary\"}, {\"value\": \"text-success\", \"content\": \"success\"}, {\"value\": \"text-danger\", \"content\": \"danger\"}, {\"value\": \"text-warning\", \"content\": \"warning\"}, {\"value\": \"text-info\", \"content\": \"info\"}, {\"value\": \"text-light\", \"content\": \"light\"}, {\"value\": \"text-dark\", \"content\": \"dark\"}]}}, {\"type\": \"ColorSelect\", \"field\": \"bgcolor\", \"config\": {\"label\": \"Background Color\", \"helper\": \"Set the element's background color\", \"options\": [{\"value\": \"alert alert-primary\", \"content\": \"primary\"}, {\"value\": \"alert alert-secondary\", \"content\": \"secondary\"}, {\"value\": \"alert alert-success\", \"content\": \"success\"}, {\"value\": \"alert alert-danger\", \"content\": \"danger\"}, {\"value\": \"alert alert-warning\", \"content\": \"warning\"}, {\"value\": \"alert alert-info\", \"content\": \"info\"}, {\"value\": \"alert alert-light\", \"content\": \"light\"}, {\"value\": \"alert alert-dark\", \"content\": \"dark\"}]}}, {\"type\": {\"_Ctor\": [], \"props\": {\"value\": {\"type\": null}, \"helper\": {\"type\": null}}, \"watch\": {\"value\": {\"user\": true, \"immediate\": true}}, \"methods\": [], \"_scopeId\": \"data-v-172d71e1\", \"computed\": {\"effectiveValue\": []}, \"_compiled\": true, \"components\": {\"MonacoEditor\": {\"name\": \"monaco-editor\", \"_Ctor\": [], \"props\": {\"amdRequire\": []}, \"extends\": {\"name\": \"MonacoEditor\", \"model\": {\"event\": \"change\"}, \"props\": {\"theme\": {\"default\": \"vs\"}, \"value\": {\"required\": true}, \"options\": [], \"language\": [], \"original\": [], \"amdRequire\": [], \"diffEditor\": {\"default\": false}}, \"watch\": {\"options\": {\"deep\": true, \"user\": true}}, \"methods\": []}, \"methods\": []}}, \"staticRenderFns\": []}, \"field\": \"defaultValue\", \"config\": {\"label\": \"Default Value\", \"helper\": \"The default value is pre populated using the existing request data. This feature will allow you to modify the value displayed on screen load if needed.\"}}, {\"type\": \"FormInput\", \"field\": \"conditionalHide\", \"config\": {\"label\": \"Visibility Rule\", \"helper\": \"This control is hidden until this expression is true\"}}, {\"type\": \"FormInput\", \"field\": \"customFormatter\", \"config\": {\"label\": \"Custom Format String\", \"helper\": \"Use the Mask Pattern format
Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####\", \"validation\": null}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}, {\"type\": \"FormInput\", \"field\": \"ariaLabel\", \"config\": {\"label\": \"Aria Label\", \"helper\": \"Attribute designed to help assistive technology (e.g. screen readers) attach a label\"}}, {\"type\": \"FormInput\", \"field\": \"tabindex\", \"config\": {\"label\": \"Tab Order\", \"helper\": \"Order in which a user will move focus from one control to another by pressing the Tab key\", \"validation\": \"regex: [0-9]*\"}}], \"editor-control\": \"FormInput\", \"editor-component\": \"FormInput\"}]], \"label\": \"Multicolumn \/ Table\", \"config\": {\"icon\": \"fas fa-table\", \"label\": null, \"options\": [{\"value\": \"1\", \"content\": \"6\"}, {\"value\": \"2\", \"content\": \"6\"}]}, \"component\": \"FormMultiColumn\", \"container\": true, \"inspector\": [{\"type\": \"ContainerColumns\", \"field\": \"options\", \"config\": {\"label\": \"Column Width\", \"validation\": \"columns-adds-to-12\"}}, {\"type\": \"ColorSelect\", \"field\": \"color\", \"config\": {\"label\": \"Text Color\", \"helper\": \"Set the element's text color\", \"options\": [{\"value\": \"text-primary\", \"content\": \"primary\"}, {\"value\": \"text-secondary\", \"content\": \"secondary\"}, {\"value\": \"text-success\", \"content\": \"success\"}, {\"value\": \"text-danger\", \"content\": \"danger\"}, {\"value\": \"text-warning\", \"content\": \"warning\"}, {\"value\": \"text-info\", \"content\": \"info\"}, {\"value\": \"text-light\", \"content\": \"light\"}, {\"value\": \"text-dark\", \"content\": \"dark\"}]}}, {\"type\": \"ColorSelect\", \"field\": \"bgcolor\", \"config\": {\"label\": \"Background Color\", \"helper\": \"Set the element's background color\", \"options\": [{\"value\": \"alert alert-primary\", \"content\": \"primary\"}, {\"value\": \"alert alert-secondary\", \"content\": \"secondary\"}, {\"value\": \"alert alert-success\", \"content\": \"success\"}, {\"value\": \"alert alert-danger\", \"content\": \"danger\"}, {\"value\": \"alert alert-warning\", \"content\": \"warning\"}, {\"value\": \"alert alert-info\", \"content\": \"info\"}, {\"value\": \"alert alert-light\", \"content\": \"light\"}, {\"value\": \"alert alert-dark\", \"content\": \"dark\"}]}}, {\"type\": \"FormInput\", \"field\": \"conditionalHide\", \"config\": {\"label\": \"Visibility Rule\", \"helper\": \"This control is hidden until this expression is true\"}}, {\"type\": \"FormInput\", \"field\": \"customFormatter\", \"config\": {\"label\": \"Custom Format String\", \"helper\": \"Use the Mask Pattern format
Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####\", \"validation\": null}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}, {\"type\": \"FormInput\", \"field\": \"ariaLabel\", \"config\": {\"label\": \"Aria Label\", \"helper\": \"Attribute designed to help assistive technology (e.g. screen readers) attach a label\"}}, {\"type\": \"FormInput\", \"field\": \"tabindex\", \"config\": {\"label\": \"Tab Order\", \"helper\": \"Order in which a user will move focus from one control to another by pressing the Tab key\", \"validation\": \"regex: [0-9]*\"}}], \"editor-control\": \"FormMultiColumn\", \"editor-component\": \"MultiColumn\"}, {\"label\": \"Submit Button\", \"config\": {\"icon\": \"fas fa-share-square\", \"name\": null, \"event\": \"submit\", \"label\": \"New Submit\", \"variant\": \"primary\", \"fieldValue\": null, \"defaultSubmit\": true}, \"component\": \"FormButton\", \"inspector\": [{\"type\": \"FormInput\", \"field\": \"label\", \"config\": {\"label\": \"Label\", \"helper\": \"The label describes the button's text\"}}, {\"type\": \"FormInput\", \"field\": \"name\", \"config\": {\"name\": \"Variable Name\", \"label\": \"Variable Name\", \"helper\": \"A variable name is a symbolic name to reference information.\"}}, {\"type\": \"FormMultiselect\", \"field\": \"event\", \"config\": {\"label\": \"Type\", \"helper\": \"Choose whether the button should submit the form\", \"options\": [{\"value\": \"submit\", \"content\": \"Submit Button\"}, {\"value\": \"script\", \"content\": \"Regular Button\"}]}}, {\"type\": \"FormInput\", \"field\": \"fieldValue\", \"config\": {\"label\": \"Value\", \"helper\": \"The value being submitted\"}}, {\"type\": \"FormMultiselect\", \"field\": \"variant\", \"config\": {\"label\": \"Button Variant Style\", \"helper\": \"The variant determines the appearance of the button\", \"options\": [{\"value\": \"primary\", \"content\": \"Primary\"}, {\"value\": \"secondary\", \"content\": \"Secondary\"}, {\"value\": \"success\", \"content\": \"Success\"}, {\"value\": \"danger\", \"content\": \"Danger\"}, {\"value\": \"warning\", \"content\": \"Warning\"}, {\"value\": \"info\", \"content\": \"Info\"}, {\"value\": \"light\", \"content\": \"Light\"}, {\"value\": \"dark\", \"content\": \"Dark\"}, {\"value\": \"link\", \"content\": \"Link\"}]}}, {\"type\": \"FormInput\", \"field\": \"conditionalHide\", \"config\": {\"label\": \"Visibility Rule\", \"helper\": \"This control is hidden until this expression is true\"}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}], \"editor-control\": \"FormSubmit\", \"editor-component\": \"FormButton\"}]}]","computed":"[{\"id\": 1, \"name\": \"season\", \"type\": \"expression\", \"formula\": \"2+2\", \"property\": \"season\"}, {\"id\": 2, \"name\": \"what\", \"type\": \"javascript\", \"formula\": \"return this.form_input_1 + 4;\", \"property\": \"what\"}, {\"id\": 3, \"name\": \"date\", \"type\": \"javascript\", \"formula\": \"var date = new Date();\\nvar str = date.getFullYear() + \\\"-\\\" + (date.getMonth() + 1) + \\\"-\\\" + date.getDate() + \\\" \\\" + date.getHours() + \\\":\\\" + date.getMinutes() + \\\":\\\" + date.getSeconds();\\nreturn str;\", \"property\": \"date\"}]","custom_css":null,"created_at":"2020-06-18 19:21:08","updated_at":"2024-08-26 20:51:24","status":"ACTIVE","key":null,"watchers":null,"translations":"{\"it\": {\"strings\": [{\"key\": \"New Textarea\", \"string\": \"Nuovo Textarea\"}, {\"key\": \"_season\", \"string\": \"_stagione\"}, {\"key\": \"New Input\", \"string\": \"Nuovo Input\"}, {\"key\": \"New Submit\", \"string\": \"Nuovo Invia\"}, {\"key\": \"New Checkbox\", \"string\": \"Nuovo Checkbox\"}, {\"key\": \"New Select List\", \"string\": \"Nuovo Elenco Selezione\"}, {\"key\": \"Page Navigation\", \"string\": \"Navigazione Pagina\"}], \"created_at\": \"2024-05-03T17:57:42.142565Z\", \"updated_at\": \"2024-05-03T17:57:42.142576Z\"}}","is_template":0,"asset_type":null},"extraAttributes":{"translatedLanguages":{"it":"Italian"}},"references":{"uncategorized-category":true}},"9cdc6db8-6b84-4456-a233-533e90e5c85e":{"exporter":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","type":"Screen","type_human":"Screen","type_plural":"Screens","type_human_plural":"Screens","last_modified_by":"","last_modified_by_id":null,"model":"ProcessMaker\\Models\\Screen","force_password_protect":false,"hidden":false,"mode":"update","saveAssetsMode":"saveAllAssets","explicit_discard":false,"dependents":[],"name":"screen simple spring 2","description":"test","process_manager":"","process_manager_id":null,"attributes":{"id":1460,"uuid":"9cdc6db8-6b84-4456-a233-533e90e5c85e","title":"screen simple spring 2","description":"test","type":"FORM","config":"[{\"name\": \"screen simple spring\", \"items\": [{\"label\": \"Line Input\", \"config\": {\"icon\": \"far fa-square\", \"name\": \"form_input_1\", \"type\": \"text\", \"label\": \"New Input\", \"helper\": null, \"dataFormat\": \"string\", \"validation\": null, \"placeholder\": null}, \"component\": \"FormInput\", \"inspector\": [{\"type\": \"FormInput\", \"field\": \"name\", \"config\": {\"name\": \"Variable Name\", \"label\": \"Variable Name\", \"helper\": \"A variable name is a symbolic name to reference information.\", \"validation\": \"regex:\/^([a-zA-Z]([a-zA-Z0-9_]?)+\\\\.?)+(? Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####\", \"validation\": null}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}, {\"type\": \"FormInput\", \"field\": \"ariaLabel\", \"config\": {\"label\": \"Aria Label\", \"helper\": \"Attribute designed to help assistive technology (e.g. screen readers) attach a label\"}}, {\"type\": \"FormInput\", \"field\": \"tabindex\", \"config\": {\"label\": \"Tab Order\", \"helper\": \"Order in which a user will move focus from one control to another by pressing the Tab key\", \"validation\": \"regex: [0-9]*\"}}], \"editor-control\": \"FormInput\", \"editor-component\": \"FormInput\"}, {\"label\": \"Submit Button\", \"config\": {\"icon\": \"fas fa-share-square\", \"name\": null, \"event\": \"submit\", \"label\": \"New Submit\", \"tooltip\": [], \"variant\": \"primary\", \"fieldValue\": null, \"defaultSubmit\": true}, \"component\": \"FormButton\", \"inspector\": [{\"type\": \"FormInput\", \"field\": \"label\", \"config\": {\"label\": \"Label\", \"helper\": \"The label describes the button's text\"}}, {\"type\": \"FormInput\", \"field\": \"name\", \"config\": {\"name\": \"Variable Name\", \"label\": \"Variable Name\", \"helper\": \"A variable name is a symbolic name to reference information.\", \"validation\": \"regex:\/^(?:[A-Za-z])(?:[0-9A-Z_.a-z])*(? Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####\", \"validation\": null}}, {\"type\": \"FormInput\", \"field\": \"customCssSelector\", \"config\": {\"label\": \"CSS Selector Name\", \"helper\": \"Use this in your custom css rules\", \"validation\": \"regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]\"}}, {\"type\": \"FormInput\", \"field\": \"ariaLabel\", \"config\": {\"label\": \"Aria Label\", \"helper\": \"Attribute designed to help assistive technology (e.g. screen readers) attach a label\"}}, {\"type\": \"FormInput\", \"field\": \"tabindex\", \"config\": {\"label\": \"Tab Order\", \"helper\": \"Order in which a user will move focus from one control to another by pressing the Tab key\", \"validation\": \"regex: [0-9]*\"}}], \"editor-control\": \"FormSubmit\", \"editor-component\": \"FormButton\"}]}]","computed":"[]","custom_css":null,"created_at":"2023-08-03 14:52:16","updated_at":"2024-08-26 20:51:20","status":"ACTIVE","key":null,"watchers":"[]","translations":null,"is_template":0,"asset_type":null},"extraAttributes":{"translatedLanguages":[]},"references":{"uncategorized-category":true}},"9966acef-cf73-47ee-9398-534b6df21fe1":{"exporter":"ProcessMaker\\ImportExport\\Exporters\\CategoryExporter","type":"ProcessCategory","type_human":"Process Category","type_plural":"ProcessCategories","type_human_plural":"Process Categories","last_modified_by":"","last_modified_by_id":null,"model":"ProcessMaker\\Models\\ProcessCategory","force_password_protect":false,"hidden":true,"mode":"update","saveAssetsMode":"saveAllAssets","explicit_discard":false,"dependents":[],"name":"catPaoProcess","description":null,"process_manager":"","process_manager_id":null,"attributes":{"id":15,"uuid":"9966acef-cf73-47ee-9398-534b6df21fe1","name":"catPaoProcess","status":"ACTIVE","is_system":0,"created_at":"2021-08-16 20:52:11","updated_at":"2023-06-13 13:24:31"},"extraAttributes":{"translatedLanguages":[]},"references":[]},"9caa3816-941a-4e32-a54c-2b10d2e2dede":{"exporter":"ProcessMaker\\ImportExport\\Exporters\\ProcessExporter","type":"Process","type_human":"Process","type_plural":"Processes","type_human_plural":"Processes","last_modified_by":"Admin User","last_modified_by_id":1,"model":"ProcessMaker\\Models\\Process","force_password_protect":false,"hidden":false,"mode":"update","saveAssetsMode":"saveAllAssets","explicit_discard":false,"dependents":[{"type":"user","uuid":"9ccdbd47-b67c-47f8-a8e7-1fcf3f43c4c9","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\UserExporter","modelClass":"ProcessMaker\\Models\\User","fallbackMatches":{"email":"paola.pellegrini@processmaker.com","username":"paola"},"name":"","discard":false},{"type":"interstitial_screen","uuid":"9aa37b55-6fed-4982-b25c-9a5f2b012643","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:startEvent"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"Screen Interstitial 57"},"name":"Screen Interstitial 57","discard":false},{"type":"screens","uuid":"98de0484-72de-4b48-945f-cbd15a7efb69","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:task"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"1Season"},"name":"1Season","discard":false},{"type":"interstitial_screen","uuid":"9aa37b55-6fed-4982-b25c-9a5f2b012643","meta":{"path":"\/bpmn:definitions\/bpmn:process\/bpmn:task"},"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ScreenExporter","modelClass":"ProcessMaker\\Models\\Screen","fallbackMatches":{"key":null,"title":"Screen Interstitial 57"},"name":"Screen Interstitial 57","discard":false},{"type":"process_launchpad","uuid":"9caa3893-d3da-4f8d-b7c7-47974788b162","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\ProcessLaunchpadExporter","modelClass":"ProcessMaker\\Models\\ProcessLaunchpad","fallbackMatches":[],"name":"Setting","discard":false},{"type":"media","uuid":"275d72b9-1cbe-4c05-b774-7935255bfac8","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\MediaExporter","modelClass":"ProcessMaker\\Models\\Media","fallbackMatches":[],"name":"media-libraryIblehf","discard":false},{"type":"media","uuid":"303ab789-317e-4312-bac9-54e696031aa0","meta":null,"exporterClass":"ProcessMaker\\ImportExport\\Exporters\\MediaExporter","modelClass":"ProcessMaker\\Models\\Media","fallbackMatches":[],"name":"media-libraryNJFeeE","discard":false}],"name":"subprocess 1","description":"testing","process_manager":"","process_manager_id":null,"attributes":{"id":879,"uuid":"9caa3816-941a-4e32-a54c-2b10d2e2dede","process_category_id":2,"user_id":114,"bpmn":"\n\n \n \n node_89<\/bpmn:incoming>\n <\/bpmn:endEvent>\n \n node_81<\/bpmn:outgoing>\n <\/bpmn:startEvent>\n \n node_81<\/bpmn:incoming>\n node_89<\/bpmn:outgoing>\n <\/bpmn:task>\n \n \n <\/bpmn:process>\n \n \n \n \n <\/bpmndi:BPMNShape>\n \n \n <\/bpmndi:BPMNShape>\n \n \n <\/bpmndi:BPMNShape>\n \n \n \n <\/bpmndi:BPMNEdge>\n \n \n \n <\/bpmndi:BPMNEdge>\n <\/bpmndi:BPMNPlane>\n <\/bpmndi:BPMNDiagram>\n<\/bpmn:definitions>","description":"testing","name":"subprocess 1","cancel_screen_id":null,"request_detail_screen_id":null,"status":"ACTIVE","is_valid":1,"package_key":null,"pause_timer_start":0,"deleted_at":null,"created_at":"2024-08-01 21:49:53","updated_at":"2024-08-27 02:30:05","updated_by":1,"start_events":"[{\"id\": \"node_22\", \"name\": \"Start Event\", \"config\": \"{\\\"web_entry\\\":null}\", \"ownerProcessId\": \"ProcessId\", \"eventDefinitions\": [], \"ownerProcessName\": \"ProcessName\", \"allowInterstitial\": \"true\", \"interstitialScreenRef\": \"1\"}]","warnings":null,"self_service_tasks":"[]","svg":"<\/marker><\/marker><\/marker><\/marker><\/defs>Start\u00a0Event<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>End\u00a0Event<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>Form\u00a0Task<\/tspan><\/text><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g><\/g>