@valtimo/process-management 13.42.0 → 13.44.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 +1688 -278
- 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 +2 -0
- package/lib/components/process-management-builder/panel/index.d.ts.map +1 -1
- package/lib/components/process-management-builder/panel/read-only-properties-panel.d.ts +17 -0
- package/lib/components/process-management-builder/panel/read-only-properties-panel.d.ts.map +1 -0
- package/lib/components/process-management-builder/panel/valtimo-properties-provider.d.ts +3 -1
- 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 +45 -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 +46 -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 +26 -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 +11 -11
- 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 +15 -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/lib/utils/process-management-builder.utils.d.ts +8 -0
- package/lib/utils/process-management-builder.utils.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
|
/*
|
|
@@ -85,11 +86,37 @@ const PROCESS_MANAGEMENT_LIST_TEST_IDS = {
|
|
|
85
86
|
uploadButton: 'processManagementUploadButton',
|
|
86
87
|
createProcessButton: 'processManagementCreateProcessButton',
|
|
87
88
|
};
|
|
89
|
+
const PROCESS_MANAGEMENT_UPLOAD_TEST_IDS = {
|
|
90
|
+
fileUploader: 'processManagementUploadFileUploader',
|
|
91
|
+
cancelButton: 'processManagementUploadCancelButton',
|
|
92
|
+
submitButton: 'processManagementUploadSubmitButton',
|
|
93
|
+
backButton: 'processManagementUploadBackButton',
|
|
94
|
+
importButton: 'processManagementUploadImportButton',
|
|
95
|
+
closeButton: 'processManagementUploadCloseButton',
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* The "Process link" group the Valtimo properties provider adds to the bpmn-js
|
|
99
|
+
* properties panel. The surrounding panel is rendered by bpmn-js itself and
|
|
100
|
+
* cannot carry test ids — only this group is ours.
|
|
101
|
+
*/
|
|
102
|
+
const PROCESS_LINK_PANEL_TEST_IDS = {
|
|
103
|
+
createButton: 'processLinkPanelCreateButton',
|
|
104
|
+
editButton: 'processLinkPanelEditButton',
|
|
105
|
+
unlinkButton: 'processLinkPanelUnlinkButton',
|
|
106
|
+
};
|
|
88
107
|
const PROCESS_MANAGEMENT_BUILDER_TEST_IDS = {
|
|
89
108
|
draftToggle: 'processManagementBuilderDraftToggle',
|
|
90
109
|
startsCaseToggle: 'processManagementBuilderStartsCaseToggle',
|
|
91
110
|
startableByUserToggle: 'processManagementBuilderStartableByUserToggle',
|
|
92
111
|
deployButton: 'processManagementBuilderDeployButton',
|
|
112
|
+
exportOption: 'processManagementBuilderExportOption',
|
|
113
|
+
markersVisibilityToggle: 'processManagementBuilderMarkersVisibilityToggle',
|
|
114
|
+
versionDropdown: 'processManagementBuilderVersionDropdown',
|
|
115
|
+
validateButton: 'processManagementBuilderValidateButton',
|
|
116
|
+
moreButton: 'processManagementBuilderMoreButton',
|
|
117
|
+
readOnlyTag: 'processManagementBuilderReadOnlyTag',
|
|
118
|
+
systemProcessTag: 'processManagementBuilderSystemProcessTag',
|
|
119
|
+
validationErrors: 'processManagementBuilderValidationErrors',
|
|
93
120
|
};
|
|
94
121
|
|
|
95
122
|
/*
|
|
@@ -108,8 +135,30 @@ const PROCESS_MANAGEMENT_BUILDER_TEST_IDS = {
|
|
|
108
135
|
* limitations under the License.
|
|
109
136
|
*/
|
|
110
137
|
|
|
138
|
+
class ProcessBeanService extends BaseApiService {
|
|
139
|
+
constructor(httpClient, configService) {
|
|
140
|
+
super(httpClient, configService);
|
|
141
|
+
this.httpClient = httpClient;
|
|
142
|
+
this.configService = configService;
|
|
143
|
+
}
|
|
144
|
+
getProcessBeans() {
|
|
145
|
+
return this.httpClient.get(this.getApiUrl('/management/v1/process-bean'));
|
|
146
|
+
}
|
|
147
|
+
getProcessBean(beanName) {
|
|
148
|
+
return this.httpClient.get(this.getApiUrl(`/management/v1/process-bean/${beanName}`));
|
|
149
|
+
}
|
|
150
|
+
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 }); }
|
|
151
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessBeanService, providedIn: 'root' }); }
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessBeanService, decorators: [{
|
|
154
|
+
type: Injectable,
|
|
155
|
+
args: [{
|
|
156
|
+
providedIn: 'root',
|
|
157
|
+
}]
|
|
158
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ConfigService }] });
|
|
159
|
+
|
|
111
160
|
/*
|
|
112
|
-
* Copyright 2015-
|
|
161
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
113
162
|
*
|
|
114
163
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
115
164
|
* you may not use this file except in compliance with the License.
|
|
@@ -154,6 +203,39 @@ class ProcessManagementEditorService {
|
|
|
154
203
|
setValidationErrors(errors) {
|
|
155
204
|
this._validationErrors$.next(errors);
|
|
156
205
|
}
|
|
206
|
+
get dismissedAutofills() {
|
|
207
|
+
return this._dismissedAutofills$.getValue();
|
|
208
|
+
}
|
|
209
|
+
get autofillDismissed$() {
|
|
210
|
+
return this._autofillDismissed$.asObservable();
|
|
211
|
+
}
|
|
212
|
+
dismissAutofill(activityId) {
|
|
213
|
+
const current = this._dismissedAutofills$.getValue();
|
|
214
|
+
current.add(activityId);
|
|
215
|
+
this._dismissedAutofills$.next(new Set(current));
|
|
216
|
+
this._autofillDismissed$.next(activityId);
|
|
217
|
+
}
|
|
218
|
+
clearDismissedAutofills() {
|
|
219
|
+
this._dismissedAutofills$.next(new Set());
|
|
220
|
+
}
|
|
221
|
+
isAutofillDismissed(activityId) {
|
|
222
|
+
return this._dismissedAutofills$.getValue().has(activityId);
|
|
223
|
+
}
|
|
224
|
+
get autofilledElements() {
|
|
225
|
+
return this._autofilledElements$.getValue();
|
|
226
|
+
}
|
|
227
|
+
setAutofilledElements(elements) {
|
|
228
|
+
this._autofilledElements$.next(elements);
|
|
229
|
+
}
|
|
230
|
+
getAutofillForActivity(activityId) {
|
|
231
|
+
return this._autofilledElements$.getValue().find(e => e.activityId === activityId);
|
|
232
|
+
}
|
|
233
|
+
get editingAllowed() {
|
|
234
|
+
return this._editingAllowed$.getValue();
|
|
235
|
+
}
|
|
236
|
+
setEditingAllowed(editingAllowed) {
|
|
237
|
+
this._editingAllowed$.next(editingAllowed);
|
|
238
|
+
}
|
|
157
239
|
constructor(processLinkService, formService) {
|
|
158
240
|
this.processLinkService = processLinkService;
|
|
159
241
|
this.formService = formService;
|
|
@@ -165,6 +247,10 @@ class ProcessManagementEditorService {
|
|
|
165
247
|
this._formDefinitionOptions$ = new BehaviorSubject([]);
|
|
166
248
|
this._validationErrors$ = new BehaviorSubject([]);
|
|
167
249
|
this.validationErrors$ = this._validationErrors$.asObservable();
|
|
250
|
+
this._dismissedAutofills$ = new BehaviorSubject(new Set());
|
|
251
|
+
this._autofillDismissed$ = new Subject();
|
|
252
|
+
this._autofilledElements$ = new BehaviorSubject([]);
|
|
253
|
+
this._editingAllowed$ = new BehaviorSubject(true);
|
|
168
254
|
this._updatingBpmnView = false;
|
|
169
255
|
this._activityIdBusinessIdMap = {};
|
|
170
256
|
this._subscriptions = new Subscription();
|
|
@@ -275,12 +361,12 @@ class ProcessManagementEditorService {
|
|
|
275
361
|
}
|
|
276
362
|
}));
|
|
277
363
|
}
|
|
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 }); }
|
|
364
|
+
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
365
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementEditorService }); }
|
|
280
366
|
}
|
|
281
367
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementEditorService, decorators: [{
|
|
282
368
|
type: Injectable
|
|
283
|
-
}], ctorParameters: () => [{ type: i5.ProcessLinkService }, { type: i2.FormService }] });
|
|
369
|
+
}], ctorParameters: () => [{ type: i5.ProcessLinkService }, { type: i2$1.FormService }] });
|
|
284
370
|
|
|
285
371
|
/*
|
|
286
372
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
@@ -326,7 +412,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
326
412
|
}] });
|
|
327
413
|
|
|
328
414
|
/*
|
|
329
|
-
* Copyright 2015-
|
|
415
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
330
416
|
*
|
|
331
417
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
332
418
|
* you may not use this file except in compliance with the License.
|
|
@@ -358,7 +444,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
358
444
|
*/
|
|
359
445
|
|
|
360
446
|
/*
|
|
361
|
-
* Copyright 2015-
|
|
447
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
448
|
+
*
|
|
449
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
450
|
+
* you may not use this file except in compliance with the License.
|
|
451
|
+
* You may obtain a copy of the License at
|
|
452
|
+
*
|
|
453
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
454
|
+
*
|
|
455
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
456
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
457
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
458
|
+
* See the License for the specific language governing permissions and
|
|
459
|
+
* limitations under the License.
|
|
460
|
+
*/
|
|
461
|
+
|
|
462
|
+
/*
|
|
463
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
464
|
+
*
|
|
465
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
466
|
+
* you may not use this file except in compliance with the License.
|
|
467
|
+
* You may obtain a copy of the License at
|
|
468
|
+
*
|
|
469
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
470
|
+
*
|
|
471
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
472
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
473
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
474
|
+
* See the License for the specific language governing permissions and
|
|
475
|
+
* limitations under the License.
|
|
476
|
+
*/
|
|
477
|
+
|
|
478
|
+
/*
|
|
479
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
362
480
|
*
|
|
363
481
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
364
482
|
* you may not use this file except in compliance with the License.
|
|
@@ -378,7 +496,7 @@ const PROCESS_MANAGEMENT_ENDPOINTS = {
|
|
|
378
496
|
};
|
|
379
497
|
|
|
380
498
|
/*
|
|
381
|
-
* Copyright 2015-
|
|
499
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
382
500
|
*
|
|
383
501
|
* Licensed under EUPL, Version 1.2 (the "License");
|
|
384
502
|
* you may not use this file except in compliance with the License.
|
|
@@ -409,6 +527,21 @@ const PROCESS_MANAGEMENT_ENDPOINTS = {
|
|
|
409
527
|
* limitations under the License.
|
|
410
528
|
*/
|
|
411
529
|
|
|
530
|
+
/*
|
|
531
|
+
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
532
|
+
*
|
|
533
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
534
|
+
* you may not use this file except in compliance with the License.
|
|
535
|
+
* You may obtain a copy of the License at
|
|
536
|
+
*
|
|
537
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
538
|
+
*
|
|
539
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
540
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
541
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
542
|
+
* See the License for the specific language governing permissions and
|
|
543
|
+
* limitations under the License.
|
|
544
|
+
*/
|
|
412
545
|
class ProcessManagementService extends BaseApiService {
|
|
413
546
|
get caseDefinitionKey() {
|
|
414
547
|
return this._definitionKey$.getValue() ?? '';
|
|
@@ -475,6 +608,18 @@ class ProcessManagementService extends BaseApiService {
|
|
|
475
608
|
updateProcessDefinitionCaseDefinitionProperties(caseDefinitionKey, caseDefinitionVersionTag, processDefinitionId, body) {
|
|
476
609
|
return this.httpClient.put(this.getApiUrl(`/management/v1/case-definition/${caseDefinitionKey}/version/${caseDefinitionVersionTag}/process/${processDefinitionId}/properties`), body);
|
|
477
610
|
}
|
|
611
|
+
exportProcessDefinition(processDefinitionId) {
|
|
612
|
+
return this.httpClient.get(this.getApiUrl(`/management/v1/process-definition/${processDefinitionId}/export`), { observe: 'response', responseType: 'blob', headers: InterceptorSkipHeader });
|
|
613
|
+
}
|
|
614
|
+
previewProcessDefinitionImport(file) {
|
|
615
|
+
return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/import/preview'), file, { headers: new HttpHeaders().set(InterceptorSkip, '400') });
|
|
616
|
+
}
|
|
617
|
+
importProcessDefinition(file, pluginConfigurationMappings) {
|
|
618
|
+
if (pluginConfigurationMappings) {
|
|
619
|
+
file.set('pluginConfigurationMappings', new Blob([JSON.stringify(pluginConfigurationMappings)], { type: 'application/json' }));
|
|
620
|
+
}
|
|
621
|
+
return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/import'), file, { headers: new HttpHeaders().set(InterceptorSkip, '400') });
|
|
622
|
+
}
|
|
478
623
|
validateProcessDefinition(request) {
|
|
479
624
|
return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/validate'), request);
|
|
480
625
|
}
|
|
@@ -499,7 +644,7 @@ class ProcessManagementService extends BaseApiService {
|
|
|
499
644
|
}
|
|
500
645
|
return object;
|
|
501
646
|
}
|
|
502
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, deps: [{ token: i1.HttpClient }, { token: i2
|
|
647
|
+
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
648
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, providedIn: 'root' }); }
|
|
504
649
|
}
|
|
505
650
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementService, decorators: [{
|
|
@@ -507,7 +652,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
507
652
|
args: [{
|
|
508
653
|
providedIn: 'root',
|
|
509
654
|
}]
|
|
510
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2
|
|
655
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ConfigService }] });
|
|
511
656
|
|
|
512
657
|
/*
|
|
513
658
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
@@ -629,6 +774,10 @@ const DisableBpmnWriteModule = {
|
|
|
629
774
|
],
|
|
630
775
|
move: ['value', null],
|
|
631
776
|
resizeHandles: ['value', { addResizer: () => { }, removeResizers: () => { } }],
|
|
777
|
+
bendpoints: ['value', {}],
|
|
778
|
+
bendpointMove: ['value', { start: () => { } }],
|
|
779
|
+
bendpointMovePreview: ['value', {}],
|
|
780
|
+
connectionSegmentMove: ['value', { start: () => { } }],
|
|
632
781
|
};
|
|
633
782
|
const disableCommands = (editor) => {
|
|
634
783
|
const commandStack = editor.get('commandStack');
|
|
@@ -759,6 +908,9 @@ class ValtimoPropertiesProvider {
|
|
|
759
908
|
get pluginTranslationService() {
|
|
760
909
|
return window.pluginTranslationService;
|
|
761
910
|
}
|
|
911
|
+
get processLinkService() {
|
|
912
|
+
return window.processLinkService;
|
|
913
|
+
}
|
|
762
914
|
constructor(propertiesPanel) {
|
|
763
915
|
propertiesPanel.registerProvider(500, this);
|
|
764
916
|
}
|
|
@@ -774,6 +926,8 @@ class ValtimoPropertiesProvider {
|
|
|
774
926
|
getGroups(element) {
|
|
775
927
|
const processLink = this.processManagementEditorService.processLinksForSelectedDefinition.find(processLink => processLink.activityId === element.id) || null;
|
|
776
928
|
const elementErrors = this.processManagementEditorService.validationErrors.filter(error => error.elementId === element.id);
|
|
929
|
+
const autofillInfo = this.processManagementEditorService.getAutofillForActivity(element.id);
|
|
930
|
+
const isAutofillDismissed = this.processManagementEditorService.isAutofillDismissed(element.id);
|
|
777
931
|
return (groups) => {
|
|
778
932
|
const generalGroup = groups.find((g) => g.id === 'general');
|
|
779
933
|
if (generalGroup) {
|
|
@@ -795,6 +949,23 @@ class ValtimoPropertiesProvider {
|
|
|
795
949
|
};
|
|
796
950
|
groups.unshift(errorGroup);
|
|
797
951
|
}
|
|
952
|
+
if (autofillInfo && !isAutofillDismissed) {
|
|
953
|
+
const targetGroupId = this.getGroupIdForModificationType(autofillInfo.modificationType);
|
|
954
|
+
const targetGroup = groups.find((g) => g.id === targetGroupId);
|
|
955
|
+
if (targetGroup) {
|
|
956
|
+
const notificationEntry = {
|
|
957
|
+
id: 'autofilledNotificationEntry',
|
|
958
|
+
activityId: element.id,
|
|
959
|
+
element,
|
|
960
|
+
translateService: this.translateService,
|
|
961
|
+
processManagementEditorService: this.processManagementEditorService,
|
|
962
|
+
processLinkService: this.processLinkService,
|
|
963
|
+
component: AutofilledNotificationElement,
|
|
964
|
+
};
|
|
965
|
+
targetGroup.entries.unshift(notificationEntry);
|
|
966
|
+
targetGroup.shouldOpen = true;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
798
969
|
if (is(element, 'bpmn:UserTask') ||
|
|
799
970
|
is(element, 'bpmn:StartEvent') ||
|
|
800
971
|
is(element, 'bpmn:ServiceTask') ||
|
|
@@ -803,18 +974,31 @@ class ValtimoPropertiesProvider {
|
|
|
803
974
|
is(element, 'bpmn:IntermediateThrowEvent') ||
|
|
804
975
|
is(element, 'bpmn:IntermediateCatchEvent') ||
|
|
805
976
|
is(element, 'bpmn:CallActivity')) {
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
977
|
+
const editingAllowed = this.processManagementEditorService.editingAllowed;
|
|
978
|
+
if (editingAllowed || processLink) {
|
|
979
|
+
const customGroup = {
|
|
980
|
+
id: 'customRootGroup',
|
|
981
|
+
label: 'Process link',
|
|
982
|
+
entries: [this.createCustomRootElement(element, processLink, editingAllowed)],
|
|
983
|
+
groupType: 'root',
|
|
984
|
+
};
|
|
985
|
+
this.addAsSecondOrFirst(groups, customGroup);
|
|
986
|
+
}
|
|
813
987
|
}
|
|
814
988
|
return groups;
|
|
815
989
|
};
|
|
816
990
|
}
|
|
817
|
-
|
|
991
|
+
getGroupIdForModificationType(modificationType) {
|
|
992
|
+
const groupMapping = {
|
|
993
|
+
SERVICE_TASK_EXPRESSION: 'CamundaPlatform__Implementation',
|
|
994
|
+
SEND_TASK_EXPRESSION: 'CamundaPlatform__Implementation',
|
|
995
|
+
MESSAGE_EVENT_EXPRESSION: 'message',
|
|
996
|
+
TIMER_DURATION: 'timer',
|
|
997
|
+
CALL_ACTIVITY_BUSINESS_KEY: 'CamundaPlatform__BusinessKey',
|
|
998
|
+
};
|
|
999
|
+
return groupMapping[modificationType] || 'general';
|
|
1000
|
+
}
|
|
1001
|
+
createCustomRootElement(element, processLink, editingAllowed) {
|
|
818
1002
|
return {
|
|
819
1003
|
translateService: this.translateService,
|
|
820
1004
|
processManagementEditorService: this.processManagementEditorService,
|
|
@@ -822,18 +1006,20 @@ class ValtimoPropertiesProvider {
|
|
|
822
1006
|
id: 'customRootElement',
|
|
823
1007
|
processLink,
|
|
824
1008
|
element,
|
|
1009
|
+
editingAllowed,
|
|
825
1010
|
component: CustomRootElement,
|
|
826
|
-
isEdited: () =>
|
|
1011
|
+
isEdited: (node) => node && !!node.value,
|
|
827
1012
|
};
|
|
828
1013
|
}
|
|
829
1014
|
}
|
|
830
1015
|
const CustomRootElement = (props) => {
|
|
831
|
-
const { element, processLink, translateService, processManagementEditorService, pluginTranslationService, } = props;
|
|
1016
|
+
const { element, processLink, translateService, processManagementEditorService, pluginTranslationService, editingAllowed, } = props;
|
|
832
1017
|
const modeling = useService('modeling');
|
|
833
1018
|
const elementRegistry = useService('elementRegistry');
|
|
834
1019
|
const editProcessLinkText = translateService.instant('interface.edit');
|
|
835
1020
|
const unlinkText = translateService.instant('processLink.unlink');
|
|
836
1021
|
const createText = translateService.instant('processLink.create');
|
|
1022
|
+
const viewText = translateService.instant('interface.view');
|
|
837
1023
|
const getModalParams = () => {
|
|
838
1024
|
const currentElement = elementRegistry.get(element.id) || element;
|
|
839
1025
|
return {
|
|
@@ -874,55 +1060,26 @@ const CustomRootElement = (props) => {
|
|
|
874
1060
|
};
|
|
875
1061
|
const processLinkFormDefinitionId = processLink?.formDefinitionId;
|
|
876
1062
|
const processLinkFormDefinitionName = processManagementEditorService.formDefinitionOptions.find(option => option.id === processLinkFormDefinitionId)?.name;
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
${translateService.instant('processLinkType.form')}
|
|
886
|
-
</span>
|
|
887
|
-
</cds-tag>
|
|
888
|
-
</div>
|
|
889
|
-
|
|
890
|
-
<div class="process-link-properties-panel__buttons">
|
|
891
|
-
<button
|
|
892
|
-
class="cds--btn cds--btn--danger cds--btn--sm cds--layout--side-md"
|
|
893
|
-
onClick=${handleUnlinkClick}
|
|
894
|
-
>
|
|
895
|
-
${unlinkText}
|
|
896
|
-
</button>
|
|
897
|
-
|
|
1063
|
+
const hiddenInput = html `<input
|
|
1064
|
+
type="hidden"
|
|
1065
|
+
class="bio-properties-panel-input"
|
|
1066
|
+
value=${processLink ? 'configured' : ''}
|
|
1067
|
+
/>`;
|
|
1068
|
+
const wrapEntry = (content) => html `<div data-entry-id=${props.id}>${hiddenInput}${content}</div>`;
|
|
1069
|
+
const linkedButtons = !editingAllowed
|
|
1070
|
+
? html `<div class="process-link-properties-panel__buttons">
|
|
898
1071
|
<button
|
|
899
1072
|
class="cds--btn cds--btn--primary cds--btn--sm cds--layout--size-md"
|
|
1073
|
+
data-test-id=${PROCESS_LINK_PANEL_TEST_IDS.editButton}
|
|
900
1074
|
onClick=${handleEditClick}
|
|
901
1075
|
>
|
|
902
|
-
${
|
|
1076
|
+
${viewText}
|
|
903
1077
|
</button>
|
|
904
|
-
</div
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
const processLinkFormFlowDefinitionKey = processLink?.formFlowDefinitionKey;
|
|
908
|
-
if (processLinkFormFlowDefinitionKey) {
|
|
909
|
-
return html `<div class="process-link-properties-panel">
|
|
910
|
-
<div class="process-link-properties-panel__header">
|
|
911
|
-
<span class="process-link-properties-panel__title"
|
|
912
|
-
>${processLinkFormFlowDefinitionKey}</span
|
|
913
|
-
>
|
|
914
|
-
|
|
915
|
-
<cds-tag
|
|
916
|
-
class="cds--tag cds--tag--teal cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
917
|
-
><span class="cds--tag__label">
|
|
918
|
-
${translateService.instant('processLinkType.form-flow')}
|
|
919
|
-
</span>
|
|
920
|
-
</cds-tag>
|
|
921
|
-
</div>
|
|
922
|
-
|
|
923
|
-
<div class="process-link-properties-panel__buttons">
|
|
1078
|
+
</div>`
|
|
1079
|
+
: html `<div class="process-link-properties-panel__buttons">
|
|
924
1080
|
<button
|
|
925
1081
|
class="cds--btn cds--btn--danger cds--btn--sm cds--layout--side-md"
|
|
1082
|
+
data-test-id=${PROCESS_LINK_PANEL_TEST_IDS.unlinkButton}
|
|
926
1083
|
onClick=${handleUnlinkClick}
|
|
927
1084
|
>
|
|
928
1085
|
${unlinkText}
|
|
@@ -930,165 +1087,848 @@ const CustomRootElement = (props) => {
|
|
|
930
1087
|
|
|
931
1088
|
<button
|
|
932
1089
|
class="cds--btn cds--btn--primary cds--btn--sm cds--layout--size-md"
|
|
1090
|
+
data-test-id=${PROCESS_LINK_PANEL_TEST_IDS.editButton}
|
|
933
1091
|
onClick=${handleEditClick}
|
|
934
1092
|
>
|
|
935
1093
|
${editProcessLinkText}
|
|
936
1094
|
</button>
|
|
937
|
-
</div
|
|
938
|
-
|
|
1095
|
+
</div>`;
|
|
1096
|
+
if (processLinkFormDefinitionName) {
|
|
1097
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
1098
|
+
<div class="process-link-properties-panel__header">
|
|
1099
|
+
<span class="process-link-properties-panel__title">${processLinkFormDefinitionName}</span>
|
|
1100
|
+
|
|
1101
|
+
<cds-tag
|
|
1102
|
+
class="cds--tag cds--tag--blue cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
1103
|
+
><span class="cds--tag__label">
|
|
1104
|
+
${translateService.instant('processLinkType.form')}
|
|
1105
|
+
</span>
|
|
1106
|
+
</cds-tag>
|
|
1107
|
+
</div>
|
|
1108
|
+
|
|
1109
|
+
${linkedButtons}
|
|
1110
|
+
</div>`);
|
|
1111
|
+
}
|
|
1112
|
+
const processLinkFormFlowDefinitionKey = processLink?.formFlowDefinitionKey;
|
|
1113
|
+
if (processLinkFormFlowDefinitionKey) {
|
|
1114
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
1115
|
+
<div class="process-link-properties-panel__header">
|
|
1116
|
+
<span class="process-link-properties-panel__title"
|
|
1117
|
+
>${processLinkFormFlowDefinitionKey}</span
|
|
1118
|
+
>
|
|
1119
|
+
|
|
1120
|
+
<cds-tag
|
|
1121
|
+
class="cds--tag cds--tag--teal cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
1122
|
+
><span class="cds--tag__label">
|
|
1123
|
+
${translateService.instant('processLinkType.form-flow')}
|
|
1124
|
+
</span>
|
|
1125
|
+
</cds-tag>
|
|
1126
|
+
</div>
|
|
1127
|
+
|
|
1128
|
+
${linkedButtons}
|
|
1129
|
+
</div>`);
|
|
939
1130
|
}
|
|
940
1131
|
const buildingBlockDefinitionKey = processLink?.buildingBlockDefinitionKey;
|
|
941
1132
|
const buildingBlockDefinitionVersion = processLink?.buildingBlockDefinitionVersionTag;
|
|
942
1133
|
if (buildingBlockDefinitionKey) {
|
|
943
|
-
return html `<div class="process-link-properties-panel">
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1134
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
1135
|
+
<div class="process-link-properties-panel__header">
|
|
1136
|
+
<span class="process-link-properties-panel__title"
|
|
1137
|
+
>${buildingBlockDefinitionKey} (${buildingBlockDefinitionVersion})</span
|
|
1138
|
+
>
|
|
948
1139
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
1140
|
+
<cds-tag
|
|
1141
|
+
class="cds--tag cds--tag--green cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
1142
|
+
><span class="cds--tag__label">
|
|
1143
|
+
${translateService.instant('processLinkType.building-block')}
|
|
1144
|
+
</span>
|
|
1145
|
+
</cds-tag>
|
|
1146
|
+
</div>
|
|
956
1147
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
class="cds--btn cds--btn--danger cds--btn--sm cds--layout--side-md"
|
|
960
|
-
onClick=${handleUnlinkClick}
|
|
961
|
-
>
|
|
962
|
-
${unlinkText}
|
|
963
|
-
</button>
|
|
964
|
-
|
|
965
|
-
<button
|
|
966
|
-
class="cds--btn cds--btn--primary cds--btn--sm cds--layout--size-md"
|
|
967
|
-
onClick=${handleEditClick}
|
|
968
|
-
>
|
|
969
|
-
${editProcessLinkText}
|
|
970
|
-
</button>
|
|
971
|
-
</div>
|
|
972
|
-
</div>`;
|
|
1148
|
+
${linkedButtons}
|
|
1149
|
+
</div>`);
|
|
973
1150
|
}
|
|
974
1151
|
const pluginActionKey = processLink?.pluginActionDefinitionKey;
|
|
975
1152
|
const pluginActionTranslation = pluginTranslationService.instantByPluginActionKey(pluginActionKey);
|
|
976
1153
|
const pluginTitleTranslation = pluginTranslationService.instantPluginTitleByPluginActionKey(pluginActionKey);
|
|
977
1154
|
if (pluginActionKey) {
|
|
978
|
-
return html `<div class="process-link-properties-panel">
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1155
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
1156
|
+
<div class="process-link-properties-panel__header">
|
|
1157
|
+
<span class="process-link-properties-panel__title-container">
|
|
1158
|
+
<span class="process-link-properties-panel__title">${pluginTitleTranslation}</span>
|
|
982
1159
|
|
|
983
|
-
|
|
984
|
-
</span>
|
|
985
|
-
|
|
986
|
-
<cds-tag
|
|
987
|
-
class="cds--tag cds--tag--purple cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
988
|
-
><span class="cds--tag__label">
|
|
989
|
-
${translateService.instant('processLinkType.plugin')}
|
|
1160
|
+
<span class="process-link-properties-panel__title">${pluginActionTranslation}</span>
|
|
990
1161
|
</span>
|
|
991
|
-
</cds-tag>
|
|
992
|
-
</div>
|
|
993
1162
|
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
</
|
|
1163
|
+
<cds-tag
|
|
1164
|
+
class="cds--tag cds--tag--purple cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
1165
|
+
><span class="cds--tag__label">
|
|
1166
|
+
${translateService.instant('processLinkType.plugin')}
|
|
1167
|
+
</span>
|
|
1168
|
+
</cds-tag>
|
|
1169
|
+
</div>
|
|
1001
1170
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
onClick=${handleEditClick}
|
|
1005
|
-
>
|
|
1006
|
-
${editProcessLinkText}
|
|
1007
|
-
</button>
|
|
1008
|
-
</div>
|
|
1009
|
-
</div>`;
|
|
1171
|
+
${linkedButtons}
|
|
1172
|
+
</div>`);
|
|
1010
1173
|
}
|
|
1011
1174
|
const uiComponentKey = processLink?.componentKey;
|
|
1012
1175
|
if (uiComponentKey) {
|
|
1013
|
-
return html `<div class="process-link-properties-panel">
|
|
1014
|
-
|
|
1015
|
-
|
|
1176
|
+
return wrapEntry(html `<div class="process-link-properties-panel">
|
|
1177
|
+
<div class="process-link-properties-panel__header">
|
|
1178
|
+
<span class="process-link-properties-panel__title">${uiComponentKey}</span>
|
|
1016
1179
|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1180
|
+
<cds-tag
|
|
1181
|
+
class="cds--tag cds--tag--magenta cds--tag--md cds--layout--size-md cds-tag--no-margin"
|
|
1182
|
+
><span class="cds--tag__label">
|
|
1183
|
+
${translateService.instant('processLinkType.ui-component')}
|
|
1184
|
+
</span>
|
|
1185
|
+
</cds-tag>
|
|
1186
|
+
</div>
|
|
1024
1187
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1188
|
+
${linkedButtons}
|
|
1189
|
+
</div>`);
|
|
1190
|
+
}
|
|
1191
|
+
const genericLinkedPanel = html `<div class="process-link-properties-panel">
|
|
1192
|
+
${linkedButtons}
|
|
1193
|
+
</div>`;
|
|
1194
|
+
const genericCreatePanel = html `<div class="process-link-properties-panel">
|
|
1195
|
+
<div class="process-link-properties-panel__buttons">
|
|
1196
|
+
<button
|
|
1197
|
+
class="cds--btn cds--btn--primary cds--btn--sm cds--layout--size-md"
|
|
1198
|
+
data-test-id=${PROCESS_LINK_PANEL_TEST_IDS.createButton}
|
|
1199
|
+
onClick=${handleCreateClick}
|
|
1200
|
+
>
|
|
1201
|
+
${createText}
|
|
1202
|
+
</button>
|
|
1203
|
+
</div>
|
|
1204
|
+
</div>`;
|
|
1205
|
+
return wrapEntry(processLink ? genericLinkedPanel : genericCreatePanel);
|
|
1206
|
+
};
|
|
1207
|
+
const ValidationErrorsElement = (props) => {
|
|
1208
|
+
const getErrorMessage = (error) => {
|
|
1209
|
+
if (error.errorCode) {
|
|
1210
|
+
const translationKey = `processManagement.validationErrorCodes.${error.errorCode}`;
|
|
1211
|
+
const translated = props.translateService.instant(translationKey, {
|
|
1212
|
+
expression: error.expression ?? '',
|
|
1213
|
+
});
|
|
1214
|
+
if (translated !== translationKey) {
|
|
1215
|
+
return translated;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return error.reason;
|
|
1219
|
+
};
|
|
1220
|
+
return html `<div class="validation-errors-panel">
|
|
1221
|
+
${props.errors.map(error => html `<div
|
|
1222
|
+
class="validation-errors-panel__item${error.severity === 'WARNING' ? ' warning' : ''}"
|
|
1029
1223
|
>
|
|
1030
|
-
|
|
1031
|
-
|
|
1224
|
+
<span
|
|
1225
|
+
class="validation-errors-panel__icon${error.severity === 'WARNING' ? ' warning' : ''}"
|
|
1226
|
+
>!</span
|
|
1227
|
+
>
|
|
1228
|
+
<span
|
|
1229
|
+
class="validation-errors-panel__reason${error.severity === 'WARNING' ? ' warning' : ''}"
|
|
1230
|
+
>${getErrorMessage(error)}</span
|
|
1231
|
+
>
|
|
1232
|
+
</div>`)}
|
|
1233
|
+
</div>`;
|
|
1234
|
+
};
|
|
1235
|
+
const AutofilledNotificationElement = (props) => {
|
|
1236
|
+
const handleDismiss = (event) => {
|
|
1237
|
+
const processDefinitionId = props.processManagementEditorService.selectionProcessDefinition?.id;
|
|
1238
|
+
if (processDefinitionId) {
|
|
1239
|
+
props.processLinkService.deleteAutofill(processDefinitionId, props.activityId).subscribe();
|
|
1240
|
+
}
|
|
1241
|
+
props.processManagementEditorService.dismissAutofill(props.activityId);
|
|
1242
|
+
const target = event.currentTarget;
|
|
1243
|
+
const panel = target.closest('.autofilled-notification-panel');
|
|
1244
|
+
if (panel) {
|
|
1245
|
+
panel.style.display = 'none';
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
return html `<div class="autofilled-notification-panel">
|
|
1249
|
+
<span class="autofilled-notification-panel__icon">!</span>
|
|
1250
|
+
<span class="autofilled-notification-panel__message">
|
|
1251
|
+
${props.translateService.instant('processManagement.autofilled.sidebarMessage')}
|
|
1252
|
+
</span>
|
|
1253
|
+
<button class="autofilled-notification-panel__dismiss" onClick=${handleDismiss}>×</button>
|
|
1254
|
+
</div>`;
|
|
1255
|
+
};
|
|
1256
|
+
const ValtimoPropertiesProviderModule = {
|
|
1257
|
+
__init__: ['customPropertiesProvider'],
|
|
1258
|
+
customPropertiesProvider: ['type', ValtimoPropertiesProvider],
|
|
1259
|
+
};
|
|
1032
1260
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1261
|
+
/*
|
|
1262
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
1263
|
+
*
|
|
1264
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
1265
|
+
* you may not use this file except in compliance with the License.
|
|
1266
|
+
* You may obtain a copy of the License at
|
|
1267
|
+
*
|
|
1268
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
1269
|
+
*
|
|
1270
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1271
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
1272
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1273
|
+
* See the License for the specific language governing permissions and
|
|
1274
|
+
* limitations under the License.
|
|
1275
|
+
*/
|
|
1276
|
+
const READ_ONLY_PRIORITY = 1;
|
|
1277
|
+
const removeEditActions = (node) => {
|
|
1278
|
+
if (!node || typeof node !== 'object')
|
|
1279
|
+
return;
|
|
1280
|
+
if (node.add)
|
|
1281
|
+
node.add = null;
|
|
1282
|
+
if (node.remove)
|
|
1283
|
+
node.remove = null;
|
|
1284
|
+
if (Array.isArray(node.entries)) {
|
|
1285
|
+
node.entries.forEach((entry) => removeEditActions(entry));
|
|
1286
|
+
}
|
|
1287
|
+
if (Array.isArray(node.items)) {
|
|
1288
|
+
node.items.forEach((item) => removeEditActions(item));
|
|
1289
|
+
}
|
|
1290
|
+
};
|
|
1291
|
+
class ReadOnlyPropertiesProvider {
|
|
1292
|
+
static { this.$inject = ['propertiesPanel']; }
|
|
1293
|
+
constructor(propertiesPanel) {
|
|
1294
|
+
propertiesPanel.registerProvider(READ_ONLY_PRIORITY, this);
|
|
1295
|
+
}
|
|
1296
|
+
getGroups() {
|
|
1297
|
+
return (groups) => {
|
|
1298
|
+
groups.forEach(group => removeEditActions(group));
|
|
1299
|
+
return groups;
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
const ENTRY = '.bio-properties-panel-entry';
|
|
1304
|
+
const READ_ONLY_INPUT_TYPES = ['email', 'number', 'password', 'search', 'tel', 'text', 'url'];
|
|
1305
|
+
const makeControlsReadOnly = (container) => {
|
|
1306
|
+
container.querySelectorAll(`${ENTRY} input`).forEach(input => {
|
|
1307
|
+
if (READ_ONLY_INPUT_TYPES.includes(input.type)) {
|
|
1308
|
+
input.readOnly = true;
|
|
1309
|
+
}
|
|
1310
|
+
else {
|
|
1311
|
+
input.disabled = true;
|
|
1312
|
+
}
|
|
1313
|
+
});
|
|
1314
|
+
container
|
|
1315
|
+
.querySelectorAll(`${ENTRY} textarea`)
|
|
1316
|
+
.forEach(textarea => (textarea.readOnly = true));
|
|
1317
|
+
container
|
|
1318
|
+
.querySelectorAll(`${ENTRY} select, ${ENTRY} button`)
|
|
1319
|
+
.forEach(control => (control.disabled = true));
|
|
1320
|
+
container
|
|
1321
|
+
.querySelectorAll(`${ENTRY} [contenteditable="true"]`)
|
|
1322
|
+
.forEach(editor => editor.setAttribute('contenteditable', 'false'));
|
|
1323
|
+
};
|
|
1324
|
+
class ReadOnlyPropertiesPanel {
|
|
1325
|
+
static { this.$inject = ['config.propertiesPanel', 'eventBus']; }
|
|
1326
|
+
constructor(config, eventBus) {
|
|
1327
|
+
this._observer = null;
|
|
1328
|
+
const parent = config?.parent;
|
|
1329
|
+
if (!parent)
|
|
1330
|
+
return;
|
|
1331
|
+
this._observer = new MutationObserver(() => makeControlsReadOnly(parent));
|
|
1332
|
+
this._observer.observe(parent, { childList: true, subtree: true });
|
|
1333
|
+
eventBus.on('diagram.destroy', () => this._observer?.disconnect());
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
const ReadOnlyPropertiesPanelModule = {
|
|
1337
|
+
__init__: ['readOnlyPropertiesProvider', 'readOnlyPropertiesPanel'],
|
|
1338
|
+
readOnlyPropertiesProvider: ['type', ReadOnlyPropertiesProvider],
|
|
1339
|
+
readOnlyPropertiesPanel: ['type', ReadOnlyPropertiesPanel],
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
/*
|
|
1343
|
+
* Copyright 2015-2026 Ritense BV, the Netherlands.
|
|
1344
|
+
*
|
|
1345
|
+
* Licensed under EUPL, Version 1.2 (the "License");
|
|
1346
|
+
* you may not use this file except in compliance with the License.
|
|
1347
|
+
* You may obtain a copy of the License at
|
|
1348
|
+
*
|
|
1349
|
+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
|
|
1350
|
+
*
|
|
1351
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1352
|
+
* distributed under the License is distributed on an "AS IS" basis,
|
|
1353
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1354
|
+
* See the License for the specific language governing permissions and
|
|
1355
|
+
* limitations under the License.
|
|
1356
|
+
*/
|
|
1357
|
+
class ExpressionAutocomplete {
|
|
1358
|
+
static { this.$inject = ['eventBus']; }
|
|
1359
|
+
constructor(eventBus) {
|
|
1360
|
+
this.processBeans = [];
|
|
1361
|
+
this.panelContainer = null;
|
|
1362
|
+
this.stylesInjected = false;
|
|
1363
|
+
this.observer = null;
|
|
1364
|
+
this.documentClickHandlers = [];
|
|
1365
|
+
this.injectStyles();
|
|
1366
|
+
eventBus.on('diagram.destroy', () => {
|
|
1367
|
+
this.dispose();
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
dispose() {
|
|
1371
|
+
this.cleanupClickHandlers();
|
|
1372
|
+
if (this.observer) {
|
|
1373
|
+
this.observer.disconnect();
|
|
1374
|
+
this.observer = null;
|
|
1375
|
+
}
|
|
1376
|
+
this.panelContainer = null;
|
|
1377
|
+
}
|
|
1378
|
+
cleanupClickHandlers() {
|
|
1379
|
+
for (const handler of this.documentClickHandlers) {
|
|
1380
|
+
document.removeEventListener('click', handler);
|
|
1381
|
+
}
|
|
1382
|
+
this.documentClickHandlers = [];
|
|
1383
|
+
}
|
|
1384
|
+
setProcessBeans(beans) {
|
|
1385
|
+
this.processBeans = beans;
|
|
1386
|
+
}
|
|
1387
|
+
setPanelContainer(container) {
|
|
1388
|
+
this.panelContainer = container;
|
|
1389
|
+
this.startObserving();
|
|
1390
|
+
setTimeout(() => this.scanAndAttach(), 100);
|
|
1391
|
+
}
|
|
1392
|
+
startObserving() {
|
|
1393
|
+
if (!this.panelContainer || this.observer)
|
|
1394
|
+
return;
|
|
1395
|
+
this.observer = new MutationObserver(() => {
|
|
1396
|
+
this.scanAndAttach();
|
|
1397
|
+
});
|
|
1398
|
+
this.observer.observe(this.panelContainer, {
|
|
1399
|
+
childList: true,
|
|
1400
|
+
subtree: true,
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
scanAndAttach() {
|
|
1404
|
+
if (!this.panelContainer)
|
|
1405
|
+
return;
|
|
1406
|
+
const allInputs = this.panelContainer.querySelectorAll('input, textarea');
|
|
1407
|
+
allInputs.forEach(input => {
|
|
1408
|
+
if (input.dataset.autocompleteAttached)
|
|
1409
|
+
return;
|
|
1410
|
+
if (this.isExpressionField(input)) {
|
|
1411
|
+
this.attachAutocomplete(input);
|
|
1412
|
+
input.dataset.autocompleteAttached = 'true';
|
|
1413
|
+
}
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1416
|
+
isExpressionField(input) {
|
|
1417
|
+
const type = input.type?.toLowerCase();
|
|
1418
|
+
if (input.tagName !== 'TEXTAREA' && !(input.tagName === 'INPUT' && (!type || type === 'text'))) {
|
|
1419
|
+
return false;
|
|
1420
|
+
}
|
|
1421
|
+
if (input.closest('.expression-editor-simple')) {
|
|
1422
|
+
return false;
|
|
1423
|
+
}
|
|
1424
|
+
const name = (input.name || input.id || '').toLowerCase();
|
|
1425
|
+
if (name.includes('resultvariable') || name.includes('result-variable')) {
|
|
1426
|
+
return false;
|
|
1427
|
+
}
|
|
1428
|
+
if (name.includes('expression') || name.includes('delegateexpression')) {
|
|
1429
|
+
return true;
|
|
1430
|
+
}
|
|
1431
|
+
const entry = input.closest('.bio-properties-panel-entry');
|
|
1432
|
+
if (entry) {
|
|
1433
|
+
const entryId = (entry.getAttribute('data-entry-id') || '').toLowerCase();
|
|
1434
|
+
if (entryId.includes('resultvariable') || entryId.includes('result-variable')) {
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
if (entryId.includes('expression')) {
|
|
1438
|
+
return true;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
const label = input.closest('.bio-properties-panel-entry')?.querySelector('label');
|
|
1442
|
+
if (label) {
|
|
1443
|
+
const labelText = label.textContent?.toLowerCase() || '';
|
|
1444
|
+
if (labelText.includes('result variable') || labelText.includes('resultvariable')) {
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
if (labelText.includes('expression') || labelText.includes('delegate')) {
|
|
1448
|
+
return true;
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
return false;
|
|
1452
|
+
}
|
|
1453
|
+
attachAutocomplete(input) {
|
|
1454
|
+
this.wrapWithEditor(input);
|
|
1455
|
+
}
|
|
1456
|
+
// --- Expression Editor (Dropdown/Manual toggle) ---
|
|
1457
|
+
wrapWithEditor(input) {
|
|
1458
|
+
const wrapper = document.createElement('div');
|
|
1459
|
+
wrapper.className = 'expression-editor-wrapper';
|
|
1460
|
+
const parsed = this.parseExpression(input.value);
|
|
1461
|
+
const canUseDropdown = !input.value || (parsed.beanName !== null && parsed.methodName !== null);
|
|
1462
|
+
const initialMode = canUseDropdown ? 'simple' : 'technical';
|
|
1463
|
+
wrapper.dataset.mode = initialMode;
|
|
1464
|
+
input.parentNode?.insertBefore(wrapper, input);
|
|
1465
|
+
const toggle = document.createElement('div');
|
|
1466
|
+
toggle.className = 'expression-editor-toggle';
|
|
1467
|
+
toggle.innerHTML = `
|
|
1468
|
+
<button type="button" class="expression-editor-toggle__btn${initialMode === 'simple' ? ' active' : ''}" data-mode="simple">Dropdown</button>
|
|
1469
|
+
<button type="button" class="expression-editor-toggle__btn${initialMode === 'technical' ? ' active' : ''}" data-mode="technical">Manual</button>
|
|
1470
|
+
`;
|
|
1471
|
+
const technicalContainer = document.createElement('div');
|
|
1472
|
+
technicalContainer.className = 'expression-editor-technical';
|
|
1473
|
+
technicalContainer.appendChild(input);
|
|
1474
|
+
technicalContainer.style.display = initialMode === 'technical' ? 'block' : 'none';
|
|
1475
|
+
const simpleContainer = document.createElement('div');
|
|
1476
|
+
simpleContainer.className = 'expression-editor-simple';
|
|
1477
|
+
simpleContainer.style.display = initialMode === 'simple' ? 'block' : 'none';
|
|
1478
|
+
wrapper.appendChild(toggle);
|
|
1479
|
+
wrapper.appendChild(technicalContainer);
|
|
1480
|
+
wrapper.appendChild(simpleContainer);
|
|
1481
|
+
toggle.querySelectorAll('button').forEach(btn => {
|
|
1482
|
+
btn.addEventListener('click', e => {
|
|
1483
|
+
e.preventDefault();
|
|
1484
|
+
this.setEditorMode(wrapper, input, btn.dataset.mode || 'technical');
|
|
1485
|
+
});
|
|
1486
|
+
});
|
|
1487
|
+
if (initialMode === 'simple') {
|
|
1488
|
+
this.renderSimpleMode(simpleContainer, input);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
setEditorMode(wrapper, input, mode) {
|
|
1492
|
+
wrapper.dataset.mode = mode;
|
|
1493
|
+
wrapper.querySelectorAll('.expression-editor-toggle__btn').forEach(btn => {
|
|
1494
|
+
btn.classList.toggle('active', btn.dataset.mode === mode);
|
|
1495
|
+
});
|
|
1496
|
+
const technicalContainer = wrapper.querySelector('.expression-editor-technical');
|
|
1497
|
+
const simpleContainer = wrapper.querySelector('.expression-editor-simple');
|
|
1498
|
+
const invalidArgsStr = wrapper.dataset.invalidArgs;
|
|
1499
|
+
const invalidArgs = invalidArgsStr ? JSON.parse(invalidArgsStr) : [];
|
|
1500
|
+
if (mode === 'simple') {
|
|
1501
|
+
technicalContainer.style.display = 'none';
|
|
1502
|
+
simpleContainer.style.display = 'block';
|
|
1503
|
+
input.classList.remove('validation-error-param');
|
|
1504
|
+
this.renderSimpleMode(simpleContainer, input);
|
|
1505
|
+
if (invalidArgs.length > 0) {
|
|
1506
|
+
setTimeout(() => {
|
|
1507
|
+
for (const idx of invalidArgs) {
|
|
1508
|
+
const paramInput = simpleContainer.querySelector(`.expression-editor-param input[data-param-index="${idx}"]`);
|
|
1509
|
+
if (paramInput) {
|
|
1510
|
+
paramInput.classList.add('validation-error-param');
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}, 0);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
else {
|
|
1517
|
+
technicalContainer.style.display = 'block';
|
|
1518
|
+
simpleContainer.style.display = 'none';
|
|
1519
|
+
if (invalidArgs.length > 0) {
|
|
1520
|
+
input.classList.add('validation-error-param');
|
|
1521
|
+
}
|
|
1522
|
+
setTimeout(() => input.blur(), 0);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
renderSimpleMode(container, input) {
|
|
1526
|
+
this.cleanupClickHandlers();
|
|
1527
|
+
const parsed = this.parseExpression(input.value);
|
|
1528
|
+
container.innerHTML = `
|
|
1529
|
+
<div class="expression-editor-field" data-container="bean">
|
|
1530
|
+
<label>Service</label>
|
|
1531
|
+
</div>
|
|
1532
|
+
<div class="expression-editor-field" data-container="method"></div>
|
|
1533
|
+
<div data-container="params"></div>
|
|
1534
|
+
`;
|
|
1535
|
+
const beanContainer = container.querySelector('[data-container="bean"]');
|
|
1536
|
+
this.renderCustomSelect(beanContainer, this.processBeans.map(b => ({
|
|
1537
|
+
value: b.name,
|
|
1538
|
+
label: this.camelCaseToReadable(b.name),
|
|
1539
|
+
description: b.description,
|
|
1540
|
+
})), parsed.beanName, 'Select service...', 'bean', beanName => {
|
|
1541
|
+
this.renderMethodDropdown(container, beanName, null, input);
|
|
1542
|
+
this.renderParameterInputs(container, beanName, null, [], input);
|
|
1543
|
+
this.buildAndSetExpression(container, input);
|
|
1544
|
+
});
|
|
1545
|
+
if (parsed.beanName) {
|
|
1546
|
+
this.renderMethodDropdown(container, parsed.beanName, parsed.methodName, input);
|
|
1547
|
+
}
|
|
1548
|
+
if (parsed.beanName && parsed.methodName) {
|
|
1549
|
+
this.renderParameterInputs(container, parsed.beanName, parsed.methodName, parsed.parameters, input);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
renderCustomSelect(container, options, selectedValue, placeholder, dataField, onChange) {
|
|
1553
|
+
const wrapper = document.createElement('div');
|
|
1554
|
+
wrapper.className = 'expression-editor-custom-select';
|
|
1555
|
+
wrapper.dataset.field = dataField;
|
|
1556
|
+
wrapper.dataset.value = selectedValue || '';
|
|
1557
|
+
const nativeSelect = document.createElement('select');
|
|
1558
|
+
nativeSelect.className = 'bio-properties-panel-input';
|
|
1559
|
+
nativeSelect.innerHTML =
|
|
1560
|
+
`<option value="" disabled ${!selectedValue ? 'selected' : ''}>${this.escapeHtml(placeholder)}</option>` +
|
|
1561
|
+
options
|
|
1562
|
+
.map(opt => `<option value="${this.escapeAttr(opt.value)}" ${opt.value === selectedValue ? 'selected' : ''}>${this.escapeHtml(opt.label)}</option>`)
|
|
1563
|
+
.join('');
|
|
1564
|
+
const selectedOption = options.find(o => o.value === selectedValue);
|
|
1565
|
+
if (selectedOption?.description) {
|
|
1566
|
+
nativeSelect.title = selectedOption.description;
|
|
1567
|
+
}
|
|
1568
|
+
const dropdown = document.createElement('div');
|
|
1569
|
+
dropdown.className = 'expression-editor-custom-select__dropdown';
|
|
1570
|
+
dropdown.style.display = 'none';
|
|
1571
|
+
let selectedIndex = options.findIndex(o => o.value === selectedValue);
|
|
1572
|
+
if (selectedIndex < 0)
|
|
1573
|
+
selectedIndex = 0;
|
|
1574
|
+
const renderItems = () => {
|
|
1575
|
+
dropdown.innerHTML = options
|
|
1576
|
+
.map((opt, i) => `
|
|
1577
|
+
<div class="expression-editor-custom-select__item${opt.value === selectedValue ? ' selected' : ''}" data-index="${i}" data-value="${this.escapeAttr(opt.value)}">
|
|
1578
|
+
<div class="expression-editor-custom-select__label">${this.escapeHtml(opt.label)}</div>
|
|
1579
|
+
${opt.description ? `<div class="expression-editor-custom-select__desc">${this.escapeHtml(opt.description)}</div>` : ''}
|
|
1580
|
+
</div>
|
|
1581
|
+
`)
|
|
1582
|
+
.join('');
|
|
1583
|
+
dropdown.querySelectorAll('.expression-editor-custom-select__item').forEach(item => {
|
|
1584
|
+
item.addEventListener('click', e => {
|
|
1585
|
+
e.stopPropagation();
|
|
1586
|
+
const value = item.dataset.value;
|
|
1587
|
+
const selected = options.find(o => o.value === value);
|
|
1588
|
+
wrapper.dataset.value = value;
|
|
1589
|
+
nativeSelect.value = value;
|
|
1590
|
+
nativeSelect.title = selected?.description || '';
|
|
1591
|
+
dropdown.style.display = 'none';
|
|
1592
|
+
onChange(value);
|
|
1593
|
+
});
|
|
1594
|
+
});
|
|
1595
|
+
};
|
|
1596
|
+
renderItems();
|
|
1597
|
+
nativeSelect.addEventListener('mousedown', e => {
|
|
1598
|
+
e.preventDefault();
|
|
1599
|
+
nativeSelect.focus();
|
|
1600
|
+
const isOpen = dropdown.style.display !== 'none';
|
|
1601
|
+
dropdown.style.display = isOpen ? 'none' : 'block';
|
|
1602
|
+
});
|
|
1603
|
+
nativeSelect.addEventListener('keydown', e => {
|
|
1604
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
1605
|
+
e.preventDefault();
|
|
1606
|
+
if (dropdown.style.display === 'none') {
|
|
1607
|
+
dropdown.style.display = 'block';
|
|
1608
|
+
}
|
|
1609
|
+
const delta = e.key === 'ArrowDown' ? 1 : -1;
|
|
1610
|
+
selectedIndex = Math.max(0, Math.min(options.length - 1, selectedIndex + delta));
|
|
1611
|
+
dropdown.querySelectorAll('.expression-editor-custom-select__item').forEach((item, i) => {
|
|
1612
|
+
item.classList.toggle('highlighted', i === selectedIndex);
|
|
1613
|
+
});
|
|
1614
|
+
dropdown.children[selectedIndex]?.scrollIntoView({ block: 'nearest' });
|
|
1615
|
+
}
|
|
1616
|
+
else if (e.key === 'Enter' && dropdown.style.display !== 'none') {
|
|
1617
|
+
e.preventDefault();
|
|
1618
|
+
const opt = options[selectedIndex];
|
|
1619
|
+
if (opt) {
|
|
1620
|
+
wrapper.dataset.value = opt.value;
|
|
1621
|
+
nativeSelect.value = opt.value;
|
|
1622
|
+
nativeSelect.title = opt.description || '';
|
|
1623
|
+
dropdown.style.display = 'none';
|
|
1624
|
+
onChange(opt.value);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
else if (e.key === 'Escape') {
|
|
1628
|
+
dropdown.style.display = 'none';
|
|
1629
|
+
}
|
|
1630
|
+
else if (e.key === ' ' && dropdown.style.display === 'none') {
|
|
1631
|
+
e.preventDefault();
|
|
1632
|
+
dropdown.style.display = 'block';
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1635
|
+
const closeHandler = (e) => {
|
|
1636
|
+
if (!wrapper.contains(e.target)) {
|
|
1637
|
+
dropdown.style.display = 'none';
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
document.addEventListener('click', closeHandler);
|
|
1641
|
+
this.documentClickHandlers.push(closeHandler);
|
|
1642
|
+
wrapper.appendChild(nativeSelect);
|
|
1643
|
+
wrapper.appendChild(dropdown);
|
|
1644
|
+
container.appendChild(wrapper);
|
|
1645
|
+
}
|
|
1646
|
+
renderMethodDropdown(container, beanName, selectedMethod, input) {
|
|
1647
|
+
const methodContainer = container.querySelector('[data-container="method"]');
|
|
1648
|
+
if (!methodContainer)
|
|
1649
|
+
return;
|
|
1650
|
+
const bean = this.processBeans.find(b => b.name === beanName);
|
|
1651
|
+
if (!bean) {
|
|
1652
|
+
methodContainer.innerHTML = '';
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
methodContainer.innerHTML = '<label>Method</label>';
|
|
1656
|
+
this.renderCustomSelect(methodContainer, bean.methods.map(m => ({
|
|
1657
|
+
value: m.name,
|
|
1658
|
+
label: this.camelCaseToReadable(m.name),
|
|
1659
|
+
description: m.description,
|
|
1660
|
+
})), selectedMethod, 'Select method...', 'method', methodName => {
|
|
1661
|
+
this.renderParameterInputs(container, beanName, methodName, [], input);
|
|
1662
|
+
this.buildAndSetExpression(container, input);
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
renderParameterInputs(container, beanName, methodName, values, input) {
|
|
1666
|
+
const paramsContainer = container.querySelector('[data-container="params"]');
|
|
1667
|
+
if (!paramsContainer)
|
|
1668
|
+
return;
|
|
1669
|
+
if (!methodName) {
|
|
1670
|
+
paramsContainer.innerHTML = '';
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
const bean = this.processBeans.find(b => b.name === beanName);
|
|
1674
|
+
const method = bean?.methods.find(m => m.name === methodName);
|
|
1675
|
+
if (!method || method.parameters.length === 0) {
|
|
1676
|
+
paramsContainer.innerHTML = '';
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
paramsContainer.innerHTML = method.parameters
|
|
1680
|
+
.map((p, i) => `
|
|
1681
|
+
<div class="expression-editor-param">
|
|
1682
|
+
<label>${this.escapeHtml(p.name)} <span class="type">(${this.escapeHtml(p.type)})</span></label>
|
|
1683
|
+
<input type="text" class="expression-editor-input" data-param-index="${i}" value="${this.escapeAttr(values[i] || '')}">
|
|
1039
1684
|
</div>
|
|
1040
|
-
|
|
1685
|
+
`)
|
|
1686
|
+
.join('');
|
|
1687
|
+
paramsContainer.querySelectorAll('input').forEach(paramInput => {
|
|
1688
|
+
paramInput.addEventListener('input', () => {
|
|
1689
|
+
this.buildAndSetExpression(container, input);
|
|
1690
|
+
});
|
|
1691
|
+
});
|
|
1041
1692
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1693
|
+
buildAndSetExpression(simpleContainer, input) {
|
|
1694
|
+
const beanSelect = simpleContainer.querySelector('[data-field="bean"]');
|
|
1695
|
+
const methodSelect = simpleContainer.querySelector('[data-field="method"]');
|
|
1696
|
+
const paramInputs = simpleContainer.querySelectorAll('[data-param-index]');
|
|
1697
|
+
const bean = beanSelect?.dataset.value;
|
|
1698
|
+
const method = methodSelect?.dataset.value;
|
|
1699
|
+
if (!bean || !method) {
|
|
1700
|
+
input.value = '';
|
|
1701
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
const params = Array.from(paramInputs).map(i => i.value);
|
|
1705
|
+
input.value = `\${${bean}.${method}(${params.join(', ')})}`;
|
|
1706
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
1707
|
+
}
|
|
1708
|
+
parseExpression(expr) {
|
|
1709
|
+
const match = expr.match(/^\$\{([a-zA-Z_]\w*)\.([a-zA-Z_]\w*)\((.*)\)\}$/);
|
|
1710
|
+
if (!match)
|
|
1711
|
+
return { beanName: null, methodName: null, parameters: [] };
|
|
1712
|
+
return {
|
|
1713
|
+
beanName: match[1],
|
|
1714
|
+
methodName: match[2],
|
|
1715
|
+
parameters: this.parseParameters(match[3]),
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
parseParameters(paramsStr) {
|
|
1719
|
+
const params = [];
|
|
1720
|
+
let current = '';
|
|
1721
|
+
let depth = 0;
|
|
1722
|
+
let inString = false;
|
|
1723
|
+
let stringChar = '';
|
|
1724
|
+
for (const char of paramsStr) {
|
|
1725
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
1726
|
+
inString = true;
|
|
1727
|
+
stringChar = char;
|
|
1728
|
+
current += char;
|
|
1729
|
+
}
|
|
1730
|
+
else if (inString && char === stringChar) {
|
|
1731
|
+
inString = false;
|
|
1732
|
+
current += char;
|
|
1733
|
+
}
|
|
1734
|
+
else if (!inString && (char === '(' || char === '[')) {
|
|
1735
|
+
depth++;
|
|
1736
|
+
current += char;
|
|
1737
|
+
}
|
|
1738
|
+
else if (!inString && (char === ')' || char === ']')) {
|
|
1739
|
+
depth--;
|
|
1740
|
+
current += char;
|
|
1741
|
+
}
|
|
1742
|
+
else if (!inString && char === ',' && depth === 0) {
|
|
1743
|
+
params.push(current.trim());
|
|
1744
|
+
current = '';
|
|
1745
|
+
}
|
|
1746
|
+
else {
|
|
1747
|
+
current += char;
|
|
1078
1748
|
}
|
|
1079
1749
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1750
|
+
if (current.trim())
|
|
1751
|
+
params.push(current.trim());
|
|
1752
|
+
return params;
|
|
1753
|
+
}
|
|
1754
|
+
escapeHtml(text) {
|
|
1755
|
+
const div = document.createElement('div');
|
|
1756
|
+
div.textContent = text;
|
|
1757
|
+
return div.innerHTML;
|
|
1758
|
+
}
|
|
1759
|
+
escapeAttr(text) {
|
|
1760
|
+
return text
|
|
1761
|
+
.replace(/&/g, '&')
|
|
1762
|
+
.replace(/"/g, '"')
|
|
1763
|
+
.replace(/'/g, ''')
|
|
1764
|
+
.replace(/</g, '<')
|
|
1765
|
+
.replace(/>/g, '>');
|
|
1766
|
+
}
|
|
1767
|
+
camelCaseToReadable(text) {
|
|
1768
|
+
return text
|
|
1769
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
1770
|
+
.replace(/^./, str => str.toUpperCase());
|
|
1771
|
+
}
|
|
1772
|
+
injectStyles() {
|
|
1773
|
+
if (this.stylesInjected)
|
|
1774
|
+
return;
|
|
1775
|
+
this.stylesInjected = true;
|
|
1776
|
+
const style = document.createElement('style');
|
|
1777
|
+
style.textContent = `
|
|
1778
|
+
/* Expression Editor Toggle UI */
|
|
1779
|
+
.expression-editor-wrapper {
|
|
1780
|
+
width: 100%;
|
|
1781
|
+
}
|
|
1782
|
+
.expression-editor-toggle {
|
|
1783
|
+
display: flex;
|
|
1784
|
+
gap: 0;
|
|
1785
|
+
margin-bottom: 8px;
|
|
1786
|
+
}
|
|
1787
|
+
.expression-editor-toggle__btn {
|
|
1788
|
+
flex: 1;
|
|
1789
|
+
padding: 4px 8px;
|
|
1790
|
+
border: 1px solid #ccc;
|
|
1791
|
+
background: #fafafa;
|
|
1792
|
+
color: #333;
|
|
1793
|
+
cursor: pointer;
|
|
1794
|
+
font-size: 13px;
|
|
1795
|
+
font-family: inherit;
|
|
1796
|
+
}
|
|
1797
|
+
.expression-editor-toggle__btn:first-child {
|
|
1798
|
+
border-radius: 2px 0 0 2px;
|
|
1799
|
+
}
|
|
1800
|
+
.expression-editor-toggle__btn:last-child {
|
|
1801
|
+
border-radius: 0 2px 2px 0;
|
|
1802
|
+
border-left: none;
|
|
1803
|
+
}
|
|
1804
|
+
.expression-editor-toggle__btn.active {
|
|
1805
|
+
background: #2b79bd;
|
|
1806
|
+
color: white;
|
|
1807
|
+
border-color: #2b79bd;
|
|
1808
|
+
}
|
|
1809
|
+
.expression-editor-toggle__btn:hover:not(.active) {
|
|
1810
|
+
background: #fff;
|
|
1811
|
+
}
|
|
1812
|
+
.expression-editor-simple {
|
|
1813
|
+
display: flex;
|
|
1814
|
+
flex-direction: column;
|
|
1815
|
+
gap: 6px;
|
|
1816
|
+
}
|
|
1817
|
+
.expression-editor-field label,
|
|
1818
|
+
.expression-editor-param > label {
|
|
1819
|
+
display: block;
|
|
1820
|
+
font-size: var(--text-size-small, 12px);
|
|
1821
|
+
color: var(--label-color, #666);
|
|
1822
|
+
margin-bottom: 2px;
|
|
1823
|
+
}
|
|
1824
|
+
.expression-editor-field label .type,
|
|
1825
|
+
.expression-editor-param label .type {
|
|
1826
|
+
color: var(--description-color, #808080);
|
|
1827
|
+
}
|
|
1828
|
+
.expression-editor-select,
|
|
1829
|
+
.expression-editor-input {
|
|
1830
|
+
display: block;
|
|
1831
|
+
width: 100%;
|
|
1832
|
+
padding: 3px 6px 2px;
|
|
1833
|
+
border: 1px solid #ccc;
|
|
1834
|
+
border-radius: 2px;
|
|
1835
|
+
font-size: 14px;
|
|
1836
|
+
background-color: #fafafa;
|
|
1837
|
+
font-family: inherit;
|
|
1838
|
+
box-sizing: border-box;
|
|
1839
|
+
}
|
|
1840
|
+
.expression-editor-select:focus,
|
|
1841
|
+
.expression-editor-input:focus {
|
|
1842
|
+
outline: none;
|
|
1843
|
+
background-color: hsl(205, 100%, 95%);
|
|
1844
|
+
border-color: hsl(205, 100%, 50%);
|
|
1845
|
+
}
|
|
1846
|
+
/* Override bpmn-js input styles to prevent focus-within highlighting */
|
|
1847
|
+
.expression-editor-technical input,
|
|
1848
|
+
.expression-editor-technical textarea {
|
|
1849
|
+
background-color: #fafafa !important;
|
|
1850
|
+
border-color: #ccc !important;
|
|
1851
|
+
}
|
|
1852
|
+
/* Override native select and input styles in simple mode */
|
|
1853
|
+
.expression-editor-simple select.bio-properties-panel-input,
|
|
1854
|
+
.expression-editor-simple .expression-editor-input {
|
|
1855
|
+
background-color: #fafafa !important;
|
|
1856
|
+
border-color: #ccc !important;
|
|
1857
|
+
}
|
|
1858
|
+
.expression-editor-simple select.bio-properties-panel-input:focus,
|
|
1859
|
+
.expression-editor-simple .expression-editor-input:focus {
|
|
1860
|
+
background-color: hsl(205, 100%, 95%) !important;
|
|
1861
|
+
border-color: hsl(205, 100%, 50%) !important;
|
|
1862
|
+
}
|
|
1863
|
+
.expression-editor-technical input:focus,
|
|
1864
|
+
.expression-editor-technical textarea:focus {
|
|
1865
|
+
background-color: hsl(205, 100%, 95%) !important;
|
|
1866
|
+
border-color: hsl(205, 100%, 50%) !important;
|
|
1867
|
+
}
|
|
1868
|
+
.expression-editor-param {
|
|
1869
|
+
padding-left: 8px;
|
|
1870
|
+
border-left: 2px solid #ccc;
|
|
1871
|
+
margin-top: 4px;
|
|
1872
|
+
}
|
|
1873
|
+
.expression-editor-description {
|
|
1874
|
+
font-size: var(--text-size-small, 12px);
|
|
1875
|
+
color: var(--description-color, #808080);
|
|
1876
|
+
margin-top: 4px;
|
|
1877
|
+
font-style: italic;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
/* Custom Select (Listbox) */
|
|
1881
|
+
.expression-editor-custom-select {
|
|
1882
|
+
position: relative;
|
|
1883
|
+
width: 100%;
|
|
1884
|
+
}
|
|
1885
|
+
.expression-editor-custom-select select {
|
|
1886
|
+
width: 100%;
|
|
1887
|
+
}
|
|
1888
|
+
.expression-editor-custom-select__dropdown {
|
|
1889
|
+
position: absolute;
|
|
1890
|
+
top: 100%;
|
|
1891
|
+
left: 0;
|
|
1892
|
+
right: 0;
|
|
1893
|
+
max-height: 200px;
|
|
1894
|
+
overflow-y: auto;
|
|
1895
|
+
background: #fff;
|
|
1896
|
+
border: 1px solid #ccc;
|
|
1897
|
+
border-radius: 2px;
|
|
1898
|
+
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
|
1899
|
+
z-index: 1000;
|
|
1900
|
+
margin-top: 2px;
|
|
1901
|
+
}
|
|
1902
|
+
.expression-editor-custom-select__item {
|
|
1903
|
+
padding: 8px;
|
|
1904
|
+
cursor: pointer;
|
|
1905
|
+
border-bottom: 1px solid #eee;
|
|
1906
|
+
}
|
|
1907
|
+
.expression-editor-custom-select__item:last-child {
|
|
1908
|
+
border-bottom: none;
|
|
1909
|
+
}
|
|
1910
|
+
.expression-editor-custom-select__item:hover,
|
|
1911
|
+
.expression-editor-custom-select__item.selected,
|
|
1912
|
+
.expression-editor-custom-select__item.highlighted {
|
|
1913
|
+
background: hsl(205, 100%, 95%);
|
|
1914
|
+
}
|
|
1915
|
+
.expression-editor-custom-select__label {
|
|
1916
|
+
font-weight: 500;
|
|
1917
|
+
font-size: 14px;
|
|
1918
|
+
color: #333;
|
|
1919
|
+
}
|
|
1920
|
+
.expression-editor-custom-select__desc {
|
|
1921
|
+
font-size: 11px;
|
|
1922
|
+
color: #666;
|
|
1923
|
+
margin-top: 2px;
|
|
1924
|
+
}
|
|
1925
|
+
`;
|
|
1926
|
+
document.head.appendChild(style);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
const ExpressionAutocompleteModule = {
|
|
1930
|
+
__init__: ['expressionAutocomplete'],
|
|
1931
|
+
expressionAutocomplete: ['type', ExpressionAutocomplete],
|
|
1092
1932
|
};
|
|
1093
1933
|
|
|
1094
1934
|
/*
|
|
@@ -1123,7 +1963,13 @@ const ValtimoPropertiesProviderModule = {
|
|
|
1123
1963
|
* limitations under the License.
|
|
1124
1964
|
*/
|
|
1125
1965
|
class ProcessManagementBuilderComponent {
|
|
1126
|
-
|
|
1966
|
+
get activeEditor() {
|
|
1967
|
+
return this._viewerActive ? this._bpmnViewer : this._bpmnModeler;
|
|
1968
|
+
}
|
|
1969
|
+
get loadedEditors() {
|
|
1970
|
+
return [this._bpmnModeler, this._bpmnViewer].filter(editor => !!editor);
|
|
1971
|
+
}
|
|
1972
|
+
constructor(breadcrumbService, iconService, logger, modalService, notificationService, pageHeaderService, pageTitleService, processLinkService, processLinkStateService, processManagementEditorService, processManagementService, processService, route, router, translateService, pluginTranslationService, editPermissionsService, processLinkBuildingBlockApiService, processBeanService) {
|
|
1127
1973
|
this.breadcrumbService = breadcrumbService;
|
|
1128
1974
|
this.iconService = iconService;
|
|
1129
1975
|
this.logger = logger;
|
|
@@ -1142,26 +1988,41 @@ class ProcessManagementBuilderComponent {
|
|
|
1142
1988
|
this.pluginTranslationService = pluginTranslationService;
|
|
1143
1989
|
this.editPermissionsService = editPermissionsService;
|
|
1144
1990
|
this.processLinkBuildingBlockApiService = processLinkBuildingBlockApiService;
|
|
1991
|
+
this.processBeanService = processBeanService;
|
|
1145
1992
|
this._selectedProcess$ = new BehaviorSubject(null);
|
|
1146
1993
|
this.loading$ = new BehaviorSubject(true);
|
|
1147
1994
|
this._validationErrorElementIds = [];
|
|
1148
1995
|
this._validationHoverHandler = null;
|
|
1149
1996
|
this._validationOutHandler = null;
|
|
1997
|
+
this._selectionChangedHandler = null;
|
|
1998
|
+
this._fieldInputCleanupFns = [];
|
|
1999
|
+
this._expressionAutocomplete = null;
|
|
2000
|
+
this._activityMarkerElementIds = [];
|
|
2001
|
+
this._activityMarkerUpdateTimeout = null;
|
|
2002
|
+
this._autofilledElements = [];
|
|
2003
|
+
this._autofilledElementIds = [];
|
|
2004
|
+
this._viewerActive = false;
|
|
1150
2005
|
this.isReadOnlyProcess$ = new BehaviorSubject(false);
|
|
1151
2006
|
this.isSystemProcess$ = new BehaviorSubject(false);
|
|
1152
2007
|
this.draft$ = new BehaviorSubject(false);
|
|
1153
2008
|
this.canInitializeDocument$ = new BehaviorSubject(false);
|
|
1154
2009
|
this.startableByUser$ = new BehaviorSubject(false);
|
|
1155
2010
|
this.validationErrors$ = this.processManagementEditorService.validationErrors$;
|
|
2011
|
+
this.$markersVisible = signal(true);
|
|
1156
2012
|
this.testIds = PROCESS_MANAGEMENT_BUILDER_TEST_IDS;
|
|
1157
2013
|
this.selectedProcessDefinitionXml$ = this.processManagementEditorService.selectionProcessDefinition$.pipe(filter(selectedProcessDefinition => !!selectedProcessDefinition?.id), distinctUntilChanged((previous, current) => isEqual(previous, current)), tap(selectedProcessDefinition => {
|
|
1158
2014
|
this.loading$.next(true);
|
|
1159
2015
|
this.pageTitleService.setCustomPageTitle(selectedProcessDefinition?.name || '-');
|
|
1160
2016
|
}), switchMap(selectedProcessDefinition => this.processService.getProcessDefinitionXml(selectedProcessDefinition.id)), tap(result => {
|
|
1161
2017
|
this.cleanUpListenersOnModeler();
|
|
1162
|
-
this.
|
|
1163
|
-
this.
|
|
1164
|
-
this.
|
|
2018
|
+
this._autofilledElements = result.autofilledElements ?? [];
|
|
2019
|
+
this.processManagementEditorService.setAutofilledElements(this._autofilledElements);
|
|
2020
|
+
this._bpmnModeler?.importXML(result.bpmn20Xml).then(() => {
|
|
2021
|
+
this.highlightAutofilledElements();
|
|
2022
|
+
});
|
|
2023
|
+
this._bpmnViewer?.importXML(result.bpmn20Xml).then(() => {
|
|
2024
|
+
this.highlightAutofilledElements();
|
|
2025
|
+
});
|
|
1165
2026
|
this.isReadOnlyProcess$.next(result.readOnly);
|
|
1166
2027
|
this.isSystemProcess$.next(result.systemProcess);
|
|
1167
2028
|
this.loading$.next(false);
|
|
@@ -1186,6 +2047,10 @@ class ProcessManagementBuilderComponent {
|
|
|
1186
2047
|
}
|
|
1187
2048
|
return this.managementParams$.pipe(switchMap(params => this.editPermissionsService.hasPermissionsToEditBasedOnContext(params, context)));
|
|
1188
2049
|
}));
|
|
2050
|
+
this.viewerActive$ = combineLatest([
|
|
2051
|
+
this.isReadOnlyProcess$,
|
|
2052
|
+
this.hasEditPermissions$,
|
|
2053
|
+
]).pipe(map$1(([isReadOnlyProcess, hasEditPermissions]) => isReadOnlyProcess || !hasEditPermissions), distinctUntilChanged());
|
|
1189
2054
|
this._reload$ = new Subject();
|
|
1190
2055
|
this.processDefinitionVersions$ = combineLatest([this.editParam$, this.context$, this._reload$.pipe(startWith(null))]).pipe(switchMap(([editParam, context]) => context === 'independent'
|
|
1191
2056
|
? this.processManagementService.getUnlinkedProcessDefinitionsByKey(editParam)
|
|
@@ -1228,8 +2093,9 @@ class ProcessManagementBuilderComponent {
|
|
|
1228
2093
|
if (!activityId || !businessId)
|
|
1229
2094
|
return;
|
|
1230
2095
|
this.processManagementEditorService.updateProcessLinksOnIdChange(activityId, businessId);
|
|
2096
|
+
this.scheduleActivityMarkerUpdate();
|
|
1231
2097
|
};
|
|
1232
|
-
this.iconService.registerAll([
|
|
2098
|
+
this.iconService.registerAll([View16, ViewOff16]);
|
|
1233
2099
|
this.setProcessManagementWindow();
|
|
1234
2100
|
}
|
|
1235
2101
|
ngAfterViewInit() {
|
|
@@ -1242,10 +2108,16 @@ class ProcessManagementBuilderComponent {
|
|
|
1242
2108
|
this.subscribeToProcessLinkUpdateEvents();
|
|
1243
2109
|
this.subscribeToProcessLinkCreateEvents();
|
|
1244
2110
|
this.subscribeToProcessLinkDeleteEvents();
|
|
2111
|
+
this.subscribeToAutofillDismissEvents();
|
|
2112
|
+
this.subscribeToViewerActive();
|
|
1245
2113
|
this.initEditing();
|
|
1246
2114
|
}
|
|
1247
2115
|
ngOnDestroy() {
|
|
1248
2116
|
this.clearValidationErrors();
|
|
2117
|
+
this.clearActivityMarkers();
|
|
2118
|
+
if (this._activityMarkerUpdateTimeout) {
|
|
2119
|
+
clearTimeout(this._activityMarkerUpdateTimeout);
|
|
2120
|
+
}
|
|
1249
2121
|
this._bpmnModeler?.destroy();
|
|
1250
2122
|
this._bpmnViewer?.destroy();
|
|
1251
2123
|
this._subscriptions.unsubscribe();
|
|
@@ -1255,19 +2127,50 @@ class ProcessManagementBuilderComponent {
|
|
|
1255
2127
|
this.breadcrumbService.clearThirdBreadcrumb();
|
|
1256
2128
|
this.breadcrumbService.clearFourthBreadcrumb();
|
|
1257
2129
|
}
|
|
1258
|
-
|
|
2130
|
+
exportBpmn(isReadOnlyProcess) {
|
|
1259
2131
|
(isReadOnlyProcess ? from(this._bpmnViewer.saveXML()) : from(this._bpmnModeler.saveXML()))
|
|
1260
2132
|
.pipe(take(1))
|
|
1261
2133
|
.subscribe(result => {
|
|
1262
2134
|
const file = new Blob([result.xml ?? ''], { type: 'text/xml' });
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
2135
|
+
const processDefinitionKey = this.processManagementEditorService.selectionProcessDefinition?.key;
|
|
2136
|
+
this.downloadFile(file, processDefinitionKey ? `${processDefinitionKey}.bpmn` : 'diagram.bpmn');
|
|
2137
|
+
});
|
|
2138
|
+
}
|
|
2139
|
+
export() {
|
|
2140
|
+
const processDefinitionId = this.processManagementEditorService.selectionProcessDefinition?.id;
|
|
2141
|
+
if (!processDefinitionId) {
|
|
2142
|
+
this.showNotification('exportError');
|
|
2143
|
+
return;
|
|
2144
|
+
}
|
|
2145
|
+
this.processManagementService
|
|
2146
|
+
.exportProcessDefinition(processDefinitionId)
|
|
2147
|
+
.pipe(take(1))
|
|
2148
|
+
.subscribe({
|
|
2149
|
+
next: response => {
|
|
2150
|
+
const blob = response.body;
|
|
2151
|
+
if (!blob) {
|
|
2152
|
+
this.showNotification('exportError');
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
this.downloadFile(blob, this.getFileName(response));
|
|
2156
|
+
},
|
|
2157
|
+
error: () => {
|
|
2158
|
+
this.showNotification('exportError');
|
|
2159
|
+
},
|
|
1269
2160
|
});
|
|
1270
2161
|
}
|
|
2162
|
+
getFileName(response) {
|
|
2163
|
+
const contentDisposition = response.headers.get('Content-Disposition') ?? '';
|
|
2164
|
+
return contentDisposition.split('filename=')[1]?.replace(/"/g, '').trim() || 'process.zip';
|
|
2165
|
+
}
|
|
2166
|
+
downloadFile(file, fileName) {
|
|
2167
|
+
const link = document.createElement('a');
|
|
2168
|
+
link.download = fileName;
|
|
2169
|
+
link.href = window.URL.createObjectURL(file);
|
|
2170
|
+
link.click();
|
|
2171
|
+
window.URL.revokeObjectURL(link.href);
|
|
2172
|
+
link.remove();
|
|
2173
|
+
}
|
|
1271
2174
|
validateProcessDefinition(isReadOnlyProcess) {
|
|
1272
2175
|
combineLatest([
|
|
1273
2176
|
from(isReadOnlyProcess ? this._bpmnViewer.saveXML() : this._bpmnModeler.saveXML()),
|
|
@@ -1281,6 +2184,8 @@ class ProcessManagementBuilderComponent {
|
|
|
1281
2184
|
...link,
|
|
1282
2185
|
processDefinitionId: '-',
|
|
1283
2186
|
})),
|
|
2187
|
+
canInitializeDocument: this.canInitializeDocument$.getValue(),
|
|
2188
|
+
startableByUser: this.startableByUser$.getValue(),
|
|
1284
2189
|
});
|
|
1285
2190
|
}))
|
|
1286
2191
|
.subscribe({
|
|
@@ -1321,6 +2226,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1321
2226
|
.subscribe({
|
|
1322
2227
|
next: context => {
|
|
1323
2228
|
this.clearValidationErrors();
|
|
2229
|
+
this.processManagementEditorService.clearDismissedAutofills();
|
|
1324
2230
|
if (context === 'independent') {
|
|
1325
2231
|
this.reload();
|
|
1326
2232
|
this.showNotification('success');
|
|
@@ -1369,6 +2275,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1369
2275
|
.subscribe({
|
|
1370
2276
|
next: () => {
|
|
1371
2277
|
this.clearValidationErrors();
|
|
2278
|
+
this.processManagementEditorService.clearDismissedAutofills();
|
|
1372
2279
|
this.navigateBack('success');
|
|
1373
2280
|
},
|
|
1374
2281
|
error: (error) => {
|
|
@@ -1400,27 +2307,6 @@ class ProcessManagementBuilderComponent {
|
|
|
1400
2307
|
return;
|
|
1401
2308
|
this.showNotification(notification);
|
|
1402
2309
|
}
|
|
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
2310
|
onProcessToggleChange(field, value) {
|
|
1425
2311
|
if (field === 'draft')
|
|
1426
2312
|
this.draft$.next(value);
|
|
@@ -1440,7 +2326,6 @@ class ProcessManagementBuilderComponent {
|
|
|
1440
2326
|
this._pendingDeployAction = null;
|
|
1441
2327
|
}
|
|
1442
2328
|
validateAndDeploy(isReadOnlyProcess, deployAction) {
|
|
1443
|
-
// Skip validation for draft processes
|
|
1444
2329
|
if (this.draft$.getValue()) {
|
|
1445
2330
|
deployAction();
|
|
1446
2331
|
return;
|
|
@@ -1457,27 +2342,25 @@ class ProcessManagementBuilderComponent {
|
|
|
1457
2342
|
...link,
|
|
1458
2343
|
processDefinitionId: '-',
|
|
1459
2344
|
})),
|
|
2345
|
+
canInitializeDocument: this.canInitializeDocument$.getValue(),
|
|
2346
|
+
startableByUser: this.startableByUser$.getValue(),
|
|
1460
2347
|
});
|
|
1461
2348
|
}))
|
|
1462
2349
|
.subscribe({
|
|
1463
2350
|
next: validationResult => {
|
|
1464
2351
|
if (!validationResult.isValid) {
|
|
1465
|
-
// Has errors - show them and block deployment
|
|
1466
2352
|
this.highlightValidationErrors(validationResult.errors);
|
|
1467
2353
|
}
|
|
1468
2354
|
else if (validationResult.hasWarnings) {
|
|
1469
|
-
// Only warnings - show confirmation dialog
|
|
1470
2355
|
this.highlightValidationErrors(validationResult.errors);
|
|
1471
2356
|
this._pendingDeployAction = deployAction;
|
|
1472
2357
|
this.showWarningConfirmationModal$.next(true);
|
|
1473
2358
|
}
|
|
1474
2359
|
else {
|
|
1475
|
-
// No issues - proceed with deployment
|
|
1476
2360
|
deployAction();
|
|
1477
2361
|
}
|
|
1478
2362
|
},
|
|
1479
2363
|
error: () => {
|
|
1480
|
-
// Validation endpoint failed - proceed with deployment anyway (server will validate again)
|
|
1481
2364
|
deployAction();
|
|
1482
2365
|
},
|
|
1483
2366
|
});
|
|
@@ -1489,6 +2372,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1489
2372
|
processManagementWindow.processManagementEditorService = this.processManagementEditorService;
|
|
1490
2373
|
processManagementWindow.translateService = this.translateService;
|
|
1491
2374
|
processManagementWindow.pluginTranslationService = this.pluginTranslationService;
|
|
2375
|
+
processManagementWindow.processLinkService = this.processLinkService;
|
|
1492
2376
|
}
|
|
1493
2377
|
showNotification(notification) {
|
|
1494
2378
|
if (!notification)
|
|
@@ -1496,6 +2380,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1496
2380
|
let type;
|
|
1497
2381
|
if (notification === 'alreadyExists' ||
|
|
1498
2382
|
notification === 'validationError' ||
|
|
2383
|
+
notification === 'exportError' ||
|
|
1499
2384
|
notification === 'error') {
|
|
1500
2385
|
type = 'error';
|
|
1501
2386
|
}
|
|
@@ -1557,7 +2442,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1557
2442
|
highlightValidationErrors(errors) {
|
|
1558
2443
|
this.clearValidationErrors();
|
|
1559
2444
|
this.processManagementEditorService.setValidationErrors(errors);
|
|
1560
|
-
const modeler = this.
|
|
2445
|
+
const modeler = this.activeEditor;
|
|
1561
2446
|
const canvas = modeler.get('canvas');
|
|
1562
2447
|
const overlays = modeler.get('overlays');
|
|
1563
2448
|
const errorElementIds = new Set();
|
|
@@ -1620,6 +2505,10 @@ class ProcessManagementBuilderComponent {
|
|
|
1620
2505
|
};
|
|
1621
2506
|
eventBus.on('element.hover', this._validationHoverHandler);
|
|
1622
2507
|
eventBus.on('element.out', this._validationOutHandler);
|
|
2508
|
+
this._selectionChangedHandler = (event) => {
|
|
2509
|
+
this.highlightInvalidFieldsInPropertiesPanel(event.newSelection, errors);
|
|
2510
|
+
};
|
|
2511
|
+
eventBus.on('selection.changed', this._selectionChangedHandler);
|
|
1623
2512
|
const selection = modeler.get('selection');
|
|
1624
2513
|
const selected = selection.get();
|
|
1625
2514
|
if (selected?.length > 0) {
|
|
@@ -1628,8 +2517,88 @@ class ProcessManagementBuilderComponent {
|
|
|
1628
2517
|
selection.select(current);
|
|
1629
2518
|
}
|
|
1630
2519
|
}
|
|
2520
|
+
highlightInvalidFieldsInPropertiesPanel(newSelection, errors) {
|
|
2521
|
+
document.querySelectorAll('.validation-error-field').forEach(el => {
|
|
2522
|
+
el.classList.remove('validation-error-field');
|
|
2523
|
+
});
|
|
2524
|
+
document.querySelectorAll('.validation-error-param').forEach(el => {
|
|
2525
|
+
el.classList.remove('validation-error-param');
|
|
2526
|
+
});
|
|
2527
|
+
if (!newSelection?.length)
|
|
2528
|
+
return;
|
|
2529
|
+
const selectedId = newSelection[0]?.id;
|
|
2530
|
+
if (!selectedId)
|
|
2531
|
+
return;
|
|
2532
|
+
const elementErrors = errors.filter(e => e.elementId === selectedId);
|
|
2533
|
+
setTimeout(() => {
|
|
2534
|
+
for (const error of elementErrors) {
|
|
2535
|
+
const listenerEntryId = error.listenerType != null && error.listenerIndex != null
|
|
2536
|
+
? `${selectedId}-${error.listenerType}-${error.listenerIndex}`
|
|
2537
|
+
: null;
|
|
2538
|
+
if (error.invalidFields) {
|
|
2539
|
+
for (const fieldId of error.invalidFields) {
|
|
2540
|
+
let entry = null;
|
|
2541
|
+
if (listenerEntryId) {
|
|
2542
|
+
const listenerEntry = document.querySelector(`[data-entry-id="${listenerEntryId}"]`);
|
|
2543
|
+
if (listenerEntry) {
|
|
2544
|
+
entry = listenerEntry.querySelector(`[data-entry-id="${fieldId}"]`);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
if (!entry) {
|
|
2548
|
+
entry = document.querySelector(`[data-entry-id="${fieldId}"]`);
|
|
2549
|
+
}
|
|
2550
|
+
if (entry) {
|
|
2551
|
+
entry.classList.add('validation-error-field');
|
|
2552
|
+
const input = entry.querySelector('input, textarea, select');
|
|
2553
|
+
if (input) {
|
|
2554
|
+
const handler = () => {
|
|
2555
|
+
entry.classList.remove('validation-error-field');
|
|
2556
|
+
input.removeEventListener('input', handler);
|
|
2557
|
+
input.removeEventListener('change', handler);
|
|
2558
|
+
};
|
|
2559
|
+
input.addEventListener('input', handler);
|
|
2560
|
+
input.addEventListener('change', handler);
|
|
2561
|
+
this._fieldInputCleanupFns.push(() => {
|
|
2562
|
+
input.removeEventListener('input', handler);
|
|
2563
|
+
input.removeEventListener('change', handler);
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
if (error.invalidArguments && error.invalidArguments.length > 0) {
|
|
2570
|
+
let scopeElement = null;
|
|
2571
|
+
if (listenerEntryId) {
|
|
2572
|
+
scopeElement = document.querySelector(`[data-entry-id="${listenerEntryId}"]`);
|
|
2573
|
+
}
|
|
2574
|
+
const wrapper = scopeElement
|
|
2575
|
+
? scopeElement.querySelector('.expression-editor-wrapper')
|
|
2576
|
+
: document.querySelector('.expression-editor-wrapper');
|
|
2577
|
+
if (wrapper) {
|
|
2578
|
+
wrapper.dataset.invalidArgs = JSON.stringify(error.invalidArguments);
|
|
2579
|
+
}
|
|
2580
|
+
for (const idx of error.invalidArguments) {
|
|
2581
|
+
const paramInput = scopeElement
|
|
2582
|
+
? scopeElement.querySelector(`.expression-editor-param input[data-param-index="${idx}"]`)
|
|
2583
|
+
: document.querySelector(`.expression-editor-param input[data-param-index="${idx}"]`);
|
|
2584
|
+
if (paramInput) {
|
|
2585
|
+
paramInput.classList.add('validation-error-param');
|
|
2586
|
+
const handler = () => {
|
|
2587
|
+
paramInput.classList.remove('validation-error-param');
|
|
2588
|
+
paramInput.removeEventListener('input', handler);
|
|
2589
|
+
};
|
|
2590
|
+
paramInput.addEventListener('input', handler);
|
|
2591
|
+
this._fieldInputCleanupFns.push(() => {
|
|
2592
|
+
paramInput.removeEventListener('input', handler);
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
}, 50);
|
|
2599
|
+
}
|
|
1631
2600
|
clearValidationErrors() {
|
|
1632
|
-
const modeler = this.
|
|
2601
|
+
const modeler = this.activeEditor;
|
|
1633
2602
|
if (!modeler)
|
|
1634
2603
|
return;
|
|
1635
2604
|
this.processManagementEditorService.setValidationErrors([]);
|
|
@@ -1644,6 +2613,21 @@ class ProcessManagementBuilderComponent {
|
|
|
1644
2613
|
eventBus.off('element.out', this._validationOutHandler);
|
|
1645
2614
|
this._validationOutHandler = null;
|
|
1646
2615
|
}
|
|
2616
|
+
if (this._selectionChangedHandler) {
|
|
2617
|
+
eventBus.off('selection.changed', this._selectionChangedHandler);
|
|
2618
|
+
this._selectionChangedHandler = null;
|
|
2619
|
+
}
|
|
2620
|
+
this._fieldInputCleanupFns.forEach(fn => fn());
|
|
2621
|
+
this._fieldInputCleanupFns = [];
|
|
2622
|
+
document.querySelectorAll('.validation-error-field').forEach(el => {
|
|
2623
|
+
el.classList.remove('validation-error-field');
|
|
2624
|
+
});
|
|
2625
|
+
document.querySelectorAll('.validation-error-param').forEach(el => {
|
|
2626
|
+
el.classList.remove('validation-error-param');
|
|
2627
|
+
});
|
|
2628
|
+
document.querySelectorAll('.expression-editor-wrapper[data-invalid-args]').forEach(el => {
|
|
2629
|
+
delete el.dataset.invalidArgs;
|
|
2630
|
+
});
|
|
1647
2631
|
for (const elementId of this._validationErrorElementIds) {
|
|
1648
2632
|
try {
|
|
1649
2633
|
canvas.removeMarker(elementId, 'highlight-overlay-error');
|
|
@@ -1661,6 +2645,209 @@ class ProcessManagementBuilderComponent {
|
|
|
1661
2645
|
// ignore
|
|
1662
2646
|
}
|
|
1663
2647
|
}
|
|
2648
|
+
highlightAutofilledElements() {
|
|
2649
|
+
this.clearAutofilledHighlights();
|
|
2650
|
+
if (!this._autofilledElements?.length)
|
|
2651
|
+
return;
|
|
2652
|
+
const modeler = this.activeEditor;
|
|
2653
|
+
if (!modeler)
|
|
2654
|
+
return;
|
|
2655
|
+
const overlays = modeler.get('overlays');
|
|
2656
|
+
for (const element of this._autofilledElements) {
|
|
2657
|
+
try {
|
|
2658
|
+
this._autofilledElementIds.push(element.activityId);
|
|
2659
|
+
const tooltipText = this.getAutofilledTooltip();
|
|
2660
|
+
overlays.add(element.activityId, 'autofilled-indicator', {
|
|
2661
|
+
position: { top: -12, left: -12 },
|
|
2662
|
+
html: this.buildAutofilledOverlayElement(element.activityId, tooltipText),
|
|
2663
|
+
});
|
|
2664
|
+
}
|
|
2665
|
+
catch (e) {
|
|
2666
|
+
// Element may not exist on the canvas
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
clearAutofilledHighlights() {
|
|
2671
|
+
const modeler = this.activeEditor;
|
|
2672
|
+
if (!modeler)
|
|
2673
|
+
return;
|
|
2674
|
+
const overlays = modeler.get('overlays');
|
|
2675
|
+
this._autofilledElementIds = [];
|
|
2676
|
+
try {
|
|
2677
|
+
overlays.remove({ type: 'autofilled-indicator' });
|
|
2678
|
+
}
|
|
2679
|
+
catch (e) {
|
|
2680
|
+
// ignore
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
buildAutofilledOverlayElement(elementId, tooltipText) {
|
|
2684
|
+
const container = document.createElement('div');
|
|
2685
|
+
container.className = 'autofilled-indicator-overlay';
|
|
2686
|
+
container.dataset.elementId = elementId;
|
|
2687
|
+
const icon = document.createElement('span');
|
|
2688
|
+
icon.className = 'autofilled-indicator-icon';
|
|
2689
|
+
icon.innerHTML = '!';
|
|
2690
|
+
container.appendChild(icon);
|
|
2691
|
+
const tooltip = document.createElement('span');
|
|
2692
|
+
tooltip.className = 'autofilled-indicator-tooltip';
|
|
2693
|
+
tooltip.textContent = tooltipText;
|
|
2694
|
+
container.appendChild(tooltip);
|
|
2695
|
+
return container;
|
|
2696
|
+
}
|
|
2697
|
+
getAutofilledTooltip() {
|
|
2698
|
+
return this.translateService.instant('processManagement.autofilled.generic');
|
|
2699
|
+
}
|
|
2700
|
+
getElementListeners(element) {
|
|
2701
|
+
const extensionElements = element?.businessObject?.extensionElements;
|
|
2702
|
+
const values = extensionElements?.values || [];
|
|
2703
|
+
const executionListeners = values.filter((v) => v.$type === 'camunda:ExecutionListener');
|
|
2704
|
+
const taskListeners = values.filter((v) => v.$type === 'camunda:TaskListener');
|
|
2705
|
+
return {
|
|
2706
|
+
hasExecutionListener: executionListeners.length > 0,
|
|
2707
|
+
hasTaskListener: taskListeners.length > 0,
|
|
2708
|
+
executionListenerCount: executionListeners.length,
|
|
2709
|
+
taskListenerCount: taskListeners.length,
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2712
|
+
toggleMarkerVisibility() {
|
|
2713
|
+
this.$markersVisible.update(v => !v);
|
|
2714
|
+
if (this.$markersVisible()) {
|
|
2715
|
+
this.updateActivityMarkers();
|
|
2716
|
+
}
|
|
2717
|
+
else {
|
|
2718
|
+
this.clearActivityMarkers();
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
updateActivityMarkers() {
|
|
2722
|
+
this.clearActivityMarkers();
|
|
2723
|
+
if (!this.$markersVisible())
|
|
2724
|
+
return;
|
|
2725
|
+
const modeler = this.activeEditor;
|
|
2726
|
+
if (!modeler)
|
|
2727
|
+
return;
|
|
2728
|
+
const overlays = modeler.get('overlays');
|
|
2729
|
+
const elementRegistry = modeler.get('elementRegistry');
|
|
2730
|
+
const processLinks = this.processManagementEditorService.processLinksForSelectedDefinition;
|
|
2731
|
+
const processLinkActivityIds = new Set(processLinks.map(pl => pl.activityId));
|
|
2732
|
+
const elementMarkers = new Map();
|
|
2733
|
+
elementRegistry.forEach((element) => {
|
|
2734
|
+
if (!element.id || element.type === 'label')
|
|
2735
|
+
return;
|
|
2736
|
+
const listeners = this.getElementListeners(element);
|
|
2737
|
+
const hasProcessLink = processLinkActivityIds.has(element.id);
|
|
2738
|
+
if (listeners.hasExecutionListener || listeners.hasTaskListener || hasProcessLink) {
|
|
2739
|
+
elementMarkers.set(element.id, {
|
|
2740
|
+
hasExecutionListener: listeners.hasExecutionListener,
|
|
2741
|
+
hasTaskListener: listeners.hasTaskListener,
|
|
2742
|
+
hasProcessLink,
|
|
2743
|
+
executionListenerCount: listeners.executionListenerCount,
|
|
2744
|
+
taskListenerCount: listeners.taskListenerCount,
|
|
2745
|
+
});
|
|
2746
|
+
}
|
|
2747
|
+
});
|
|
2748
|
+
for (const [elementId, info] of elementMarkers) {
|
|
2749
|
+
this._activityMarkerElementIds.push(elementId);
|
|
2750
|
+
const badges = this.buildActivityMarkerBadges(info, elementId);
|
|
2751
|
+
if (badges) {
|
|
2752
|
+
try {
|
|
2753
|
+
const element = elementRegistry.get(elementId);
|
|
2754
|
+
const position = this.calculateMarkerPosition(element);
|
|
2755
|
+
overlays.add(elementId, 'activity-marker', {
|
|
2756
|
+
position,
|
|
2757
|
+
html: badges,
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
catch (e) {
|
|
2761
|
+
// Element may not exist on canvas
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
calculateMarkerPosition(element) {
|
|
2767
|
+
if (element?.waypoints?.length > 1) {
|
|
2768
|
+
const waypoints = element.waypoints;
|
|
2769
|
+
const lastPoint = waypoints[waypoints.length - 1];
|
|
2770
|
+
const secondLastPoint = waypoints[waypoints.length - 2];
|
|
2771
|
+
// Compute bounding box from waypoints (same as diagram-js getBBox)
|
|
2772
|
+
const minX = Math.min(...waypoints.map((wp) => wp.x));
|
|
2773
|
+
const minY = Math.min(...waypoints.map((wp) => wp.y));
|
|
2774
|
+
// Direction of the final segment
|
|
2775
|
+
const dx = lastPoint.x - secondLastPoint.x;
|
|
2776
|
+
const dy = lastPoint.y - secondLastPoint.y;
|
|
2777
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
2778
|
+
// Offset back from arrow tip along the line
|
|
2779
|
+
const backOffset = 30;
|
|
2780
|
+
const backX = len > 0 ? (-dx / len) * backOffset : 0;
|
|
2781
|
+
const backY = len > 0 ? (-dy / len) * backOffset : 0;
|
|
2782
|
+
// Perpendicular offset: above for horizontal lines, right for vertical lines
|
|
2783
|
+
const perpOffset = 20;
|
|
2784
|
+
const isMoreHorizontal = Math.abs(dx) > Math.abs(dy);
|
|
2785
|
+
const perpX = isMoreHorizontal ? 0 : perpOffset;
|
|
2786
|
+
const perpY = isMoreHorizontal ? -perpOffset : 0;
|
|
2787
|
+
return {
|
|
2788
|
+
top: lastPoint.y - minY + backY + perpY - 11,
|
|
2789
|
+
left: lastPoint.x - minX + backX + perpX - 11,
|
|
2790
|
+
};
|
|
2791
|
+
}
|
|
2792
|
+
return { top: -12, right: 12 };
|
|
2793
|
+
}
|
|
2794
|
+
buildActivityMarkerBadges(info, elementId) {
|
|
2795
|
+
const container = document.createElement('div');
|
|
2796
|
+
container.className = 'activity-marker-overlay';
|
|
2797
|
+
container.dataset.elementId = elementId;
|
|
2798
|
+
if (info.hasProcessLink) {
|
|
2799
|
+
const tooltip = this.translateService.instant('processManagement.markers.processLink');
|
|
2800
|
+
container.appendChild(this.buildMarkerBadge('process-link', 'P', tooltip));
|
|
2801
|
+
}
|
|
2802
|
+
if (info.hasExecutionListener) {
|
|
2803
|
+
const countSuffix = info.executionListenerCount > 1 ? ` (${info.executionListenerCount})` : '';
|
|
2804
|
+
const tooltip = this.translateService.instant('processManagement.markers.executionListener') + countSuffix;
|
|
2805
|
+
container.appendChild(this.buildMarkerBadge('execution-listener', 'E', tooltip));
|
|
2806
|
+
}
|
|
2807
|
+
if (info.hasTaskListener) {
|
|
2808
|
+
const countSuffix = info.taskListenerCount > 1 ? ` (${info.taskListenerCount})` : '';
|
|
2809
|
+
const tooltip = this.translateService.instant('processManagement.markers.taskListener') + countSuffix;
|
|
2810
|
+
container.appendChild(this.buildMarkerBadge('task-listener', 'T', tooltip));
|
|
2811
|
+
}
|
|
2812
|
+
if (container.children.length === 0)
|
|
2813
|
+
return null;
|
|
2814
|
+
return container;
|
|
2815
|
+
}
|
|
2816
|
+
buildMarkerBadge(type, label, tooltip) {
|
|
2817
|
+
const badge = document.createElement('div');
|
|
2818
|
+
badge.className = `activity-marker-badge activity-marker-badge--${type}`;
|
|
2819
|
+
const icon = document.createElement('span');
|
|
2820
|
+
icon.className = 'activity-marker-badge__icon';
|
|
2821
|
+
icon.textContent = label;
|
|
2822
|
+
badge.appendChild(icon);
|
|
2823
|
+
const text = document.createElement('span');
|
|
2824
|
+
text.className = 'activity-marker-badge__text';
|
|
2825
|
+
text.textContent = tooltip;
|
|
2826
|
+
badge.appendChild(text);
|
|
2827
|
+
return badge;
|
|
2828
|
+
}
|
|
2829
|
+
clearActivityMarkers() {
|
|
2830
|
+
const modeler = this.activeEditor;
|
|
2831
|
+
if (!modeler)
|
|
2832
|
+
return;
|
|
2833
|
+
const overlays = modeler.get('overlays');
|
|
2834
|
+
this._activityMarkerElementIds = [];
|
|
2835
|
+
try {
|
|
2836
|
+
overlays.remove({ type: 'activity-marker' });
|
|
2837
|
+
}
|
|
2838
|
+
catch (e) {
|
|
2839
|
+
// ignore
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
scheduleActivityMarkerUpdate() {
|
|
2843
|
+
if (this._activityMarkerUpdateTimeout) {
|
|
2844
|
+
clearTimeout(this._activityMarkerUpdateTimeout);
|
|
2845
|
+
}
|
|
2846
|
+
this._activityMarkerUpdateTimeout = setTimeout(() => {
|
|
2847
|
+
this.updateActivityMarkers();
|
|
2848
|
+
this._activityMarkerUpdateTimeout = null;
|
|
2849
|
+
}, 300);
|
|
2850
|
+
}
|
|
1664
2851
|
setSelectedProcessDefinitionToLatest(processDefinitions) {
|
|
1665
2852
|
const latest = getLatestProcessDefinition(processDefinitions);
|
|
1666
2853
|
if (!latest)
|
|
@@ -1675,11 +2862,16 @@ class ProcessManagementBuilderComponent {
|
|
|
1675
2862
|
CamundaPlatformPropertiesProviderModule,
|
|
1676
2863
|
camundaPlatformBehaviors,
|
|
1677
2864
|
ValtimoPropertiesProviderModule,
|
|
2865
|
+
ExpressionAutocompleteModule,
|
|
1678
2866
|
],
|
|
1679
2867
|
moddleExtensions: { camunda: CamundaBpmnModdle },
|
|
1680
2868
|
propertiesPanel: { parent: this.modelerPanelElementRef.nativeElement },
|
|
1681
2869
|
});
|
|
1682
2870
|
this._bpmnModeler?.attachTo(this.modelerElementRef.nativeElement);
|
|
2871
|
+
// Initialize expression autocomplete
|
|
2872
|
+
this._expressionAutocomplete = this._bpmnModeler.get('expressionAutocomplete');
|
|
2873
|
+
this._expressionAutocomplete?.setPanelContainer(this.modelerPanelElementRef.nativeElement);
|
|
2874
|
+
this.loadProcessBeansForAutocomplete();
|
|
1683
2875
|
this._bpmnModeler.on('commandStack.changed', () => {
|
|
1684
2876
|
this.changesPending$.next(true);
|
|
1685
2877
|
});
|
|
@@ -1695,6 +2887,17 @@ class ProcessManagementBuilderComponent {
|
|
|
1695
2887
|
});
|
|
1696
2888
|
this.processManagementEditorService.setActivityIdBusinessIdMap(idMap);
|
|
1697
2889
|
this.listenToActivityChangesOnModeler();
|
|
2890
|
+
this.updateActivityMarkers();
|
|
2891
|
+
});
|
|
2892
|
+
}
|
|
2893
|
+
loadProcessBeansForAutocomplete() {
|
|
2894
|
+
this.processBeanService.getProcessBeans().subscribe({
|
|
2895
|
+
next: beans => {
|
|
2896
|
+
this._expressionAutocomplete?.setProcessBeans(beans);
|
|
2897
|
+
},
|
|
2898
|
+
error: err => {
|
|
2899
|
+
this.logger.warn('Failed to load process beans for autocomplete', err);
|
|
2900
|
+
},
|
|
1698
2901
|
});
|
|
1699
2902
|
}
|
|
1700
2903
|
initViewer() {
|
|
@@ -1702,7 +2905,10 @@ class ProcessManagementBuilderComponent {
|
|
|
1702
2905
|
additionalModules: [
|
|
1703
2906
|
DisableBpmnWriteModule,
|
|
1704
2907
|
BpmnPropertiesPanelModule,
|
|
2908
|
+
BpmnPropertiesProviderModule,
|
|
2909
|
+
CamundaPlatformPropertiesProviderModule,
|
|
1705
2910
|
ValtimoPropertiesProviderModule,
|
|
2911
|
+
ReadOnlyPropertiesPanelModule,
|
|
1706
2912
|
],
|
|
1707
2913
|
moddleExtensions: { camunda: CamundaBpmnModdle },
|
|
1708
2914
|
propertiesPanel: { parent: this.viewerPanelElementRef.nativeElement },
|
|
@@ -1713,6 +2919,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1713
2919
|
});
|
|
1714
2920
|
this._bpmnViewer.on('import.done', () => {
|
|
1715
2921
|
disableCommands(this._bpmnViewer);
|
|
2922
|
+
this.updateActivityMarkers();
|
|
1716
2923
|
});
|
|
1717
2924
|
}
|
|
1718
2925
|
reload() {
|
|
@@ -1723,6 +2930,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1723
2930
|
this.processLinkStateService.setModalParams(event?.modalParams);
|
|
1724
2931
|
this.processLinkStateService.setElementName(event?.modalParams?.element?.name ?? '');
|
|
1725
2932
|
this.processLinkStateService.selectProcessLink(event.processLink);
|
|
2933
|
+
this.processLinkStateService.setReadOnly(!this.processManagementEditorService.editingAllowed);
|
|
1726
2934
|
this.processLinkStateService.showModal();
|
|
1727
2935
|
}
|
|
1728
2936
|
handleCreateEvent(event) {
|
|
@@ -1763,6 +2971,7 @@ class ProcessManagementBuilderComponent {
|
|
|
1763
2971
|
this.processManagementEditorService.createProcessLink(event);
|
|
1764
2972
|
this.processLinkStateService.stopSaving();
|
|
1765
2973
|
this.processLinkStateService.closeModal();
|
|
2974
|
+
this.updateActivityMarkers();
|
|
1766
2975
|
const buildingBlockProcessLinkCreateDto = event;
|
|
1767
2976
|
if (buildingBlockProcessLinkCreateDto.buildingBlockDefinitionKey &&
|
|
1768
2977
|
buildingBlockProcessLinkCreateDto.buildingBlockDefinitionVersionTag) {
|
|
@@ -1775,9 +2984,39 @@ class ProcessManagementBuilderComponent {
|
|
|
1775
2984
|
this.processManagementEditorService.deleteProcessLink(event);
|
|
1776
2985
|
this.processLinkStateService.stopSaving();
|
|
1777
2986
|
this.processLinkStateService.closeModal();
|
|
2987
|
+
this.updateActivityMarkers();
|
|
1778
2988
|
this.unsetCalledElementForBuildingBlockProcessLink(event.activityId);
|
|
1779
2989
|
}));
|
|
1780
2990
|
}
|
|
2991
|
+
subscribeToViewerActive() {
|
|
2992
|
+
this._subscriptions.add(this.viewerActive$.subscribe(viewerActive => {
|
|
2993
|
+
this._viewerActive = viewerActive;
|
|
2994
|
+
this.updateActivityMarkers();
|
|
2995
|
+
this.highlightAutofilledElements();
|
|
2996
|
+
}));
|
|
2997
|
+
this._subscriptions.add(this.hasEditPermissions$.subscribe(hasEditPermissions => this.processManagementEditorService.setEditingAllowed(hasEditPermissions)));
|
|
2998
|
+
}
|
|
2999
|
+
subscribeToAutofillDismissEvents() {
|
|
3000
|
+
this._subscriptions.add(this.processManagementEditorService.autofillDismissed$.subscribe(activityId => {
|
|
3001
|
+
this.removeAutofillOverlay(activityId);
|
|
3002
|
+
}));
|
|
3003
|
+
}
|
|
3004
|
+
removeAutofillOverlay(activityId) {
|
|
3005
|
+
const modeler = this.activeEditor;
|
|
3006
|
+
if (!modeler)
|
|
3007
|
+
return;
|
|
3008
|
+
const overlays = modeler.get('overlays');
|
|
3009
|
+
try {
|
|
3010
|
+
overlays.remove({ element: activityId, type: 'autofilled-indicator' });
|
|
3011
|
+
}
|
|
3012
|
+
catch (e) {
|
|
3013
|
+
// ignore
|
|
3014
|
+
}
|
|
3015
|
+
const idx = this._autofilledElementIds.indexOf(activityId);
|
|
3016
|
+
if (idx > -1) {
|
|
3017
|
+
this._autofilledElementIds.splice(idx, 1);
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
1781
3020
|
initIfCreate() {
|
|
1782
3021
|
if (this._selectedProcess$.getValue() !== 'create')
|
|
1783
3022
|
return;
|
|
@@ -1809,12 +3048,17 @@ class ProcessManagementBuilderComponent {
|
|
|
1809
3048
|
.subscribe(result => {
|
|
1810
3049
|
const processDefinitionResult = result;
|
|
1811
3050
|
this.cleanUpListenersOnModeler();
|
|
1812
|
-
this.
|
|
1813
|
-
this.
|
|
1814
|
-
this.
|
|
1815
|
-
this.
|
|
3051
|
+
this._autofilledElements = processDefinitionResult.autofilledElements ?? [];
|
|
3052
|
+
this.processManagementEditorService.setAutofilledElements(this._autofilledElements);
|
|
3053
|
+
this._bpmnModeler?.importXML(processDefinitionResult.bpmn20Xml).then(() => {
|
|
3054
|
+
this.highlightAutofilledElements();
|
|
3055
|
+
});
|
|
3056
|
+
this._bpmnViewer?.importXML(processDefinitionResult.bpmn20Xml).then(() => {
|
|
3057
|
+
this.highlightAutofilledElements();
|
|
3058
|
+
});
|
|
1816
3059
|
this.canInitializeDocument$.next(!!processDefinitionResult?.processCaseLink?.canInitializeDocument);
|
|
1817
3060
|
this.startableByUser$.next(!!processDefinitionResult?.processCaseLink?.startableByUser);
|
|
3061
|
+
this.draft$.next(!!processDefinitionResult?.draft);
|
|
1818
3062
|
this.loading$.next(false);
|
|
1819
3063
|
}));
|
|
1820
3064
|
}
|
|
@@ -1869,8 +3113,8 @@ class ProcessManagementBuilderComponent {
|
|
|
1869
3113
|
.subscribe();
|
|
1870
3114
|
}
|
|
1871
3115
|
setCalledElementForBuildingBlockProcessLink(activityId, buildingBlockDefinitionKey, buildingBlockDefinitionVersionTag) {
|
|
1872
|
-
const
|
|
1873
|
-
if (!
|
|
3116
|
+
const editors = this.loadedEditors;
|
|
3117
|
+
if (!editors.length) {
|
|
1874
3118
|
return;
|
|
1875
3119
|
}
|
|
1876
3120
|
this.processLinkBuildingBlockApiService
|
|
@@ -1878,22 +3122,29 @@ class ProcessManagementBuilderComponent {
|
|
|
1878
3122
|
.subscribe({
|
|
1879
3123
|
next: (mainProcessDefinitionKey) => {
|
|
1880
3124
|
const versionTag = `BB:${buildingBlockDefinitionKey}:${buildingBlockDefinitionVersionTag}`;
|
|
1881
|
-
applyBuildingBlockCalledElement(editor, activityId, mainProcessDefinitionKey, versionTag);
|
|
3125
|
+
editors.forEach(editor => applyBuildingBlockCalledElement(editor, activityId, mainProcessDefinitionKey, versionTag));
|
|
1882
3126
|
},
|
|
1883
3127
|
});
|
|
1884
3128
|
}
|
|
1885
3129
|
unsetCalledElementForBuildingBlockProcessLink(activityId) {
|
|
1886
|
-
|
|
1887
|
-
|
|
3130
|
+
this.loadedEditors.forEach(editor => clearBuildingBlockCalledElement(editor, activityId));
|
|
3131
|
+
}
|
|
3132
|
+
onValidationErrorClick(elementId) {
|
|
3133
|
+
const modeler = this.activeEditor;
|
|
3134
|
+
const canvas = modeler.get('canvas');
|
|
3135
|
+
const selection = modeler.get('selection');
|
|
3136
|
+
const elementRegistry = modeler.get('elementRegistry');
|
|
3137
|
+
const element = elementRegistry.get(elementId);
|
|
3138
|
+
if (!element)
|
|
1888
3139
|
return;
|
|
1889
|
-
}
|
|
1890
|
-
|
|
3140
|
+
canvas.scrollToElement(element, { top: 100, bottom: 100, left: 100, right: 100 });
|
|
3141
|
+
selection.select(element);
|
|
1891
3142
|
}
|
|
1892
3143
|
getValidationErrorMessage(error) {
|
|
1893
3144
|
if (error.errorCode) {
|
|
1894
|
-
const translationKey = `processManagement.
|
|
3145
|
+
const translationKey = `processManagement.validationErrorCodes.${error.errorCode}`;
|
|
1895
3146
|
const translated = this.translateService.instant(translationKey, {
|
|
1896
|
-
expression: error.expression
|
|
3147
|
+
expression: error.expression ?? '',
|
|
1897
3148
|
});
|
|
1898
3149
|
if (translated !== translationKey) {
|
|
1899
3150
|
return translated;
|
|
@@ -1915,13 +3166,13 @@ class ProcessManagementBuilderComponent {
|
|
|
1915
3166
|
container.appendChild(text);
|
|
1916
3167
|
return container;
|
|
1917
3168
|
}
|
|
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
|
|
3169
|
+
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
3170
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: ProcessManagementBuilderComponent, isStandalone: true, selector: "valtimo-process-management-builder", providers: [
|
|
1920
3171
|
ProcessManagementEditorService,
|
|
1921
3172
|
ProcessLinkStateService,
|
|
1922
3173
|
ProcessLinkStepService,
|
|
1923
3174
|
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"] }] }); }
|
|
3175
|
+
], 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 {{\n ($markersVisible()\n ? 'processManagement.markers.hide'\n : 'processManagement.markers.show'\n ) | translate\n }}\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 [attr.data-test-id]=\"testIds.validationErrors\"\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 {{\n ($markersVisible()\n ? 'processManagement.markers.hide'\n : 'processManagement.markers.show'\n ) | translate\n }}\n </span>\n </button>\n </cds-tooltip>\n </div>\n\n <div class=\"bpmn__modeler-panel bpmn__modeler-panel--read-only\" #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 [attr.data-test-id]=\"testIds.versionDropdown\"\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 [attr.data-test-id]=\"testIds.readOnlyTag\"\n >{{ 'processManagement.readOnly' | translate }}</cds-tag\n >\n\n <cds-tag\n *ngIf=\"actionsObs.isSystemProcess\"\n type=\"red\"\n [attr.data-test-id]=\"testIds.systemProcessTag\"\n >{{ 'processManagement.systemProcess' | translate }}</cds-tag\n >\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\n overflowTrigger\n [attr.data-test-id]=\"testIds.moreButton\"\n ></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 || !actionsObs.hasEditPermissions\"\n [attr.data-test-id]=\"testIds.validateButton\"\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 || !actionsObs.hasEditPermissions\"\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__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry input,.bpmn__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry select,.bpmn__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry textarea,.bpmn__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry .bio-properties-panel-feel-editor-container{opacity:.65}.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
3176
|
}
|
|
1926
3177
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementBuilderComponent, decorators: [{
|
|
1927
3178
|
type: Component,
|
|
@@ -1938,20 +3189,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
1938
3189
|
TranslateModule,
|
|
1939
3190
|
TagModule,
|
|
1940
3191
|
ProcessLinkModule,
|
|
1941
|
-
ProcessLinkModule,
|
|
1942
|
-
OverflowMenuComponent,
|
|
1943
|
-
OverflowMenuOptionComponent,
|
|
1944
|
-
OverflowMenuTriggerComponent,
|
|
1945
3192
|
ToggleModule,
|
|
1946
3193
|
TooltipModule,
|
|
1947
3194
|
ConfirmationModalModule,
|
|
3195
|
+
OverflowMenuModule,
|
|
1948
3196
|
], providers: [
|
|
1949
3197
|
ProcessManagementEditorService,
|
|
1950
3198
|
ProcessLinkStateService,
|
|
1951
3199
|
ProcessLinkStepService,
|
|
1952
3200
|
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
|
|
3201
|
+
], 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 {{\n ($markersVisible()\n ? 'processManagement.markers.hide'\n : 'processManagement.markers.show'\n ) | translate\n }}\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 [attr.data-test-id]=\"testIds.validationErrors\"\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 {{\n ($markersVisible()\n ? 'processManagement.markers.hide'\n : 'processManagement.markers.show'\n ) | translate\n }}\n </span>\n </button>\n </cds-tooltip>\n </div>\n\n <div class=\"bpmn__modeler-panel bpmn__modeler-panel--read-only\" #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 [attr.data-test-id]=\"testIds.versionDropdown\"\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 [attr.data-test-id]=\"testIds.readOnlyTag\"\n >{{ 'processManagement.readOnly' | translate }}</cds-tag\n >\n\n <cds-tag\n *ngIf=\"actionsObs.isSystemProcess\"\n type=\"red\"\n [attr.data-test-id]=\"testIds.systemProcessTag\"\n >{{ 'processManagement.systemProcess' | translate }}</cds-tag\n >\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\n overflowTrigger\n [attr.data-test-id]=\"testIds.moreButton\"\n ></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 || !actionsObs.hasEditPermissions\"\n [attr.data-test-id]=\"testIds.validateButton\"\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 || !actionsObs.hasEditPermissions\"\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__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry input,.bpmn__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry select,.bpmn__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry textarea,.bpmn__modeler-panel--read-only ::ng-deep .bio-properties-panel-entry .bio-properties-panel-feel-editor-container{opacity:.65}.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"] }]
|
|
3202
|
+
}], 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
3203
|
type: ViewChild,
|
|
1956
3204
|
args: ['modeler', { static: false }]
|
|
1957
3205
|
}], modelerPanelElementRef: [{
|
|
@@ -2070,7 +3318,7 @@ class ProcessManagementListComponent {
|
|
|
2070
3318
|
this.processToDelete$.next(process.processDefinition);
|
|
2071
3319
|
this.showDeleteModal$.next(true);
|
|
2072
3320
|
}
|
|
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
|
|
3321
|
+
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
3322
|
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
3323
|
}
|
|
2076
3324
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementListComponent, decorators: [{
|
|
@@ -2084,7 +3332,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2084
3332
|
TranslateModule,
|
|
2085
3333
|
ConfirmationModalModule,
|
|
2086
3334
|
], 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
|
|
3335
|
+
}], 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
3336
|
type: Output
|
|
2089
3337
|
}] } });
|
|
2090
3338
|
|
|
@@ -2103,45 +3351,206 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2103
3351
|
* See the License for the specific language governing permissions and
|
|
2104
3352
|
* limitations under the License.
|
|
2105
3353
|
*/
|
|
3354
|
+
var UPLOAD_STEP;
|
|
3355
|
+
(function (UPLOAD_STEP) {
|
|
3356
|
+
UPLOAD_STEP["FILE_SELECT"] = "fileSelect";
|
|
3357
|
+
UPLOAD_STEP["REVIEW"] = "review";
|
|
3358
|
+
UPLOAD_STEP["SUMMARY"] = "summary";
|
|
3359
|
+
})(UPLOAD_STEP || (UPLOAD_STEP = {}));
|
|
2106
3360
|
class ProcessManagementUploadComponent {
|
|
2107
|
-
constructor(formBuilder, notificationService, processManagementService, processManagementStateService, processLinkService, translateService) {
|
|
3361
|
+
constructor(formBuilder, notificationService, processManagementService, processManagementStateService, processLinkService, translateService, changeDetectorRef) {
|
|
2108
3362
|
this.formBuilder = formBuilder;
|
|
2109
3363
|
this.notificationService = notificationService;
|
|
2110
3364
|
this.processManagementService = processManagementService;
|
|
2111
3365
|
this.processManagementStateService = processManagementStateService;
|
|
2112
3366
|
this.processLinkService = processLinkService;
|
|
2113
3367
|
this.translateService = translateService;
|
|
3368
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
2114
3369
|
this.modalOpen$ = this.processManagementStateService.openModal$;
|
|
2115
3370
|
this.showReplaceConfirmationModal$ = new BehaviorSubject(false);
|
|
2116
3371
|
this.replaceModalContent = '';
|
|
2117
3372
|
this._conflictingProcessDefinitionId = null;
|
|
2118
|
-
|
|
3373
|
+
// Extensions need a leading dot: the file dialog only filters on valid accept tokens, and Carbon
|
|
3374
|
+
// matches a dropped file on its dot-prefixed extension
|
|
3375
|
+
this.ACCEPTED_FILES = ['.bpmn', '.zip'];
|
|
3376
|
+
this.UPLOAD_STEP = UPLOAD_STEP;
|
|
3377
|
+
this.testIds = PROCESS_MANAGEMENT_UPLOAD_TEST_IDS;
|
|
2119
3378
|
this.form = this.formBuilder.group({
|
|
2120
3379
|
file: this.formBuilder.control(new Set(), [Validators.required]),
|
|
2121
3380
|
});
|
|
2122
|
-
|
|
3381
|
+
// The current control value is read instead of the emitted one, so this also reports the selection
|
|
3382
|
+
// correctly when the footer is re-created after going back to the file select step
|
|
3383
|
+
this.fileSelected$ = this.form.get('file')?.valueChanges.pipe(startWith(null), map$1(() => {
|
|
3384
|
+
const value = this.form.get('file')?.value;
|
|
3385
|
+
return !!(value instanceof Set && value.size > 0);
|
|
3386
|
+
}));
|
|
3387
|
+
this.activeStep$ = new BehaviorSubject(UPLOAD_STEP.FILE_SELECT);
|
|
3388
|
+
this.preview$ = new BehaviorSubject(null);
|
|
3389
|
+
this.missingReferences$ = new BehaviorSubject([]);
|
|
3390
|
+
this.importing$ = new BehaviorSubject(false);
|
|
3391
|
+
/**
|
|
3392
|
+
* Leaving the file select step destroys cds-file-uploader, which empties the form control: every
|
|
3393
|
+
* cds-file emits (remove) from its own ngOnDestroy. So the selection is kept here to import it
|
|
3394
|
+
* afterwards, and to restore it when the user goes back.
|
|
3395
|
+
*/
|
|
3396
|
+
this._selectedFile = null;
|
|
3397
|
+
this._selectedFileItems = null;
|
|
2123
3398
|
}
|
|
2124
3399
|
closeModal() {
|
|
2125
3400
|
this.processManagementStateService.closeModal();
|
|
2126
3401
|
setTimeout(() => {
|
|
2127
3402
|
this.form.reset();
|
|
3403
|
+
this.activeStep$.next(UPLOAD_STEP.FILE_SELECT);
|
|
3404
|
+
this.preview$.next(null);
|
|
3405
|
+
this.missingReferences$.next([]);
|
|
3406
|
+
this.importing$.next(false);
|
|
3407
|
+
this._selectedFile = null;
|
|
3408
|
+
this._selectedFileItems = null;
|
|
2128
3409
|
}, CARBON_CONSTANTS.modalAnimationMs);
|
|
2129
3410
|
}
|
|
2130
3411
|
uploadProcessBpmn() {
|
|
2131
|
-
const
|
|
2132
|
-
if (!
|
|
3412
|
+
const file = this.form.value?.file?.values()?.next()?.value?.file;
|
|
3413
|
+
if (!file)
|
|
2133
3414
|
return;
|
|
3415
|
+
// A package of an earlier selection must not be imported when another file is uploaded
|
|
3416
|
+
this._selectedFile = null;
|
|
3417
|
+
this._selectedFileItems = null;
|
|
3418
|
+
if (this.isZip(file)) {
|
|
3419
|
+
this.previewProcessPackage(file);
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
2134
3422
|
if (this.processManagementService.$context() === 'case') {
|
|
2135
|
-
this.uploadForCase(
|
|
3423
|
+
this.uploadForCase(file);
|
|
2136
3424
|
}
|
|
2137
3425
|
else {
|
|
2138
|
-
this.uploadIndependent(
|
|
3426
|
+
this.uploadIndependent(file);
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
importProcessPackage() {
|
|
3430
|
+
const existingProcessDefinitionKeys = this.preview$.value?.existingProcessDefinitionKeys ?? [];
|
|
3431
|
+
// Ask before replacing, the same way uploading a single bpmn file does
|
|
3432
|
+
if (existingProcessDefinitionKeys.length > 0) {
|
|
3433
|
+
this.showReplaceConfirmation(this.translateService.instant('processManagement.upload.replaceContentWithDuplicates', {
|
|
3434
|
+
duplicates: existingProcessDefinitionKeys.join(', '),
|
|
3435
|
+
}));
|
|
3436
|
+
return;
|
|
3437
|
+
}
|
|
3438
|
+
this.executeImportProcessPackage();
|
|
3439
|
+
}
|
|
3440
|
+
showReplaceConfirmation(content) {
|
|
3441
|
+
this.replaceModalContent = content;
|
|
3442
|
+
// The content is bound from a plain field, so this OnPush component has to be checked again.
|
|
3443
|
+
// The bpmn flow sets it from an http error callback, which does not mark this view dirty itself.
|
|
3444
|
+
this.changeDetectorRef.markForCheck();
|
|
3445
|
+
this.showReplaceConfirmationModal$.next(true);
|
|
3446
|
+
}
|
|
3447
|
+
executeImportProcessPackage() {
|
|
3448
|
+
const file = this._selectedFile;
|
|
3449
|
+
if (!file)
|
|
3450
|
+
return;
|
|
3451
|
+
this.importing$.next(true);
|
|
3452
|
+
this.processManagementService
|
|
3453
|
+
.importProcessDefinition(this.toFormData(file), this._pluginConfigurationMapping?.getMappings())
|
|
3454
|
+
.pipe(take(1))
|
|
3455
|
+
.subscribe({
|
|
3456
|
+
next: result => {
|
|
3457
|
+
this.importing$.next(false);
|
|
3458
|
+
this.processManagementStateService.reloadDefinitions();
|
|
3459
|
+
if (result.missingReferences.length > 0) {
|
|
3460
|
+
// Keep the summary on screen: a toast disappears before it can be read
|
|
3461
|
+
this.missingReferences$.next(result.missingReferences);
|
|
3462
|
+
this.activeStep$.next(UPLOAD_STEP.SUMMARY);
|
|
3463
|
+
return;
|
|
3464
|
+
}
|
|
3465
|
+
this.notificationService.showNotification({
|
|
3466
|
+
type: 'success',
|
|
3467
|
+
title: this.translateService.instant('processManagement.upload.success'),
|
|
3468
|
+
});
|
|
3469
|
+
this.closeModal();
|
|
3470
|
+
},
|
|
3471
|
+
error: () => {
|
|
3472
|
+
this.importing$.next(false);
|
|
3473
|
+
this.notificationService.showNotification({
|
|
3474
|
+
type: 'error',
|
|
3475
|
+
title: this.translateService.instant('processManagement.upload.failure'),
|
|
3476
|
+
});
|
|
3477
|
+
},
|
|
3478
|
+
});
|
|
3479
|
+
}
|
|
3480
|
+
onBackClick() {
|
|
3481
|
+
this.activeStep$.next(UPLOAD_STEP.FILE_SELECT);
|
|
3482
|
+
// Restore the selection the file uploader dropped when it was destroyed
|
|
3483
|
+
if (this._selectedFileItems) {
|
|
3484
|
+
this.form.get('file')?.setValue(this._selectedFileItems);
|
|
2139
3485
|
}
|
|
2140
3486
|
}
|
|
3487
|
+
getMissingReferenceGroups(missingReferences) {
|
|
3488
|
+
return missingReferences.reduce((groups, missingReference) => {
|
|
3489
|
+
const group = groups.find(({ type }) => type === missingReference.type);
|
|
3490
|
+
if (group) {
|
|
3491
|
+
group.references = [...new Set([...group.references, missingReference.reference])];
|
|
3492
|
+
return groups;
|
|
3493
|
+
}
|
|
3494
|
+
return [...groups, { type: missingReference.type, references: [missingReference.reference] }];
|
|
3495
|
+
}, []);
|
|
3496
|
+
}
|
|
3497
|
+
getReplacedElementGroups(elementsToReplace) {
|
|
3498
|
+
return (elementsToReplace ?? []).reduce((groups, element) => {
|
|
3499
|
+
const group = groups.find(({ type }) => type === element.type);
|
|
3500
|
+
if (group) {
|
|
3501
|
+
group.keys = [...new Set([...group.keys, element.key])];
|
|
3502
|
+
return groups;
|
|
3503
|
+
}
|
|
3504
|
+
return [...groups, { type: element.type, keys: [element.key] }];
|
|
3505
|
+
}, []);
|
|
3506
|
+
}
|
|
3507
|
+
previewProcessPackage(file) {
|
|
3508
|
+
const fileItem = this.form.value?.file?.values()?.next()?.value;
|
|
3509
|
+
this.processManagementService
|
|
3510
|
+
.previewProcessDefinitionImport(this.toFormData(file))
|
|
3511
|
+
.pipe(take(1))
|
|
3512
|
+
.subscribe({
|
|
3513
|
+
next: preview => {
|
|
3514
|
+
this._selectedFile = file;
|
|
3515
|
+
this._selectedFileItems = this.form.value?.file ?? null;
|
|
3516
|
+
this.preview$.next(preview);
|
|
3517
|
+
this.missingReferences$.next(preview.missingReferences);
|
|
3518
|
+
// Nothing to review, so the package can be imported straight away. Elements that will be
|
|
3519
|
+
// replaced are shown in the review step first, so the replacement is a conscious choice.
|
|
3520
|
+
if (preview.pluginConfigurations.length === 0 &&
|
|
3521
|
+
preview.missingReferences.length === 0 &&
|
|
3522
|
+
preview.elementsToReplace.length === 0) {
|
|
3523
|
+
this.importProcessPackage();
|
|
3524
|
+
return;
|
|
3525
|
+
}
|
|
3526
|
+
this.activeStep$.next(UPLOAD_STEP.REVIEW);
|
|
3527
|
+
},
|
|
3528
|
+
error: () => {
|
|
3529
|
+
if (fileItem) {
|
|
3530
|
+
fileItem.invalid = true;
|
|
3531
|
+
fileItem.invalidTitle = this.translateService.instant('processManagement.upload.invalidZip.title');
|
|
3532
|
+
fileItem.invalidText = this.translateService.instant('processManagement.upload.invalidZip.text');
|
|
3533
|
+
}
|
|
3534
|
+
},
|
|
3535
|
+
});
|
|
3536
|
+
}
|
|
3537
|
+
isZip(file) {
|
|
3538
|
+
return file.name.toLowerCase().endsWith('.zip');
|
|
3539
|
+
}
|
|
3540
|
+
toFormData(file) {
|
|
3541
|
+
const formData = new FormData();
|
|
3542
|
+
formData.append('file', file, file.name);
|
|
3543
|
+
return formData;
|
|
3544
|
+
}
|
|
2141
3545
|
confirmReplace() {
|
|
2142
3546
|
const processDefinitionId = this._conflictingProcessDefinitionId;
|
|
2143
3547
|
this.replaceModalContent = '';
|
|
2144
3548
|
this._conflictingProcessDefinitionId = null;
|
|
3549
|
+
// A selected package is only set while importing a zip, which replaces through the import itself
|
|
3550
|
+
if (this._selectedFile) {
|
|
3551
|
+
this.executeImportProcessPackage();
|
|
3552
|
+
return;
|
|
3553
|
+
}
|
|
2145
3554
|
if (!processDefinitionId) {
|
|
2146
3555
|
this.notificationService.showNotification({
|
|
2147
3556
|
type: 'error',
|
|
@@ -2192,11 +3601,9 @@ class ProcessManagementUploadComponent {
|
|
|
2192
3601
|
error: (error) => {
|
|
2193
3602
|
const isConflict = error instanceof HttpErrorResponse && error.status === 409;
|
|
2194
3603
|
if (isConflict) {
|
|
2195
|
-
const body = error
|
|
2196
|
-
.error;
|
|
3604
|
+
const body = error.error;
|
|
2197
3605
|
this._conflictingProcessDefinitionId = body?.processDefinitionId ?? null;
|
|
2198
|
-
this.
|
|
2199
|
-
this.showReplaceConfirmationModal$.next(true);
|
|
3606
|
+
this.showReplaceConfirmation(this.buildReplaceModalContent(body));
|
|
2200
3607
|
return;
|
|
2201
3608
|
}
|
|
2202
3609
|
this.notificationService.showNotification({
|
|
@@ -2221,11 +3628,9 @@ class ProcessManagementUploadComponent {
|
|
|
2221
3628
|
error: (error) => {
|
|
2222
3629
|
const isConflict = error instanceof HttpErrorResponse && error.status === 409;
|
|
2223
3630
|
if (isConflict) {
|
|
2224
|
-
const body = error
|
|
2225
|
-
.error;
|
|
3631
|
+
const body = error.error;
|
|
2226
3632
|
this._conflictingProcessDefinitionId = body?.processDefinitionId ?? null;
|
|
2227
|
-
this.
|
|
2228
|
-
this.showReplaceConfirmationModal$.next(true);
|
|
3633
|
+
this.showReplaceConfirmation(this.buildReplaceModalContent(body));
|
|
2229
3634
|
return;
|
|
2230
3635
|
}
|
|
2231
3636
|
this.notificationService.showNotification({
|
|
@@ -2244,8 +3649,8 @@ class ProcessManagementUploadComponent {
|
|
|
2244
3649
|
}
|
|
2245
3650
|
return this.translateService.instant('processManagement.upload.replaceContent');
|
|
2246
3651
|
}
|
|
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 }); }
|
|
3652
|
+
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 }); }
|
|
3653
|
+
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 [attr.data-test-id]=\"testIds.fileUploader\"\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\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.cancelButton\"\n (click)=\"closeModal()\"\n >\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"(fileSelected$ | async) === false || obs.importing\"\n [attr.data-test-id]=\"testIds.submitButton\"\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\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.backButton\"\n (click)=\"onBackClick()\"\n >\n {{ 'interface.back' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.preview?.canImport === false || obs.importing\"\n [attr.data-test-id]=\"testIds.importButton\"\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 [attr.data-test-id]=\"testIds.closeButton\"\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
3654
|
}
|
|
2250
3655
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: ProcessManagementUploadComponent, decorators: [{
|
|
2251
3656
|
type: Component,
|
|
@@ -2260,8 +3665,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2260
3665
|
ConfirmationModalModule,
|
|
2261
3666
|
RenderInBodyComponent,
|
|
2262
3667
|
ValtimoCdsModalDirective,
|
|
2263
|
-
|
|
2264
|
-
|
|
3668
|
+
NotificationModule,
|
|
3669
|
+
PluginConfigurationMappingComponent,
|
|
3670
|
+
], 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 [attr.data-test-id]=\"testIds.fileUploader\"\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\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.cancelButton\"\n (click)=\"closeModal()\"\n >\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"(fileSelected$ | async) === false || obs.importing\"\n [attr.data-test-id]=\"testIds.submitButton\"\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\n cdsButton=\"secondary\"\n [attr.data-test-id]=\"testIds.backButton\"\n (click)=\"onBackClick()\"\n >\n {{ 'interface.back' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"obs.preview?.canImport === false || obs.importing\"\n [attr.data-test-id]=\"testIds.importButton\"\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 [attr.data-test-id]=\"testIds.closeButton\"\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"] }]
|
|
3671
|
+
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: i2.GlobalNotificationService }, { type: ProcessManagementService }, { type: ProcessManagementStateService }, { type: i5.ProcessLinkService }, { type: i9.TranslateService }, { type: i0.ChangeDetectorRef }], propDecorators: { _pluginConfigurationMapping: [{
|
|
3672
|
+
type: ViewChild,
|
|
3673
|
+
args: [PluginConfigurationMappingComponent]
|
|
3674
|
+
}] } });
|
|
2265
3675
|
|
|
2266
3676
|
/*
|
|
2267
3677
|
* Copyright 2015-2025 Ritense BV, the Netherlands.
|
|
@@ -2512,5 +3922,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
2512
3922
|
* Generated bundle index. Do not edit.
|
|
2513
3923
|
*/
|
|
2514
3924
|
|
|
2515
|
-
export { PROCESS_MANAGEMENT_BUILDER_TEST_IDS, PROCESS_MANAGEMENT_ENDPOINTS, PROCESS_MANAGEMENT_LIST_TEST_IDS, ProcessManagementBuilderComponent, ProcessManagementComponent, ProcessManagementModule, ProcessManagementStateService };
|
|
3925
|
+
export { PROCESS_LINK_PANEL_TEST_IDS, PROCESS_MANAGEMENT_BUILDER_TEST_IDS, PROCESS_MANAGEMENT_ENDPOINTS, PROCESS_MANAGEMENT_LIST_TEST_IDS, PROCESS_MANAGEMENT_UPLOAD_TEST_IDS, ProcessManagementBuilderComponent, ProcessManagementComponent, ProcessManagementModule, ProcessManagementStateService };
|
|
2516
3926
|
//# sourceMappingURL=valtimo-process-management.mjs.map
|