From e2ab33b3d17cd28f3015371ec1f617531cac5886 Mon Sep 17 00:00:00 2001 From: Teisha McRae Date: Wed, 18 Sep 2024 13:31:50 -0400 Subject: [PATCH 1/3] Add route for applyTemplate --- ProcessMaker/Http/Controllers/Api/TemplateController.php | 5 +++++ ProcessMaker/Models/Template.php | 5 +++++ routes/api.php | 1 + 3 files changed, 11 insertions(+) diff --git a/ProcessMaker/Http/Controllers/Api/TemplateController.php b/ProcessMaker/Http/Controllers/Api/TemplateController.php index 0cb2426fa7..213f44c2ca 100644 --- a/ProcessMaker/Http/Controllers/Api/TemplateController.php +++ b/ProcessMaker/Http/Controllers/Api/TemplateController.php @@ -242,6 +242,11 @@ public function deleteMediaImages(string $type, Request $request) return $this->template->deleteMediaImages($type, $request); } + public function applyTemplate(string $type, Request $request) + { + return $this->template->applyTemplate($type, $request); + } + private function validateImportedFile($content, $request, $type) { $decoded = null; diff --git a/ProcessMaker/Models/Template.php b/ProcessMaker/Models/Template.php index 6fc29dcd3a..1a7ed2768c 100644 --- a/ProcessMaker/Models/Template.php +++ b/ProcessMaker/Models/Template.php @@ -101,6 +101,11 @@ public function deleteMediaImages(string $type, Request $request) return (new $this->types[$type][1])->deleteMediaImages($request); } + public function applyTemplate(string $type, Request $request) + { + return (new $this->types[$type][1])->applyTemplate($request); + } + public function user() { return $this->belongsTo(User::class, 'user_id'); diff --git a/routes/api.php b/routes/api.php index 4e55539bbe..c2c68b792a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -330,6 +330,7 @@ Route::get('modeler/templates/{type}/{id}', [TemplateController::class, 'show'])->name('modeler.template.show')->middleware('template-authorization'); Route::post('templates/{type}/import/validation', [TemplateController::class, 'preImportValidation'])->name('template.preImportValidation')->middleware('template-authorization'); Route::post('template/{type}/{id}/publish', [TemplateController::class, 'publishTemplate'])->name('template.publishTemplate')->middleware('can:publish-screen-templates'); + Route::post('template/{type}/{id}/apply', [TemplateController::class, 'applyTemplate'])->name('template.applyTemplate')->middleware('template-authorization'); Route::get('screen-builder/{type}/{id}', [TemplateController::class, 'show'])->name('screenBuilder.template.show')->middleware('template-authorization'); // Wizard Templates From 303054f5e5ebaf6a41225ed252e2b453d87998e0 Mon Sep 17 00:00:00 2001 From: Teisha McRae Date: Wed, 18 Sep 2024 13:33:41 -0400 Subject: [PATCH 2/3] Apply CSS to Screen --- ProcessMaker/Helpers/ScreenTemplateHelper.php | 68 +++++++++++++++++++ ProcessMaker/Templates/ScreenTemplate.php | 33 +++++++++ 2 files changed, 101 insertions(+) diff --git a/ProcessMaker/Helpers/ScreenTemplateHelper.php b/ProcessMaker/Helpers/ScreenTemplateHelper.php index b8360b3496..b2c64b5e23 100644 --- a/ProcessMaker/Helpers/ScreenTemplateHelper.php +++ b/ProcessMaker/Helpers/ScreenTemplateHelper.php @@ -250,4 +250,72 @@ private static function flattenNestedItems($items) return $flattenedItems; } + + // Parse the CSS string into an associative array + public static function parseCss($cssString) + { + $rules = []; + // Regex to match complex CSS selectors, allowing for any selector pattern + preg_match_all('/\[selector="([\w-]+)"\]\s*([^{]+)\s*{([^}]+)}/', $cssString, $matches, PREG_SET_ORDER); + + foreach ($matches as $match) { + $baseSelector = $match[1]; + $additionalSelector = trim($match[2]); + $fullSelector = "[selector=\"$baseSelector\"] " . $additionalSelector; + $propertiesString = trim($match[3]); + + // Split properties into key-value pairs + $propertiesArray = explode(';', $propertiesString); + $properties = []; + + foreach ($propertiesArray as $property) { + $propertyParts = explode(':', $property); + if (count($propertyParts) == 2) { + $key = trim($propertyParts[0]); + $value = trim($propertyParts[1]); + if (!empty($key) && !empty($value)) { + $properties[$key] = $value; + } + } + } + + $rules[$fullSelector] = $properties; + } + + return $rules; + } + + // Merge the two CSS arrays + public static function mergeCss($currentCss, $templateCss) + { + foreach ($templateCss as $selector => $properties) { + if (isset($currentCss[$selector])) { + // Merge properties from Template CSS into the Current Screen CSS for the same selector + $currentCss[$selector] = array_merge($currentCss[$selector], $properties); + } else { + // Add new selector and properties from Template CSS + $currentCss[$selector] = $properties; + } + } + + return $currentCss; + } + + public static function generateCss($cssArray) + { + // Convert the CSS array back into a string and output the final CSS + $cssString = ''; + + foreach ($cssArray as $selector => $properties) { + $cssString .= "$selector {\n"; + + foreach ($properties as $key => $value) { + $cssString .= " $key: $value;\n"; + } + + $cssString .= "}\n\n"; + } + + return $cssString; + } } diff --git a/ProcessMaker/Templates/ScreenTemplate.php b/ProcessMaker/Templates/ScreenTemplate.php index 7c77db54c2..544f9b9f11 100644 --- a/ProcessMaker/Templates/ScreenTemplate.php +++ b/ProcessMaker/Templates/ScreenTemplate.php @@ -677,6 +677,39 @@ public function syncProjectAssets($data, int $newScreenId): void } } + // Applies the template to an existing screen in screen builder + public function applyTemplate($request) + { + // Get the selected template + $templateId = (int) $request->id; + $template = ScreenTemplates::findOrFail($templateId); + + // Get the selected template options + $templateOptions = $request->get('templateOptions'); + // Get the current screen to apply the template + $screenId = $request->get('screenId'); + $screen = Screen::where('id', $screenId)->first(); + // Define available options and their corresponding components + $availableOptions = ScreenComponents::getComponents(); + + if (is_array($templateOptions)) { + // Iterate through available options to handle each one + foreach ($availableOptions as $option => $components) { + // Apply the CSS to the current screen + if ($option == 'CSS' && in_array($option, $templateOptions)) { + $currentScreenCssArray = ScreenTemplateHelper::parseCss($screen->custom_css); + $templateCssArray = ScreenTemplateHelper::parseCss($template->screen_custom_css); + $mergedCss = ScreenTemplateHelper::mergeCss($currentScreenCssArray, $templateCssArray); + + $finalCss = ScreenTemplateHelper::generateCss($mergedCss); + $screen->custom_css = $finalCss; + } + + $screen->save(); + } + } + } + private function syncTemplateMedia($template, $media) { // Get the UUIDs of updated media From 1c9147646de6c9c526e49090fa616806248c9a94 Mon Sep 17 00:00:00 2001 From: Teisha McRae Date: Wed, 18 Sep 2024 14:45:24 -0400 Subject: [PATCH 3/3] Update regex in ScreenTemplateHelper --- ProcessMaker/Helpers/ScreenTemplateHelper.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ProcessMaker/Helpers/ScreenTemplateHelper.php b/ProcessMaker/Helpers/ScreenTemplateHelper.php index b2c64b5e23..652591f1c9 100644 --- a/ProcessMaker/Helpers/ScreenTemplateHelper.php +++ b/ProcessMaker/Helpers/ScreenTemplateHelper.php @@ -256,13 +256,11 @@ public static function parseCss($cssString) { $rules = []; // Regex to match complex CSS selectors, allowing for any selector pattern - preg_match_all('/\[selector="([\w-]+)"\]\s*([^{]+)\s*{([^}]+)}/', $cssString, $matches, PREG_SET_ORDER); + preg_match_all('/([^{}]+)\s*\{([^}]*)\}/', $cssString, $matches, PREG_SET_ORDER); foreach ($matches as $match) { - $baseSelector = $match[1]; - $additionalSelector = trim($match[2]); - $fullSelector = "[selector=\"$baseSelector\"] " . $additionalSelector; - $propertiesString = trim($match[3]); + $fullSelector = trim($match[1]); // Full CSS selector + $propertiesString = trim($match[2]); // Properties between the brackets // Split properties into key-value pairs $propertiesArray = explode(';', $propertiesString); @@ -279,6 +277,7 @@ public static function parseCss($cssString) } } + // Add rule for the selector $rules[$fullSelector] = $properties; }