diff --git a/ProcessMaker/Http/Controllers/CasesController.php b/ProcessMaker/Http/Controllers/CasesController.php index 942c87ac95..88d48593ad 100644 --- a/ProcessMaker/Http/Controllers/CasesController.php +++ b/ProcessMaker/Http/Controllers/CasesController.php @@ -3,16 +3,21 @@ namespace ProcessMaker\Http\Controllers; use Illuminate\Support\Facades\Auth; +use ProcessMaker\Events\ModelerStarting; use ProcessMaker\Events\ScreenBuilderStarting; use ProcessMaker\Http\Controllers\Controller; +use ProcessMaker\Http\Controllers\Process\ModelerController; +use ProcessMaker\Managers\ModelerManager; use ProcessMaker\Managers\ScreenBuilderManager; use ProcessMaker\Models\ProcessRequest; use ProcessMaker\Models\Screen; use ProcessMaker\Package\PackageComments\PackageServiceProvider; use ProcessMaker\ProcessTranslations\ScreenTranslation; +use ProcessMaker\Traits\ProcessMapTrait; class CasesController extends Controller { + use ProcessMapTrait; /** * Get the list of requests. * @@ -38,6 +43,10 @@ public function show($case_number) // Load event ScreenBuilderStarting $manager = app(ScreenBuilderManager::class); event(new ScreenBuilderStarting($manager, 'FORM')); + // Load event ModelerStarting + $managerModeler = app(ModelerManager::class); + event(new ModelerStarting($managerModeler)); + // Get all the request related to this case number $allRequests = ProcessRequest::where('case_number', $case_number)->get(); $parentRequest = null; @@ -76,6 +85,14 @@ public function show($case_number) // Get the summary screen tranlations $this->summaryScreenTranslation($request); + // Load the process map + $inflightData = $this->loadProcessMap($request); + $bpmn = $inflightData['bpmn']; + + // Get all PM-Blocks + $modelerController = new ModelerController(); + $pmBlockList = $modelerController->getPmBlockList(); + // Return the view return view('cases.edit', compact( 'request', @@ -85,7 +102,11 @@ public function show($case_number) 'canViewComments', 'canPrintScreens', 'isProcessManager', - 'manager' + 'manager', + 'managerModeler', + 'bpmn', + 'inflightData', + 'pmBlockList' )); } diff --git a/ProcessMaker/Http/Controllers/RequestController.php b/ProcessMaker/Http/Controllers/RequestController.php index 91b9934bf0..0d55426666 100644 --- a/ProcessMaker/Http/Controllers/RequestController.php +++ b/ProcessMaker/Http/Controllers/RequestController.php @@ -28,6 +28,7 @@ use ProcessMaker\ProcessTranslations\ScreenTranslation; use ProcessMaker\RetryProcessRequest; use ProcessMaker\Traits\HasControllerAddons; +use ProcessMaker\Traits\ProcessMapTrait; use ProcessMaker\Traits\SearchAutocompleteTrait; use Spatie\MediaLibrary\MediaCollections\Models\Media; @@ -35,6 +36,7 @@ class RequestController extends Controller { use SearchAutocompleteTrait; use HasControllerAddons; + use ProcessMapTrait; /** * Get the list of requests. @@ -182,6 +184,10 @@ public function show(ProcessRequest $request, Media $mediaItems) } $this->summaryScreenTranslation($request); + //Load the process map + $inflightData = $this->loadProcessMap($request); + $bpmn = $inflightData['bpmn']; + if (isset($_SERVER['HTTP_USER_AGENT']) && MobileHelper::isMobile($_SERVER['HTTP_USER_AGENT'])) { return view('requests.showMobile', compact( 'request', @@ -217,6 +223,8 @@ public function show(ProcessRequest $request, Media $mediaItems) 'eligibleRollbackTask', 'errorTask', 'userConfiguration', + 'bpmn', + 'inflightData', )); } diff --git a/ProcessMaker/Traits/ProcessMapTrait.php b/ProcessMaker/Traits/ProcessMapTrait.php index baac236a67..8aed611f3c 100644 --- a/ProcessMaker/Traits/ProcessMapTrait.php +++ b/ProcessMaker/Traits/ProcessMapTrait.php @@ -3,6 +3,7 @@ namespace ProcessMaker\Traits; use Illuminate\Support\Collection; +use ProcessMaker\Bpmn\Process; use ProcessMaker\Models\ProcessRequest; use SimpleXMLElement; @@ -17,6 +18,9 @@ private function loadAndPrepareXML(string $bpmn): SimpleXMLElement $xml = simplexml_load_string($bpmn); $namespaces = $xml->getNamespaces(true); + // Register the BPMN namespace explicitly + $xml->registerXPathNamespace('bpmn', 'http://www.omg.org/spec/BPMN/20100524/MODEL'); + foreach ($namespaces as $prefix => $ns) { $xml->registerXPathNamespace($prefix, $ns); } @@ -108,4 +112,45 @@ private function getCountFlag(int $sourceCount, int $targetCount, string $source return $maxToken->status === 'ACTIVE' && $sourceCount === $targetCount; } + + private function loadProcessMap(ProcessRequest $request): array + { + $processRequest = ProcessRequest::find($request->id); + $bpmn = $request->process->bpmn; + $filteredCompletedNodes = []; + $requestInProgressNodes = []; + $requestIdleNodes = []; + + if ($processRequest) { + $requestCompletedNodes = $processRequest->tokens() + ->whereIn('status', ['CLOSED', 'COMPLETED', 'TRIGGERED']) + ->pluck('element_id'); + $requestInProgressNodes = $processRequest->tokens() + ->whereIn('status', ['ACTIVE', 'INCOMING']) + ->pluck('element_id'); + + // Remove any node that is 'ACTIVE' from the completed list. + $filteredCompletedNodes = $requestCompletedNodes->diff($requestInProgressNodes)->values(); + + // Obtain In-Progress nodes that were completed before + $matchingNodes = $requestInProgressNodes->intersect($requestCompletedNodes); + + // Get idle nodes. + $xml = $this->loadAndPrepareXML($bpmn); + $nodeIds = $this->getNodeIds($xml); + $requestIdleNodes = $nodeIds->diff($filteredCompletedNodes)->diff($requestInProgressNodes)->values(); + + // Add completed sequence flow to the list of completed nodes. + $sequenceFlowNodes = $this->getCompletedSequenceFlow($xml, $filteredCompletedNodes->implode(' '), $requestInProgressNodes->implode(' '), $matchingNodes->implode(' ')); + $filteredCompletedNodes = $filteredCompletedNodes->merge($sequenceFlowNodes); + } + + return [ + 'bpmn' => $bpmn, + 'requestCompletedNodes' => $filteredCompletedNodes, + 'requestInProgressNodes' => $requestInProgressNodes, + 'requestIdleNodes' => $requestIdleNodes, + 'requestId' => $request->id, + ]; + } } diff --git a/resources/js/requests/show.js b/resources/js/requests/show.js index 88b7dd082b..da273326e8 100644 --- a/resources/js/requests/show.js +++ b/resources/js/requests/show.js @@ -16,6 +16,7 @@ import FilesMobile from "./components/FilesMobile.vue"; import RequestHeaderMobile from "./components/RequestHeaderMobile.vue"; import FilterMobile from "../Mobile/FilterMobile.vue"; import FilterMixin from "../Mobile/FilterMixin"; +import NewOverview from "../../jscomposition/cases/casesDetail/components/NewOverview.vue"; Vue.component("DataSummary", DataSummary); Vue.component("RequestDetail", RequestDetail); @@ -31,6 +32,7 @@ Vue.component("SummaryMobile", SummaryMobile); Vue.component("FilesMobile", FilesMobile); Vue.component("RequestHeaderMobile", RequestHeaderMobile); Vue.component("FilterMobile", FilterMobile); +Vue.component("NewOverview", NewOverview); Vue.mixin(FilterMixin); Vue.use("vue-form-renderer", VueFormRenderer); diff --git a/resources/jscomposition/cases/casesDetail/components/CaseDetail.vue b/resources/jscomposition/cases/casesDetail/components/CaseDetail.vue index ca952c0614..ab03e9e023 100644 --- a/resources/jscomposition/cases/casesDetail/components/CaseDetail.vue +++ b/resources/jscomposition/cases/casesDetail/components/CaseDetail.vue @@ -13,7 +13,7 @@ import RequestTable from "./RequestTable.vue"; import TabHistory from "./TabHistory.vue"; import CompletedForms from "./CompletedForms.vue"; import TabFiles from "./TabFiles.vue"; -import Overview from "./Overview.vue"; +import Overview from "./NewOverview.vue"; import TabSummary from "./TabSummary.vue"; import ErrorsTab from "./ErrorsTab.vue"; import { getRequestCount, getRequestStatus, isErrors } from "../variables/index"; @@ -67,7 +67,7 @@ const tabs = [ name: translate.t("Summary"), href: "#summary", current: "summary", - show: getRequestStatus() !== 'ERROR', + show: getRequestStatus() !== "ERROR", content: TabSummary, }, { diff --git a/resources/jscomposition/cases/casesDetail/components/MapLegend.vue b/resources/jscomposition/cases/casesDetail/components/MapLegend.vue new file mode 100644 index 0000000000..5414b03833 --- /dev/null +++ b/resources/jscomposition/cases/casesDetail/components/MapLegend.vue @@ -0,0 +1,44 @@ + + + diff --git a/resources/jscomposition/cases/casesDetail/components/NewOverview.vue b/resources/jscomposition/cases/casesDetail/components/NewOverview.vue new file mode 100644 index 0000000000..f6fafbde87 --- /dev/null +++ b/resources/jscomposition/cases/casesDetail/components/NewOverview.vue @@ -0,0 +1,145 @@ + + + diff --git a/resources/jscomposition/cases/casesDetail/variables/index.js b/resources/jscomposition/cases/casesDetail/variables/index.js index 00d1a3d564..ad960a1ffb 100644 --- a/resources/jscomposition/cases/casesDetail/variables/index.js +++ b/resources/jscomposition/cases/casesDetail/variables/index.js @@ -21,3 +21,7 @@ export const getRequestCount = () => requestCount; export const getErrors = () => errorLogs; export const isErrors = () => request.status === "ERROR"; + +export const getInflightData = () => inflightData; + +export const getXML = () => inflightData.bpmn; diff --git a/resources/views/cases/edit.blade.php b/resources/views/cases/edit.blade.php index 9832c8ea9d..d249ca6ab5 100644 --- a/resources/views/cases/edit.blade.php +++ b/resources/views/cases/edit.blade.php @@ -118,6 +118,16 @@ class="tw-grow tw-overflow-hidden" @endsection @section('js') + + @if (hasPackage('package-files')) @@ -141,6 +173,11 @@ class="tw-grow tw-overflow-hidden" @foreach($manager->getScripts() as $script) @endforeach + @foreach($managerModeler->getScripts() as $script) + @if (!str_contains($script, 'slideshow')) + + @endif + @endforeach @endsection @section('css') diff --git a/resources/views/requests/show.blade.php b/resources/views/requests/show.blade.php index 3df5f3402d..ebb6174cd0 100644 --- a/resources/views/requests/show.blade.php +++ b/resources/views/requests/show.blade.php @@ -235,32 +235,9 @@ class="tab-pane card card-body border-top-0 p-3">
-
+
-

- {{ __(':name In-Flight Map', ['name' => $request->process->name]) }} -

-
-
-
-
- - -

- {{ __('Content not available. Check settings or try a different device.') }} -

-
-
+
@@ -484,7 +461,16 @@ class="btn btn-outline-info btn-block" @foreach ($manager->getScripts() as $script) @endforeach - + + @if (hasPackage('package-files')) @@ -529,7 +515,7 @@ class="btn btn-outline-info btn-block" packages: [], processId: @json($request->process->id), canViewComments: @json($canViewComments), - isObjectLoading: false, + isObjectLoading: true, showTree: false, showInfo: true, showMenu: true, @@ -900,6 +886,23 @@ classStatusCard() { }, }); + @endsection @section('css') @@ -962,5 +965,11 @@ classStatusCard() { .menu-tab-content { margin-left: -16px; } + .main-paper { + position: static !important; + } + .card-height { + height: 50vh; + } @endsection