diff --git a/ProcessMaker/Console/Commands/EvaluateCaseRetention.php b/ProcessMaker/Console/Commands/EvaluateCaseRetention.php new file mode 100644 index 0000000000..61245fc915 --- /dev/null +++ b/ProcessMaker/Console/Commands/EvaluateCaseRetention.php @@ -0,0 +1,74 @@ +info('Case retention policy is disabled'); + $this->error('Skipping case retention evaluation'); + + return; + } + + $this->info('Case retention policy is enabled'); + $this->info('Dispatching retention evaluation jobs for all processes'); + + // Get system category IDs to exclude + $systemCategoryIds = ProcessCategory::where('is_system', true)->pluck('id'); + + // Exclude processes that are templates or in system categories + $jobCount = 0; + $query = Process::where('is_template', '!=', 1); + + // Exclude processes in system categories + if ($systemCategoryIds->isNotEmpty()) { + $query->where(function ($q) use ($systemCategoryIds) { + $q->where(function ($subQuery) use ($systemCategoryIds) { + $subQuery->whereNotIn('process_category_id', $systemCategoryIds) + ->orWhereNull('process_category_id'); + }); + }) + ->whereDoesntHave('categories', function ($q) use ($systemCategoryIds) { + // Exclude processes with any category assignment to system categories + $q->whereIn('process_categories.id', $systemCategoryIds); + }); + } + + $query->chunkById(100, function ($processes) use (&$jobCount) { + foreach ($processes as $process) { + dispatch(new EvaluateProcessRetentionJob($process->id)); + $jobCount++; + } + }); + + $this->info("Dispatched {$jobCount} retention evaluation job(s) to the queue"); + $this->info('Jobs will be processed asynchronously by queue workers'); + } +} diff --git a/ProcessMaker/Console/Kernel.php b/ProcessMaker/Console/Kernel.php index 7edd255225..03fc408949 100644 --- a/ProcessMaker/Console/Kernel.php +++ b/ProcessMaker/Console/Kernel.php @@ -90,6 +90,13 @@ protected function schedule(Schedule $schedule) break; } + // evaluate cases retention policy + $schedule->command('cases:retention:evaluate') + ->daily() + ->onOneServer() + ->withoutOverlapping() + ->runInBackground(); + // 5 minutes is recommended in https://laravel.com/docs/12.x/horizon#metrics $schedule->command('horizon:snapshot')->everyFiveMinutes(); } diff --git a/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeleteCase.php b/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeleteCase.php index 6d34bcf7b7..7dc266c2ea 100644 --- a/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeleteCase.php +++ b/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeleteCase.php @@ -99,20 +99,4 @@ private function getTaskDraftIds(array $tokenIds): array ->pluck('id') ->all(); } - - private function dispatchSavedSearchRecount(): void - { - if (!config('savedsearch.count', false)) { - return; - } - - $jobClass = 'ProcessMaker\\Package\\SavedSearch\\Jobs\\RecountAllSavedSearches'; - if (!class_exists($jobClass)) { - return; - } - - DB::afterCommit(static function () use ($jobClass): void { - $jobClass::dispatch(['request', 'task']); - }); - } } diff --git a/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeletesCaseRecords.php b/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeletesCaseRecords.php index f59850a67b..05bc9ebe00 100644 --- a/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeletesCaseRecords.php +++ b/ProcessMaker/Http/Controllers/Api/Actions/Cases/DeletesCaseRecords.php @@ -21,18 +21,30 @@ trait DeletesCaseRecords { - private function deleteCasesStarted(string $caseNumber): void + private function deleteCasesStarted(string | array $caseNumbers): void { - CaseStarted::query() - ->where('case_number', $caseNumber) - ->delete(); + if (is_array($caseNumbers) && $caseNumbers !== []) { + CaseStarted::query() + ->whereIn('case_number', $caseNumbers) + ->delete(); + } else { + CaseStarted::query() + ->where('case_number', $caseNumbers) + ->delete(); + } } - private function deleteCasesParticipated(string $caseNumber): void + private function deleteCasesParticipated(string | array $caseNumbers): void { - CaseParticipated::query() - ->where('case_number', $caseNumber) - ->delete(); + if (is_array($caseNumbers)) { + CaseParticipated::query() + ->whereIn('case_number', $caseNumbers) + ->delete(); + } else { + CaseParticipated::query() + ->where('case_number', $caseNumbers) + ->delete(); + } } private function deleteCaseNumbers(array $requestIds): void @@ -183,11 +195,18 @@ private function deleteRequestMedia(array $requestIds): void ->delete(); } - private function deleteComments(string $caseNumber, array $requestIds, array $tokenIds): void + private function deleteComments(string | array $caseNumbers, array $requestIds, array $tokenIds): void { - Comment::query() - ->where('case_number', $caseNumber) - ->orWhere(function ($query) use ($requestIds, $tokenIds) { + if (is_array($caseNumbers) && $caseNumbers !== []) { + $query = Comment::query() + ->whereIn('case_number', $caseNumbers); + } else { + $query = Comment::query() + ->where('case_number', $caseNumbers); + } + + if ($requestIds !== [] || $tokenIds !== []) { + $query->orWhere(function ($query) use ($requestIds, $tokenIds) { $query->where('commentable_type', ProcessRequest::class) ->whereIn('commentable_id', $requestIds); @@ -197,8 +216,10 @@ private function deleteComments(string $caseNumber, array $requestIds, array $to ->whereIn('commentable_id', $tokenIds); }); } - }) - ->delete(); + }); + } + + $query->delete(); } private function deleteNotifications(array $requestIds): void @@ -220,4 +241,20 @@ private function deleteNotifications(array $requestIds): void ->whereIn('data->type', $notificationTypes) ->delete(); } + + private function dispatchSavedSearchRecount(): void + { + if (!config('savedsearch.count', false)) { + return; + } + + $jobClass = 'ProcessMaker\\Package\\SavedSearch\\Jobs\\RecountAllSavedSearches'; + if (!class_exists($jobClass)) { + return; + } + + DB::afterCommit(static function () use ($jobClass): void { + $jobClass::dispatch(['request', 'task']); + }); + } } diff --git a/ProcessMaker/Jobs/EvaluateProcessRetentionJob.php b/ProcessMaker/Jobs/EvaluateProcessRetentionJob.php new file mode 100644 index 0000000000..1e1df53c57 --- /dev/null +++ b/ProcessMaker/Jobs/EvaluateProcessRetentionJob.php @@ -0,0 +1,251 @@ + $this->processId, + ]); + + // Only run if case retention policy is enabled + $enabled = config('app.case_retention_policy_enabled', false); + if (!$enabled) { + Log::info('EvaluateProcessRetentionJob: Case retention policy is disabled, skipping', [ + 'process_id' => $this->processId, + ]); + + return; + } + + $process = Process::find($this->processId); + if (!$process) { + Log::error('EvaluateProcessRetentionJob: Process not found', [ + 'process_id' => $this->processId, + ]); + + return; + } + + // Skip template processes + if ($process->is_template) { + Log::info('EvaluateProcessRetentionJob: Skipping template process', [ + 'process_id' => $this->processId, + ]); + + return; + } + + // Skip processes in system categories + if ($process->categories()->where('is_system', true)->exists()) { + Log::info('EvaluateProcessRetentionJob: Skipping process in system category', [ + 'process_id' => $this->processId, + ]); + + return; + } + + // Default to one_year if retention_period is not set + $retentionPeriod = $process->properties['retention_period'] ?? 'one_year'; + $retentionMonths = match ($retentionPeriod) { + 'six_months' => 6, + 'one_year' => 12, + 'three_years' => 36, + 'five_years' => 60, + default => 12, // Default to one_year + }; + + Log::info('EvaluateProcessRetentionJob: Retention configuration loaded', [ + 'process_id' => $this->processId, + 'process_name' => $process->name, + 'retention_period' => $retentionPeriod, + 'retention_months' => $retentionMonths, + ]); + + // Default retention_updated_at to now if not set + // This means the retention policy applies from now for processes without explicit retention settings + $retentionUpdatedAt = isset($process->properties['retention_updated_at']) + ? Carbon::parse($process->properties['retention_updated_at']) + : Carbon::now(); + + // Check if there are any process requests for this process + if (!ProcessRequest::where('process_id', $this->processId)->exists()) { + Log::info('EvaluateProcessRetentionJob: No process requests found, nothing to evaluate', [ + 'process_id' => $this->processId, + ]); + + return; + } + + // Handle two scenarios: + // 1. Cases created BEFORE retention_updated_at: Delete if older than retention period from retention_updated_at + // (These cases were subject to the old retention policy, but we apply current retention from update date) + // 2. Cases created AFTER retention_updated_at: Delete if older than retention period from their creation date + // (These cases are subject to the new retention policy) + + $now = Carbon::now(); + + // For cases created before retention_updated_at: cutoff is retention_updated_at - retention_period + $oldCasesCutoff = $retentionUpdatedAt->copy()->subMonths($retentionMonths); + + // For cases created after retention_updated_at: cutoff is now - retention_period + $newCasesCutoff = $now->copy()->subMonths($retentionMonths); + + Log::info('EvaluateProcessRetentionJob: Retention cutoff dates calculated', [ + 'process_id' => $this->processId, + 'retention_updated_at' => $retentionUpdatedAt->toIso8601String(), + 'old_cases_cutoff' => $oldCasesCutoff->toIso8601String(), + 'new_cases_cutoff' => $newCasesCutoff->toIso8601String(), + 'current_time' => $now->toIso8601String(), + ]); + + // Use subquery to get process request IDs + $processRequestSubquery = ProcessRequest::where('process_id', $this->processId)->select('id'); + + // Collect all ProcessRequest IDs that will be deleted (to delete them after all chunks are processed) + $processRequestIdsToDelete = []; + $totalDeleted = 0; + $chunkCount = 0; + + CaseNumber::whereIn('process_request_id', $processRequestSubquery) + ->where($this->buildRetentionQuery($retentionUpdatedAt, $oldCasesCutoff, $newCasesCutoff)) + ->chunkById(100, function ($cases) use (&$processRequestIdsToDelete, &$totalDeleted, &$chunkCount) { + $caseIds = $cases->pluck('id')->all(); + $processRequestIds = $cases->pluck('process_request_id')->unique()->all(); + + // Collect ProcessRequest IDs for deletion after all chunks are processed + $processRequestIdsToDelete = array_merge($processRequestIdsToDelete, $processRequestIds); + + $processRequestTokenIds = ProcessRequestToken::whereIn('process_request_id', $processRequestIds)->pluck('id')->all(); + $draftIds = $this->getTaskDraftIds($processRequestTokenIds); + + // uses case_number to delete + $this->deleteCasesStarted($caseIds); + $this->deleteCasesParticipated($caseIds); + $this->deleteComments($caseIds, $processRequestIds, $processRequestTokenIds); + + // Delete the CaseNumber records that were returned by the query (by their IDs) + CaseNumber::whereIn('id', $caseIds)->delete(); + + $this->deleteProcessRequestLocks($processRequestIds, $processRequestTokenIds); + $this->deleteInboxRuleLogs($processRequestTokenIds); + $this->deleteInboxRules($processRequestTokenIds); + $this->deleteProcessAbeRequestTokens($processRequestIds, $processRequestTokenIds); + $this->deleteScheduledTasks($processRequestIds, $processRequestTokenIds); + $this->deleteEllucianEthosSyncTasks($processRequestTokenIds); + + $this->deleteTaskDraftMedia($draftIds); + $this->deleteTaskDrafts($processRequestTokenIds); + + $chunkCount++; + $chunkSize = count($caseIds); + $totalDeleted += $chunkSize; + + Log::info('EvaluateProcessRetentionJob: Deleted chunk of cases', [ + 'process_id' => $this->processId, + 'chunk_number' => $chunkCount, + 'cases_deleted' => $chunkSize, + ]); + }); + + // Delete ProcessRequests after all chunks are processed + // Only delete ProcessRequests that have no remaining cases + if (!empty($processRequestIdsToDelete)) { + $processRequestIdsToDelete = array_unique($processRequestIdsToDelete); + + // Filter to only ProcessRequests that have no remaining CaseNumbers + $processRequestIdsWithNoCases = array_filter($processRequestIdsToDelete, function ($requestId) { + return !CaseNumber::where('process_request_id', $requestId)->exists(); + }); + + if (!empty($processRequestIdsWithNoCases)) { + $this->deleteProcessRequests($processRequestIdsWithNoCases); + + // Delete any remaining related records + $this->deleteRequestMedia($processRequestIdsWithNoCases); + $this->deleteNotifications($processRequestIdsWithNoCases); + + $this->dispatchSavedSearchRecount(); + } + } + + $endTime = microtime(true); + $executionTime = round(($endTime - $startTime) * 1000, 2); + + Log::info('EvaluateProcessRetentionJob: Evaluation completed', [ + 'process_id' => $this->processId, + 'total_cases_deleted' => $totalDeleted, + 'total_chunks_processed' => $chunkCount, + 'execution_time_ms' => $executionTime, + ]); + } + + /** + * Build a retention query closure that can be applied to any query builder. + * + * This method encapsulates the retention evaluation logic: + * - Cases created before retention_updated_at: delete if created before (retention_updated_at - retention_period) + * - Cases created after retention_updated_at: delete if created before (now - retention_period) + * + * @param Carbon $retentionUpdatedAt The date when the retention policy was updated + * @param Carbon $oldCasesCutoff The cutoff date for cases created before retention_updated_at + * @param Carbon $newCasesCutoff The cutoff date for cases created after retention_updated_at + * @return \Closure A closure that applies the retention query to a query builder + */ + private function buildRetentionQuery(Carbon $retentionUpdatedAt, Carbon $oldCasesCutoff, Carbon $newCasesCutoff): \Closure + { + return function ($query) use ($retentionUpdatedAt, $oldCasesCutoff, $newCasesCutoff) { + // Cases created before retention_updated_at: delete if created before (retention_updated_at - retention_period) + $query->where(function ($q) use ($retentionUpdatedAt, $oldCasesCutoff) { + $q->where('created_at', '<', $retentionUpdatedAt) + ->where('created_at', '<', $oldCasesCutoff); + }) + // Cases created after retention_updated_at: delete if created before (now - retention_period) + ->orWhere(function ($q) use ($retentionUpdatedAt, $newCasesCutoff) { + $q->where('created_at', '>=', $retentionUpdatedAt) + ->where('created_at', '<', $newCasesCutoff); + }); + }; + } + + private function getTaskDraftIds(array $tokenIds): array + { + if ($tokenIds === []) { + return []; + } + + return TaskDraft::query() + ->whereIn('task_id', $tokenIds) + ->pluck('id') + ->all(); + } +} diff --git a/README.md b/README.md index 17789a6e1a..889bb63882 100644 --- a/README.md +++ b/README.md @@ -439,6 +439,26 @@ How to use icon: npm run dev-font ``` +# Case Retention Tier (CASE_RETENTION_TIER) + +The case retention policy controls how long cases are stored before they are automatically and permanently deleted. The **CASE_RETENTION_TIER** environment variable determines which retention periods customers can select when configuring a process. Each tier exposes a different set of options in the UI; options for higher tiers are visible but disabled so users see what is available at higher tiers. + +### Supported tiers + +| Tier | Retention options available | +|------|----------------------------| +| **1** | Six months, One year | +| **2** | Six months, One year, Three years | +| **3** | Six months, One year, Three years, Five years | + +Set the variable in your `.env` file: +```env +CASE_RETENTION_POLICY_ENABLED=true +CASE_RETENTION_TIER=1 +``` +Use `1`, `2`, or `3`. The default is `1` if not set. The default retention period shown in the UI for Tier 1 is one year. + + # Prometheus and Grafana diff --git a/config/app.php b/config/app.php index 4d461545fd..229bca462c 100644 --- a/config/app.php +++ b/config/app.php @@ -288,6 +288,9 @@ // Enable or disable TCE customization feature 'tce_customization_enable' => env('TCE_CUSTOMIZATION_ENABLED', false), + // Enable or disable case retention policy + 'case_retention_policy_enabled' => env('CASE_RETENTION_POLICY_ENABLED', false), + 'prometheus_namespace' => env('PROMETHEUS_NAMESPACE', strtolower(preg_replace('/[^a-zA-Z0-9_]+/', '_', env('APP_NAME', 'processmaker')))), 'server_timing' => [ @@ -302,6 +305,18 @@ 'multitenancy' => env('MULTITENANCY', false), 'reassign_restrict_to_assignable_users' => env('REASSIGN_RESTRICT_TO_ASSIGNABLE_USERS', true), + + // When true, shows the Cases Retention section on process configuration + 'case_retention_policy_enabled' => filter_var(env('CASE_RETENTION_POLICY_ENABLED', false), FILTER_VALIDATE_BOOLEAN), + + // Controls which retention periods are available in the UI for the current tier. + 'case_retention_tier' => env('CASE_RETENTION_TIER', '1'), + 'case_retention_tier_options' => [ + '1' => ['six_months', 'one_year'], + '2' => ['six_months', 'one_year', 'three_years'], + '3' => ['six_months', 'one_year', 'three_years', 'five_years'], + ], + 'resources_core_path' => base_path('resources-core'), 'scheduler' => [ 'claim_timeout_minutes' => env('SCHEDULER_CLAIM_TIMEOUT_MINUTES', 5), diff --git a/devhub/pm-font/svg/check-circle-outline.svg b/devhub/pm-font/svg/check-circle-outline.svg new file mode 100644 index 0000000000..79932fc0c0 --- /dev/null +++ b/devhub/pm-font/svg/check-circle-outline.svg @@ -0,0 +1,3 @@ + diff --git a/devhub/pm-font/svg/exclamation-triangle.svg b/devhub/pm-font/svg/exclamation-triangle.svg new file mode 100644 index 0000000000..dc9fa5ea18 --- /dev/null +++ b/devhub/pm-font/svg/exclamation-triangle.svg @@ -0,0 +1,3 @@ + diff --git a/resources/fonts/pm-font/index.html b/resources/fonts/pm-font/index.html index 90ee73e5e7..19b60faa9a 100644 --- a/resources/fonts/pm-font/index.html +++ b/resources/fonts/pm-font/index.html @@ -103,7 +103,7 @@
diff --git a/resources/fonts/pm-font/processmaker-font.css b/resources/fonts/pm-font/processmaker-font.css
index c716cce24f..e8ceeedff5 100644
--- a/resources/fonts/pm-font/processmaker-font.css
+++ b/resources/fonts/pm-font/processmaker-font.css
@@ -1,11 +1,11 @@
@font-face {
font-family: "processmaker-font";
- src: url('processmaker-font.eot?t=1747081178345'); /* IE9*/
- src: url('processmaker-font.eot?t=1747081178345#iefix') format('embedded-opentype'), /* IE6-IE8 */
- url("processmaker-font.woff2?t=1747081178345") format("woff2"),
- url("processmaker-font.woff?t=1747081178345") format("woff"),
- url('processmaker-font.ttf?t=1747081178345') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
- url('processmaker-font.svg?t=1747081178345#processmaker-font') format('svg'); /* iOS 4.1- */
+ src: url('processmaker-font.eot?t=1770239064379'); /* IE9*/
+ src: url('processmaker-font.eot?t=1770239064379#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url("processmaker-font.woff2?t=1770239064379") format("woff2"),
+ url("processmaker-font.woff?t=1770239064379") format("woff"),
+ url('processmaker-font.ttf?t=1770239064379') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('processmaker-font.svg?t=1770239064379#processmaker-font') format('svg'); /* iOS 4.1- */
}
[class^="fp-"], [class*=" fp-"] {
@@ -37,42 +37,44 @@
.fp-bpmn-text-annotation:before { content: "\ea13"; }
.fp-brush-icon:before { content: "\ea14"; }
.fp-check-circle-blue:before { content: "\ea15"; }
-.fp-close:before { content: "\ea16"; }
-.fp-cloud-download-outline:before { content: "\ea17"; }
-.fp-connector-outline:before { content: "\ea18"; }
-.fp-copy-outline:before { content: "\ea19"; }
-.fp-copy:before { content: "\ea1a"; }
-.fp-desktop:before { content: "\ea1b"; }
-.fp-edit-outline:before { content: "\ea1c"; }
-.fp-expand:before { content: "\ea1d"; }
-.fp-eye:before { content: "\ea1e"; }
-.fp-fields-icon:before { content: "\ea1f"; }
-.fp-flowgenie-outline:before { content: "\ea20"; }
-.fp-folder-outline:before { content: "\ea21"; }
-.fp-fullscreen:before { content: "\ea22"; }
-.fp-github:before { content: "\ea23"; }
-.fp-inbox:before { content: "\ea24"; }
-.fp-layout-icon:before { content: "\ea25"; }
-.fp-link-icon:before { content: "\ea26"; }
-.fp-map:before { content: "\ea27"; }
-.fp-minimize:before { content: "\ea28"; }
-.fp-mobile:before { content: "\ea29"; }
-.fp-pdf:before { content: "\ea2a"; }
-.fp-pen-edit:before { content: "\ea2b"; }
-.fp-play-outline:before { content: "\ea2c"; }
-.fp-plus-thin:before { content: "\ea2d"; }
-.fp-plus:before { content: "\ea2e"; }
-.fp-pm-block:before { content: "\ea2f"; }
-.fp-remove-outlined:before { content: "\ea30"; }
-.fp-screen-outline:before { content: "\ea31"; }
-.fp-script-outline:before { content: "\ea32"; }
-.fp-slack-notification:before { content: "\ea33"; }
-.fp-slack:before { content: "\ea34"; }
-.fp-slideshow:before { content: "\ea35"; }
-.fp-table:before { content: "\ea36"; }
-.fp-tachometer-alt-average:before { content: "\ea37"; }
-.fp-trash-blue:before { content: "\ea38"; }
-.fp-trash:before { content: "\ea39"; }
-.fp-unlink:before { content: "\ea3a"; }
-.fp-update-outline:before { content: "\ea3b"; }
+.fp-check-circle-outline:before { content: "\ea16"; }
+.fp-close:before { content: "\ea17"; }
+.fp-cloud-download-outline:before { content: "\ea18"; }
+.fp-connector-outline:before { content: "\ea19"; }
+.fp-copy-outline:before { content: "\ea1a"; }
+.fp-copy:before { content: "\ea1b"; }
+.fp-desktop:before { content: "\ea1c"; }
+.fp-edit-outline:before { content: "\ea1d"; }
+.fp-exclamation-triangle:before { content: "\ea1e"; }
+.fp-expand:before { content: "\ea1f"; }
+.fp-eye:before { content: "\ea20"; }
+.fp-fields-icon:before { content: "\ea21"; }
+.fp-flowgenie-outline:before { content: "\ea22"; }
+.fp-folder-outline:before { content: "\ea23"; }
+.fp-fullscreen:before { content: "\ea24"; }
+.fp-github:before { content: "\ea25"; }
+.fp-inbox:before { content: "\ea26"; }
+.fp-layout-icon:before { content: "\ea27"; }
+.fp-link-icon:before { content: "\ea28"; }
+.fp-map:before { content: "\ea29"; }
+.fp-minimize:before { content: "\ea2a"; }
+.fp-mobile:before { content: "\ea2b"; }
+.fp-pdf:before { content: "\ea2c"; }
+.fp-pen-edit:before { content: "\ea2d"; }
+.fp-play-outline:before { content: "\ea2e"; }
+.fp-plus-thin:before { content: "\ea2f"; }
+.fp-plus:before { content: "\ea30"; }
+.fp-pm-block:before { content: "\ea31"; }
+.fp-remove-outlined:before { content: "\ea32"; }
+.fp-screen-outline:before { content: "\ea33"; }
+.fp-script-outline:before { content: "\ea34"; }
+.fp-slack-notification:before { content: "\ea35"; }
+.fp-slack:before { content: "\ea36"; }
+.fp-slideshow:before { content: "\ea37"; }
+.fp-table:before { content: "\ea38"; }
+.fp-tachometer-alt-average:before { content: "\ea39"; }
+.fp-trash-blue:before { content: "\ea3a"; }
+.fp-trash:before { content: "\ea3b"; }
+.fp-unlink:before { content: "\ea3c"; }
+.fp-update-outline:before { content: "\ea3d"; }
diff --git a/resources/fonts/pm-font/processmaker-font.eot b/resources/fonts/pm-font/processmaker-font.eot
index fc8398ccf1..b10e9eb2b5 100644
Binary files a/resources/fonts/pm-font/processmaker-font.eot and b/resources/fonts/pm-font/processmaker-font.eot differ
diff --git a/resources/fonts/pm-font/processmaker-font.less b/resources/fonts/pm-font/processmaker-font.less
index 889600b9db..9d190be82b 100644
--- a/resources/fonts/pm-font/processmaker-font.less
+++ b/resources/fonts/pm-font/processmaker-font.less
@@ -1,10 +1,10 @@
@font-face {font-family: "processmaker-font";
- src: url('processmaker-font.eot?t=1747081178345'); /* IE9*/
- src: url('processmaker-font.eot?t=1747081178345#iefix') format('embedded-opentype'), /* IE6-IE8 */
- url("processmaker-font.woff2?t=1747081178345") format("woff2"),
- url("processmaker-font.woff?t=1747081178345") format("woff"),
- url('processmaker-font.ttf?t=1747081178345') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
- url('processmaker-font.svg?t=1747081178345#processmaker-font') format('svg'); /* iOS 4.1- */
+ src: url('processmaker-font.eot?t=1770239064379'); /* IE9*/
+ src: url('processmaker-font.eot?t=1770239064379#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url("processmaker-font.woff2?t=1770239064379") format("woff2"),
+ url("processmaker-font.woff?t=1770239064379") format("woff"),
+ url('processmaker-font.ttf?t=1770239064379') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('processmaker-font.svg?t=1770239064379#processmaker-font') format('svg'); /* iOS 4.1- */
}
[class^="fp-"], [class*=" fp-"] {
@@ -35,41 +35,43 @@
.fp-bpmn-text-annotation:before { content: "\ea13"; }
.fp-brush-icon:before { content: "\ea14"; }
.fp-check-circle-blue:before { content: "\ea15"; }
-.fp-close:before { content: "\ea16"; }
-.fp-cloud-download-outline:before { content: "\ea17"; }
-.fp-connector-outline:before { content: "\ea18"; }
-.fp-copy-outline:before { content: "\ea19"; }
-.fp-copy:before { content: "\ea1a"; }
-.fp-desktop:before { content: "\ea1b"; }
-.fp-edit-outline:before { content: "\ea1c"; }
-.fp-expand:before { content: "\ea1d"; }
-.fp-eye:before { content: "\ea1e"; }
-.fp-fields-icon:before { content: "\ea1f"; }
-.fp-flowgenie-outline:before { content: "\ea20"; }
-.fp-folder-outline:before { content: "\ea21"; }
-.fp-fullscreen:before { content: "\ea22"; }
-.fp-github:before { content: "\ea23"; }
-.fp-inbox:before { content: "\ea24"; }
-.fp-layout-icon:before { content: "\ea25"; }
-.fp-link-icon:before { content: "\ea26"; }
-.fp-map:before { content: "\ea27"; }
-.fp-minimize:before { content: "\ea28"; }
-.fp-mobile:before { content: "\ea29"; }
-.fp-pdf:before { content: "\ea2a"; }
-.fp-pen-edit:before { content: "\ea2b"; }
-.fp-play-outline:before { content: "\ea2c"; }
-.fp-plus-thin:before { content: "\ea2d"; }
-.fp-plus:before { content: "\ea2e"; }
-.fp-pm-block:before { content: "\ea2f"; }
-.fp-remove-outlined:before { content: "\ea30"; }
-.fp-screen-outline:before { content: "\ea31"; }
-.fp-script-outline:before { content: "\ea32"; }
-.fp-slack-notification:before { content: "\ea33"; }
-.fp-slack:before { content: "\ea34"; }
-.fp-slideshow:before { content: "\ea35"; }
-.fp-table:before { content: "\ea36"; }
-.fp-tachometer-alt-average:before { content: "\ea37"; }
-.fp-trash-blue:before { content: "\ea38"; }
-.fp-trash:before { content: "\ea39"; }
-.fp-unlink:before { content: "\ea3a"; }
-.fp-update-outline:before { content: "\ea3b"; }
+.fp-check-circle-outline:before { content: "\ea16"; }
+.fp-close:before { content: "\ea17"; }
+.fp-cloud-download-outline:before { content: "\ea18"; }
+.fp-connector-outline:before { content: "\ea19"; }
+.fp-copy-outline:before { content: "\ea1a"; }
+.fp-copy:before { content: "\ea1b"; }
+.fp-desktop:before { content: "\ea1c"; }
+.fp-edit-outline:before { content: "\ea1d"; }
+.fp-exclamation-triangle:before { content: "\ea1e"; }
+.fp-expand:before { content: "\ea1f"; }
+.fp-eye:before { content: "\ea20"; }
+.fp-fields-icon:before { content: "\ea21"; }
+.fp-flowgenie-outline:before { content: "\ea22"; }
+.fp-folder-outline:before { content: "\ea23"; }
+.fp-fullscreen:before { content: "\ea24"; }
+.fp-github:before { content: "\ea25"; }
+.fp-inbox:before { content: "\ea26"; }
+.fp-layout-icon:before { content: "\ea27"; }
+.fp-link-icon:before { content: "\ea28"; }
+.fp-map:before { content: "\ea29"; }
+.fp-minimize:before { content: "\ea2a"; }
+.fp-mobile:before { content: "\ea2b"; }
+.fp-pdf:before { content: "\ea2c"; }
+.fp-pen-edit:before { content: "\ea2d"; }
+.fp-play-outline:before { content: "\ea2e"; }
+.fp-plus-thin:before { content: "\ea2f"; }
+.fp-plus:before { content: "\ea30"; }
+.fp-pm-block:before { content: "\ea31"; }
+.fp-remove-outlined:before { content: "\ea32"; }
+.fp-screen-outline:before { content: "\ea33"; }
+.fp-script-outline:before { content: "\ea34"; }
+.fp-slack-notification:before { content: "\ea35"; }
+.fp-slack:before { content: "\ea36"; }
+.fp-slideshow:before { content: "\ea37"; }
+.fp-table:before { content: "\ea38"; }
+.fp-tachometer-alt-average:before { content: "\ea39"; }
+.fp-trash-blue:before { content: "\ea3a"; }
+.fp-trash:before { content: "\ea3b"; }
+.fp-unlink:before { content: "\ea3c"; }
+.fp-update-outline:before { content: "\ea3d"; }
diff --git a/resources/fonts/pm-font/processmaker-font.module.less b/resources/fonts/pm-font/processmaker-font.module.less
index d101bf60e6..b0168741d1 100644
--- a/resources/fonts/pm-font/processmaker-font.module.less
+++ b/resources/fonts/pm-font/processmaker-font.module.less
@@ -1,10 +1,10 @@
@font-face {font-family: "processmaker-font";
- src: url('processmaker-font.eot?t=1747081178345'); /* IE9*/
- src: url('processmaker-font.eot?t=1747081178345#iefix') format('embedded-opentype'), /* IE6-IE8 */
- url("processmaker-font.woff2?t=1747081178345") format("woff2"),
- url("processmaker-font.woff?t=1747081178345") format("woff"),
- url('processmaker-font.ttf?t=1747081178345') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
- url('processmaker-font.svg?t=1747081178345#processmaker-font') format('svg'); /* iOS 4.1- */
+ src: url('processmaker-font.eot?t=1770239064379'); /* IE9*/
+ src: url('processmaker-font.eot?t=1770239064379#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url("processmaker-font.woff2?t=1770239064379") format("woff2"),
+ url("processmaker-font.woff?t=1770239064379") format("woff"),
+ url('processmaker-font.ttf?t=1770239064379') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('processmaker-font.svg?t=1770239064379#processmaker-font') format('svg'); /* iOS 4.1- */
}
[class^="fp-"], [class*=" fp-"] {
@@ -36,43 +36,45 @@
.fp-bpmn-text-annotation:before { content: "\ea13"; }
.fp-brush-icon:before { content: "\ea14"; }
.fp-check-circle-blue:before { content: "\ea15"; }
-.fp-close:before { content: "\ea16"; }
-.fp-cloud-download-outline:before { content: "\ea17"; }
-.fp-connector-outline:before { content: "\ea18"; }
-.fp-copy-outline:before { content: "\ea19"; }
-.fp-copy:before { content: "\ea1a"; }
-.fp-desktop:before { content: "\ea1b"; }
-.fp-edit-outline:before { content: "\ea1c"; }
-.fp-expand:before { content: "\ea1d"; }
-.fp-eye:before { content: "\ea1e"; }
-.fp-fields-icon:before { content: "\ea1f"; }
-.fp-flowgenie-outline:before { content: "\ea20"; }
-.fp-folder-outline:before { content: "\ea21"; }
-.fp-fullscreen:before { content: "\ea22"; }
-.fp-github:before { content: "\ea23"; }
-.fp-inbox:before { content: "\ea24"; }
-.fp-layout-icon:before { content: "\ea25"; }
-.fp-link-icon:before { content: "\ea26"; }
-.fp-map:before { content: "\ea27"; }
-.fp-minimize:before { content: "\ea28"; }
-.fp-mobile:before { content: "\ea29"; }
-.fp-pdf:before { content: "\ea2a"; }
-.fp-pen-edit:before { content: "\ea2b"; }
-.fp-play-outline:before { content: "\ea2c"; }
-.fp-plus-thin:before { content: "\ea2d"; }
-.fp-plus:before { content: "\ea2e"; }
-.fp-pm-block:before { content: "\ea2f"; }
-.fp-remove-outlined:before { content: "\ea30"; }
-.fp-screen-outline:before { content: "\ea31"; }
-.fp-script-outline:before { content: "\ea32"; }
-.fp-slack-notification:before { content: "\ea33"; }
-.fp-slack:before { content: "\ea34"; }
-.fp-slideshow:before { content: "\ea35"; }
-.fp-table:before { content: "\ea36"; }
-.fp-tachometer-alt-average:before { content: "\ea37"; }
-.fp-trash-blue:before { content: "\ea38"; }
-.fp-trash:before { content: "\ea39"; }
-.fp-unlink:before { content: "\ea3a"; }
-.fp-update-outline:before { content: "\ea3b"; }
+.fp-check-circle-outline:before { content: "\ea16"; }
+.fp-close:before { content: "\ea17"; }
+.fp-cloud-download-outline:before { content: "\ea18"; }
+.fp-connector-outline:before { content: "\ea19"; }
+.fp-copy-outline:before { content: "\ea1a"; }
+.fp-copy:before { content: "\ea1b"; }
+.fp-desktop:before { content: "\ea1c"; }
+.fp-edit-outline:before { content: "\ea1d"; }
+.fp-exclamation-triangle:before { content: "\ea1e"; }
+.fp-expand:before { content: "\ea1f"; }
+.fp-eye:before { content: "\ea20"; }
+.fp-fields-icon:before { content: "\ea21"; }
+.fp-flowgenie-outline:before { content: "\ea22"; }
+.fp-folder-outline:before { content: "\ea23"; }
+.fp-fullscreen:before { content: "\ea24"; }
+.fp-github:before { content: "\ea25"; }
+.fp-inbox:before { content: "\ea26"; }
+.fp-layout-icon:before { content: "\ea27"; }
+.fp-link-icon:before { content: "\ea28"; }
+.fp-map:before { content: "\ea29"; }
+.fp-minimize:before { content: "\ea2a"; }
+.fp-mobile:before { content: "\ea2b"; }
+.fp-pdf:before { content: "\ea2c"; }
+.fp-pen-edit:before { content: "\ea2d"; }
+.fp-play-outline:before { content: "\ea2e"; }
+.fp-plus-thin:before { content: "\ea2f"; }
+.fp-plus:before { content: "\ea30"; }
+.fp-pm-block:before { content: "\ea31"; }
+.fp-remove-outlined:before { content: "\ea32"; }
+.fp-screen-outline:before { content: "\ea33"; }
+.fp-script-outline:before { content: "\ea34"; }
+.fp-slack-notification:before { content: "\ea35"; }
+.fp-slack:before { content: "\ea36"; }
+.fp-slideshow:before { content: "\ea37"; }
+.fp-table:before { content: "\ea38"; }
+.fp-tachometer-alt-average:before { content: "\ea39"; }
+.fp-trash-blue:before { content: "\ea3a"; }
+.fp-trash:before { content: "\ea3b"; }
+.fp-unlink:before { content: "\ea3c"; }
+.fp-update-outline:before { content: "\ea3d"; }
}
\ No newline at end of file
diff --git a/resources/fonts/pm-font/processmaker-font.scss b/resources/fonts/pm-font/processmaker-font.scss
index 0eae6ae361..e6e8bbda03 100644
--- a/resources/fonts/pm-font/processmaker-font.scss
+++ b/resources/fonts/pm-font/processmaker-font.scss
@@ -1,10 +1,10 @@
@font-face {font-family: "processmaker-font";
- src: url('processmaker-font.eot?t=1747081178345'); /* IE9*/
- src: url('processmaker-font.eot?t=1747081178345#iefix') format('embedded-opentype'), /* IE6-IE8 */
- url("processmaker-font.woff2?t=1747081178345") format("woff2"),
- url("processmaker-font.woff?t=1747081178345") format("woff"),
- url('processmaker-font.ttf?t=1747081178345') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
- url('processmaker-font.svg?t=1747081178345#processmaker-font') format('svg'); /* iOS 4.1- */
+ src: url('processmaker-font.eot?t=1770239064379'); /* IE9*/
+ src: url('processmaker-font.eot?t=1770239064379#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url("processmaker-font.woff2?t=1770239064379") format("woff2"),
+ url("processmaker-font.woff?t=1770239064379") format("woff"),
+ url('processmaker-font.ttf?t=1770239064379') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('processmaker-font.svg?t=1770239064379#processmaker-font') format('svg'); /* iOS 4.1- */
}
[class^="fp-"], [class*=" fp-"] {
@@ -35,44 +35,46 @@
.fp-bpmn-text-annotation:before { content: "\ea13"; }
.fp-brush-icon:before { content: "\ea14"; }
.fp-check-circle-blue:before { content: "\ea15"; }
-.fp-close:before { content: "\ea16"; }
-.fp-cloud-download-outline:before { content: "\ea17"; }
-.fp-connector-outline:before { content: "\ea18"; }
-.fp-copy-outline:before { content: "\ea19"; }
-.fp-copy:before { content: "\ea1a"; }
-.fp-desktop:before { content: "\ea1b"; }
-.fp-edit-outline:before { content: "\ea1c"; }
-.fp-expand:before { content: "\ea1d"; }
-.fp-eye:before { content: "\ea1e"; }
-.fp-fields-icon:before { content: "\ea1f"; }
-.fp-flowgenie-outline:before { content: "\ea20"; }
-.fp-folder-outline:before { content: "\ea21"; }
-.fp-fullscreen:before { content: "\ea22"; }
-.fp-github:before { content: "\ea23"; }
-.fp-inbox:before { content: "\ea24"; }
-.fp-layout-icon:before { content: "\ea25"; }
-.fp-link-icon:before { content: "\ea26"; }
-.fp-map:before { content: "\ea27"; }
-.fp-minimize:before { content: "\ea28"; }
-.fp-mobile:before { content: "\ea29"; }
-.fp-pdf:before { content: "\ea2a"; }
-.fp-pen-edit:before { content: "\ea2b"; }
-.fp-play-outline:before { content: "\ea2c"; }
-.fp-plus-thin:before { content: "\ea2d"; }
-.fp-plus:before { content: "\ea2e"; }
-.fp-pm-block:before { content: "\ea2f"; }
-.fp-remove-outlined:before { content: "\ea30"; }
-.fp-screen-outline:before { content: "\ea31"; }
-.fp-script-outline:before { content: "\ea32"; }
-.fp-slack-notification:before { content: "\ea33"; }
-.fp-slack:before { content: "\ea34"; }
-.fp-slideshow:before { content: "\ea35"; }
-.fp-table:before { content: "\ea36"; }
-.fp-tachometer-alt-average:before { content: "\ea37"; }
-.fp-trash-blue:before { content: "\ea38"; }
-.fp-trash:before { content: "\ea39"; }
-.fp-unlink:before { content: "\ea3a"; }
-.fp-update-outline:before { content: "\ea3b"; }
+.fp-check-circle-outline:before { content: "\ea16"; }
+.fp-close:before { content: "\ea17"; }
+.fp-cloud-download-outline:before { content: "\ea18"; }
+.fp-connector-outline:before { content: "\ea19"; }
+.fp-copy-outline:before { content: "\ea1a"; }
+.fp-copy:before { content: "\ea1b"; }
+.fp-desktop:before { content: "\ea1c"; }
+.fp-edit-outline:before { content: "\ea1d"; }
+.fp-exclamation-triangle:before { content: "\ea1e"; }
+.fp-expand:before { content: "\ea1f"; }
+.fp-eye:before { content: "\ea20"; }
+.fp-fields-icon:before { content: "\ea21"; }
+.fp-flowgenie-outline:before { content: "\ea22"; }
+.fp-folder-outline:before { content: "\ea23"; }
+.fp-fullscreen:before { content: "\ea24"; }
+.fp-github:before { content: "\ea25"; }
+.fp-inbox:before { content: "\ea26"; }
+.fp-layout-icon:before { content: "\ea27"; }
+.fp-link-icon:before { content: "\ea28"; }
+.fp-map:before { content: "\ea29"; }
+.fp-minimize:before { content: "\ea2a"; }
+.fp-mobile:before { content: "\ea2b"; }
+.fp-pdf:before { content: "\ea2c"; }
+.fp-pen-edit:before { content: "\ea2d"; }
+.fp-play-outline:before { content: "\ea2e"; }
+.fp-plus-thin:before { content: "\ea2f"; }
+.fp-plus:before { content: "\ea30"; }
+.fp-pm-block:before { content: "\ea31"; }
+.fp-remove-outlined:before { content: "\ea32"; }
+.fp-screen-outline:before { content: "\ea33"; }
+.fp-script-outline:before { content: "\ea34"; }
+.fp-slack-notification:before { content: "\ea35"; }
+.fp-slack:before { content: "\ea36"; }
+.fp-slideshow:before { content: "\ea37"; }
+.fp-table:before { content: "\ea38"; }
+.fp-tachometer-alt-average:before { content: "\ea39"; }
+.fp-trash-blue:before { content: "\ea3a"; }
+.fp-trash:before { content: "\ea3b"; }
+.fp-unlink:before { content: "\ea3c"; }
+.fp-update-outline:before { content: "\ea3d"; }
$fp-add-outlined: "\ea01";
$fp-arrow-left: "\ea02";
@@ -95,42 +97,44 @@ $fp-bpmn-task: "\ea12";
$fp-bpmn-text-annotation: "\ea13";
$fp-brush-icon: "\ea14";
$fp-check-circle-blue: "\ea15";
-$fp-close: "\ea16";
-$fp-cloud-download-outline: "\ea17";
-$fp-connector-outline: "\ea18";
-$fp-copy-outline: "\ea19";
-$fp-copy: "\ea1a";
-$fp-desktop: "\ea1b";
-$fp-edit-outline: "\ea1c";
-$fp-expand: "\ea1d";
-$fp-eye: "\ea1e";
-$fp-fields-icon: "\ea1f";
-$fp-flowgenie-outline: "\ea20";
-$fp-folder-outline: "\ea21";
-$fp-fullscreen: "\ea22";
-$fp-github: "\ea23";
-$fp-inbox: "\ea24";
-$fp-layout-icon: "\ea25";
-$fp-link-icon: "\ea26";
-$fp-map: "\ea27";
-$fp-minimize: "\ea28";
-$fp-mobile: "\ea29";
-$fp-pdf: "\ea2a";
-$fp-pen-edit: "\ea2b";
-$fp-play-outline: "\ea2c";
-$fp-plus-thin: "\ea2d";
-$fp-plus: "\ea2e";
-$fp-pm-block: "\ea2f";
-$fp-remove-outlined: "\ea30";
-$fp-screen-outline: "\ea31";
-$fp-script-outline: "\ea32";
-$fp-slack-notification: "\ea33";
-$fp-slack: "\ea34";
-$fp-slideshow: "\ea35";
-$fp-table: "\ea36";
-$fp-tachometer-alt-average: "\ea37";
-$fp-trash-blue: "\ea38";
-$fp-trash: "\ea39";
-$fp-unlink: "\ea3a";
-$fp-update-outline: "\ea3b";
+$fp-check-circle-outline: "\ea16";
+$fp-close: "\ea17";
+$fp-cloud-download-outline: "\ea18";
+$fp-connector-outline: "\ea19";
+$fp-copy-outline: "\ea1a";
+$fp-copy: "\ea1b";
+$fp-desktop: "\ea1c";
+$fp-edit-outline: "\ea1d";
+$fp-exclamation-triangle: "\ea1e";
+$fp-expand: "\ea1f";
+$fp-eye: "\ea20";
+$fp-fields-icon: "\ea21";
+$fp-flowgenie-outline: "\ea22";
+$fp-folder-outline: "\ea23";
+$fp-fullscreen: "\ea24";
+$fp-github: "\ea25";
+$fp-inbox: "\ea26";
+$fp-layout-icon: "\ea27";
+$fp-link-icon: "\ea28";
+$fp-map: "\ea29";
+$fp-minimize: "\ea2a";
+$fp-mobile: "\ea2b";
+$fp-pdf: "\ea2c";
+$fp-pen-edit: "\ea2d";
+$fp-play-outline: "\ea2e";
+$fp-plus-thin: "\ea2f";
+$fp-plus: "\ea30";
+$fp-pm-block: "\ea31";
+$fp-remove-outlined: "\ea32";
+$fp-screen-outline: "\ea33";
+$fp-script-outline: "\ea34";
+$fp-slack-notification: "\ea35";
+$fp-slack: "\ea36";
+$fp-slideshow: "\ea37";
+$fp-table: "\ea38";
+$fp-tachometer-alt-average: "\ea39";
+$fp-trash-blue: "\ea3a";
+$fp-trash: "\ea3b";
+$fp-unlink: "\ea3c";
+$fp-update-outline: "\ea3d";
diff --git a/resources/fonts/pm-font/processmaker-font.styl b/resources/fonts/pm-font/processmaker-font.styl
index 889600b9db..9d190be82b 100644
--- a/resources/fonts/pm-font/processmaker-font.styl
+++ b/resources/fonts/pm-font/processmaker-font.styl
@@ -1,10 +1,10 @@
@font-face {font-family: "processmaker-font";
- src: url('processmaker-font.eot?t=1747081178345'); /* IE9*/
- src: url('processmaker-font.eot?t=1747081178345#iefix') format('embedded-opentype'), /* IE6-IE8 */
- url("processmaker-font.woff2?t=1747081178345") format("woff2"),
- url("processmaker-font.woff?t=1747081178345") format("woff"),
- url('processmaker-font.ttf?t=1747081178345') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
- url('processmaker-font.svg?t=1747081178345#processmaker-font') format('svg'); /* iOS 4.1- */
+ src: url('processmaker-font.eot?t=1770239064379'); /* IE9*/
+ src: url('processmaker-font.eot?t=1770239064379#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url("processmaker-font.woff2?t=1770239064379") format("woff2"),
+ url("processmaker-font.woff?t=1770239064379") format("woff"),
+ url('processmaker-font.ttf?t=1770239064379') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('processmaker-font.svg?t=1770239064379#processmaker-font') format('svg'); /* iOS 4.1- */
}
[class^="fp-"], [class*=" fp-"] {
@@ -35,41 +35,43 @@
.fp-bpmn-text-annotation:before { content: "\ea13"; }
.fp-brush-icon:before { content: "\ea14"; }
.fp-check-circle-blue:before { content: "\ea15"; }
-.fp-close:before { content: "\ea16"; }
-.fp-cloud-download-outline:before { content: "\ea17"; }
-.fp-connector-outline:before { content: "\ea18"; }
-.fp-copy-outline:before { content: "\ea19"; }
-.fp-copy:before { content: "\ea1a"; }
-.fp-desktop:before { content: "\ea1b"; }
-.fp-edit-outline:before { content: "\ea1c"; }
-.fp-expand:before { content: "\ea1d"; }
-.fp-eye:before { content: "\ea1e"; }
-.fp-fields-icon:before { content: "\ea1f"; }
-.fp-flowgenie-outline:before { content: "\ea20"; }
-.fp-folder-outline:before { content: "\ea21"; }
-.fp-fullscreen:before { content: "\ea22"; }
-.fp-github:before { content: "\ea23"; }
-.fp-inbox:before { content: "\ea24"; }
-.fp-layout-icon:before { content: "\ea25"; }
-.fp-link-icon:before { content: "\ea26"; }
-.fp-map:before { content: "\ea27"; }
-.fp-minimize:before { content: "\ea28"; }
-.fp-mobile:before { content: "\ea29"; }
-.fp-pdf:before { content: "\ea2a"; }
-.fp-pen-edit:before { content: "\ea2b"; }
-.fp-play-outline:before { content: "\ea2c"; }
-.fp-plus-thin:before { content: "\ea2d"; }
-.fp-plus:before { content: "\ea2e"; }
-.fp-pm-block:before { content: "\ea2f"; }
-.fp-remove-outlined:before { content: "\ea30"; }
-.fp-screen-outline:before { content: "\ea31"; }
-.fp-script-outline:before { content: "\ea32"; }
-.fp-slack-notification:before { content: "\ea33"; }
-.fp-slack:before { content: "\ea34"; }
-.fp-slideshow:before { content: "\ea35"; }
-.fp-table:before { content: "\ea36"; }
-.fp-tachometer-alt-average:before { content: "\ea37"; }
-.fp-trash-blue:before { content: "\ea38"; }
-.fp-trash:before { content: "\ea39"; }
-.fp-unlink:before { content: "\ea3a"; }
-.fp-update-outline:before { content: "\ea3b"; }
+.fp-check-circle-outline:before { content: "\ea16"; }
+.fp-close:before { content: "\ea17"; }
+.fp-cloud-download-outline:before { content: "\ea18"; }
+.fp-connector-outline:before { content: "\ea19"; }
+.fp-copy-outline:before { content: "\ea1a"; }
+.fp-copy:before { content: "\ea1b"; }
+.fp-desktop:before { content: "\ea1c"; }
+.fp-edit-outline:before { content: "\ea1d"; }
+.fp-exclamation-triangle:before { content: "\ea1e"; }
+.fp-expand:before { content: "\ea1f"; }
+.fp-eye:before { content: "\ea20"; }
+.fp-fields-icon:before { content: "\ea21"; }
+.fp-flowgenie-outline:before { content: "\ea22"; }
+.fp-folder-outline:before { content: "\ea23"; }
+.fp-fullscreen:before { content: "\ea24"; }
+.fp-github:before { content: "\ea25"; }
+.fp-inbox:before { content: "\ea26"; }
+.fp-layout-icon:before { content: "\ea27"; }
+.fp-link-icon:before { content: "\ea28"; }
+.fp-map:before { content: "\ea29"; }
+.fp-minimize:before { content: "\ea2a"; }
+.fp-mobile:before { content: "\ea2b"; }
+.fp-pdf:before { content: "\ea2c"; }
+.fp-pen-edit:before { content: "\ea2d"; }
+.fp-play-outline:before { content: "\ea2e"; }
+.fp-plus-thin:before { content: "\ea2f"; }
+.fp-plus:before { content: "\ea30"; }
+.fp-pm-block:before { content: "\ea31"; }
+.fp-remove-outlined:before { content: "\ea32"; }
+.fp-screen-outline:before { content: "\ea33"; }
+.fp-script-outline:before { content: "\ea34"; }
+.fp-slack-notification:before { content: "\ea35"; }
+.fp-slack:before { content: "\ea36"; }
+.fp-slideshow:before { content: "\ea37"; }
+.fp-table:before { content: "\ea38"; }
+.fp-tachometer-alt-average:before { content: "\ea39"; }
+.fp-trash-blue:before { content: "\ea3a"; }
+.fp-trash:before { content: "\ea3b"; }
+.fp-unlink:before { content: "\ea3c"; }
+.fp-update-outline:before { content: "\ea3d"; }
diff --git a/resources/fonts/pm-font/processmaker-font.svg b/resources/fonts/pm-font/processmaker-font.svg
index ed7d5af29f..cb0f0ad5f9 100644
--- a/resources/fonts/pm-font/processmaker-font.svg
+++ b/resources/fonts/pm-font/processmaker-font.svg
@@ -70,119 +70,125 @@
{{ __('Each case in this process is retained from the moment it is created for the period defined in this section.')}}
+{{ __('After this period expires, the case is automatically and ') }}{{ __('permanently deleted') }}{{ __(', regardless of its status. This deletion includes all files and all data associated with the case and cannot be undone.') }}
+{{ __('Retention periods over one year must be handled by Technical Support. Please contact Technical Support for assistance.')}}
++ {{ __('If you reduce the current retention period, cases older than the new period will be ') }}{{ __('permanently deleted') }}{{ __('. Only cases that meet the new retention period will be kept.') }} +
+ +{{ __('Cases older than the retention period will be automatically deleted during the previously set retention time.') }}
+ + +