@valtimo/process-management 13.34.0 → 13.36.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.
@@ -1,19 +1,20 @@
1
1
  import * as i6 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { Injectable, signal, computed, ViewChild, Component, EventEmitter, Output, ChangeDetectionStrategy, NgModule } from '@angular/core';
4
+ import { Injectable, signal, ViewChild, Component, EventEmitter, Output, ChangeDetectionStrategy, NgModule } from '@angular/core';
5
5
  import * as i1$2 from '@angular/forms';
6
6
  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, OverflowMenuComponent, OverflowMenuOptionComponent, OverflowMenuTriggerComponent, ViewType, CarbonListModule, ConfirmationModalModule, CARBON_CONSTANTS, RenderInBodyComponent, WidgetModule } from '@valtimo/components';
10
+ import { FitPageDirective, RenderInPageHeaderDirective, OverflowMenuComponent, OverflowMenuOptionComponent, OverflowMenuTriggerComponent, ConfirmationModalModule, ViewType, CarbonListModule, CARBON_CONSTANTS, RenderInBodyComponent, 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
16
  import { HttpErrorResponse } from '@angular/common/http';
17
+ import { Deploy16, ListChecked16, Return16, Upload16 } from '@carbon/icons';
17
18
  import * as i2$1 from '@valtimo/shared';
18
19
  import { BaseApiService, getCaseManagementRouteParams, getBuildingBlockManagementRouteParams, ROLE_ADMIN } from '@valtimo/shared';
19
20
  import { useService, BpmnPropertiesPanelModule, BpmnPropertiesProviderModule, CamundaPlatformPropertiesProviderModule } from 'bpmn-js-properties-panel';
@@ -32,7 +33,6 @@ import * as i7 from '@valtimo/process';
32
33
  import * as i8 from '@angular/router';
33
34
  import { RouterModule } from '@angular/router';
34
35
  import * as i10 from '@valtimo/plugin';
35
- import { Upload16 } from '@carbon/icons';
36
36
  import { AuthGuardService } from '@valtimo/security';
37
37
 
38
38
  /*
@@ -86,6 +86,7 @@ const PROCESS_MANAGEMENT_LIST_TEST_IDS = {
86
86
  createProcessButton: 'processManagementCreateProcessButton',
87
87
  };
88
88
  const PROCESS_MANAGEMENT_BUILDER_TEST_IDS = {
89
+ draftToggle: 'processManagementBuilderDraftToggle',
89
90
  startsCaseToggle: 'processManagementBuilderStartsCaseToggle',
90
91
  startableByUserToggle: 'processManagementBuilderStartableByUserToggle',
91
92
  deployButton: 'processManagementBuilderDeployButton',
@@ -147,6 +148,12 @@ class ProcessManagementEditorService {
147
148
  get formDefinitionOptions() {
148
149
  return this._formDefinitionOptions$.getValue();
149
150
  }
151
+ get validationErrors() {
152
+ return this._validationErrors$.getValue();
153
+ }
154
+ setValidationErrors(errors) {
155
+ this._validationErrors$.next(errors);
156
+ }
150
157
  constructor(processLinkService, formService) {
151
158
  this.processLinkService = processLinkService;
152
159
  this.formService = formService;
@@ -156,6 +163,8 @@ class ProcessManagementEditorService {
156
163
  this._deleteProcessLinkEvents$ = new Subject();
157
164
  this._managementRouteParams$ = new BehaviorSubject(null);
158
165
  this._formDefinitionOptions$ = new BehaviorSubject([]);
166
+ this._validationErrors$ = new BehaviorSubject([]);
167
+ this.validationErrors$ = this._validationErrors$.asObservable();
159
168
  this._updatingBpmnView = false;
160
169
  this._activityIdBusinessIdMap = {};
161
170
  this._subscriptions = new Subscription();
@@ -466,6 +475,9 @@ class ProcessManagementService extends BaseApiService {
466
475
  updateProcessDefinitionCaseDefinitionProperties(caseDefinitionKey, caseDefinitionVersionTag, processDefinitionId, body) {
467
476
  return this.httpClient.put(this.getApiUrl(`/management/v1/case-definition/${caseDefinitionKey}/version/${caseDefinitionVersionTag}/process/${processDefinitionId}/properties`), body);
468
477
  }
478
+ validateProcessDefinition(request) {
479
+ return this.httpClient.post(this.getApiUrl('/management/v1/process-definition/validate'), request);
480
+ }
469
481
  getProcesses(definitionName, versionTag) {
470
482
  return this.httpClient.get(this.getApiUrl(`${PROCESS_MANAGEMENT_ENDPOINTS[this._$context()]}/${definitionName}/version/${versionTag}/process-definition`));
471
483
  }
@@ -761,7 +773,28 @@ class ValtimoPropertiesProvider {
761
773
  }
762
774
  getGroups(element) {
763
775
  const processLink = this.processManagementEditorService.processLinksForSelectedDefinition.find(processLink => processLink.activityId === element.id) || null;
776
+ const elementErrors = this.processManagementEditorService.validationErrors.filter(error => error.elementId === element.id);
764
777
  return (groups) => {
778
+ const generalGroup = groups.find((g) => g.id === 'general');
779
+ if (generalGroup) {
780
+ generalGroup.entries = generalGroup.entries.filter((entry) => entry.id !== 'isExecutable');
781
+ }
782
+ if (elementErrors.length > 0) {
783
+ const errorGroup = {
784
+ id: 'validationErrorsGroup',
785
+ label: this.translateService.instant('processManagement.validationErrors'),
786
+ entries: [
787
+ {
788
+ id: 'validationErrorsEntry',
789
+ errors: elementErrors,
790
+ translateService: this.translateService,
791
+ component: ValidationErrorsElement,
792
+ },
793
+ ],
794
+ shouldOpen: true,
795
+ };
796
+ groups.unshift(errorGroup);
797
+ }
765
798
  if (is(element, 'bpmn:UserTask') ||
766
799
  is(element, 'bpmn:StartEvent') ||
767
800
  is(element, 'bpmn:ServiceTask') ||
@@ -1035,6 +1068,24 @@ const CustomRootElement = (props) => {
1035
1068
  </div>`;
1036
1069
  return processLink ? genericLinkedPanel : genericCreatePanel;
1037
1070
  };
1071
+ const ValidationErrorsElement = (props) => {
1072
+ const getErrorMessage = (error) => {
1073
+ if (error.errorCode) {
1074
+ const translationKey = `processManagement.expressionErrors.${error.errorCode}`;
1075
+ const translated = props.translateService.instant(translationKey);
1076
+ if (translated !== translationKey) {
1077
+ return error.expression ? `${translated}: '${error.expression}'` : translated;
1078
+ }
1079
+ }
1080
+ return error.reason;
1081
+ };
1082
+ return html `<div class="validation-errors-panel">
1083
+ ${props.errors.map(error => html `<div class="validation-errors-panel__item${error.severity === 'WARNING' ? ' warning' : ''}">
1084
+ <span class="validation-errors-panel__icon${error.severity === 'WARNING' ? ' warning' : ''}">!</span>
1085
+ <span class="validation-errors-panel__reason${error.severity === 'WARNING' ? ' warning' : ''}">${getErrorMessage(error)}</span>
1086
+ </div>`)}
1087
+ </div>`;
1088
+ };
1038
1089
  const ValtimoPropertiesProviderModule = {
1039
1090
  __init__: ['customPropertiesProvider'],
1040
1091
  customPropertiesProvider: ['type', ValtimoPropertiesProvider],
@@ -1057,7 +1108,7 @@ const ValtimoPropertiesProviderModule = {
1057
1108
  */
1058
1109
 
1059
1110
  /*
1060
- * Copyright 2015-2025 Ritense BV, the Netherlands.
1111
+ * Copyright 2015-2026 Ritense BV, the Netherlands.
1061
1112
  *
1062
1113
  * Licensed under EUPL, Version 1.2 (the "License");
1063
1114
  * you may not use this file except in compliance with the License.
@@ -1093,10 +1144,15 @@ class ProcessManagementBuilderComponent {
1093
1144
  this.processLinkBuildingBlockApiService = processLinkBuildingBlockApiService;
1094
1145
  this._selectedProcess$ = new BehaviorSubject(null);
1095
1146
  this.loading$ = new BehaviorSubject(true);
1147
+ this._validationErrorElementIds = [];
1148
+ this._validationHoverHandler = null;
1149
+ this._validationOutHandler = null;
1096
1150
  this.isReadOnlyProcess$ = new BehaviorSubject(false);
1097
1151
  this.isSystemProcess$ = new BehaviorSubject(false);
1152
+ this.draft$ = new BehaviorSubject(false);
1098
1153
  this.canInitializeDocument$ = new BehaviorSubject(false);
1099
1154
  this.startableByUser$ = new BehaviorSubject(false);
1155
+ this.validationErrors$ = this.processManagementEditorService.validationErrors$;
1100
1156
  this.testIds = PROCESS_MANAGEMENT_BUILDER_TEST_IDS;
1101
1157
  this.selectedProcessDefinitionXml$ = this.processManagementEditorService.selectionProcessDefinition$.pipe(filter(selectedProcessDefinition => !!selectedProcessDefinition?.id), distinctUntilChanged((previous, current) => isEqual(previous, current)), tap(selectedProcessDefinition => {
1102
1158
  this.loading$.next(true);
@@ -1105,6 +1161,7 @@ class ProcessManagementBuilderComponent {
1105
1161
  this.cleanUpListenersOnModeler();
1106
1162
  this._bpmnModeler?.importXML(result.bpmn20Xml);
1107
1163
  this._bpmnViewer?.importXML(result.bpmn20Xml);
1164
+ this.draft$.next(this.parseDraftFromXml(result.bpmn20Xml));
1108
1165
  this.isReadOnlyProcess$.next(result.readOnly);
1109
1166
  this.isSystemProcess$.next(result.systemProcess);
1110
1167
  this.loading$.next(false);
@@ -1150,8 +1207,9 @@ class ProcessManagementBuilderComponent {
1150
1207
  .sort((a, b) => b.id - a.id)));
1151
1208
  this.compactMode$ = this.pageHeaderService.compactMode$;
1152
1209
  this.creatingNewProcess$ = new BehaviorSubject(false);
1153
- this.$spaceAdjustment = computed(() => this.processManagementService.$context() === 'case' ? 0 : 0);
1154
1210
  this.updatingProcessDefinitionCaseDefinition$ = new BehaviorSubject(false);
1211
+ this.showWarningConfirmationModal$ = new BehaviorSubject(false);
1212
+ this._pendingDeployAction = null;
1155
1213
  this._subscriptions = new Subscription();
1156
1214
  this.shapeAddedHandler = (event) => {
1157
1215
  this.logger.debug('Shape added:', event);
@@ -1171,10 +1229,12 @@ class ProcessManagementBuilderComponent {
1171
1229
  return;
1172
1230
  this.processManagementEditorService.updateProcessLinksOnIdChange(activityId, businessId);
1173
1231
  };
1232
+ this.iconService.registerAll([Deploy16, ListChecked16, Return16]);
1174
1233
  this.setProcessManagementWindow();
1175
1234
  }
1176
1235
  ngAfterViewInit() {
1177
1236
  this.pageTitleService.disableReset();
1237
+ this.pageHeaderService.enableTitleAsBreadcrumb();
1178
1238
  this.openParamsAndContextSubscription();
1179
1239
  this.initModeler();
1180
1240
  this.initViewer();
@@ -1185,10 +1245,12 @@ class ProcessManagementBuilderComponent {
1185
1245
  this.initEditing();
1186
1246
  }
1187
1247
  ngOnDestroy() {
1248
+ this.clearValidationErrors();
1188
1249
  this._bpmnModeler?.destroy();
1189
1250
  this._bpmnViewer?.destroy();
1190
1251
  this._subscriptions.unsubscribe();
1191
1252
  this.pageTitleService.enableReset();
1253
+ this.pageHeaderService.disableTitleAsBreadcrumb();
1192
1254
  this.pageTitleService.clearPageActionsViewContainerRef();
1193
1255
  this.breadcrumbService.clearThirdBreadcrumb();
1194
1256
  this.breadcrumbService.clearFourthBreadcrumb();
@@ -1206,7 +1268,37 @@ class ProcessManagementBuilderComponent {
1206
1268
  link.remove();
1207
1269
  });
1208
1270
  }
1271
+ validateProcessDefinition(isReadOnlyProcess) {
1272
+ combineLatest([
1273
+ from(isReadOnlyProcess ? this._bpmnViewer.saveXML() : this._bpmnModeler.saveXML()),
1274
+ this.processManagementEditorService.processLinksForSelectedDefinition$,
1275
+ ])
1276
+ .pipe(take(1), switchMap(([result, processLinks]) => {
1277
+ const xml = this.applyDraftState(result?.xml ?? '') ?? '';
1278
+ return this.processManagementService.validateProcessDefinition({
1279
+ bpmnXml: xml,
1280
+ processLinks: processLinks.map(link => ({
1281
+ ...link,
1282
+ processDefinitionId: '-',
1283
+ })),
1284
+ });
1285
+ }))
1286
+ .subscribe({
1287
+ next: validationResult => {
1288
+ this.highlightValidationErrors(validationResult.errors);
1289
+ if (validationResult.isValid && !validationResult.hasWarnings) {
1290
+ this.showNotification('validationSuccess');
1291
+ }
1292
+ },
1293
+ error: () => {
1294
+ this.showNotification('error');
1295
+ },
1296
+ });
1297
+ }
1209
1298
  deployChanges(isReadOnlyProcess) {
1299
+ this.validateAndDeploy(isReadOnlyProcess, () => this.executeDeployChanges(isReadOnlyProcess));
1300
+ }
1301
+ executeDeployChanges(isReadOnlyProcess) {
1210
1302
  combineLatest([
1211
1303
  from(isReadOnlyProcess ? this._bpmnViewer.saveXML() : this._bpmnModeler.saveXML()),
1212
1304
  this.processManagementEditorService.processLinksForSelectedDefinition$,
@@ -1215,18 +1307,20 @@ class ProcessManagementBuilderComponent {
1215
1307
  this.managementParams$.pipe(startWith(null)),
1216
1308
  ])
1217
1309
  .pipe(take(1), switchMap(([result, processLinks, selectedProcessDefinition, context, params]) => {
1310
+ const xml = !isReadOnlyProcess ? this.applyDraftState(result?.xml ?? '') : null;
1218
1311
  if (context === 'case') {
1219
1312
  const caseManagementParams = params;
1220
- return this.processLinkService.updateProcessDefinitionForCase(processLinks, selectedProcessDefinition.id, !isReadOnlyProcess ? (result?.xml ?? '') : null, caseManagementParams?.caseDefinitionKey ?? '', caseManagementParams?.caseDefinitionVersionTag ?? '', this.canInitializeDocument$.getValue(), this.startableByUser$.getValue());
1313
+ return this.processLinkService.updateProcessDefinitionForCase(processLinks, selectedProcessDefinition.id, xml, caseManagementParams?.caseDefinitionKey ?? '', caseManagementParams?.caseDefinitionVersionTag ?? '', this.canInitializeDocument$.getValue(), this.startableByUser$.getValue());
1221
1314
  }
1222
1315
  if (context === 'buildingBlock') {
1223
1316
  const buildingBlockManagementParams = params;
1224
- return this.processLinkService.updateProcessDefinitionForBuildingBlock(processLinks, selectedProcessDefinition.id, result?.xml, buildingBlockManagementParams.buildingBlockDefinitionKey, buildingBlockManagementParams.buildingBlockDefinitionVersionTag);
1317
+ return this.processLinkService.updateProcessDefinitionForBuildingBlock(processLinks, selectedProcessDefinition.id, this.applyDraftState(result?.xml), buildingBlockManagementParams.buildingBlockDefinitionKey, buildingBlockManagementParams.buildingBlockDefinitionVersionTag);
1225
1318
  }
1226
- return this.processLinkService.updateProcessDefinition(processLinks, selectedProcessDefinition.id, !isReadOnlyProcess ? (result?.xml ?? '') : null);
1319
+ return this.processLinkService.updateProcessDefinition(processLinks, selectedProcessDefinition.id, xml);
1227
1320
  }), switchMap(() => this.context$))
1228
1321
  .subscribe({
1229
1322
  next: context => {
1323
+ this.clearValidationErrors();
1230
1324
  if (context === 'independent') {
1231
1325
  this.reload();
1232
1326
  this.showNotification('success');
@@ -1235,12 +1329,20 @@ class ProcessManagementBuilderComponent {
1235
1329
  this.navigateBack('success');
1236
1330
  }
1237
1331
  },
1238
- error: () => {
1239
- this.showNotification('error');
1332
+ error: (error) => {
1333
+ if (this.isValidationError(error)) {
1334
+ this.highlightValidationErrors(error.error.errors);
1335
+ }
1336
+ else {
1337
+ this.showNotification('error');
1338
+ }
1240
1339
  },
1241
1340
  });
1242
1341
  }
1243
1342
  deployNewProcessDefinition() {
1343
+ this.validateAndDeploy(false, () => this.executeDeployNewProcessDefinition());
1344
+ }
1345
+ executeDeployNewProcessDefinition() {
1244
1346
  combineLatest([
1245
1347
  from(this._bpmnModeler.saveXML()),
1246
1348
  this.processManagementEditorService.processLinksForSelectedDefinition$,
@@ -1248,29 +1350,34 @@ class ProcessManagementBuilderComponent {
1248
1350
  this.managementParams$.pipe(startWith(null)),
1249
1351
  ])
1250
1352
  .pipe(take(1), switchMap(([result, processLinks, context, params]) => {
1353
+ const xml = this.applyDraftState(result.xml ?? '');
1251
1354
  const mappedProcessLinks = processLinks.map(link => ({
1252
1355
  ...link,
1253
1356
  processDefinitionId: '-',
1254
1357
  }));
1255
1358
  switch (context) {
1256
1359
  case 'independent':
1257
- return this.processLinkService.createProcessDefinition(mappedProcessLinks, result.xml ?? '');
1360
+ return this.processLinkService.createProcessDefinition(mappedProcessLinks, xml);
1258
1361
  case 'buildingBlock':
1259
1362
  const buildingBlockParams = params;
1260
- return this.processLinkService.createProcessDefinitionForBuildingBlock(mappedProcessLinks, result.xml ?? '', buildingBlockParams.buildingBlockDefinitionKey, buildingBlockParams.buildingBlockDefinitionVersionTag);
1363
+ return this.processLinkService.createProcessDefinitionForBuildingBlock(mappedProcessLinks, xml, buildingBlockParams.buildingBlockDefinitionKey, buildingBlockParams.buildingBlockDefinitionVersionTag);
1261
1364
  case 'case':
1262
1365
  const caseManagementParams = params;
1263
- return this.processLinkService.createProcessDefinitionForCase(mappedProcessLinks, result.xml ?? '', caseManagementParams.caseDefinitionKey, caseManagementParams.caseDefinitionVersionTag, this.canInitializeDocument$.getValue(), this.startableByUser$.getValue());
1366
+ return this.processLinkService.createProcessDefinitionForCase(mappedProcessLinks, xml, caseManagementParams.caseDefinitionKey, caseManagementParams.caseDefinitionVersionTag, this.canInitializeDocument$.getValue(), this.startableByUser$.getValue());
1264
1367
  }
1265
1368
  }))
1266
1369
  .subscribe({
1267
1370
  next: () => {
1371
+ this.clearValidationErrors();
1268
1372
  this.navigateBack('success');
1269
1373
  },
1270
1374
  error: (error) => {
1271
1375
  if (this.isProcessDefinitionAlreadyExistsError(error)) {
1272
1376
  this.showNotification('alreadyExists');
1273
1377
  }
1378
+ else if (this.isValidationError(error)) {
1379
+ this.highlightValidationErrors(error.error.errors);
1380
+ }
1274
1381
  else {
1275
1382
  this.showNotification('error');
1276
1383
  }
@@ -1293,13 +1400,88 @@ class ProcessManagementBuilderComponent {
1293
1400
  return;
1294
1401
  this.showNotification(notification);
1295
1402
  }
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
+ }
1296
1424
  onProcessToggleChange(field, value) {
1425
+ if (field === 'draft')
1426
+ this.draft$.next(value);
1297
1427
  if (field === 'canInitializeDocument')
1298
1428
  this.canInitializeDocument$.next(value);
1299
1429
  if (field === 'startableByUser')
1300
1430
  this.startableByUser$.next(value);
1301
1431
  this.changesPending$.next(true);
1302
1432
  }
1433
+ onWarningConfirmationConfirm() {
1434
+ if (this._pendingDeployAction) {
1435
+ this._pendingDeployAction();
1436
+ this._pendingDeployAction = null;
1437
+ }
1438
+ }
1439
+ onWarningConfirmationCancel() {
1440
+ this._pendingDeployAction = null;
1441
+ }
1442
+ validateAndDeploy(isReadOnlyProcess, deployAction) {
1443
+ // Skip validation for draft processes
1444
+ if (this.draft$.getValue()) {
1445
+ deployAction();
1446
+ return;
1447
+ }
1448
+ combineLatest([
1449
+ from(isReadOnlyProcess ? this._bpmnViewer.saveXML() : this._bpmnModeler.saveXML()),
1450
+ this.processManagementEditorService.processLinksForSelectedDefinition$,
1451
+ ])
1452
+ .pipe(take(1), switchMap(([result, processLinks]) => {
1453
+ const xml = this.applyDraftState(result?.xml ?? '') ?? '';
1454
+ return this.processManagementService.validateProcessDefinition({
1455
+ bpmnXml: xml,
1456
+ processLinks: processLinks.map(link => ({
1457
+ ...link,
1458
+ processDefinitionId: '-',
1459
+ })),
1460
+ });
1461
+ }))
1462
+ .subscribe({
1463
+ next: validationResult => {
1464
+ if (!validationResult.isValid) {
1465
+ // Has errors - show them and block deployment
1466
+ this.highlightValidationErrors(validationResult.errors);
1467
+ }
1468
+ else if (validationResult.hasWarnings) {
1469
+ // Only warnings - show confirmation dialog
1470
+ this.highlightValidationErrors(validationResult.errors);
1471
+ this._pendingDeployAction = deployAction;
1472
+ this.showWarningConfirmationModal$.next(true);
1473
+ }
1474
+ else {
1475
+ // No issues - proceed with deployment
1476
+ deployAction();
1477
+ }
1478
+ },
1479
+ error: () => {
1480
+ // Validation endpoint failed - proceed with deployment anyway (server will validate again)
1481
+ deployAction();
1482
+ },
1483
+ });
1484
+ }
1303
1485
  setProcessManagementWindow() {
1304
1486
  const processManagementWindow = window;
1305
1487
  if (!processManagementWindow)
@@ -1309,7 +1491,20 @@ class ProcessManagementBuilderComponent {
1309
1491
  processManagementWindow.pluginTranslationService = this.pluginTranslationService;
1310
1492
  }
1311
1493
  showNotification(notification) {
1312
- const type = notification === 'alreadyExists' ? 'error' : notification;
1494
+ if (!notification)
1495
+ return;
1496
+ let type;
1497
+ if (notification === 'alreadyExists' ||
1498
+ notification === 'validationError' ||
1499
+ notification === 'error') {
1500
+ type = 'error';
1501
+ }
1502
+ else if (notification === 'validationWarning') {
1503
+ type = 'warning';
1504
+ }
1505
+ else {
1506
+ type = 'success';
1507
+ }
1313
1508
  this.notificationService.showToast({
1314
1509
  caption: this.translateService.instant(`processManagement.${notification}Notification`),
1315
1510
  type,
@@ -1323,7 +1518,148 @@ class ProcessManagementBuilderComponent {
1323
1518
  if (body?.processDefinitionId)
1324
1519
  return true;
1325
1520
  const bbBody = body;
1326
- return Array.isArray(bbBody?.duplicateProcessDefinitions) && bbBody.duplicateProcessDefinitions.length > 0;
1521
+ return (Array.isArray(bbBody?.duplicateProcessDefinitions) &&
1522
+ bbBody.duplicateProcessDefinitions.length > 0);
1523
+ }
1524
+ applyDraftState(xml) {
1525
+ if (!xml)
1526
+ return null;
1527
+ const doc = new DOMParser().parseFromString(xml, 'application/xml');
1528
+ if (doc.getElementsByTagName('parsererror').length > 0)
1529
+ return xml;
1530
+ const executableValue = this.draft$.getValue() ? 'false' : 'true';
1531
+ const processes = doc.getElementsByTagNameNS('*', 'process');
1532
+ for (let i = 0; i < processes.length; i++) {
1533
+ processes[i].setAttribute('isExecutable', executableValue);
1534
+ }
1535
+ return new XMLSerializer().serializeToString(doc);
1536
+ }
1537
+ parseDraftFromXml(xml) {
1538
+ if (!xml)
1539
+ return false;
1540
+ const doc = new DOMParser().parseFromString(xml, 'application/xml');
1541
+ if (doc.getElementsByTagName('parsererror').length > 0)
1542
+ return false;
1543
+ const processes = doc.getElementsByTagNameNS('*', 'process');
1544
+ if (processes.length === 0)
1545
+ return false;
1546
+ for (let i = 0; i < processes.length; i++) {
1547
+ if (processes[i].getAttribute('isExecutable') === 'true')
1548
+ return false;
1549
+ }
1550
+ return true;
1551
+ }
1552
+ isValidationError(error) {
1553
+ return (error instanceof HttpErrorResponse &&
1554
+ error.status === 422 &&
1555
+ Array.isArray(error.error?.errors));
1556
+ }
1557
+ highlightValidationErrors(errors) {
1558
+ this.clearValidationErrors();
1559
+ this.processManagementEditorService.setValidationErrors(errors);
1560
+ const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
1561
+ const canvas = modeler.get('canvas');
1562
+ const overlays = modeler.get('overlays');
1563
+ const errorElementIds = new Set();
1564
+ const elementHasError = new Map();
1565
+ const elementFirstIssue = new Map();
1566
+ for (const error of errors) {
1567
+ if (error.elementType === 'Process')
1568
+ continue;
1569
+ const hasErrorAlready = elementHasError.get(error.elementId) ?? false;
1570
+ const isError = error.severity !== 'WARNING';
1571
+ if (!elementFirstIssue.has(error.elementId)) {
1572
+ elementFirstIssue.set(error.elementId, error);
1573
+ }
1574
+ else if (isError && !hasErrorAlready) {
1575
+ elementFirstIssue.set(error.elementId, error);
1576
+ }
1577
+ if (isError) {
1578
+ elementHasError.set(error.elementId, true);
1579
+ }
1580
+ else if (!hasErrorAlready) {
1581
+ elementHasError.set(error.elementId, false);
1582
+ }
1583
+ }
1584
+ for (const [elementId, issue] of elementFirstIssue) {
1585
+ try {
1586
+ const hasError = elementHasError.get(elementId) ?? false;
1587
+ const markerClass = hasError ? 'highlight-overlay-error' : 'highlight-overlay-warning';
1588
+ const overlayClass = hasError ? 'validation-error-overlay' : 'validation-warning-overlay';
1589
+ this._validationErrorElementIds.push(elementId);
1590
+ errorElementIds.add(elementId);
1591
+ canvas.addMarker(elementId, markerClass);
1592
+ const position = issue.elementType === 'Participant' ? { top: 5, left: 5 } : { top: -12, left: -12 };
1593
+ overlays.add(elementId, 'validation-error', {
1594
+ position,
1595
+ html: this.buildOverlayElement(overlayClass, elementId, this.getValidationErrorMessage(issue)),
1596
+ });
1597
+ }
1598
+ catch (e) {
1599
+ // Element may not exist on the canvas
1600
+ }
1601
+ }
1602
+ const eventBus = modeler.get('eventBus');
1603
+ this._validationHoverHandler = (event) => {
1604
+ const id = event.element?.id;
1605
+ if (id && errorElementIds.has(id)) {
1606
+ const errorOverlay = document.querySelector(`.validation-error-overlay[data-element-id="${id}"]`);
1607
+ const warningOverlay = document.querySelector(`.validation-warning-overlay[data-element-id="${id}"]`);
1608
+ errorOverlay?.classList.add('validation-error-overlay--active');
1609
+ warningOverlay?.classList.add('validation-warning-overlay--active');
1610
+ }
1611
+ };
1612
+ this._validationOutHandler = (event) => {
1613
+ const id = event.element?.id;
1614
+ if (id && errorElementIds.has(id)) {
1615
+ const errorOverlay = document.querySelector(`.validation-error-overlay[data-element-id="${id}"]`);
1616
+ const warningOverlay = document.querySelector(`.validation-warning-overlay[data-element-id="${id}"]`);
1617
+ errorOverlay?.classList.remove('validation-error-overlay--active');
1618
+ warningOverlay?.classList.remove('validation-warning-overlay--active');
1619
+ }
1620
+ };
1621
+ eventBus.on('element.hover', this._validationHoverHandler);
1622
+ eventBus.on('element.out', this._validationOutHandler);
1623
+ const selection = modeler.get('selection');
1624
+ const selected = selection.get();
1625
+ if (selected?.length > 0) {
1626
+ const current = selected[0];
1627
+ selection.deselect(current);
1628
+ selection.select(current);
1629
+ }
1630
+ }
1631
+ clearValidationErrors() {
1632
+ const modeler = this.isReadOnlyProcess$.getValue() ? this._bpmnViewer : this._bpmnModeler;
1633
+ if (!modeler)
1634
+ return;
1635
+ this.processManagementEditorService.setValidationErrors([]);
1636
+ const canvas = modeler.get('canvas');
1637
+ const overlays = modeler.get('overlays');
1638
+ const eventBus = modeler.get('eventBus');
1639
+ if (this._validationHoverHandler) {
1640
+ eventBus.off('element.hover', this._validationHoverHandler);
1641
+ this._validationHoverHandler = null;
1642
+ }
1643
+ if (this._validationOutHandler) {
1644
+ eventBus.off('element.out', this._validationOutHandler);
1645
+ this._validationOutHandler = null;
1646
+ }
1647
+ for (const elementId of this._validationErrorElementIds) {
1648
+ try {
1649
+ canvas.removeMarker(elementId, 'highlight-overlay-error');
1650
+ canvas.removeMarker(elementId, 'highlight-overlay-warning');
1651
+ }
1652
+ catch (e) {
1653
+ // ignore
1654
+ }
1655
+ }
1656
+ this._validationErrorElementIds = [];
1657
+ try {
1658
+ overlays.remove({ type: 'validation-error' });
1659
+ }
1660
+ catch (e) {
1661
+ // ignore
1662
+ }
1327
1663
  }
1328
1664
  setSelectedProcessDefinitionToLatest(processDefinitions) {
1329
1665
  const latest = getLatestProcessDefinition(processDefinitions);
@@ -1475,6 +1811,8 @@ class ProcessManagementBuilderComponent {
1475
1811
  this.cleanUpListenersOnModeler();
1476
1812
  this._bpmnModeler?.importXML(processDefinitionResult.bpmn20Xml);
1477
1813
  this._bpmnViewer?.importXML(processDefinitionResult.bpmn20Xml);
1814
+ this.draft$.next(processDefinitionResult.draft ??
1815
+ this.parseDraftFromXml(processDefinitionResult.bpmn20Xml));
1478
1816
  this.canInitializeDocument$.next(!!processDefinitionResult?.processCaseLink?.canInitializeDocument);
1479
1817
  this.startableByUser$.next(!!processDefinitionResult?.processCaseLink?.startableByUser);
1480
1818
  this.loading$.next(false);
@@ -1551,13 +1889,37 @@ class ProcessManagementBuilderComponent {
1551
1889
  }
1552
1890
  clearBuildingBlockCalledElement(editor, activityId);
1553
1891
  }
1892
+ getValidationErrorMessage(error) {
1893
+ if (error.errorCode) {
1894
+ const translationKey = `processManagement.expressionErrors.${error.errorCode}`;
1895
+ const translated = this.translateService.instant(translationKey);
1896
+ if (translated !== translationKey) {
1897
+ return error.expression ? `${translated}: '${error.expression}'` : translated;
1898
+ }
1899
+ }
1900
+ return error.reason;
1901
+ }
1902
+ buildOverlayElement(overlayClass, elementId, message) {
1903
+ const container = document.createElement('div');
1904
+ container.className = overlayClass;
1905
+ container.dataset.elementId = elementId;
1906
+ const icon = document.createElement('span');
1907
+ icon.className = `${overlayClass}__icon`;
1908
+ icon.textContent = '!';
1909
+ container.appendChild(icon);
1910
+ const text = document.createElement('span');
1911
+ text.className = `${overlayClass}__text`;
1912
+ text.textContent = message;
1913
+ container.appendChild(text);
1914
+ return container;
1915
+ }
1554
1916
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ProcessManagementBuilderComponent, deps: [{ token: i1$1.BreadcrumbService }, { token: i2$2.IconService }, { token: i3.NGXLogger }, { token: i1$1.ModalService }, { token: i2$1.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$1.EditPermissionsService }, { token: i5.ProcessLinkBuildingBlockApiService }], target: i0.ɵɵFactoryTarget.Component }); }
1555
1917
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: ProcessManagementBuilderComponent, isStandalone: true, selector: "valtimo-process-management-builder", providers: [
1556
1918
  ProcessManagementEditorService,
1557
1919
  ProcessLinkStateService,
1558
1920
  ProcessLinkStepService,
1559
1921
  ProcessLinkButtonService,
1560
- ], 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-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<div\n fitPage\n [spaceAdjustment]=\"$spaceAdjustment()\"\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></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<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 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 class=\"page-header-actions__tags\">\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 </div>\n\n <div class=\"page-header-actions__buttons\">\n @if (actionsObs.context === 'case') {\n <cds-tooltip\n [description]=\"'processCaseConnection.processCreatesCaseTooltip' | translate\"\n >\n <cds-toggle\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 [description]=\"'processCaseConnection.startableWithinCaseTooltip' | translate\"\n >\n <cds-toggle\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\n <button\n *ngIf=\"actionsObs.context === 'case'\"\n cdsButton=\"secondary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n >\n <svg class=\"cds--btn__icon\" cdsIcon=\"arrow--left\" size=\"16\"></svg>\n\n <span>{{ 'interface.back' | translate }}</span>\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\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 </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%}.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}.page-header-actions__left-container{display:flex;gap:24px;align-items:flex-end}.page-header-actions__tags{display:flex;gap:8px;align-items:flex-end}.page-header-actions__version-dropdown{width:150px}.page-header-actions__buttons{display:flex;gap:16px;align-items:center}.page-header-actions__buttons cds-toggle{height:24px}.page-header-actions__buttons ::ng-deep .cds--toggle__label-text{display:none}.valtimo-process-builder__header{display:flex;justify-content:space-between}.valtimo-process-builder__actions>*:not(:last-child){margin-right:8px}::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.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "directive", type: FitPageDirective, selector: "[fitPage]", inputs: ["spaceAdjustment", "fitPageDisabled", "disableOverflow"] }, { 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"] }] }); }
1922
+ ], 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"] }] }); }
1561
1923
  }
1562
1924
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ProcessManagementBuilderComponent, decorators: [{
1563
1925
  type: Component,
@@ -1580,12 +1942,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1580
1942
  OverflowMenuTriggerComponent,
1581
1943
  ToggleModule,
1582
1944
  TooltipModule,
1945
+ ConfirmationModalModule,
1583
1946
  ], providers: [
1584
1947
  ProcessManagementEditorService,
1585
1948
  ProcessLinkStateService,
1586
1949
  ProcessLinkStepService,
1587
1950
  ProcessLinkButtonService,
1588
- ], 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<div\n fitPage\n [spaceAdjustment]=\"$spaceAdjustment()\"\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></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<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 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 class=\"page-header-actions__tags\">\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 </div>\n\n <div class=\"page-header-actions__buttons\">\n @if (actionsObs.context === 'case') {\n <cds-tooltip\n [description]=\"'processCaseConnection.processCreatesCaseTooltip' | translate\"\n >\n <cds-toggle\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 [description]=\"'processCaseConnection.startableWithinCaseTooltip' | translate\"\n >\n <cds-toggle\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\n <button\n *ngIf=\"actionsObs.context === 'case'\"\n cdsButton=\"secondary\"\n [size]=\"actionsObs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n >\n <svg class=\"cds--btn__icon\" cdsIcon=\"arrow--left\" size=\"16\"></svg>\n\n <span>{{ 'interface.back' | translate }}</span>\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\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 </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%}.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}.page-header-actions__left-container{display:flex;gap:24px;align-items:flex-end}.page-header-actions__tags{display:flex;gap:8px;align-items:flex-end}.page-header-actions__version-dropdown{width:150px}.page-header-actions__buttons{display:flex;gap:16px;align-items:center}.page-header-actions__buttons cds-toggle{height:24px}.page-header-actions__buttons ::ng-deep .cds--toggle__label-text{display:none}.valtimo-process-builder__header{display:flex;justify-content:space-between}.valtimo-process-builder__actions>*:not(:last-child){margin-right:8px}::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"] }]
1951
+ ], 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"] }]
1589
1952
  }], ctorParameters: () => [{ type: i1$1.BreadcrumbService }, { type: i2$2.IconService }, { type: i3.NGXLogger }, { type: i1$1.ModalService }, { type: i2$1.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$1.EditPermissionsService }, { type: i5.ProcessLinkBuildingBlockApiService }], propDecorators: { modelerElementRef: [{
1590
1953
  type: ViewChild,
1591
1954
  args: ['modeler', { static: false }]
@@ -1635,7 +1998,19 @@ class ProcessManagementListComponent {
1635
1998
  { label: 'Delete', callback: this.onDeleteProcess.bind(this), type: 'danger' },
1636
1999
  ];
1637
2000
  this.context$ = getContextObservable(this.route);
1638
- this.processDefinitions$ = this.processManagementStateService.reloadDefinitions$.pipe(tap(() => this.loading$.next(true)), switchMap(() => this.processManagementService.processes$), tap(() => this.loading$.next(false)));
2001
+ this.processDefinitions$ = combineLatest([
2002
+ this.processManagementStateService.reloadDefinitions$.pipe(tap(() => this.loading$.next(true)), switchMap(() => this.processManagementService.processes$), tap(() => this.loading$.next(false))),
2003
+ this.translateService.stream('key'),
2004
+ ]).pipe(map$1(([definitions]) => definitions.map(def => {
2005
+ const tags = [];
2006
+ if (def.draft) {
2007
+ tags.push({ content: this.translateService.instant('processManagement.draft'), type: 'red' });
2008
+ }
2009
+ if (def.processDefinition?.readOnly) {
2010
+ tags.push({ content: this.translateService.instant('processManagement.readOnly'), type: 'gray' });
2011
+ }
2012
+ return { ...def, statusTags: tags };
2013
+ })));
1639
2014
  this.hasEditPermissions$ = combineLatest([
1640
2015
  getCaseManagementRouteParams(this.route),
1641
2016
  this.context$,
@@ -1645,11 +2020,6 @@ class ProcessManagementListComponent {
1645
2020
  this.FIELDS = [
1646
2021
  { key: 'processDefinition.name', label: 'processManagement.name' },
1647
2022
  { key: 'processDefinition.key', label: 'processManagement.key' },
1648
- {
1649
- key: 'processDefinition.readOnly',
1650
- label: 'processManagement.readOnly',
1651
- viewType: ViewType.BOOLEAN,
1652
- },
1653
2023
  ...(this.processManagementService.$context() === 'case'
1654
2024
  ? [
1655
2025
  {
@@ -1657,10 +2027,6 @@ class ProcessManagementListComponent {
1657
2027
  label: 'processManagement.canInitializeDocument',
1658
2028
  viewType: ViewType.BOOLEAN,
1659
2029
  },
1660
- ]
1661
- : []),
1662
- ...(this.processManagementService.$context() === 'case'
1663
- ? [
1664
2030
  {
1665
2031
  key: 'processCaseLink.startableByUser',
1666
2032
  label: 'processManagement.startableByUser',
@@ -1668,6 +2034,12 @@ class ProcessManagementListComponent {
1668
2034
  },
1669
2035
  ]
1670
2036
  : []),
2037
+ {
2038
+ key: 'statusTags',
2039
+ label: 'processManagement.status',
2040
+ viewType: ViewType.TAGS,
2041
+ tagAmount: 2,
2042
+ },
1671
2043
  ];
1672
2044
  this.iconService.registerAll([Upload16]);
1673
2045
  }