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