@valtimo/decision 13.34.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,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, ViewEncapsulation, EventEmitter, Output, ViewChild, NgModule } from '@angular/core';
3
- import { Subject, startWith, BehaviorSubject, map, combineLatest, switchMap, tap, filter, take, from, of, catchError } from 'rxjs';
2
+ import { Injectable, EventEmitter, signal, Output, Input, ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation, NgModule } from '@angular/core';
3
+ import { Subject, startWith, BehaviorSubject, map, combineLatest, switchMap, shareReplay, tap, filter, take, from, of, catchError } from 'rxjs';
4
4
  import * as i1 from '@angular/common/http';
5
5
  import { HttpHeaders } from '@angular/common/http';
6
6
  import * as i6 from '@valtimo/shared';
@@ -11,17 +11,18 @@ import * as i7 from '@angular/common';
11
11
  import { CommonModule } from '@angular/common';
12
12
  import { AuthGuardService } from '@valtimo/security';
13
13
  import DmnJS from 'dmn-js/dist/dmn-modeler.development.js';
14
- import { migrateDiagram } from '@bpmn-io/dmn-migrate';
15
- import * as i4 from '@valtimo/components';
16
- import { PendingChangesComponent, WidgetModule, SelectModule as SelectModule$1, RenderInPageHeaderDirective, FitPageDirective, OverflowMenuComponent, OverflowMenuOptionComponent, OverflowMenuTriggerComponent, CarbonListModule, ModalModule as ModalModule$1, SpinnerModule } from '@valtimo/components';
14
+ import DmnViewer from 'dmn-js/dist/dmn-viewer.development.js';
15
+ import * as i1$1 from '@angular/forms';
16
+ import { Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
17
17
  import * as i3 from '@ngx-translate/core';
18
18
  import { TranslateModule } from '@ngx-translate/core';
19
- import * as i6$1 from 'carbon-components-angular';
20
- import { ModalModule, SelectModule, ButtonModule, IconModule, LayerModule, FileUploaderModule } from 'carbon-components-angular';
21
- import { Deploy16, Download16, ArrowLeft16, Upload16 } from '@carbon/icons';
22
- import DmnViewer from 'dmn-js';
23
- import * as i3$1 from '@angular/forms';
24
- import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
19
+ import * as i4$1 from '@valtimo/components';
20
+ import { runAfterCarbonModalClosed, ValtimoCdsModalDirective, CarbonMultiInputModule, PendingChangesComponent, WidgetModule, SelectModule as SelectModule$1, RenderInPageHeaderDirective, FitPageDirective, OverflowMenuComponent, OverflowMenuOptionComponent, OverflowMenuTriggerComponent, ConfirmationModalModule, CarbonListModule, ModalModule as ModalModule$1, SpinnerModule } from '@valtimo/components';
21
+ import * as i4 from 'carbon-components-angular';
22
+ import { ModalModule, ButtonModule, InputModule, LayerModule, SelectModule, IconModule, TagModule, FileUploaderModule } from 'carbon-components-angular';
23
+ import { migrateDiagram } from '@bpmn-io/dmn-migrate';
24
+ import { Deploy16, Download16, ArrowLeft16, Upload16, Add16 } from '@carbon/icons';
25
+ import DmnViewer$1 from 'dmn-js';
25
26
 
26
27
  /*
27
28
  * Copyright 2015-2025 Ritense BV, the Netherlands.
@@ -137,6 +138,10 @@ class DecisionService extends BaseApiService {
137
138
  getDecisions() {
138
139
  return this.httpClient.get(this.getApiUrl('/operaton-rest/engine/default/decision-definition'));
139
140
  }
141
+ getUnlinkedDecisions() {
142
+ // Only the "global" decision tables: those not linked to a case or building block definition.
143
+ return this.httpClient.get(this.getApiUrl('/management/v1/decision-definition'));
144
+ }
140
145
  getDecisionById(decisionId) {
141
146
  return this.httpClient.get(this.getApiUrl(`/operaton-rest/engine/default/decision-definition/${decisionId}`));
142
147
  }
@@ -215,13 +220,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
215
220
  */
216
221
  const DECISION_LIST_TEST_IDS = {
217
222
  uploadButton: 'decisionListUploadButton',
223
+ createButton: 'decisionListCreateButton',
218
224
  };
219
225
  const DECISION_UPLOAD_TEST_IDS = {
220
226
  submitButton: 'decisionUploadModalSubmitButton',
221
227
  };
228
+ const DECISION_FORM_TEST_IDS = {
229
+ nameInput: 'decisionFormModalNameInput',
230
+ inputVariables: 'decisionFormModalInputVariables',
231
+ submitButton: 'decisionFormModalSubmitButton',
232
+ };
222
233
  const DECISION_MODELER_TEST_IDS = {
223
234
  deployButton: 'decisionModelerDeployButton',
224
235
  backButton: 'decisionModelerBackButton',
236
+ readOnlyTag: 'decisionModelerReadOnlyTag',
225
237
  };
226
238
 
227
239
  /*
@@ -240,6 +252,348 @@ const DECISION_MODELER_TEST_IDS = {
240
252
  * limitations under the License.
241
253
  */
242
254
 
255
+ /*
256
+ * Copyright 2015-2026 Ritense BV, the Netherlands.
257
+ *
258
+ * Licensed under EUPL, Version 1.2 (the "License");
259
+ * you may not use this file except in compliance with the License.
260
+ * You may obtain a copy of the License at
261
+ *
262
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
263
+ *
264
+ * Unless required by applicable law or agreed to in writing, software
265
+ * distributed under the License is distributed on an "AS IS" basis,
266
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
267
+ * See the License for the specific language governing permissions and
268
+ * limitations under the License.
269
+ */
270
+ const DEFAULT_DECISION_KEY = 'decision';
271
+ function escapeXmlAttribute(value) {
272
+ return value
273
+ .replace(/&/g, '&')
274
+ .replace(/</g, '&lt;')
275
+ .replace(/>/g, '&gt;')
276
+ .replace(/"/g, '&quot;')
277
+ .replace(/'/g, '&apos;');
278
+ }
279
+ function escapeXmlText(value) {
280
+ return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
281
+ }
282
+ /**
283
+ * Derives a valid DMN decision key (an XML NCName) from a human-readable name.
284
+ * The decision key doubles as the identifier referenced from a process'
285
+ * business rule task, so it must be a stable, valid identifier.
286
+ */
287
+ function toDecisionKey(name) {
288
+ const cleaned = (name ?? '')
289
+ .trim()
290
+ .replace(/[^A-Za-z0-9_-]+/g, '_')
291
+ .replace(/^[_-]+|[_-]+$/g, '');
292
+ if (!cleaned)
293
+ return DEFAULT_DECISION_KEY;
294
+ return /^[A-Za-z_]/.test(cleaned) ? cleaned : `${DEFAULT_DECISION_KEY}_${cleaned}`;
295
+ }
296
+ /**
297
+ * Derives the name of the `.dmn` file that is deployed for a created decision.
298
+ */
299
+ function toDecisionFileName(name) {
300
+ return `${toDecisionKey(name)}.dmn`;
301
+ }
302
+ /**
303
+ * Normalizes input columns: trims label/expression, drops rows without a process
304
+ * variable (the expression is required), defaults the label to the process
305
+ * variable name when it is left blank, and guarantees at least one (empty) input
306
+ * column so the decision table always has an input to work with.
307
+ */
308
+ function normalizeInputVariables(inputVariables) {
309
+ const cleaned = (inputVariables ?? [])
310
+ .map(({ label, expression }) => ({
311
+ label: (label ?? '').trim(),
312
+ expression: (expression ?? '').trim(),
313
+ }))
314
+ .filter(({ expression }) => expression.length > 0)
315
+ .map(({ label, expression }) => ({ label: label || expression, expression }));
316
+ return cleaned.length ? cleaned : [{ label: '', expression: '' }];
317
+ }
318
+ /**
319
+ * Builds a deployable DMN 1.3 decision table seeded with one input column per
320
+ * provided input variable and a single output. Each input column gets its
321
+ * process variable as the input expression and, optionally, a human-readable
322
+ * label as the column header. Seeding this up front means the created table is
323
+ * functional immediately - the user only has to add rules before deploying.
324
+ */
325
+ function createDmnXml({ name, inputVariables }) {
326
+ const key = toDecisionKey(name);
327
+ const safeName = escapeXmlAttribute((name ?? '').trim() || key);
328
+ const inputs = normalizeInputVariables(inputVariables);
329
+ const inputsXml = inputs
330
+ .map(({ label, expression }, index) => {
331
+ const labelAttr = label ? ` label="${escapeXmlAttribute(label)}"` : '';
332
+ return ` <input id="Input_${index + 1}"${labelAttr}>
333
+ <inputExpression id="InputExpression_${index + 1}" typeRef="string">
334
+ <text>${escapeXmlText(expression)}</text>
335
+ </inputExpression>
336
+ </input>`;
337
+ })
338
+ .join('\n');
339
+ const inputEntriesXml = inputs
340
+ .map((_, index) => ` <inputEntry id="UnaryTests_${index + 1}">
341
+ <text></text>
342
+ </inputEntry>`)
343
+ .join('\n');
344
+ const dmnXml = `<?xml version="1.0" encoding="UTF-8"?>
345
+ <definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/" xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/" xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/" id="Definitions_${key}" name="${safeName}" namespace="http://camunda.org/schema/1.0/dmn">
346
+ <decision id="${key}" name="${safeName}">
347
+ <decisionTable id="DecisionTable_${key}">
348
+ ${inputsXml}
349
+ <output id="Output_1" label="Output" name="result" typeRef="string" />
350
+ <rule id="DecisionRule_1">
351
+ ${inputEntriesXml}
352
+ <outputEntry id="LiteralExpression_1">
353
+ <text></text>
354
+ </outputEntry>
355
+ </rule>
356
+ </decisionTable>
357
+ </decision>
358
+ <dmndi:DMNDI>
359
+ <dmndi:DMNDiagram>
360
+ <dmndi:DMNShape dmnElementRef="${key}">
361
+ <dc:Bounds height="80" width="180" x="160" y="100" />
362
+ </dmndi:DMNShape>
363
+ </dmndi:DMNDiagram>
364
+ </dmndi:DMNDI>
365
+ </definitions>
366
+ `;
367
+ return { id: '', dmnXml };
368
+ }
369
+ function childrenByLocalName(parent, localName) {
370
+ return Array.from(parent.children).filter(child => child.localName === localName);
371
+ }
372
+ function firstChildByLocalName(parent, localName) {
373
+ return childrenByLocalName(parent, localName)[0] ?? null;
374
+ }
375
+ function uniqueId(doc, prefix) {
376
+ let id;
377
+ do {
378
+ id = `${prefix}_${Math.random().toString(36).slice(2, 10)}`;
379
+ } while (doc.querySelector(`[id="${id}"]`));
380
+ return id;
381
+ }
382
+ /**
383
+ * Reads the editable form values (decision name and input columns) from an
384
+ * existing DMN XML document.
385
+ */
386
+ function parseDecisionForm(xml) {
387
+ const doc = new DOMParser().parseFromString(xml, 'application/xml');
388
+ const decision = doc.getElementsByTagNameNS('*', 'decision')[0];
389
+ const name = decision?.getAttribute('name') || decision?.getAttribute('id') || '';
390
+ const inputVariables = Array.from(doc.getElementsByTagNameNS('*', 'input')).map(input => {
391
+ const inputExpression = input.getElementsByTagNameNS('*', 'inputExpression')[0];
392
+ const text = inputExpression?.getElementsByTagNameNS('*', 'text')[0];
393
+ const expression = (text?.textContent ?? '').trim();
394
+ const label = (input.getAttribute('label') ?? '').trim();
395
+ // A label equal to the expression means it was defaulted, so present it as blank.
396
+ return { label: label === expression ? '' : label, expression };
397
+ });
398
+ return { name, inputVariables };
399
+ }
400
+ function setInputColumn(input, { label, expression }, doc, ns) {
401
+ if (label) {
402
+ input.setAttribute('label', label);
403
+ }
404
+ else {
405
+ input.removeAttribute('label');
406
+ }
407
+ let inputExpression = firstChildByLocalName(input, 'inputExpression');
408
+ if (!inputExpression) {
409
+ inputExpression = doc.createElementNS(ns, 'inputExpression');
410
+ inputExpression.setAttribute('id', uniqueId(doc, 'InputExpression'));
411
+ inputExpression.setAttribute('typeRef', 'string');
412
+ input.appendChild(inputExpression);
413
+ }
414
+ let text = firstChildByLocalName(inputExpression, 'text');
415
+ if (!text) {
416
+ text = doc.createElementNS(ns, 'text');
417
+ inputExpression.appendChild(text);
418
+ }
419
+ text.textContent = expression;
420
+ }
421
+ function createInputElement(inputVariable, doc, ns) {
422
+ const input = doc.createElementNS(ns, 'input');
423
+ input.setAttribute('id', uniqueId(doc, 'Input'));
424
+ setInputColumn(input, inputVariable, doc, ns);
425
+ return input;
426
+ }
427
+ function createEmptyInputEntry(doc, ns) {
428
+ const entry = doc.createElementNS(ns, 'inputEntry');
429
+ entry.setAttribute('id', uniqueId(doc, 'UnaryTests'));
430
+ const text = doc.createElementNS(ns, 'text');
431
+ text.textContent = '';
432
+ entry.appendChild(text);
433
+ return entry;
434
+ }
435
+ /**
436
+ * Patches an existing DMN XML document with a new decision name and set of input
437
+ * columns, while preserving the decision key, outputs, rules and diagram. Input
438
+ * columns are reconciled positionally: existing columns are updated (label +
439
+ * expression), extra columns add an input (and a blank entry to every rule), and
440
+ * removed columns drop the input (and their rule entries).
441
+ */
442
+ function updateDmnXml(xml, { name, inputVariables }) {
443
+ const doc = new DOMParser().parseFromString(xml, 'application/xml');
444
+ if (doc.getElementsByTagName('parsererror').length > 0) {
445
+ return xml;
446
+ }
447
+ const trimmedName = (name ?? '').trim();
448
+ const decision = doc.getElementsByTagNameNS('*', 'decision')[0];
449
+ if (decision && trimmedName) {
450
+ decision.setAttribute('name', trimmedName);
451
+ }
452
+ const decisionTable = doc.getElementsByTagNameNS('*', 'decisionTable')[0];
453
+ if (!decisionTable) {
454
+ return new XMLSerializer().serializeToString(doc);
455
+ }
456
+ const ns = decisionTable.namespaceURI;
457
+ const targets = normalizeInputVariables(inputVariables);
458
+ const existingInputs = childrenByLocalName(decisionTable, 'input');
459
+ const rules = childrenByLocalName(decisionTable, 'rule');
460
+ // Build the final ordered list of input columns, reusing existing nodes where possible.
461
+ const finalInputs = targets.map((inputVariable, index) => {
462
+ const existing = existingInputs[index];
463
+ if (existing) {
464
+ setInputColumn(existing, inputVariable, doc, ns);
465
+ return existing;
466
+ }
467
+ return createInputElement(inputVariable, doc, ns);
468
+ });
469
+ // Remove all existing inputs, then re-insert the final ones in order before the outputs/rules.
470
+ existingInputs.forEach(input => input.remove());
471
+ const anchor = firstChildByLocalName(decisionTable, 'output') ??
472
+ firstChildByLocalName(decisionTable, 'rule') ??
473
+ null;
474
+ finalInputs.forEach(input => decisionTable.insertBefore(input, anchor));
475
+ // Reconcile each rule's input entries to match the number of input columns.
476
+ rules.forEach(rule => {
477
+ const entries = childrenByLocalName(rule, 'inputEntry');
478
+ for (let index = entries.length; index < finalInputs.length; index++) {
479
+ const firstOutputEntry = firstChildByLocalName(rule, 'outputEntry');
480
+ rule.insertBefore(createEmptyInputEntry(doc, ns), firstOutputEntry);
481
+ }
482
+ for (let index = entries.length - 1; index >= finalInputs.length; index--) {
483
+ entries[index].remove();
484
+ }
485
+ });
486
+ return new XMLSerializer().serializeToString(doc);
487
+ }
488
+
489
+ /*
490
+ * Copyright 2015-2026 Ritense BV, the Netherlands.
491
+ *
492
+ * Licensed under EUPL, Version 1.2 (the "License");
493
+ * you may not use this file except in compliance with the License.
494
+ * You may obtain a copy of the License at
495
+ *
496
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
497
+ *
498
+ * Unless required by applicable law or agreed to in writing, software
499
+ * distributed under the License is distributed on an "AS IS" basis,
500
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
501
+ * See the License for the specific language governing permissions and
502
+ * limitations under the License.
503
+ */
504
+ class DecisionFormModalComponent {
505
+ get name() {
506
+ return this.form.get('name');
507
+ }
508
+ constructor(formBuilder) {
509
+ this.formBuilder = formBuilder;
510
+ this.titleKey = 'decisions.createModal.title';
511
+ this.submitKey = 'interface.create';
512
+ this.submitEvent = new EventEmitter();
513
+ this.MAX_INPUT_VARIABLES = 100;
514
+ this.modalOpen$ = new BehaviorSubject(false);
515
+ this.defaultInputVariables$ = new BehaviorSubject([
516
+ { key: '', value: '' },
517
+ ]);
518
+ /** True when a row has a label but no process variable (the process variable is required). */
519
+ this.$inputVariablesInvalid = signal(false);
520
+ this.testIds = DECISION_FORM_TEST_IDS;
521
+ this.form = this.formBuilder.group({
522
+ name: this.formBuilder.control('', [Validators.required]),
523
+ });
524
+ this._inputVariables = [];
525
+ }
526
+ open(initial) {
527
+ const inputVariables = initial?.inputVariables ?? [];
528
+ this._inputVariables = inputVariables.map(({ label, expression }) => ({ label, expression }));
529
+ // The multi-input renders key (left) then value (right); the process variable is
530
+ // the first column, so it maps to key and the label maps to value.
531
+ this.defaultInputVariables$.next(inputVariables.length
532
+ ? inputVariables.map(({ label, expression }) => ({ key: expression, value: label }))
533
+ : [{ key: '', value: '' }]);
534
+ this.updateInputVariablesValidity();
535
+ this.form.reset({ name: initial?.name ?? '' });
536
+ this.modalOpen$.next(true);
537
+ }
538
+ /** Convenience used by the "create" trigger, which opens an empty form. */
539
+ openModal() {
540
+ this.open();
541
+ }
542
+ closeModal() {
543
+ this.modalOpen$.next(false);
544
+ runAfterCarbonModalClosed(() => {
545
+ this.form.reset({ name: '' });
546
+ this._inputVariables = [];
547
+ this.$inputVariablesInvalid.set(false);
548
+ this.defaultInputVariables$.next([{ key: '', value: '' }]);
549
+ });
550
+ }
551
+ onInputVariablesChange(values) {
552
+ this._inputVariables = (values ?? []).map(row => ({
553
+ label: row.value ?? '',
554
+ expression: row.key ?? '',
555
+ }));
556
+ this.updateInputVariablesValidity();
557
+ }
558
+ submit() {
559
+ if (this.form.invalid || this.$inputVariablesInvalid()) {
560
+ this.form.markAllAsTouched();
561
+ return;
562
+ }
563
+ const name = (this.form.getRawValue().name ?? '').trim();
564
+ const inputVariables = this._inputVariables
565
+ .map(({ label, expression }) => ({ label: label.trim(), expression: expression.trim() }))
566
+ .filter(({ expression }) => expression.length > 0);
567
+ this.submitEvent.emit({ name, inputVariables });
568
+ this.closeModal();
569
+ }
570
+ updateInputVariablesValidity() {
571
+ this.$inputVariablesInvalid.set(this._inputVariables.some(({ label, expression }) => label.trim().length > 0 && expression.trim().length === 0));
572
+ }
573
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionFormModalComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
574
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DecisionFormModalComponent, isStandalone: true, selector: "valtimo-decision-form-modal", inputs: { titleKey: "titleKey", submitKey: "submitKey" }, outputs: { submitEvent: "submitEvent" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal showFooter=\"true\" valtimoCdsModal [open]=\"modalOpen$ | async\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ titleKey | translate }}</h3>\n </cds-modal-header>\n\n <form cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\">\n <div class=\"cds--text-input__field-wrapper\">\n <cds-label [invalid]=\"name.touched && name.invalid\">\n <span>{{ 'decisions.createModal.name' | translate }}</span>\n\n <input\n cdsText\n formControlName=\"name\"\n [attr.data-test-id]=\"testIds.nameInput\"\n [invalid]=\"name.touched && name.invalid\"\n placeholder=\"{{ 'decisions.createModal.namePlaceholder' | translate }}\"\n />\n </cds-label>\n\n <div *ngIf=\"name.touched && name.invalid\" class=\"cds--form-requirement\">\n {{ 'decisions.createModal.nameRequired' | translate }}\n </div>\n </div>\n\n <valtimo-carbon-multi-input\n *ngIf=\"modalOpen$ | async\"\n type=\"keyValue\"\n [attr.data-test-id]=\"testIds.inputVariables\"\n [titleTranslationKey]=\"'decisions.createModal.inputVariables'\"\n [tooltip]=\"'decisions.createModal.inputVariablesHelper' | translate\"\n [keyColumnTitle]=\"'decisions.createModal.inputExpression' | translate\"\n [valueColumnTitle]=\"'decisions.createModal.inputLabel' | translate\"\n [addRowTranslationKey]=\"'decisions.createModal.addInputVariable'\"\n [defaultValues]=\"defaultInputVariables$ | async\"\n [initialAmountOfRows]=\"1\"\n [minimumAmountOfRows]=\"1\"\n [maxRows]=\"MAX_INPUT_VARIABLES\"\n [margin]=\"true\"\n [fullWidth]=\"true\"\n (valueChange)=\"onInputVariablesChange($event)\"\n ></valtimo-carbon-multi-input>\n\n <div *ngIf=\"$inputVariablesInvalid()\" class=\"cds--form-requirement\">\n {{ 'decisions.createModal.inputExpressionRequired' | translate }}\n </div>\n </form>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"form.invalid || $inputVariablesInvalid()\"\n (click)=\"submit()\"\n [attr.data-test-id]=\"testIds.submitButton\"\n >\n {{ submitKey | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [":host ::ng-deep cds-label{width:100%}.cds--modal-content{display:flex;flex-direction:column;gap:16px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i4.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i4.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i4.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i4.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i4.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: InputModule }, { kind: "component", type: i4.Label, selector: "cds-label, ibm-label", inputs: ["labelInputID", "disabled", "skeleton", "helperText", "invalidText", "invalid", "warn", "warnText", "ariaLabel"] }, { kind: "directive", type: i4.TextInput, selector: "[cdsText], [ibmText]", inputs: ["theme", "size", "invalid", "warn", "skeleton"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i4.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "directive", type: ValtimoCdsModalDirective, selector: "[valtimoCdsModal]", inputs: ["minContentHeight"] }, { kind: "ngmodule", type: CarbonMultiInputModule }, { kind: "component", type: i4$1.CarbonMultiInputComponent, selector: "valtimo-carbon-multi-input", inputs: ["addRowText", "addButtonType", "addRowTranslationKey", "arbitraryAmountTitles", "arbitraryValueAmount", "defaultValues", "deleteRowText", "deleteRowTranslationKey", "disabled", "dropdownColumnTitle", "dropdownItems", "dropdownWidth", "fullWidth", "hideAddButton", "hideDeleteButton", "initialAmountOfRows", "keyColumnTitle", "margin", "maxRows", "minimumAmountOfRows", "name", "required", "title", "titleTranslationKey", "tooltip", "type", "valueColumnTitle", "valuePathSelectorCaseDefinitionKey", "valuePathSelectorPrefixes", "valuePathSelectorShowCaseDefinitionSelector", "valuePathSelectorNotation", "keyColumnFlex", "dropdownColumnFlex", "valueColumnFlex"], outputs: ["valueChange", "allValuesValidEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
575
+ }
576
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionFormModalComponent, decorators: [{
577
+ type: Component,
578
+ args: [{ selector: 'valtimo-decision-form-modal', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
579
+ CommonModule,
580
+ ReactiveFormsModule,
581
+ TranslateModule,
582
+ ModalModule,
583
+ ButtonModule,
584
+ InputModule,
585
+ LayerModule,
586
+ ValtimoCdsModalDirective,
587
+ CarbonMultiInputModule,
588
+ ], template: "<!--\n ~ Copyright 2015-2026 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal showFooter=\"true\" valtimoCdsModal [open]=\"modalOpen$ | async\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ titleKey | translate }}</h3>\n </cds-modal-header>\n\n <form cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\">\n <div class=\"cds--text-input__field-wrapper\">\n <cds-label [invalid]=\"name.touched && name.invalid\">\n <span>{{ 'decisions.createModal.name' | translate }}</span>\n\n <input\n cdsText\n formControlName=\"name\"\n [attr.data-test-id]=\"testIds.nameInput\"\n [invalid]=\"name.touched && name.invalid\"\n placeholder=\"{{ 'decisions.createModal.namePlaceholder' | translate }}\"\n />\n </cds-label>\n\n <div *ngIf=\"name.touched && name.invalid\" class=\"cds--form-requirement\">\n {{ 'decisions.createModal.nameRequired' | translate }}\n </div>\n </div>\n\n <valtimo-carbon-multi-input\n *ngIf=\"modalOpen$ | async\"\n type=\"keyValue\"\n [attr.data-test-id]=\"testIds.inputVariables\"\n [titleTranslationKey]=\"'decisions.createModal.inputVariables'\"\n [tooltip]=\"'decisions.createModal.inputVariablesHelper' | translate\"\n [keyColumnTitle]=\"'decisions.createModal.inputExpression' | translate\"\n [valueColumnTitle]=\"'decisions.createModal.inputLabel' | translate\"\n [addRowTranslationKey]=\"'decisions.createModal.addInputVariable'\"\n [defaultValues]=\"defaultInputVariables$ | async\"\n [initialAmountOfRows]=\"1\"\n [minimumAmountOfRows]=\"1\"\n [maxRows]=\"MAX_INPUT_VARIABLES\"\n [margin]=\"true\"\n [fullWidth]=\"true\"\n (valueChange)=\"onInputVariablesChange($event)\"\n ></valtimo-carbon-multi-input>\n\n <div *ngIf=\"$inputVariablesInvalid()\" class=\"cds--form-requirement\">\n {{ 'decisions.createModal.inputExpressionRequired' | translate }}\n </div>\n </form>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"form.invalid || $inputVariablesInvalid()\"\n (click)=\"submit()\"\n [attr.data-test-id]=\"testIds.submitButton\"\n >\n {{ submitKey | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: [":host ::ng-deep cds-label{width:100%}.cds--modal-content{display:flex;flex-direction:column;gap:16px}\n/*!\n * Copyright 2015-2026 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
589
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }], propDecorators: { titleKey: [{
590
+ type: Input
591
+ }], submitKey: [{
592
+ type: Input
593
+ }], submitEvent: [{
594
+ type: Output
595
+ }] } });
596
+
243
597
  /*
244
598
  * Copyright 2015-2025 Ritense BV, the Netherlands.
245
599
  *
@@ -296,7 +650,7 @@ const EMPTY_DECISION = {
296
650
  * limitations under the License.
297
651
  */
298
652
  class DecisionModelerComponent extends PendingChangesComponent {
299
- constructor(decisionService, route, router, translateService, pageTitleService, breadcrumbService, iconService, pageHeaderService, notificationService, editPermissionsService) {
653
+ constructor(decisionService, route, router, translateService, pageTitleService, breadcrumbService, iconService, pageHeaderService, notificationService, editPermissionsService, draftVersionService) {
300
654
  super();
301
655
  this.decisionService = decisionService;
302
656
  this.route = route;
@@ -308,6 +662,7 @@ class DecisionModelerComponent extends PendingChangesComponent {
308
662
  this.pageHeaderService = pageHeaderService;
309
663
  this.notificationService = notificationService;
310
664
  this.editPermissionsService = editPermissionsService;
665
+ this.draftVersionService = draftVersionService;
311
666
  this.CLASS_NAMES = {
312
667
  drd: 'dmn-icon-lasso-tool',
313
668
  decisionTable: 'dmn-icon-decision-table',
@@ -317,6 +672,11 @@ class DecisionModelerComponent extends PendingChangesComponent {
317
672
  this.versionSelectionDisabled$ = new BehaviorSubject(true);
318
673
  this.isCreating$ = new BehaviorSubject(false);
319
674
  this.selectionId$ = new BehaviorSubject('');
675
+ this.showDeleteModal$ = new BehaviorSubject(false);
676
+ // Emits once the dmn-js editor instance has been created, so XML import can wait for it.
677
+ this._editorReady$ = new BehaviorSubject(false);
678
+ this._createSeed = null;
679
+ this._decisionKey = null;
320
680
  this.caseManagementRouteParams$ = getCaseManagementRouteParams(this.route);
321
681
  this.buildingBlockManagementRouteParams$ = getBuildingBlockManagementRouteParams(this.route);
322
682
  this.context$ = getContextObservable(this.route);
@@ -324,38 +684,74 @@ class DecisionModelerComponent extends PendingChangesComponent {
324
684
  this.compactMode$ = this.pageHeaderService.compactMode$;
325
685
  this.hasEditPermissions$ = combineLatest([
326
686
  this.caseManagementRouteParams$,
687
+ this.buildingBlockManagementRouteParams$,
327
688
  this.context$,
328
- ]).pipe(switchMap(([params, context]) => this.editPermissionsService.hasPermissionsToEditBasedOnContext(params, context ?? '')));
689
+ ]).pipe(switchMap(([caseParams, buildingBlockParams, context]) => {
690
+ // Building block decision tables can only be edited on a draft (non-final) version.
691
+ if (context === 'buildingBlock') {
692
+ return this.draftVersionService.isDraftVersionBuildingBlock(buildingBlockParams?.buildingBlockDefinitionKey ?? '', buildingBlockParams?.buildingBlockDefinitionVersionTag ?? '');
693
+ }
694
+ return this.editPermissionsService.hasPermissionsToEditBasedOnContext(caseParams, context ?? '');
695
+ }), shareReplay({ bufferSize: 1, refCount: false }));
696
+ // The editor is shown as a read-only viewer when the user cannot edit (e.g. a final case or
697
+ // building block definition) and is not creating a new decision table.
698
+ this.readOnly$ = combineLatest([
699
+ this.isCreating$,
700
+ this.hasEditPermissions$,
701
+ ]).pipe(map(([isCreating, hasEditPermissions]) => !isCreating && !hasEditPermissions));
329
702
  this.decisionId$ = this.route.params.pipe(map(params => params?.id), tap(id => {
330
703
  this.isCreating$.next(id === 'create');
331
704
  this.versionSelectionDisabled$.next(true);
332
705
  }), filter(id => !!id && id !== 'create'));
333
706
  this.decision$ = this.decisionId$.pipe(switchMap(id => this.decisionService.getDecisionById(id)), tap(decision => {
334
707
  this._fileName = decision.resource;
708
+ this._decisionKey = decision?.key ?? null;
335
709
  if (decision)
336
710
  this.selectionId$.next(decision.id);
337
711
  }));
338
712
  this.decisionTitle$ = this.decision$.pipe(map(d => d?.name || d?.key || '-'), tap(title => this.pageTitleService.setCustomPageTitle(title)));
339
713
  this._refreshDecisionSelectItems$ = new BehaviorSubject(null);
340
- this.decisionVersionSelectItems$ = this._refreshDecisionSelectItems$.pipe(switchMap(() => combineLatest([this.decision$, this.decisionService.getDecisions()])), map(([current, list]) => {
714
+ this.decisionVersionSelectItems$ = this._refreshDecisionSelectItems$.pipe(switchMap(() => combineLatest([this.decision$, this.decisionService.getUnlinkedDecisions()])), map(([current, list]) => {
341
715
  const filtered = list.filter(d => d.key === current.key);
342
716
  return [...filtered.map(d => ({ id: d.id, text: d.version.toString() }))].sort((a, b) => +(b.text ?? '') - +(a.text ?? ''));
343
717
  }), tap(() => this.versionSelectionDisabled$.next(false)));
344
- this.decisionXml$ = this.decisionId$.pipe(switchMap(id => this.decisionService.getDecisionXml(id)), tap(xml => xml && this.loadDecisionXml(xml)));
718
+ this.decisionXml$ = this.decisionId$.pipe(switchMap(id => this.decisionService.getDecisionXml(id)),
719
+ // Wait until the editor (modeler or read-only viewer) has been created before importing.
720
+ switchMap(xml => this._editorReady$.pipe(filter(Boolean), take(1), map(() => xml))), tap(xml => xml && this.loadDecisionXml(xml)));
345
721
  this.iconService.registerAll([Deploy16, Download16, ArrowLeft16]);
722
+ this._createSeed = this.extractCreateSeed();
723
+ }
724
+ extractCreateSeed() {
725
+ const navigationState = this.router.getCurrentNavigation()?.extras?.state ??
726
+ (typeof history !== 'undefined' ? history.state : undefined);
727
+ const name = navigationState?.['decisionName'];
728
+ const inputVariables = navigationState?.['inputVariables'];
729
+ if (typeof name === 'string' && name) {
730
+ return {
731
+ name,
732
+ inputVariables: Array.isArray(inputVariables)
733
+ ? inputVariables
734
+ .filter((variable) => !!variable)
735
+ .map(variable => ({
736
+ label: String(variable['label'] ?? ''),
737
+ expression: String(variable['expression'] ?? ''),
738
+ }))
739
+ : [],
740
+ };
741
+ }
742
+ return null;
346
743
  }
347
744
  ngOnInit() {
348
745
  this.pageTitleService.disableReset();
349
746
  }
350
747
  ngOnDestroy() {
748
+ this.dmnEditor?.destroy();
351
749
  this.pageTitleService.enableReset();
352
750
  this.breadcrumbService.clearThirdBreadcrumb();
353
751
  this.breadcrumbService.clearFourthBreadcrumb();
354
752
  }
355
753
  ngAfterViewInit() {
356
- this.setProperties();
357
- this.setTabEvents();
358
- this.setModelerEvents();
754
+ this.initEditor();
359
755
  this.context$.pipe(take(1)).subscribe(context => {
360
756
  if (!context)
361
757
  return;
@@ -380,7 +776,7 @@ class DecisionModelerComponent extends PendingChangesComponent {
380
776
  this._refreshDecisionSelectItems$.next(null);
381
777
  }
382
778
  deploy() {
383
- from(this.dmnModeler.saveXML({ format: true }))
779
+ from(this.dmnEditor.saveXML({ format: true }))
384
780
  .pipe(map(result => new File([result.xml], this._fileName, { type: 'text/xml' })), switchMap(file => combineLatest([of(file), this.context$])), switchMap(([file, context]) => {
385
781
  if (context === 'independent') {
386
782
  return this.decisionService.deployDmn(file);
@@ -399,7 +795,7 @@ class DecisionModelerComponent extends PendingChangesComponent {
399
795
  .subscribe();
400
796
  }
401
797
  download() {
402
- from(this.dmnModeler.saveXML({ format: true }))
798
+ from(this.dmnEditor.saveXML({ format: true }))
403
799
  .pipe(map(result => new File([result.xml], 'decision.dmn', { type: 'text/xml' })), tap(file => {
404
800
  const link = document.createElement('a');
405
801
  link.download = 'diagram.dmn';
@@ -410,11 +806,54 @@ class DecisionModelerComponent extends PendingChangesComponent {
410
806
  }))
411
807
  .subscribe();
412
808
  }
413
- navigateBack(notification, message) {
414
- this.router.navigate(['../'], { relativeTo: this.route });
415
- if (!notification)
809
+ openEditModal() {
810
+ from(this.dmnEditor.saveXML({ format: true }))
811
+ .pipe(take(1))
812
+ .subscribe(result => this.edit.open(parseDecisionForm(result.xml)));
813
+ }
814
+ onEditDecision(value) {
815
+ from(this.dmnEditor.saveXML({ format: true }))
816
+ .pipe(map(result => updateDmnXml(result.xml, value)), switchMap(xml => this.dmnEditor.importXML(xml)), tap(() => {
817
+ this.setEditor();
818
+ if (value.name)
819
+ this.pageTitleService.setCustomPageTitle(value.name);
820
+ }), catchError(() => {
821
+ this.showNotification('error', 'decisions.loadFailure');
822
+ return of(null);
823
+ }))
824
+ .subscribe();
825
+ }
826
+ onDeleteClick() {
827
+ this.showDeleteModal$.next(true);
828
+ }
829
+ onDeleteConfirm() {
830
+ const decisionKey = this._decisionKey;
831
+ if (!decisionKey)
416
832
  return;
417
- this.showNotification(notification, message);
833
+ this.context$
834
+ .pipe(take(1), switchMap(context => {
835
+ if (context === 'buildingBlock') {
836
+ return this.buildingBlockManagementRouteParams$.pipe(take(1), switchMap(params => this.decisionService.deleteBuildingBlockDecisionDefinition(params?.buildingBlockDefinitionKey ?? '', params?.buildingBlockDefinitionVersionTag ?? '', decisionKey)));
837
+ }
838
+ return this.caseManagementRouteParams$.pipe(take(1), switchMap(params => this.decisionService.deleteCaseDecisionDefinition(params?.caseDefinitionKey ?? '', params?.caseDefinitionVersionTag ?? '', decisionKey)));
839
+ }))
840
+ .subscribe({
841
+ next: () => {
842
+ this.navigateBack();
843
+ this.showNotification('success', 'decisions.deleteSuccess');
844
+ },
845
+ error: () => this.showNotification('error', 'decisions.deleteFailure'),
846
+ });
847
+ }
848
+ navigateBack() {
849
+ this.context$.pipe(take(1)).subscribe(context => {
850
+ if (context === 'independent') {
851
+ this.router.navigate(['/decision-tables']);
852
+ }
853
+ else {
854
+ this.router.navigate(['../'], { relativeTo: this.route });
855
+ }
856
+ });
418
857
  }
419
858
  showNotification(notification, message) {
420
859
  if (!notification)
@@ -425,28 +864,53 @@ class DecisionModelerComponent extends PendingChangesComponent {
425
864
  title: this.translateService.instant(`interface.${notification}`),
426
865
  });
427
866
  }
428
- setProperties() {
429
- const isCreating = this.isCreating$.getValue();
867
+ initEditor() {
868
+ // A new decision table is always created in the editable modeler. For existing tables the
869
+ // edit permissions decide whether to render the editable modeler or a read-only viewer.
870
+ if (this.route.snapshot.params?.['id'] === 'create') {
871
+ this.createEditor(false);
872
+ this.loadEmptyDecisionTable();
873
+ return;
874
+ }
875
+ this.hasEditPermissions$
876
+ .pipe(take(1))
877
+ .subscribe(hasEditPermissions => this.createEditor(!hasEditPermissions));
878
+ }
879
+ createEditor(readOnly) {
430
880
  this.$container = $('.editor-container');
431
881
  this.$tabs = $('.editor-tabs');
432
- this.dmnModeler = new DmnJS({
433
- container: this.$container,
434
- height: 500,
435
- width: '100%',
436
- keyboard: { bindTo: window },
437
- });
438
- if (isCreating)
439
- this.loadEmptyDecisionTable();
882
+ this.dmnEditor = readOnly
883
+ ? new DmnViewer({
884
+ container: this.$container,
885
+ height: 500,
886
+ width: '100%',
887
+ })
888
+ : new DmnJS({
889
+ container: this.$container,
890
+ height: 500,
891
+ width: '100%',
892
+ keyboard: { bindTo: window },
893
+ });
894
+ this.setTabEvents();
895
+ this.setModelerEvents();
896
+ this._editorReady$.next(true);
440
897
  }
441
898
  loadEmptyDecisionTable() {
899
+ if (this._createSeed) {
900
+ this._fileName = toDecisionFileName(this._createSeed.name);
901
+ this.pageTitleService.setCustomPageTitle(this._createSeed.name);
902
+ this.loadDecisionXml(createDmnXml(this._createSeed));
903
+ return;
904
+ }
905
+ this._fileName = 'decision.dmn';
442
906
  this.loadDecisionXml(EMPTY_DECISION);
443
907
  }
444
908
  setTabEvents() {
445
909
  this.$tabs.delegate('.tab', 'click', async (event) => {
446
910
  const index = +event.currentTarget.getAttribute('data-id');
447
- const view = this.dmnModeler.getViews()[index];
911
+ const view = this.dmnEditor.getViews()[index];
448
912
  try {
449
- await this.dmnModeler.open(view);
913
+ await this.dmnEditor.open(view);
450
914
  }
451
915
  catch (err) {
452
916
  console.error('tab open error', err);
@@ -454,7 +918,7 @@ class DecisionModelerComponent extends PendingChangesComponent {
454
918
  });
455
919
  }
456
920
  setModelerEvents() {
457
- this.dmnModeler.on('views.changed', event => {
921
+ this.dmnEditor.on('views.changed', event => {
458
922
  const { views, activeView } = event;
459
923
  this.$tabs.empty();
460
924
  views.forEach((v, i) => {
@@ -465,7 +929,7 @@ class DecisionModelerComponent extends PendingChangesComponent {
465
929
  });
466
930
  }
467
931
  loadDecisionXml(decision) {
468
- from(this.dmnModeler.importXML(decision.dmnXml))
932
+ from(this.dmnEditor.importXML(decision.dmnXml))
469
933
  .pipe(tap(() => this.setEditor()), catchError(() => {
470
934
  this.migrateAndLoadDecisionXml(decision);
471
935
  return of(null);
@@ -474,16 +938,16 @@ class DecisionModelerComponent extends PendingChangesComponent {
474
938
  }
475
939
  migrateAndLoadDecisionXml(decision) {
476
940
  from(migrateDiagram(decision.dmnXml))
477
- .pipe(switchMap(xml => this.dmnModeler.importXML(xml)), tap(() => this.setEditor()), catchError(() => {
941
+ .pipe(switchMap(xml => this.dmnEditor.importXML(xml)), tap(() => this.setEditor()), catchError(() => {
478
942
  this.showNotification('error', 'decisions.loadFailure');
479
943
  return of(null);
480
944
  }))
481
945
  .subscribe();
482
946
  }
483
947
  setEditor() {
484
- const view = this.dmnModeler.getActiveView();
948
+ const view = this.dmnEditor.getActiveView();
485
949
  if (view?.type === 'drd') {
486
- const canvas = this.dmnModeler.getActiveViewer().get('canvas');
950
+ const canvas = this.dmnEditor.getActiveViewer().get('canvas');
487
951
  canvas.zoom('fit-viewport');
488
952
  }
489
953
  }
@@ -518,8 +982,8 @@ class DecisionModelerComponent extends PendingChangesComponent {
518
982
  href: routeWithDecisions,
519
983
  });
520
984
  }
521
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionModelerComponent, deps: [{ token: DecisionService }, { token: i2.ActivatedRoute }, { token: i2.Router }, { token: i3.TranslateService }, { token: i4.PageTitleService }, { token: i4.BreadcrumbService }, { token: i6$1.IconService }, { token: i4.PageHeaderService }, { token: i6.GlobalNotificationService }, { token: i6.EditPermissionsService }], target: i0.ɵɵFactoryTarget.Component }); }
522
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: DecisionModelerComponent, isStandalone: true, selector: "valtimo-decision-modeler", usesInheritance: 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 *ngIf=\"{\n decisionXml: decisionXml$ | async,\n decisionTitle: decisionTitle$ | async,\n } as obs\"\n fitPage\n [disableOverflow]=\"true\"\n class=\"dmn-editor\"\n>\n <ng-container *ngTemplateOutlet=\"diagram\"></ng-container>\n</div>\n\n<ng-template #diagram>\n <div class=\"editor-parent\">\n <div class=\"editor-container\"></div>\n <div class=\"editor-tabs\"></div>\n </div>\n</ng-template>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n selectionId: selectionId$ | async,\n isCreating: isCreating$ | async,\n context: context$ | async,\n compactMode: compactMode$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n } as obs\"\n class=\"decision-modeler-actions\"\n >\n <ng-container *ngTemplateOutlet=\"versionSelection\"></ng-container>\n\n <button\n *ngIf=\"obs.context === 'case'\"\n cdsButton=\"secondary\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n [attr.data-test-id]=\"testIds.backButton\"\n >\n <svg class=\"cds--btn__icon\" cdsIcon=\"arrow--left\" size=\"16\"></svg>\n\n <span>{{ 'interface.back' | translate }}</span>\n </button>\n\n @if (obs.selectionId && !obs.isCreating) {\n <button\n *ngIf=\"obs.hasEditPermissions\"\n cdsButton=\"primary\"\n (click)=\"deploy()\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'decisions.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 (selected)=\"download()\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n } @else {\n <button class=\"btn btn-success btn-space\" (click)=\"deploy()\">\n <i class=\"icon mdi mdi-upload mr-1\"></i>{{ 'decisions.deploy' | translate }}\n </button>\n }\n </div>\n </ng-template>\n</ng-container>\n\n<ng-template #versionSelection>\n <ng-container\n *ngIf=\"{\n selectItems: (decisionVersionSelectItems$ | async) || [],\n isIndependent: isIndependent$ | async,\n versionSelectionDisabled: versionSelectionDisabled$ | async,\n selectionId: selectionId$ | async,\n } as obs\"\n >\n <v-select\n *ngIf=\"obs.isIndependent\"\n name=\"version\"\n [title]=\"'decisions.version' | translate\"\n [disabled]=\"obs.versionSelectionDisabled\"\n [clearable]=\"false\"\n [loading]=\"obs.selectItems.length === 0\"\n [items]=\"obs.selectItems\"\n [defaultSelectionId]=\"obs.selectionId\"\n [widthInPx]=\"120\"\n (selectedChange)=\"switchVersion($event)\"\n ></v-select>\n </ng-container>\n</ng-template>\n", styles: ["#save-button{position:absolute;bottom:10px;left:10px;background:#fff;border:solid 1px #ccc;border-radius:2px;padding:8px;font-family:Arial,sans-serif;font-weight:700;cursor:default;font-size:14px;color:#444}.dmn-modeler{display:flex;flex-direction:column;width:100%;padding:1rem}.diagram,.diagram-header{border:1px solid #dee2e6}.decision-title{color:#6b6b6b;font-size:1.5rem;margin:0}.fullscreen-toggle{font-size:2rem}.fullscreen-toggle>i{cursor:pointer}.dmn-editor{background-color:var(--cds-layer);outline:1px solid var(--cds-border-subtle);outline-offset:-1px;padding:16px}.decision-modeler-actions{display:flex;width:100%;justify-content:flex-end;align-items:flex-end;gap:16px}\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: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: ModalModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: WidgetModule }, { kind: "ngmodule", type: SelectModule$1 }, { kind: "component", type: i4.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "directive", type: RenderInPageHeaderDirective, selector: "[renderInPageHeader]", inputs: ["fullWidth"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i6$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "directive", type: FitPageDirective, selector: "[fitPage]", inputs: ["spaceAdjustment", "fitPageDisabled", "disableOverflow"] }, { 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"] }] }); }
985
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionModelerComponent, deps: [{ token: DecisionService }, { token: i2.ActivatedRoute }, { token: i2.Router }, { token: i3.TranslateService }, { token: i4$1.PageTitleService }, { token: i4$1.BreadcrumbService }, { token: i4.IconService }, { token: i4$1.PageHeaderService }, { token: i6.GlobalNotificationService }, { token: i6.EditPermissionsService }, { token: i6.DraftVersionService }], target: i0.ɵɵFactoryTarget.Component }); }
986
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: DecisionModelerComponent, isStandalone: true, selector: "valtimo-decision-modeler", viewQueries: [{ propertyName: "edit", first: true, predicate: ["decisionEdit"], descendants: true }], usesInheritance: 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 *ngIf=\"{\n decisionXml: decisionXml$ | async,\n decisionTitle: decisionTitle$ | async,\n } as obs\"\n fitPage\n [disableOverflow]=\"true\"\n class=\"dmn-editor\"\n>\n <ng-container *ngTemplateOutlet=\"diagram\"></ng-container>\n</div>\n\n<ng-template #diagram>\n <div class=\"editor-parent\">\n <div class=\"editor-container\"></div>\n <div class=\"editor-tabs\"></div>\n </div>\n</ng-template>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n selectionId: selectionId$ | async,\n isCreating: isCreating$ | async,\n context: context$ | async,\n compactMode: compactMode$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n readOnly: readOnly$ | async,\n } as obs\"\n class=\"decision-modeler-actions\"\n >\n <cds-tag *ngIf=\"obs.readOnly\" type=\"blue\" [attr.data-test-id]=\"testIds.readOnlyTag\">{{\n 'decisions.readOnly' | translate\n }}</cds-tag>\n\n <ng-container *ngTemplateOutlet=\"versionSelection\"></ng-container>\n\n <button\n *ngIf=\"obs.context === 'case' || obs.isCreating\"\n cdsButton=\"secondary\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack()\"\n [attr.data-test-id]=\"testIds.backButton\"\n >\n <svg class=\"cds--btn__icon\" cdsIcon=\"arrow--left\" size=\"16\"></svg>\n\n <span>{{ 'interface.back' | translate }}</span>\n </button>\n\n @if (obs.selectionId && !obs.isCreating) {\n <button\n cdsButton=\"primary\"\n [disabled]=\"!obs.hasEditPermissions\"\n (click)=\"deploy()\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'decisions.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 [disabled]=\"!obs.hasEditPermissions\" (selected)=\"openEditModal()\"\n >{{ 'interface.edit' | translate }}\n </v-overflow-menu-option>\n <v-overflow-menu-option (selected)=\"download()\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n <v-overflow-menu-option\n [disabled]=\"!obs.hasEditPermissions || obs.context === 'independent'\"\n type=\"danger\"\n (selected)=\"onDeleteClick()\"\n >{{ 'interface.delete' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n } @else {\n <button\n cdsButton=\"primary\"\n [disabled]=\"!obs.hasEditPermissions\"\n (click)=\"deploy()\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'decisions.deploy' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"deploy\" size=\"16\"></svg>\n </button>\n }\n </div>\n </ng-template>\n</ng-container>\n\n<ng-template #versionSelection>\n <ng-container\n *ngIf=\"{\n selectItems: (decisionVersionSelectItems$ | async) || [],\n isIndependent: isIndependent$ | async,\n versionSelectionDisabled: versionSelectionDisabled$ | async,\n selectionId: selectionId$ | async,\n } as obs\"\n >\n <v-select\n *ngIf=\"obs.isIndependent\"\n name=\"version\"\n [title]=\"'decisions.version' | translate\"\n [disabled]=\"obs.versionSelectionDisabled\"\n [clearable]=\"false\"\n [loading]=\"obs.selectItems.length === 0\"\n [items]=\"obs.selectItems\"\n [defaultSelectionId]=\"obs.selectionId\"\n [widthInPx]=\"120\"\n (selectedChange)=\"switchVersion($event)\"\n ></v-select>\n </ng-container>\n</ng-template>\n\n<valtimo-decision-form-modal\n #decisionEdit\n titleKey=\"decisions.editModal.title\"\n submitKey=\"interface.save\"\n (submitEvent)=\"onEditDecision($event)\"\n></valtimo-decision-form-modal>\n\n<valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"decisions.deleteModal.content\"\n [showModalSubject$]=\"showDeleteModal$\"\n titleTranslationKey=\"decisions.deleteModal.title\"\n (confirmEvent)=\"onDeleteConfirm()\"\n></valtimo-confirmation-modal>\n", styles: ["#save-button{position:absolute;bottom:10px;left:10px;background:#fff;border:solid 1px #ccc;border-radius:2px;padding:8px;font-family:Arial,sans-serif;font-weight:700;cursor:default;font-size:14px;color:#444}.dmn-modeler{display:flex;flex-direction:column;width:100%;padding:1rem}.diagram,.diagram-header{border:1px solid #dee2e6}.decision-title{color:#6b6b6b;font-size:1.5rem;margin:0}.fullscreen-toggle{font-size:2rem}.fullscreen-toggle>i{cursor:pointer}.dmn-editor{background-color:var(--cds-layer);outline:1px solid var(--cds-border-subtle);outline-offset:-1px;padding:16px}.decision-modeler-actions{display:flex;width:100%;justify-content:flex-end;align-items:flex-end;gap:16px}\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: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: ModalModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: WidgetModule }, { kind: "ngmodule", type: SelectModule$1 }, { kind: "component", type: i4$1.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "directive", type: RenderInPageHeaderDirective, selector: "[renderInPageHeader]", inputs: ["fullWidth"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i4.Tag, selector: "cds-tag, ibm-tag", inputs: ["type", "size", "class", "skeleton"] }, { kind: "directive", type: FitPageDirective, selector: "[fitPage]", inputs: ["spaceAdjustment", "fitPageDisabled", "disableOverflow", "bottomMargin"] }, { 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: "component", type: DecisionFormModalComponent, selector: "valtimo-decision-form-modal", inputs: ["titleKey", "submitKey"], outputs: ["submitEvent"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i4$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"] }] }); }
523
987
  }
524
988
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionModelerComponent, decorators: [{
525
989
  type: Component,
@@ -534,12 +998,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
534
998
  RenderInPageHeaderDirective,
535
999
  ButtonModule,
536
1000
  IconModule,
1001
+ TagModule,
537
1002
  FitPageDirective,
538
1003
  OverflowMenuComponent,
539
1004
  OverflowMenuOptionComponent,
540
1005
  OverflowMenuTriggerComponent,
541
- ], 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 *ngIf=\"{\n decisionXml: decisionXml$ | async,\n decisionTitle: decisionTitle$ | async,\n } as obs\"\n fitPage\n [disableOverflow]=\"true\"\n class=\"dmn-editor\"\n>\n <ng-container *ngTemplateOutlet=\"diagram\"></ng-container>\n</div>\n\n<ng-template #diagram>\n <div class=\"editor-parent\">\n <div class=\"editor-container\"></div>\n <div class=\"editor-tabs\"></div>\n </div>\n</ng-template>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n selectionId: selectionId$ | async,\n isCreating: isCreating$ | async,\n context: context$ | async,\n compactMode: compactMode$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n } as obs\"\n class=\"decision-modeler-actions\"\n >\n <ng-container *ngTemplateOutlet=\"versionSelection\"></ng-container>\n\n <button\n *ngIf=\"obs.context === 'case'\"\n cdsButton=\"secondary\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack(null)\"\n [attr.data-test-id]=\"testIds.backButton\"\n >\n <svg class=\"cds--btn__icon\" cdsIcon=\"arrow--left\" size=\"16\"></svg>\n\n <span>{{ 'interface.back' | translate }}</span>\n </button>\n\n @if (obs.selectionId && !obs.isCreating) {\n <button\n *ngIf=\"obs.hasEditPermissions\"\n cdsButton=\"primary\"\n (click)=\"deploy()\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'decisions.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 (selected)=\"download()\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n } @else {\n <button class=\"btn btn-success btn-space\" (click)=\"deploy()\">\n <i class=\"icon mdi mdi-upload mr-1\"></i>{{ 'decisions.deploy' | translate }}\n </button>\n }\n </div>\n </ng-template>\n</ng-container>\n\n<ng-template #versionSelection>\n <ng-container\n *ngIf=\"{\n selectItems: (decisionVersionSelectItems$ | async) || [],\n isIndependent: isIndependent$ | async,\n versionSelectionDisabled: versionSelectionDisabled$ | async,\n selectionId: selectionId$ | async,\n } as obs\"\n >\n <v-select\n *ngIf=\"obs.isIndependent\"\n name=\"version\"\n [title]=\"'decisions.version' | translate\"\n [disabled]=\"obs.versionSelectionDisabled\"\n [clearable]=\"false\"\n [loading]=\"obs.selectItems.length === 0\"\n [items]=\"obs.selectItems\"\n [defaultSelectionId]=\"obs.selectionId\"\n [widthInPx]=\"120\"\n (selectedChange)=\"switchVersion($event)\"\n ></v-select>\n </ng-container>\n</ng-template>\n", styles: ["#save-button{position:absolute;bottom:10px;left:10px;background:#fff;border:solid 1px #ccc;border-radius:2px;padding:8px;font-family:Arial,sans-serif;font-weight:700;cursor:default;font-size:14px;color:#444}.dmn-modeler{display:flex;flex-direction:column;width:100%;padding:1rem}.diagram,.diagram-header{border:1px solid #dee2e6}.decision-title{color:#6b6b6b;font-size:1.5rem;margin:0}.fullscreen-toggle{font-size:2rem}.fullscreen-toggle>i{cursor:pointer}.dmn-editor{background-color:var(--cds-layer);outline:1px solid var(--cds-border-subtle);outline-offset:-1px;padding:16px}.decision-modeler-actions{display:flex;width:100%;justify-content:flex-end;align-items:flex-end;gap:16px}\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"] }]
542
- }], ctorParameters: () => [{ type: DecisionService }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i3.TranslateService }, { type: i4.PageTitleService }, { type: i4.BreadcrumbService }, { type: i6$1.IconService }, { type: i4.PageHeaderService }, { type: i6.GlobalNotificationService }, { type: i6.EditPermissionsService }] });
1006
+ DecisionFormModalComponent,
1007
+ ConfirmationModalModule,
1008
+ ], 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 *ngIf=\"{\n decisionXml: decisionXml$ | async,\n decisionTitle: decisionTitle$ | async,\n } as obs\"\n fitPage\n [disableOverflow]=\"true\"\n class=\"dmn-editor\"\n>\n <ng-container *ngTemplateOutlet=\"diagram\"></ng-container>\n</div>\n\n<ng-template #diagram>\n <div class=\"editor-parent\">\n <div class=\"editor-container\"></div>\n <div class=\"editor-tabs\"></div>\n </div>\n</ng-template>\n\n<ng-container renderInPageHeader>\n <ng-template>\n <div\n *ngIf=\"{\n selectionId: selectionId$ | async,\n isCreating: isCreating$ | async,\n context: context$ | async,\n compactMode: compactMode$ | async,\n hasEditPermissions: hasEditPermissions$ | async,\n readOnly: readOnly$ | async,\n } as obs\"\n class=\"decision-modeler-actions\"\n >\n <cds-tag *ngIf=\"obs.readOnly\" type=\"blue\" [attr.data-test-id]=\"testIds.readOnlyTag\">{{\n 'decisions.readOnly' | translate\n }}</cds-tag>\n\n <ng-container *ngTemplateOutlet=\"versionSelection\"></ng-container>\n\n <button\n *ngIf=\"obs.context === 'case' || obs.isCreating\"\n cdsButton=\"secondary\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n (click)=\"navigateBack()\"\n [attr.data-test-id]=\"testIds.backButton\"\n >\n <svg class=\"cds--btn__icon\" cdsIcon=\"arrow--left\" size=\"16\"></svg>\n\n <span>{{ 'interface.back' | translate }}</span>\n </button>\n\n @if (obs.selectionId && !obs.isCreating) {\n <button\n cdsButton=\"primary\"\n [disabled]=\"!obs.hasEditPermissions\"\n (click)=\"deploy()\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'decisions.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 [disabled]=\"!obs.hasEditPermissions\" (selected)=\"openEditModal()\"\n >{{ 'interface.edit' | translate }}\n </v-overflow-menu-option>\n <v-overflow-menu-option (selected)=\"download()\"\n >{{ 'interface.export' | translate }}\n </v-overflow-menu-option>\n <v-overflow-menu-option\n [disabled]=\"!obs.hasEditPermissions || obs.context === 'independent'\"\n type=\"danger\"\n (selected)=\"onDeleteClick()\"\n >{{ 'interface.delete' | translate }}\n </v-overflow-menu-option>\n </v-overflow-menu>\n } @else {\n <button\n cdsButton=\"primary\"\n [disabled]=\"!obs.hasEditPermissions\"\n (click)=\"deploy()\"\n [size]=\"obs.compactMode ? 'sm' : 'md'\"\n [attr.data-test-id]=\"testIds.deployButton\"\n >\n {{ 'decisions.deploy' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"deploy\" size=\"16\"></svg>\n </button>\n }\n </div>\n </ng-template>\n</ng-container>\n\n<ng-template #versionSelection>\n <ng-container\n *ngIf=\"{\n selectItems: (decisionVersionSelectItems$ | async) || [],\n isIndependent: isIndependent$ | async,\n versionSelectionDisabled: versionSelectionDisabled$ | async,\n selectionId: selectionId$ | async,\n } as obs\"\n >\n <v-select\n *ngIf=\"obs.isIndependent\"\n name=\"version\"\n [title]=\"'decisions.version' | translate\"\n [disabled]=\"obs.versionSelectionDisabled\"\n [clearable]=\"false\"\n [loading]=\"obs.selectItems.length === 0\"\n [items]=\"obs.selectItems\"\n [defaultSelectionId]=\"obs.selectionId\"\n [widthInPx]=\"120\"\n (selectedChange)=\"switchVersion($event)\"\n ></v-select>\n </ng-container>\n</ng-template>\n\n<valtimo-decision-form-modal\n #decisionEdit\n titleKey=\"decisions.editModal.title\"\n submitKey=\"interface.save\"\n (submitEvent)=\"onEditDecision($event)\"\n></valtimo-decision-form-modal>\n\n<valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"decisions.deleteModal.content\"\n [showModalSubject$]=\"showDeleteModal$\"\n titleTranslationKey=\"decisions.deleteModal.title\"\n (confirmEvent)=\"onDeleteConfirm()\"\n></valtimo-confirmation-modal>\n", styles: ["#save-button{position:absolute;bottom:10px;left:10px;background:#fff;border:solid 1px #ccc;border-radius:2px;padding:8px;font-family:Arial,sans-serif;font-weight:700;cursor:default;font-size:14px;color:#444}.dmn-modeler{display:flex;flex-direction:column;width:100%;padding:1rem}.diagram,.diagram-header{border:1px solid #dee2e6}.decision-title{color:#6b6b6b;font-size:1.5rem;margin:0}.fullscreen-toggle{font-size:2rem}.fullscreen-toggle>i{cursor:pointer}.dmn-editor{background-color:var(--cds-layer);outline:1px solid var(--cds-border-subtle);outline-offset:-1px;padding:16px}.decision-modeler-actions{display:flex;width:100%;justify-content:flex-end;align-items:flex-end;gap:16px}\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"] }]
1009
+ }], ctorParameters: () => [{ type: DecisionService }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i3.TranslateService }, { type: i4$1.PageTitleService }, { type: i4$1.BreadcrumbService }, { type: i4.IconService }, { type: i4$1.PageHeaderService }, { type: i6.GlobalNotificationService }, { type: i6.EditPermissionsService }, { type: i6.DraftVersionService }], propDecorators: { edit: [{
1010
+ type: ViewChild,
1011
+ args: ['decisionEdit']
1012
+ }] } });
543
1013
 
544
1014
  /*
545
1015
  * Copyright 2015-2025 Ritense BV, the Netherlands.
@@ -562,7 +1032,7 @@ class DecisionDisplayComponent {
562
1032
  this.route = route;
563
1033
  }
564
1034
  ngOnInit() {
565
- this.viewer = new DmnViewer({
1035
+ this.viewer = new DmnViewer$1({
566
1036
  container: '#canvas',
567
1037
  });
568
1038
  this.decisionId = this.route.snapshot.paramMap.get('id');
@@ -698,8 +1168,8 @@ class DecisionDeployComponent {
698
1168
  closeModal() {
699
1169
  this.modalOpen$.next(false);
700
1170
  }
701
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionDeployComponent, deps: [{ token: DecisionService }, { token: DecisionStateService }, { token: i2.ActivatedRoute }, { token: i3$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
702
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DecisionDeployComponent, isStandalone: true, selector: "valtimo-decision-deploy", outputs: { deploySuccessful: "deploySuccessful" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal showFooter=\"true\" valtimoCdsModal [open]=\"modalOpen$ | async\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ 'decisions.upload.title' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\">\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [multiple]=\"false\"\n buttonType=\"primary\"\n [title]=\"'decisions.upload.fileUploaderTitle' | translate\"\n [description]=\"'decisions.upload.fileUploaderDescription' | translate\"\n [buttonText]=\"'decisions.upload.fileUploaderButton' | translate\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"!selectedDmnFile\"\n (click)=\"deployDmn()\"\n [attr.data-test-id]=\"testIds.submitButton\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i6$1.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i6$1.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i6$1.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i6$1.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i6$1.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i6$1.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: FileUploaderModule }, { kind: "component", type: i6$1.FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: ["buttonText", "buttonType", "title", "description", "accept", "multiple", "skeleton", "size", "fileItemSize", "drop", "dropText", "fileUploaderId", "files", "disabled"], outputs: ["filesChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
1171
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionDeployComponent, deps: [{ token: DecisionService }, { token: DecisionStateService }, { token: i2.ActivatedRoute }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
1172
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DecisionDeployComponent, isStandalone: true, selector: "valtimo-decision-deploy", outputs: { deploySuccessful: "deploySuccessful" }, ngImport: i0, template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal showFooter=\"true\" valtimoCdsModal [open]=\"modalOpen$ | async\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ 'decisions.upload.title' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\">\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [multiple]=\"false\"\n buttonType=\"primary\"\n [title]=\"'decisions.upload.fileUploaderTitle' | translate\"\n [description]=\"'decisions.upload.fileUploaderDescription' | translate\"\n [buttonText]=\"'decisions.upload.fileUploaderButton' | translate\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"!selectedDmnFile\"\n (click)=\"deployDmn()\"\n [attr.data-test-id]=\"testIds.submitButton\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ModalModule }, { kind: "component", type: i4.Modal, selector: "cds-modal, ibm-modal", inputs: ["size", "theme", "ariaLabel", "open", "trigger", "hasScrollingContent"], outputs: ["overlaySelected", "close"] }, { kind: "component", type: i4.ModalHeader, selector: "cds-modal-header, ibm-modal-header", inputs: ["theme", "closeLabel", "showCloseButton"], outputs: ["closeSelect"] }, { kind: "component", type: i4.ModalFooter, selector: "cds-modal-footer, ibm-modal-footer" }, { kind: "directive", type: i4.ModalContent, selector: "[cdsModalContent], [ibmModalContent]", inputs: ["hasForm"] }, { kind: "directive", type: i4.ModalHeaderHeading, selector: "[cdsModalHeaderHeading], [ibmModalHeaderHeading]" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "ngmodule", type: LayerModule }, { kind: "directive", type: i4.LayerDirective, selector: "[cdsLayer], [ibmLayer]", inputs: ["ibmLayer", "cdsLayer"], exportAs: ["layer"] }, { kind: "ngmodule", type: FileUploaderModule }, { kind: "component", type: i4.FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: ["buttonText", "buttonType", "title", "description", "accept", "multiple", "skeleton", "size", "fileItemSize", "drop", "dropText", "fileUploaderId", "files", "disabled"], outputs: ["filesChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
703
1173
  }
704
1174
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionDeployComponent, decorators: [{
705
1175
  type: Component,
@@ -713,7 +1183,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
713
1183
  FileUploaderModule,
714
1184
  ReactiveFormsModule,
715
1185
  ], template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<cds-modal showFooter=\"true\" valtimoCdsModal [open]=\"modalOpen$ | async\" (close)=\"closeModal()\">\n <cds-modal-header showCloseButton=\"true\" (closeSelect)=\"closeModal()\">\n <h3 cdsModalHeaderHeading>{{ 'decisions.upload.title' | translate }}</h3>\n </cds-modal-header>\n\n <section cdsModalContent [cdsLayer]=\"1\" [formGroup]=\"form\">\n <cds-file-uploader\n [accept]=\"ACCEPTED_FILES\"\n [multiple]=\"false\"\n buttonType=\"primary\"\n [title]=\"'decisions.upload.fileUploaderTitle' | translate\"\n [description]=\"'decisions.upload.fileUploaderDescription' | translate\"\n [buttonText]=\"'decisions.upload.fileUploaderButton' | translate\"\n formControlName=\"file\"\n >\n </cds-file-uploader>\n </section>\n\n <cds-modal-footer>\n <button cdsButton=\"secondary\" (click)=\"closeModal()\">\n {{ 'interface.cancel' | translate }}\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"!selectedDmnFile\"\n (click)=\"deployDmn()\"\n [attr.data-test-id]=\"testIds.submitButton\"\n >\n {{ 'interface.upload' | translate }}\n </button>\n </cds-modal-footer>\n</cds-modal>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
716
- }], ctorParameters: () => [{ type: DecisionService }, { type: DecisionStateService }, { type: i2.ActivatedRoute }, { type: i3$1.FormBuilder }], propDecorators: { deploySuccessful: [{
1186
+ }], ctorParameters: () => [{ type: DecisionService }, { type: DecisionStateService }, { type: i2.ActivatedRoute }, { type: i1$1.FormBuilder }], propDecorators: { deploySuccessful: [{
717
1187
  type: Output
718
1188
  }] } });
719
1189
 
@@ -733,22 +1203,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
733
1203
  * limitations under the License.
734
1204
  */
735
1205
  class DecisionListComponent {
736
- constructor(decisionService, iconService, router, configService, stateService, route, cdr, editPermissionsService) {
1206
+ constructor(decisionService, iconService, router, stateService, route, cdr, editPermissionsService, notificationService, translateService) {
737
1207
  this.decisionService = decisionService;
738
1208
  this.iconService = iconService;
739
1209
  this.router = router;
740
- this.configService = configService;
741
1210
  this.stateService = stateService;
742
1211
  this.route = route;
743
1212
  this.cdr = cdr;
744
1213
  this.editPermissionsService = editPermissionsService;
1214
+ this.notificationService = notificationService;
1215
+ this.translateService = translateService;
745
1216
  this.fields = [
746
1217
  { key: 'key', label: 'Key' },
747
1218
  { key: 'name', label: 'Name' },
748
1219
  { key: 'version', label: 'Version' },
749
1220
  ];
1221
+ this.ACTION_ITEMS = [
1222
+ {
1223
+ label: 'interface.edit',
1224
+ callback: this.openEditModal.bind(this),
1225
+ type: 'normal',
1226
+ disabled$: () => this.hasEditPermissions$.pipe(map(canEdit => !canEdit)),
1227
+ },
1228
+ {
1229
+ label: 'interface.delete',
1230
+ callback: this.onDeleteClick.bind(this),
1231
+ type: 'danger',
1232
+ disabled$: () => this.hasEditPermissions$.pipe(map(canEdit => !canEdit || this._context !== 'case')),
1233
+ },
1234
+ ];
1235
+ this.showDeleteModal$ = new BehaviorSubject(false);
750
1236
  this.loading$ = new BehaviorSubject(true);
751
- this.experimentalEditing$ = this.configService.getFeatureToggleObservable('experimentalDmnEditing');
752
1237
  this.testIds = DECISION_LIST_TEST_IDS;
753
1238
  this.caseManagementRouteParams$ = getCaseManagementRouteParams(this.route);
754
1239
  this.buildingBlockManagementRouteParams$ = getBuildingBlockManagementRouteParams(this.route);
@@ -760,7 +1245,7 @@ class DecisionListComponent {
760
1245
  if (context === 'buildingBlock') {
761
1246
  return this.buildingBlockManagementRouteParams$.pipe(switchMap(params => this.decisionService.listBuildingBlockDecisionDefinitions(params.buildingBlockDefinitionKey, params.buildingBlockDefinitionVersionTag)));
762
1247
  }
763
- return this.decisionService.getDecisions();
1248
+ return this.decisionService.getUnlinkedDecisions();
764
1249
  }), map(filterLatestDecisionVersions), tap(() => {
765
1250
  this.loading$.next(false);
766
1251
  this.cdr.detectChanges();
@@ -771,30 +1256,110 @@ class DecisionListComponent {
771
1256
  ]).pipe(switchMap(([params, context]) => {
772
1257
  return this.editPermissionsService.hasPermissionsToEditBasedOnContext(params, context);
773
1258
  }));
774
- this.iconService.registerAll([Upload16]);
1259
+ this._editDecision = null;
1260
+ this._editXml = null;
1261
+ this._decisionToDelete = null;
1262
+ this._context = null;
1263
+ this.iconService.registerAll([Upload16, Add16]);
1264
+ this.context$.pipe(take(1)).subscribe(context => (this._context = context));
775
1265
  }
776
1266
  viewDecisionTable(decision) {
777
- combineLatest([this.context$, this.experimentalEditing$])
778
- .pipe(take(1))
779
- .subscribe(([context, experimentalEditing]) => {
780
- if (context === 'independent') {
781
- const basePath = experimentalEditing ? '/decision-tables/edit/' : '/decision-tables/';
782
- this.router.navigate([basePath + decision.id]);
783
- }
784
- else if (context === 'buildingBlock') {
1267
+ this.context$.pipe(take(1)).subscribe(context => {
1268
+ if (context === 'buildingBlock') {
785
1269
  this.buildingBlockManagementRouteParams$.pipe(take(1)).subscribe(params => {
786
1270
  this.router.navigateByUrl(`building-block-management/building-block/${params.buildingBlockDefinitionKey}/version/${params.buildingBlockDefinitionVersionTag}/decisions/${decision.id}`);
787
1271
  });
788
1272
  }
789
- else {
1273
+ else if (context === 'case') {
790
1274
  this.caseManagementRouteParams$.pipe(take(1)).subscribe(params => {
791
1275
  this.router.navigateByUrl(`case-management/case/${params.caseDefinitionKey}/version/${params.caseDefinitionVersionTag}/decisions/${decision.id}`);
792
1276
  });
793
1277
  }
1278
+ else {
1279
+ this.router.navigate(['/decision-tables/edit/' + decision.id]);
1280
+ }
1281
+ });
1282
+ }
1283
+ onCreateDecision(value) {
1284
+ const state = { decisionName: value.name, inputVariables: value.inputVariables };
1285
+ this.context$.pipe(take(1)).subscribe(context => {
1286
+ if (context === 'buildingBlock') {
1287
+ this.buildingBlockManagementRouteParams$.pipe(take(1)).subscribe(params => {
1288
+ this.router.navigateByUrl(`building-block-management/building-block/${params.buildingBlockDefinitionKey}/version/${params.buildingBlockDefinitionVersionTag}/decisions/create`, { state });
1289
+ });
1290
+ }
1291
+ else if (context === 'case') {
1292
+ this.caseManagementRouteParams$.pipe(take(1)).subscribe(params => {
1293
+ this.router.navigateByUrl(`case-management/case/${params.caseDefinitionKey}/version/${params.caseDefinitionVersionTag}/decisions/create`, { state });
1294
+ });
1295
+ }
1296
+ else {
1297
+ this.router.navigate(['/decision-tables/edit/create'], { state });
1298
+ }
1299
+ });
1300
+ }
1301
+ openEditModal(decision) {
1302
+ this.decisionService
1303
+ .getDecisionXml(decision.id)
1304
+ .pipe(take(1))
1305
+ .subscribe(xml => {
1306
+ this._editDecision = decision;
1307
+ this._editXml = xml.dmnXml;
1308
+ this.edit.open(parseDecisionForm(xml.dmnXml));
1309
+ });
1310
+ }
1311
+ onEditDecision(value) {
1312
+ if (!this._editXml || !this._editDecision)
1313
+ return;
1314
+ const patchedXml = updateDmnXml(this._editXml, value);
1315
+ const fileName = this._editDecision.resource || toDecisionFileName(this._editDecision.key);
1316
+ const file = new File([patchedXml], fileName, { type: 'text/xml' });
1317
+ this.deployFileForContext(file).subscribe({
1318
+ next: () => {
1319
+ this.showNotification('success', 'decisions.deploySuccess');
1320
+ this.stateService.refreshDecisions();
1321
+ },
1322
+ error: () => this.showNotification('error', 'decisions.deployFailure'),
1323
+ });
1324
+ }
1325
+ onDeleteClick(decision) {
1326
+ this._decisionToDelete = decision;
1327
+ this.showDeleteModal$.next(true);
1328
+ }
1329
+ onDeleteConfirm() {
1330
+ if (!this._decisionToDelete)
1331
+ return;
1332
+ const decisionKey = this._decisionToDelete.key;
1333
+ this.caseManagementRouteParams$
1334
+ .pipe(take(1), switchMap(params => this.decisionService.deleteCaseDecisionDefinition(params.caseDefinitionKey, params.caseDefinitionVersionTag, decisionKey)))
1335
+ .subscribe({
1336
+ next: () => {
1337
+ this.showNotification('success', 'decisions.deleteSuccess');
1338
+ this.stateService.refreshDecisions();
1339
+ },
1340
+ error: () => this.showNotification('error', 'decisions.deleteFailure'),
794
1341
  });
795
1342
  }
796
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionListComponent, deps: [{ token: DecisionService }, { token: i6$1.IconService }, { token: i2.Router }, { token: i6.ConfigService }, { token: DecisionStateService }, { token: i2.ActivatedRoute }, { token: i0.ChangeDetectorRef }, { token: i6.EditPermissionsService }], target: i0.ɵɵFactoryTarget.Component }); }
797
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DecisionListComponent, isStandalone: true, selector: "valtimo-decision-list", viewQueries: [{ propertyName: "deploy", first: true, predicate: ["decisionDeploy"], 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<valtimo-carbon-list\n [items]=\"(decisionsLatestVersions$ | async) || []\"\n [loading]=\"loading$ | async\"\n [fields]=\"fields\"\n (rowClicked)=\"viewDecisionTable($event)\"\n [header]=\"false\"\n [isSearchable]=\"true\"\n>\n <ng-container carbonToolbarContent>\n <button\n *ngIf=\"hasEditPermissions$ | async\"\n cdsButton=\"primary\"\n (click)=\"this.deploy.openModal()\"\n [attr.data-test-id]=\"testIds.uploadButton\"\n >\n {{ 'Upload' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n </ng-container>\n</valtimo-carbon-list>\n\n<valtimo-decision-deploy #decisionDeploy></valtimo-decision-deploy>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: CarbonListModule }, { kind: "component", type: i4.CarbonListComponent, selector: "valtimo-carbon-list", inputs: ["items", "fields", "tableTranslations", "paginatorConfig", "pagination", "loading", "skeletonRowCount", "actions", "actionItems", "showActionItems", "header", "hideColumnHeader", "initialSortState", "sortState", "isSearchable", "enableSingleSelection", "lastColumnTemplate", "paginationIdentifier", "showSelectionColumn", "striped", "hideToolbar", "lockedTooltipTranslationKey", "movingRowsEnabled", "dragAndDrop", "dragAndDropDisabled"], outputs: ["rowClicked", "paginationClicked", "paginationSet", "search", "sortChanged", "moveRow", "itemsReordered"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i6$1.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: WidgetModule }, { kind: "component", type: DecisionDeployComponent, selector: "valtimo-decision-deploy", outputs: ["deploySuccessful"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }] }); }
1343
+ deployFileForContext(file) {
1344
+ return this.context$.pipe(take(1), switchMap(context => {
1345
+ if (context === 'case') {
1346
+ return this.caseManagementRouteParams$.pipe(take(1), switchMap(params => this.decisionService.deployCaseDecisionDefinition(params.caseDefinitionKey, params.caseDefinitionVersionTag, file)));
1347
+ }
1348
+ if (context === 'buildingBlock') {
1349
+ return this.buildingBlockManagementRouteParams$.pipe(take(1), switchMap(params => this.decisionService.deployBuildingBlockDecisionDefinition(params.buildingBlockDefinitionKey, params.buildingBlockDefinitionVersionTag, file)));
1350
+ }
1351
+ return this.decisionService.deployDmn(file);
1352
+ }));
1353
+ }
1354
+ showNotification(type, message) {
1355
+ this.notificationService.showToast({
1356
+ caption: this.translateService.instant(message),
1357
+ type,
1358
+ title: this.translateService.instant(`interface.${type}`),
1359
+ });
1360
+ }
1361
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionListComponent, deps: [{ token: DecisionService }, { token: i4.IconService }, { token: i2.Router }, { token: DecisionStateService }, { token: i2.ActivatedRoute }, { token: i0.ChangeDetectorRef }, { token: i6.EditPermissionsService }, { token: i6.GlobalNotificationService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
1362
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DecisionListComponent, isStandalone: true, selector: "valtimo-decision-list", viewQueries: [{ propertyName: "deploy", first: true, predicate: ["decisionDeploy"], descendants: true }, { propertyName: "create", first: true, predicate: ["decisionCreate"], descendants: true }, { propertyName: "edit", first: true, predicate: ["decisionEdit"], 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<valtimo-carbon-list\n [items]=\"(decisionsLatestVersions$ | async) || []\"\n [loading]=\"loading$ | async\"\n [fields]=\"fields\"\n [actionItems]=\"ACTION_ITEMS\"\n (rowClicked)=\"viewDecisionTable($event)\"\n [header]=\"false\"\n [isSearchable]=\"true\"\n>\n <ng-container carbonToolbarContent>\n <ng-container *ngIf=\"{canEdit: hasEditPermissions$ | async} as obs\">\n <button\n cdsButton=\"ghost\"\n iconOnly=\"true\"\n [disabled]=\"!obs.canEdit\"\n (click)=\"this.deploy.openModal()\"\n [attr.data-test-id]=\"testIds.uploadButton\"\n >\n <svg cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"!obs.canEdit\"\n (click)=\"this.create.openModal()\"\n [attr.data-test-id]=\"testIds.createButton\"\n >\n {{ 'decisions.create' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </ng-container>\n </ng-container>\n</valtimo-carbon-list>\n\n<valtimo-decision-deploy #decisionDeploy></valtimo-decision-deploy>\n\n<valtimo-decision-form-modal\n #decisionCreate\n (submitEvent)=\"onCreateDecision($event)\"\n></valtimo-decision-form-modal>\n\n<valtimo-decision-form-modal\n #decisionEdit\n titleKey=\"decisions.editModal.title\"\n submitKey=\"interface.save\"\n (submitEvent)=\"onEditDecision($event)\"\n></valtimo-decision-form-modal>\n\n<valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"decisions.deleteModal.content\"\n [showModalSubject$]=\"showDeleteModal$\"\n titleTranslationKey=\"decisions.deleteModal.title\"\n (confirmEvent)=\"onDeleteConfirm()\"\n></valtimo-confirmation-modal>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: CarbonListModule }, { kind: "component", type: i4$1.CarbonListComponent, selector: "valtimo-carbon-list", inputs: ["items", "fields", "tableTranslations", "paginatorConfig", "pagination", "loading", "skeletonRowCount", "actions", "actionItems", "showActionItems", "header", "hideColumnHeader", "initialSortState", "sortState", "isSearchable", "enableSingleSelection", "lastColumnTemplate", "paginationIdentifier", "showSelectionColumn", "striped", "hideToolbar", "lockedTooltipTranslationKey", "movingRowsEnabled", "dragAndDrop", "dragAndDropDisabled"], outputs: ["rowClicked", "paginationClicked", "paginationSet", "search", "sortChanged", "moveRow", "itemsReordered"] }, { kind: "ngmodule", type: IconModule }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "ngmodule", type: WidgetModule }, { kind: "component", type: DecisionDeployComponent, selector: "valtimo-decision-deploy", outputs: ["deploySuccessful"] }, { kind: "component", type: DecisionFormModalComponent, selector: "valtimo-decision-form-modal", inputs: ["titleKey", "submitKey"], outputs: ["submitEvent"] }, { kind: "ngmodule", type: ConfirmationModalModule }, { kind: "component", type: i4$1.ConfirmationModalComponent, selector: "valtimo-confirmation-modal", inputs: ["titleTranslationKey", "title", "content", "contentTranslationKey", "confirmButtonText", "confirmButtonTextTranslationKey", "confirmButtonType", "showOptionalButton", "optionalButtonText", "optionalButtonTextTranslationKey", "optionalButtonType", "cancelButtonText", "cancelButtonTextTranslationKey", "cancelButtonType", "showModalSubject$", "outputOnConfirm", "outputOnOptional", "spacerAfterCancelButton"], outputs: ["confirmEvent", "optionalEvent", "cancelEvent"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }] }); }
798
1363
  }
799
1364
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DecisionListComponent, decorators: [{
800
1365
  type: Component,
@@ -805,12 +1370,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
805
1370
  IconModule,
806
1371
  WidgetModule,
807
1372
  DecisionDeployComponent,
1373
+ DecisionFormModalComponent,
1374
+ ConfirmationModalModule,
808
1375
  TranslateModule,
809
1376
  ButtonModule,
810
- ], template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<valtimo-carbon-list\n [items]=\"(decisionsLatestVersions$ | async) || []\"\n [loading]=\"loading$ | async\"\n [fields]=\"fields\"\n (rowClicked)=\"viewDecisionTable($event)\"\n [header]=\"false\"\n [isSearchable]=\"true\"\n>\n <ng-container carbonToolbarContent>\n <button\n *ngIf=\"hasEditPermissions$ | async\"\n cdsButton=\"primary\"\n (click)=\"this.deploy.openModal()\"\n [attr.data-test-id]=\"testIds.uploadButton\"\n >\n {{ 'Upload' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n </ng-container>\n</valtimo-carbon-list>\n\n<valtimo-decision-deploy #decisionDeploy></valtimo-decision-deploy>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
811
- }], ctorParameters: () => [{ type: DecisionService }, { type: i6$1.IconService }, { type: i2.Router }, { type: i6.ConfigService }, { type: DecisionStateService }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i6.EditPermissionsService }], propDecorators: { deploy: [{
1377
+ ], template: "<!--\n ~ Copyright 2015-2025 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<valtimo-carbon-list\n [items]=\"(decisionsLatestVersions$ | async) || []\"\n [loading]=\"loading$ | async\"\n [fields]=\"fields\"\n [actionItems]=\"ACTION_ITEMS\"\n (rowClicked)=\"viewDecisionTable($event)\"\n [header]=\"false\"\n [isSearchable]=\"true\"\n>\n <ng-container carbonToolbarContent>\n <ng-container *ngIf=\"{canEdit: hasEditPermissions$ | async} as obs\">\n <button\n cdsButton=\"ghost\"\n iconOnly=\"true\"\n [disabled]=\"!obs.canEdit\"\n (click)=\"this.deploy.openModal()\"\n [attr.data-test-id]=\"testIds.uploadButton\"\n >\n <svg cdsIcon=\"upload\" size=\"16\"></svg>\n </button>\n\n <button\n cdsButton=\"primary\"\n [disabled]=\"!obs.canEdit\"\n (click)=\"this.create.openModal()\"\n [attr.data-test-id]=\"testIds.createButton\"\n >\n {{ 'decisions.create' | translate }}\n\n <svg class=\"cds--btn__icon\" cdsIcon=\"add\" size=\"16\"></svg>\n </button>\n </ng-container>\n </ng-container>\n</valtimo-carbon-list>\n\n<valtimo-decision-deploy #decisionDeploy></valtimo-decision-deploy>\n\n<valtimo-decision-form-modal\n #decisionCreate\n (submitEvent)=\"onCreateDecision($event)\"\n></valtimo-decision-form-modal>\n\n<valtimo-decision-form-modal\n #decisionEdit\n titleKey=\"decisions.editModal.title\"\n submitKey=\"interface.save\"\n (submitEvent)=\"onEditDecision($event)\"\n></valtimo-decision-form-modal>\n\n<valtimo-confirmation-modal\n confirmButtonTextTranslationKey=\"interface.delete\"\n confirmButtonType=\"danger\"\n contentTranslationKey=\"decisions.deleteModal.content\"\n [showModalSubject$]=\"showDeleteModal$\"\n titleTranslationKey=\"decisions.deleteModal.title\"\n (confirmEvent)=\"onDeleteConfirm()\"\n></valtimo-confirmation-modal>\n", styles: ["/*!\n * Copyright 2015-2025 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
1378
+ }], ctorParameters: () => [{ type: DecisionService }, { type: i4.IconService }, { type: i2.Router }, { type: DecisionStateService }, { type: i2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i6.EditPermissionsService }, { type: i6.GlobalNotificationService }, { type: i3.TranslateService }], propDecorators: { deploy: [{
812
1379
  type: ViewChild,
813
1380
  args: ['decisionDeploy']
1381
+ }], create: [{
1382
+ type: ViewChild,
1383
+ args: ['decisionCreate']
1384
+ }], edit: [{
1385
+ type: ViewChild,
1386
+ args: ['decisionEdit']
814
1387
  }] } });
815
1388
 
816
1389
  /*
@@ -914,6 +1487,7 @@ class DecisionModule {
914
1487
  ButtonModule,
915
1488
  IconModule,
916
1489
  DecisionDeployComponent,
1490
+ DecisionFormModalComponent,
917
1491
  DecisionModelerComponent,
918
1492
  DecisionListComponent,
919
1493
  DecisionDisplayComponent], exports: [DecisionModelerComponent] }); }
@@ -929,6 +1503,7 @@ class DecisionModule {
929
1503
  ButtonModule,
930
1504
  IconModule,
931
1505
  DecisionDeployComponent,
1506
+ DecisionFormModalComponent,
932
1507
  DecisionModelerComponent,
933
1508
  DecisionListComponent,
934
1509
  DecisionDisplayComponent] }); }
@@ -949,6 +1524,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
949
1524
  ButtonModule,
950
1525
  IconModule,
951
1526
  DecisionDeployComponent,
1527
+ DecisionFormModalComponent,
952
1528
  DecisionModelerComponent,
953
1529
  DecisionListComponent,
954
1530
  DecisionDisplayComponent,
@@ -980,5 +1556,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
980
1556
  * Generated bundle index. Do not edit.
981
1557
  */
982
1558
 
983
- export { DECISION_LIST_TEST_IDS, DECISION_MODELER_TEST_IDS, DECISION_UPLOAD_TEST_IDS, DecisionDeployComponent, DecisionDisplayComponent, DecisionListComponent, DecisionModelerComponent, DecisionModule, DecisionService, DecisionStateService, filterLatestDecisionVersions };
1559
+ export { DECISION_FORM_TEST_IDS, DECISION_LIST_TEST_IDS, DECISION_MODELER_TEST_IDS, DECISION_UPLOAD_TEST_IDS, DecisionDeployComponent, DecisionDisplayComponent, DecisionFormModalComponent, DecisionListComponent, DecisionModelerComponent, DecisionModule, DecisionService, DecisionStateService, createDmnXml, filterLatestDecisionVersions, parseDecisionForm, toDecisionFileName, toDecisionKey, updateDmnXml };
984
1560
  //# sourceMappingURL=valtimo-decision.mjs.map