@meshmakers/octo-meshboard 3.5.570 → 3.5.580

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.
@@ -29632,7 +29632,8 @@ function findDiagramConnections(diagram) {
29632
29632
  }
29633
29633
  const connections = [];
29634
29634
  for (const primitive of diagram.primitives) {
29635
- if (!CONNECTION_PRIMITIVE_TYPES.includes(primitive.type)) {
29635
+ // A stored diagram can hold a malformed entry (AB#8151): skip it instead of throwing.
29636
+ if (!primitive || typeof primitive !== 'object' || !CONNECTION_PRIMITIVE_TYPES.includes(primitive.type)) {
29636
29637
  continue;
29637
29638
  }
29638
29639
  const bindings = diagram.propertyBindings.filter(b => isDirectionBinding(b, primitive.id));
@@ -29701,6 +29702,140 @@ function connectionDirectionIssues(diagram, directions) {
29701
29702
  return issues;
29702
29703
  }
29703
29704
 
29705
+ /**
29706
+ * Render-time validation of a stored process diagram (AB#8151).
29707
+ *
29708
+ * A diagram can be written through the API / MCP without the designer, so a single
29709
+ * element may lack its `config`, geometry or carry an unknown type. The widget
29710
+ * template dereferences those members directly; one bad element would throw during
29711
+ * change detection and take the whole MeshBoard down. {@link sanitizeProcessDiagram}
29712
+ * returns a copy that is safe to render plus the list of problems. The stored diagram
29713
+ * is never modified or written back.
29714
+ */
29715
+ /** Element types the widget can render; every one of them except `pipe` carries a `config` object. */
29716
+ const KNOWN_ELEMENT_TYPES = [
29717
+ 'tank', 'silo', 'vessel', 'pipe', 'valve', 'pump', 'motor', 'gauge',
29718
+ 'digitalDisplay', 'statusLight', 'label', 'image', 'shape', 'customSvg'
29719
+ ];
29720
+ const TYPES_WITHOUT_CONFIG = ['pipe'];
29721
+ const FALLBACK_WIDTH = 160;
29722
+ const FALLBACK_HEIGHT = 28;
29723
+ function isRecord(value) {
29724
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
29725
+ }
29726
+ function isFiniteNumber(value) {
29727
+ return typeof value === 'number' && Number.isFinite(value);
29728
+ }
29729
+ function hasPosition(value) {
29730
+ return isRecord(value) && isFiniteNumber(value['x']) && isFiniteNumber(value['y']);
29731
+ }
29732
+ function hasSize(value) {
29733
+ return isRecord(value) && isFiniteNumber(value['width']) && isFiniteNumber(value['height']);
29734
+ }
29735
+ function elementProblem(element) {
29736
+ if (!isRecord(element)) {
29737
+ return 'not an object';
29738
+ }
29739
+ const problems = [];
29740
+ const type = element['type'];
29741
+ if (typeof type !== 'string' || !KNOWN_ELEMENT_TYPES.includes(type)) {
29742
+ problems.push(`unknown type '${String(type ?? '')}'`);
29743
+ }
29744
+ else if (!TYPES_WITHOUT_CONFIG.includes(type) && !isRecord(element['config'])) {
29745
+ problems.push('missing config');
29746
+ }
29747
+ if (!hasPosition(element['position'])) {
29748
+ problems.push('missing or invalid position');
29749
+ }
29750
+ if (!hasSize(element['size'])) {
29751
+ problems.push('missing or invalid size');
29752
+ }
29753
+ return problems.length > 0 ? problems.join(', ') : null;
29754
+ }
29755
+ function connectionProblem(connection) {
29756
+ if (!isRecord(connection)) {
29757
+ return 'not an object';
29758
+ }
29759
+ const problems = [];
29760
+ if (typeof connection['id'] !== 'string' || connection['id'] === '') {
29761
+ problems.push('missing id');
29762
+ }
29763
+ const from = connection['from'];
29764
+ const to = connection['to'];
29765
+ if (!isRecord(from) || typeof from['elementId'] !== 'string' || !isRecord(to) || typeof to['elementId'] !== 'string') {
29766
+ problems.push('missing from/to element');
29767
+ }
29768
+ if (!isRecord(connection['style'])) {
29769
+ problems.push('missing style');
29770
+ }
29771
+ return problems.length > 0 ? problems.join(', ') : null;
29772
+ }
29773
+ function labelOf(item, index) {
29774
+ if (isRecord(item)) {
29775
+ const id = typeof item['id'] === 'string' && item['id'] !== '' ? item['id'] : `#${index}`;
29776
+ const name = typeof item['name'] === 'string' && item['name'] !== '' ? item['name'] : id;
29777
+ return { id, label: name };
29778
+ }
29779
+ return { id: `#${index}`, label: `#${index}` };
29780
+ }
29781
+ /**
29782
+ * Splits the diagram into what can be rendered and what cannot.
29783
+ * Never throws, whatever shape `elements` / `connections` have.
29784
+ */
29785
+ function sanitizeProcessDiagram(diagram) {
29786
+ const issues = [];
29787
+ const placeholders = [];
29788
+ const rawElements = Array.isArray(diagram.elements) ? diagram.elements : [];
29789
+ const elements = [];
29790
+ let fallbackRow = 0;
29791
+ rawElements.forEach((element, index) => {
29792
+ const problem = elementProblem(element);
29793
+ if (!problem) {
29794
+ elements.push(element);
29795
+ return;
29796
+ }
29797
+ const { id, label } = labelOf(element, index);
29798
+ const issue = { id, label, kind: 'element', reason: problem, message: `${label}: ${problem}` };
29799
+ issues.push(issue);
29800
+ const record = isRecord(element) ? element : {};
29801
+ const position = hasPosition(record['position']) ? record['position'] : { x: 8, y: 8 + fallbackRow++ * (FALLBACK_HEIGHT + 6) };
29802
+ const size = hasSize(record['size']) ? record['size'] : { width: FALLBACK_WIDTH, height: FALLBACK_HEIGHT };
29803
+ placeholders.push({
29804
+ key: `${id}@${index}`,
29805
+ issue,
29806
+ x: position.x,
29807
+ y: position.y,
29808
+ width: Math.max(size.width, 60),
29809
+ height: Math.max(size.height, FALLBACK_HEIGHT)
29810
+ });
29811
+ });
29812
+ const rawConnections = Array.isArray(diagram.connections) ? diagram.connections : [];
29813
+ const connections = [];
29814
+ rawConnections.forEach((connection, index) => {
29815
+ const problem = connectionProblem(connection);
29816
+ if (!problem) {
29817
+ connections.push(connection);
29818
+ return;
29819
+ }
29820
+ const { id, label } = labelOf(connection, index);
29821
+ issues.push({ id, label, kind: 'connection', reason: problem, message: `Connection ${label}: ${problem}` });
29822
+ });
29823
+ const clean = issues.length === 0 && Array.isArray(diagram.elements) && Array.isArray(diagram.connections);
29824
+ return {
29825
+ diagram: clean ? diagram : { ...diagram, elements, connections },
29826
+ issues,
29827
+ placeholders
29828
+ };
29829
+ }
29830
+ /** One line for the in-widget hint / dialog hint. */
29831
+ function describeProcessDiagramIssues(issues) {
29832
+ if (issues.length === 0) {
29833
+ return '';
29834
+ }
29835
+ const noun = issues.length === 1 ? 'item' : 'items';
29836
+ return `${issues.length} invalid diagram ${noun} skipped: ${issues.map(i => i.message).join('; ')}`;
29837
+ }
29838
+
29704
29839
  class ProcessDataService {
29705
29840
  dataService = inject(MeshBoardDataService);
29706
29841
  variableService = inject(MeshBoardVariableService);
@@ -30411,6 +30546,11 @@ class ProcessWidgetComponent {
30411
30546
  ...(ngDevMode ? [{ debugName: "_error" }] : /* istanbul ignore next */ []));
30412
30547
  _diagramConfig = signal(null, /* @ts-ignore */
30413
30548
  ...(ngDevMode ? [{ debugName: "_diagramConfig" }] : /* istanbul ignore next */ []));
30549
+ /** Problems found when the diagram was loaded; invalid elements are skipped, not rendered (AB#8151). */
30550
+ _diagramIssues = signal([], /* @ts-ignore */
30551
+ ...(ngDevMode ? [{ debugName: "_diagramIssues" }] : /* istanbul ignore next */ []));
30552
+ _invalidElements = signal([], /* @ts-ignore */
30553
+ ...(ngDevMode ? [{ debugName: "_invalidElements" }] : /* istanbul ignore next */ []));
30414
30554
  _runtimeState = signal(null, /* @ts-ignore */
30415
30555
  ...(ngDevMode ? [{ debugName: "_runtimeState" }] : /* istanbul ignore next */ []));
30416
30556
  _symbolDefinitions = signal(new Map(), /* @ts-ignore */
@@ -30430,6 +30570,10 @@ class ProcessWidgetComponent {
30430
30570
  isLoading = this._isLoading.asReadonly();
30431
30571
  error = this._error.asReadonly();
30432
30572
  diagramConfig = this._diagramConfig.asReadonly();
30573
+ diagramIssues = this._diagramIssues.asReadonly();
30574
+ invalidElements = this._invalidElements.asReadonly();
30575
+ diagramIssueText = computed(() => describeProcessDiagramIssues(this._diagramIssues()), /* @ts-ignore */
30576
+ ...(ngDevMode ? [{ debugName: "diagramIssueText" }] : /* istanbul ignore next */ []));
30433
30577
  data = computed(() => this._runtimeState(), /* @ts-ignore */
30434
30578
  ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
30435
30579
  /**
@@ -30572,15 +30716,16 @@ class ProcessWidgetComponent {
30572
30716
  try {
30573
30717
  // Check for inline config first
30574
30718
  if (this.config.inlineConfig) {
30575
- this._diagramConfig.set(applyConnectionDirections(this.config.inlineConfig, this.config.connectionDirections));
30576
- await this.loadSymbolDefinitions(this.config.inlineConfig);
30719
+ const inline = this.acceptDiagram(this.config.inlineConfig);
30720
+ this._diagramConfig.set(applyConnectionDirections(inline, this.config.connectionDirections));
30721
+ await this.loadSymbolDefinitions(inline);
30577
30722
  await this.loadRuntimeData();
30578
30723
  scopePending = await this.loadBoundData(generation);
30579
30724
  return;
30580
30725
  }
30581
30726
  // Load from backend by rtId
30582
30727
  if (this.config.processDiagramRtId) {
30583
- const diagram = await this.dataService.loadDiagram(this.config.processDiagramRtId);
30728
+ const diagram = this.acceptDiagram(await this.dataService.loadDiagram(this.config.processDiagramRtId));
30584
30729
  // Connection directions picked in the widget (AB#8025) re-point the
30585
30730
  // direction effects of their lines; the stored diagram stays unchanged.
30586
30731
  this._diagramConfig.set(applyConnectionDirections(diagram, this.config.connectionDirections));
@@ -30602,6 +30747,19 @@ class ProcessWidgetComponent {
30602
30747
  }
30603
30748
  }
30604
30749
  }
30750
+ /**
30751
+ * Validates the loaded diagram (AB#8151): invalid elements are replaced by a visible
30752
+ * placeholder and reported once on the console; the stored diagram is not modified.
30753
+ */
30754
+ acceptDiagram(diagram) {
30755
+ const result = sanitizeProcessDiagram(diagram);
30756
+ this._diagramIssues.set(result.issues);
30757
+ this._invalidElements.set(result.placeholders);
30758
+ for (const issue of result.issues) {
30759
+ this.warnOnce(`[ProcessWidget] ${this.config.title || this.config.id}: skipped invalid diagram ${issue.kind} ${issue.message}`);
30760
+ }
30761
+ return result.diagram;
30762
+ }
30605
30763
  /**
30606
30764
  * Loads bound data based on widget data binding configuration.
30607
30765
  * Returns `true` when the bound entity-selector scope is still resolving (AB#7721).
@@ -32708,6 +32866,32 @@ class ProcessWidgetComponent {
32708
32866
  </g>
32709
32867
  }
32710
32868
 
32869
+ <!-- Elements that failed validation (AB#8151): visible placeholder naming the element -->
32870
+ @for (placeholder of invalidElements(); track placeholder.key) {
32871
+ <g class="element element-invalid"
32872
+ [attr.data-id]="placeholder.issue.id"
32873
+ [attr.transform]="'translate(' + placeholder.x + ',' + placeholder.y + ')'">
32874
+ <title>{{ placeholder.issue.message }}</title>
32875
+ <rect
32876
+ x="0" y="0"
32877
+ [attr.width]="placeholder.width"
32878
+ [attr.height]="placeholder.height"
32879
+ class="invalid-element-box"
32880
+ fill="rgba(211, 47, 47, 0.08)"
32881
+ stroke="#d32f2f"
32882
+ stroke-width="1"
32883
+ stroke-dasharray="4,3"/>
32884
+ <text
32885
+ x="6"
32886
+ [attr.y]="placeholder.height / 2"
32887
+ dominant-baseline="middle"
32888
+ fill="#d32f2f"
32889
+ font-size="10">
32890
+ ⚠ {{ placeholder.issue.label }}: {{ placeholder.issue.reason }}
32891
+ </text>
32892
+ </g>
32893
+ }
32894
+
32711
32895
  <!-- Primitives (from Process Designer, with bindings applied) -->
32712
32896
  @for (primitive of boundPrimitives(); track primitive.id) {
32713
32897
  @if (primitive.visible !== false) {
@@ -33104,6 +33288,12 @@ class ProcessWidgetComponent {
33104
33288
  <span>No process diagram configured</span>
33105
33289
  </div>
33106
33290
  }
33291
+ @if (!isLoading() && !error() && diagramIssues().length > 0) {
33292
+ <div class="diagram-issue-badge" role="status" [attr.title]="diagramIssueText()">
33293
+ <span class="binding-error-icon" aria-hidden="true">⚠</span>
33294
+ <span class="binding-error-text">{{ diagramIssueText() }}</span>
33295
+ </div>
33296
+ }
33107
33297
  @if (!isLoading() && !error() && bindingErrors().length > 0) {
33108
33298
  <div class="binding-error-badge" role="status" [attr.title]="bindingErrorText()">
33109
33299
  <span class="binding-error-icon" aria-hidden="true">⚠</span>
@@ -33111,7 +33301,7 @@ class ProcessWidgetComponent {
33111
33301
  </div>
33112
33302
  }
33113
33303
  </div>
33114
- `, isInline: true, styles: [":host{display:block;width:100%;height:100%}.process-widget{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:hidden;background-color:var(--process-bg, #fafafa)}.loading-overlay{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;color:var(--kendo-color-subtle, #666)}.loading-spinner{width:40px;height:40px;border:3px solid #e0e0e0;border-top-color:var(--kendo-color-primary, #1976d2);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.error-container{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:1rem;color:var(--kendo-color-error, #d32f2f)}.error-icon{font-size:2rem}.error-message{font-size:.875rem;text-align:center}.no-config{display:flex;align-items:center;justify-content:center;color:var(--kendo-color-subtle, #999);font-style:italic}.diagram-container{position:relative;overflow:hidden}.binding-error-badge{position:absolute;top:4px;right:4px;max-width:calc(100% - 8px);display:flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;font-size:.75rem;color:var(--kendo-color-error, #d32f2f);background-color:var(--kendo-color-surface-alt, #ffffff);border:1px solid var(--kendo-color-error, #d32f2f);z-index:1}.binding-error-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diagram-container.fit-to-bounds{width:100%!important;height:100%!important}.process-svg{display:block}.diagram-container.fit-to-bounds .process-svg{width:100%;height:100%}.canvas-background{fill:var(--process-canvas-bg, #fafafa)}.element{cursor:default}.element.interactive{cursor:pointer}.element.interactive:hover{filter:brightness(1.1)}.tank-fill{transition:height .5s ease-out,y .5s ease-out}.tank-label{pointer-events:none;-webkit-user-select:none;user-select:none}.pump-element .rotating{animation:rotate 1s linear infinite;transform-origin:center}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.blinking{animation:blink 1s ease-in-out infinite}@keyframes blink{0%,to{opacity:1}50%{opacity:.3}}.connection-flow{animation:flow 2s linear infinite}@keyframes flow{0%{stroke-dashoffset:0}to{stroke-dashoffset:-40}}.digital-display-value{font-family:Courier New,monospace;letter-spacing:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.Eager });
33304
+ `, isInline: true, styles: [":host{display:block;width:100%;height:100%}.process-widget{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:hidden;background-color:var(--process-bg, #fafafa)}.loading-overlay{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;color:var(--kendo-color-subtle, #666)}.loading-spinner{width:40px;height:40px;border:3px solid #e0e0e0;border-top-color:var(--kendo-color-primary, #1976d2);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.error-container{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:1rem;color:var(--kendo-color-error, #d32f2f)}.error-icon{font-size:2rem}.error-message{font-size:.875rem;text-align:center}.no-config{display:flex;align-items:center;justify-content:center;color:var(--kendo-color-subtle, #999);font-style:italic}.diagram-container{position:relative;overflow:hidden}.binding-error-badge{position:absolute;top:4px;right:4px;max-width:calc(100% - 8px);display:flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;font-size:.75rem;color:var(--kendo-color-error, #d32f2f);background-color:var(--kendo-color-surface-alt, #ffffff);border:1px solid var(--kendo-color-error, #d32f2f);z-index:1}.diagram-issue-badge{position:absolute;bottom:4px;left:4px;max-width:calc(100% - 8px);display:flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;font-size:.75rem;color:var(--kendo-color-error, #d32f2f);background-color:var(--kendo-color-surface-alt, #ffffff);border:1px solid var(--kendo-color-error, #d32f2f);z-index:1}.binding-error-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diagram-container.fit-to-bounds{width:100%!important;height:100%!important}.process-svg{display:block}.diagram-container.fit-to-bounds .process-svg{width:100%;height:100%}.canvas-background{fill:var(--process-canvas-bg, #fafafa)}.element{cursor:default}.element.interactive{cursor:pointer}.element.interactive:hover{filter:brightness(1.1)}.tank-fill{transition:height .5s ease-out,y .5s ease-out}.tank-label{pointer-events:none;-webkit-user-select:none;user-select:none}.pump-element .rotating{animation:rotate 1s linear infinite;transform-origin:center}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.blinking{animation:blink 1s ease-in-out infinite}@keyframes blink{0%,to{opacity:1}50%{opacity:.3}}.connection-flow{animation:flow 2s linear infinite}@keyframes flow{0%{stroke-dashoffset:0}to{stroke-dashoffset:-40}}.digital-display-value{font-family:Courier New,monospace;letter-spacing:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.Eager });
33115
33305
  }
33116
33306
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ProcessWidgetComponent, decorators: [{
33117
33307
  type: Component,
@@ -33715,6 +33905,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
33715
33905
  </g>
33716
33906
  }
33717
33907
 
33908
+ <!-- Elements that failed validation (AB#8151): visible placeholder naming the element -->
33909
+ @for (placeholder of invalidElements(); track placeholder.key) {
33910
+ <g class="element element-invalid"
33911
+ [attr.data-id]="placeholder.issue.id"
33912
+ [attr.transform]="'translate(' + placeholder.x + ',' + placeholder.y + ')'">
33913
+ <title>{{ placeholder.issue.message }}</title>
33914
+ <rect
33915
+ x="0" y="0"
33916
+ [attr.width]="placeholder.width"
33917
+ [attr.height]="placeholder.height"
33918
+ class="invalid-element-box"
33919
+ fill="rgba(211, 47, 47, 0.08)"
33920
+ stroke="#d32f2f"
33921
+ stroke-width="1"
33922
+ stroke-dasharray="4,3"/>
33923
+ <text
33924
+ x="6"
33925
+ [attr.y]="placeholder.height / 2"
33926
+ dominant-baseline="middle"
33927
+ fill="#d32f2f"
33928
+ font-size="10">
33929
+ ⚠ {{ placeholder.issue.label }}: {{ placeholder.issue.reason }}
33930
+ </text>
33931
+ </g>
33932
+ }
33933
+
33718
33934
  <!-- Primitives (from Process Designer, with bindings applied) -->
33719
33935
  @for (primitive of boundPrimitives(); track primitive.id) {
33720
33936
  @if (primitive.visible !== false) {
@@ -34111,6 +34327,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
34111
34327
  <span>No process diagram configured</span>
34112
34328
  </div>
34113
34329
  }
34330
+ @if (!isLoading() && !error() && diagramIssues().length > 0) {
34331
+ <div class="diagram-issue-badge" role="status" [attr.title]="diagramIssueText()">
34332
+ <span class="binding-error-icon" aria-hidden="true">⚠</span>
34333
+ <span class="binding-error-text">{{ diagramIssueText() }}</span>
34334
+ </div>
34335
+ }
34114
34336
  @if (!isLoading() && !error() && bindingErrors().length > 0) {
34115
34337
  <div class="binding-error-badge" role="status" [attr.title]="bindingErrorText()">
34116
34338
  <span class="binding-error-icon" aria-hidden="true">⚠</span>
@@ -34118,7 +34340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
34118
34340
  </div>
34119
34341
  }
34120
34342
  </div>
34121
- `, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;width:100%;height:100%}.process-widget{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:hidden;background-color:var(--process-bg, #fafafa)}.loading-overlay{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;color:var(--kendo-color-subtle, #666)}.loading-spinner{width:40px;height:40px;border:3px solid #e0e0e0;border-top-color:var(--kendo-color-primary, #1976d2);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.error-container{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:1rem;color:var(--kendo-color-error, #d32f2f)}.error-icon{font-size:2rem}.error-message{font-size:.875rem;text-align:center}.no-config{display:flex;align-items:center;justify-content:center;color:var(--kendo-color-subtle, #999);font-style:italic}.diagram-container{position:relative;overflow:hidden}.binding-error-badge{position:absolute;top:4px;right:4px;max-width:calc(100% - 8px);display:flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;font-size:.75rem;color:var(--kendo-color-error, #d32f2f);background-color:var(--kendo-color-surface-alt, #ffffff);border:1px solid var(--kendo-color-error, #d32f2f);z-index:1}.binding-error-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diagram-container.fit-to-bounds{width:100%!important;height:100%!important}.process-svg{display:block}.diagram-container.fit-to-bounds .process-svg{width:100%;height:100%}.canvas-background{fill:var(--process-canvas-bg, #fafafa)}.element{cursor:default}.element.interactive{cursor:pointer}.element.interactive:hover{filter:brightness(1.1)}.tank-fill{transition:height .5s ease-out,y .5s ease-out}.tank-label{pointer-events:none;-webkit-user-select:none;user-select:none}.pump-element .rotating{animation:rotate 1s linear infinite;transform-origin:center}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.blinking{animation:blink 1s ease-in-out infinite}@keyframes blink{0%,to{opacity:1}50%{opacity:.3}}.connection-flow{animation:flow 2s linear infinite}@keyframes flow{0%{stroke-dashoffset:0}to{stroke-dashoffset:-40}}.digital-display-value{font-family:Courier New,monospace;letter-spacing:2px}\n"] }]
34343
+ `, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;width:100%;height:100%}.process-widget{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:hidden;background-color:var(--process-bg, #fafafa)}.loading-overlay{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;color:var(--kendo-color-subtle, #666)}.loading-spinner{width:40px;height:40px;border:3px solid #e0e0e0;border-top-color:var(--kendo-color-primary, #1976d2);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.error-container{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:1rem;color:var(--kendo-color-error, #d32f2f)}.error-icon{font-size:2rem}.error-message{font-size:.875rem;text-align:center}.no-config{display:flex;align-items:center;justify-content:center;color:var(--kendo-color-subtle, #999);font-style:italic}.diagram-container{position:relative;overflow:hidden}.binding-error-badge{position:absolute;top:4px;right:4px;max-width:calc(100% - 8px);display:flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;font-size:.75rem;color:var(--kendo-color-error, #d32f2f);background-color:var(--kendo-color-surface-alt, #ffffff);border:1px solid var(--kendo-color-error, #d32f2f);z-index:1}.diagram-issue-badge{position:absolute;bottom:4px;left:4px;max-width:calc(100% - 8px);display:flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;font-size:.75rem;color:var(--kendo-color-error, #d32f2f);background-color:var(--kendo-color-surface-alt, #ffffff);border:1px solid var(--kendo-color-error, #d32f2f);z-index:1}.binding-error-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diagram-container.fit-to-bounds{width:100%!important;height:100%!important}.process-svg{display:block}.diagram-container.fit-to-bounds .process-svg{width:100%;height:100%}.canvas-background{fill:var(--process-canvas-bg, #fafafa)}.element{cursor:default}.element.interactive{cursor:pointer}.element.interactive:hover{filter:brightness(1.1)}.tank-fill{transition:height .5s ease-out,y .5s ease-out}.tank-label{pointer-events:none;-webkit-user-select:none;user-select:none}.pump-element .rotating{animation:rotate 1s linear infinite;transform-origin:center}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.blinking{animation:blink 1s ease-in-out infinite}@keyframes blink{0%,to{opacity:1}50%{opacity:.3}}.connection-flow{animation:flow 2s linear infinite}@keyframes flow{0%{stroke-dashoffset:0}to{stroke-dashoffset:-40}}.digital-display-value{font-family:Courier New,monospace;letter-spacing:2px}\n"] }]
34122
34344
  }], propDecorators: { config: [{
34123
34345
  type: Input
34124
34346
  }], containerRef: [{
@@ -34671,7 +34893,7 @@ class ProcessBindingCardsComponent {
34671
34893
  data-binding-action="add" (click)="add()">Add binding</button>
34672
34894
  }
34673
34895
  </div>
34674
- `, isInline: true, styles: [":host{display:block;container-type:inline-size}.binding-cards,.card-list{display:flex;flex-direction:column;gap:10px}.binding-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface, #ffffff)}.binding-card.invalid{border-color:var(--kendo-color-warning, #ffc107)}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:6px 6px 0 0;cursor:pointer}.binding-card.collapsed .card-header{border-radius:6px}.card-header:focus-visible{outline:2px solid var(--kendo-color-primary, #0d6efd);outline-offset:-2px}.card-header .name{font-weight:600}.card-header .meta{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.header-actions{display:inline-flex;gap:2px;margin-left:auto}.tag{font-size:.7rem;padding:1px 7px;border-radius:10px;border:1px solid var(--kendo-color-border, #dee2e6);color:var(--kendo-color-subtle, #6c757d)}.tag.warn{border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.delete-confirm{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-error-subtle, var(--kendo-color-surface-alt, #f8f9fa));font-size:.85rem}.confirm-actions{display:inline-flex;gap:6px}.card-body{padding:4px 10px 10px}.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}.form-field{display:flex;flex-direction:column;gap:4px;margin-top:10px}.form-field label{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.required,.field-error{color:var(--kendo-color-error, #dc3545)}.field-error{margin:0;font-size:.8rem}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{margin-top:8px;color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.empty-state{padding:16px;border:1px dashed var(--kendo-color-border, #dee2e6);border-radius:6px;color:var(--kendo-color-subtle, #6c757d)}.empty-state p{margin:0 0 8px}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}@container (max-width: 560px){.grid2{grid-template-columns:1fr}.card-header .meta{order:10;flex-basis:100%;margin-left:24px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i1$4.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
34896
+ `, isInline: true, styles: [":host{display:block;container-type:inline-size}.binding-cards,.card-list{display:flex;flex-direction:column;gap:10px}.binding-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface, #ffffff)}.binding-card.invalid{border-color:var(--kendo-color-warning, #ffc107)}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:6px 6px 0 0;cursor:pointer}.binding-card.collapsed .card-header{border-radius:6px}.card-header:focus-visible{outline:2px solid var(--kendo-color-primary, #0d6efd);outline-offset:-2px}.card-header .name{font-weight:600}.card-header .meta{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.header-actions{display:inline-flex;gap:2px;margin-left:auto}.tag{font-size:.7rem;padding:1px 7px;border-radius:10px;border:1px solid var(--kendo-color-border, #dee2e6);color:var(--kendo-color-subtle, #6c757d)}.tag.warn{border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.delete-confirm{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-on-app-surface, #212529);border-left:4px solid var(--kendo-color-error, #dc3545);font-size:.85rem}.confirm-actions{display:inline-flex;gap:6px}.card-body{padding:4px 10px 10px}.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}.form-field{display:flex;flex-direction:column;gap:4px;margin-top:10px}.form-field label{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.required,.field-error{color:var(--kendo-color-error, #dc3545)}.field-error{margin:0;font-size:.8rem}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{margin-top:8px;color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.empty-state{padding:16px;border:1px dashed var(--kendo-color-border, #dee2e6);border-radius:6px;color:var(--kendo-color-subtle, #6c757d)}.empty-state p{margin:0 0 8px}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}@container (max-width: 560px){.grid2{grid-template-columns:1fr}.card-header .meta{order:10;flex-basis:100%;margin-left:24px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i1$4.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
34675
34897
  }
34676
34898
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ProcessBindingCardsComponent, decorators: [{
34677
34899
  type: Component,
@@ -34857,7 +35079,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
34857
35079
  data-binding-action="add" (click)="add()">Add binding</button>
34858
35080
  }
34859
35081
  </div>
34860
- `, styles: [":host{display:block;container-type:inline-size}.binding-cards,.card-list{display:flex;flex-direction:column;gap:10px}.binding-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface, #ffffff)}.binding-card.invalid{border-color:var(--kendo-color-warning, #ffc107)}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:6px 6px 0 0;cursor:pointer}.binding-card.collapsed .card-header{border-radius:6px}.card-header:focus-visible{outline:2px solid var(--kendo-color-primary, #0d6efd);outline-offset:-2px}.card-header .name{font-weight:600}.card-header .meta{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.header-actions{display:inline-flex;gap:2px;margin-left:auto}.tag{font-size:.7rem;padding:1px 7px;border-radius:10px;border:1px solid var(--kendo-color-border, #dee2e6);color:var(--kendo-color-subtle, #6c757d)}.tag.warn{border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.delete-confirm{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-error-subtle, var(--kendo-color-surface-alt, #f8f9fa));font-size:.85rem}.confirm-actions{display:inline-flex;gap:6px}.card-body{padding:4px 10px 10px}.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}.form-field{display:flex;flex-direction:column;gap:4px;margin-top:10px}.form-field label{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.required,.field-error{color:var(--kendo-color-error, #dc3545)}.field-error{margin:0;font-size:.8rem}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{margin-top:8px;color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.empty-state{padding:16px;border:1px dashed var(--kendo-color-border, #dee2e6);border-radius:6px;color:var(--kendo-color-subtle, #6c757d)}.empty-state p{margin:0 0 8px}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}@container (max-width: 560px){.grid2{grid-template-columns:1fr}.card-header .meta{order:10;flex-basis:100%;margin-left:24px}}\n"] }]
35082
+ `, styles: [":host{display:block;container-type:inline-size}.binding-cards,.card-list{display:flex;flex-direction:column;gap:10px}.binding-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface, #ffffff)}.binding-card.invalid{border-color:var(--kendo-color-warning, #ffc107)}.card-header{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:6px 6px 0 0;cursor:pointer}.binding-card.collapsed .card-header{border-radius:6px}.card-header:focus-visible{outline:2px solid var(--kendo-color-primary, #0d6efd);outline-offset:-2px}.card-header .name{font-weight:600}.card-header .meta{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.header-actions{display:inline-flex;gap:2px;margin-left:auto}.tag{font-size:.7rem;padding:1px 7px;border-radius:10px;border:1px solid var(--kendo-color-border, #dee2e6);color:var(--kendo-color-subtle, #6c757d)}.tag.warn{border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.delete-confirm{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-on-app-surface, #212529);border-left:4px solid var(--kendo-color-error, #dc3545);font-size:.85rem}.confirm-actions{display:inline-flex;gap:6px}.card-body{padding:4px 10px 10px}.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}.form-field{display:flex;flex-direction:column;gap:4px;margin-top:10px}.form-field label{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.required,.field-error{color:var(--kendo-color-error, #dc3545)}.field-error{margin:0;font-size:.8rem}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{margin-top:8px;color:var(--kendo-color-warning-emphasis, var(--kendo-color-warning, #8a6d00))}.empty-state{padding:16px;border:1px dashed var(--kendo-color-border, #dee2e6);border-radius:6px;color:var(--kendo-color-subtle, #6c757d)}.empty-state p{margin:0 0 8px}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}@container (max-width: 560px){.grid2{grid-template-columns:1fr}.card-header .meta{order:10;flex-basis:100%;margin-left:24px}}\n"] }]
34861
35083
  }], propDecorators: { drafts: [{
34862
35084
  type: Input
34863
35085
  }], selectors: [{
@@ -34922,6 +35144,8 @@ class ProcessConfigDialogComponent {
34922
35144
  selectedDiagram = null;
34923
35145
  /** Full config of the selected diagram (properties, connections). */
34924
35146
  diagramConfig = null;
35147
+ /** Validation hint naming diagram elements that are invalid and skipped when rendering (AB#8151). */
35148
+ diagramIssueHint = '';
34925
35149
  // State - Bindings (AB#8025)
34926
35150
  drafts = [];
34927
35151
  persistentQueries = [];
@@ -35033,6 +35257,7 @@ class ProcessConfigDialogComponent {
35033
35257
  this.selectedDiagram = diagram;
35034
35258
  this.diagramExposedProperties = [];
35035
35259
  this.diagramConfig = null;
35260
+ this.diagramIssueHint = '';
35036
35261
  this.connections = [];
35037
35262
  // Connection ids belong to the previous diagram.
35038
35263
  this.connectionDirections.clear();
@@ -35044,7 +35269,15 @@ class ProcessConfigDialogComponent {
35044
35269
  async loadDiagramConfig(diagramRtId) {
35045
35270
  this.isLoadingDiagramConfig = true;
35046
35271
  try {
35047
- const fullDiagram = await this.processDataService.loadDiagram(diagramRtId);
35272
+ const loaded = await this.processDataService.loadDiagram(diagramRtId);
35273
+ // A malformed element must not leave the other tabs empty (AB#8151): the exposed
35274
+ // properties and connections come from the valid part, the problems become a hint.
35275
+ const result = loaded ? sanitizeProcessDiagram(loaded) : null;
35276
+ const fullDiagram = result?.diagram;
35277
+ this.diagramIssueHint = result ? describeProcessDiagramIssues(result.issues) : '';
35278
+ if (this.diagramIssueHint) {
35279
+ console.warn(`[ProcessConfigDialog] ${this.diagramIssueHint}`);
35280
+ }
35048
35281
  this.diagramConfig = fullDiagram ?? null;
35049
35282
  this.diagramExposedProperties = fullDiagram?.transformProperties ?? [];
35050
35283
  this.connections = findDiagramConnections(fullDiagram);
@@ -35352,6 +35585,9 @@ class ProcessConfigDialogComponent {
35352
35585
  @if (storedDiagrams.length === 0 && !isLoadingDiagrams) {
35353
35586
  <p class="field-hint warning">No diagrams found. Create diagrams using the Process Designer.</p>
35354
35587
  }
35588
+ @if (diagramIssueHint) {
35589
+ <p class="field-hint warning diagram-issue-hint" role="status">{{ diagramIssueHint }}</p>
35590
+ }
35355
35591
  </div>
35356
35592
 
35357
35593
  <!-- Preview Section -->
@@ -35443,6 +35679,7 @@ class ProcessConfigDialogComponent {
35443
35679
  <kendo-combobox
35444
35680
  class="col-path"
35445
35681
  [attr.aria-label]="'Field of ' + prop.name"
35682
+ [title]="getMappingSourcePath(prop.id) || ''"
35446
35683
  [data]="attributes"
35447
35684
  textField="attributePath"
35448
35685
  valueField="attributePath"
@@ -35457,6 +35694,7 @@ class ProcessConfigDialogComponent {
35457
35694
  <kendo-textbox
35458
35695
  class="col-path"
35459
35696
  [attr.aria-label]="'Field of ' + prop.name"
35697
+ [title]="getMappingSourcePath(prop.id) || ''"
35460
35698
  [value]="getMappingSourcePath(prop.id)"
35461
35699
  (valueChange)="onMappingSourcePathChange(prop.id, $event)"
35462
35700
  [placeholder]="bindingModeOf(prop.id) === 'runtimeEntity' ? 'Attribute...' : 'Column...'">
@@ -35494,7 +35732,7 @@ class ProcessConfigDialogComponent {
35494
35732
  <div class="connections-section" data-connections>
35495
35733
  <h4 class="section-title">Connections</h4>
35496
35734
  @if (connections.length === 0) {
35497
- <p class="field-hint">This diagram has no connection lines with a flow binding. Bind the flow animation, visibility or colour of a line to a property in the Process Designer to show its direction here.</p>
35735
+ <p class="field-hint">This diagram has no flow lines with a direction binding. Only line, polyline and path shapes whose flow animation, visibility or colour is bound to a property in the Process Designer are listed; plain connections between elements have no direction to pick.</p>
35498
35736
  } @else {
35499
35737
  <p class="section-hint">Each line takes its direction from the sign of a mapped value: positive flows forward, negative backward, 0 or no value shows no flow.</p>
35500
35738
  <div class="connection-list" role="list" aria-label="Connections">
@@ -35601,7 +35839,7 @@ class ProcessConfigDialogComponent {
35601
35839
  </button>
35602
35840
  </div>
35603
35841
  </div>
35604
- `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{flex:1;overflow-y:auto;padding:16px}.tab-content{padding:16px;min-height:200px;position:relative}.tab-content.loading{pointer-events:none}.section-hint{margin:0 0 16px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.empty-hint{text-align:center;padding:24px;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-field:last-child{margin-bottom:0}.form-field.disabled{opacity:.6}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{color:var(--kendo-color-warning, #ffc107)}.form-row{display:flex;gap:24px;margin-bottom:12px}.form-row:last-child{margin-bottom:0}.checkbox-field{flex-direction:row;align-items:flex-start}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.checkbox-field .field-hint{margin-top:4px;margin-left:28px}.preview-section{margin-top:16px;padding:12px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.preview-info{display:flex;flex-direction:column;gap:6px}.preview-item{display:flex;justify-content:space-between;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border-radius:4px}.preview-label{font-weight:500;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.preview-value{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.diagram-item{display:flex;justify-content:space-between;gap:16px}.diagram-name{font-weight:500}.diagram-size{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.property-mappings-table{display:flex;flex-direction:column;gap:6px}.mapping-header{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(80px,.9fr) minmax(80px,1fr) minmax(90px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:4px;font-weight:600;font-size:.7rem;color:var(--kendo-color-subtle, #6c757d)}.mapping-row{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(80px,.9fr) minmax(80px,1fr) minmax(90px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;align-items:center}.col-property{font-weight:500;font-size:.85rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.col-type.type-badge{font-size:.65rem;padding:2px 4px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:10px;text-align:center;color:var(--kendo-color-subtle, #6c757d)}.col-expression kendo-textbox{font-family:var(--theme-font-mono);font-size:.8rem}.expression-help{margin-top:12px}.expression-help code{background:var(--kendo-color-surface-alt, #f8f9fa);padding:1px 4px;border-radius:3px;font-size:.75rem}.tab-content{container-type:inline-size}@container (max-width: 560px){.mapping-header{display:none}.mapping-row{grid-template-columns:1fr 55px 1fr}.mapping-row .col-property{grid-column:1 / 3}}.connections-section{margin-top:20px}.section-title{margin:0 0 6px;font-size:.9rem;font-weight:600}.connection-list{display:flex;flex-direction:column;gap:6px}.connection-row{display:grid;grid-template-columns:minmax(80px,1fr) 120px minmax(160px,1.4fr);gap:4px 10px;align-items:center;padding:6px 10px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.connection-name{font-weight:500;font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-source{grid-column:1 / -1}.connection-preview .flow-line{stroke:var(--kendo-color-primary, #0d6efd);stroke-width:3;stroke-dasharray:8 5;stroke-linecap:round}.connection-preview .flow-arrow{fill:var(--kendo-color-primary, #0d6efd)}@container (max-width: 560px){.connection-row{grid-template-columns:1fr}}.save-issues{margin:0 16px;padding:8px 10px;border:1px solid var(--kendo-color-error, #dc3545);border-radius:4px;color:var(--kendo-color-error, #dc3545);font-size:.8rem}.save-issues p{margin:0}.loading-hint{font-style:italic;color:var(--kendo-color-subtle, #6c757d);padding:8px;text-align:center}:host ::ng-deep kendo-tabstrip{border:none}:host ::ng-deep .k-tabstrip-items-wrapper{border-bottom:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .k-tabstrip-content{border:none;padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: LayoutModule }, { kind: "component", type: i5.TabStripComponent, selector: "kendo-tabstrip", inputs: ["height", "animate", "tabAlignment", "tabPosition", "keepTabContent", "closable", "scrollable", "size", "closeIcon", "closeIconClass", "closeSVGIcon", "showContentArea"], outputs: ["tabSelect", "tabClose", "tabScroll"], exportAs: ["kendoTabStrip"] }, { kind: "component", type: i5.TabStripTabComponent, selector: "kendo-tabstrip-tab", inputs: ["title", "disabled", "cssClass", "cssStyle", "selected", "closable", "closeIcon", "closeIconClass", "closeSVGIcon"], exportAs: ["kendoTabStripTab"] }, { kind: "directive", type: i5.TabContentDirective, selector: "[kendoTabContent]" }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: ProcessBindingCardsComponent, selector: "mm-process-binding-cards", inputs: ["drafts", "selectors", "persistentQueries", "isLoadingQueries", "filterVariables", "mappings", "nextUid"], outputs: ["draftsChange", "bindingRenamed", "bindingDeleted", "queryFilterChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
35842
+ `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{flex:1;overflow-y:auto;padding:16px}.tab-content{padding:16px;min-height:200px;position:relative}.tab-content.loading{pointer-events:none}.section-hint{margin:0 0 16px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.empty-hint{text-align:center;padding:24px;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-field:last-child{margin-bottom:0}.form-field.disabled{opacity:.6}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{color:var(--kendo-color-warning, #ffc107)}.form-row{display:flex;gap:24px;margin-bottom:12px}.form-row:last-child{margin-bottom:0}.checkbox-field{flex-direction:row;align-items:flex-start}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.checkbox-field .field-hint{margin-top:4px;margin-left:28px}.preview-section{margin-top:16px;padding:12px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.preview-info{display:flex;flex-direction:column;gap:6px}.preview-item{display:flex;justify-content:space-between;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border-radius:4px}.preview-label{font-weight:500;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.preview-value{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.diagram-item{display:flex;justify-content:space-between;gap:16px}.diagram-name{font-weight:500}.diagram-size{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.property-mappings-table{display:flex;flex-direction:column;gap:6px}.mapping-header{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(90px,.9fr) minmax(130px,1.2fr) minmax(100px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:4px;font-weight:600;font-size:.7rem;color:var(--kendo-color-subtle, #6c757d)}.mapping-row{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(90px,.9fr) minmax(130px,1.2fr) minmax(100px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;align-items:center}.col-property{font-weight:500;font-size:.85rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.col-type.type-badge{font-size:.65rem;padding:2px 4px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:10px;text-align:center;color:var(--kendo-color-subtle, #6c757d)}.col-expression kendo-textbox{font-family:var(--theme-font-mono);font-size:.8rem}.expression-help{margin-top:12px}.expression-help code{background:var(--kendo-color-surface-alt, #f8f9fa);padding:1px 4px;border-radius:3px;font-size:.75rem}.tab-content{container-type:inline-size}@container (max-width: 560px){.mapping-header{display:none}.mapping-row{grid-template-columns:repeat(2,minmax(0,1fr))}.mapping-row .col-property{grid-column:1}.mapping-row .col-type{grid-column:2;justify-self:end;min-width:55px}.mapping-row .col-binding{grid-column:1}.mapping-row .col-aggregate{grid-column:2}.mapping-row .col-path{grid-column:1}.mapping-row .col-expression{grid-column:2}}.connections-section{margin-top:20px}.section-title{margin:0 0 6px;font-size:.9rem;font-weight:600}.connection-list{display:flex;flex-direction:column;gap:6px}.connection-row{display:grid;grid-template-columns:minmax(80px,1fr) 120px minmax(160px,1.4fr);gap:4px 10px;align-items:center;padding:6px 10px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.connection-name{font-weight:500;font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-source{grid-column:1 / -1}.connection-preview .flow-line{stroke:var(--kendo-color-primary, #0d6efd);stroke-width:3;stroke-dasharray:8 5;stroke-linecap:round}.connection-preview .flow-arrow{fill:var(--kendo-color-primary, #0d6efd)}@container (max-width: 560px){.connection-row{grid-template-columns:1fr}}.save-issues{margin:0 16px;padding:8px 10px;border:1px solid var(--kendo-color-error, #dc3545);border-radius:4px;color:var(--kendo-color-error, #dc3545);font-size:.8rem}.save-issues p{margin:0}.loading-hint{font-style:italic;color:var(--kendo-color-subtle, #6c757d);padding:8px;text-align:center}:host ::ng-deep kendo-tabstrip{border:none}:host ::ng-deep .k-tabstrip-items-wrapper{border-bottom:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .k-tabstrip-content{border:none;padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: LayoutModule }, { kind: "component", type: i5.TabStripComponent, selector: "kendo-tabstrip", inputs: ["height", "animate", "tabAlignment", "tabPosition", "keepTabContent", "closable", "scrollable", "size", "closeIcon", "closeIconClass", "closeSVGIcon", "showContentArea"], outputs: ["tabSelect", "tabClose", "tabScroll"], exportAs: ["kendoTabStrip"] }, { kind: "component", type: i5.TabStripTabComponent, selector: "kendo-tabstrip-tab", inputs: ["title", "disabled", "cssClass", "cssStyle", "selected", "closable", "closeIcon", "closeIconClass", "closeSVGIcon"], exportAs: ["kendoTabStripTab"] }, { kind: "directive", type: i5.TabContentDirective, selector: "[kendoTabContent]" }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: ProcessBindingCardsComponent, selector: "mm-process-binding-cards", inputs: ["drafts", "selectors", "persistentQueries", "isLoadingQueries", "filterVariables", "mappings", "nextUid"], outputs: ["draftsChange", "bindingRenamed", "bindingDeleted", "queryFilterChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
35605
35843
  }
35606
35844
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ProcessConfigDialogComponent, decorators: [{
35607
35845
  type: Component,
@@ -35648,6 +35886,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
35648
35886
  @if (storedDiagrams.length === 0 && !isLoadingDiagrams) {
35649
35887
  <p class="field-hint warning">No diagrams found. Create diagrams using the Process Designer.</p>
35650
35888
  }
35889
+ @if (diagramIssueHint) {
35890
+ <p class="field-hint warning diagram-issue-hint" role="status">{{ diagramIssueHint }}</p>
35891
+ }
35651
35892
  </div>
35652
35893
 
35653
35894
  <!-- Preview Section -->
@@ -35739,6 +35980,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
35739
35980
  <kendo-combobox
35740
35981
  class="col-path"
35741
35982
  [attr.aria-label]="'Field of ' + prop.name"
35983
+ [title]="getMappingSourcePath(prop.id) || ''"
35742
35984
  [data]="attributes"
35743
35985
  textField="attributePath"
35744
35986
  valueField="attributePath"
@@ -35753,6 +35995,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
35753
35995
  <kendo-textbox
35754
35996
  class="col-path"
35755
35997
  [attr.aria-label]="'Field of ' + prop.name"
35998
+ [title]="getMappingSourcePath(prop.id) || ''"
35756
35999
  [value]="getMappingSourcePath(prop.id)"
35757
36000
  (valueChange)="onMappingSourcePathChange(prop.id, $event)"
35758
36001
  [placeholder]="bindingModeOf(prop.id) === 'runtimeEntity' ? 'Attribute...' : 'Column...'">
@@ -35790,7 +36033,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
35790
36033
  <div class="connections-section" data-connections>
35791
36034
  <h4 class="section-title">Connections</h4>
35792
36035
  @if (connections.length === 0) {
35793
- <p class="field-hint">This diagram has no connection lines with a flow binding. Bind the flow animation, visibility or colour of a line to a property in the Process Designer to show its direction here.</p>
36036
+ <p class="field-hint">This diagram has no flow lines with a direction binding. Only line, polyline and path shapes whose flow animation, visibility or colour is bound to a property in the Process Designer are listed; plain connections between elements have no direction to pick.</p>
35794
36037
  } @else {
35795
36038
  <p class="section-hint">Each line takes its direction from the sign of a mapped value: positive flows forward, negative backward, 0 or no value shows no flow.</p>
35796
36039
  <div class="connection-list" role="list" aria-label="Connections">
@@ -35897,7 +36140,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
35897
36140
  </button>
35898
36141
  </div>
35899
36142
  </div>
35900
- `, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{flex:1;overflow-y:auto;padding:16px}.tab-content{padding:16px;min-height:200px;position:relative}.tab-content.loading{pointer-events:none}.section-hint{margin:0 0 16px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.empty-hint{text-align:center;padding:24px;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-field:last-child{margin-bottom:0}.form-field.disabled{opacity:.6}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{color:var(--kendo-color-warning, #ffc107)}.form-row{display:flex;gap:24px;margin-bottom:12px}.form-row:last-child{margin-bottom:0}.checkbox-field{flex-direction:row;align-items:flex-start}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.checkbox-field .field-hint{margin-top:4px;margin-left:28px}.preview-section{margin-top:16px;padding:12px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.preview-info{display:flex;flex-direction:column;gap:6px}.preview-item{display:flex;justify-content:space-between;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border-radius:4px}.preview-label{font-weight:500;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.preview-value{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.diagram-item{display:flex;justify-content:space-between;gap:16px}.diagram-name{font-weight:500}.diagram-size{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.property-mappings-table{display:flex;flex-direction:column;gap:6px}.mapping-header{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(80px,.9fr) minmax(80px,1fr) minmax(90px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:4px;font-weight:600;font-size:.7rem;color:var(--kendo-color-subtle, #6c757d)}.mapping-row{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(80px,.9fr) minmax(80px,1fr) minmax(90px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;align-items:center}.col-property{font-weight:500;font-size:.85rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.col-type.type-badge{font-size:.65rem;padding:2px 4px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:10px;text-align:center;color:var(--kendo-color-subtle, #6c757d)}.col-expression kendo-textbox{font-family:var(--theme-font-mono);font-size:.8rem}.expression-help{margin-top:12px}.expression-help code{background:var(--kendo-color-surface-alt, #f8f9fa);padding:1px 4px;border-radius:3px;font-size:.75rem}.tab-content{container-type:inline-size}@container (max-width: 560px){.mapping-header{display:none}.mapping-row{grid-template-columns:1fr 55px 1fr}.mapping-row .col-property{grid-column:1 / 3}}.connections-section{margin-top:20px}.section-title{margin:0 0 6px;font-size:.9rem;font-weight:600}.connection-list{display:flex;flex-direction:column;gap:6px}.connection-row{display:grid;grid-template-columns:minmax(80px,1fr) 120px minmax(160px,1.4fr);gap:4px 10px;align-items:center;padding:6px 10px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.connection-name{font-weight:500;font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-source{grid-column:1 / -1}.connection-preview .flow-line{stroke:var(--kendo-color-primary, #0d6efd);stroke-width:3;stroke-dasharray:8 5;stroke-linecap:round}.connection-preview .flow-arrow{fill:var(--kendo-color-primary, #0d6efd)}@container (max-width: 560px){.connection-row{grid-template-columns:1fr}}.save-issues{margin:0 16px;padding:8px 10px;border:1px solid var(--kendo-color-error, #dc3545);border-radius:4px;color:var(--kendo-color-error, #dc3545);font-size:.8rem}.save-issues p{margin:0}.loading-hint{font-style:italic;color:var(--kendo-color-subtle, #6c757d);padding:8px;text-align:center}:host ::ng-deep kendo-tabstrip{border:none}:host ::ng-deep .k-tabstrip-items-wrapper{border-bottom:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .k-tabstrip-content{border:none;padding:0}\n"] }]
36143
+ `, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{flex:1;overflow-y:auto;padding:16px}.tab-content{padding:16px;min-height:200px;position:relative}.tab-content.loading{pointer-events:none}.section-hint{margin:0 0 16px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.empty-hint{text-align:center;padding:24px;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-field:last-child{margin-bottom:0}.form-field.disabled{opacity:.6}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.field-hint.warning{color:var(--kendo-color-warning, #ffc107)}.form-row{display:flex;gap:24px;margin-bottom:12px}.form-row:last-child{margin-bottom:0}.checkbox-field{flex-direction:row;align-items:flex-start}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.checkbox-field .field-hint{margin-top:4px;margin-left:28px}.preview-section{margin-top:16px;padding:12px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.preview-info{display:flex;flex-direction:column;gap:6px}.preview-item{display:flex;justify-content:space-between;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border-radius:4px}.preview-label{font-weight:500;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.preview-value{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529)}.diagram-item{display:flex;justify-content:space-between;gap:16px}.diagram-name{font-weight:500}.diagram-size{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.property-mappings-table{display:flex;flex-direction:column;gap:6px}.mapping-header{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(90px,.9fr) minmax(130px,1.2fr) minmax(100px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:4px;font-weight:600;font-size:.7rem;color:var(--kendo-color-subtle, #6c757d)}.mapping-row{display:grid;grid-template-columns:minmax(70px,1fr) 55px minmax(90px,.9fr) minmax(130px,1.2fr) minmax(100px,.9fr) minmax(80px,1fr);gap:6px;padding:6px 10px;background:var(--kendo-color-surface, #ffffff);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;align-items:center}.col-property{font-weight:500;font-size:.85rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.col-type.type-badge{font-size:.65rem;padding:2px 4px;background:var(--kendo-color-surface-alt, #f8f9fa);border-radius:10px;text-align:center;color:var(--kendo-color-subtle, #6c757d)}.col-expression kendo-textbox{font-family:var(--theme-font-mono);font-size:.8rem}.expression-help{margin-top:12px}.expression-help code{background:var(--kendo-color-surface-alt, #f8f9fa);padding:1px 4px;border-radius:3px;font-size:.75rem}.tab-content{container-type:inline-size}@container (max-width: 560px){.mapping-header{display:none}.mapping-row{grid-template-columns:repeat(2,minmax(0,1fr))}.mapping-row .col-property{grid-column:1}.mapping-row .col-type{grid-column:2;justify-self:end;min-width:55px}.mapping-row .col-binding{grid-column:1}.mapping-row .col-aggregate{grid-column:2}.mapping-row .col-path{grid-column:1}.mapping-row .col-expression{grid-column:2}}.connections-section{margin-top:20px}.section-title{margin:0 0 6px;font-size:.9rem;font-weight:600}.connection-list{display:flex;flex-direction:column;gap:6px}.connection-row{display:grid;grid-template-columns:minmax(80px,1fr) 120px minmax(160px,1.4fr);gap:4px 10px;align-items:center;padding:6px 10px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.connection-name{font-weight:500;font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-source{grid-column:1 / -1}.connection-preview .flow-line{stroke:var(--kendo-color-primary, #0d6efd);stroke-width:3;stroke-dasharray:8 5;stroke-linecap:round}.connection-preview .flow-arrow{fill:var(--kendo-color-primary, #0d6efd)}@container (max-width: 560px){.connection-row{grid-template-columns:1fr}}.save-issues{margin:0 16px;padding:8px 10px;border:1px solid var(--kendo-color-error, #dc3545);border-radius:4px;color:var(--kendo-color-error, #dc3545);font-size:.8rem}.save-issues p{margin:0}.loading-hint{font-style:italic;color:var(--kendo-color-subtle, #6c757d);padding:8px;text-align:center}:host ::ng-deep kendo-tabstrip{border:none}:host ::ng-deep .k-tabstrip-items-wrapper{border-bottom:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .k-tabstrip-content{border:none;padding:0}\n"] }]
35901
36144
  }], propDecorators: { initialProcessDiagramRtId: [{
35902
36145
  type: Input
35903
36146
  }], initialFitToBounds: [{