From 460c41b92e5de19a3b81b35c9306681fa00cb62b Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 21 Jun 2024 10:10:56 -0400 Subject: [PATCH 1/8] Improve task screen endpoints --- .../Controllers/Api/V1_1/TaskController.php | 66 +++++++++++++++++-- .../V1_1/TaskInterstitialResource.php | 19 ++++++ .../Http/Resources/V1_1/TaskResource.php | 15 +++-- ProcessMaker/Traits/TaskResourceIncludes.php | 2 +- routes/v1_1/api.php | 4 ++ 5 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 ProcessMaker/Http/Resources/V1_1/TaskInterstitialResource.php diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php b/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php index 047b24f1da..79b908a34c 100644 --- a/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php @@ -4,15 +4,22 @@ namespace ProcessMaker\Http\Controllers\Api\V1_1; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Http\Request; use ProcessMaker\Http\Controllers\Controller; -use ProcessMaker\Models\ProcessRequestToken; +use ProcessMaker\Http\Resources\V1_1\TaskInterstitialResource; +use ProcessMaker\Http\Resources\V1_1\TaskResource; use ProcessMaker\Http\Resources\V1_1\TaskScreen; +use ProcessMaker\Models\ProcessRequestToken; class TaskController extends Controller { protected $defaultFields = [ 'id', + 'element_id', 'element_name', + 'element_type', + 'status', 'due_at', ]; @@ -24,18 +31,52 @@ public function index() $query = ProcessRequestToken::select($this->defaultFields) ->where('element_type', 'task'); - return $query->paginate(); + $this->processFilters(request(), $query); + $pagination = $query->paginate(); + $perPage = $pagination->perPage(); + $page = $pagination->currentPage(); + $orderBy = $pagination->orderBy; + $orderDirection = $pagination->orderDirection; + $lastPage = $pagination->lastPage(); + return [ + 'data' => $pagination->items(), + 'meta' => [ + 'total' => $pagination->total(), + 'perPage' => $pagination->perPage(), + 'currentPage' => $pagination->currentPage(), + 'lastPage' => $pagination->lastPage(), + 'count' => $pagination->count(), + // 'filter' => $filter, + 'from' => $perPage * ($page - 1) + 1, + 'last_page' => $lastPage, + 'path' => '/', + 'per_page' => $perPage, + 'sort_by' => $orderBy, + 'sort_order' => strtolower($orderDirection), + 'to' => $perPage * ($page - 1) + $perPage, + 'total_pages' => ceil($pagination->count() / $perPage), + ], + ]; + } + + private function processFilters(Request $request, Builder $query) + { + if ($request->has('process_request_id')) { + $query->where('process_request_id', $request->input('process_request_id')); + } } public function show(ProcessRequestToken $task) { - return $task; + $resource = TaskResource::preprocessInclude(request(), ProcessRequestToken::where('id', $task->id)); + return $resource->toArray(request()); } public function showScreen($taskId) { - $task = ProcessRequestToken::select('id', 'process_request_id', 'element_id', 'process_id') - ->findOrFail($taskId); + $task = ProcessRequestToken::select( + array_merge($this->defaultFields, ['process_request_id', 'process_id']) + )->findOrFail($taskId); $response = new TaskScreen($task); $response = response($response->toArray(request())['screen'], 200); $now = time(); @@ -45,4 +86,19 @@ public function showScreen($taskId) $response->headers->set('Expires', gmdate('D, d M Y H:i:s', $now + $cacheTime) . ' GMT'); return $response; } + + public function showInterstitial($taskId) + { + $task = ProcessRequestToken::select( + array_merge($this->defaultFields, ['process_request_id', 'process_id']) + )->findOrFail($taskId); + $response = new TaskInterstitialResource($task); + $response = response($response->toArray(request())['screen'], 200); + $now = time(); + // screen cache time + $cacheTime = config('screen_task_cache_time', 86400); + $response->headers->set('Cache-Control', 'max-age=' . $cacheTime . ', must-revalidate, public'); + $response->headers->set('Expires', gmdate('D, d M Y H:i:s', $now + $cacheTime) . ' GMT'); + return $response; + } } diff --git a/ProcessMaker/Http/Resources/V1_1/TaskInterstitialResource.php b/ProcessMaker/Http/Resources/V1_1/TaskInterstitialResource.php new file mode 100644 index 0000000000..cedfa8a5f4 --- /dev/null +++ b/ProcessMaker/Http/Resources/V1_1/TaskInterstitialResource.php @@ -0,0 +1,19 @@ +includeInterstitial(); + } +} diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php index 7877910217..51c0d5edb2 100644 --- a/ProcessMaker/Http/Resources/V1_1/TaskResource.php +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -42,6 +42,8 @@ class TaskResource extends ApiResource 'id', 'element_name', 'element_id', + 'element_type', + 'status', 'due_at', ]; @@ -53,7 +55,7 @@ class TaskResource extends ApiResource protected static $defaultFieldsFor = [ 'user' => ['id', 'firstname', 'lastname', 'email', 'username', 'avatar'], 'requestor' => ['id', 'first_name', 'last_name', 'email'], - 'processRequest' => ['id', 'process_id', 'status'], + 'processRequest' => ['id', 'process_id', 'process_version_id', 'callable_id', 'status'], 'draft' => ['id', 'task_id', 'data'], 'screen' => ['id', 'config'], 'process' => ['id', 'name'], @@ -68,12 +70,11 @@ class TaskResource extends ApiResource public function toArray($request) { $array = [ - 'id' => $this->id, - 'element_name' => $this->element_name, - 'element_id' => $this->element_id, - 'due_at' => $this->due_at, 'advancedStatus' => $this->advanceStatus, ]; + foreach (self::$defaultFields as $field) { + $array[$field] = $this->$field; + } return $this->processInclude($request, $array); } @@ -108,7 +109,8 @@ private static function addRelationship(ProcessRequestToken $model, string $rela } $relationshipColumns = self::$defaultFieldsFor[$relationship] ?? ['id']; - $model->$relationship = $relationshipObject->select($relationshipColumns)->get(); + $sql = $relationshipObject->toRawSql(); + $model->$relationship = $relationshipObject->select($relationshipColumns)->getResults(); return true; } @@ -127,6 +129,7 @@ public static function preprocessInclude(Request $request, Builder $query): self if (in_array('data', $include)) { $query->addSelect('process_request_id'); + self::$defaultFieldsFor['processRequest'][] = 'data'; } foreach (self::$includeMethods as $key) { diff --git a/ProcessMaker/Traits/TaskResourceIncludes.php b/ProcessMaker/Traits/TaskResourceIncludes.php index 467190244a..6c046cd905 100644 --- a/ProcessMaker/Traits/TaskResourceIncludes.php +++ b/ProcessMaker/Traits/TaskResourceIncludes.php @@ -135,7 +135,7 @@ private function includeProcess() return ['process' => $this->process]; } - private function includeInterstitial() + public function includeInterstitial() { $interstitial = $this->getInterstitial(); diff --git a/routes/v1_1/api.php b/routes/v1_1/api.php index d4580ae996..fe1b6a01c7 100644 --- a/routes/v1_1/api.php +++ b/routes/v1_1/api.php @@ -21,5 +21,9 @@ // Route to show the screen of a task Route::get('/{taskId}/screen', [TaskController::class, 'showScreen']) ->name('show.screen'); + + // Route to show the interstitial screen of a task + Route::get('/{taskId}/interstitial', [TaskController::class, 'showInterstitial']) + ->name('show.interstitial'); }); }); From 43ba79d9a59501ae56e9b87d2e0c4d6f541be0c7 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Mon, 24 Jun 2024 10:53:12 -0400 Subject: [PATCH 2/8] Bring up nayra container automatically --- .../Console/Commands/BuildScriptExecutors.php | 3 ++- ProcessMaker/Models/ScriptDockerNayraTrait.php | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ProcessMaker/Console/Commands/BuildScriptExecutors.php b/ProcessMaker/Console/Commands/BuildScriptExecutors.php index 963d2b2803..0bc35ee5e5 100644 --- a/ProcessMaker/Console/Commands/BuildScriptExecutors.php +++ b/ProcessMaker/Console/Commands/BuildScriptExecutors.php @@ -9,6 +9,7 @@ use ProcessMaker\Exception\InvalidDockerImageException; use ProcessMaker\Facades\Docker; use ProcessMaker\Models\ScriptExecutor; +use ProcessMaker\ScriptRunners\Base; use UnexpectedValueException; class BuildScriptExecutors extends Command @@ -161,7 +162,7 @@ public function buildExecutor() $this->execCommand($command); - $isNayra = $scriptExecutor->language === 'php-nayra'; + $isNayra = $scriptExecutor->language === Base::NAYRA_LANG; if ($isNayra) { $instanceName = config('app.instance'); $this->info('Stop existing nayra container'); diff --git a/ProcessMaker/Models/ScriptDockerNayraTrait.php b/ProcessMaker/Models/ScriptDockerNayraTrait.php index fc50e26e07..a840d22b32 100644 --- a/ProcessMaker/Models/ScriptDockerNayraTrait.php +++ b/ProcessMaker/Models/ScriptDockerNayraTrait.php @@ -2,10 +2,12 @@ namespace ProcessMaker\Models; +use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; use ProcessMaker\Exception\ScriptException; use ProcessMaker\Facades\Docker; +use ProcessMaker\ScriptRunners\Base; /** * Execute a docker container copying files to interchange information. @@ -36,12 +38,12 @@ public function handleNayraDocker(string $code, array $data, array $config, $tim $body = json_encode($params); $servers = Cache::get('nayra_ips'); if (!$servers) { - $url = config('app.nayra_rest_api_host') . '/run_script'; - } else { - $index = array_rand($servers); - $url = 'http://' . $servers[$index] . ':8080/run_script'; - $this->ensureNayraServerIsRunning('http://' . $servers[$index] . ':8080'); + $this->bringUpNayraContainer(); + $servers = Cache::get('nayra_ips'); } + $index = array_rand($servers); + $url = 'http://' . $servers[$index] . ':8080/run_script'; + $this->ensureNayraServerIsRunning('http://' . $servers[$index] . ':8080'); $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); @@ -104,6 +106,12 @@ private function bringUpNayra(string $url) $this->nayraServiceIsRunning($url); } + private function bringUpNayraContainer() + { + $lang = Base::NAYRA_LANG; + Artisan::call("processmaker:build-script-executor {$lang} --rebuild"); + } + /** * Waits for the container network to be ready. * From c401b9c36da2d54e26d4e5688497b57a552091ea Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Mon, 24 Jun 2024 16:55:49 -0400 Subject: [PATCH 3/8] Add filter by status --- ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php b/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php index 79b908a34c..79eca44e79 100644 --- a/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php @@ -35,8 +35,6 @@ public function index() $pagination = $query->paginate(); $perPage = $pagination->perPage(); $page = $pagination->currentPage(); - $orderBy = $pagination->orderBy; - $orderDirection = $pagination->orderDirection; $lastPage = $pagination->lastPage(); return [ 'data' => $pagination->items(), @@ -51,8 +49,6 @@ public function index() 'last_page' => $lastPage, 'path' => '/', 'per_page' => $perPage, - 'sort_by' => $orderBy, - 'sort_order' => strtolower($orderDirection), 'to' => $perPage * ($page - 1) + $perPage, 'total_pages' => ceil($pagination->count() / $perPage), ], @@ -64,6 +60,9 @@ private function processFilters(Request $request, Builder $query) if ($request->has('process_request_id')) { $query->where('process_request_id', $request->input('process_request_id')); } + if ($request->has('status')) { + $query->where('status', $request->input('status')); + } } public function show(ProcessRequestToken $task) From 1dde4b0c6ed2e036ce465b7c461694c9f84f66b3 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Mon, 24 Jun 2024 16:56:01 -0400 Subject: [PATCH 4/8] Fix status errors --- resources/views/tasks/edit.blade.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/views/tasks/edit.blade.php b/resources/views/tasks/edit.blade.php index df7e17a3bd..6c2d83307c 100644 --- a/resources/views/tasks/edit.blade.php +++ b/resources/views/tasks/edit.blade.php @@ -508,7 +508,7 @@ class="multiselect__tag-icon"> "COMPLETED": "open-style", "TRIGGERED": "open-style", }; - const status = this.task.advanceStatus.toUpperCase(); + const status = (this.task.advanceStatus || '').toUpperCase(); return "card-header text-status " + header[status]; }, isAllowReassignment() { @@ -646,9 +646,14 @@ class="multiselect__tag-icon"> // to view error details. This is done in loadTask in Task.vue if (error.response?.status && error.response?.status === 422) { // Validation error - Object.entries(error.response.data.errors).forEach(([key, value]) => { - window.ProcessMaker.alert(`${key}: ${value[0]}`, 'danger', 0); - }); + if (error.response.data.errors) { + Object.entries(error.response.data.errors).forEach(([key, value]) => { + window.ProcessMaker.alert(`${key}: ${value[0]}`, 'danger', 0); + }); + } else if (error.response.data.message) { + window.ProcessMaker.alert(error.response.data.message, 'danger', 0); + } + this.$refs.task.loadNextAssignedTask(); } }).finally(() => { this.submitting = false; From 77d650b9d05ef9091b0d00e724453fcc62cd63d8 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Mon, 24 Jun 2024 17:12:13 -0400 Subject: [PATCH 5/8] Remove debug code --- ProcessMaker/Http/Resources/V1_1/TaskResource.php | 1 - 1 file changed, 1 deletion(-) diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php index 51c0d5edb2..dd9b948f23 100644 --- a/ProcessMaker/Http/Resources/V1_1/TaskResource.php +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -109,7 +109,6 @@ private static function addRelationship(ProcessRequestToken $model, string $rela } $relationshipColumns = self::$defaultFieldsFor[$relationship] ?? ['id']; - $sql = $relationshipObject->toRawSql(); $model->$relationship = $relationshipObject->select($relationshipColumns)->getResults(); return true; From 14506b092e9e548ac9b320dd3d34f4856c370e03 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 25 Jun 2024 09:44:14 -0400 Subject: [PATCH 6/8] Remove commented code --- ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php b/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php index 79eca44e79..4a7dd3bfc5 100644 --- a/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/V1_1/TaskController.php @@ -44,7 +44,6 @@ public function index() 'currentPage' => $pagination->currentPage(), 'lastPage' => $pagination->lastPage(), 'count' => $pagination->count(), - // 'filter' => $filter, 'from' => $perPage * ($page - 1) + 1, 'last_page' => $lastPage, 'path' => '/', From fbb1fda2693ea6f9f4eabcdd34b2ee707bca7dfd Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 25 Jun 2024 10:11:55 -0400 Subject: [PATCH 7/8] Add docker-executor-php-nayra:install --- .../Commands/DockerExecutorPhpNayra.php | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php diff --git a/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php b/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php new file mode 100644 index 0000000000..1da053e5a4 --- /dev/null +++ b/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php @@ -0,0 +1,46 @@ +exists(); + if (!$exists) { + ScriptExecutor::install([ + 'language' => Base::NAYRA_LANG, + 'title' => 'Nayra (µService)', + 'description' => 'Nayra (µService) Executor', + 'config' => 'RUN composer require nayra/nayra', + ]); + } + + // Build the instance image. This is the same as if you were to build it from the admin UI + Artisan::call('processmaker:build-script-executor ' . Base::NAYRA_LANG . ' --rebuild'); + } +} From 26b703adf42ac8b80754b17f3ee05574c3f2aa5f Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Tue, 25 Jun 2024 23:29:56 -0400 Subject: [PATCH 8/8] Fix default docker config --- ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php b/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php index 1da053e5a4..08586bc99f 100644 --- a/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php +++ b/ProcessMaker/Console/Commands/DockerExecutorPhpNayra.php @@ -36,7 +36,7 @@ public function handle() 'language' => Base::NAYRA_LANG, 'title' => 'Nayra (µService)', 'description' => 'Nayra (µService) Executor', - 'config' => 'RUN composer require nayra/nayra', + 'config' => '', ]); }