@valtimo/process-management 13.42.0 → 13.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/valtimo-process-management.mjs +1411 -101
- package/fesm2022/valtimo-process-management.mjs.map +1 -1
- package/lib/components/process-management-builder/panel/expression-autocomplete.d.ts +37 -0
- package/lib/components/process-management-builder/panel/expression-autocomplete.d.ts.map +1 -0
- package/lib/components/process-management-builder/panel/index.d.ts +1 -0
- package/lib/components/process-management-builder/panel/index.d.ts.map +1 -1
- package/lib/components/process-management-builder/panel/valtimo-properties-provider.d.ts +2 -0
- package/lib/components/process-management-builder/panel/valtimo-properties-provider.d.ts.map +1 -1
- package/lib/components/process-management-builder/process-management-builder.component.d.ts +34 -3
- package/lib/components/process-management-builder/process-management-builder.component.d.ts.map +1 -1
- package/lib/components/process-management-list/process-management-list.component.d.ts +1 -0
- package/lib/components/process-management-list/process-management-list.component.d.ts.map +1 -1
- package/lib/components/process-management-upload/process-management-upload.component.d.ts +38 -1
- package/lib/components/process-management-upload/process-management-upload.component.d.ts.map +1 -1
- package/lib/constants/process-management.test-ids.d.ts +2 -0
- package/lib/constants/process-management.test-ids.d.ts.map +1 -1
- package/lib/models/index.d.ts +2 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/process-bean.model.d.ts +19 -0
- package/lib/models/process-bean.model.d.ts.map +1 -0
- package/lib/models/process-definition-import.model.d.ts +37 -0
- package/lib/models/process-definition-import.model.d.ts.map +1 -0
- package/lib/models/process-management.model.d.ts +14 -1
- package/lib/models/process-management.model.d.ts.map +1 -1
- package/lib/models/process.model.d.ts +2 -0
- package/lib/models/process.model.d.ts.map +1 -1
- package/lib/models/window.model.d.ts +2 -0
- package/lib/models/window.model.d.ts.map +1 -1
- package/lib/services/index.d.ts +1 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/process-bean.service.d.ts +15 -0
- package/lib/services/process-bean.service.d.ts.map +1 -0
- package/lib/services/process-management-editor.service.d.ts +12 -0
- package/lib/services/process-management-editor.service.d.ts.map +1 -1
- package/lib/services/process-management.service.d.ts +5 -2
- package/lib/services/process-management.service.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -7,16 +7,15 @@ import { ReactiveFormsModule, Validators, FormsModule } from '@angular/forms';
|
|
|
7
7
|
import * as i9 from '@ngx-translate/core';
|
|
8
8
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
|
9
9
|
import * as i1$1 from '@valtimo/components';
|
|
10
|
-
import { FitPageDirective, RenderInPageHeaderDirective,
|
|
10
|
+
import { FitPageDirective, RenderInPageHeaderDirective, ConfirmationModalModule, OverflowMenuModule, ViewType, CarbonListModule, CARBON_CONSTANTS, RenderInBodyComponent, ValtimoCdsModalDirective, WidgetModule } from '@valtimo/components';
|
|
11
11
|
import * as i5 from '@valtimo/process-link';
|
|
12
12
|
import { ProcessLinkModule, ProcessLinkStateService, ProcessLinkStepService, ProcessLinkButtonService } from '@valtimo/process-link';
|
|
13
13
|
import * as i2$2 from 'carbon-components-angular';
|
|
14
14
|
import { LoadingModule, DropdownModule, SelectModule, ButtonModule, IconModule, TagModule, ToggleModule, TooltipModule, FileUploaderModule, ModalModule, LayerModule, NotificationModule, RadioModule } from 'carbon-components-angular';
|
|
15
15
|
import * as i1 from '@angular/common/http';
|
|
16
|
-
import { HttpErrorResponse } from '@angular/common/http';
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import { BaseApiService, getCaseManagementRouteParams, getBuildingBlockManagementRouteParams, ROLE_ADMIN } from '@valtimo/shared';
|
|
16
|
+
import { HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
|
17
|
+
import * as i2 from '@valtimo/shared';
|
|
18
|
+
import { BaseApiService, InterceptorSkipHeader, InterceptorSkip, getCaseManagementRouteParams, getBuildingBlockManagementRouteParams, ROLE_ADMIN } from '@valtimo/shared';
|
|
20
19
|
import { useService, BpmnPropertiesPanelModule, BpmnPropertiesProviderModule, CamundaPlatformPropertiesProviderModule } from 'bpmn-js-properties-panel';
|
|
21
20
|
import Modeler from 'bpmn-js/lib/Modeler';
|
|
22
21
|
import camundaPlatformBehaviors from 'camunda-bpmn-js-behaviors/lib/camunda-platform';
|
|
@@ -24,15 +23,17 @@ import CamundaBpmnModdle from 'camunda-bpmn-moddle/resources/camunda.json';
|
|
|
24
23
|
import { isEqual } from 'lodash';
|
|
25
24
|
import { filter, BehaviorSubject, Subject, Subscription, combineLatest, switchMap, of, tap, map as map$1, startWith, from, take, merge } from 'rxjs';
|
|
26
25
|
import { distinctUntilChanged, map, filter as filter$1 } from 'rxjs/operators';
|
|
27
|
-
import * as i2 from '@valtimo/form';
|
|
26
|
+
import * as i2$1 from '@valtimo/form';
|
|
28
27
|
import { toObservable } from '@angular/core/rxjs-interop';
|
|
29
28
|
import { is } from 'bpmn-js/lib/util/ModelUtil';
|
|
30
29
|
import { html } from 'htm/preact';
|
|
30
|
+
import { View16, ViewOff16, Upload16 } from '@carbon/icons';
|
|
31
31
|
import * as i3 from 'ngx-logger';
|
|
32
32
|
import * as i7 from '@valtimo/process';
|
|
33
33
|
import * as i8 from '@angular/router';
|
|
34
34
|
import { RouterModule } from '@angular/router';
|
|
35
35
|
import * as i10 from '@valtimo/plugin';
|
|
36
|
+
import { PluginConfigurationMappingComponent } from '@valtimo/plugin';
|
|
36
37
|
import { AuthGuardService } from '@valtimo/security';
|
|
37
38
|
|
|
38
39
|
/*
|
|
@@ -90,6 +91,8 @@ const PROCESS_MANAGEMENT_BUILDER_TEST_IDS = {
|
|
|
90
91
|
startsCaseToggle: 'processManagementBuilderStartsCaseToggle',
|
|
91
92
|
startableByUserToggle: 'processManagementBuilderStartableByUserToggle',
|
|
92
93
|
deployButton: 'processManagementBuilderDeployButton',
|
|
94
|
+
exportOption: 'processManagementBuilderExportOption',
|
|
95
|
+
markersVisibilityToggle: 'processManagementBuilderMarkersVisibilityToggle',
|
|
93
96
|
};
|
|
94
97
|
|
|
95
98
|
/*
|
|
@@ -108,8 +111,30 @@ const PROCESS_MANAGEMENT_BUILDER_TEST_IDS = {
|
|
|
108
111
|
* limitations under the License.
|
|
109
112
|
*/
|
|
110
113
|
|
|
114
|
+
class ProcessBeanService extends BaseApiService {
|
|
115
|
+
constructor(httpClient, configService) {
|
|
116
|
+
super(httpClient, configService);
|
|
117
|
+
this.httpClient = httpClient;
|
|
118
|
+
this.configService = configService;
|
|
119
|
+
}
|
|
120
|
+
getProcessBeans() {
|
|
121
|
+
return this.httpClient.get(this.getApiUrl('/management/v1/process-bean'));
|
|
122
|
+
}
|
|
123
|
+
getProcessBean(beanName) {
|
|
124
|
+
return this.httpClient.get(this.getApiUrl(`/management/v1/process-bean/${beanName}`));
|
|
125
|
+
}
|
|
126
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessBeanService, deps: [{ token: i1.HttpClient }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
127
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessBeanService, providedIn: 'root' }); }
|
|
128
|
+
}
|
|
129
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessBeanService, decorators: [{
|
|
130
|
+
type: Injectable,
|
|
131
|
+
args: [{
|
|
132
|
+
providedIn: 'root',
|
|
133
|
+
}]
|
|
134
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ConfigService }] });
|
|
135
|
+
|
|
111
136
|
/*
|
|
112
|
-
* Copyright 2015-
|
|
137
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
113
138
|
*
|
|
114
139
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
115
140
|
* you may not use this file except in compliance with the License.
|
|
@@ -154,6 +179,33 @@ class ProcessManagementEditorService {
|
|
|
154
179
|
setValidationErrors(errors) {
|
|
155
180
|
this._validationErrors$.next(errors);
|
|
156
181
|
}
|
|
182
|
+
get dismissedAutofills() {
|
|
183
|
+
return this._dismissedAutofills$.getValue();
|
|
184
|
+
}
|
|
185
|
+
get autofillDismissed$() {
|
|
186
|
+
return this._autofillDismissed$.asObservable();
|
|
187
|
+
}
|
|
188
|
+
dismissAutofill(activityId) {
|
|
189
|
+
const current = this._dismissedAutofills$.getValue();
|
|
190
|
+
current.add(activityId);
|
|
191
|
+
this._dismissedAutofills$.next(new Set(current));
|
|
192
|
+
this._autofillDismissed$.next(activityId);
|
|
193
|
+
}
|
|
194
|
+
clearDismissedAutofills() {
|
|
195
|
+
this._dismissedAutofills$.next(new Set());
|
|
196
|
+
}
|
|
197
|
+
isAutofillDismissed(activityId) {
|
|
198
|
+
return this._dismissedAutofills$.getValue().has(activityId);
|
|
199
|
+
}
|
|
200
|
+
get autofilledElements() {
|
|
201
|
+
return this._autofilledElements$.getValue();
|
|
202
|
+
}
|
|
203
|
+
setAutofilledElements(elements) {
|
|
204
|
+
this._autofilledElements$.next(elements);
|
|
205
|
+
}
|
|
206
|
+
getAutofillForActivity(activityId) {
|
|
207
|
+
return this._autofilledElements$.getValue().find(e => e.activityId === activityId);
|
|
208
|
+
}
|
|
157
209
|
constructor(processLinkService, formService) {
|
|
158
210
|
this.processLinkService = processLinkService;
|
|
159
211
|
this.formService = formService;
|
|
@@ -165,6 +217,9 @@ class ProcessManagementEditorService {
|
|
|
165
217
|
this._formDefinitionOptions$ = new BehaviorSubject([]);
|
|
166
218
|
this._validationErrors$ = new BehaviorSubject([]);
|
|
167
219
|
this.validationErrors$ = this._validationErrors$.asObservable();
|
|
220
|
+
this._dismissedAutofills$ = new BehaviorSubject(new Set());
|
|
221
|
+
this._autofillDismissed$ = new Subject();
|
|
222
|
+
this._autofilledElements$ = new BehaviorSubject([]);
|
|
168
223
|
this._updatingBpmnView = false;
|
|
169
224
|
this._activityIdBusinessIdMap = {};
|
|
170
225
|
this._subscriptions = new Subscription();
|
|
@@ -275,12 +330,12 @@ class ProcessManagementEditorService {
|
|
|
275
330
|
}
|
|
276
331
|
}));
|
|
277
332
|
}
|
|
278
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementEditorService, deps: [{ token: i5.ProcessLinkService }, { token: i2.FormService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
333
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementEditorService, deps: [{ token: i5.ProcessLinkService }, { token: i2$1.FormService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
279
334
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementEditorService }); }
|
|
280
335
|
}
|
|
281
336
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementEditorService, decorators: [{
|
|
282
337
|
type: Injectable
|
|
283
|
-
}], ctorParameters: () => [{ type: i5.ProcessLinkService }, { type: i2.FormService }] });
|
|
338
|
+
}], ctorParameters: () => [{ type: i5.ProcessLinkService }, { type: i2$1.FormService }] });
|
|
284
339
|
|
|
285
340
|
/*
|
|
286
341
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
@@ -326,7 +381,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
326
381
|
}] });
|
|
327
382
|
|
|
328
383
|
/*
|
|
329
|
-
* Copyright 2015-
|
|
384
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
330
385
|
*
|
|
331
386
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
332
387
|
* you may not use this file except in compliance with the License.
|
|
@@ -358,7 +413,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
358
413
|
*/
|
|
359
414
|
|
|
360
415
|
/*
|
|
361
|
-
* Copyright 2015-
|
|
416
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
417
|
+
*
|
|
418
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
419
|
+
* you may not use this file except in compliance with the License.
|
|
420
|
+
* You may obtain a copy of the License at
|
|
421
|
+
*
|
|
422
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
423
|
+
*
|
|
424
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
425
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
426
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
427
|
+
* See the License for the specific language governing permissions and
|
|
428
|
+
* limitations under the License.
|
|
429
|
+
*/
|
|
430
|
+
|
|
431
|
+
/*
|
|
432
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
433
|
+
*
|
|
434
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
435
|
+
* you may not use this file except in compliance with the License.
|
|
436
|
+
* You may obtain a copy of the License at
|
|
437
|
+
*
|
|
438
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
439
|
+
*
|
|
440
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
441
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
442
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
443
|
+
* See the License for the specific language governing permissions and
|
|
444
|
+
* limitations under the License.
|
|
445
|
+
*/
|
|
446
|
+
|
|
447
|
+
/*
|
|
448
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
362
449
|
*
|
|
363
450
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
364
451
|
* you may not use this file except in compliance with the License.
|
|
@@ -378,7 +465,7 @@ const PROCESS_MANAGEMENT_ENDPOINTS = {
|
|
|
378
465
|
};
|
|
379
466
|
|
|
380
467
|
/*
|
|
381
|
-
* Copyright 2015-
|
|
468
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
382
469
|
*
|
|
383
470
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
384
471
|
* you may not use this file except in compliance with the License.
|
|
@@ -409,6 +496,21 @@ const PROCESS_MANAGEMENT_ENDPOINTS = {
|
|
|
409
496
|
* limitations under the License.
|
|
410
497
|
*/
|
|
411
498
|
|
|
499
|
+
/*
|
|
500
|
+
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
501
|
+
*
|
|
502
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
503
|
+
* you may not use this file except in compliance with the License.
|
|
504
|
+
* You may obtain a copy of the License at
|
|
505
|
+
*
|
|
506
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
507
|
+
*
|
|
508
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
509
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
510
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
511
|
+
* See the License for the specific language governing permissions and
|
|
512
|
+
* limitations under the License.
|
|
513
|
+
*/
|
|
412
514
|
class ProcessManagementService extends BaseApiService {
|
|
413
515
|
get caseDefinitionKey() {
|
|
414
516
|
return this._definitionKey$.getValue() ?? '';
|
|
@@ -475,6 +577,18 @@ class ProcessManagementService extends BaseApiService {
|
|
|
475
577
|
updateProcessDefinitionCaseDefinitionProperties(caseDefinitionKey, caseDefinitionVersionTag, processDefinitionId, body) {
|
|
476
578
|
return this.httpClient.put(this.getApiUrl(`/management/v1/case-definition/${caseDefinitionKey}/version/${caseDefinitionVersionTag}/process/${processDefinitionId}/properties`), body);
|
|
477
579
|
}
|
|
580
|
+
exportProcessDefinition(processDefinitionId) {
|
|
581
|
+
return this.httpClient.get(this.getApiUrl(`/management/v1/process-definition/${processDefinitionId}/export`), { observe: 'response', responseType: 'blob', headers: InterceptorSkipHeader });
|
|
582
|
+
}
|
|
583
|
+
previewProcessDefinitionImport(file) {
|
|
584
|
+
return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/import/preview'), file, { headers: new HttpHeaders().set(InterceptorSkip, '400') });
|
|
585
|
+
}
|
|
586
|
+
importProcessDefinition(file, pluginConfigurationMappings) {
|
|
587
|
+
if (pluginConfigurationMappings) {
|
|
588
|
+
file.set('pluginConfigurationMappings', new Blob([JSON.stringify(pluginConfigurationMappings)], { type: 'application/json' }));
|
|
589
|
+
}
|
|
590
|
+
return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/import'), file, { headers: new HttpHeaders().set(InterceptorSkip, '400') });
|
|
591
|
+
}
|
|
478
592
|
validateProcessDefinition(request) {
|
|
479
593
|
return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/validate'), request);
|
|
480
594
|
}
|
|
@@ -499,7 +613,7 @@ class ProcessManagementService extends BaseApiService {
|
|
|
499
613
|
}
|
|
500
614
|
return object;
|
|
501
615
|
}
|
|
502
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, deps: [{ token: i1.HttpClient }, { token: i2
|
|
616
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, deps: [{ token: i1.HttpClient }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
503
617
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, providedIn: 'root' }); }
|
|
504
618
|
}
|
|
505
619
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, decorators: [{
|
|
@@ -507,7 +621,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
507
621
|
args: [{
|
|
508
622
|
providedIn: 'root',
|
|
509
623
|
}]
|
|
510
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2
|
|
624
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ConfigService }] });
|
|
511
625
|
|
|
512
626
|
/*
|
|
513
627
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
@@ -759,6 +873,9 @@ class ValtimoPropertiesProvider {
|
|
|
759
873
|
get pluginTranslationService() {
|
|
760
874
|
return window.pluginTranslationService;
|
|
761
875
|
}
|
|
876
|
+
get processLinkService() {
|
|
877
|
+
return window.processLinkService;
|
|
878
|
+
}
|
|
762
879
|
constructor(propertiesPanel) {
|
|
763
880
|
propertiesPanel.registerProvider(500, this);
|
|
764
881
|
}
|
|
@@ -774,6 +891,8 @@ class ValtimoPropertiesProvider {
|
|
|
774
891
|
getGroups(element) {
|
|
775
892
|
const processLink = this.processManagementEditorService.processLinksForSelectedDefinition.find(processLink => processLink.activityId === element.id) || null;
|
|
776
893
|
const elementErrors = this.processManagementEditorService.validationErrors.filter(error => error.elementId === element.id);
|
|
894
|
+
const autofillInfo = this.processManagementEditorService.getAutofillForActivity(element.id);
|
|
895
|
+
const isAutofillDismissed = this.processManagementEditorService.isAutofillDismissed(element.id);
|
|
777
896
|
return (groups) => {
|
|
778
897
|
const generalGroup = groups.find((g) => g.id === 'general');
|
|
779
898
|
if (generalGroup) {
|
|
@@ -795,6 +914,23 @@ class ValtimoPropertiesProvider {
|
|
|
795
914
|
};
|
|
796
915
|
groups.unshift(errorGroup);
|
|
797
916
|
}
|
|
917
|
+
if (autofillInfo && !isAutofillDismissed) {
|
|
918
|
+
const targetGroupId = this.getGroupIdForModificationType(autofillInfo.modificationType);
|
|
919
|
+
const targetGroup = groups.find((g) => g.id === targetGroupId);
|
|
920
|
+
if (targetGroup) {
|
|
921
|
+
const notificationEntry = {
|
|
922
|
+
id: 'autofilledNotificationEntry',
|
|
923
|
+
activityId: element.id,
|
|
924
|
+
element,
|
|
925
|
+
translateService: this.translateService,
|
|
926
|
+
processManagementEditorService: this.processManagementEditorService,
|
|
927
|
+
processLinkService: this.processLinkService,
|
|
928
|
+
component: AutofilledNotificationElement,
|
|
929
|
+
};
|
|
930
|
+
targetGroup.entries.unshift(notificationEntry);
|
|
931
|
+
targetGroup.shouldOpen = true;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
798
934
|
if (is(element, 'bpmn:UserTask') ||
|
|
799
935
|
is(element, 'bpmn:StartEvent') ||
|
|
800
936
|
is(element, 'bpmn:ServiceTask') ||
|
|
@@ -814,6 +950,16 @@ class ValtimoPropertiesProvider {
|
|
|
814
950
|
return groups;
|
|
815
951
|
};
|
|
816
952
|
}
|
|
953
|
+
getGroupIdForModificationType(modificationType) {
|
|
954
|
+
const groupMapping = {
|
|
955
|
+
SERVICE_TASK_EXPRESSION: 'CamundaPlatform__Implementation',
|
|
956
|
+
SEND_TASK_EXPRESSION: 'CamundaPlatform__Implementation',
|
|
957
|
+
MESSAGE_EVENT_EXPRESSION: 'message',
|
|
958
|
+
TIMER_DURATION: 'timer',
|
|
959
|
+
CALL_ACTIVITY_BUSINESS_KEY: 'CamundaPlatform__BusinessKey',
|
|
960
|
+
};
|
|
961
|
+
return groupMapping[modificationType] || 'general';
|
|
962
|
+
}
|
|
817
963
|
createCustomRootElement(element, processLink) {
|
|
818
964
|
return {
|
|
819
965
|
translateService: this.translateService,
|
|
@@ -823,7 +969,7 @@ class ValtimoPropertiesProvider {
|
|
|
823
969
|
processLink,
|
|
824
970
|
element,
|
|
825
971
|
component: CustomRootElement,
|
|
826
|
-
isEdited: () =>
|
|
972
|
+
isEdited: (node) => node && !!node.value,
|
|
827
973
|
};
|
|
828
974
|
}
|
|
829
975
|
}
|
|
@@ -874,8 +1020,10 @@ const CustomRootElement = (props) => {
|
|
|
874
1020
|
};
|
|
875
1021
|
const processLinkFormDefinitionId = processLink?.formDefinitionId;
|
|
876
1022
|
const processLinkFormDefinitionName = processManagementEditorService.formDefinitionOptions.find(option => option.id === processLinkFormDefinitionId)?.name;
|
|
1023
|
+
const hiddenInput = html `<input type="hidden" class="bio-properties-panel-input" value=${processLink ? 'configured' : ''} />`;
|
|
1024
|
+
const wrapEntry = (content) => html `<div data-entry-id=${props.id}>${hiddenInput}${content}</div>`;
|
|
877
1025
|
if (processLinkFormDefinitionName) {
|
|
878
|
-
return html `<div class="process-link-properties-panel">
|
|
1026
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
879
1027
|
<div class="process-link-properties-panel__header">
|
|
880
1028
|
<span class="process-link-properties-panel__title">${processLinkFormDefinitionName}</span>
|
|
881
1029
|
|
|
@@ -902,11 +1050,11 @@ const CustomRootElement = (props) => {
|
|
|
902
1050
|
${editProcessLinkText}
|
|
903
1051
|
</button>
|
|
904
1052
|
</div>
|
|
905
|
-
</div
|
|
1053
|
+
</div>`);
|
|
906
1054
|
}
|
|
907
1055
|
const processLinkFormFlowDefinitionKey = processLink?.formFlowDefinitionKey;
|
|
908
1056
|
if (processLinkFormFlowDefinitionKey) {
|
|
909
|
-
return html `<div class="process-link-properties-panel">
|
|
1057
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
910
1058
|
<div class="process-link-properties-panel__header">
|
|
911
1059
|
<span class="process-link-properties-panel__title"
|
|
912
1060
|
>${processLinkFormFlowDefinitionKey}</span
|
|
@@ -935,12 +1083,12 @@ const CustomRootElement = (props) => {
|
|
|
935
1083
|
${editProcessLinkText}
|
|
936
1084
|
</button>
|
|
937
1085
|
</div>
|
|
938
|
-
</div
|
|
1086
|
+
</div>`);
|
|
939
1087
|
}
|
|
940
1088
|
const buildingBlockDefinitionKey = processLink?.buildingBlockDefinitionKey;
|
|
941
1089
|
const buildingBlockDefinitionVersion = processLink?.buildingBlockDefinitionVersionTag;
|
|
942
1090
|
if (buildingBlockDefinitionKey) {
|
|
943
|
-
return html `<div class="process-link-properties-panel">
|
|
1091
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
944
1092
|
<div class="process-link-properties-panel__header">
|
|
945
1093
|
<span class="process-link-properties-panel__title"
|
|
946
1094
|
>${buildingBlockDefinitionKey} (${buildingBlockDefinitionVersion})</span
|
|
@@ -969,13 +1117,13 @@ const CustomRootElement = (props) => {
|
|
|
969
1117
|
${editProcessLinkText}
|
|
970
1118
|
</button>
|
|
971
1119
|
</div>
|
|
972
|
-
</div
|
|
1120
|
+
</div>`);
|
|
973
1121
|
}
|
|
974
1122
|
const pluginActionKey = processLink?.pluginActionDefinitionKey;
|
|
975
1123
|
const pluginActionTranslation = pluginTranslationService.instantByPluginActionKey(pluginActionKey);
|
|
976
1124
|
const pluginTitleTranslation = pluginTranslationService.instantPluginTitleByPluginActionKey(pluginActionKey);
|
|
977
1125
|
if (pluginActionKey) {
|
|
978
|
-
return html `<div class="process-link-properties-panel">
|
|
1126
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
979
1127
|
<div class="process-link-properties-panel__header">
|
|
980
1128
|
<span class="process-link-properties-panel__title-container">
|
|
981
1129
|
<span class="process-link-properties-panel__title">${pluginTitleTranslation}</span>
|
|
@@ -1006,11 +1154,11 @@ const CustomRootElement = (props) => {
|
|
|
1006
1154
|
${editProcessLinkText}
|
|
1007
1155
|
</button>
|
|
1008
1156
|
</div>
|
|
1009
|
-
</div
|
|
1157
|
+
</div>`);
|
|
1010
1158
|
}
|
|
1011
1159
|
const uiComponentKey = processLink?.componentKey;
|
|
1012
1160
|
if (uiComponentKey) {
|
|
1013
|
-
return html `<div class="process-link-properties-panel">
|
|
1161
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
1014
1162
|
<div class="process-link-properties-panel__header">
|
|
1015
1163
|
<span class="process-link-properties-panel__title">${uiComponentKey}</span>
|
|
1016
1164
|
|
|
@@ -1037,7 +1185,7 @@ const CustomRootElement = (props) => {
|
|
|
1037
1185
|
${editProcessLinkText}
|
|
1038
1186
|
</button>
|
|
1039
1187
|
</div>
|
|
1040
|
-
</div
|
|
1188
|
+
</div>`);
|
|
1041
1189
|
}
|
|
1042
1190
|
const genericLinkedPanel = html `<div class="process-link-properties-panel">
|
|
1043
1191
|
<div class="process-link-properties-panel__buttons">
|
|
@@ -1066,13 +1214,13 @@ const CustomRootElement = (props) => {
|
|
|
1066
1214
|
</button>
|
|
1067
1215
|
</div>
|
|
1068
1216
|
</div>`;
|
|
1069
|
-
return processLink ? genericLinkedPanel : genericCreatePanel;
|
|
1217
|
+
return wrapEntry(processLink ? genericLinkedPanel : genericCreatePanel);
|
|
1070
1218
|
};
|
|
1071
1219
|
const ValidationErrorsElement = (props) => {
|
|
1072
1220
|
const getErrorMessage = (error) => {
|
|
1073
1221
|
if (error.errorCode) {
|
|
1074
|
-
const translationKey = `processManagement.
|
|
1075
|
-
const translated = props.translateService.instant(translationKey, { expression: error.expression
|
|
1222
|
+
const translationKey = `processManagement.validationErrorCodes.${error.errorCode}`;
|
|
1223
|
+
const translated = props.translateService.instant(translationKey, { expression: error.expression ?? '' });
|
|
1076
1224
|
if (translated !== translationKey) {
|
|
1077
1225
|
return translated;
|
|
1078
1226
|
}
|
|
@@ -1086,11 +1234,624 @@ const ValidationErrorsElement = (props) => {
|
|
|
1086
1234
|
</div>`)}
|
|
1087
1235
|
</div>`;
|
|
1088
1236
|
};
|
|
1237
|
+
const AutofilledNotificationElement = (props) => {
|
|
1238
|
+
const handleDismiss = (event) => {
|
|
1239
|
+
const processDefinitionId = props.processManagementEditorService.selectionProcessDefinition?.id;
|
|
1240
|
+
if (processDefinitionId) {
|
|
1241
|
+
props.processLinkService.deleteAutofill(processDefinitionId, props.activityId).subscribe();
|
|
1242
|
+
}
|
|
1243
|
+
props.processManagementEditorService.dismissAutofill(props.activityId);
|
|
1244
|
+
const target = event.currentTarget;
|
|
1245
|
+
const panel = target.closest('.autofilled-notification-panel');
|
|
1246
|
+
if (panel) {
|
|
1247
|
+
panel.style.display = 'none';
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
return html `<div class="autofilled-notification-panel">
|
|
1251
|
+
<span class="autofilled-notification-panel__icon">!</span>
|
|
1252
|
+
<span class="autofilled-notification-panel__message">
|
|
1253
|
+
${props.translateService.instant('processManagement.autofilled.sidebarMessage')}
|
|
1254
|
+
</span>
|
|
1255
|
+
<button class="autofilled-notification-panel__dismiss" onClick=${handleDismiss}>×</button>
|
|
1256
|
+
</div>`;
|
|
1257
|
+
};
|
|
1089
1258
|
const ValtimoPropertiesProviderModule = {
|
|
1090
1259
|
__init__: ['customPropertiesProvider'],
|
|
1091
1260
|
customPropertiesProvider: ['type', ValtimoPropertiesProvider],
|
|
1092
1261
|
};
|
|
1093
1262
|
|
|
1263
|
+
/*
|
|
1264
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
1265
|
+
*
|
|
1266
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
1267
|
+
* you may not use this file except in compliance with the License.
|
|
1268
|
+
* You may obtain a copy of the License at
|
|
1269
|
+
*
|
|
1270
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
1271
|
+
*
|
|
1272
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1273
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
1274
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1275
|
+
* See the License for the specific language governing permissions and
|
|
1276
|
+
* limitations under the License.
|
|
1277
|
+
*/
|
|
1278
|
+
class ExpressionAutocomplete {
|
|
1279
|
+
static { this.$inject = ['eventBus']; }
|
|
1280
|
+
constructor(eventBus) {
|
|
1281
|
+
this.processBeans = [];
|
|
1282
|
+
this.panelContainer = null;
|
|
1283
|
+
this.stylesInjected = false;
|
|
1284
|
+
this.observer = null;
|
|
1285
|
+
this.documentClickHandlers = [];
|
|
1286
|
+
this.injectStyles();
|
|
1287
|
+
eventBus.on('diagram.destroy', () => {
|
|
1288
|
+
this.dispose();
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
dispose() {
|
|
1292
|
+
this.cleanupClickHandlers();
|
|
1293
|
+
if (this.observer) {
|
|
1294
|
+
this.observer.disconnect();
|
|
1295
|
+
this.observer = null;
|
|
1296
|
+
}
|
|
1297
|
+
this.panelContainer = null;
|
|
1298
|
+
}
|
|
1299
|
+
cleanupClickHandlers() {
|
|
1300
|
+
for (const handler of this.documentClickHandlers) {
|
|
1301
|
+
document.removeEventListener('click', handler);
|
|
1302
|
+
}
|
|
1303
|
+
this.documentClickHandlers = [];
|
|
1304
|
+
}
|
|
1305
|
+
setProcessBeans(beans) {
|
|
1306
|
+
this.processBeans = beans;
|
|
1307
|
+
}
|
|
1308
|
+
setPanelContainer(container) {
|
|
1309
|
+
this.panelContainer = container;
|
|
1310
|
+
this.startObserving();
|
|
1311
|
+
setTimeout(() => this.scanAndAttach(), 100);
|
|
1312
|
+
}
|
|
1313
|
+
startObserving() {
|
|
1314
|
+
if (!this.panelContainer || this.observer)
|
|
1315
|
+
return;
|
|
1316
|
+
this.observer = new MutationObserver(() => {
|
|
1317
|
+
this.scanAndAttach();
|
|
1318
|
+
});
|
|
1319
|
+
this.observer.observe(this.panelContainer, {
|
|
1320
|
+
childList: true,
|
|
1321
|
+
subtree: true,
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
scanAndAttach() {
|
|
1325
|
+
if (!this.panelContainer)
|
|
1326
|
+
return;
|
|
1327
|
+
const allInputs = this.panelContainer.querySelectorAll('input, textarea');
|
|
1328
|
+
allInputs.forEach(input => {
|
|
1329
|
+
if (input.dataset.autocompleteAttached)
|
|
1330
|
+
return;
|
|
1331
|
+
if (this.isExpressionField(input)) {
|
|
1332
|
+
this.attachAutocomplete(input);
|
|
1333
|
+
input.dataset.autocompleteAttached = 'true';
|
|
1334
|
+
}
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
isExpressionField(input) {
|
|
1338
|
+
const type = input.type?.toLowerCase();
|
|
1339
|
+
if (input.tagName !== 'TEXTAREA' && !(input.tagName === 'INPUT' && (!type || type === 'text'))) {
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
1342
|
+
if (input.closest('.expression-editor-simple')) {
|
|
1343
|
+
return false;
|
|
1344
|
+
}
|
|
1345
|
+
const name = (input.name || input.id || '').toLowerCase();
|
|
1346
|
+
if (name.includes('resultvariable') || name.includes('result-variable')) {
|
|
1347
|
+
return false;
|
|
1348
|
+
}
|
|
1349
|
+
if (name.includes('expression') || name.includes('delegateexpression')) {
|
|
1350
|
+
return true;
|
|
1351
|
+
}
|
|
1352
|
+
const entry = input.closest('.bio-properties-panel-entry');
|
|
1353
|
+
if (entry) {
|
|
1354
|
+
const entryId = (entry.getAttribute('data-entry-id') || '').toLowerCase();
|
|
1355
|
+
if (entryId.includes('resultvariable') || entryId.includes('result-variable')) {
|
|
1356
|
+
return false;
|
|
1357
|
+
}
|
|
1358
|
+
if (entryId.includes('expression')) {
|
|
1359
|
+
return true;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
const label = input.closest('.bio-properties-panel-entry')?.querySelector('label');
|
|
1363
|
+
if (label) {
|
|
1364
|
+
const labelText = label.textContent?.toLowerCase() || '';
|
|
1365
|
+
if (labelText.includes('result variable') || labelText.includes('resultvariable')) {
|
|
1366
|
+
return false;
|
|
1367
|
+
}
|
|
1368
|
+
if (labelText.includes('expression') || labelText.includes('delegate')) {
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
return false;
|
|
1373
|
+
}
|
|
1374
|
+
attachAutocomplete(input) {
|
|
1375
|
+
this.wrapWithEditor(input);
|
|
1376
|
+
}
|
|
1377
|
+
// --- Expression Editor (Dropdown/Manual toggle) ---
|
|
1378
|
+
wrapWithEditor(input) {
|
|
1379
|
+
const wrapper = document.createElement('div');
|
|
1380
|
+
wrapper.className = 'expression-editor-wrapper';
|
|
1381
|
+
const parsed = this.parseExpression(input.value);
|
|
1382
|
+
const canUseDropdown = !input.value || (parsed.beanName !== null && parsed.methodName !== null);
|
|
1383
|
+
const initialMode = canUseDropdown ? 'simple' : 'technical';
|
|
1384
|
+
wrapper.dataset.mode = initialMode;
|
|
1385
|
+
input.parentNode?.insertBefore(wrapper, input);
|
|
1386
|
+
const toggle = document.createElement('div');
|
|
1387
|
+
toggle.className = 'expression-editor-toggle';
|
|
1388
|
+
toggle.innerHTML = `
|
|
1389
|
+
<button type="button" class="expression-editor-toggle__btn${initialMode === 'simple' ? ' active' : ''}" data-mode="simple">Dropdown</button>
|
|
1390
|
+
<button type="button" class="expression-editor-toggle__btn${initialMode === 'technical' ? ' active' : ''}" data-mode="technical">Manual</button>
|
|
1391
|
+
`;
|
|
1392
|
+
const technicalContainer = document.createElement('div');
|
|
1393
|
+
technicalContainer.className = 'expression-editor-technical';
|
|
1394
|
+
technicalContainer.appendChild(input);
|
|
1395
|
+
technicalContainer.style.display = initialMode === 'technical' ? 'block' : 'none';
|
|
1396
|
+
const simpleContainer = document.createElement('div');
|
|
1397
|
+
simpleContainer.className = 'expression-editor-simple';
|
|
1398
|
+
simpleContainer.style.display = initialMode === 'simple' ? 'block' : 'none';
|
|
1399
|
+
wrapper.appendChild(toggle);
|
|
1400
|
+
wrapper.appendChild(technicalContainer);
|
|
1401
|
+
wrapper.appendChild(simpleContainer);
|
|
1402
|
+
toggle.querySelectorAll('button').forEach(btn => {
|
|
1403
|
+
btn.addEventListener('click', e => {
|
|
1404
|
+
e.preventDefault();
|
|
1405
|
+
this.setEditorMode(wrapper, input, btn.dataset.mode || 'technical');
|
|
1406
|
+
});
|
|
1407
|
+
});
|
|
1408
|
+
if (initialMode === 'simple') {
|
|
1409
|
+
this.renderSimpleMode(simpleContainer, input);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
setEditorMode(wrapper, input, mode) {
|
|
1413
|
+
wrapper.dataset.mode = mode;
|
|
1414
|
+
wrapper.querySelectorAll('.expression-editor-toggle__btn').forEach(btn => {
|
|
1415
|
+
btn.classList.toggle('active', btn.dataset.mode === mode);
|
|
1416
|
+
});
|
|
1417
|
+
const technicalContainer = wrapper.querySelector('.expression-editor-technical');
|
|
1418
|
+
const simpleContainer = wrapper.querySelector('.expression-editor-simple');
|
|
1419
|
+
const invalidArgsStr = wrapper.dataset.invalidArgs;
|
|
1420
|
+
const invalidArgs = invalidArgsStr ? JSON.parse(invalidArgsStr) : [];
|
|
1421
|
+
if (mode === 'simple') {
|
|
1422
|
+
technicalContainer.style.display = 'none';
|
|
1423
|
+
simpleContainer.style.display = 'block';
|
|
1424
|
+
input.classList.remove('validation-error-param');
|
|
1425
|
+
this.renderSimpleMode(simpleContainer, input);
|
|
1426
|
+
if (invalidArgs.length > 0) {
|
|
1427
|
+
setTimeout(() => {
|
|
1428
|
+
for (const idx of invalidArgs) {
|
|
1429
|
+
const paramInput = simpleContainer.querySelector(`.expression-editor-param input[data-param-index="${idx}"]`);
|
|
1430
|
+
if (paramInput) {
|
|
1431
|
+
paramInput.classList.add('validation-error-param');
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}, 0);
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
else {
|
|
1438
|
+
technicalContainer.style.display = 'block';
|
|
1439
|
+
simpleContainer.style.display = 'none';
|
|
1440
|
+
if (invalidArgs.length > 0) {
|
|
1441
|
+
input.classList.add('validation-error-param');
|
|
1442
|
+
}
|
|
1443
|
+
setTimeout(() => input.blur(), 0);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
renderSimpleMode(container, input) {
|
|
1447
|
+
this.cleanupClickHandlers();
|
|
1448
|
+
const parsed = this.parseExpression(input.value);
|
|
1449
|
+
container.innerHTML = `
|
|
1450
|
+
<div class="expression-editor-field" data-container="bean">
|
|
1451
|
+
<label>Service</label>
|
|
1452
|
+
</div>
|
|
1453
|
+
<div class="expression-editor-field" data-container="method"></div>
|
|
1454
|
+
<div data-container="params"></div>
|
|
1455
|
+
`;
|
|
1456
|
+
const beanContainer = container.querySelector('[data-container="bean"]');
|
|
1457
|
+
this.renderCustomSelect(beanContainer, this.processBeans.map(b => ({
|
|
1458
|
+
value: b.name,
|
|
1459
|
+
label: this.camelCaseToReadable(b.name),
|
|
1460
|
+
description: b.description,
|
|
1461
|
+
})), parsed.beanName, 'Select service...', 'bean', beanName => {
|
|
1462
|
+
this.renderMethodDropdown(container, beanName, null, input);
|
|
1463
|
+
this.renderParameterInputs(container, beanName, null, [], input);
|
|
1464
|
+
this.buildAndSetExpression(container, input);
|
|
1465
|
+
});
|
|
1466
|
+
if (parsed.beanName) {
|
|
1467
|
+
this.renderMethodDropdown(container, parsed.beanName, parsed.methodName, input);
|
|
1468
|
+
}
|
|
1469
|
+
if (parsed.beanName && parsed.methodName) {
|
|
1470
|
+
this.renderParameterInputs(container, parsed.beanName, parsed.methodName, parsed.parameters, input);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
renderCustomSelect(container, options, selectedValue, placeholder, dataField, onChange) {
|
|
1474
|
+
const wrapper = document.createElement('div');
|
|
1475
|
+
wrapper.className = 'expression-editor-custom-select';
|
|
1476
|
+
wrapper.dataset.field = dataField;
|
|
1477
|
+
wrapper.dataset.value = selectedValue || '';
|
|
1478
|
+
const nativeSelect = document.createElement('select');
|
|
1479
|
+
nativeSelect.className = 'bio-properties-panel-input';
|
|
1480
|
+
nativeSelect.innerHTML =
|
|
1481
|
+
`<option value="" disabled ${!selectedValue ? 'selected' : ''}>${this.escapeHtml(placeholder)}</option>` +
|
|
1482
|
+
options
|
|
1483
|
+
.map(opt => `<option value="${this.escapeAttr(opt.value)}" ${opt.value === selectedValue ? 'selected' : ''}>${this.escapeHtml(opt.label)}</option>`)
|
|
1484
|
+
.join('');
|
|
1485
|
+
const selectedOption = options.find(o => o.value === selectedValue);
|
|
1486
|
+
if (selectedOption?.description) {
|
|
1487
|
+
nativeSelect.title = selectedOption.description;
|
|
1488
|
+
}
|
|
1489
|
+
const dropdown = document.createElement('div');
|
|
1490
|
+
dropdown.className = 'expression-editor-custom-select__dropdown';
|
|
1491
|
+
dropdown.style.display = 'none';
|
|
1492
|
+
let selectedIndex = options.findIndex(o => o.value === selectedValue);
|
|
1493
|
+
if (selectedIndex < 0)
|
|
1494
|
+
selectedIndex = 0;
|
|
1495
|
+
const renderItems = () => {
|
|
1496
|
+
dropdown.innerHTML = options
|
|
1497
|
+
.map((opt, i) => `
|
|
1498
|
+
<div class="expression-editor-custom-select__item${opt.value === selectedValue ? ' selected' : ''}" data-index="${i}" data-value="${this.escapeAttr(opt.value)}">
|
|
1499
|
+
<div class="expression-editor-custom-select__label">${this.escapeHtml(opt.label)}</div>
|
|
1500
|
+
${opt.description ? `<div class="expression-editor-custom-select__desc">${this.escapeHtml(opt.description)}</div>` : ''}
|
|
1501
|
+
</div>
|
|
1502
|
+
`)
|
|
1503
|
+
.join('');
|
|
1504
|
+
dropdown.querySelectorAll('.expression-editor-custom-select__item').forEach(item => {
|
|
1505
|
+
item.addEventListener('click', e => {
|
|
1506
|
+
e.stopPropagation();
|
|
1507
|
+
const value = item.dataset.value;
|
|
1508
|
+
const selected = options.find(o => o.value === value);
|
|
1509
|
+
wrapper.dataset.value = value;
|
|
1510
|
+
nativeSelect.value = value;
|
|
1511
|
+
nativeSelect.title = selected?.description || '';
|
|
1512
|
+
dropdown.style.display = 'none';
|
|
1513
|
+
onChange(value);
|
|
1514
|
+
});
|
|
1515
|
+
});
|
|
1516
|
+
};
|
|
1517
|
+
renderItems();
|
|
1518
|
+
nativeSelect.addEventListener('mousedown', e => {
|
|
1519
|
+
e.preventDefault();
|
|
1520
|
+
nativeSelect.focus();
|
|
1521
|
+
const isOpen = dropdown.style.display !== 'none';
|
|
1522
|
+
dropdown.style.display = isOpen ? 'none' : 'block';
|
|
1523
|
+
});
|
|
1524
|
+
nativeSelect.addEventListener('keydown', e => {
|
|
1525
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
1526
|
+
e.preventDefault();
|
|
1527
|
+
if (dropdown.style.display === 'none') {
|
|
1528
|
+
dropdown.style.display = 'block';
|
|
1529
|
+
}
|
|
1530
|
+
const delta = e.key === 'ArrowDown' ? 1 : -1;
|
|
1531
|
+
selectedIndex = Math.max(0, Math.min(options.length - 1, selectedIndex + delta));
|
|
1532
|
+
dropdown.querySelectorAll('.expression-editor-custom-select__item').forEach((item, i) => {
|
|
1533
|
+
item.classList.toggle('highlighted', i === selectedIndex);
|
|
1534
|
+
});
|
|
1535
|
+
dropdown.children[selectedIndex]?.scrollIntoView({ block: 'nearest' });
|
|
1536
|
+
}
|
|
1537
|
+
else if (e.key === 'Enter' && dropdown.style.display !== 'none') {
|
|
1538
|
+
e.preventDefault();
|
|
1539
|
+
const opt = options[selectedIndex];
|
|
1540
|
+
if (opt) {
|
|
1541
|
+
wrapper.dataset.value = opt.value;
|
|
1542
|
+
nativeSelect.value = opt.value;
|
|
1543
|
+
nativeSelect.title = opt.description || '';
|
|
1544
|
+
dropdown.style.display = 'none';
|
|
1545
|
+
onChange(opt.value);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
else if (e.key === 'Escape') {
|
|
1549
|
+
dropdown.style.display = 'none';
|
|
1550
|
+
}
|
|
1551
|
+
else if (e.key === ' ' && dropdown.style.display === 'none') {
|
|
1552
|
+
e.preventDefault();
|
|
1553
|
+
dropdown.style.display = 'block';
|
|
1554
|
+
}
|
|
1555
|
+
});
|
|
1556
|
+
const closeHandler = (e) => {
|
|
1557
|
+
if (!wrapper.contains(e.target)) {
|
|
1558
|
+
dropdown.style.display = 'none';
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1561
|
+
document.addEventListener('click', closeHandler);
|
|
1562
|
+
this.documentClickHandlers.push(closeHandler);
|
|
1563
|
+
wrapper.appendChild(nativeSelect);
|
|
1564
|
+
wrapper.appendChild(dropdown);
|
|
1565
|
+
container.appendChild(wrapper);
|
|
1566
|
+
}
|
|
1567
|
+
renderMethodDropdown(container, beanName, selectedMethod, input) {
|
|
1568
|
+
const methodContainer = container.querySelector('[data-container="method"]');
|
|
1569
|
+
if (!methodContainer)
|
|
1570
|
+
return;
|
|
1571
|
+
const bean = this.processBeans.find(b => b.name === beanName);
|
|
1572
|
+
if (!bean) {
|
|
1573
|
+
methodContainer.innerHTML = '';
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1576
|
+
methodContainer.innerHTML = '<label>Method</label>';
|
|
1577
|
+
this.renderCustomSelect(methodContainer, bean.methods.map(m => ({
|
|
1578
|
+
value: m.name,
|
|
1579
|
+
label: this.camelCaseToReadable(m.name),
|
|
1580
|
+
description: m.description,
|
|
1581
|
+
})), selectedMethod, 'Select method...', 'method', methodName => {
|
|
1582
|
+
this.renderParameterInputs(container, beanName, methodName, [], input);
|
|
1583
|
+
this.buildAndSetExpression(container, input);
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
renderParameterInputs(container, beanName, methodName, values, input) {
|
|
1587
|
+
const paramsContainer = container.querySelector('[data-container="params"]');
|
|
1588
|
+
if (!paramsContainer)
|
|
1589
|
+
return;
|
|
1590
|
+
if (!methodName) {
|
|
1591
|
+
paramsContainer.innerHTML = '';
|
|
1592
|
+
return;
|
|
1593
|
+
}
|
|
1594
|
+
const bean = this.processBeans.find(b => b.name === beanName);
|
|
1595
|
+
const method = bean?.methods.find(m => m.name === methodName);
|
|
1596
|
+
if (!method || method.parameters.length === 0) {
|
|
1597
|
+
paramsContainer.innerHTML = '';
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
paramsContainer.innerHTML = method.parameters
|
|
1601
|
+
.map((p, i) => `
|
|
1602
|
+
<div class="expression-editor-param">
|
|
1603
|
+
<label>${this.escapeHtml(p.name)} <span class="type">(${this.escapeHtml(p.type)})</span></label>
|
|
1604
|
+
<input type="text" class="expression-editor-input" data-param-index="${i}" value="${this.escapeAttr(values[i] || '')}">
|
|
1605
|
+
</div>
|
|
1606
|
+
`)
|
|
1607
|
+
.join('');
|
|
1608
|
+
paramsContainer.querySelectorAll('input').forEach(paramInput => {
|
|
1609
|
+
paramInput.addEventListener('input', () => {
|
|
1610
|
+
this.buildAndSetExpression(container, input);
|
|
1611
|
+
});
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
buildAndSetExpression(simpleContainer, input) {
|
|
1615
|
+
const beanSelect = simpleContainer.querySelector('[data-field="bean"]');
|
|
1616
|
+
const methodSelect = simpleContainer.querySelector('[data-field="method"]');
|
|
1617
|
+
const paramInputs = simpleContainer.querySelectorAll('[data-param-index]');
|
|
1618
|
+
const bean = beanSelect?.dataset.value;
|
|
1619
|
+
const method = methodSelect?.dataset.value;
|
|
1620
|
+
if (!bean || !method) {
|
|
1621
|
+
input.value = '';
|
|
1622
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
const params = Array.from(paramInputs).map(i => i.value);
|
|
1626
|
+
input.value = `\${${bean}.${method}(${params.join(', ')})}`;
|
|
1627
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
1628
|
+
}
|
|
1629
|
+
parseExpression(expr) {
|
|
1630
|
+
const match = expr.match(/^\$\{([a-zA-Z_]\w*)\.([a-zA-Z_]\w*)\((.*)\)\}$/);
|
|
1631
|
+
if (!match)
|
|
1632
|
+
return { beanName: null, methodName: null, parameters: [] };
|
|
1633
|
+
return {
|
|
1634
|
+
beanName: match[1],
|
|
1635
|
+
methodName: match[2],
|
|
1636
|
+
parameters: this.parseParameters(match[3]),
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
parseParameters(paramsStr) {
|
|
1640
|
+
const params = [];
|
|
1641
|
+
let current = '';
|
|
1642
|
+
let depth = 0;
|
|
1643
|
+
let inString = false;
|
|
1644
|
+
let stringChar = '';
|
|
1645
|
+
for (const char of paramsStr) {
|
|
1646
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
1647
|
+
inString = true;
|
|
1648
|
+
stringChar = char;
|
|
1649
|
+
current += char;
|
|
1650
|
+
}
|
|
1651
|
+
else if (inString && char === stringChar) {
|
|
1652
|
+
inString = false;
|
|
1653
|
+
current += char;
|
|
1654
|
+
}
|
|
1655
|
+
else if (!inString && (char === '(' || char === '[')) {
|
|
1656
|
+
depth++;
|
|
1657
|
+
current += char;
|
|
1658
|
+
}
|
|
1659
|
+
else if (!inString && (char === ')' || char === ']')) {
|
|
1660
|
+
depth--;
|
|
1661
|
+
current += char;
|
|
1662
|
+
}
|
|
1663
|
+
else if (!inString && char === ',' && depth === 0) {
|
|
1664
|
+
params.push(current.trim());
|
|
1665
|
+
current = '';
|
|
1666
|
+
}
|
|
1667
|
+
else {
|
|
1668
|
+
current += char;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
if (current.trim())
|
|
1672
|
+
params.push(current.trim());
|
|
1673
|
+
return params;
|
|
1674
|
+
}
|
|
1675
|
+
escapeHtml(text) {
|
|
1676
|
+
const div = document.createElement('div');
|
|
1677
|
+
div.textContent = text;
|
|
1678
|
+
return div.innerHTML;
|
|
1679
|
+
}
|
|
1680
|
+
escapeAttr(text) {
|
|
1681
|
+
return text
|
|
1682
|
+
.replace(/&/g, '&')
|
|
1683
|
+
.replace(/"/g, '"')
|
|
1684
|
+
.replace(/'/g, ''')
|
|
1685
|
+
.replace(/</g, '<')
|
|
1686
|
+
.replace(/>/g, '>');
|
|
1687
|
+
}
|
|
1688
|
+
camelCaseToReadable(text) {
|
|
1689
|
+
return text
|
|
1690
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
1691
|
+
.replace(/^./, str => str.toUpperCase());
|
|
1692
|
+
}
|
|
1693
|
+
injectStyles() {
|
|
1694
|
+
if (this.stylesInjected)
|
|
1695
|
+
return;
|
|
1696
|
+
this.stylesInjected = true;
|
|
1697
|
+
const style = document.createElement('style');
|
|
1698
|
+
style.textContent = `
|
|
1699
|
+
/* Expression Editor Toggle UI */
|
|
1700
|
+
.expression-editor-wrapper {
|
|
1701
|
+
width: 100%;
|
|
1702
|
+
}
|
|
1703
|
+
.expression-editor-toggle {
|
|
1704
|
+
display: flex;
|
|
1705
|
+
gap: 0;
|
|
1706
|
+
margin-bottom: 8px;
|
|
1707
|
+
}
|
|
1708
|
+
.expression-editor-toggle__btn {
|
|
1709
|
+
flex: 1;
|
|
1710
|
+
padding: 4px 8px;
|
|
1711
|
+
border: 1px solid #ccc;
|
|
1712
|
+
background: #fafafa;
|
|
1713
|
+
color: #333;
|
|
1714
|
+
cursor: pointer;
|
|
1715
|
+
font-size: 13px;
|
|
1716
|
+
font-family: inherit;
|
|
1717
|
+
}
|
|
1718
|
+
.expression-editor-toggle__btn:first-child {
|
|
1719
|
+
border-radius: 2px 0 0 2px;
|
|
1720
|
+
}
|
|
1721
|
+
.expression-editor-toggle__btn:last-child {
|
|
1722
|
+
border-radius: 0 2px 2px 0;
|
|
1723
|
+
border-left: none;
|
|
1724
|
+
}
|
|
1725
|
+
.expression-editor-toggle__btn.active {
|
|
1726
|
+
background: #2b79bd;
|
|
1727
|
+
color: white;
|
|
1728
|
+
border-color: #2b79bd;
|
|
1729
|
+
}
|
|
1730
|
+
.expression-editor-toggle__btn:hover:not(.active) {
|
|
1731
|
+
background: #fff;
|
|
1732
|
+
}
|
|
1733
|
+
.expression-editor-simple {
|
|
1734
|
+
display: flex;
|
|
1735
|
+
flex-direction: column;
|
|
1736
|
+
gap: 6px;
|
|
1737
|
+
}
|
|
1738
|
+
.expression-editor-field label,
|
|
1739
|
+
.expression-editor-param > label {
|
|
1740
|
+
display: block;
|
|
1741
|
+
font-size: var(--text-size-small, 12px);
|
|
1742
|
+
color: var(--label-color, #666);
|
|
1743
|
+
margin-bottom: 2px;
|
|
1744
|
+
}
|
|
1745
|
+
.expression-editor-field label .type,
|
|
1746
|
+
.expression-editor-param label .type {
|
|
1747
|
+
color: var(--description-color, #808080);
|
|
1748
|
+
}
|
|
1749
|
+
.expression-editor-select,
|
|
1750
|
+
.expression-editor-input {
|
|
1751
|
+
display: block;
|
|
1752
|
+
width: 100%;
|
|
1753
|
+
padding: 3px 6px 2px;
|
|
1754
|
+
border: 1px solid #ccc;
|
|
1755
|
+
border-radius: 2px;
|
|
1756
|
+
font-size: 14px;
|
|
1757
|
+
background-color: #fafafa;
|
|
1758
|
+
font-family: inherit;
|
|
1759
|
+
box-sizing: border-box;
|
|
1760
|
+
}
|
|
1761
|
+
.expression-editor-select:focus,
|
|
1762
|
+
.expression-editor-input:focus {
|
|
1763
|
+
outline: none;
|
|
1764
|
+
background-color: hsl(205, 100%, 95%);
|
|
1765
|
+
border-color: hsl(205, 100%, 50%);
|
|
1766
|
+
}
|
|
1767
|
+
/* Override bpmn-js input styles to prevent focus-within highlighting */
|
|
1768
|
+
.expression-editor-technical input,
|
|
1769
|
+
.expression-editor-technical textarea {
|
|
1770
|
+
background-color: #fafafa !important;
|
|
1771
|
+
border-color: #ccc !important;
|
|
1772
|
+
}
|
|
1773
|
+
/* Override native select and input styles in simple mode */
|
|
1774
|
+
.expression-editor-simple select.bio-properties-panel-input,
|
|
1775
|
+
.expression-editor-simple .expression-editor-input {
|
|
1776
|
+
background-color: #fafafa !important;
|
|
1777
|
+
border-color: #ccc !important;
|
|
1778
|
+
}
|
|
1779
|
+
.expression-editor-simple select.bio-properties-panel-input:focus,
|
|
1780
|
+
.expression-editor-simple .expression-editor-input:focus {
|
|
1781
|
+
background-color: hsl(205, 100%, 95%) !important;
|
|
1782
|
+
border-color: hsl(205, 100%, 50%) !important;
|
|
1783
|
+
}
|
|
1784
|
+
.expression-editor-technical input:focus,
|
|
1785
|
+
.expression-editor-technical textarea:focus {
|
|
1786
|
+
background-color: hsl(205, 100%, 95%) !important;
|
|
1787
|
+
border-color: hsl(205, 100%, 50%) !important;
|
|
1788
|
+
}
|
|
1789
|
+
.expression-editor-param {
|
|
1790
|
+
padding-left: 8px;
|
|
1791
|
+
border-left: 2px solid #ccc;
|
|
1792
|
+
margin-top: 4px;
|
|
1793
|
+
}
|
|
1794
|
+
.expression-editor-description {
|
|
1795
|
+
font-size: var(--text-size-small, 12px);
|
|
1796
|
+
color: var(--description-color, #808080);
|
|
1797
|
+
margin-top: 4px;
|
|
1798
|
+
font-style: italic;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
/* Custom Select (Listbox) */
|
|
1802
|
+
.expression-editor-custom-select {
|
|
1803
|
+
position: relative;
|
|
1804
|
+
width: 100%;
|
|
1805
|
+
}
|
|
1806
|
+
.expression-editor-custom-select select {
|
|
1807
|
+
width: 100%;
|
|
1808
|
+
}
|
|
1809
|
+
.expression-editor-custom-select__dropdown {
|
|
1810
|
+
position: absolute;
|
|
1811
|
+
top: 100%;
|
|
1812
|
+
left: 0;
|
|
1813
|
+
right: 0;
|
|
1814
|
+
max-height: 200px;
|
|
1815
|
+
overflow-y: auto;
|
|
1816
|
+
background: #fff;
|
|
1817
|
+
border: 1px solid #ccc;
|
|
1818
|
+
border-radius: 2px;
|
|
1819
|
+
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
|
1820
|
+
z-index: 1000;
|
|
1821
|
+
margin-top: 2px;
|
|
1822
|
+
}
|
|
1823
|
+
.expression-editor-custom-select__item {
|
|
1824
|
+
padding: 8px;
|
|
1825
|
+
cursor: pointer;
|
|
1826
|
+
border-bottom: 1px solid #eee;
|
|
1827
|
+
}
|
|
1828
|
+
.expression-editor-custom-select__item:last-child {
|
|
1829
|
+
border-bottom: none;
|
|
1830
|
+
}
|
|
1831
|
+
.expression-editor-custom-select__item:hover,
|
|
1832
|
+
.expression-editor-custom-select__item.selected,
|
|
1833
|
+
.expression-editor-custom-select__item.highlighted {
|
|
1834
|
+
background: hsl(205, 100%, 95%);
|
|
1835
|
+
}
|
|
1836
|
+
.expression-editor-custom-select__label {
|
|
1837
|
+
font-weight: 500;
|
|
1838
|
+
font-size: 14px;
|
|
1839
|
+
color: #333;
|
|
1840
|
+
}
|
|
1841
|
+
.expression-editor-custom-select__desc {
|
|
1842
|
+
font-size: 11px;
|
|
1843
|
+
color: #666;
|
|
1844
|
+
margin-top: 2px;
|
|
1845
|
+
}
|
|
1846
|
+
`;
|
|
1847
|
+
document.head.appendChild(style);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
const ExpressionAutocompleteModule = {
|
|
1851
|
+
__init__: ['expressionAutocomplete'],
|
|
1852
|
+
expressionAutocomplete: ['type', ExpressionAutocomplete],
|
|
1853
|
+
};
|
|
1854
|
+
|
|
1094
1855
|
/*
|
|
1095
1856
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
1096
1857
|
*
|
|
@@ -1123,7 +1884,7 @@ const ValtimoPropertiesProviderModule = {
|
|
|
1123
1884
|
* limitations under the License.
|
|
1124
1885
|
*/
|
|
1125
1886
|
class ProcessManagementBuilderComponent {
|
|
1126
|
-
constructor(breadcrumbService, iconService, logger, modalService, notificationService, pageHeaderService, pageTitleService, processLinkService, processLinkStateService, processManagementEditorService, processManagementService, processService, route, router, translateService, pluginTranslationService, editPermissionsService, processLinkBuildingBlockApiService) {
|
|
1887
|
+
constructor(breadcrumbService, iconService, logger, modalService, notificationService, pageHeaderService, pageTitleService, processLinkService, processLinkStateService, processManagementEditorService, processManagementService, processService, route, router, translateService, pluginTranslationService, editPermissionsService, processLinkBuildingBlockApiService, processBeanService) {
|
|
1127
1888
|
this.breadcrumbService = breadcrumbService;
|
|
1128
1889
|
this.iconService = iconService;
|
|
1129
1890
|
this.logger = logger;
|
|
@@ -1142,26 +1903,40 @@ class ProcessManagementBuilderComponent {
|
|
|
1142
1903
|
this.pluginTranslationService = pluginTranslationService;
|
|
1143
1904
|
this.editPermissionsService = editPermissionsService;
|
|
1144
1905
|
this.processLinkBuildingBlockApiService = processLinkBuildingBlockApiService;
|
|
1906
|
+
this.processBeanService = processBeanService;
|
|
1145
1907
|
this._selectedProcess$ = new BehaviorSubject(null);
|
|
1146
1908
|
this.loading$ = new BehaviorSubject(true);
|
|
1147
1909
|
this._validationErrorElementIds = [];
|
|
1148
1910
|
this._validationHoverHandler = null;
|
|
1149
1911
|
this._validationOutHandler = null;
|
|
1912
|
+
this._selectionChangedHandler = null;
|
|
1913
|
+
this._fieldInputCleanupFns = [];
|
|
1914
|
+
this._expressionAutocomplete = null;
|
|
1915
|
+
this._activityMarkerElementIds = [];
|
|
1916
|
+
this._activityMarkerUpdateTimeout = null;
|
|
1917
|
+
this._autofilledElements = [];
|
|
1918
|
+
this._autofilledElementIds = [];
|
|
1150
1919
|
this.isReadOnlyProcess$ = new BehaviorSubject(false);
|
|
1151
1920
|
this.isSystemProcess$ = new BehaviorSubject(false);
|
|
1152
1921
|
this.draft$ = new BehaviorSubject(false);
|
|
1153
1922
|
this.canInitializeDocument$ = new BehaviorSubject(false);
|
|
1154
1923
|
this.startableByUser$ = new BehaviorSubject(false);
|
|
1155
1924
|
this.validationErrors$ = this.processManagementEditorService.validationErrors$;
|
|
1925
|
+
this.$markersVisible = signal(true);
|
|
1156
1926
|
this.testIds = PROCESS_MANAGEMENT_BUILDER_TEST_IDS;
|
|
1157
1927
|
this.selectedProcessDefinitionXml$ = this.processManagementEditorService.selectionProcessDefinition$.pipe(filter(selectedProcessDefinition => !!selectedProcessDefinition?.id), distinctUntilChanged((previous, current) => isEqual(previous, current)), tap(selectedProcessDefinition => {
|
|
1158
1928
|
this.loading$.next(true);
|
|
1159
1929
|
this.pageTitleService.setCustomPageTitle(selectedProcessDefinition?.name || '-');
|
|
1160
1930
|
}), switchMap(selectedProcessDefinition => this.processService.getProcessDefinitionXml(selectedProcessDefinition.id)), tap(result => {
|
|
1161
1931
|
this.cleanUpListenersOnModeler();
|
|
1162
|
-
this.
|
|
1163
|
-
this.
|
|
1164
|
-
this.
|
|
1932
|
+
this._autofilledElements = result.autofilledElements ?? [];
|
|
1933
|
+
this.processManagementEditorService.setAutofilledElements(this._autofilledElements);
|
|
1934
|
+
this._bpmnModeler?.importXML(result.bpmn20Xml).then(() => {
|
|
1935
|
+
this.highlightAutofilledElements();
|
|
1936
|
+
});
|
|
1937
|
+
this._bpmnViewer?.importXML(result.bpmn20Xml).then(() => {
|
|
1938
|
+
this.highlightAutofilledElements();
|
|
1939
|
+
});
|
|
1165
1940
|
this.isReadOnlyProcess$.next(result.readOnly);
|
|
1166
1941
|
this.isSystemProcess$.next(result.systemProcess);
|
|
1167
1942
|
this.loading$.next(false);
|
|
@@ -1228,8 +2003,9 @@ class ProcessManagementBuilderComponent {
|
|
|
1228
2003
|
if (!activityId || !businessId)
|
|
1229
2004
|
return;
|
|
1230
2005
|
this.processManagementEditorService.updateProcessLinksOnIdChange(activityId, businessId);
|
|
2006
|
+
this.scheduleActivityMarkerUpdate();
|
|
1231
2007
|
};
|
|
1232
|
-
this.iconService.registerAll([
|
|
2008
|
+
this.iconService.registerAll([View16, ViewOff16]);
|
|
1233
2009
|
this.setProcessManagementWindow();
|
|
1234
2010
|
}
|
|
1235
2011
|
ngAfterViewInit() {
|
|
@@ -1242,10 +2018,15 @@ class ProcessManagementBuilderComponent {
|
|
|
1242
2018
|
this.subscribeToProcessLinkUpdateEvents();
|
|
1243
2019
|
this.subscribeToProcessLinkCreateEvents();
|
|
1244
2020
|
this.subscribeToProcessLinkDeleteEvents();
|
|
2021
|
+
this.subscribeToAutofillDismissEvents();
|
|
1245
2022
|
this.initEditing();
|
|
1246
2023
|
}
|
|
1247
2024
|
ngOnDestroy() {
|
|
1248
2025
|
this.clearValidationErrors();
|
|
2026
|
+
this.clearActivityMarkers();
|
|
2027
|
+
if (this._activityMarkerUpdateTimeout) {
|
|
2028
|
+
clearTimeout(this._activityMarkerUpdateTimeout);
|
|
2029
|
+
}
|
|
1249
2030
|
this._bpmnModeler?.destroy();
|
|
1250
2031
|
this._bpmnViewer?.destroy();
|
|
1251
2032
|
this._subscriptions.unsubscribe();
|
|
@@ -1255,19 +2036,50 @@ class ProcessManagementBuilderComponent {
|
|
|
1255
2036
|
this.breadcrumbService.clearThirdBreadcrumb();
|
|
1256
2037
|
this.breadcrumbService.clearFourthBreadcrumb();
|
|
1257
2038
|
}
|
|
1258
|
-
|
|
2039
|
+
exportBpmn(isReadOnlyProcess) {
|
|
1259
2040
|
(isReadOnlyProcess ? from(this._bpmnViewer.saveXML()) : from(this._bpmnModeler.saveXML()))
|
|
1260
2041
|
.pipe(take(1))
|
|
1261
2042
|
.subscribe(result => {
|
|
1262
2043
|
const file = new Blob([result.xml ?? ''], { type: 'text/xml' });
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
2044
|
+
const processDefinitionKey = this.processManagementEditorService.selectionProcessDefinition?.key;
|
|
2045
|
+
this.downloadFile(file, processDefinitionKey ? `${processDefinitionKey}.bpmn` : 'diagram.bpmn');
|
|
2046
|
+
});
|
|
2047
|
+
}
|
|
2048
|
+
export() {
|
|
2049
|
+
const processDefinitionId = this.processManagementEditorService.selectionProcessDefinition?.id;
|
|
2050
|
+
if (!processDefinitionId) {
|
|
2051
|
+
this.showNotification('exportError');
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
this.processManagementService
|
|
2055
|
+
.exportProcessDefinition(processDefinitionId)
|
|
2056
|
+
.pipe(take(1))
|
|
2057
|
+
.subscribe({
|
|
2058
|
+
next: response => {
|
|
2059
|
+
const blob = response.body;
|
|
2060
|
+
if (!blob) {
|
|
2061
|
+
this.showNotification('exportError');
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
this.downloadFile(blob, this.getFileName(response));
|
|
2065
|
+
},
|
|
2066
|
+
error: () => {
|
|
2067
|
+
this.showNotification('exportError');
|
|
2068
|
+
},
|
|
1269
2069
|
});
|
|
1270
2070
|
}
|
|
2071
|
+
getFileName(response) {
|
|
2072
|
+
const contentDisposition = response.headers.get('Content-Disposition') ?? '';
|
|
2073
|
+
return contentDisposition.split('filename=')[1]?.replace(/"/g, '').trim() || 'process.zip';
|
|
2074
|
+
}
|
|
2075
|
+
downloadFile(file, fileName) {
|
|
2076
|
+
const link = document.createElement('a');
|
|
2077
|
+
link.download = fileName;
|
|
2078
|
+
link.href = window.URL.createObjectURL(file);
|
|
2079
|
+
link.click();
|
|
2080
|
+
window.URL.revokeObjectURL(link.href);
|
|
2081
|
+
link.remove();
|
|
2082
|
+
}
|
|
1271
2083
|
validateProcessDefinition(isReadOnlyProcess) {
|
|
1272
2084
|
combineLatest([
|
|
1273
2085
|
from(isReadOnlyProcess ? this._bpmnViewer.saveXML() : this._bpmnModeler.saveXML()),
|
|
@@ -1281,6 +2093,8 @@ class ProcessManagementBuilderComponent {
|
|
|
1281
2093
|
...link,
|
|
1282
2094
|
processDefinitionId: '-',
|
|
1283
2095
|
})),
|
|
2096
|
+
canInitializeDocument: this.canInitializeDocument$.getValue(),
|
|
2097
|
+
startableByUser: this.startableByUser$.getValue(),
|
|
1284
2098
|
});
|
|
1285
2099
|
}))
|
|
1286
2100
|
.subscribe({
|
|
@@ -1321,6 +2135,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1321
2135
|
.subscribe({
|
|
1322
2136
|
next: context => {
|
|
1323
2137
|
this.clearValidationErrors();
|
|
2138
|
+
this.processManagementEditorService.clearDismissedAutofills();
|
|
1324
2139
|
if (context === 'independent') {
|
|
1325
2140
|
this.reload();
|
|
1326
2141
|
this.showNotification('success');
|
|
@@ -1369,6 +2184,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1369
2184
|
.subscribe({
|
|
1370
2185
|
next: () => {
|
|
1371
2186
|
this.clearValidationErrors();
|
|
2187
|
+
this.processManagementEditorService.clearDismissedAutofills();
|
|
1372
2188
|
this.navigateBack('success');
|
|
1373
2189
|
},
|
|
1374
2190
|
error: (error) => {
|
|
@@ -1400,27 +2216,6 @@ class ProcessManagementBuilderComponent {
|
|
|
1400
2216
|
return;
|
|
1401
2217
|
this.showNotification(notification);
|
|
1402
2218
|
}
|
|
1403
|
-
onValidationErrorClick(elementId) {
|
|
1404
|
-
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
1405
|
-
const elementRegistry = modeler.get('elementRegistry');
|
|
1406
|
-
const canvas = modeler.get('canvas');
|
|
1407
|
-
const element = elementRegistry.get(elementId);
|
|
1408
|
-
if (!element)
|
|
1409
|
-
return;
|
|
1410
|
-
try {
|
|
1411
|
-
const selection = modeler.get('selection');
|
|
1412
|
-
selection?.select?.(element);
|
|
1413
|
-
}
|
|
1414
|
-
catch {
|
|
1415
|
-
// Viewer may not expose the selection service.
|
|
1416
|
-
}
|
|
1417
|
-
try {
|
|
1418
|
-
canvas.scrollToElement(element);
|
|
1419
|
-
}
|
|
1420
|
-
catch {
|
|
1421
|
-
// ignore
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
2219
|
onProcessToggleChange(field, value) {
|
|
1425
2220
|
if (field === 'draft')
|
|
1426
2221
|
this.draft$.next(value);
|
|
@@ -1440,7 +2235,6 @@ class ProcessManagementBuilderComponent {
|
|
|
1440
2235
|
this._pendingDeployAction = null;
|
|
1441
2236
|
}
|
|
1442
2237
|
validateAndDeploy(isReadOnlyProcess, deployAction) {
|
|
1443
|
-
// Skip validation for draft processes
|
|
1444
2238
|
if (this.draft$.getValue()) {
|
|
1445
2239
|
deployAction();
|
|
1446
2240
|
return;
|
|
@@ -1457,27 +2251,25 @@ class ProcessManagementBuilderComponent {
|
|
|
1457
2251
|
...link,
|
|
1458
2252
|
processDefinitionId: '-',
|
|
1459
2253
|
})),
|
|
2254
|
+
canInitializeDocument: this.canInitializeDocument$.getValue(),
|
|
2255
|
+
startableByUser: this.startableByUser$.getValue(),
|
|
1460
2256
|
});
|
|
1461
2257
|
}))
|
|
1462
2258
|
.subscribe({
|
|
1463
2259
|
next: validationResult => {
|
|
1464
2260
|
if (!validationResult.isValid) {
|
|
1465
|
-
// Has errors - show them and block deployment
|
|
1466
2261
|
this.highlightValidationErrors(validationResult.errors);
|
|
1467
2262
|
}
|
|
1468
2263
|
else if (validationResult.hasWarnings) {
|
|
1469
|
-
// Only warnings - show confirmation dialog
|
|
1470
2264
|
this.highlightValidationErrors(validationResult.errors);
|
|
1471
2265
|
this._pendingDeployAction = deployAction;
|
|
1472
2266
|
this.showWarningConfirmationModal$.next(true);
|
|
1473
2267
|
}
|
|
1474
2268
|
else {
|
|
1475
|
-
// No issues - proceed with deployment
|
|
1476
2269
|
deployAction();
|
|
1477
2270
|
}
|
|
1478
2271
|
},
|
|
1479
2272
|
error: () => {
|
|
1480
|
-
// Validation endpoint failed - proceed with deployment anyway (server will validate again)
|
|
1481
2273
|
deployAction();
|
|
1482
2274
|
},
|
|
1483
2275
|
});
|
|
@@ -1489,6 +2281,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1489
2281
|
processManagementWindow.processManagementEditorService = this.processManagementEditorService;
|
|
1490
2282
|
processManagementWindow.translateService = this.translateService;
|
|
1491
2283
|
processManagementWindow.pluginTranslationService = this.pluginTranslationService;
|
|
2284
|
+
processManagementWindow.processLinkService = this.processLinkService;
|
|
1492
2285
|
}
|
|
1493
2286
|
showNotification(notification) {
|
|
1494
2287
|
if (!notification)
|
|
@@ -1496,6 +2289,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1496
2289
|
let type;
|
|
1497
2290
|
if (notification === 'alreadyExists' ||
|
|
1498
2291
|
notification === 'validationError' ||
|
|
2292
|
+
notification === 'exportError' ||
|
|
1499
2293
|
notification === 'error') {
|
|
1500
2294
|
type = 'error';
|
|
1501
2295
|
}
|
|
@@ -1620,6 +2414,10 @@ class ProcessManagementBuilderComponent {
|
|
|
1620
2414
|
};
|
|
1621
2415
|
eventBus.on('element.hover', this._validationHoverHandler);
|
|
1622
2416
|
eventBus.on('element.out', this._validationOutHandler);
|
|
2417
|
+
this._selectionChangedHandler = (event) => {
|
|
2418
|
+
this.highlightInvalidFieldsInPropertiesPanel(event.newSelection, errors);
|
|
2419
|
+
};
|
|
2420
|
+
eventBus.on('selection.changed', this._selectionChangedHandler);
|
|
1623
2421
|
const selection = modeler.get('selection');
|
|
1624
2422
|
const selected = selection.get();
|
|
1625
2423
|
if (selected?.length > 0) {
|
|
@@ -1628,6 +2426,86 @@ class ProcessManagementBuilderComponent {
|
|
|
1628
2426
|
selection.select(current);
|
|
1629
2427
|
}
|
|
1630
2428
|
}
|
|
2429
|
+
highlightInvalidFieldsInPropertiesPanel(newSelection, errors) {
|
|
2430
|
+
document.querySelectorAll('.validation-error-field').forEach(el => {
|
|
2431
|
+
el.classList.remove('validation-error-field');
|
|
2432
|
+
});
|
|
2433
|
+
document.querySelectorAll('.validation-error-param').forEach(el => {
|
|
2434
|
+
el.classList.remove('validation-error-param');
|
|
2435
|
+
});
|
|
2436
|
+
if (!newSelection?.length)
|
|
2437
|
+
return;
|
|
2438
|
+
const selectedId = newSelection[0]?.id;
|
|
2439
|
+
if (!selectedId)
|
|
2440
|
+
return;
|
|
2441
|
+
const elementErrors = errors.filter(e => e.elementId === selectedId);
|
|
2442
|
+
setTimeout(() => {
|
|
2443
|
+
for (const error of elementErrors) {
|
|
2444
|
+
const listenerEntryId = error.listenerType != null && error.listenerIndex != null
|
|
2445
|
+
? `${selectedId}-${error.listenerType}-${error.listenerIndex}`
|
|
2446
|
+
: null;
|
|
2447
|
+
if (error.invalidFields) {
|
|
2448
|
+
for (const fieldId of error.invalidFields) {
|
|
2449
|
+
let entry = null;
|
|
2450
|
+
if (listenerEntryId) {
|
|
2451
|
+
const listenerEntry = document.querySelector(`[data-entry-id="${listenerEntryId}"]`);
|
|
2452
|
+
if (listenerEntry) {
|
|
2453
|
+
entry = listenerEntry.querySelector(`[data-entry-id="${fieldId}"]`);
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
if (!entry) {
|
|
2457
|
+
entry = document.querySelector(`[data-entry-id="${fieldId}"]`);
|
|
2458
|
+
}
|
|
2459
|
+
if (entry) {
|
|
2460
|
+
entry.classList.add('validation-error-field');
|
|
2461
|
+
const input = entry.querySelector('input, textarea, select');
|
|
2462
|
+
if (input) {
|
|
2463
|
+
const handler = () => {
|
|
2464
|
+
entry.classList.remove('validation-error-field');
|
|
2465
|
+
input.removeEventListener('input', handler);
|
|
2466
|
+
input.removeEventListener('change', handler);
|
|
2467
|
+
};
|
|
2468
|
+
input.addEventListener('input', handler);
|
|
2469
|
+
input.addEventListener('change', handler);
|
|
2470
|
+
this._fieldInputCleanupFns.push(() => {
|
|
2471
|
+
input.removeEventListener('input', handler);
|
|
2472
|
+
input.removeEventListener('change', handler);
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
if (error.invalidArguments && error.invalidArguments.length > 0) {
|
|
2479
|
+
let scopeElement = null;
|
|
2480
|
+
if (listenerEntryId) {
|
|
2481
|
+
scopeElement = document.querySelector(`[data-entry-id="${listenerEntryId}"]`);
|
|
2482
|
+
}
|
|
2483
|
+
const wrapper = scopeElement
|
|
2484
|
+
? scopeElement.querySelector('.expression-editor-wrapper')
|
|
2485
|
+
: document.querySelector('.expression-editor-wrapper');
|
|
2486
|
+
if (wrapper) {
|
|
2487
|
+
wrapper.dataset.invalidArgs = JSON.stringify(error.invalidArguments);
|
|
2488
|
+
}
|
|
2489
|
+
for (const idx of error.invalidArguments) {
|
|
2490
|
+
const paramInput = scopeElement
|
|
2491
|
+
? scopeElement.querySelector(`.expression-editor-param input[data-param-index="${idx}"]`)
|
|
2492
|
+
: document.querySelector(`.expression-editor-param input[data-param-index="${idx}"]`);
|
|
2493
|
+
if (paramInput) {
|
|
2494
|
+
paramInput.classList.add('validation-error-param');
|
|
2495
|
+
const handler = () => {
|
|
2496
|
+
paramInput.classList.remove('validation-error-param');
|
|
2497
|
+
paramInput.removeEventListener('input', handler);
|
|
2498
|
+
};
|
|
2499
|
+
paramInput.addEventListener('input', handler);
|
|
2500
|
+
this._fieldInputCleanupFns.push(() => {
|
|
2501
|
+
paramInput.removeEventListener('input', handler);
|
|
2502
|
+
});
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
}, 50);
|
|
2508
|
+
}
|
|
1631
2509
|
clearValidationErrors() {
|
|
1632
2510
|
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
1633
2511
|
if (!modeler)
|
|
@@ -1644,6 +2522,21 @@ class ProcessManagementBuilderComponent {
|
|
|
1644
2522
|
eventBus.off('element.out', this._validationOutHandler);
|
|
1645
2523
|
this._validationOutHandler = null;
|
|
1646
2524
|
}
|
|
2525
|
+
if (this._selectionChangedHandler) {
|
|
2526
|
+
eventBus.off('selection.changed', this._selectionChangedHandler);
|
|
2527
|
+
this._selectionChangedHandler = null;
|
|
2528
|
+
}
|
|
2529
|
+
this._fieldInputCleanupFns.forEach(fn => fn());
|
|
2530
|
+
this._fieldInputCleanupFns = [];
|
|
2531
|
+
document.querySelectorAll('.validation-error-field').forEach(el => {
|
|
2532
|
+
el.classList.remove('validation-error-field');
|
|
2533
|
+
});
|
|
2534
|
+
document.querySelectorAll('.validation-error-param').forEach(el => {
|
|
2535
|
+
el.classList.remove('validation-error-param');
|
|
2536
|
+
});
|
|
2537
|
+
document.querySelectorAll('.expression-editor-wrapper[data-invalid-args]').forEach(el => {
|
|
2538
|
+
delete el.dataset.invalidArgs;
|
|
2539
|
+
});
|
|
1647
2540
|
for (const elementId of this._validationErrorElementIds) {
|
|
1648
2541
|
try {
|
|
1649
2542
|
canvas.removeMarker(elementId, 'highlight-overlay-error');
|
|
@@ -1661,6 +2554,209 @@ class ProcessManagementBuilderComponent {
|
|
|
1661
2554
|
// ignore
|
|
1662
2555
|
}
|
|
1663
2556
|
}
|
|
2557
|
+
highlightAutofilledElements() {
|
|
2558
|
+
this.clearAutofilledHighlights();
|
|
2559
|
+
if (!this._autofilledElements?.length)
|
|
2560
|
+
return;
|
|
2561
|
+
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
2562
|
+
if (!modeler)
|
|
2563
|
+
return;
|
|
2564
|
+
const overlays = modeler.get('overlays');
|
|
2565
|
+
for (const element of this._autofilledElements) {
|
|
2566
|
+
try {
|
|
2567
|
+
this._autofilledElementIds.push(element.activityId);
|
|
2568
|
+
const tooltipText = this.getAutofilledTooltip();
|
|
2569
|
+
overlays.add(element.activityId, 'autofilled-indicator', {
|
|
2570
|
+
position: { top: -12, left: -12 },
|
|
2571
|
+
html: this.buildAutofilledOverlayElement(element.activityId, tooltipText),
|
|
2572
|
+
});
|
|
2573
|
+
}
|
|
2574
|
+
catch (e) {
|
|
2575
|
+
// Element may not exist on the canvas
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
clearAutofilledHighlights() {
|
|
2580
|
+
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
2581
|
+
if (!modeler)
|
|
2582
|
+
return;
|
|
2583
|
+
const overlays = modeler.get('overlays');
|
|
2584
|
+
this._autofilledElementIds = [];
|
|
2585
|
+
try {
|
|
2586
|
+
overlays.remove({ type: 'autofilled-indicator' });
|
|
2587
|
+
}
|
|
2588
|
+
catch (e) {
|
|
2589
|
+
// ignore
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
buildAutofilledOverlayElement(elementId, tooltipText) {
|
|
2593
|
+
const container = document.createElement('div');
|
|
2594
|
+
container.className = 'autofilled-indicator-overlay';
|
|
2595
|
+
container.dataset.elementId = elementId;
|
|
2596
|
+
const icon = document.createElement('span');
|
|
2597
|
+
icon.className = 'autofilled-indicator-icon';
|
|
2598
|
+
icon.innerHTML = '!';
|
|
2599
|
+
container.appendChild(icon);
|
|
2600
|
+
const tooltip = document.createElement('span');
|
|
2601
|
+
tooltip.className = 'autofilled-indicator-tooltip';
|
|
2602
|
+
tooltip.textContent = tooltipText;
|
|
2603
|
+
container.appendChild(tooltip);
|
|
2604
|
+
return container;
|
|
2605
|
+
}
|
|
2606
|
+
getAutofilledTooltip() {
|
|
2607
|
+
return this.translateService.instant('processManagement.autofilled.generic');
|
|
2608
|
+
}
|
|
2609
|
+
getElementListeners(element) {
|
|
2610
|
+
const extensionElements = element?.businessObject?.extensionElements;
|
|
2611
|
+
const values = extensionElements?.values || [];
|
|
2612
|
+
const executionListeners = values.filter((v) => v.$type === 'camunda:ExecutionListener');
|
|
2613
|
+
const taskListeners = values.filter((v) => v.$type === 'camunda:TaskListener');
|
|
2614
|
+
return {
|
|
2615
|
+
hasExecutionListener: executionListeners.length > 0,
|
|
2616
|
+
hasTaskListener: taskListeners.length > 0,
|
|
2617
|
+
executionListenerCount: executionListeners.length,
|
|
2618
|
+
taskListenerCount: taskListeners.length,
|
|
2619
|
+
};
|
|
2620
|
+
}
|
|
2621
|
+
toggleMarkerVisibility() {
|
|
2622
|
+
this.$markersVisible.update(v => !v);
|
|
2623
|
+
if (this.$markersVisible()) {
|
|
2624
|
+
this.updateActivityMarkers();
|
|
2625
|
+
}
|
|
2626
|
+
else {
|
|
2627
|
+
this.clearActivityMarkers();
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
updateActivityMarkers() {
|
|
2631
|
+
this.clearActivityMarkers();
|
|
2632
|
+
if (!this.$markersVisible())
|
|
2633
|
+
return;
|
|
2634
|
+
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
2635
|
+
if (!modeler)
|
|
2636
|
+
return;
|
|
2637
|
+
const overlays = modeler.get('overlays');
|
|
2638
|
+
const elementRegistry = modeler.get('elementRegistry');
|
|
2639
|
+
const processLinks = this.processManagementEditorService.processLinksForSelectedDefinition;
|
|
2640
|
+
const processLinkActivityIds = new Set(processLinks.map(pl => pl.activityId));
|
|
2641
|
+
const elementMarkers = new Map();
|
|
2642
|
+
elementRegistry.forEach((element) => {
|
|
2643
|
+
if (!element.id || element.type === 'label')
|
|
2644
|
+
return;
|
|
2645
|
+
const listeners = this.getElementListeners(element);
|
|
2646
|
+
const hasProcessLink = processLinkActivityIds.has(element.id);
|
|
2647
|
+
if (listeners.hasExecutionListener || listeners.hasTaskListener || hasProcessLink) {
|
|
2648
|
+
elementMarkers.set(element.id, {
|
|
2649
|
+
hasExecutionListener: listeners.hasExecutionListener,
|
|
2650
|
+
hasTaskListener: listeners.hasTaskListener,
|
|
2651
|
+
hasProcessLink,
|
|
2652
|
+
executionListenerCount: listeners.executionListenerCount,
|
|
2653
|
+
taskListenerCount: listeners.taskListenerCount,
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
});
|
|
2657
|
+
for (const [elementId, info] of elementMarkers) {
|
|
2658
|
+
this._activityMarkerElementIds.push(elementId);
|
|
2659
|
+
const badges = this.buildActivityMarkerBadges(info, elementId);
|
|
2660
|
+
if (badges) {
|
|
2661
|
+
try {
|
|
2662
|
+
const element = elementRegistry.get(elementId);
|
|
2663
|
+
const position = this.calculateMarkerPosition(element);
|
|
2664
|
+
overlays.add(elementId, 'activity-marker', {
|
|
2665
|
+
position,
|
|
2666
|
+
html: badges,
|
|
2667
|
+
});
|
|
2668
|
+
}
|
|
2669
|
+
catch (e) {
|
|
2670
|
+
// Element may not exist on canvas
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
calculateMarkerPosition(element) {
|
|
2676
|
+
if (element?.waypoints?.length > 1) {
|
|
2677
|
+
const waypoints = element.waypoints;
|
|
2678
|
+
const lastPoint = waypoints[waypoints.length - 1];
|
|
2679
|
+
const secondLastPoint = waypoints[waypoints.length - 2];
|
|
2680
|
+
// Compute bounding box from waypoints (same as diagram-js getBBox)
|
|
2681
|
+
const minX = Math.min(...waypoints.map((wp) => wp.x));
|
|
2682
|
+
const minY = Math.min(...waypoints.map((wp) => wp.y));
|
|
2683
|
+
// Direction of the final segment
|
|
2684
|
+
const dx = lastPoint.x - secondLastPoint.x;
|
|
2685
|
+
const dy = lastPoint.y - secondLastPoint.y;
|
|
2686
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
2687
|
+
// Offset back from arrow tip along the line
|
|
2688
|
+
const backOffset = 30;
|
|
2689
|
+
const backX = len > 0 ? (-dx / len) * backOffset : 0;
|
|
2690
|
+
const backY = len > 0 ? (-dy / len) * backOffset : 0;
|
|
2691
|
+
// Perpendicular offset: above for horizontal lines, right for vertical lines
|
|
2692
|
+
const perpOffset = 20;
|
|
2693
|
+
const isMoreHorizontal = Math.abs(dx) > Math.abs(dy);
|
|
2694
|
+
const perpX = isMoreHorizontal ? 0 : perpOffset;
|
|
2695
|
+
const perpY = isMoreHorizontal ? -perpOffset : 0;
|
|
2696
|
+
return {
|
|
2697
|
+
top: lastPoint.y - minY + backY + perpY - 11,
|
|
2698
|
+
left: lastPoint.x - minX + backX + perpX - 11,
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
return { top: -12, right: 12 };
|
|
2702
|
+
}
|
|
2703
|
+
buildActivityMarkerBadges(info, elementId) {
|
|
2704
|
+
const container = document.createElement('div');
|
|
2705
|
+
container.className = 'activity-marker-overlay';
|
|
2706
|
+
container.dataset.elementId = elementId;
|
|
2707
|
+
if (info.hasProcessLink) {
|
|
2708
|
+
const tooltip = this.translateService.instant('processManagement.markers.processLink');
|
|
2709
|
+
container.appendChild(this.buildMarkerBadge('process-link', 'P', tooltip));
|
|
2710
|
+
}
|
|
2711
|
+
if (info.hasExecutionListener) {
|
|
2712
|
+
const countSuffix = info.executionListenerCount > 1 ? ` (${info.executionListenerCount})` : '';
|
|
2713
|
+
const tooltip = this.translateService.instant('processManagement.markers.executionListener') + countSuffix;
|
|
2714
|
+
container.appendChild(this.buildMarkerBadge('execution-listener', 'E', tooltip));
|
|
2715
|
+
}
|
|
2716
|
+
if (info.hasTaskListener) {
|
|
2717
|
+
const countSuffix = info.taskListenerCount > 1 ? ` (${info.taskListenerCount})` : '';
|
|
2718
|
+
const tooltip = this.translateService.instant('processManagement.markers.taskListener') + countSuffix;
|
|
2719
|
+
container.appendChild(this.buildMarkerBadge('task-listener', 'T', tooltip));
|
|
2720
|
+
}
|
|
2721
|
+
if (container.children.length === 0)
|
|
2722
|
+
return null;
|
|
2723
|
+
return container;
|
|
2724
|
+
}
|
|
2725
|
+
buildMarkerBadge(type, label, tooltip) {
|
|
2726
|
+
const badge = document.createElement('div');
|
|
2727
|
+
badge.className = `activity-marker-badge activity-marker-badge--${type}`;
|
|
2728
|
+
const icon = document.createElement('span');
|
|
2729
|
+
icon.className = 'activity-marker-badge__icon';
|
|
2730
|
+
icon.textContent = label;
|
|
2731
|
+
badge.appendChild(icon);
|
|
2732
|
+
const text = document.createElement('span');
|
|
2733
|
+
text.className = 'activity-marker-badge__text';
|
|
2734
|
+
text.textContent = tooltip;
|
|
2735
|
+
badge.appendChild(text);
|
|
2736
|
+
return badge;
|
|
2737
|
+
}
|
|
2738
|
+
clearActivityMarkers() {
|
|
2739
|
+
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
2740
|
+
if (!modeler)
|
|
2741
|
+
return;
|
|
2742
|
+
const overlays = modeler.get('overlays');
|
|
2743
|
+
this._activityMarkerElementIds = [];
|
|
2744
|
+
try {
|
|
2745
|
+
overlays.remove({ type: 'activity-marker' });
|
|
2746
|
+
}
|
|
2747
|
+
catch (e) {
|
|
2748
|
+
// ignore
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
scheduleActivityMarkerUpdate() {
|
|
2752
|
+
if (this._activityMarkerUpdateTimeout) {
|
|
2753
|
+
clearTimeout(this._activityMarkerUpdateTimeout);
|
|
2754
|
+
}
|
|
2755
|
+
this._activityMarkerUpdateTimeout = setTimeout(() => {
|
|
2756
|
+
this.updateActivityMarkers();
|
|
2757
|
+
this._activityMarkerUpdateTimeout = null;
|
|
2758
|
+
}, 300);
|
|
2759
|
+
}
|
|
1664
2760
|
setSelectedProcessDefinitionToLatest(processDefinitions) {
|
|
1665
2761
|
const latest = getLatestProcessDefinition(processDefinitions);
|
|
1666
2762
|
if (!latest)
|
|
@@ -1675,11 +2771,16 @@ class ProcessManagementBuilderComponent {
|
|
|
1675
2771
|
CamundaPlatformPropertiesProviderModule,
|
|
1676
2772
|
camundaPlatformBehaviors,
|
|
1677
2773
|
ValtimoPropertiesProviderModule,
|
|
2774
|
+
ExpressionAutocompleteModule,
|
|
1678
2775
|
],
|
|
1679
2776
|
moddleExtensions: { camunda: CamundaBpmnModdle },
|
|
1680
2777
|
propertiesPanel: { parent: this.modelerPanelElementRef.nativeElement },
|
|
1681
2778
|
});
|
|
1682
2779
|
this._bpmnModeler?.attachTo(this.modelerElementRef.nativeElement);
|
|
2780
|
+
// Initialize expression autocomplete
|
|
2781
|
+
this._expressionAutocomplete = this._bpmnModeler.get('expressionAutocomplete');
|
|
2782
|
+
this._expressionAutocomplete?.setPanelContainer(this.modelerPanelElementRef.nativeElement);
|
|
2783
|
+
this.loadProcessBeansForAutocomplete();
|
|
1683
2784
|
this._bpmnModeler.on('commandStack.changed', () => {
|
|
1684
2785
|
this.changesPending$.next(true);
|
|
1685
2786
|
});
|
|
@@ -1695,6 +2796,17 @@ class ProcessManagementBuilderComponent {
|
|
|
1695
2796
|
});
|
|
1696
2797
|
this.processManagementEditorService.setActivityIdBusinessIdMap(idMap);
|
|
1697
2798
|
this.listenToActivityChangesOnModeler();
|
|
2799
|
+
this.updateActivityMarkers();
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2802
|
+
loadProcessBeansForAutocomplete() {
|
|
2803
|
+
this.processBeanService.getProcessBeans().subscribe({
|
|
2804
|
+
next: beans => {
|
|
2805
|
+
this._expressionAutocomplete?.setProcessBeans(beans);
|
|
2806
|
+
},
|
|
2807
|
+
error: err => {
|
|
2808
|
+
this.logger.warn('Failed to load process beans for autocomplete', err);
|
|
2809
|
+
},
|
|
1698
2810
|
});
|
|
1699
2811
|
}
|
|
1700
2812
|
initViewer() {
|
|
@@ -1713,6 +2825,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1713
2825
|
});
|
|
1714
2826
|
this._bpmnViewer.on('import.done', () => {
|
|
1715
2827
|
disableCommands(this._bpmnViewer);
|
|
2828
|
+
this.updateActivityMarkers();
|
|
1716
2829
|
});
|
|
1717
2830
|
}
|
|
1718
2831
|
reload() {
|
|
@@ -1763,6 +2876,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1763
2876
|
this.processManagementEditorService.createProcessLink(event);
|
|
1764
2877
|
this.processLinkStateService.stopSaving();
|
|
1765
2878
|
this.processLinkStateService.closeModal();
|
|
2879
|
+
this.updateActivityMarkers();
|
|
1766
2880
|
const buildingBlockProcessLinkCreateDto = event;
|
|
1767
2881
|
if (buildingBlockProcessLinkCreateDto.buildingBlockDefinitionKey &&
|
|
1768
2882
|
buildingBlockProcessLinkCreateDto.buildingBlockDefinitionVersionTag) {
|
|
@@ -1775,9 +2889,31 @@ class ProcessManagementBuilderComponent {
|
|
|
1775
2889
|
this.processManagementEditorService.deleteProcessLink(event);
|
|
1776
2890
|
this.processLinkStateService.stopSaving();
|
|
1777
2891
|
this.processLinkStateService.closeModal();
|
|
2892
|
+
this.updateActivityMarkers();
|
|
1778
2893
|
this.unsetCalledElementForBuildingBlockProcessLink(event.activityId);
|
|
1779
2894
|
}));
|
|
1780
2895
|
}
|
|
2896
|
+
subscribeToAutofillDismissEvents() {
|
|
2897
|
+
this._subscriptions.add(this.processManagementEditorService.autofillDismissed$.subscribe(activityId => {
|
|
2898
|
+
this.removeAutofillOverlay(activityId);
|
|
2899
|
+
}));
|
|
2900
|
+
}
|
|
2901
|
+
removeAutofillOverlay(activityId) {
|
|
2902
|
+
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
2903
|
+
if (!modeler)
|
|
2904
|
+
return;
|
|
2905
|
+
const overlays = modeler.get('overlays');
|
|
2906
|
+
try {
|
|
2907
|
+
overlays.remove({ element: activityId, type: 'autofilled-indicator' });
|
|
2908
|
+
}
|
|
2909
|
+
catch (e) {
|
|
2910
|
+
// ignore
|
|
2911
|
+
}
|
|
2912
|
+
const idx = this._autofilledElementIds.indexOf(activityId);
|
|
2913
|
+
if (idx > -1) {
|
|
2914
|
+
this._autofilledElementIds.splice(idx, 1);
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
1781
2917
|
initIfCreate() {
|
|
1782
2918
|
if (this._selectedProcess$.getValue() !== 'create')
|
|
1783
2919
|
return;
|
|
@@ -1809,12 +2945,17 @@ class ProcessManagementBuilderComponent {
|
|
|
1809
2945
|
.subscribe(result => {
|
|
1810
2946
|
const processDefinitionResult = result;
|
|
1811
2947
|
this.cleanUpListenersOnModeler();
|
|
1812
|
-
this.
|
|
1813
|
-
this.
|
|
1814
|
-
this.
|
|
1815
|
-
this.
|
|
2948
|
+
this._autofilledElements = processDefinitionResult.autofilledElements ?? [];
|
|
2949
|
+
this.processManagementEditorService.setAutofilledElements(this._autofilledElements);
|
|
2950
|
+
this._bpmnModeler?.importXML(processDefinitionResult.bpmn20Xml).then(() => {
|
|
2951
|
+
this.highlightAutofilledElements();
|
|
2952
|
+
});
|
|
2953
|
+
this._bpmnViewer?.importXML(processDefinitionResult.bpmn20Xml).then(() => {
|
|
2954
|
+
this.highlightAutofilledElements();
|
|
2955
|
+
});
|
|
1816
2956
|
this.canInitializeDocument$.next(!!processDefinitionResult?.processCaseLink?.canInitializeDocument);
|
|
1817
2957
|
this.startableByUser$.next(!!processDefinitionResult?.processCaseLink?.startableByUser);
|
|
2958
|
+
this.draft$.next(!!processDefinitionResult?.draft);
|
|
1818
2959
|
this.loading$.next(false);
|
|
1819
2960
|
}));
|
|
1820
2961
|
}
|
|
@@ -1889,11 +3030,22 @@ class ProcessManagementBuilderComponent {
|
|
|
1889
3030
|
}
|
|
1890
3031
|
clearBuildingBlockCalledElement(editor, activityId);
|
|
1891
3032
|
}
|
|
3033
|
+
onValidationErrorClick(elementId) {
|
|
3034
|
+
const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
|
|
3035
|
+
const canvas = modeler.get('canvas');
|
|
3036
|
+
const selection = modeler.get('selection');
|
|
3037
|
+
const elementRegistry = modeler.get('elementRegistry');
|
|
3038
|
+
const element = elementRegistry.get(elementId);
|
|
3039
|
+
if (!element)
|
|
3040
|
+
return;
|
|
3041
|
+
canvas.scrollToElement(element, { top: 100, bottom: 100, left: 100, right: 100 });
|
|
3042
|
+
selection.select(element);
|
|
3043
|
+
}
|
|
1892
3044
|
getValidationErrorMessage(error) {
|
|
1893
3045
|
if (error.errorCode) {
|
|
1894
|
-
const translationKey = `processManagement.
|
|
3046
|
+
const translationKey = `processManagement.validationErrorCodes.${error.errorCode}`;
|
|
1895
3047
|
const translated = this.translateService.instant(translationKey, {
|
|
1896
|
-
expression: error.expression
|
|
3048
|
+
expression: error.expression ?? '',
|
|
1897
3049
|
});
|
|
1898
3050
|
if (translated !== translationKey) {
|
|
1899
3051
|
return translated;
|
|
@@ -1915,13 +3067,13 @@ class ProcessManagementBuilderComponent {
|
|
|
1915
3067
|
container.appendChild(text);
|
|
1916
3068
|
return container;
|
|
1917
3069
|
}
|
|
1918
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementBuilderComponent, deps: [{ token: i1$1.BreadcrumbService }, { token: i2$2.IconService }, { token: i3.NGXLogger }, { token: i1$1.ModalService }, { token: i2
|
|
3070
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementBuilderComponent, deps: [{ token: i1$1.BreadcrumbService }, { token: i2$2.IconService }, { token: i3.NGXLogger }, { token: i1$1.ModalService }, { token: i2.GlobalNotificationService }, { token: i1$1.PageHeaderService }, { token: i1$1.PageTitleService }, { token: i5.ProcessLinkService }, { token: i5.ProcessLinkStateService }, { token: ProcessManagementEditorService }, { token: ProcessManagementService }, { token: i7.ProcessService }, { token: i8.ActivatedRoute }, { token: i8.Router }, { token: i9.TranslateService }, { token: i10.PluginTranslationService }, { token: i2.EditPermissionsService }, { token: i5.ProcessLinkBuildingBlockApiService }, { token: ProcessBeanService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1919
3071
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: ProcessManagementBuilderComponent, isStandalone: true, selector: "valtimo-process-management-builder", providers: [
|
|
1920
3072
|
ProcessManagementEditorService,
|
|
1921
3073
|
ProcessLinkStateService,
|
|
1922
3074
|
ProcessLinkStepService,
|
|
1923
3075
|
ProcessLinkButtonService,
|
|
1924
|
-
], viewQueries: [{ propertyName: "modelerElementRef", first: true, predicate: ["modeler"], descendants: true }, { propertyName: "modelerPanelElementRef", first: true, predicate: ["modelerPanel"], descendants: true }, { propertyName: "viewerElementRef", first: true, predicate: ["viewer"], descendants: true }, { propertyName: "viewerPanelElementRef", first: true, predicate: ["viewerPanel"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n fitPage\n [disableOverflow]=\"true\"\n *ngIf=\"{\n processDefinitionVersions: processDefinitionVersions$ | async,\n selectedProcessDefinitionXml: selectedProcessDefinitionXml$ | async,\n loading: loading$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n } as obs\"\n data-carbon-theme=\"g10\"\n class=\"bpmn__container\"\n>\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'none' : 'flex'\"\n >\n <div class=\"bpmn__modeler-canvas\" #modeler>\n <div\n class=\"validation-errors-list\"\n *ngIf=\"validationErrors$ | async as validationErrors\"\n [style.display]=\"validationErrors.length > 0 ? '' : 'none'\"\n >\n <details open>\n <summary class=\"validation-errors-list__header\">\n <span>{{\n 'processManagement.validationErrorsCount'\n | translate: {count: validationErrors.length}\n }}</span>\n <svg\n class=\"validation-errors-list__arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8Z\"\n />\n </svg>\n </summary>\n\n <div class=\"validation-errors-list__items\">\n <button\n *ngFor=\"let error of validationErrors\"\n class=\"validation-errors-list__item\"\n [class.warning]=\"error.severity === 'WARNING'\"\n (click)=\"onValidationErrorClick(error.elementId)\"\n >\n <span\n class=\"validation-errors-list__icon\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ error.severity === 'WARNING' ? '!' : '!' }}</span\n >\n\n <span class=\"validation-errors-list__details\">\n <span class=\"validation-errors-list__element\">{{\n error.elementName || error.elementId\n }}</span>\n\n <span\n class=\"validation-errors-list__reason\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ getValidationErrorMessage(error) }}</span\n >\n </span>\n </button>\n </div>\n </details>\n </div>\n </div>\n\n <div class=\"bpmn__modeler-panel\" #modelerPanel></div>\n </div>\n\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'flex' : 'none'\"\n >\n <div class=\"bpmn__modeler-canvas\" #viewer></div>\n\n <div class=\"bpmn__modeler-panel\" #viewerPanel></div>\n </div>\n</div>\n\n<valtimo-process-link-modal></valtimo-process-link-modal>\n\n<valtimo-confirmation-modal\n [showModalSubject$]=\"showWarningConfirmationModal$\"\n [titleTranslationKey]=\"'processManagement.warningConfirmation.title'\"\n [contentTranslationKey]=\"'processManagement.warningConfirmation.content'\"\n [confirmButtonTextTranslationKey]=\"'processManagement.warningConfirmation.confirm'\"\n [cancelButtonTextTranslationKey]=\"'interface.cancel'\"\n (confirmEvent)=\"onWarningConfirmationConfirm()\"\n (cancelEvent)=\"onWarningConfirmationCancel()\"\n></valtimo-confirmation-modal>\n\n<ng-container renderInPageHeader [fullWidth]=\"true\">\n <ng-template>\n <div\n class=\"page-header-actions\"\n *ngIf=\"{\n processDefinitionVersionsListItems: processDefinitionVersionsListItems$ | async,\n loading: loading$ | async,\n changesPending: changesPending$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n isSystemProcess: isSystemProcess$ | async,\n compactMode: compactMode$ | async,\n creatingNewProcess: creatingNewProcess$ | async,\n context: context$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n draft: draft$ | async,\n canInitializeDocument: canInitializeDocument$ | async,\n startableByUser: startableByUser$ | async,\n updatingProcessDefinitionCaseDefinition: updatingProcessDefinitionCaseDefinition$ | async,\n } as actionsObs\"\n >\n <div class=\"page-header-actions__left-container\">\n <cds-dropdown\n *ngIf=\"!actionsObs.creatingNewProcess && actionsObs?.context === 'independent'\"\n class=\"page-header-actions__version-dropdown\"\n (selected)=\"selectedVersionChange($event)\"\n [disabled]=\"\n actionsObs.loading ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 0 ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 1\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n >\n <cds-dropdown-list\n [items]=\"actionsObs.processDefinitionVersionsListItems || []\"\n ></cds-dropdown-list>\n </cds-dropdown>\n\n <div\n class=\"page-header-actions__tags\"\n *ngIf=\"\n actionsObs.isReadOnlyProcess ||\n !actionsObs.hasEditPermissions ||\n actionsObs.isSystemProcess\n \"\n >\n <cds-tag\n *ngIf=\"actionsObs.isReadOnlyProcess || !actionsObs.hasEditPermissions\"\n type=\"blue\"\n >{{ 'processManagement.readOnly' | translate }}</cds-tag\n >\n\n <cds-tag *ngIf=\"actionsObs.isSystemProcess\" type=\"red\">{{\n 'processManagement.systemProcess' | translate\n }}</cds-tag>\n </div>\n\n <div class=\"page-header-actions__toggles\">\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.draftTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.draft' | translate\"\n [offText]=\"'processManagement.draft' | translate\"\n [checked]=\"actionsObs.draft\"\n [disabled]=\"actionsObs.loading || !actionsObs.hasEditPermissions\"\n (checkedChange)=\"onProcessToggleChange('draft', $event)\"\n [attr.data-test-id]=\"testIds.draftToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n @if (actionsObs.context === 'case') {\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.processCreatesCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.canInitializeDocument' | translate\"\n [offText]=\"'processManagement.canInitializeDocument' | translate\"\n [checked]=\"actionsObs.canInitializeDocument\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('canInitializeDocument', $event)\"\n [attr.data-test-id]=\"testIds.startsCaseToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.startableWithinCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.startableByUser' | translate\"\n [offText]=\"'processManagement.startableByUser' | translate\"\n [checked]=\"actionsObs.startableByUser\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('startableByUser', $event)\"\n [attr.data-test-id]=\"testIds.startableByUserToggle\"\n ></cds-toggle\n ></cds-tooltip>\n }\n </div>\n </div>\n\n <div class=\"page-header-actions__buttons\">\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option\n [disabled]=\"actionsObs.loading\"\n (selected)=\"export(actionsObs.isReadOnlyProcess)\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n\n <button\n *ngIf=\"actionsObs.context === 'case'\"\n cdsButton=\"tertiary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n >\n {{ 'interface.back' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"return\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"secondary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [disabled]=\"actionsObs.loading\"\n (click)=\"validateProcessDefinition(actionsObs.isReadOnlyProcess)\"\n >\n {{ 'processManagement.validate' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"list--checked\" size=\"16\"></svg>\n </button>\n\n <button\n [disabled]=\"!actionsObs.changesPending\"\n cdsButton=\"primary\"\n (click)=\"\n !actionsObs.creatingNewProcess\n ? deployChanges(actionsObs.isReadOnlyProcess)\n : deployNewProcessDefinition()\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'processManagement.deploy' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"deploy\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n </ng-template>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;gap:24px}.bpmn__container{position:relative;background-color:var(--cds-layer);width:100%}.bpmn__modeler{width:100%;height:100%;flex-direction:row;padding:1px;box-sizing:border-box;outline:1px solid var(--cds-border-subtle);outline-offset:-1px}.bpmn__modeler ::ng-deep .djs-container>svg{outline:none!important}.bpmn__modeler-canvas{width:100%;position:relative}.bpmn__modeler-panel{width:481px;padding-left:1px;box-shadow:inset 1px 0 0 0 var(--cds-border-subtle);box-sizing:border-box}.bpmn__loading{width:100%;height:100%;display:flex;justify-content:center;align-items:center;background-color:var(--cds-background-selected)}.page-header-actions{display:flex;width:100%;justify-content:space-between;align-items:center;gap:16px}.page-header-actions__left-container{display:flex;gap:16px;align-items:center}.page-header-actions__tags{display:flex;gap:8px;align-items:center}.page-header-actions__version-dropdown{width:150px}.page-header-actions__toggles{display:flex;gap:16px;align-items:center}.page-header-actions__toggles ::ng-deep cds-toggle{display:inline-flex;align-items:center}.page-header-actions__toggles ::ng-deep .cds--toggle__label-text{display:none}.page-header-actions__buttons{display:flex;gap:16px;align-items:center;flex-shrink:0}.valtimo-process-builder__header{display:flex;justify-content:space-between}.valtimo-process-builder__actions>*:not(:last-child){margin-right:8px}.validation-errors-list{position:absolute;top:8px;right:8px;z-index:10;width:320px;max-height:250px;overflow-y:auto;border:1px solid var(--cds-border-subtle);background-color:var(--cds-layer);border-radius:4px;box-shadow:0 2px 6px #00000026}.validation-errors-list details[open]>summary .validation-errors-list__arrow{transform:rotate(90deg)}.validation-errors-list__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;font-size:14px;font-weight:600;color:var(--cds-support-error, #da1e28);cursor:pointer;list-style:none;-webkit-user-select:none;user-select:none}.validation-errors-list__header::-webkit-details-marker{display:none}.validation-errors-list__arrow{display:inline-flex;width:16px;height:16px;fill:currentColor;transition:transform .15s ease;flex-shrink:0}.validation-errors-list__items{display:flex;flex-direction:column;border-top:1px solid var(--cds-border-subtle)}.validation-errors-list__item{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border:none;border-bottom:1px solid var(--cds-border-subtle);border-left:3px solid var(--cds-support-error, #da1e28);background-color:var(--cds-notification-error-background, #fff1f1);text-align:left;cursor:pointer;font-family:inherit}.validation-errors-list__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}.validation-errors-list__item:last-child{border-bottom:none}.validation-errors-list__item:hover{filter:brightness(.97)}.validation-errors-list__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;margin-top:1px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}.validation-errors-list__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}.validation-errors-list__details{display:flex;flex-direction:column;gap:2px}.validation-errors-list__element{font-size:13px;font-weight:600;color:var(--cds-text-primary)}.validation-errors-list__reason{font-size:13px;color:var(--cds-text-primary)}::ng-deep .highlight-overlay-error:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-error, #da1e28)!important}::ng-deep .highlight-overlay-warning:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-warning, #f1c21b)!important}::ng-deep .djs-overlay-validation-error{overflow:visible!important;pointer-events:all!important}::ng-deep .validation-error-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-error-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-error-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-error, #da1e28);color:var(--cds-support-error, #da1e28);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-error-overlay:hover ::ng-deep .validation-error-overlay__text,::ng-deep .validation-error-overlay--active ::ng-deep .validation-error-overlay__text{display:block}::ng-deep .validation-warning-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-warning-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-warning-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-warning-overlay:hover ::ng-deep .validation-warning-overlay__text,::ng-deep .validation-warning-overlay--active ::ng-deep .validation-warning-overlay__text{display:block}::ng-deep .validation-errors-panel{padding:8px 12px;display:flex;flex-direction:column;gap:8px}::ng-deep .validation-errors-panel__item{display:flex;align-items:flex-start;gap:8px;padding:8px 12px;background-color:var(--cds-notification-error-background, #fff1f1);border-left:3px solid var(--cds-support-error, #da1e28)}::ng-deep .validation-errors-panel__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}::ng-deep .validation-errors-panel__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}::ng-deep .validation-errors-panel__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}::ng-deep .validation-errors-panel__reason{color:var(--cds-text-primary, #161616);font-size:13px;line-height:18px}::ng-deep .process-link-properties-panel{padding:8px 12px 16px;width:100%;display:flex;flex-direction:column;gap:16px}::ng-deep .process-link-properties-panel__buttons,::ng-deep .process-link-properties-panel__header{width:100%;display:flex;gap:16px}::ng-deep .process-link-properties-panel__header{align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--cds-border-subtle-00);padding-bottom:8px;padding-left:8px;padding-right:8px}::ng-deep .process-link-properties-panel__title{color:var(--cds-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;margin:auto 0}::ng-deep .process-link-properties-panel__title-container{display:flex;flex-direction:column;gap:4px}::ng-deep .process-link-properties-panel__title-container :last-child{color:var(--cds-text-helper);font-style:italic}::ng-deep .process-link-properties-panel .cds--tag{margin:0}::ng-deep .process-link-properties-panel .cds--btn{flex-shrink:1;width:100%;display:flex;align-items:center}\n/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "directive", type: FitPageDirective, selector: "[fitPage]", inputs: ["spaceAdjustment", "fitPageDisabled", "disableOverflow", "bottomMargin"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "directive", type: RenderInPageHeaderDirective, selector: "[renderInPageHeader]", inputs: ["fullWidth"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i2$2.Dropdown, selector: "cds-dropdown, ibm-dropdown", inputs: ["id", "label", "hideLabel", "helperText", "placeholder", "displayValue", "clearText", "size", "type", "theme", "disabled", "readonly", "skeleton", "inline", "disableArrowKeys", "invalid", "invalidText", "warn", "warnText", "appendInline", "scrollableContainer", "itemValueKey", "selectionFeedback", "menuButtonLabel", "selectedLabel", "dropUp", "fluid"], outputs: ["selected", "onClose", "close"] }, { kind: "component", type: i2$2.DropdownList, selector: "cds-dropdown-list, ibm-dropdown-list", inputs: ["ariaLabel", "items", "listTpl", "type", "showTitles"], outputs: ["select", "scroll", "blurIntent"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$2.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i2$2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i2$2.Tag, selector: "cds-tag, ibm-tag", inputs: ["type", "size", "class", "skeleton"] }, { kind: "ngmodule", type: ProcessLinkModule }, { kind: "component", type: i5.ProcessLinkModalComponent, selector: "valtimo-process-link-modal" }, { kind: "component", type: OverflowMenuComponent, selector: "v-overflow-menu", inputs: ["open", "placement", "menuWidth", "offsetX", "offsetY", "closeOnSelect", "useHostAsReference", "portalToBody"], outputs: ["openChange"] }, { kind: "component", type: OverflowMenuOptionComponent, selector: "v-overflow-menu-option", inputs: ["disabled", "type", "testId", "optionId"], outputs: ["selected"] }, { kind: "component", type: OverflowMenuTriggerComponent, selector: "v-overflow-menu-trigger", inputs: ["compact"] }, { kind: "ngmodule", type: ToggleModule }, { kind: "component", type: i2$2.Toggle, selector: "cds-toggle, ibm-toggle", inputs: ["offText", "onText", "label", "size", "hideLabel", "ariaLabel", "skeleton"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "component", type: i2$2.Tooltip, selector: "cds-tooltip, ibm-tooltip", inputs: ["id", "enterDelayMs", "leaveDelayMs", "disabled", "description", "templateContext"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i1$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }] }); }
|
|
3076
|
+
], viewQueries: [{ propertyName: "modelerElementRef", first: true, predicate: ["modeler"], descendants: true }, { propertyName: "modelerPanelElementRef", first: true, predicate: ["modelerPanel"], descendants: true }, { propertyName: "viewerElementRef", first: true, predicate: ["viewer"], descendants: true }, { propertyName: "viewerPanelElementRef", first: true, predicate: ["viewerPanel"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n fitPage\n [disableOverflow]=\"true\"\n *ngIf=\"{\n processDefinitionVersions: processDefinitionVersions$ | async,\n selectedProcessDefinitionXml: selectedProcessDefinitionXml$ | async,\n loading: loading$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n } as obs\"\n data-carbon-theme=\"g10\"\n class=\"bpmn__container\"\n>\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'none' : 'flex'\"\n >\n <div class=\"bpmn__modeler-canvas\" #modeler>\n <cds-tooltip\n align=\"top-right\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.markers.toggleTooltip' | translate\"\n class=\"markers-visibility-toggle-wrapper\"\n >\n <button\n type=\"button\"\n class=\"markers-visibility-toggle\"\n (click)=\"toggleMarkerVisibility()\"\n [attr.data-test-id]=\"testIds.markersVisibilityToggle\"\n >\n <svg cdsIcon=\"view\" *ngIf=\"$markersVisible()\" size=\"16\"></svg>\n <svg cdsIcon=\"view--off\" *ngIf=\"!$markersVisible()\" size=\"16\"></svg>\n <span class=\"markers-visibility-toggle__label\">\n {{ ($markersVisible() ? 'processManagement.markers.hide' : 'processManagement.markers.show') | translate }}\n </span>\n </button>\n </cds-tooltip>\n\n <div\n class=\"validation-errors-list\"\n *ngIf=\"validationErrors$ | async as validationErrors\"\n [style.display]=\"validationErrors.length > 0 ? '' : 'none'\"\n >\n <details open>\n <summary class=\"validation-errors-list__header\">\n <span>{{\n 'processManagement.validationErrorsCount'\n | translate: {count: validationErrors.length}\n }}</span>\n <svg\n class=\"validation-errors-list__arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8Z\"\n />\n </svg>\n </summary>\n\n <div class=\"validation-errors-list__items\">\n <button\n *ngFor=\"let error of validationErrors\"\n class=\"validation-errors-list__item\"\n [class.warning]=\"error.severity === 'WARNING'\"\n (click)=\"onValidationErrorClick(error.elementId)\"\n >\n <span\n class=\"validation-errors-list__icon\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ error.severity === 'WARNING' ? '!' : '!' }}</span\n >\n\n <span class=\"validation-errors-list__details\">\n <span class=\"validation-errors-list__element\">{{\n error.elementName || error.elementId\n }}</span>\n\n <span\n class=\"validation-errors-list__reason\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ getValidationErrorMessage(error) }}</span\n >\n </span>\n </button>\n </div>\n </details>\n </div>\n </div>\n\n <div class=\"bpmn__modeler-panel\" #modelerPanel></div>\n </div>\n\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'flex' : 'none'\"\n >\n <div class=\"bpmn__modeler-canvas\" #viewer>\n <cds-tooltip\n align=\"top-right\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.markers.toggleTooltip' | translate\"\n class=\"markers-visibility-toggle-wrapper\"\n >\n <button\n type=\"button\"\n class=\"markers-visibility-toggle\"\n (click)=\"toggleMarkerVisibility()\"\n [attr.data-test-id]=\"testIds.markersVisibilityToggle\"\n >\n <svg cdsIcon=\"view\" *ngIf=\"$markersVisible()\" size=\"16\"></svg>\n <svg cdsIcon=\"view--off\" *ngIf=\"!$markersVisible()\" size=\"16\"></svg>\n <span class=\"markers-visibility-toggle__label\">\n {{ ($markersVisible() ? 'processManagement.markers.hide' : 'processManagement.markers.show') | translate }}\n </span>\n </button>\n </cds-tooltip>\n </div>\n\n <div class=\"bpmn__modeler-panel\" #viewerPanel></div>\n </div>\n</div>\n\n<valtimo-process-link-modal></valtimo-process-link-modal>\n\n<valtimo-confirmation-modal\n [showModalSubject$]=\"showWarningConfirmationModal$\"\n [titleTranslationKey]=\"'processManagement.warningConfirmation.title'\"\n [contentTranslationKey]=\"'processManagement.warningConfirmation.content'\"\n [confirmButtonTextTranslationKey]=\"'processManagement.warningConfirmation.confirm'\"\n [cancelButtonTextTranslationKey]=\"'interface.cancel'\"\n (confirmEvent)=\"onWarningConfirmationConfirm()\"\n (cancelEvent)=\"onWarningConfirmationCancel()\"\n></valtimo-confirmation-modal>\n\n<ng-container renderInPageHeader [fullWidth]=\"true\">\n <ng-template>\n <div\n class=\"page-header-actions\"\n *ngIf=\"{\n processDefinitionVersionsListItems: processDefinitionVersionsListItems$ | async,\n loading: loading$ | async,\n changesPending: changesPending$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n isSystemProcess: isSystemProcess$ | async,\n compactMode: compactMode$ | async,\n creatingNewProcess: creatingNewProcess$ | async,\n context: context$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n draft: draft$ | async,\n canInitializeDocument: canInitializeDocument$ | async,\n startableByUser: startableByUser$ | async,\n updatingProcessDefinitionCaseDefinition: updatingProcessDefinitionCaseDefinition$ | async,\n } as actionsObs\"\n >\n <div class=\"page-header-actions__left-container\">\n <cds-dropdown\n *ngIf=\"!actionsObs.creatingNewProcess && actionsObs?.context === 'independent'\"\n class=\"page-header-actions__version-dropdown\"\n (selected)=\"selectedVersionChange($event)\"\n [disabled]=\"\n actionsObs.loading ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 0 ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 1\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n >\n <cds-dropdown-list\n [items]=\"actionsObs.processDefinitionVersionsListItems || []\"\n ></cds-dropdown-list>\n </cds-dropdown>\n\n <div\n class=\"page-header-actions__tags\"\n *ngIf=\"\n actionsObs.isReadOnlyProcess ||\n !actionsObs.hasEditPermissions ||\n actionsObs.isSystemProcess\n \"\n >\n <cds-tag\n *ngIf=\"actionsObs.isReadOnlyProcess || !actionsObs.hasEditPermissions\"\n type=\"blue\"\n >{{ 'processManagement.readOnly' | translate }}</cds-tag\n >\n\n <cds-tag *ngIf=\"actionsObs.isSystemProcess\" type=\"red\">{{\n 'processManagement.systemProcess' | translate\n }}</cds-tag>\n </div>\n\n <div class=\"page-header-actions__toggles\">\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.draftTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.draft' | translate\"\n [offText]=\"'processManagement.draft' | translate\"\n [checked]=\"actionsObs.draft\"\n [disabled]=\"actionsObs.loading || !actionsObs.hasEditPermissions\"\n (checkedChange)=\"onProcessToggleChange('draft', $event)\"\n [attr.data-test-id]=\"testIds.draftToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n @if (actionsObs.context === 'case') {\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.processCreatesCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.canInitializeDocument' | translate\"\n [offText]=\"'processManagement.canInitializeDocument' | translate\"\n [checked]=\"actionsObs.canInitializeDocument\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('canInitializeDocument', $event)\"\n [attr.data-test-id]=\"testIds.startsCaseToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.startableWithinCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.startableByUser' | translate\"\n [offText]=\"'processManagement.startableByUser' | translate\"\n [checked]=\"actionsObs.startableByUser\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('startableByUser', $event)\"\n [attr.data-test-id]=\"testIds.startableByUserToggle\"\n ></cds-toggle\n ></cds-tooltip>\n }\n </div>\n </div>\n\n <div class=\"page-header-actions__buttons\">\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option\n *ngIf=\"actionsObs.context !== 'case'\"\n [disabled]=\"actionsObs.loading\"\n [attr.data-test-id]=\"testIds.exportOption\"\n (selected)=\"export()\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n\n <v-overflow-menu-option\n [disabled]=\"actionsObs.loading\"\n (selected)=\"exportBpmn(actionsObs.isReadOnlyProcess)\"\n >{{ 'processManagement.exportBpmn' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n\n <button\n *ngIf=\"actionsObs.context === 'case'\"\n cdsButton=\"tertiary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n >\n {{ 'interface.back' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"return\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"secondary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [disabled]=\"actionsObs.loading\"\n (click)=\"validateProcessDefinition(actionsObs.isReadOnlyProcess)\"\n >\n {{ 'processManagement.validate' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"list--checked\" size=\"16\"></svg>\n </button>\n\n <button\n [disabled]=\"!actionsObs.changesPending\"\n cdsButton=\"primary\"\n (click)=\"\n !actionsObs.creatingNewProcess\n ? deployChanges(actionsObs.isReadOnlyProcess)\n : deployNewProcessDefinition()\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'processManagement.deploy' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"deploy\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n </ng-template>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;gap:24px}.bpmn__container{position:relative;background-color:var(--cds-layer);width:100%}.bpmn__modeler{width:100%;height:100%;flex-direction:row;padding:1px;box-sizing:border-box;outline:1px solid var(--cds-border-subtle);outline-offset:-1px}.bpmn__modeler ::ng-deep .djs-container>svg{outline:none!important}.bpmn__modeler-canvas{width:100%;position:relative}.bpmn__modeler-canvas .markers-visibility-toggle-wrapper{position:absolute;bottom:55px;right:15px;z-index:100}.bpmn__modeler-canvas .markers-visibility-toggle{display:flex;align-items:center;gap:6px;height:32px;padding:0 10px;border:none;border-radius:2px;background-color:var(--cds-layer);cursor:pointer;color:var(--cds-text-secondary);transition:background-color .15s,color .15s}.bpmn__modeler-canvas .markers-visibility-toggle:hover{background-color:var(--cds-layer-hover);color:var(--cds-text-primary)}.bpmn__modeler-canvas .markers-visibility-toggle:focus{outline:2px solid var(--cds-focus);outline-offset:-2px}.bpmn__modeler-canvas .markers-visibility-toggle__label{font-size:12px;white-space:nowrap}.bpmn__modeler-panel{width:481px;padding-left:1px;box-shadow:inset 1px 0 0 0 var(--cds-border-subtle);box-sizing:border-box}.bpmn__loading{width:100%;height:100%;display:flex;justify-content:center;align-items:center;background-color:var(--cds-background-selected)}.page-header-actions{display:flex;width:100%;justify-content:space-between;align-items:center;gap:16px}.page-header-actions__left-container{display:flex;gap:16px;align-items:center}.page-header-actions__tags{display:flex;gap:8px;align-items:center}.page-header-actions__version-dropdown{width:150px}.page-header-actions__toggles{display:flex;gap:16px;align-items:center}.page-header-actions__toggles ::ng-deep cds-toggle{display:inline-flex;align-items:center}.page-header-actions__toggles ::ng-deep .cds--toggle__label-text{display:none}.page-header-actions__buttons{display:flex;gap:16px;align-items:center;flex-shrink:0}.valtimo-process-builder__header{display:flex;justify-content:space-between}.valtimo-process-builder__actions>*:not(:last-child){margin-right:8px}.validation-errors-list{position:absolute;top:8px;right:8px;z-index:10;width:320px;max-height:250px;overflow-y:auto;border:1px solid var(--cds-border-subtle);background-color:var(--cds-layer);border-radius:4px;box-shadow:0 2px 6px #00000026}.validation-errors-list details[open]>summary .validation-errors-list__arrow{transform:rotate(90deg)}.validation-errors-list__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;font-size:14px;font-weight:600;color:var(--cds-support-error, #da1e28);cursor:pointer;list-style:none;-webkit-user-select:none;user-select:none}.validation-errors-list__header::-webkit-details-marker{display:none}.validation-errors-list__arrow{display:inline-flex;width:16px;height:16px;fill:currentColor;transition:transform .15s ease;flex-shrink:0}.validation-errors-list__items{display:flex;flex-direction:column;border-top:1px solid var(--cds-border-subtle)}.validation-errors-list__item{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border:none;border-bottom:1px solid var(--cds-border-subtle);border-left:3px solid var(--cds-support-error, #da1e28);background-color:var(--cds-notification-error-background, #fff1f1);text-align:left;cursor:pointer;font-family:inherit}.validation-errors-list__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}.validation-errors-list__item:last-child{border-bottom:none}.validation-errors-list__item:hover{filter:brightness(.97)}.validation-errors-list__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;margin-top:1px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}.validation-errors-list__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}.validation-errors-list__details{display:flex;flex-direction:column;gap:2px}.validation-errors-list__element{font-size:13px;font-weight:600;color:var(--cds-text-primary)}.validation-errors-list__reason{font-size:13px;color:var(--cds-text-primary)}::ng-deep .highlight-overlay-error:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-error, #da1e28)!important}::ng-deep .highlight-overlay-warning:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-warning, #f1c21b)!important}::ng-deep .djs-overlay-validation-error{overflow:visible!important;pointer-events:all!important}::ng-deep .validation-error-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-error-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-error-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-error, #da1e28);color:var(--cds-support-error, #da1e28);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-error-overlay:hover ::ng-deep .validation-error-overlay__text,::ng-deep .validation-error-overlay--active ::ng-deep .validation-error-overlay__text{display:block}::ng-deep .validation-warning-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-warning-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-warning-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-warning-overlay:hover ::ng-deep .validation-warning-overlay__text,::ng-deep .validation-warning-overlay--active ::ng-deep .validation-warning-overlay__text{display:block}::ng-deep .djs-overlay-activity-marker{overflow:visible!important;pointer-events:all!important}::ng-deep .activity-marker-overlay{display:flex;gap:2px}::ng-deep .activity-marker-badge{position:relative;cursor:pointer;pointer-events:all}::ng-deep .activity-marker-badge__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;font-size:14px;font-weight:700;line-height:0}::ng-deep .activity-marker-badge__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .activity-marker-badge:hover ::ng-deep .activity-marker-badge__text,::ng-deep .activity-marker-badge--active ::ng-deep .activity-marker-badge__text{display:block}::ng-deep .activity-marker-badge--process-link ::ng-deep .activity-marker-badge__icon{background-color:var(--cds-support-info, #0043ce);color:var(--cds-text-on-color, #ffffff)}::ng-deep .activity-marker-badge--process-link ::ng-deep .activity-marker-badge__text{border:1px solid var(--cds-support-info, #0043ce);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff)}::ng-deep .activity-marker-badge--execution-listener ::ng-deep .activity-marker-badge__icon{background-color:var(--cds-purple-60, #8a3ffc);color:var(--cds-text-on-color, #ffffff)}::ng-deep .activity-marker-badge--execution-listener ::ng-deep .activity-marker-badge__text{border:1px solid var(--cds-purple-60, #8a3ffc);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff)}::ng-deep .activity-marker-badge--task-listener ::ng-deep .activity-marker-badge__icon{background-color:var(--cds-teal-50, #009d9a);color:var(--cds-text-on-color, #ffffff)}::ng-deep .activity-marker-badge--task-listener ::ng-deep .activity-marker-badge__text{border:1px solid var(--cds-teal-50, #009d9a);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff)}::ng-deep .validation-errors-panel{padding:8px 12px;display:flex;flex-direction:column;gap:8px}::ng-deep .validation-errors-panel__item{display:flex;align-items:flex-start;gap:8px;padding:8px 12px;background-color:var(--cds-notification-error-background, #fff1f1);border-left:3px solid var(--cds-support-error, #da1e28)}::ng-deep .validation-errors-panel__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}::ng-deep .validation-errors-panel__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}::ng-deep .validation-errors-panel__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}::ng-deep .validation-errors-panel__reason{color:var(--cds-text-primary, #161616);font-size:13px;line-height:18px}::ng-deep .bio-properties-panel-entry.validation-error-field .bio-properties-panel-input,::ng-deep .bio-properties-panel-entry.validation-error-field .bio-properties-panel-textfield,::ng-deep .bio-properties-panel-entry.validation-error-field .bio-properties-panel-feel-editor-container{border:2px solid var(--cds-support-error, #da1e28)!important;background-color:var(--cds-notification-error-background, #fff1f1)!important}::ng-deep .expression-editor-param input.validation-error-param,::ng-deep input.expression-editor-input.validation-error-param,::ng-deep .expression-editor-technical input.validation-error-param,::ng-deep .expression-editor-technical textarea.validation-error-param{border:2px solid #da1e28!important;background-color:#fff1f1!important;border-color:#da1e28!important}::ng-deep .process-link-properties-panel{padding:8px 12px 16px;width:100%;display:flex;flex-direction:column;gap:16px}::ng-deep .process-link-properties-panel__buttons,::ng-deep .process-link-properties-panel__header{width:100%;display:flex;gap:16px}::ng-deep .process-link-properties-panel__header{align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--cds-border-subtle-00);padding-bottom:8px;padding-left:8px;padding-right:8px}::ng-deep .process-link-properties-panel__title{color:var(--cds-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;margin:auto 0}::ng-deep .process-link-properties-panel__title-container{display:flex;flex-direction:column;gap:4px}::ng-deep .process-link-properties-panel__title-container :last-child{color:var(--cds-text-helper);font-style:italic}::ng-deep .process-link-properties-panel .cds--tag{margin:0}::ng-deep .process-link-properties-panel .cds--btn{flex-shrink:1;width:100%;display:flex;align-items:center}::ng-deep .djs-overlay-autofilled-indicator{overflow:visible!important;pointer-events:all!important}::ng-deep .autofilled-indicator-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .autofilled-indicator-overlay .autofilled-indicator-icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-info, #0043ce);color:var(--cds-text-on-color, #ffffff);font-size:14px;font-weight:700;line-height:0}::ng-deep .autofilled-indicator-overlay .autofilled-indicator-tooltip{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-info, #0043ce);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .autofilled-indicator-overlay:hover .autofilled-indicator-tooltip{display:block}::ng-deep .autofilled-notification-panel{display:flex;align-items:center;gap:8px;padding:8px 12px;background-color:var(--cds-layer-02, #f4f4f4);border-left:3px solid var(--cds-support-info, #0043ce);margin-bottom:8px}::ng-deep .autofilled-notification-panel__icon{display:flex;align-items:center;justify-content:center;min-width:18px;height:18px;border-radius:50%;background-color:var(--cds-support-info, #0043ce);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700}::ng-deep .autofilled-notification-panel__message{flex:1;font-size:12px;color:var(--cds-text-primary, #161616)}::ng-deep .autofilled-notification-panel__dismiss{background:none;border:none;cursor:pointer;padding:2px 6px;font-size:16px;color:var(--cds-text-secondary, #525252);line-height:1}::ng-deep .autofilled-notification-panel__dismiss:hover{color:var(--cds-text-primary, #161616)}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "directive", type: FitPageDirective, selector: "[fitPage]", inputs: ["spaceAdjustment", "fitPageDisabled", "disableOverflow", "bottomMargin"] }, { kind: "ngmodule", type: LoadingModule }, { kind: "directive", type: RenderInPageHeaderDirective, selector: "[renderInPageHeader]", inputs: ["fullWidth"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "component", type: i2$2.Dropdown, selector: "cds-dropdown, ibm-dropdown", inputs: ["id", "label", "hideLabel", "helperText", "placeholder", "displayValue", "clearText", "size", "type", "theme", "disabled", "readonly", "skeleton", "inline", "disableArrowKeys", "invalid", "invalidText", "warn", "warnText", "appendInline", "scrollableContainer", "itemValueKey", "selectionFeedback", "menuButtonLabel", "selectedLabel", "dropUp", "fluid"], outputs: ["selected", "onClose", "close"] }, { kind: "component", type: i2$2.DropdownList, selector: "cds-dropdown-list, ibm-dropdown-list", inputs: ["ariaLabel", "items", "listTpl", "type", "showTitles"], outputs: ["select", "scroll", "blurIntent"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$2.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i2$2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i2$2.Tag, selector: "cds-tag, ibm-tag", inputs: ["type", "size", "class", "skeleton"] }, { kind: "ngmodule", type: ProcessLinkModule }, { kind: "component", type: i5.ProcessLinkModalComponent, selector: "valtimo-process-link-modal" }, { kind: "ngmodule", type: ToggleModule }, { kind: "component", type: i2$2.Toggle, selector: "cds-toggle, ibm-toggle", inputs: ["offText", "onText", "label", "size", "hideLabel", "ariaLabel", "skeleton"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "component", type: i2$2.Tooltip, selector: "cds-tooltip, ibm-tooltip", inputs: ["id", "enterDelayMs", "leaveDelayMs", "disabled", "description", "templateContext"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i1$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }, { kind: "ngmodule", type: OverflowMenuModule }, { kind: "component", type: i1$1.OverflowMenuComponent, selector: "v-overflow-menu", inputs: ["open", "placement", "menuWidth", "offsetX", "offsetY", "closeOnSelect", "useHostAsReference", "portalToBody"], outputs: ["openChange"] }, { kind: "component", type: i1$1.OverflowMenuOptionComponent, selector: "v-overflow-menu-option", inputs: ["disabled", "type", "testId", "optionId"], outputs: ["selected"] }, { kind: "component", type: i1$1.OverflowMenuTriggerComponent, selector: "v-overflow-menu-trigger", inputs: ["compact", "label"] }] }); }
|
|
1925
3077
|
}
|
|
1926
3078
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementBuilderComponent, decorators: [{
|
|
1927
3079
|
type: Component,
|
|
@@ -1938,20 +3090,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
1938
3090
|
TranslateModule,
|
|
1939
3091
|
TagModule,
|
|
1940
3092
|
ProcessLinkModule,
|
|
1941
|
-
ProcessLinkModule,
|
|
1942
|
-
OverflowMenuComponent,
|
|
1943
|
-
OverflowMenuOptionComponent,
|
|
1944
|
-
OverflowMenuTriggerComponent,
|
|
1945
3093
|
ToggleModule,
|
|
1946
3094
|
TooltipModule,
|
|
1947
3095
|
ConfirmationModalModule,
|
|
3096
|
+
OverflowMenuModule,
|
|
1948
3097
|
], providers: [
|
|
1949
3098
|
ProcessManagementEditorService,
|
|
1950
3099
|
ProcessLinkStateService,
|
|
1951
3100
|
ProcessLinkStepService,
|
|
1952
3101
|
ProcessLinkButtonService,
|
|
1953
|
-
], template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n fitPage\n [disableOverflow]=\"true\"\n *ngIf=\"{\n processDefinitionVersions: processDefinitionVersions$ | async,\n selectedProcessDefinitionXml: selectedProcessDefinitionXml$ | async,\n loading: loading$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n } as obs\"\n data-carbon-theme=\"g10\"\n class=\"bpmn__container\"\n>\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'none' : 'flex'\"\n >\n <div class=\"bpmn__modeler-canvas\" #modeler>\n <div\n class=\"validation-errors-list\"\n *ngIf=\"validationErrors$ | async as validationErrors\"\n [style.display]=\"validationErrors.length > 0 ? '' : 'none'\"\n >\n <details open>\n <summary class=\"validation-errors-list__header\">\n <span>{{\n 'processManagement.validationErrorsCount'\n | translate: {count: validationErrors.length}\n }}</span>\n <svg\n class=\"validation-errors-list__arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8Z\"\n />\n </svg>\n </summary>\n\n <div class=\"validation-errors-list__items\">\n <button\n *ngFor=\"let error of validationErrors\"\n class=\"validation-errors-list__item\"\n [class.warning]=\"error.severity === 'WARNING'\"\n (click)=\"onValidationErrorClick(error.elementId)\"\n >\n <span\n class=\"validation-errors-list__icon\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ error.severity === 'WARNING' ? '!' : '!' }}</span\n >\n\n <span class=\"validation-errors-list__details\">\n <span class=\"validation-errors-list__element\">{{\n error.elementName || error.elementId\n }}</span>\n\n <span\n class=\"validation-errors-list__reason\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ getValidationErrorMessage(error) }}</span\n >\n </span>\n </button>\n </div>\n </details>\n </div>\n </div>\n\n <div class=\"bpmn__modeler-panel\" #modelerPanel></div>\n </div>\n\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'flex' : 'none'\"\n >\n <div class=\"bpmn__modeler-canvas\" #viewer></div>\n\n <div class=\"bpmn__modeler-panel\" #viewerPanel></div>\n </div>\n</div>\n\n<valtimo-process-link-modal></valtimo-process-link-modal>\n\n<valtimo-confirmation-modal\n [showModalSubject$]=\"showWarningConfirmationModal$\"\n [titleTranslationKey]=\"'processManagement.warningConfirmation.title'\"\n [contentTranslationKey]=\"'processManagement.warningConfirmation.content'\"\n [confirmButtonTextTranslationKey]=\"'processManagement.warningConfirmation.confirm'\"\n [cancelButtonTextTranslationKey]=\"'interface.cancel'\"\n (confirmEvent)=\"onWarningConfirmationConfirm()\"\n (cancelEvent)=\"onWarningConfirmationCancel()\"\n></valtimo-confirmation-modal>\n\n<ng-container renderInPageHeader [fullWidth]=\"true\">\n <ng-template>\n <div\n class=\"page-header-actions\"\n *ngIf=\"{\n processDefinitionVersionsListItems: processDefinitionVersionsListItems$ | async,\n loading: loading$ | async,\n changesPending: changesPending$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n isSystemProcess: isSystemProcess$ | async,\n compactMode: compactMode$ | async,\n creatingNewProcess: creatingNewProcess$ | async,\n context: context$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n draft: draft$ | async,\n canInitializeDocument: canInitializeDocument$ | async,\n startableByUser: startableByUser$ | async,\n updatingProcessDefinitionCaseDefinition: updatingProcessDefinitionCaseDefinition$ | async,\n } as actionsObs\"\n >\n <div class=\"page-header-actions__left-container\">\n <cds-dropdown\n *ngIf=\"!actionsObs.creatingNewProcess && actionsObs?.context === 'independent'\"\n class=\"page-header-actions__version-dropdown\"\n (selected)=\"selectedVersionChange($event)\"\n [disabled]=\"\n actionsObs.loading ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 0 ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 1\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n >\n <cds-dropdown-list\n [items]=\"actionsObs.processDefinitionVersionsListItems || []\"\n ></cds-dropdown-list>\n </cds-dropdown>\n\n <div\n class=\"page-header-actions__tags\"\n *ngIf=\"\n actionsObs.isReadOnlyProcess ||\n !actionsObs.hasEditPermissions ||\n actionsObs.isSystemProcess\n \"\n >\n <cds-tag\n *ngIf=\"actionsObs.isReadOnlyProcess || !actionsObs.hasEditPermissions\"\n type=\"blue\"\n >{{ 'processManagement.readOnly' | translate }}</cds-tag\n >\n\n <cds-tag *ngIf=\"actionsObs.isSystemProcess\" type=\"red\">{{\n 'processManagement.systemProcess' | translate\n }}</cds-tag>\n </div>\n\n <div class=\"page-header-actions__toggles\">\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.draftTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.draft' | translate\"\n [offText]=\"'processManagement.draft' | translate\"\n [checked]=\"actionsObs.draft\"\n [disabled]=\"actionsObs.loading || !actionsObs.hasEditPermissions\"\n (checkedChange)=\"onProcessToggleChange('draft', $event)\"\n [attr.data-test-id]=\"testIds.draftToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n @if (actionsObs.context === 'case') {\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.processCreatesCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.canInitializeDocument' | translate\"\n [offText]=\"'processManagement.canInitializeDocument' | translate\"\n [checked]=\"actionsObs.canInitializeDocument\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('canInitializeDocument', $event)\"\n [attr.data-test-id]=\"testIds.startsCaseToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.startableWithinCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.startableByUser' | translate\"\n [offText]=\"'processManagement.startableByUser' | translate\"\n [checked]=\"actionsObs.startableByUser\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('startableByUser', $event)\"\n [attr.data-test-id]=\"testIds.startableByUserToggle\"\n ></cds-toggle\n ></cds-tooltip>\n }\n </div>\n </div>\n\n <div class=\"page-header-actions__buttons\">\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option\n [disabled]=\"actionsObs.loading\"\n (selected)=\"export(actionsObs.isReadOnlyProcess)\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n\n <button\n *ngIf=\"actionsObs.context === 'case'\"\n cdsButton=\"tertiary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n >\n {{ 'interface.back' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"return\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"secondary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [disabled]=\"actionsObs.loading\"\n (click)=\"validateProcessDefinition(actionsObs.isReadOnlyProcess)\"\n >\n {{ 'processManagement.validate' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"list--checked\" size=\"16\"></svg>\n </button>\n\n <button\n [disabled]=\"!actionsObs.changesPending\"\n cdsButton=\"primary\"\n (click)=\"\n !actionsObs.creatingNewProcess\n ? deployChanges(actionsObs.isReadOnlyProcess)\n : deployNewProcessDefinition()\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'processManagement.deploy' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"deploy\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n </ng-template>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;gap:24px}.bpmn__container{position:relative;background-color:var(--cds-layer);width:100%}.bpmn__modeler{width:100%;height:100%;flex-direction:row;padding:1px;box-sizing:border-box;outline:1px solid var(--cds-border-subtle);outline-offset:-1px}.bpmn__modeler ::ng-deep .djs-container>svg{outline:none!important}.bpmn__modeler-canvas{width:100%;position:relative}.bpmn__modeler-panel{width:481px;padding-left:1px;box-shadow:inset 1px 0 0 0 var(--cds-border-subtle);box-sizing:border-box}.bpmn__loading{width:100%;height:100%;display:flex;justify-content:center;align-items:center;background-color:var(--cds-background-selected)}.page-header-actions{display:flex;width:100%;justify-content:space-between;align-items:center;gap:16px}.page-header-actions__left-container{display:flex;gap:16px;align-items:center}.page-header-actions__tags{display:flex;gap:8px;align-items:center}.page-header-actions__version-dropdown{width:150px}.page-header-actions__toggles{display:flex;gap:16px;align-items:center}.page-header-actions__toggles ::ng-deep cds-toggle{display:inline-flex;align-items:center}.page-header-actions__toggles ::ng-deep .cds--toggle__label-text{display:none}.page-header-actions__buttons{display:flex;gap:16px;align-items:center;flex-shrink:0}.valtimo-process-builder__header{display:flex;justify-content:space-between}.valtimo-process-builder__actions>*:not(:last-child){margin-right:8px}.validation-errors-list{position:absolute;top:8px;right:8px;z-index:10;width:320px;max-height:250px;overflow-y:auto;border:1px solid var(--cds-border-subtle);background-color:var(--cds-layer);border-radius:4px;box-shadow:0 2px 6px #00000026}.validation-errors-list details[open]>summary .validation-errors-list__arrow{transform:rotate(90deg)}.validation-errors-list__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;font-size:14px;font-weight:600;color:var(--cds-support-error, #da1e28);cursor:pointer;list-style:none;-webkit-user-select:none;user-select:none}.validation-errors-list__header::-webkit-details-marker{display:none}.validation-errors-list__arrow{display:inline-flex;width:16px;height:16px;fill:currentColor;transition:transform .15s ease;flex-shrink:0}.validation-errors-list__items{display:flex;flex-direction:column;border-top:1px solid var(--cds-border-subtle)}.validation-errors-list__item{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border:none;border-bottom:1px solid var(--cds-border-subtle);border-left:3px solid var(--cds-support-error, #da1e28);background-color:var(--cds-notification-error-background, #fff1f1);text-align:left;cursor:pointer;font-family:inherit}.validation-errors-list__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}.validation-errors-list__item:last-child{border-bottom:none}.validation-errors-list__item:hover{filter:brightness(.97)}.validation-errors-list__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;margin-top:1px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}.validation-errors-list__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}.validation-errors-list__details{display:flex;flex-direction:column;gap:2px}.validation-errors-list__element{font-size:13px;font-weight:600;color:var(--cds-text-primary)}.validation-errors-list__reason{font-size:13px;color:var(--cds-text-primary)}::ng-deep .highlight-overlay-error:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-error, #da1e28)!important}::ng-deep .highlight-overlay-warning:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-warning, #f1c21b)!important}::ng-deep .djs-overlay-validation-error{overflow:visible!important;pointer-events:all!important}::ng-deep .validation-error-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-error-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-error-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-error, #da1e28);color:var(--cds-support-error, #da1e28);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-error-overlay:hover ::ng-deep .validation-error-overlay__text,::ng-deep .validation-error-overlay--active ::ng-deep .validation-error-overlay__text{display:block}::ng-deep .validation-warning-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-warning-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-warning-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-warning-overlay:hover ::ng-deep .validation-warning-overlay__text,::ng-deep .validation-warning-overlay--active ::ng-deep .validation-warning-overlay__text{display:block}::ng-deep .validation-errors-panel{padding:8px 12px;display:flex;flex-direction:column;gap:8px}::ng-deep .validation-errors-panel__item{display:flex;align-items:flex-start;gap:8px;padding:8px 12px;background-color:var(--cds-notification-error-background, #fff1f1);border-left:3px solid var(--cds-support-error, #da1e28)}::ng-deep .validation-errors-panel__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}::ng-deep .validation-errors-panel__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}::ng-deep .validation-errors-panel__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}::ng-deep .validation-errors-panel__reason{color:var(--cds-text-primary, #161616);font-size:13px;line-height:18px}::ng-deep .process-link-properties-panel{padding:8px 12px 16px;width:100%;display:flex;flex-direction:column;gap:16px}::ng-deep .process-link-properties-panel__buttons,::ng-deep .process-link-properties-panel__header{width:100%;display:flex;gap:16px}::ng-deep .process-link-properties-panel__header{align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--cds-border-subtle-00);padding-bottom:8px;padding-left:8px;padding-right:8px}::ng-deep .process-link-properties-panel__title{color:var(--cds-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;margin:auto 0}::ng-deep .process-link-properties-panel__title-container{display:flex;flex-direction:column;gap:4px}::ng-deep .process-link-properties-panel__title-container :last-child{color:var(--cds-text-helper);font-style:italic}::ng-deep .process-link-properties-panel .cds--tag{margin:0}::ng-deep .process-link-properties-panel .cds--btn{flex-shrink:1;width:100%;display:flex;align-items:center}\n/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
1954
|
-
}], ctorParameters: () => [{ type: i1$1.BreadcrumbService }, { type: i2$2.IconService }, { type: i3.NGXLogger }, { type: i1$1.ModalService }, { type: i2
|
|
3102
|
+
], template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<div\n fitPage\n [disableOverflow]=\"true\"\n *ngIf=\"{\n processDefinitionVersions: processDefinitionVersions$ | async,\n selectedProcessDefinitionXml: selectedProcessDefinitionXml$ | async,\n loading: loading$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n } as obs\"\n data-carbon-theme=\"g10\"\n class=\"bpmn__container\"\n>\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'none' : 'flex'\"\n >\n <div class=\"bpmn__modeler-canvas\" #modeler>\n <cds-tooltip\n align=\"top-right\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.markers.toggleTooltip' | translate\"\n class=\"markers-visibility-toggle-wrapper\"\n >\n <button\n type=\"button\"\n class=\"markers-visibility-toggle\"\n (click)=\"toggleMarkerVisibility()\"\n [attr.data-test-id]=\"testIds.markersVisibilityToggle\"\n >\n <svg cdsIcon=\"view\" *ngIf=\"$markersVisible()\" size=\"16\"></svg>\n <svg cdsIcon=\"view--off\" *ngIf=\"!$markersVisible()\" size=\"16\"></svg>\n <span class=\"markers-visibility-toggle__label\">\n {{ ($markersVisible() ? 'processManagement.markers.hide' : 'processManagement.markers.show') | translate }}\n </span>\n </button>\n </cds-tooltip>\n\n <div\n class=\"validation-errors-list\"\n *ngIf=\"validationErrors$ | async as validationErrors\"\n [style.display]=\"validationErrors.length > 0 ? '' : 'none'\"\n >\n <details open>\n <summary class=\"validation-errors-list__header\">\n <span>{{\n 'processManagement.validationErrorsCount'\n | translate: {count: validationErrors.length}\n }}</span>\n <svg\n class=\"validation-errors-list__arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8Z\"\n />\n </svg>\n </summary>\n\n <div class=\"validation-errors-list__items\">\n <button\n *ngFor=\"let error of validationErrors\"\n class=\"validation-errors-list__item\"\n [class.warning]=\"error.severity === 'WARNING'\"\n (click)=\"onValidationErrorClick(error.elementId)\"\n >\n <span\n class=\"validation-errors-list__icon\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ error.severity === 'WARNING' ? '!' : '!' }}</span\n >\n\n <span class=\"validation-errors-list__details\">\n <span class=\"validation-errors-list__element\">{{\n error.elementName || error.elementId\n }}</span>\n\n <span\n class=\"validation-errors-list__reason\"\n [class.warning]=\"error.severity === 'WARNING'\"\n >{{ getValidationErrorMessage(error) }}</span\n >\n </span>\n </button>\n </div>\n </details>\n </div>\n </div>\n\n <div class=\"bpmn__modeler-panel\" #modelerPanel></div>\n </div>\n\n <div\n class=\"bpmn__modeler\"\n [style.display]=\"obs.isReadOnlyProcess || !obs.hasEditPermissions ? 'flex' : 'none'\"\n >\n <div class=\"bpmn__modeler-canvas\" #viewer>\n <cds-tooltip\n align=\"top-right\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.markers.toggleTooltip' | translate\"\n class=\"markers-visibility-toggle-wrapper\"\n >\n <button\n type=\"button\"\n class=\"markers-visibility-toggle\"\n (click)=\"toggleMarkerVisibility()\"\n [attr.data-test-id]=\"testIds.markersVisibilityToggle\"\n >\n <svg cdsIcon=\"view\" *ngIf=\"$markersVisible()\" size=\"16\"></svg>\n <svg cdsIcon=\"view--off\" *ngIf=\"!$markersVisible()\" size=\"16\"></svg>\n <span class=\"markers-visibility-toggle__label\">\n {{ ($markersVisible() ? 'processManagement.markers.hide' : 'processManagement.markers.show') | translate }}\n </span>\n </button>\n </cds-tooltip>\n </div>\n\n <div class=\"bpmn__modeler-panel\" #viewerPanel></div>\n </div>\n</div>\n\n<valtimo-process-link-modal></valtimo-process-link-modal>\n\n<valtimo-confirmation-modal\n [showModalSubject$]=\"showWarningConfirmationModal$\"\n [titleTranslationKey]=\"'processManagement.warningConfirmation.title'\"\n [contentTranslationKey]=\"'processManagement.warningConfirmation.content'\"\n [confirmButtonTextTranslationKey]=\"'processManagement.warningConfirmation.confirm'\"\n [cancelButtonTextTranslationKey]=\"'interface.cancel'\"\n (confirmEvent)=\"onWarningConfirmationConfirm()\"\n (cancelEvent)=\"onWarningConfirmationCancel()\"\n></valtimo-confirmation-modal>\n\n<ng-container renderInPageHeader [fullWidth]=\"true\">\n <ng-template>\n <div\n class=\"page-header-actions\"\n *ngIf=\"{\n processDefinitionVersionsListItems: processDefinitionVersionsListItems$ | async,\n loading: loading$ | async,\n changesPending: changesPending$ | async,\n isReadOnlyProcess: isReadOnlyProcess$ | async,\n isSystemProcess: isSystemProcess$ | async,\n compactMode: compactMode$ | async,\n creatingNewProcess: creatingNewProcess$ | async,\n context: context$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n draft: draft$ | async,\n canInitializeDocument: canInitializeDocument$ | async,\n startableByUser: startableByUser$ | async,\n updatingProcessDefinitionCaseDefinition: updatingProcessDefinitionCaseDefinition$ | async,\n } as actionsObs\"\n >\n <div class=\"page-header-actions__left-container\">\n <cds-dropdown\n *ngIf=\"!actionsObs.creatingNewProcess && actionsObs?.context === 'independent'\"\n class=\"page-header-actions__version-dropdown\"\n (selected)=\"selectedVersionChange($event)\"\n [disabled]=\"\n actionsObs.loading ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 0 ||\n (actionsObs.processDefinitionVersionsListItems || []).length === 1\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n >\n <cds-dropdown-list\n [items]=\"actionsObs.processDefinitionVersionsListItems || []\"\n ></cds-dropdown-list>\n </cds-dropdown>\n\n <div\n class=\"page-header-actions__tags\"\n *ngIf=\"\n actionsObs.isReadOnlyProcess ||\n !actionsObs.hasEditPermissions ||\n actionsObs.isSystemProcess\n \"\n >\n <cds-tag\n *ngIf=\"actionsObs.isReadOnlyProcess || !actionsObs.hasEditPermissions\"\n type=\"blue\"\n >{{ 'processManagement.readOnly' | translate }}</cds-tag\n >\n\n <cds-tag *ngIf=\"actionsObs.isSystemProcess\" type=\"red\">{{\n 'processManagement.systemProcess' | translate\n }}</cds-tag>\n </div>\n\n <div class=\"page-header-actions__toggles\">\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processManagement.draftTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.draft' | translate\"\n [offText]=\"'processManagement.draft' | translate\"\n [checked]=\"actionsObs.draft\"\n [disabled]=\"actionsObs.loading || !actionsObs.hasEditPermissions\"\n (checkedChange)=\"onProcessToggleChange('draft', $event)\"\n [attr.data-test-id]=\"testIds.draftToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n @if (actionsObs.context === 'case') {\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.processCreatesCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.canInitializeDocument' | translate\"\n [offText]=\"'processManagement.canInitializeDocument' | translate\"\n [checked]=\"actionsObs.canInitializeDocument\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('canInitializeDocument', $event)\"\n [attr.data-test-id]=\"testIds.startsCaseToggle\"\n ></cds-toggle>\n </cds-tooltip>\n\n <cds-tooltip\n align=\"bottom-left\"\n [autoAlign]=\"true\"\n [description]=\"'processCaseConnection.startableWithinCaseTooltip' | translate\"\n >\n <cds-toggle\n size=\"sm\"\n [onText]=\"'processManagement.startableByUser' | translate\"\n [offText]=\"'processManagement.startableByUser' | translate\"\n [checked]=\"actionsObs.startableByUser\"\n [disabled]=\"\n actionsObs.loading ||\n actionsObs.updatingProcessDefinitionCaseDefinition ||\n !actionsObs.hasEditPermissions\n \"\n (checkedChange)=\"onProcessToggleChange('startableByUser', $event)\"\n [attr.data-test-id]=\"testIds.startableByUserToggle\"\n ></cds-toggle\n ></cds-tooltip>\n }\n </div>\n </div>\n\n <div class=\"page-header-actions__buttons\">\n <v-overflow-menu class=\"overflow-button\" placement=\"bottom-end\">\n <v-overflow-menu-trigger overflowTrigger></v-overflow-menu-trigger>\n <v-overflow-menu-option\n *ngIf=\"actionsObs.context !== 'case'\"\n [disabled]=\"actionsObs.loading\"\n [attr.data-test-id]=\"testIds.exportOption\"\n (selected)=\"export()\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n\n <v-overflow-menu-option\n [disabled]=\"actionsObs.loading\"\n (selected)=\"exportBpmn(actionsObs.isReadOnlyProcess)\"\n >{{ 'processManagement.exportBpmn' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n\n <button\n *ngIf=\"actionsObs.context === 'case'\"\n cdsButton=\"tertiary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n >\n {{ 'interface.back' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"return\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"secondary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [disabled]=\"actionsObs.loading\"\n (click)=\"validateProcessDefinition(actionsObs.isReadOnlyProcess)\"\n >\n {{ 'processManagement.validate' | translate }}\n <svg class=\"cds--btn__icon\" cdsIcon=\"list--checked\" size=\"16\"></svg>\n </button>\n\n <button\n [disabled]=\"!actionsObs.changesPending\"\n cdsButton=\"primary\"\n (click)=\"\n !actionsObs.creatingNewProcess\n ? deployChanges(actionsObs.isReadOnlyProcess)\n : deployNewProcessDefinition()\n \"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'processManagement.deploy' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"deploy\" size=\"16\"></svg>\n </button>\n </div>\n </div>\n </ng-template>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column;gap:24px}.bpmn__container{position:relative;background-color:var(--cds-layer);width:100%}.bpmn__modeler{width:100%;height:100%;flex-direction:row;padding:1px;box-sizing:border-box;outline:1px solid var(--cds-border-subtle);outline-offset:-1px}.bpmn__modeler ::ng-deep .djs-container>svg{outline:none!important}.bpmn__modeler-canvas{width:100%;position:relative}.bpmn__modeler-canvas .markers-visibility-toggle-wrapper{position:absolute;bottom:55px;right:15px;z-index:100}.bpmn__modeler-canvas .markers-visibility-toggle{display:flex;align-items:center;gap:6px;height:32px;padding:0 10px;border:none;border-radius:2px;background-color:var(--cds-layer);cursor:pointer;color:var(--cds-text-secondary);transition:background-color .15s,color .15s}.bpmn__modeler-canvas .markers-visibility-toggle:hover{background-color:var(--cds-layer-hover);color:var(--cds-text-primary)}.bpmn__modeler-canvas .markers-visibility-toggle:focus{outline:2px solid var(--cds-focus);outline-offset:-2px}.bpmn__modeler-canvas .markers-visibility-toggle__label{font-size:12px;white-space:nowrap}.bpmn__modeler-panel{width:481px;padding-left:1px;box-shadow:inset 1px 0 0 0 var(--cds-border-subtle);box-sizing:border-box}.bpmn__loading{width:100%;height:100%;display:flex;justify-content:center;align-items:center;background-color:var(--cds-background-selected)}.page-header-actions{display:flex;width:100%;justify-content:space-between;align-items:center;gap:16px}.page-header-actions__left-container{display:flex;gap:16px;align-items:center}.page-header-actions__tags{display:flex;gap:8px;align-items:center}.page-header-actions__version-dropdown{width:150px}.page-header-actions__toggles{display:flex;gap:16px;align-items:center}.page-header-actions__toggles ::ng-deep cds-toggle{display:inline-flex;align-items:center}.page-header-actions__toggles ::ng-deep .cds--toggle__label-text{display:none}.page-header-actions__buttons{display:flex;gap:16px;align-items:center;flex-shrink:0}.valtimo-process-builder__header{display:flex;justify-content:space-between}.valtimo-process-builder__actions>*:not(:last-child){margin-right:8px}.validation-errors-list{position:absolute;top:8px;right:8px;z-index:10;width:320px;max-height:250px;overflow-y:auto;border:1px solid var(--cds-border-subtle);background-color:var(--cds-layer);border-radius:4px;box-shadow:0 2px 6px #00000026}.validation-errors-list details[open]>summary .validation-errors-list__arrow{transform:rotate(90deg)}.validation-errors-list__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;font-size:14px;font-weight:600;color:var(--cds-support-error, #da1e28);cursor:pointer;list-style:none;-webkit-user-select:none;user-select:none}.validation-errors-list__header::-webkit-details-marker{display:none}.validation-errors-list__arrow{display:inline-flex;width:16px;height:16px;fill:currentColor;transition:transform .15s ease;flex-shrink:0}.validation-errors-list__items{display:flex;flex-direction:column;border-top:1px solid var(--cds-border-subtle)}.validation-errors-list__item{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border:none;border-bottom:1px solid var(--cds-border-subtle);border-left:3px solid var(--cds-support-error, #da1e28);background-color:var(--cds-notification-error-background, #fff1f1);text-align:left;cursor:pointer;font-family:inherit}.validation-errors-list__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}.validation-errors-list__item:last-child{border-bottom:none}.validation-errors-list__item:hover{filter:brightness(.97)}.validation-errors-list__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;margin-top:1px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}.validation-errors-list__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}.validation-errors-list__details{display:flex;flex-direction:column;gap:2px}.validation-errors-list__element{font-size:13px;font-weight:600;color:var(--cds-text-primary)}.validation-errors-list__reason{font-size:13px;color:var(--cds-text-primary)}::ng-deep .highlight-overlay-error:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-error, #da1e28)!important}::ng-deep .highlight-overlay-warning:not(.djs-connection) .djs-visual>:nth-child(1){stroke:var(--cds-support-warning, #f1c21b)!important}::ng-deep .djs-overlay-validation-error{overflow:visible!important;pointer-events:all!important}::ng-deep .validation-error-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-error-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-error-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-error, #da1e28);color:var(--cds-support-error, #da1e28);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-error-overlay:hover ::ng-deep .validation-error-overlay__text,::ng-deep .validation-error-overlay--active ::ng-deep .validation-error-overlay__text{display:block}::ng-deep .validation-warning-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .validation-warning-overlay__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);font-size:14px;font-weight:700;line-height:0}::ng-deep .validation-warning-overlay__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .validation-warning-overlay:hover ::ng-deep .validation-warning-overlay__text,::ng-deep .validation-warning-overlay--active ::ng-deep .validation-warning-overlay__text{display:block}::ng-deep .djs-overlay-activity-marker{overflow:visible!important;pointer-events:all!important}::ng-deep .activity-marker-overlay{display:flex;gap:2px}::ng-deep .activity-marker-badge{position:relative;cursor:pointer;pointer-events:all}::ng-deep .activity-marker-badge__icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;font-size:14px;font-weight:700;line-height:0}::ng-deep .activity-marker-badge__text{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .activity-marker-badge:hover ::ng-deep .activity-marker-badge__text,::ng-deep .activity-marker-badge--active ::ng-deep .activity-marker-badge__text{display:block}::ng-deep .activity-marker-badge--process-link ::ng-deep .activity-marker-badge__icon{background-color:var(--cds-support-info, #0043ce);color:var(--cds-text-on-color, #ffffff)}::ng-deep .activity-marker-badge--process-link ::ng-deep .activity-marker-badge__text{border:1px solid var(--cds-support-info, #0043ce);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff)}::ng-deep .activity-marker-badge--execution-listener ::ng-deep .activity-marker-badge__icon{background-color:var(--cds-purple-60, #8a3ffc);color:var(--cds-text-on-color, #ffffff)}::ng-deep .activity-marker-badge--execution-listener ::ng-deep .activity-marker-badge__text{border:1px solid var(--cds-purple-60, #8a3ffc);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff)}::ng-deep .activity-marker-badge--task-listener ::ng-deep .activity-marker-badge__icon{background-color:var(--cds-teal-50, #009d9a);color:var(--cds-text-on-color, #ffffff)}::ng-deep .activity-marker-badge--task-listener ::ng-deep .activity-marker-badge__text{border:1px solid var(--cds-teal-50, #009d9a);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff)}::ng-deep .validation-errors-panel{padding:8px 12px;display:flex;flex-direction:column;gap:8px}::ng-deep .validation-errors-panel__item{display:flex;align-items:flex-start;gap:8px;padding:8px 12px;background-color:var(--cds-notification-error-background, #fff1f1);border-left:3px solid var(--cds-support-error, #da1e28)}::ng-deep .validation-errors-panel__item.warning{background-color:var(--cds-notification-warning-background, #fdf6dd);border-left-color:var(--cds-support-warning, #f1c21b)}::ng-deep .validation-errors-panel__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;min-width:18px;border-radius:50%;background-color:var(--cds-support-error, #da1e28);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700;line-height:0}::ng-deep .validation-errors-panel__icon.warning{background-color:var(--cds-support-warning, #f1c21b);color:var(--cds-text-primary, #161616)}::ng-deep .validation-errors-panel__reason{color:var(--cds-text-primary, #161616);font-size:13px;line-height:18px}::ng-deep .bio-properties-panel-entry.validation-error-field .bio-properties-panel-input,::ng-deep .bio-properties-panel-entry.validation-error-field .bio-properties-panel-textfield,::ng-deep .bio-properties-panel-entry.validation-error-field .bio-properties-panel-feel-editor-container{border:2px solid var(--cds-support-error, #da1e28)!important;background-color:var(--cds-notification-error-background, #fff1f1)!important}::ng-deep .expression-editor-param input.validation-error-param,::ng-deep input.expression-editor-input.validation-error-param,::ng-deep .expression-editor-technical input.validation-error-param,::ng-deep .expression-editor-technical textarea.validation-error-param{border:2px solid #da1e28!important;background-color:#fff1f1!important;border-color:#da1e28!important}::ng-deep .process-link-properties-panel{padding:8px 12px 16px;width:100%;display:flex;flex-direction:column;gap:16px}::ng-deep .process-link-properties-panel__buttons,::ng-deep .process-link-properties-panel__header{width:100%;display:flex;gap:16px}::ng-deep .process-link-properties-panel__header{align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--cds-border-subtle-00);padding-bottom:8px;padding-left:8px;padding-right:8px}::ng-deep .process-link-properties-panel__title{color:var(--cds-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;margin:auto 0}::ng-deep .process-link-properties-panel__title-container{display:flex;flex-direction:column;gap:4px}::ng-deep .process-link-properties-panel__title-container :last-child{color:var(--cds-text-helper);font-style:italic}::ng-deep .process-link-properties-panel .cds--tag{margin:0}::ng-deep .process-link-properties-panel .cds--btn{flex-shrink:1;width:100%;display:flex;align-items:center}::ng-deep .djs-overlay-autofilled-indicator{overflow:visible!important;pointer-events:all!important}::ng-deep .autofilled-indicator-overlay{position:relative;cursor:pointer;pointer-events:all}::ng-deep .autofilled-indicator-overlay .autofilled-indicator-icon{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background-color:var(--cds-support-info, #0043ce);color:var(--cds-text-on-color, #ffffff);font-size:14px;font-weight:700;line-height:0}::ng-deep .autofilled-indicator-overlay .autofilled-indicator-tooltip{display:none;position:absolute;bottom:100%;left:50%;transform:translate(-50%);margin-bottom:4px;border:1px solid var(--cds-support-info, #0043ce);color:var(--cds-text-primary, #161616);background-color:var(--cds-layer, #ffffff);padding:4px 8px;border-radius:2px;font-size:14px;white-space:nowrap;max-width:350px;overflow:hidden;text-overflow:ellipsis;z-index:10}::ng-deep .autofilled-indicator-overlay:hover .autofilled-indicator-tooltip{display:block}::ng-deep .autofilled-notification-panel{display:flex;align-items:center;gap:8px;padding:8px 12px;background-color:var(--cds-layer-02, #f4f4f4);border-left:3px solid var(--cds-support-info, #0043ce);margin-bottom:8px}::ng-deep .autofilled-notification-panel__icon{display:flex;align-items:center;justify-content:center;min-width:18px;height:18px;border-radius:50%;background-color:var(--cds-support-info, #0043ce);color:var(--cds-text-on-color, #ffffff);font-size:12px;font-weight:700}::ng-deep .autofilled-notification-panel__message{flex:1;font-size:12px;color:var(--cds-text-primary, #161616)}::ng-deep .autofilled-notification-panel__dismiss{background:none;border:none;cursor:pointer;padding:2px 6px;font-size:16px;color:var(--cds-text-secondary, #525252);line-height:1}::ng-deep .autofilled-notification-panel__dismiss:hover{color:var(--cds-text-primary, #161616)}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
3103
|
+
}], ctorParameters: () => [{ type: i1$1.BreadcrumbService }, { type: i2$2.IconService }, { type: i3.NGXLogger }, { type: i1$1.ModalService }, { type: i2.GlobalNotificationService }, { type: i1$1.PageHeaderService }, { type: i1$1.PageTitleService }, { type: i5.ProcessLinkService }, { type: i5.ProcessLinkStateService }, { type: ProcessManagementEditorService }, { type: ProcessManagementService }, { type: i7.ProcessService }, { type: i8.ActivatedRoute }, { type: i8.Router }, { type: i9.TranslateService }, { type: i10.PluginTranslationService }, { type: i2.EditPermissionsService }, { type: i5.ProcessLinkBuildingBlockApiService }, { type: ProcessBeanService }], propDecorators: { modelerElementRef: [{
|
|
1955
3104
|
type: ViewChild,
|
|
1956
3105
|
args: ['modeler', { static: false }]
|
|
1957
3106
|
}], modelerPanelElementRef: [{
|
|
@@ -2070,7 +3219,7 @@ class ProcessManagementListComponent {
|
|
|
2070
3219
|
this.processToDelete$.next(process.processDefinition);
|
|
2071
3220
|
this.showDeleteModal$.next(true);
|
|
2072
3221
|
}
|
|
2073
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementListComponent, deps: [{ token: i2$2.IconService }, { token: i2
|
|
3222
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementListComponent, deps: [{ token: i2$2.IconService }, { token: i2.GlobalNotificationService }, { token: ProcessManagementService }, { token: ProcessManagementStateService }, { token: i9.TranslateService }, { token: i2.EnvironmentService }, { token: i8.ActivatedRoute }, { token: i2.EditPermissionsService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2074
3223
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: ProcessManagementListComponent, isStandalone: true, selector: "valtimo-process-management-list", outputs: { processSelected: "processSelected" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<valtimo-carbon-list\n [actionItems]=\"ACTION_ITEMS\"\n [showActionItems]=\"hasEditPermissions$ | async\"\n [fields]=\"FIELDS\"\n [header]=\"false\"\n [items]=\"processDefinitions$ | async\"\n [loading]=\"loading$ | async\"\n (rowClicked)=\"editProcessDefinition($event)\"\n>\n <ng-container carbonToolbarContent>\n <button\n *ngIf=\"hasEditPermissions$ | async\"\n cdsButton=\"ghost\"\n iconOnly=\"true\"\n [attr.data-test-id]=\"testIds.uploadButton\"\n (click)=\"openModal()\"\n >\n <svg cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n\n <ng-container [ngTemplateOutlet]=\"createProcess\"></ng-container>\n </ng-container>\n\n <valtimo-no-results\n [action]=\"createProcess\"\n [title]=\"'processManagement.noResults.title' | translate\"\n [description]=\"'processManagement.noResults.' + $context() + 'Description' | translate\"\n ></valtimo-no-results>\n</valtimo-carbon-list>\n\n<valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"processManagement.deleteModal.content\"\n [outputOnConfirm]=\"processToDelete$ | async\"\n [showModalSubject$]=\"showDeleteModal$\"\n titleTranslationKey=\"processManagement.deleteModal.title\"\n (confirmEvent)=\"onDeleteConfirm($event)\"\n></valtimo-confirmation-modal>\n\n<ng-template #createProcess>\n <button *ngIf=\"hasEditPermissions$ | async\" cdsButton=\"primary\" [attr.data-test-id]=\"testIds.createProcessButton\" (click)=\"onCreateProcess()\">\n {{ 'processManagement.createProcess' | translate }}\n\n <svg cdsIcon=\"add\" size=\"16\" class=\"cds--btn__icon\"></svg>\n </button>\n</ng-template>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$2.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: CarbonListModule }, { kind: "component", type: i1$1.CarbonListComponent, selector: "valtimo-carbon-list", inputs: ["items", "fields", "tableTranslations", "paginatorConfig", "pagination", "loading", "skeletonRowCount", "actions", "actionItems", "showActionItems", "header", "hideColumnHeader", "initialSortState", "sortState", "isSearchable", "initialSearchValue", "searchDebounceMs", "invalidSearchFields", "searchFields", "enableSingleSelection", "lastColumnTemplate", "paginationIdentifier", "showSelectionColumn", "striped", "hideToolbar", "lockedTooltipTranslationKey", "movingRowsEnabled", "dragAndDrop", "dragAndDropDisabled", "expandedRowTemplate", "expandedRowKey", "trackByKey"], outputs: ["rowClicked", "paginationClicked", "paginationSet", "search", "sortChanged", "moveRow", "itemsReordered"] }, { kind: "component", type: i1$1.CarbonNoResultsComponent, selector: "valtimo-no-results", inputs: ["action", "description", "illustration", "title", "smallPadding", "collapseVertically", "alwaysRenderVertically"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i2$2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i1$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2075
3224
|
}
|
|
2076
3225
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementListComponent, decorators: [{
|
|
@@ -2084,7 +3233,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2084
3233
|
TranslateModule,
|
|
2085
3234
|
ConfirmationModalModule,
|
|
2086
3235
|
], template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<valtimo-carbon-list\n [actionItems]=\"ACTION_ITEMS\"\n [showActionItems]=\"hasEditPermissions$ | async\"\n [fields]=\"FIELDS\"\n [header]=\"false\"\n [items]=\"processDefinitions$ | async\"\n [loading]=\"loading$ | async\"\n (rowClicked)=\"editProcessDefinition($event)\"\n>\n <ng-container carbonToolbarContent>\n <button\n *ngIf=\"hasEditPermissions$ | async\"\n cdsButton=\"ghost\"\n iconOnly=\"true\"\n [attr.data-test-id]=\"testIds.uploadButton\"\n (click)=\"openModal()\"\n >\n <svg cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n\n <ng-container [ngTemplateOutlet]=\"createProcess\"></ng-container>\n </ng-container>\n\n <valtimo-no-results\n [action]=\"createProcess\"\n [title]=\"'processManagement.noResults.title' | translate\"\n [description]=\"'processManagement.noResults.' + $context() + 'Description' | translate\"\n ></valtimo-no-results>\n</valtimo-carbon-list>\n\n<valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"processManagement.deleteModal.content\"\n [outputOnConfirm]=\"processToDelete$ | async\"\n [showModalSubject$]=\"showDeleteModal$\"\n titleTranslationKey=\"processManagement.deleteModal.title\"\n (confirmEvent)=\"onDeleteConfirm($event)\"\n></valtimo-confirmation-modal>\n\n<ng-template #createProcess>\n <button *ngIf=\"hasEditPermissions$ | async\" cdsButton=\"primary\" [attr.data-test-id]=\"testIds.createProcessButton\" (click)=\"onCreateProcess()\">\n {{ 'processManagement.createProcess' | translate }}\n\n <svg cdsIcon=\"add\" size=\"16\" class=\"cds--btn__icon\"></svg>\n </button>\n</ng-template>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
2087
|
-
}], ctorParameters: () => [{ type: i2$2.IconService }, { type: i2
|
|
3236
|
+
}], ctorParameters: () => [{ type: i2$2.IconService }, { type: i2.GlobalNotificationService }, { type: ProcessManagementService }, { type: ProcessManagementStateService }, { type: i9.TranslateService }, { type: i2.EnvironmentService }, { type: i8.ActivatedRoute }, { type: i2.EditPermissionsService }], propDecorators: { processSelected: [{
|
|
2088
3237
|
type: Output
|
|
2089
3238
|
}] } });
|
|
2090
3239
|
|
|
@@ -2103,45 +3252,205 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2103
3252
|
* See the License for the specific language governing permissions and
|
|
2104
3253
|
* limitations under the License.
|
|
2105
3254
|
*/
|
|
3255
|
+
var UPLOAD_STEP;
|
|
3256
|
+
(function (UPLOAD_STEP) {
|
|
3257
|
+
UPLOAD_STEP["FILE_SELECT"] = "fileSelect";
|
|
3258
|
+
UPLOAD_STEP["REVIEW"] = "review";
|
|
3259
|
+
UPLOAD_STEP["SUMMARY"] = "summary";
|
|
3260
|
+
})(UPLOAD_STEP || (UPLOAD_STEP = {}));
|
|
2106
3261
|
class ProcessManagementUploadComponent {
|
|
2107
|
-
constructor(formBuilder, notificationService, processManagementService, processManagementStateService, processLinkService, translateService) {
|
|
3262
|
+
constructor(formBuilder, notificationService, processManagementService, processManagementStateService, processLinkService, translateService, changeDetectorRef) {
|
|
2108
3263
|
this.formBuilder = formBuilder;
|
|
2109
3264
|
this.notificationService = notificationService;
|
|
2110
3265
|
this.processManagementService = processManagementService;
|
|
2111
3266
|
this.processManagementStateService = processManagementStateService;
|
|
2112
3267
|
this.processLinkService = processLinkService;
|
|
2113
3268
|
this.translateService = translateService;
|
|
3269
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
2114
3270
|
this.modalOpen$ = this.processManagementStateService.openModal$;
|
|
2115
3271
|
this.showReplaceConfirmationModal$ = new BehaviorSubject(false);
|
|
2116
3272
|
this.replaceModalContent = '';
|
|
2117
3273
|
this._conflictingProcessDefinitionId = null;
|
|
2118
|
-
|
|
3274
|
+
// Extensions need a leading dot: the file dialog only filters on valid accept tokens, and Carbon
|
|
3275
|
+
// matches a dropped file on its dot-prefixed extension
|
|
3276
|
+
this.ACCEPTED_FILES = ['.bpmn', '.zip'];
|
|
3277
|
+
this.UPLOAD_STEP = UPLOAD_STEP;
|
|
2119
3278
|
this.form = this.formBuilder.group({
|
|
2120
3279
|
file: this.formBuilder.control(new Set(), [Validators.required]),
|
|
2121
3280
|
});
|
|
2122
|
-
|
|
3281
|
+
// The current control value is read instead of the emitted one, so this also reports the selection
|
|
3282
|
+
// correctly when the footer is re-created after going back to the file select step
|
|
3283
|
+
this.fileSelected$ = this.form.get('file')?.valueChanges.pipe(startWith(null), map$1(() => {
|
|
3284
|
+
const value = this.form.get('file')?.value;
|
|
3285
|
+
return !!(value instanceof Set && value.size > 0);
|
|
3286
|
+
}));
|
|
3287
|
+
this.activeStep$ = new BehaviorSubject(UPLOAD_STEP.FILE_SELECT);
|
|
3288
|
+
this.preview$ = new BehaviorSubject(null);
|
|
3289
|
+
this.missingReferences$ = new BehaviorSubject([]);
|
|
3290
|
+
this.importing$ = new BehaviorSubject(false);
|
|
3291
|
+
/**
|
|
3292
|
+
* Leaving the file select step destroys cds-file-uploader, which empties the form control: every
|
|
3293
|
+
* cds-file emits (remove) from its own ngOnDestroy. So the selection is kept here to import it
|
|
3294
|
+
* afterwards, and to restore it when the user goes back.
|
|
3295
|
+
*/
|
|
3296
|
+
this._selectedFile = null;
|
|
3297
|
+
this._selectedFileItems = null;
|
|
2123
3298
|
}
|
|
2124
3299
|
closeModal() {
|
|
2125
3300
|
this.processManagementStateService.closeModal();
|
|
2126
3301
|
setTimeout(() => {
|
|
2127
3302
|
this.form.reset();
|
|
3303
|
+
this.activeStep$.next(UPLOAD_STEP.FILE_SELECT);
|
|
3304
|
+
this.preview$.next(null);
|
|
3305
|
+
this.missingReferences$.next([]);
|
|
3306
|
+
this.importing$.next(false);
|
|
3307
|
+
this._selectedFile = null;
|
|
3308
|
+
this._selectedFileItems = null;
|
|
2128
3309
|
}, CARBON_CONSTANTS.modalAnimationMs);
|
|
2129
3310
|
}
|
|
2130
3311
|
uploadProcessBpmn() {
|
|
2131
|
-
const
|
|
2132
|
-
if (!
|
|
3312
|
+
const file = this.form.value?.file?.values()?.next()?.value?.file;
|
|
3313
|
+
if (!file)
|
|
2133
3314
|
return;
|
|
3315
|
+
// A package of an earlier selection must not be imported when another file is uploaded
|
|
3316
|
+
this._selectedFile = null;
|
|
3317
|
+
this._selectedFileItems = null;
|
|
3318
|
+
if (this.isZip(file)) {
|
|
3319
|
+
this.previewProcessPackage(file);
|
|
3320
|
+
return;
|
|
3321
|
+
}
|
|
2134
3322
|
if (this.processManagementService.$context() === 'case') {
|
|
2135
|
-
this.uploadForCase(
|
|
3323
|
+
this.uploadForCase(file);
|
|
2136
3324
|
}
|
|
2137
3325
|
else {
|
|
2138
|
-
this.uploadIndependent(
|
|
3326
|
+
this.uploadIndependent(file);
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
importProcessPackage() {
|
|
3330
|
+
const existingProcessDefinitionKeys = this.preview$.value?.existingProcessDefinitionKeys ?? [];
|
|
3331
|
+
// Ask before replacing, the same way uploading a single bpmn file does
|
|
3332
|
+
if (existingProcessDefinitionKeys.length > 0) {
|
|
3333
|
+
this.showReplaceConfirmation(this.translateService.instant('processManagement.upload.replaceContentWithDuplicates', {
|
|
3334
|
+
duplicates: existingProcessDefinitionKeys.join(', '),
|
|
3335
|
+
}));
|
|
3336
|
+
return;
|
|
3337
|
+
}
|
|
3338
|
+
this.executeImportProcessPackage();
|
|
3339
|
+
}
|
|
3340
|
+
showReplaceConfirmation(content) {
|
|
3341
|
+
this.replaceModalContent = content;
|
|
3342
|
+
// The content is bound from a plain field, so this OnPush component has to be checked again.
|
|
3343
|
+
// The bpmn flow sets it from an http error callback, which does not mark this view dirty itself.
|
|
3344
|
+
this.changeDetectorRef.markForCheck();
|
|
3345
|
+
this.showReplaceConfirmationModal$.next(true);
|
|
3346
|
+
}
|
|
3347
|
+
executeImportProcessPackage() {
|
|
3348
|
+
const file = this._selectedFile;
|
|
3349
|
+
if (!file)
|
|
3350
|
+
return;
|
|
3351
|
+
this.importing$.next(true);
|
|
3352
|
+
this.processManagementService
|
|
3353
|
+
.importProcessDefinition(this.toFormData(file), this._pluginConfigurationMapping?.getMappings())
|
|
3354
|
+
.pipe(take(1))
|
|
3355
|
+
.subscribe({
|
|
3356
|
+
next: result => {
|
|
3357
|
+
this.importing$.next(false);
|
|
3358
|
+
this.processManagementStateService.reloadDefinitions();
|
|
3359
|
+
if (result.missingReferences.length > 0) {
|
|
3360
|
+
// Keep the summary on screen: a toast disappears before it can be read
|
|
3361
|
+
this.missingReferences$.next(result.missingReferences);
|
|
3362
|
+
this.activeStep$.next(UPLOAD_STEP.SUMMARY);
|
|
3363
|
+
return;
|
|
3364
|
+
}
|
|
3365
|
+
this.notificationService.showNotification({
|
|
3366
|
+
type: 'success',
|
|
3367
|
+
title: this.translateService.instant('processManagement.upload.success'),
|
|
3368
|
+
});
|
|
3369
|
+
this.closeModal();
|
|
3370
|
+
},
|
|
3371
|
+
error: () => {
|
|
3372
|
+
this.importing$.next(false);
|
|
3373
|
+
this.notificationService.showNotification({
|
|
3374
|
+
type: 'error',
|
|
3375
|
+
title: this.translateService.instant('processManagement.upload.failure'),
|
|
3376
|
+
});
|
|
3377
|
+
},
|
|
3378
|
+
});
|
|
3379
|
+
}
|
|
3380
|
+
onBackClick() {
|
|
3381
|
+
this.activeStep$.next(UPLOAD_STEP.FILE_SELECT);
|
|
3382
|
+
// Restore the selection the file uploader dropped when it was destroyed
|
|
3383
|
+
if (this._selectedFileItems) {
|
|
3384
|
+
this.form.get('file')?.setValue(this._selectedFileItems);
|
|
2139
3385
|
}
|
|
2140
3386
|
}
|
|
3387
|
+
getMissingReferenceGroups(missingReferences) {
|
|
3388
|
+
return missingReferences.reduce((groups, missingReference) => {
|
|
3389
|
+
const group = groups.find(({ type }) => type === missingReference.type);
|
|
3390
|
+
if (group) {
|
|
3391
|
+
group.references = [...new Set([...group.references, missingReference.reference])];
|
|
3392
|
+
return groups;
|
|
3393
|
+
}
|
|
3394
|
+
return [...groups, { type: missingReference.type, references: [missingReference.reference] }];
|
|
3395
|
+
}, []);
|
|
3396
|
+
}
|
|
3397
|
+
getReplacedElementGroups(elementsToReplace) {
|
|
3398
|
+
return (elementsToReplace ?? []).reduce((groups, element) => {
|
|
3399
|
+
const group = groups.find(({ type }) => type === element.type);
|
|
3400
|
+
if (group) {
|
|
3401
|
+
group.keys = [...new Set([...group.keys, element.key])];
|
|
3402
|
+
return groups;
|
|
3403
|
+
}
|
|
3404
|
+
return [...groups, { type: element.type, keys: [element.key] }];
|
|
3405
|
+
}, []);
|
|
3406
|
+
}
|
|
3407
|
+
previewProcessPackage(file) {
|
|
3408
|
+
const fileItem = this.form.value?.file?.values()?.next()?.value;
|
|
3409
|
+
this.processManagementService
|
|
3410
|
+
.previewProcessDefinitionImport(this.toFormData(file))
|
|
3411
|
+
.pipe(take(1))
|
|
3412
|
+
.subscribe({
|
|
3413
|
+
next: preview => {
|
|
3414
|
+
this._selectedFile = file;
|
|
3415
|
+
this._selectedFileItems = this.form.value?.file ?? null;
|
|
3416
|
+
this.preview$.next(preview);
|
|
3417
|
+
this.missingReferences$.next(preview.missingReferences);
|
|
3418
|
+
// Nothing to review, so the package can be imported straight away. Elements that will be
|
|
3419
|
+
// replaced are shown in the review step first, so the replacement is a conscious choice.
|
|
3420
|
+
if (preview.pluginConfigurations.length === 0 &&
|
|
3421
|
+
preview.missingReferences.length === 0 &&
|
|
3422
|
+
preview.elementsToReplace.length === 0) {
|
|
3423
|
+
this.importProcessPackage();
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3426
|
+
this.activeStep$.next(UPLOAD_STEP.REVIEW);
|
|
3427
|
+
},
|
|
3428
|
+
error: () => {
|
|
3429
|
+
if (fileItem) {
|
|
3430
|
+
fileItem.invalid = true;
|
|
3431
|
+
fileItem.invalidTitle = this.translateService.instant('processManagement.upload.invalidZip.title');
|
|
3432
|
+
fileItem.invalidText = this.translateService.instant('processManagement.upload.invalidZip.text');
|
|
3433
|
+
}
|
|
3434
|
+
},
|
|
3435
|
+
});
|
|
3436
|
+
}
|
|
3437
|
+
isZip(file) {
|
|
3438
|
+
return file.name.toLowerCase().endsWith('.zip');
|
|
3439
|
+
}
|
|
3440
|
+
toFormData(file) {
|
|
3441
|
+
const formData = new FormData();
|
|
3442
|
+
formData.append('file', file, file.name);
|
|
3443
|
+
return formData;
|
|
3444
|
+
}
|
|
2141
3445
|
confirmReplace() {
|
|
2142
3446
|
const processDefinitionId = this._conflictingProcessDefinitionId;
|
|
2143
3447
|
this.replaceModalContent = '';
|
|
2144
3448
|
this._conflictingProcessDefinitionId = null;
|
|
3449
|
+
// A selected package is only set while importing a zip, which replaces through the import itself
|
|
3450
|
+
if (this._selectedFile) {
|
|
3451
|
+
this.executeImportProcessPackage();
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
2145
3454
|
if (!processDefinitionId) {
|
|
2146
3455
|
this.notificationService.showNotification({
|
|
2147
3456
|
type: 'error',
|
|
@@ -2192,11 +3501,9 @@ class ProcessManagementUploadComponent {
|
|
|
2192
3501
|
error: (error) => {
|
|
2193
3502
|
const isConflict = error instanceof HttpErrorResponse && error.status === 409;
|
|
2194
3503
|
if (isConflict) {
|
|
2195
|
-
const body = error
|
|
2196
|
-
.error;
|
|
3504
|
+
const body = error.error;
|
|
2197
3505
|
this._conflictingProcessDefinitionId = body?.processDefinitionId ?? null;
|
|
2198
|
-
this.
|
|
2199
|
-
this.showReplaceConfirmationModal$.next(true);
|
|
3506
|
+
this.showReplaceConfirmation(this.buildReplaceModalContent(body));
|
|
2200
3507
|
return;
|
|
2201
3508
|
}
|
|
2202
3509
|
this.notificationService.showNotification({
|
|
@@ -2221,11 +3528,9 @@ class ProcessManagementUploadComponent {
|
|
|
2221
3528
|
error: (error) => {
|
|
2222
3529
|
const isConflict = error instanceof HttpErrorResponse && error.status === 409;
|
|
2223
3530
|
if (isConflict) {
|
|
2224
|
-
const body = error
|
|
2225
|
-
.error;
|
|
3531
|
+
const body = error.error;
|
|
2226
3532
|
this._conflictingProcessDefinitionId = body?.processDefinitionId ?? null;
|
|
2227
|
-
this.
|
|
2228
|
-
this.showReplaceConfirmationModal$.next(true);
|
|
3533
|
+
this.showReplaceConfirmation(this.buildReplaceModalContent(body));
|
|
2229
3534
|
return;
|
|
2230
3535
|
}
|
|
2231
3536
|
this.notificationService.showNotification({
|
|
@@ -2244,8 +3549,8 @@ class ProcessManagementUploadComponent {
|
|
|
2244
3549
|
}
|
|
2245
3550
|
return this.translateService.instant('processManagement.upload.replaceContent');
|
|
2246
3551
|
}
|
|
2247
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementUploadComponent, deps: [{ token: i1$2.FormBuilder }, { token: i2
|
|
2248
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: ProcessManagementUploadComponent, isStandalone: true, selector: "valtimo-process-management-upload", ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal valtimoCdsModal [open]=\"modalOpen$ | async\" size=\"sm\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ 'processManagement.upload.modalTitle' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\">\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [buttonText]=\"'processManagement.upload.buttonText' | translate\"\n [description]=\"'processManagement.upload.description' | translate\"\n [multiple]=\"false\"\n [title]=\"'processManagement.upload.title' | translate\"\n buttonType=\"primary\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"(fileSelected$ | async) === false\"\n (click)=\"uploadProcessBpmn()\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n\n<valtimo-render-in-body>\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"processManagement.upload.replaceConfirm\"\n confirmButtonType=\"danger\"\n cancelButtonTextTranslationKey=\"interface.cancel\"\n [content]=\"replaceModalContent\"\n [showModalSubject$]=\"showReplaceConfirmationModal$\"\n titleTranslationKey=\"processManagement.upload.replaceTitle\"\n (confirmEvent)=\"confirmReplace()\"\n (cancelEvent)=\"clearReplaceModal()\"\n ></valtimo-confirmation-modal>\n</valtimo-render-in-body>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: FileUploaderModule }, { kind: "component", type: i2$2.FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: ["buttonText", "buttonType", "title", "description", "accept", "multiple", "skeleton", "size", "fileItemSize", "drop", "dropText", "fileUploaderId", "files", "disabled"], outputs: ["filesChange"] }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i2$2.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i2$2.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i2$2.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i2$2.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i2$2.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i2$2.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$2.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i1$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }, { kind: "component", type: RenderInBodyComponent, selector: "valtimo-render-in-body" }, { kind: "directive", type: ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3552
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementUploadComponent, deps: [{ token: i1$2.FormBuilder }, { token: i2.GlobalNotificationService }, { token: ProcessManagementService }, { token: ProcessManagementStateService }, { token: i5.ProcessLinkService }, { token: i9.TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3553
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: ProcessManagementUploadComponent, isStandalone: true, selector: "valtimo-process-management-upload", viewQueries: [{ propertyName: "_pluginConfigurationMapping", first: true, predicate: PluginConfigurationMappingComponent, descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal valtimoCdsModal [open]=\"modalOpen$ | async\" size=\"sm\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ 'processManagement.upload.modalTitle' | translate }}</h3>\n </cds-modal-header>\n\n <ng-container\n *ngIf=\"{\n activeStep: activeStep$ | async,\n preview: preview$ | async,\n missingReferences: missingReferences$ | async,\n importing: importing$ | async,\n } as obs\"\n >\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\" [ngSwitch]=\"obs.activeStep\">\n <cds-file-uploader\n *ngSwitchCase=\"UPLOAD_STEP.FILE_SELECT\"\n [accept]=\"ACCEPTED_FILES\"\n [buttonText]=\"'processManagement.upload.buttonText' | translate\"\n [description]=\"'processManagement.upload.description' | translate\"\n [multiple]=\"false\"\n [title]=\"'processManagement.upload.title' | translate\"\n buttonType=\"primary\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n\n <div *ngSwitchCase=\"UPLOAD_STEP.REVIEW\" class=\"process-management-upload__review\">\n <ng-container *ngFor=\"let group of getMissingReferenceGroups(obs.missingReferences)\">\n <cds-inline-notification\n [notificationObj]=\"{\n type:\n group.type === 'SUB_PROCESS' || group.type === 'DECISION_DEFINITION'\n ? 'warning'\n : 'error',\n title:\n 'processManagement.upload.missingReference.' + group.type + '.title' | translate,\n message:\n ('processManagement.upload.missingReference.' + group.type + '.message'\n | translate) +\n ' ' +\n group.references.join(', '),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </ng-container>\n\n <ng-container\n *ngFor=\"let group of getReplacedElementGroups(obs.preview?.elementsToReplace ?? [])\"\n >\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'warning',\n title: 'processManagement.upload.willBeReplaced.' + group.type + '.title' | translate,\n message:\n ('processManagement.upload.willBeReplaced.' + group.type + '.message' | translate) +\n ' ' +\n group.keys.join(', '),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </ng-container>\n\n <ng-container *ngIf=\"obs.preview?.pluginConfigurations?.length\">\n <p class=\"process-management-upload__description\">\n {{ 'processManagement.upload.pluginsDescription' | translate }}\n </p>\n\n <valtimo-plugin-configuration-mapping\n [pluginConfigurations]=\"obs.preview.pluginConfigurations\"\n ></valtimo-plugin-configuration-mapping>\n </ng-container>\n </div>\n\n <div *ngSwitchCase=\"UPLOAD_STEP.SUMMARY\" class=\"process-management-upload__review\">\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'success',\n title: 'processManagement.upload.success' | translate,\n message: 'processManagement.upload.summaryDescription' | translate,\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n\n <ng-container *ngFor=\"let group of getMissingReferenceGroups(obs.missingReferences)\">\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'warning',\n title:\n 'processManagement.upload.missingReference.' + group.type + '.title' | translate,\n message:\n ('processManagement.upload.missingReference.' + group.type + '.message'\n | translate) +\n ' ' +\n group.references.join(', '),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </ng-container>\n </div>\n </section>\n\n <cds-modal-footer>\n <ng-container *ngIf=\"obs.activeStep === UPLOAD_STEP.FILE_SELECT\">\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"(fileSelected$ | async) === false || obs.importing\"\n (click)=\"uploadProcessBpmn()\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"obs.activeStep === UPLOAD_STEP.REVIEW\">\n <button cdsButton=\"secondary\" (click)=\"onBackClick()\">\n {{ 'interface.back' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.preview?.canImport === false || obs.importing\"\n (click)=\"importProcessPackage()\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </ng-container>\n\n <button\n *ngIf=\"obs.activeStep === UPLOAD_STEP.SUMMARY\"\n cdsButton=\"primary\"\n (click)=\"closeModal()\"\n >\n {{ 'interface.close' | translate }}\n </button>\n </cds-modal-footer>\n </ng-container>\n</cds-modal>\n\n<valtimo-render-in-body>\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"processManagement.upload.replaceConfirm\"\n confirmButtonType=\"danger\"\n cancelButtonTextTranslationKey=\"interface.cancel\"\n [content]=\"replaceModalContent\"\n [showModalSubject$]=\"showReplaceConfirmationModal$\"\n titleTranslationKey=\"processManagement.upload.replaceTitle\"\n (confirmEvent)=\"confirmReplace()\"\n (cancelEvent)=\"clearReplaceModal()\"\n ></valtimo-confirmation-modal>\n</valtimo-render-in-body>\n", styles: [".process-management-upload__review{display:flex;flex-direction:column;gap:16px}.process-management-upload__description{font-size:.875rem;line-height:1.25rem;color:var(--cds-text-secondary)}\n/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: FileUploaderModule }, { kind: "component", type: i2$2.FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: ["buttonText", "buttonType", "title", "description", "accept", "multiple", "skeleton", "size", "fileItemSize", "drop", "dropText", "fileUploaderId", "files", "disabled"], outputs: ["filesChange"] }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i2$2.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i2$2.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i2$2.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i2$2.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i2$2.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i2$2.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$2.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i1$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }, { kind: "component", type: RenderInBodyComponent, selector: "valtimo-render-in-body" }, { kind: "directive", type: ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "ngmodule", type: NotificationModule }, { kind: "component", type: i2$2.Notification, selector: "cds-notification, cds-inline-notification, ibm-notification, ibm-inline-notification", inputs: ["notificationObj"] }, { kind: "component", type: PluginConfigurationMappingComponent, selector: "valtimo-plugin-configuration-mapping", inputs: ["pluginConfigurations"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2249
3554
|
}
|
|
2250
3555
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementUploadComponent, decorators: [{
|
|
2251
3556
|
type: Component,
|
|
@@ -2260,8 +3565,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2260
3565
|
ConfirmationModalModule,
|
|
2261
3566
|
RenderInBodyComponent,
|
|
2262
3567
|
ValtimoCdsModalDirective,
|
|
2263
|
-
|
|
2264
|
-
|
|
3568
|
+
NotificationModule,
|
|
3569
|
+
PluginConfigurationMappingComponent,
|
|
3570
|
+
], template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal valtimoCdsModal [open]=\"modalOpen$ | async\" size=\"sm\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ 'processManagement.upload.modalTitle' | translate }}</h3>\n </cds-modal-header>\n\n <ng-container\n *ngIf=\"{\n activeStep: activeStep$ | async,\n preview: preview$ | async,\n missingReferences: missingReferences$ | async,\n importing: importing$ | async,\n } as obs\"\n >\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\" [ngSwitch]=\"obs.activeStep\">\n <cds-file-uploader\n *ngSwitchCase=\"UPLOAD_STEP.FILE_SELECT\"\n [accept]=\"ACCEPTED_FILES\"\n [buttonText]=\"'processManagement.upload.buttonText' | translate\"\n [description]=\"'processManagement.upload.description' | translate\"\n [multiple]=\"false\"\n [title]=\"'processManagement.upload.title' | translate\"\n buttonType=\"primary\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n\n <div *ngSwitchCase=\"UPLOAD_STEP.REVIEW\" class=\"process-management-upload__review\">\n <ng-container *ngFor=\"let group of getMissingReferenceGroups(obs.missingReferences)\">\n <cds-inline-notification\n [notificationObj]=\"{\n type:\n group.type === 'SUB_PROCESS' || group.type === 'DECISION_DEFINITION'\n ? 'warning'\n : 'error',\n title:\n 'processManagement.upload.missingReference.' + group.type + '.title' | translate,\n message:\n ('processManagement.upload.missingReference.' + group.type + '.message'\n | translate) +\n ' ' +\n group.references.join(', '),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </ng-container>\n\n <ng-container\n *ngFor=\"let group of getReplacedElementGroups(obs.preview?.elementsToReplace ?? [])\"\n >\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'warning',\n title: 'processManagement.upload.willBeReplaced.' + group.type + '.title' | translate,\n message:\n ('processManagement.upload.willBeReplaced.' + group.type + '.message' | translate) +\n ' ' +\n group.keys.join(', '),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </ng-container>\n\n <ng-container *ngIf=\"obs.preview?.pluginConfigurations?.length\">\n <p class=\"process-management-upload__description\">\n {{ 'processManagement.upload.pluginsDescription' | translate }}\n </p>\n\n <valtimo-plugin-configuration-mapping\n [pluginConfigurations]=\"obs.preview.pluginConfigurations\"\n ></valtimo-plugin-configuration-mapping>\n </ng-container>\n </div>\n\n <div *ngSwitchCase=\"UPLOAD_STEP.SUMMARY\" class=\"process-management-upload__review\">\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'success',\n title: 'processManagement.upload.success' | translate,\n message: 'processManagement.upload.summaryDescription' | translate,\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n\n <ng-container *ngFor=\"let group of getMissingReferenceGroups(obs.missingReferences)\">\n <cds-inline-notification\n [notificationObj]=\"{\n type: 'warning',\n title:\n 'processManagement.upload.missingReference.' + group.type + '.title' | translate,\n message:\n ('processManagement.upload.missingReference.' + group.type + '.message'\n | translate) +\n ' ' +\n group.references.join(', '),\n showClose: false,\n lowContrast: true,\n }\"\n ></cds-inline-notification>\n </ng-container>\n </div>\n </section>\n\n <cds-modal-footer>\n <ng-container *ngIf=\"obs.activeStep === UPLOAD_STEP.FILE_SELECT\">\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"(fileSelected$ | async) === false || obs.importing\"\n (click)=\"uploadProcessBpmn()\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"obs.activeStep === UPLOAD_STEP.REVIEW\">\n <button cdsButton=\"secondary\" (click)=\"onBackClick()\">\n {{ 'interface.back' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.preview?.canImport === false || obs.importing\"\n (click)=\"importProcessPackage()\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </ng-container>\n\n <button\n *ngIf=\"obs.activeStep === UPLOAD_STEP.SUMMARY\"\n cdsButton=\"primary\"\n (click)=\"closeModal()\"\n >\n {{ 'interface.close' | translate }}\n </button>\n </cds-modal-footer>\n </ng-container>\n</cds-modal>\n\n<valtimo-render-in-body>\n <valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"processManagement.upload.replaceConfirm\"\n confirmButtonType=\"danger\"\n cancelButtonTextTranslationKey=\"interface.cancel\"\n [content]=\"replaceModalContent\"\n [showModalSubject$]=\"showReplaceConfirmationModal$\"\n titleTranslationKey=\"processManagement.upload.replaceTitle\"\n (confirmEvent)=\"confirmReplace()\"\n (cancelEvent)=\"clearReplaceModal()\"\n ></valtimo-confirmation-modal>\n</valtimo-render-in-body>\n", styles: [".process-management-upload__review{display:flex;flex-direction:column;gap:16px}.process-management-upload__description{font-size:.875rem;line-height:1.25rem;color:var(--cds-text-secondary)}\n/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
|
|
3571
|
+
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: i2.GlobalNotificationService }, { type: ProcessManagementService }, { type: ProcessManagementStateService }, { type: i5.ProcessLinkService }, { type: i9.TranslateService }, { type: i0.ChangeDetectorRef }], propDecorators: { _pluginConfigurationMapping: [{
|
|
3572
|
+
type: ViewChild,
|
|
3573
|
+
args: [PluginConfigurationMappingComponent]
|
|
3574
|
+
}] } });
|
|
2265
3575
|
|
|
2266
3576
|
/*
|
|
2267
3577
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|