@meshmakers/octo-meshboard 3.5.600 → 3.5.610

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,12 +1,12 @@
1
1
  import { FieldFilterOperatorsDto, CkTypeSelectorService, RuntimeEntitySelectDataSource, RuntimeEntityDialogDataSource, DeleteStrategiesDto, AssociationModOptionsDto, CkModelService, TENANT_ID_PROVIDER, OCTO_SILENT_ERRORS, QueryModeDto, GraphDirectionDto, AttributeSelectorService, GraphQL, GetCkTypeAvailableQueryColumnsDtoGQL, SortOrdersDto, SeriesResolutionSignalDto, HealthService, AssetRepoService, JobManagementService, CONFIGURATION_SERVICE, SystemCommunicationDeploymentStateDto, SystemCommunicationConfigurationStateDto, HealthStatus } from '@meshmakers/octo-services';
2
2
  export { RuntimeEntityDialogDataSource, RuntimeEntitySelectDataSource, TENANT_ID_PROVIDER } from '@meshmakers/octo-services';
3
3
  import * as i0 from '@angular/core';
4
- import { Injectable, inject, EventEmitter, forwardRef, Output, Input, ViewChild, ChangeDetectionStrategy, Component, input, Directive, model, computed, Injector, EnvironmentInjector, ApplicationRef, signal, effect, untracked, InjectionToken, isSignal, LOCALE_ID, NgZone, DestroyRef, ElementRef, ChangeDetectorRef, ViewChildren, createEnvironmentInjector, ViewContainerRef, makeEnvironmentProviders, provideAppInitializer, output, viewChild } from '@angular/core';
4
+ import { Injectable, inject, EventEmitter, forwardRef, Output, Input, ViewChild, ChangeDetectionStrategy, Component, input, Directive, model, computed, ElementRef, Injector, EnvironmentInjector, ApplicationRef, signal, effect, untracked, InjectionToken, isSignal, LOCALE_ID, NgZone, DestroyRef, ChangeDetectorRef, ViewChildren, createEnvironmentInjector, ViewContainerRef, makeEnvironmentProviders, provideAppInitializer, output, viewChild } from '@angular/core';
5
5
  import * as i1$1 from '@angular/forms';
6
6
  import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS } from '@angular/forms';
7
7
  import { firstValueFrom, from, map, Observable, of, switchMap as switchMap$1, forkJoin, catchError, NEVER, interval, Subject, BehaviorSubject, filter as filter$1, combineLatest, defer, EMPTY } from 'rxjs';
8
8
  import * as i1$8 from '@meshmakers/shared-ui';
9
- import { EntitySelectInputComponent, WindowStateService, TimeRangeUtils, MmDialogActionsDirective, ListViewComponent, FetchResultTyped, DataSourceBase, MM_ACTION_ICONS, ConfirmationService, TimeRangePickerComponent, ImportStrategyDialogService, HAS_UNSAVED_CHANGES, UnsavedChangesDirective } from '@meshmakers/shared-ui';
9
+ import { EntitySelectInputComponent, MM_ACTION_ICONS, WindowStateService, TimeRangeUtils, MmDialogActionsDirective, ListViewComponent, FetchResultTyped, DataSourceBase, ConfirmationService, TimeRangePickerComponent, ImportStrategyDialogService, HAS_UNSAVED_CHANGES, UnsavedChangesDirective } from '@meshmakers/shared-ui';
10
10
  import * as i1 from 'apollo-angular';
11
11
  import { gql, Apollo } from 'apollo-angular';
12
12
  import * as i1$3 from '@angular/common';
@@ -17,6 +17,7 @@ import { ButtonsModule, ButtonModule } from '@progress/kendo-angular-buttons';
17
17
  import * as i3 from '@progress/kendo-angular-inputs';
18
18
  import { InputsModule, CheckBoxModule, NumericTextBoxModule, TextBoxModule, FormFieldModule } from '@progress/kendo-angular-inputs';
19
19
  import { ExpressionEvaluatorService, GetProcessDiagramDtoGQL, GetProcessDiagramsDtoGQL, CreateProcessDiagramDtoGQL, UpdateProcessDiagramDtoGQL, SymbolLibraryService, renderAnimations, getFlowParticlesAnimation, renderFlowParticles, evaluateTextValue, applyTextValueToPrimitive } from '@meshmakers/octo-process-diagrams';
20
+ import { plusIcon, arrowUpIcon, arrowDownIcon, minusIcon, arrowRightIcon, arrowLeftIcon, linkIcon, chevronDownIcon, chevronRightIcon, circleIcon, questionCircleIcon, minusCircleIcon, warningTriangleIcon, exclamationCircleIcon, xCircleIcon, checkCircleIcon, columnsIcon, sortAscIcon, filterIcon, searchIcon, trashIcon, chartPieIcon, infoCircleIcon, pencilIcon, chartLineIcon, clockArrowRotateIcon, dataIcon, connectorIcon, chartAreaRangeIcon, gearsIcon, clipboardMarkdownIcon, copyIcon, gridIcon, heartIcon, gridLayoutIcon, chartLineMarkersIcon, chartColumnStackedIcon, chartDoughnutIcon, tableIcon, shareIcon, fileTxtIcon, checkIcon, xIcon, uploadIcon, pinIcon, unpinIcon, gearIcon, saveIcon, arrowRotateCwIcon, undoIcon } from '@progress/kendo-svg-icons';
20
21
  import * as i1$5 from '@progress/kendo-angular-dialog';
21
22
  import { WindowService, WindowCloseResult, WindowRef, DialogsModule, DialogRef, DialogModule, DialogService } from '@progress/kendo-angular-dialog';
22
23
  import { switchMap, map as map$1, catchError as catchError$1, take, debounceTime, filter, startWith, shareReplay, tap } from 'rxjs/operators';
@@ -26,7 +27,6 @@ import * as i1$2 from '@progress/kendo-angular-indicators';
26
27
  import { LoaderModule } from '@progress/kendo-angular-indicators';
27
28
  import * as i1$4 from '@progress/kendo-angular-icons';
28
29
  import { SVGIconModule } from '@progress/kendo-angular-icons';
29
- import { arrowUpIcon, arrowDownIcon, minusIcon, arrowRightIcon, arrowLeftIcon, linkIcon, chevronDownIcon, chevronRightIcon, circleIcon, questionCircleIcon, minusCircleIcon, warningTriangleIcon, exclamationCircleIcon, xCircleIcon, checkCircleIcon, columnsIcon, sortAscIcon, filterIcon, searchIcon, plusIcon, trashIcon, chartPieIcon, infoCircleIcon, pencilIcon, chartLineIcon, clockArrowRotateIcon, dataIcon, connectorIcon, chartAreaRangeIcon, gearsIcon, clipboardMarkdownIcon, copyIcon, gridIcon, heartIcon, gridLayoutIcon, chartLineMarkersIcon, chartColumnStackedIcon, chartDoughnutIcon, tableIcon, shareIcon, fileTxtIcon, checkIcon, xIcon, uploadIcon, pinIcon, unpinIcon, gearIcon, saveIcon, arrowRotateCwIcon, undoIcon } from '@progress/kendo-svg-icons';
30
30
  import { NotificationService } from '@progress/kendo-angular-notification';
31
31
  import * as i1$6 from '@progress/kendo-angular-gauges';
32
32
  import { CollectionChangesService, KENDO_GAUGES } from '@progress/kendo-angular-gauges';
@@ -1687,6 +1687,251 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
1687
1687
  `, styles: [":host{display:flex;flex-direction:column;gap:20px}.form-field{display:flex;flex-direction:column;gap:6px}.form-field label,.field-label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface)}.required,.field-error{color:var(--kendo-color-error)}.field-hint,.field-error{margin:0;font-size:.8rem}.field-hint,.variable-source{color:var(--kendo-color-subtle)}.variable-list{display:flex;flex-wrap:wrap;gap:4px}\n"] }]
1688
1688
  }], propDecorators: { formula: [{ type: i0.Input, args: [{ isSignal: true, alias: "formula", required: false }] }, { type: i0.Output, args: ["formulaChange"] }], variables: [{ type: i0.Input, args: [{ isSignal: true, alias: "variables", required: false }] }], declaredNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "declaredNames", required: false }] }], numericOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "numericOnly", required: false }] }], clampHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "clampHint", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], variablesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "variablesLabel", required: false }] }], namesNoun: [{ type: i0.Input, args: [{ isSignal: true, alias: "namesNoun", required: false }] }], syntaxHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "syntaxHint", required: false }] }], emptyVariablesText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyVariablesText", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
1689
1689
 
1690
+ /**
1691
+ * Display names for the raw values of a chart field (`categoryLabels` / `seriesLabels`).
1692
+ * Display only: the widgets group, filter and match on the raw value and rename at the very end.
1693
+ */
1694
+ /**
1695
+ * Cleans a label map from a dialog or a persisted config: keeps the entries with a non-empty key and
1696
+ * a non-blank string name (the name is trimmed, the key is kept exactly as stored) and returns
1697
+ * `undefined` when nothing is left, so an empty map is never stored.
1698
+ */
1699
+ function normalizeChartValueLabels(labels) {
1700
+ if (!labels || typeof labels !== 'object' || Array.isArray(labels)) {
1701
+ return undefined;
1702
+ }
1703
+ const normalized = {};
1704
+ for (const [rawValue, label] of Object.entries(labels)) {
1705
+ const text = typeof label === 'string' ? label.trim() : '';
1706
+ if (rawValue !== '' && text !== '') {
1707
+ normalized[rawValue] = text;
1708
+ }
1709
+ }
1710
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
1711
+ }
1712
+ /**
1713
+ * The configured name of a raw value, `undefined` when there is none. Own keys only: a raw value such
1714
+ * as `constructor` must not find an inherited member of the map.
1715
+ */
1716
+ function configuredValueLabel(labels, rawValue) {
1717
+ if (!labels || !Object.prototype.hasOwnProperty.call(labels, rawValue)) {
1718
+ return undefined;
1719
+ }
1720
+ const label = labels[rawValue];
1721
+ return typeof label === 'string' && label !== '' ? label : undefined;
1722
+ }
1723
+ /**
1724
+ * The legend name of each raw series value. Chart series are keyed by their name, so a name that two
1725
+ * raw values share would merge or collide the two series; such a name is shown as `Name (raw value)`.
1726
+ * A unique name is used as it is, a raw value without an entry maps to itself.
1727
+ */
1728
+ function seriesLabelsByRawValue(rawValues, labels) {
1729
+ const unique = Array.from(new Set(rawValues));
1730
+ const nameOf = (raw) => configuredValueLabel(labels, raw) ?? raw;
1731
+ const usage = new Map();
1732
+ for (const raw of unique) {
1733
+ usage.set(nameOf(raw), (usage.get(nameOf(raw)) ?? 0) + 1);
1734
+ }
1735
+ const result = new Map();
1736
+ for (const raw of unique) {
1737
+ const name = nameOf(raw);
1738
+ result.set(raw, name !== raw && (usage.get(name) ?? 0) > 1 ? `${name} (${raw})` : name);
1739
+ }
1740
+ return result;
1741
+ }
1742
+ /** Editor rows of a label map, in the order the map lists them; ids start at `firstId`. */
1743
+ function toValueLabelRows(labels, firstId = 1) {
1744
+ return Object.entries(normalizeChartValueLabels(labels) ?? {}).map(([value, label], index) => ({ id: firstId + index, value, label }));
1745
+ }
1746
+ /**
1747
+ * The label map of the editor rows. Only complete rows count (value and name both filled in, the
1748
+ * value trimmed); an unfinished row is skipped before it can replace a complete row of the same
1749
+ * value. Of two complete rows with the same value the later one wins. `undefined` when nothing is left.
1750
+ */
1751
+ function fromValueLabelRows(rows) {
1752
+ const labels = {};
1753
+ for (const row of rows ?? []) {
1754
+ const value = (row.value ?? '').trim();
1755
+ const label = (row.label ?? '').trim();
1756
+ if (value !== '' && label !== '') {
1757
+ labels[value] = label;
1758
+ }
1759
+ }
1760
+ return normalizeChartValueLabels(labels);
1761
+ }
1762
+ /** Raw values that more than one complete row lists (trimmed; unfinished rows are ignored), each reported once. */
1763
+ function duplicateValueLabelValues(rows) {
1764
+ const seen = new Set();
1765
+ const duplicates = new Set();
1766
+ for (const row of rows ?? []) {
1767
+ const value = (row.value ?? '').trim();
1768
+ if (value === '' || (row.label ?? '').trim() === '') {
1769
+ continue;
1770
+ }
1771
+ if (seen.has(value)) {
1772
+ duplicates.add(value);
1773
+ }
1774
+ seen.add(value);
1775
+ }
1776
+ return Array.from(duplicates);
1777
+ }
1778
+
1779
+ /**
1780
+ * Edits the names of a chart widget's raw values (`categoryLabels` / `seriesLabels`) in its config
1781
+ * dialog: one row per raw value with the name to show instead (e.g. an OBIS code and what it means).
1782
+ *
1783
+ * The dialog owns the rows (`[(rows)]`) and turns them into the label map on Save with
1784
+ * `fromValueLabelRows`, which drops unfinished rows.
1785
+ *
1786
+ * ```html
1787
+ * <mm-value-labels-editor [(rows)]="categoryLabelRows" subject="category"></mm-value-labels-editor>
1788
+ * ```
1789
+ */
1790
+ class ValueLabelsEditorComponent {
1791
+ host = inject(ElementRef);
1792
+ /** The editor rows (two-way: `[(rows)]`); the editor replaces the array on every change. */
1793
+ rows = model([], /* @ts-ignore */
1794
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
1795
+ /** What the raw values are, used in the texts: `category` or `series`. */
1796
+ subject = input('category', /* @ts-ignore */
1797
+ ...(ngDevMode ? [{ debugName: "subject" }] : /* istanbul ignore next */ []));
1798
+ subjectTitle = computed(() => {
1799
+ const subject = this.subject();
1800
+ return subject.charAt(0).toUpperCase() + subject.slice(1);
1801
+ }, /* @ts-ignore */
1802
+ ...(ngDevMode ? [{ debugName: "subjectTitle" }] : /* istanbul ignore next */ []));
1803
+ /** Raw values that more than one complete row lists; only the last of them takes effect. */
1804
+ duplicates = computed(() => duplicateValueLabelValues(this.rows()), /* @ts-ignore */
1805
+ ...(ngDevMode ? [{ debugName: "duplicates" }] : /* istanbul ignore next */ []));
1806
+ get addIcon() { return plusIcon; }
1807
+ get removeIcon() { return MM_ACTION_ICONS.delete; }
1808
+ add() {
1809
+ const id = this.rows().reduce((max, row) => Math.max(max, row.id), 0) + 1;
1810
+ this.rows.set([...this.rows(), { id, value: '', label: '' }]);
1811
+ this.focusRow(id);
1812
+ }
1813
+ remove(id) {
1814
+ const rows = this.rows();
1815
+ const index = rows.findIndex(row => row.id === id);
1816
+ if (index < 0) {
1817
+ return;
1818
+ }
1819
+ const remaining = rows.filter(row => row.id !== id);
1820
+ this.rows.set(remaining);
1821
+ const next = remaining[Math.min(index, remaining.length - 1)];
1822
+ if (next) {
1823
+ this.focusRow(next.id);
1824
+ }
1825
+ else {
1826
+ setTimeout(() => this.host.nativeElement.querySelector('[data-value-labels-action="add"]')?.focus());
1827
+ }
1828
+ }
1829
+ edit(id, field, text) {
1830
+ this.rows.set(this.rows().map(row => row.id === id ? { ...row, [field]: text ?? '' } : row));
1831
+ }
1832
+ focusRow(id) {
1833
+ setTimeout(() => this.host.nativeElement.querySelector(`[data-value-label-row="${id}"] input`)?.focus());
1834
+ }
1835
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ValueLabelsEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1836
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: ValueLabelsEditorComponent, isStandalone: true, selector: "mm-value-labels-editor", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rows: "rowsChange" }, ngImport: i0, template: `
1837
+ <div class="value-labels" role="group" [attr.aria-label]="subjectTitle() + ' names'">
1838
+ <p class="value-labels-hint">
1839
+ Optional. Shows a name instead of the raw {{ subject() }} value, e.g. for a code. Enter the value as the
1840
+ data delivers it (blanks around it are removed); a row without a name is not saved, and values without a name are shown unchanged.
1841
+ </p>
1842
+
1843
+ @if (rows().length === 0) {
1844
+ <p class="value-labels-empty" data-value-labels-empty>No names yet - values are shown as the data delivers them.</p>
1845
+ } @else {
1846
+ <div class="value-label-header" aria-hidden="true">
1847
+ <span>Value</span>
1848
+ <span>Name to display</span>
1849
+ </div>
1850
+ }
1851
+
1852
+ @for (row of rows(); track row.id; let i = $index) {
1853
+ <div class="value-label-row" [attr.data-value-label-row]="row.id">
1854
+ <kendo-textbox class="value-input"
1855
+ [ngModel]="row.value"
1856
+ (ngModelChange)="edit(row.id, 'value', $event)"
1857
+ placeholder="e.g. 1-1:2.9.0 G.03"
1858
+ [inputAttributes]="{ 'aria-label': subjectTitle() + ' value, entry ' + (i + 1) }">
1859
+ </kendo-textbox>
1860
+ <kendo-textbox class="name-input"
1861
+ [ngModel]="row.label"
1862
+ (ngModelChange)="edit(row.id, 'label', $event)"
1863
+ placeholder="e.g. Feed-in"
1864
+ [inputAttributes]="{ 'aria-label': subjectTitle() + ' name, entry ' + (i + 1) }">
1865
+ </kendo-textbox>
1866
+ <button kendoButton fillMode="flat" type="button" class="remove-button" [svgIcon]="removeIcon"
1867
+ [attr.aria-label]="'Remove ' + subject() + ' name, entry ' + (i + 1)" title="Remove"
1868
+ (click)="remove(row.id)"></button>
1869
+ </div>
1870
+ }
1871
+
1872
+ @if (duplicates().length > 0) {
1873
+ <p class="value-labels-warning" role="status" data-value-labels-duplicates>
1874
+ Listed more than once: {{ duplicates().join(', ') }}. The last entry is used.
1875
+ </p>
1876
+ }
1877
+
1878
+ <button kendoButton fillMode="flat" type="button" [svgIcon]="addIcon" data-value-labels-action="add" (click)="add()">
1879
+ Add {{ subject() }} name
1880
+ </button>
1881
+ </div>
1882
+ `, isInline: true, styles: [":host{display:block;container-type:inline-size}.value-labels-hint,.value-labels-empty{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle)}.value-label-header,.value-label-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) 40px;align-items:center;gap:8px;margin-bottom:6px}.value-label-header{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface)}.value-labels-warning{margin:0 0 8px;font-size:.85rem;color:var(--kendo-color-warning)}@container (max-width: 420px){.value-label-header{display:none}.value-label-row{grid-template-columns:minmax(0,1fr) 40px;grid-template-areas:\"value remove\" \"name remove\";margin-bottom:12px}.value-label-row .value-input{grid-area:value}.value-label-row .name-input{grid-area:name}.value-label-row .remove-button{grid-area:remove}}\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: 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1883
+ }
1884
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: ValueLabelsEditorComponent, decorators: [{
1885
+ type: Component,
1886
+ args: [{ selector: 'mm-value-labels-editor', standalone: true, imports: [FormsModule, ButtonsModule, InputsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
1887
+ <div class="value-labels" role="group" [attr.aria-label]="subjectTitle() + ' names'">
1888
+ <p class="value-labels-hint">
1889
+ Optional. Shows a name instead of the raw {{ subject() }} value, e.g. for a code. Enter the value as the
1890
+ data delivers it (blanks around it are removed); a row without a name is not saved, and values without a name are shown unchanged.
1891
+ </p>
1892
+
1893
+ @if (rows().length === 0) {
1894
+ <p class="value-labels-empty" data-value-labels-empty>No names yet - values are shown as the data delivers them.</p>
1895
+ } @else {
1896
+ <div class="value-label-header" aria-hidden="true">
1897
+ <span>Value</span>
1898
+ <span>Name to display</span>
1899
+ </div>
1900
+ }
1901
+
1902
+ @for (row of rows(); track row.id; let i = $index) {
1903
+ <div class="value-label-row" [attr.data-value-label-row]="row.id">
1904
+ <kendo-textbox class="value-input"
1905
+ [ngModel]="row.value"
1906
+ (ngModelChange)="edit(row.id, 'value', $event)"
1907
+ placeholder="e.g. 1-1:2.9.0 G.03"
1908
+ [inputAttributes]="{ 'aria-label': subjectTitle() + ' value, entry ' + (i + 1) }">
1909
+ </kendo-textbox>
1910
+ <kendo-textbox class="name-input"
1911
+ [ngModel]="row.label"
1912
+ (ngModelChange)="edit(row.id, 'label', $event)"
1913
+ placeholder="e.g. Feed-in"
1914
+ [inputAttributes]="{ 'aria-label': subjectTitle() + ' name, entry ' + (i + 1) }">
1915
+ </kendo-textbox>
1916
+ <button kendoButton fillMode="flat" type="button" class="remove-button" [svgIcon]="removeIcon"
1917
+ [attr.aria-label]="'Remove ' + subject() + ' name, entry ' + (i + 1)" title="Remove"
1918
+ (click)="remove(row.id)"></button>
1919
+ </div>
1920
+ }
1921
+
1922
+ @if (duplicates().length > 0) {
1923
+ <p class="value-labels-warning" role="status" data-value-labels-duplicates>
1924
+ Listed more than once: {{ duplicates().join(', ') }}. The last entry is used.
1925
+ </p>
1926
+ }
1927
+
1928
+ <button kendoButton fillMode="flat" type="button" [svgIcon]="addIcon" data-value-labels-action="add" (click)="add()">
1929
+ Add {{ subject() }} name
1930
+ </button>
1931
+ </div>
1932
+ `, styles: [":host{display:block;container-type:inline-size}.value-labels-hint,.value-labels-empty{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle)}.value-label-header,.value-label-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) 40px;align-items:center;gap:8px;margin-bottom:6px}.value-label-header{font-weight:600;font-size:.85rem;color:var(--kendo-color-on-app-surface)}.value-labels-warning{margin:0 0 8px;font-size:.85rem;color:var(--kendo-color-warning)}@container (max-width: 420px){.value-label-header{display:none}.value-label-row{grid-template-columns:minmax(0,1fr) 40px;grid-template-areas:\"value remove\" \"name remove\";margin-bottom:12px}.value-label-row .value-input{grid-area:value}.value-label-row .name-input{grid-area:name}.value-label-row .remove-button{grid-area:remove}}\n"] }]
1933
+ }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }, { type: i0.Output, args: ["rowsChange"] }], subject: [{ type: i0.Input, args: [{ isSignal: true, alias: "subject", required: false }] }] } });
1934
+
1690
1935
  const GetDashboardsDocumentDto = gql `
1691
1936
  query getDashboards($first: Int) {
1692
1937
  runtime {
@@ -15207,13 +15452,15 @@ class PieChartWidgetComponent {
15207
15452
  this.resizeObserver?.disconnect();
15208
15453
  }
15209
15454
  /**
15210
- * Human label and status colour for a raw category value (exposed for tests). The label is the
15211
- * host resolver's text (AB#5622), else the humanized category; the colour still follows the raw value.
15455
+ * Label and colour for a raw category value (exposed for tests). The label is the `categoryLabels`
15456
+ * entry of the widget config (AB#7235), else the host resolver's text (AB#5622), else the
15457
+ * humanized category. The colour still follows the raw value (and, as before, the resolver text).
15212
15458
  */
15213
15459
  toItem(rawCategory, value, index = 0, palette = chartSeriesColors()) {
15214
- const category = this.categoryLabel(rawCategory);
15460
+ const hostLabel = this.categoryLabel(rawCategory);
15461
+ const category = configuredValueLabel(this.config?.categoryLabels, rawCategory) ?? hostLabel;
15215
15462
  const status = categoryStatus(rawCategory);
15216
- const color = this.configuredColor(rawCategory, category)
15463
+ const color = this.configuredColor(rawCategory, hostLabel)
15217
15464
  ?? (status ? statusColor(status) : undefined)
15218
15465
  ?? (palette.length ? palette[index % palette.length] : undefined);
15219
15466
  return { category, value, ...(color ? { color } : {}) };
@@ -15573,6 +15820,7 @@ class PieChartConfigDialogComponent {
15573
15820
  initialCkGroupBy;
15574
15821
  initialFilters;
15575
15822
  initialCategoryColors;
15823
+ initialCategoryLabels;
15576
15824
  initialLabelPosition;
15577
15825
  initialHideLabelsBelowPercent;
15578
15826
  addIcon = plusIcon;
@@ -15580,6 +15828,8 @@ class PieChartConfigDialogComponent {
15580
15828
  /** Rows of the category colour editor (AB#5622). */
15581
15829
  categoryColorRows = [];
15582
15830
  nextCategoryColorId = 1;
15831
+ /** Rows of the category name editor (AB#7235). */
15832
+ categoryLabelRows = [];
15583
15833
  labelPositions = [
15584
15834
  { value: undefined, label: 'Default' },
15585
15835
  { value: 'outside', label: 'Outside (with connector lines)' },
@@ -15674,6 +15924,7 @@ class PieChartConfigDialogComponent {
15674
15924
  this.form.ckGroupBy = this.initialCkGroupBy ?? 'modelState';
15675
15925
  this.form.labelPosition = this.initialLabelPosition;
15676
15926
  this.form.hideLabelsBelowPercent = this.initialHideLabelsBelowPercent ?? 0;
15927
+ this.categoryLabelRows = toValueLabelRows(this.initialCategoryLabels);
15677
15928
  this.categoryColorRows = Object.entries(this.initialCategoryColors ?? {}).map(([category, color]) => ({ id: this.nextCategoryColorId++, category, color }));
15678
15929
  this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
15679
15930
  this.entitySelectorId = this.initialEntitySelectorId;
@@ -15855,6 +16106,10 @@ class PieChartConfigDialogComponent {
15855
16106
  if (categoryColors) {
15856
16107
  result.categoryColors = categoryColors;
15857
16108
  }
16109
+ const categoryLabels = fromValueLabelRows(this.categoryLabelRows);
16110
+ if (categoryLabels) {
16111
+ result.categoryLabels = categoryLabels;
16112
+ }
15858
16113
  if (this.form.displayMode === 'labels') {
15859
16114
  if (this.form.labelPosition) {
15860
16115
  result.labelPosition = this.form.labelPosition;
@@ -15882,7 +16137,7 @@ class PieChartConfigDialogComponent {
15882
16137
  this.windowRef.close();
15883
16138
  }
15884
16139
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PieChartConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
15885
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: PieChartConfigDialogComponent, isStandalone: true, selector: "mm-pie-chart-config-dialog", inputs: { initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialValueField: "initialValueField", initialShowLabels: "initialShowLabels", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialCkQueryTarget: "initialCkQueryTarget", initialCkGroupBy: "initialCkGroupBy", initialFilters: "initialFilters", initialCategoryColors: "initialCategoryColors", initialLabelPosition: "initialLabelPosition", initialHideLabelsBelowPercent: "initialHideLabelsBelowPercent" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
16140
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: PieChartConfigDialogComponent, isStandalone: true, selector: "mm-pie-chart-config-dialog", inputs: { initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialValueField: "initialValueField", initialShowLabels: "initialShowLabels", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialCkQueryTarget: "initialCkQueryTarget", initialCkGroupBy: "initialCkGroupBy", initialFilters: "initialFilters", initialCategoryColors: "initialCategoryColors", initialCategoryLabels: "initialCategoryLabels", initialLabelPosition: "initialLabelPosition", initialHideLabelsBelowPercent: "initialHideLabelsBelowPercent" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
15886
16141
  <div class="config-container">
15887
16142
 
15888
16143
  <div class="config-form" [class.loading]="isLoadingInitial">
@@ -16018,6 +16273,12 @@ class PieChartConfigDialogComponent {
16018
16273
  </div>
16019
16274
  }
16020
16275
 
16276
+ <!-- Category Names Section (AB#7235) -->
16277
+ <div class="config-section" data-pie-category-labels>
16278
+ <h3 class="section-title">Category Names</h3>
16279
+ <mm-value-labels-editor [(rows)]="categoryLabelRows" subject="category"></mm-value-labels-editor>
16280
+ </div>
16281
+
16021
16282
  <!-- Chart Options Section -->
16022
16283
  <div class="config-section">
16023
16284
  <h3 class="section-title">Chart Options</h3>
@@ -16134,7 +16395,7 @@ class PieChartConfigDialogComponent {
16134
16395
  </button>
16135
16396
  </div>
16136
16397
  </div>
16137
- `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{display:flex;flex-direction:column;flex:1;overflow-y:auto;gap:20px;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.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)}.category-color-row{display:flex;gap:8px;align-items:center;margin-bottom:6px}.category-color-row kendo-textbox{flex:1;min-width:0}.category-color-swatch{width:32px;height:28px;padding:0;border:none;background:none;cursor:pointer}.radio-group{display:flex;gap:24px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.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)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { 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: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { 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: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
16398
+ `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{display:flex;flex-direction:column;flex:1;overflow-y:auto;gap:20px;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.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)}.category-color-row{display:flex;gap:8px;align-items:center;margin-bottom:6px}.category-color-row kendo-textbox{flex:1;min-width:0}.category-color-swatch{width:32px;height:28px;padding:0;border:none;background:none;cursor:pointer}.radio-group{display:flex;gap:24px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.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)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { 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: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { 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: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: ValueLabelsEditorComponent, selector: "mm-value-labels-editor", inputs: ["rows", "subject"], outputs: ["rowsChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
16138
16399
  }
16139
16400
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PieChartConfigDialogComponent, decorators: [{
16140
16401
  type: Component,
@@ -16149,7 +16410,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
16149
16410
  QuerySelectorComponent,
16150
16411
  SdTimeFilterToggleComponent,
16151
16412
  EntitySelectorScopePickerComponent,
16152
- LoadingOverlayComponent
16413
+ LoadingOverlayComponent,
16414
+ ValueLabelsEditorComponent
16153
16415
  ], template: `
16154
16416
  <div class="config-container">
16155
16417
 
@@ -16286,6 +16548,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
16286
16548
  </div>
16287
16549
  }
16288
16550
 
16551
+ <!-- Category Names Section (AB#7235) -->
16552
+ <div class="config-section" data-pie-category-labels>
16553
+ <h3 class="section-title">Category Names</h3>
16554
+ <mm-value-labels-editor [(rows)]="categoryLabelRows" subject="category"></mm-value-labels-editor>
16555
+ </div>
16556
+
16289
16557
  <!-- Chart Options Section -->
16290
16558
  <div class="config-section">
16291
16559
  <h3 class="section-title">Chart Options</h3>
@@ -16438,6 +16706,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
16438
16706
  type: Input
16439
16707
  }], initialCategoryColors: [{
16440
16708
  type: Input
16709
+ }], initialCategoryLabels: [{
16710
+ type: Input
16441
16711
  }], initialLabelPosition: [{
16442
16712
  type: Input
16443
16713
  }], initialHideLabelsBelowPercent: [{
@@ -17515,7 +17785,7 @@ class BarChartWidgetComponent {
17515
17785
  return;
17516
17786
  }
17517
17787
  const converted = source.primary
17518
- ? primaryRowsToCategorySeries(f.value, this.config, valueScale)
17788
+ ? this.withSeriesLabels(primaryRowsToCategorySeries(f.value, this.config, valueScale))
17519
17789
  : (r => ({ categories: r.categories, series: [r.series] }))(queryRowsToCategorySeries(f.value, source.label, source.categoryField, source.valueField, valueScale));
17520
17790
  if (converted.categories.length === 0 || converted.series.length === 0) {
17521
17791
  noData(source);
@@ -17581,6 +17851,9 @@ class BarChartWidgetComponent {
17581
17851
  const dayOf = (c) => formatInstant(new Date(c.instant), mode, { day: '2-digit', month: '2-digit', year: 'numeric' }) ?? '';
17582
17852
  const byDay = allInstants && new Set(categories.map(dayOf)).size === categories.length;
17583
17853
  return uniqueLabels(categories.map(c => {
17854
+ const configured = configuredValueLabel(this.config.categoryLabels, String(c.raw ?? ''));
17855
+ if (configured !== undefined)
17856
+ return configured;
17584
17857
  if (byDay)
17585
17858
  return dayOf(c);
17586
17859
  if (c.instant !== null) {
@@ -17589,6 +17862,17 @@ class BarChartWidgetComponent {
17589
17862
  return String(c.raw ?? '');
17590
17863
  }));
17591
17864
  }
17865
+ /**
17866
+ * Dynamic series of the primary query shown under their `seriesLabels` names; the series of a
17867
+ * static value-field list keep their configured names.
17868
+ */
17869
+ withSeriesLabels(converted) {
17870
+ if (!this.isDynamicSeriesMode()) {
17871
+ return converted;
17872
+ }
17873
+ const names = seriesLabelsByRawValue(converted.series.map(s => s.name), this.config.seriesLabels);
17874
+ return { ...converted, series: converted.series.map(s => ({ ...s, name: names.get(s.name) ?? s.name })) };
17875
+ }
17592
17876
  /** Short message of a failed source for its hint. */
17593
17877
  errorMessage(reason) {
17594
17878
  const message = reason instanceof Error ? reason.message : typeof reason === 'string' ? reason : '';
@@ -17619,7 +17903,7 @@ class BarChartWidgetComponent {
17619
17903
  // category is not overwritten by an aggregation cell over the same attribute
17620
17904
  // (e.g. `state` vs `state_count`) — AB#4293.
17621
17905
  const categoryCell = findCellForField(row.cells, this.config.categoryField);
17622
- const categoryValue = categoryCell ? this.formatCategoryValue(categoryCell.value) : '';
17906
+ const categoryValue = categoryCell ? this.categoryText(categoryCell.value) : '';
17623
17907
  const rowValues = new Map();
17624
17908
  for (const seriesConfig of (this.config.series ?? [])) {
17625
17909
  const seriesCell = findCellForField(row.cells, seriesConfig.field);
@@ -17673,6 +17957,8 @@ class BarChartWidgetComponent {
17673
17957
  const dataMap = new Map();
17674
17958
  const allCategories = new Set();
17675
17959
  const allSeriesGroups = new Set();
17960
+ // Maps stay keyed by the formatted raw category; only a configured name replaces it at the end.
17961
+ const categoryNames = new Map();
17676
17962
  for (const row of filteredRows) {
17677
17963
  // Exact match wins over the loose aggregation-suffix fallback (AB#4293).
17678
17964
  const categoryCell = findCellForField(row.cells, categoryField);
@@ -17684,6 +17970,10 @@ class BarChartWidgetComponent {
17684
17970
  if (categoryValue && seriesGroupValue) {
17685
17971
  allCategories.add(categoryValue);
17686
17972
  allSeriesGroups.add(seriesGroupValue);
17973
+ const configured = configuredValueLabel(this.config.categoryLabels, String(categoryCell?.value ?? ''));
17974
+ if (configured !== undefined && !categoryNames.has(categoryValue)) {
17975
+ categoryNames.set(categoryValue, configured);
17976
+ }
17687
17977
  if (!dataMap.has(categoryValue)) {
17688
17978
  dataMap.set(categoryValue, new Map());
17689
17979
  }
@@ -17695,6 +17985,7 @@ class BarChartWidgetComponent {
17695
17985
  const seriesGroups = Array.from(allSeriesGroups);
17696
17986
  // Build series data
17697
17987
  const valueScale = this.config?.valueScale ?? 1;
17988
+ const seriesNames = seriesLabelsByRawValue(seriesGroups, this.config.seriesLabels);
17698
17989
  const seriesData = seriesGroups.map(seriesGroup => {
17699
17990
  const rawData = categories.map(category => {
17700
17991
  const cell = dataMap.get(category);
@@ -17705,11 +17996,11 @@ class BarChartWidgetComponent {
17705
17996
  return value === null ? null : value * valueScale;
17706
17997
  });
17707
17998
  return {
17708
- name: seriesGroup,
17999
+ name: seriesNames.get(seriesGroup) ?? seriesGroup,
17709
18000
  data: this.hasColorThresholds() ? this.applyColorThresholds(rawData) : rawData
17710
18001
  };
17711
18002
  });
17712
- this._categories.set(categories);
18003
+ this._categories.set(categories.map(category => categoryNames.get(category) ?? category));
17713
18004
  this._seriesData.set(seriesData);
17714
18005
  }
17715
18006
  /**
@@ -17749,6 +18040,10 @@ class BarChartWidgetComponent {
17749
18040
  }
17750
18041
  return defaultColor;
17751
18042
  }
18043
+ /** Axis text of a category: its `categoryLabels` name (looked up by the raw value), else the formatted value. */
18044
+ categoryText(value) {
18045
+ return configuredValueLabel(this.config.categoryLabels, String(value ?? '')) ?? this.formatCategoryValue(value);
18046
+ }
17752
18047
  formatCategoryValue(value) {
17753
18048
  // ISO-8601 date-time values are formatted on the board's timezone basis;
17754
18049
  // everything else passes through as a string.
@@ -18858,6 +19153,11 @@ class BarChartConfigDialogComponent {
18858
19153
  initialFilters;
18859
19154
  initialAdditionalSeries;
18860
19155
  initialPrimarySeries;
19156
+ initialCategoryLabels;
19157
+ initialSeriesLabels;
19158
+ /** Rows of the category and series name editors (AB#7235). */
19159
+ categoryLabelRows = [];
19160
+ seriesLabelRows = [];
18861
19161
  /** Query and formula series of the Series section (AB#7953). */
18862
19162
  additionalSeries = [];
18863
19163
  /** Display options of the primary query's series (AB#7953). */
@@ -18951,6 +19251,8 @@ class BarChartConfigDialogComponent {
18951
19251
  this.form.defaultBarColor = this.initialDefaultBarColor ?? '';
18952
19252
  this.additionalSeries = this.initialAdditionalSeries ? [...this.initialAdditionalSeries] : [];
18953
19253
  this.primarySeries = this.initialPrimarySeries ? { ...this.initialPrimarySeries } : undefined;
19254
+ this.categoryLabelRows = toValueLabelRows(this.initialCategoryLabels);
19255
+ this.seriesLabelRows = toValueLabelRows(this.initialSeriesLabels);
18954
19256
  // Determine series mode from initial values
18955
19257
  if (this.initialSeriesGroupField && this.initialValueField) {
18956
19258
  this.seriesMode = 'dynamic';
@@ -19115,7 +19417,9 @@ class BarChartConfigDialogComponent {
19115
19417
  defaultBarColor: this.form.defaultBarColor || undefined,
19116
19418
  filters: filtersDto,
19117
19419
  additionalSeries: this.effectiveAdditionalSeries.length > 0 ? this.effectiveAdditionalSeries : undefined,
19118
- primarySeries: this.selectedQueryFamily === 'streamData' ? barPrimaryOptions(this.primarySeries) : undefined
19420
+ primarySeries: this.selectedQueryFamily === 'streamData' ? barPrimaryOptions(this.primarySeries) : undefined,
19421
+ categoryLabels: fromValueLabelRows(this.categoryLabelRows),
19422
+ seriesLabels: fromValueLabelRows(this.seriesLabelRows)
19119
19423
  };
19120
19424
  // Add dynamic series fields if in dynamic mode
19121
19425
  if (this.seriesMode === 'dynamic') {
@@ -19134,7 +19438,7 @@ class BarChartConfigDialogComponent {
19134
19438
  this.windowRef.close();
19135
19439
  }
19136
19440
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: BarChartConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19137
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: BarChartConfigDialogComponent, isStandalone: true, selector: "mm-bar-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeries: "initialSeries", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowDataLabels: "initialShowDataLabels", initialColorThresholds: "initialColorThresholds", initialDefaultBarColor: "initialDefaultBarColor", initialFilters: "initialFilters", initialAdditionalSeries: "initialAdditionalSeries", initialPrimarySeries: "initialPrimarySeries" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
19441
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: BarChartConfigDialogComponent, isStandalone: true, selector: "mm-bar-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeries: "initialSeries", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowDataLabels: "initialShowDataLabels", initialColorThresholds: "initialColorThresholds", initialDefaultBarColor: "initialDefaultBarColor", initialFilters: "initialFilters", initialAdditionalSeries: "initialAdditionalSeries", initialPrimarySeries: "initialPrimarySeries", initialCategoryLabels: "initialCategoryLabels", initialSeriesLabels: "initialSeriesLabels" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
19138
19442
  <div class="config-container">
19139
19443
 
19140
19444
  <div class="config-form" [class.loading]="isLoadingInitial">
@@ -19273,6 +19577,19 @@ class BarChartConfigDialogComponent {
19273
19577
  </div>
19274
19578
  }
19275
19579
 
19580
+ <!-- Category and series names (AB#7235) -->
19581
+ <div class="config-section" data-bar-category-labels>
19582
+ <h3 class="section-title">Category Names</h3>
19583
+ <mm-value-labels-editor [(rows)]="categoryLabelRows" subject="category"></mm-value-labels-editor>
19584
+ </div>
19585
+
19586
+ @if (seriesMode === 'dynamic') {
19587
+ <div class="config-section" data-bar-series-labels>
19588
+ <h3 class="section-title">Series Names</h3>
19589
+ <mm-value-labels-editor [(rows)]="seriesLabelRows" subject="series"></mm-value-labels-editor>
19590
+ </div>
19591
+ }
19592
+
19276
19593
  <!-- Series Section (AB#7953): query and formula series matched per category -->
19277
19594
  @if (selectedQueryFamily === 'streamData') {
19278
19595
  <div class="config-section">
@@ -19424,7 +19741,7 @@ class BarChartConfigDialogComponent {
19424
19741
  </button>
19425
19742
  </div>
19426
19743
  </div>
19427
- `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.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)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.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)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.threshold-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}.threshold-row label{font-size:.85rem;min-width:70px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { 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: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { 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: "component", type: i4.MultiSelectComponent, selector: "kendo-multiselect", inputs: ["showStickyHeader", "focusableId", "autoClose", "loading", "data", "value", "valueField", "textField", "tabindex", "tabIndex", "size", "rounded", "fillMode", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "disabled", "itemDisabled", "checkboxes", "readonly", "filterable", "virtual", "popupSettings", "listHeight", "valuePrimitive", "clearButton", "tagMapper", "allowCustom", "valueNormalizer", "inputAttributes"], outputs: ["filterChange", "valueChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "removeTag"], exportAs: ["kendoMultiSelect"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: LineChartSeriesEditorComponent, selector: "mm-line-chart-series-editor", inputs: ["series", "primary", "stackedChart", "selectors", "alignment", "areaChart", "linesAllowed", "defaultCategoryField"], outputs: ["primaryChange", "seriesChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
19744
+ `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.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)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.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)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.threshold-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}.threshold-row label{font-size:.85rem;min-width:70px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { 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: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { 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: "component", type: i4.MultiSelectComponent, selector: "kendo-multiselect", inputs: ["showStickyHeader", "focusableId", "autoClose", "loading", "data", "value", "valueField", "textField", "tabindex", "tabIndex", "size", "rounded", "fillMode", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "disabled", "itemDisabled", "checkboxes", "readonly", "filterable", "virtual", "popupSettings", "listHeight", "valuePrimitive", "clearButton", "tagMapper", "allowCustom", "valueNormalizer", "inputAttributes"], outputs: ["filterChange", "valueChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "removeTag"], exportAs: ["kendoMultiSelect"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: LineChartSeriesEditorComponent, selector: "mm-line-chart-series-editor", inputs: ["series", "primary", "stackedChart", "selectors", "alignment", "areaChart", "linesAllowed", "defaultCategoryField"], outputs: ["primaryChange", "seriesChange"] }, { kind: "component", type: ValueLabelsEditorComponent, selector: "mm-value-labels-editor", inputs: ["rows", "subject"], outputs: ["rowsChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
19428
19745
  }
19429
19746
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: BarChartConfigDialogComponent, decorators: [{
19430
19747
  type: Component,
@@ -19440,7 +19757,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
19440
19757
  SdTimeFilterToggleComponent,
19441
19758
  EntitySelectorScopePickerComponent,
19442
19759
  LoadingOverlayComponent,
19443
- LineChartSeriesEditorComponent
19760
+ LineChartSeriesEditorComponent,
19761
+ ValueLabelsEditorComponent
19444
19762
  ], template: `
19445
19763
  <div class="config-container">
19446
19764
 
@@ -19580,6 +19898,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
19580
19898
  </div>
19581
19899
  }
19582
19900
 
19901
+ <!-- Category and series names (AB#7235) -->
19902
+ <div class="config-section" data-bar-category-labels>
19903
+ <h3 class="section-title">Category Names</h3>
19904
+ <mm-value-labels-editor [(rows)]="categoryLabelRows" subject="category"></mm-value-labels-editor>
19905
+ </div>
19906
+
19907
+ @if (seriesMode === 'dynamic') {
19908
+ <div class="config-section" data-bar-series-labels>
19909
+ <h3 class="section-title">Series Names</h3>
19910
+ <mm-value-labels-editor [(rows)]="seriesLabelRows" subject="series"></mm-value-labels-editor>
19911
+ </div>
19912
+ }
19913
+
19583
19914
  <!-- Series Section (AB#7953): query and formula series matched per category -->
19584
19915
  @if (selectedQueryFamily === 'streamData') {
19585
19916
  <div class="config-section">
@@ -19771,6 +20102,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
19771
20102
  type: Input
19772
20103
  }], initialPrimarySeries: [{
19773
20104
  type: Input
20105
+ }], initialCategoryLabels: [{
20106
+ type: Input
20107
+ }], initialSeriesLabels: [{
20108
+ type: Input
19774
20109
  }] } });
19775
20110
  /** Primary options a bar chart keeps (AB#7953, AB#8046): `visible: false` and `missingValues`; `undefined` when default. */
19776
20111
  function barPrimaryOptions(options) {
@@ -20609,7 +20944,7 @@ class LineChartWidgetComponent {
20609
20944
  }
20610
20945
  rowCount += f.value.rows.length;
20611
20946
  const series = source.primary
20612
- ? primaryRowsToSeries(f.value.rows, this.config, f.value.downsampled)
20947
+ ? this.withSeriesLabels(primaryRowsToSeries(f.value.rows, this.config, f.value.downsampled))
20613
20948
  : [queryRowsToSeries(f.value.rows, source.label, source.valueField, f.value.downsampled)];
20614
20949
  const withData = series.filter(s => s.points.size > 0);
20615
20950
  if (withData.length === 0) {
@@ -20971,6 +21306,12 @@ class LineChartWidgetComponent {
20971
21306
  });
20972
21307
  });
20973
21308
  }
21309
+ // Names replace the raw group values only here, after grouping; the tooltip unit is looked up by the shown name.
21310
+ const seriesNames = seriesLabelsByRawValue(seriesGroups, this.config.seriesLabels);
21311
+ const unitByShownName = new Map();
21312
+ for (const [rawGroup, unit] of seriesUnitMap) {
21313
+ unitByShownName.set(seriesNames.get(rawGroup) ?? rawGroup, unit);
21314
+ }
20974
21315
  // Build series data
20975
21316
  const seriesData = seriesGroups.map((seriesGroup, index) => {
20976
21317
  const data = categoryKeys.map(categoryKey => {
@@ -20983,7 +21324,7 @@ class LineChartWidgetComponent {
20983
21324
  const unit = seriesUnitMap.get(seriesGroup);
20984
21325
  const axisName = unit ? `unit_${this.sanitizeAxisName(unit)}` : undefined;
20985
21326
  return {
20986
- name: seriesGroup,
21327
+ name: seriesNames.get(seriesGroup) ?? seriesGroup,
20987
21328
  data,
20988
21329
  band,
20989
21330
  unit,
@@ -20994,7 +21335,12 @@ class LineChartWidgetComponent {
20994
21335
  this._categories.set(categories);
20995
21336
  this._seriesData.set(seriesData);
20996
21337
  this._valueAxes.set(valueAxes);
20997
- this._seriesUnitMap.set(seriesUnitMap);
21338
+ this._seriesUnitMap.set(unitByShownName);
21339
+ }
21340
+ /** Series of the primary query shown under their `seriesLabels` names (AB#7235); the grouping itself stays on the raw values. */
21341
+ withSeriesLabels(series) {
21342
+ const names = seriesLabelsByRawValue(series.map(s => s.name), this.config.seriesLabels);
21343
+ return series.map(s => ({ ...s, name: names.get(s.name) ?? s.name }));
20998
21344
  }
20999
21345
  /**
21000
21346
  * Formats a date for display on the category axis (date only).
@@ -21393,6 +21739,9 @@ class LineChartConfigDialogComponent {
21393
21739
  initialPrimarySeries;
21394
21740
  initialBucketMinutes;
21395
21741
  initialExcludedSeriesGroupValues;
21742
+ initialSeriesLabels;
21743
+ /** Rows of the series name editor (AB#7235). */
21744
+ seriesLabelRows = [];
21396
21745
  /** Options of the bucket size dropdown (AB#8046): automatic (`null`) plus the fixed sizes. */
21397
21746
  get bucketSizeOptions() {
21398
21747
  return [
@@ -21515,6 +21864,7 @@ class LineChartConfigDialogComponent {
21515
21864
  this.additionalSeries = this.initialAdditionalSeries ? [...this.initialAdditionalSeries] : [];
21516
21865
  this.primarySeries = this.initialPrimarySeries ? { ...this.initialPrimarySeries } : undefined;
21517
21866
  this.excludedSeriesGroupValues = this.initialExcludedSeriesGroupValues ? [...this.initialExcludedSeriesGroupValues] : [];
21867
+ this.seriesLabelRows = toValueLabelRows(this.initialSeriesLabels);
21518
21868
  // Initialize filters
21519
21869
  if (this.initialFilters && this.initialFilters.length > 0) {
21520
21870
  this.filters = this.initialFilters.map((f, index) => ({
@@ -21700,7 +22050,8 @@ class LineChartConfigDialogComponent {
21700
22050
  stacked: this.form.chartType === 'area' && this.form.stacked ? true : undefined,
21701
22051
  primarySeries: this.selectedQueryFamily === 'streamData' ? this.primarySeries : undefined,
21702
22052
  bucketMinutes: this.selectedQueryFamily === 'streamData' && this.form.bucketMinutes ? this.form.bucketMinutes : undefined,
21703
- excludedSeriesGroupValues: this.excludedSeriesGroupValues.length > 0 ? [...this.excludedSeriesGroupValues] : undefined
22053
+ excludedSeriesGroupValues: this.excludedSeriesGroupValues.length > 0 ? [...this.excludedSeriesGroupValues] : undefined,
22054
+ seriesLabels: fromValueLabelRows(this.seriesLabelRows)
21704
22055
  };
21705
22056
  this.windowRef.close(result);
21706
22057
  }
@@ -21714,7 +22065,7 @@ class LineChartConfigDialogComponent {
21714
22065
  this.windowRef.close();
21715
22066
  }
21716
22067
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: LineChartConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21717
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: LineChartConfigDialogComponent, isStandalone: true, selector: "mm-line-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialResolutionAware: "initialResolutionAware", initialRequiredAggregation: "initialRequiredAggregation", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialUnitField: "initialUnitField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowMarkers: "initialShowMarkers", initialShowDataBadge: "initialShowDataBadge", initialReferenceLines: "initialReferenceLines", initialFilters: "initialFilters", initialAdditionalSeries: "initialAdditionalSeries", initialStacked: "initialStacked", initialPrimarySeries: "initialPrimarySeries", initialBucketMinutes: "initialBucketMinutes", initialExcludedSeriesGroupValues: "initialExcludedSeriesGroupValues" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
22068
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: LineChartConfigDialogComponent, isStandalone: true, selector: "mm-line-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialResolutionAware: "initialResolutionAware", initialRequiredAggregation: "initialRequiredAggregation", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialUnitField: "initialUnitField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowMarkers: "initialShowMarkers", initialShowDataBadge: "initialShowDataBadge", initialReferenceLines: "initialReferenceLines", initialFilters: "initialFilters", initialAdditionalSeries: "initialAdditionalSeries", initialStacked: "initialStacked", initialPrimarySeries: "initialPrimarySeries", initialBucketMinutes: "initialBucketMinutes", initialExcludedSeriesGroupValues: "initialExcludedSeriesGroupValues", initialSeriesLabels: "initialSeriesLabels" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
21718
22069
  <div class="config-container">
21719
22070
 
21720
22071
  <div class="config-form" [class.loading]="isLoadingInitial">
@@ -21878,6 +22229,12 @@ class LineChartConfigDialogComponent {
21878
22229
  </div>
21879
22230
  }
21880
22231
 
22232
+ <!-- Series names (AB#7235) -->
22233
+ <div class="config-section" data-line-series-labels>
22234
+ <h3 class="section-title">Series Names</h3>
22235
+ <mm-value-labels-editor [(rows)]="seriesLabelRows" subject="series"></mm-value-labels-editor>
22236
+ </div>
22237
+
21881
22238
  <!-- Series Section (AB#7951): query series from other stream-data queries on one time grid -->
21882
22239
  @if (selectedQueryFamily === 'streamData') {
21883
22240
  <div class="config-section">
@@ -22025,7 +22382,7 @@ class LineChartConfigDialogComponent {
22025
22382
  </button>
22026
22383
  </div>
22027
22384
  </div>
22028
- `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.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)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px;align-items:center}.checkbox-field{flex-direction:row;align-items:center;margin-bottom:0}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.reference-line-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { 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: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { 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: "component", type: i4.MultiSelectComponent, selector: "kendo-multiselect", inputs: ["showStickyHeader", "focusableId", "autoClose", "loading", "data", "value", "valueField", "textField", "tabindex", "tabIndex", "size", "rounded", "fillMode", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "disabled", "itemDisabled", "checkboxes", "readonly", "filterable", "virtual", "popupSettings", "listHeight", "valuePrimitive", "clearButton", "tagMapper", "allowCustom", "valueNormalizer", "inputAttributes"], outputs: ["filterChange", "valueChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "removeTag"], exportAs: ["kendoMultiSelect"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: LineChartSeriesEditorComponent, selector: "mm-line-chart-series-editor", inputs: ["series", "primary", "stackedChart", "selectors", "alignment", "areaChart", "linesAllowed", "defaultCategoryField"], outputs: ["primaryChange", "seriesChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
22385
+ `, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.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)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px;align-items:center}.checkbox-field{flex-direction:row;align-items:center;margin-bottom:0}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.reference-line-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { 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: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { 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: "component", type: i4.MultiSelectComponent, selector: "kendo-multiselect", inputs: ["showStickyHeader", "focusableId", "autoClose", "loading", "data", "value", "valueField", "textField", "tabindex", "tabIndex", "size", "rounded", "fillMode", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "disabled", "itemDisabled", "checkboxes", "readonly", "filterable", "virtual", "popupSettings", "listHeight", "valuePrimitive", "clearButton", "tagMapper", "allowCustom", "valueNormalizer", "inputAttributes"], outputs: ["filterChange", "valueChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "removeTag"], exportAs: ["kendoMultiSelect"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }, { kind: "component", type: LineChartSeriesEditorComponent, selector: "mm-line-chart-series-editor", inputs: ["series", "primary", "stackedChart", "selectors", "alignment", "areaChart", "linesAllowed", "defaultCategoryField"], outputs: ["primaryChange", "seriesChange"] }, { kind: "component", type: ValueLabelsEditorComponent, selector: "mm-value-labels-editor", inputs: ["rows", "subject"], outputs: ["rowsChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
22029
22386
  }
22030
22387
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: LineChartConfigDialogComponent, decorators: [{
22031
22388
  type: Component,
@@ -22041,7 +22398,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
22041
22398
  SdTimeFilterToggleComponent,
22042
22399
  EntitySelectorScopePickerComponent,
22043
22400
  LoadingOverlayComponent,
22044
- LineChartSeriesEditorComponent
22401
+ LineChartSeriesEditorComponent,
22402
+ ValueLabelsEditorComponent
22045
22403
  ], template: `
22046
22404
  <div class="config-container">
22047
22405
 
@@ -22206,6 +22564,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
22206
22564
  </div>
22207
22565
  }
22208
22566
 
22567
+ <!-- Series names (AB#7235) -->
22568
+ <div class="config-section" data-line-series-labels>
22569
+ <h3 class="section-title">Series Names</h3>
22570
+ <mm-value-labels-editor [(rows)]="seriesLabelRows" subject="series"></mm-value-labels-editor>
22571
+ </div>
22572
+
22209
22573
  <!-- Series Section (AB#7951): query series from other stream-data queries on one time grid -->
22210
22574
  @if (selectedQueryFamily === 'streamData') {
22211
22575
  <div class="config-section">
@@ -22403,6 +22767,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
22403
22767
  type: Input
22404
22768
  }], initialExcludedSeriesGroupValues: [{
22405
22769
  type: Input
22770
+ }], initialSeriesLabels: [{
22771
+ type: Input
22406
22772
  }] } });
22407
22773
 
22408
22774
  /**
@@ -37605,6 +37971,7 @@ function registerDefaultWidgets(registry) {
37605
37971
  initialLegendPosition: pieWidget.legendPosition,
37606
37972
  initialFilters: pieWidget.filters,
37607
37973
  initialCategoryColors: pieWidget.categoryColors,
37974
+ initialCategoryLabels: pieWidget.categoryLabels,
37608
37975
  initialLabelPosition: pieWidget.labelPosition,
37609
37976
  initialHideLabelsBelowPercent: pieWidget.hideLabelsBelowPercent
37610
37977
  };
@@ -37647,6 +38014,7 @@ function registerDefaultWidgets(registry) {
37647
38014
  legendPosition: result.legendPosition,
37648
38015
  filters,
37649
38016
  categoryColors: result.categoryColors,
38017
+ categoryLabels: result.categoryLabels,
37650
38018
  labelPosition: result.labelPosition,
37651
38019
  hideLabelsBelowPercent: result.hideLabelsBelowPercent
37652
38020
  };
@@ -37787,7 +38155,9 @@ function registerDefaultWidgets(registry) {
37787
38155
  initialDefaultBarColor: barWidget.defaultBarColor,
37788
38156
  initialFilters: barWidget.filters,
37789
38157
  initialAdditionalSeries: barWidget.additionalSeries,
37790
- initialPrimarySeries: barWidget.primarySeries
38158
+ initialPrimarySeries: barWidget.primarySeries,
38159
+ initialCategoryLabels: barWidget.categoryLabels,
38160
+ initialSeriesLabels: barWidget.seriesLabels
37791
38161
  };
37792
38162
  },
37793
38163
  applyConfigResult: (widget, result) => {
@@ -37820,7 +38190,9 @@ function registerDefaultWidgets(registry) {
37820
38190
  defaultBarColor: result.defaultBarColor,
37821
38191
  filters,
37822
38192
  additionalSeries: result.additionalSeries?.length ? result.additionalSeries : undefined,
37823
- primarySeries: barPrimaryOrUndefined(result.primarySeries)
38193
+ primarySeries: barPrimaryOrUndefined(result.primarySeries),
38194
+ categoryLabels: result.categoryLabels,
38195
+ seriesLabels: result.seriesLabels
37824
38196
  };
37825
38197
  },
37826
38198
  // SOLID: Factory function
@@ -37857,6 +38229,8 @@ function registerDefaultWidgets(registry) {
37857
38229
  // AB#7953: written only when set, so a single-query bar chart encodes exactly as before.
37858
38230
  ...(widget.additionalSeries?.length && { additionalSeries: widget.additionalSeries }),
37859
38231
  ...(barPrimaryOrUndefined(widget.primarySeries) && { primarySeries: barPrimaryOrUndefined(widget.primarySeries) }),
38232
+ ...chartValueLabelsConfig('categoryLabels', widget.categoryLabels),
38233
+ ...chartValueLabelsConfig('seriesLabels', widget.seriesLabels),
37860
38234
  queryName: widget.dataSource.queryName,
37861
38235
  queryRtId: widget.dataSource.queryRtId,
37862
38236
  ...(widget.dataSource.queryFamily && {
@@ -37893,6 +38267,8 @@ function registerDefaultWidgets(registry) {
37893
38267
  colorThresholds: config['colorThresholds'],
37894
38268
  defaultBarColor: config['defaultBarColor'],
37895
38269
  filters: config['filters'],
38270
+ ...chartValueLabelsConfig('categoryLabels', config['categoryLabels']),
38271
+ ...chartValueLabelsConfig('seriesLabels', config['seriesLabels']),
37896
38272
  ...barChartSeriesFromPersisted(config)
37897
38273
  };
37898
38274
  }
@@ -37934,7 +38310,8 @@ function registerDefaultWidgets(registry) {
37934
38310
  initialStacked: lineWidget.stacked,
37935
38311
  initialPrimarySeries: lineWidget.primarySeries,
37936
38312
  initialBucketMinutes: lineWidget.bucketMinutes,
37937
- initialExcludedSeriesGroupValues: lineWidget.excludedSeriesGroupValues
38313
+ initialExcludedSeriesGroupValues: lineWidget.excludedSeriesGroupValues,
38314
+ initialSeriesLabels: lineWidget.seriesLabels
37938
38315
  };
37939
38316
  },
37940
38317
  applyConfigResult: (widget, result) => {
@@ -37975,7 +38352,8 @@ function registerDefaultWidgets(registry) {
37975
38352
  stacked: result.stacked || undefined,
37976
38353
  primarySeries: displayOptionsOrUndefined(result.primarySeries),
37977
38354
  bucketMinutes: bucketMinutesOrUndefined(result.bucketMinutes),
37978
- excludedSeriesGroupValues: excludedSeriesGroupValuesOrUndefined(result.excludedSeriesGroupValues)
38355
+ excludedSeriesGroupValues: excludedSeriesGroupValuesOrUndefined(result.excludedSeriesGroupValues),
38356
+ seriesLabels: result.seriesLabels
37979
38357
  };
37980
38358
  },
37981
38359
  createDefaultConfig: (base) => ({
@@ -38036,7 +38414,8 @@ function registerDefaultWidgets(registry) {
38036
38414
  ...(bucketMinutesOrUndefined(widget.bucketMinutes) && { bucketMinutes: bucketMinutesOrUndefined(widget.bucketMinutes) }),
38037
38415
  ...(excludedSeriesGroupValuesOrUndefined(widget.excludedSeriesGroupValues) && {
38038
38416
  excludedSeriesGroupValues: excludedSeriesGroupValuesOrUndefined(widget.excludedSeriesGroupValues)
38039
- })
38417
+ }),
38418
+ ...chartValueLabelsConfig('seriesLabels', widget.seriesLabels)
38040
38419
  }
38041
38420
  }),
38042
38421
  fromPersistedConfig: (data, base) => {
@@ -38058,6 +38437,7 @@ function registerDefaultWidgets(registry) {
38058
38437
  showDataBadge: config['showDataBadge'] ?? true,
38059
38438
  referenceLines: config['referenceLines'],
38060
38439
  filters: config['filters'],
38440
+ ...chartValueLabelsConfig('seriesLabels', config['seriesLabels']),
38061
38441
  ...lineChartSeriesFromPersisted(config)
38062
38442
  };
38063
38443
  }
@@ -38975,6 +39355,7 @@ function provideDefaultWidgets() {
38975
39355
  function pieChartPresentationConfig(widget) {
38976
39356
  return {
38977
39357
  ...(widget.categoryColors && Object.keys(widget.categoryColors).length ? { categoryColors: widget.categoryColors } : {}),
39358
+ ...chartValueLabelsConfig('categoryLabels', widget.categoryLabels),
38978
39359
  ...(widget.labelPosition ? { labelPosition: widget.labelPosition } : {}),
38979
39360
  ...(widget.hideLabelsBelowPercent ? { hideLabelsBelowPercent: widget.hideLabelsBelowPercent } : {})
38980
39361
  };
@@ -38983,6 +39364,11 @@ function pieChartPresentationConfig(widget) {
38983
39364
  function stringEntries(record) {
38984
39365
  return Object.fromEntries(Object.entries(record).filter((entry) => typeof entry[1] === 'string'));
38985
39366
  }
39367
+ /** `{ [key]: labels }` when the map has a usable entry, else nothing, so charts without names encode exactly as before. */
39368
+ function chartValueLabelsConfig(key, labels) {
39369
+ const normalized = normalizeChartValueLabels(labels);
39370
+ return normalized ? { [key]: normalized } : {};
39371
+ }
38986
39372
  /** Reads {@link pieChartPresentationConfig} back; unknown or missing values are left out. */
38987
39373
  function readPieChartPresentationConfig(config) {
38988
39374
  const colors = config['categoryColors'];
@@ -38990,6 +39376,7 @@ function readPieChartPresentationConfig(config) {
38990
39376
  const minPercent = config['hideLabelsBelowPercent'];
38991
39377
  return {
38992
39378
  ...(colors && typeof colors === 'object' && !Array.isArray(colors) ? { categoryColors: stringEntries(colors) } : {}),
39379
+ ...chartValueLabelsConfig('categoryLabels', config['categoryLabels']),
38993
39380
  ...(position === 'inside' || position === 'outside' || position === 'none' ? { labelPosition: position } : {}),
38994
39381
  ...(typeof minPercent === 'number' && minPercent > 0 ? { hideLabelsBelowPercent: minPercent } : {})
38995
39382
  };
@@ -48399,5 +48786,5 @@ function provideCockpitWidgets() {
48399
48786
  * Generated bundle index. Do not edit.
48400
48787
  */
48401
48788
 
48402
- export { ADAPTER_OFFLINE_GRACE_MS, ASSOCIATION_HOP_SOURCE_BATCH, ASSOCIATION_HOP_TARGETS_PER_SOURCE, ATTENTION_SEVERITY_ORDER, AdaptersAttentionProvider, AddWidgetDialogComponent, AiInsightsConfigDialogComponent, AiInsightsService, AiInsightsWidgetComponent, AlertBannerConfigDialogComponent, AlertBannerWidgetComponent, AlertListConfigDialogComponent, AlertListWidgetComponent, AssociationsConfigDialogComponent, AttentionListConfigDialogComponent, AttentionListWidgetComponent, AutoRefreshTimerService, BUILT_IN_ATTENTION_PROVIDERS, BarChartConfigDialogComponent, BarChartWidgetComponent, BlueprintUpdatesAttentionProvider, COCKPIT_ADAPTER_LIMIT, COCKPIT_ATTENTION_PROVIDERS, COCKPIT_BLUEPRINT_CATALOG_LIMIT, COCKPIT_CHILD_TENANT_IDS, COCKPIT_DATA_FLOW_LIMIT, COCKPIT_EXPLAIN_HANDLER, COCKPIT_FAILED_EXECUTIONS_OPTIONS, COCKPIT_KPI_GATES, COCKPIT_KPI_SLOW_LOADING_MS, COCKPIT_LINK_RESOLVER, COCKPIT_RECENT_ITEMS, COCKPIT_ROLES, COCKPIT_SERVICE_NAMES, COCKPIT_VERSION_SOURCE, COCKPIT_VIEWER_ACCESS, COCKPIT_WIDGET_MESSAGES, COCKPIT_WIDGET_TYPES, CkModelsResolveFailedAttentionProvider, CockpitAdapterStatesService, CockpitAttentionService, CockpitBlueprintStatusService, CockpitChildTenantsService, CockpitCkModelStatesService, CockpitContextService, CockpitDataFlowExecutionsService, CockpitKpiConfigDialogComponent, CockpitKpiService, CockpitKpiWidgetComponent, CockpitServiceHealthService, DAY_MS, DEFAULT_ATTENTION_MAX_ITEMS, DEFAULT_CARRY_FORWARD_LOOKBACK_MINUTES, DEFAULT_COCKPIT_WIDGET_MESSAGES, DEFAULT_FAILED_EXECUTIONS_OPTIONS, DEFAULT_MESHBOARD_MESSAGES, DEFAULT_RECENT_ITEMS_MAX, DEFAULT_TIME_ZONE_MODE, DashboardDataService, DashboardGridService, EditModeStateService, EditWidgetDialogComponent, EntityAssociationsWidgetComponent, EntityCardConfigDialogComponent, EntityCardWidgetComponent, EntityDetailDialogComponent, EntitySelectorEditorComponent, EntitySelectorScopePathEditorComponent, EntitySelectorToolbarComponent, FALLBACK_SERIES_COLORS, FailedExecutionsAttentionProvider, FeaturesNotInstalledAttentionProvider, FormulaFieldComponent, GaugeConfigDialogComponent, GaugeWidgetComponent, HISTOGRAM_HOURS, HOUR_MS, HeatmapConfigDialogComponent, HeatmapWidgetComponent, KPI_ERROR_TEXT, KpiConfigDialogComponent, KpiWidgetComponent, LINE_CHART_BUCKET_MINUTES, LazyMarkdownComponent, LineChartConfigDialogComponent, LineChartSeriesEditorComponent, LineChartWidgetComponent, MAX_RECENT_ITEMS, MAX_SCOPE_HOPS, MESHBOARD_CHROME_ROUTE_DATA, MESHBOARD_DESCRIPTION_MARKER, MESHBOARD_EDIT_QUERY_PARAM, MESHBOARD_HEADER_MODE_ROUTE_DATA, MESHBOARD_LABEL_RESOLVER, MESHBOARD_LANGUAGE, MESHBOARD_MESSAGES, MESHBOARD_OPTIONS, MESHBOARD_TABLE_ROW_ACTION_HANDLER, MESHBOARD_TENANT_ID_PROVIDER, MarkdownConfigDialogComponent, MarkdownWidgetComponent, MeshBoardDataService, MeshBoardGridService, MeshBoardManagerDialogComponent, MeshBoardPersistenceService, MeshBoardSettingsDialogComponent, MeshBoardSettingsResult, MeshBoardStateService, MeshBoardViewComponent, NOT_AVAILABLE_TEXT, PieChartConfigDialogComponent, PieChartWidgetComponent, QueryExecutorService, QuerySelectorComponent, RecentItemsConfigDialogComponent, RecentItemsWidgetComponent, RuntimeEntitySelectorComponent, SERVICE_MANAGED_BLUEPRINT_PREFIX, STATE_STATUS_BY_KEY, ServiceHealthConfigDialogComponent, ServiceHealthWidgetComponent, ServicesHealthAttentionProvider, StatsGridConfigDialogComponent, StatsGridWidgetComponent, StatusIndicatorConfigDialogComponent, StatusIndicatorWidgetComponent, StatusListConfigDialogComponent, StatusListWidgetComponent, SummaryCardConfigDialogComponent, SummaryCardWidgetComponent, TableConfigDialogComponent, TableWidgetComponent, TableWidgetDataSourceDirective, UnregisteredPoolsAttentionProvider, WidgetFactoryService, WidgetGroupComponent, WidgetGroupConfigDialogComponent, WidgetNotConfiguredComponent, WidgetRegistryService, adapterKpi, adaptersInError, adaptersOffline, alignOnTimeGrid, blueprintUpdatesKpi, bucketStepMs, buildHourlyHistogram, categoryStatus, chartSeriesColors, circularReferenceMessage, ckModelKpi, classifyQuery, compareBlueprintVersions, compareMeshBoardNavigation, countFlowExecutions, countLabel, countPipelineExecutions, emptyQueryExecutionResult, enabledButNotInstalled, evaluateSeriesFormulas, executionKpi, failedExecutionsSeverity, formatCockpitMessage, formatCount, humanizeCategory, isAdapterAtRest, isAdapterExpectedToRun, isAdapterOnline, isCockpitWidgetType, isMeshBoardChrome, isMeshBoardHeaderMode, isPositiveMarkerValue, isServiceConfigured, joinEncodedDescription, kpiKindOf, latestStatisticsUpdate, legacyCockpitLinkTarget, loadNgxMarkdown, nameList, newMeshBoardConfig, normalizeNavigation, observeThemeChanges, orderSeriesFormulas, parseHostTimeRange, pickLocalizedText, pipelineExecutionInputs, plural, provideCockpitWidgetHost, provideCockpitWidgets, provideDefaultWidgets, provideMeshBoard, provideMeshBoardLanguage, provideMeshBoardMessages, provideProcessWidget, provideWidgetRegistrations, queryFamily, readMeshBoardNavigation, recentRelativeTime, registerCockpitWidgets, registerDefaultWidgets, registerProcessWidget, resolveChartColor, resolveCockpitWidgetMessages, resolveMeshBoardChrome, resolveMeshBoardHeaderMode, resolveMeshBoardLabel, resolveMeshBoardMessages, selectProviders, seriesFormulaOperands, serviceStateText, servicesHealthKpi, sortAttentionFindings, sparklineGeometry, splitBlueprintId, splitEncodedDescription, statusColor, summarizeAdapterOnline, tenantCountKpi, toBlueprintStatus, toServiceHealthStatus, truncationNote, validateSeriesFormulas, versionKpi, withMeshBoardNavigation };
48789
+ export { ADAPTER_OFFLINE_GRACE_MS, ASSOCIATION_HOP_SOURCE_BATCH, ASSOCIATION_HOP_TARGETS_PER_SOURCE, ATTENTION_SEVERITY_ORDER, AdaptersAttentionProvider, AddWidgetDialogComponent, AiInsightsConfigDialogComponent, AiInsightsService, AiInsightsWidgetComponent, AlertBannerConfigDialogComponent, AlertBannerWidgetComponent, AlertListConfigDialogComponent, AlertListWidgetComponent, AssociationsConfigDialogComponent, AttentionListConfigDialogComponent, AttentionListWidgetComponent, AutoRefreshTimerService, BUILT_IN_ATTENTION_PROVIDERS, BarChartConfigDialogComponent, BarChartWidgetComponent, BlueprintUpdatesAttentionProvider, COCKPIT_ADAPTER_LIMIT, COCKPIT_ATTENTION_PROVIDERS, COCKPIT_BLUEPRINT_CATALOG_LIMIT, COCKPIT_CHILD_TENANT_IDS, COCKPIT_DATA_FLOW_LIMIT, COCKPIT_EXPLAIN_HANDLER, COCKPIT_FAILED_EXECUTIONS_OPTIONS, COCKPIT_KPI_GATES, COCKPIT_KPI_SLOW_LOADING_MS, COCKPIT_LINK_RESOLVER, COCKPIT_RECENT_ITEMS, COCKPIT_ROLES, COCKPIT_SERVICE_NAMES, COCKPIT_VERSION_SOURCE, COCKPIT_VIEWER_ACCESS, COCKPIT_WIDGET_MESSAGES, COCKPIT_WIDGET_TYPES, CkModelsResolveFailedAttentionProvider, CockpitAdapterStatesService, CockpitAttentionService, CockpitBlueprintStatusService, CockpitChildTenantsService, CockpitCkModelStatesService, CockpitContextService, CockpitDataFlowExecutionsService, CockpitKpiConfigDialogComponent, CockpitKpiService, CockpitKpiWidgetComponent, CockpitServiceHealthService, DAY_MS, DEFAULT_ATTENTION_MAX_ITEMS, DEFAULT_CARRY_FORWARD_LOOKBACK_MINUTES, DEFAULT_COCKPIT_WIDGET_MESSAGES, DEFAULT_FAILED_EXECUTIONS_OPTIONS, DEFAULT_MESHBOARD_MESSAGES, DEFAULT_RECENT_ITEMS_MAX, DEFAULT_TIME_ZONE_MODE, DashboardDataService, DashboardGridService, EditModeStateService, EditWidgetDialogComponent, EntityAssociationsWidgetComponent, EntityCardConfigDialogComponent, EntityCardWidgetComponent, EntityDetailDialogComponent, EntitySelectorEditorComponent, EntitySelectorScopePathEditorComponent, EntitySelectorToolbarComponent, FALLBACK_SERIES_COLORS, FailedExecutionsAttentionProvider, FeaturesNotInstalledAttentionProvider, FormulaFieldComponent, GaugeConfigDialogComponent, GaugeWidgetComponent, HISTOGRAM_HOURS, HOUR_MS, HeatmapConfigDialogComponent, HeatmapWidgetComponent, KPI_ERROR_TEXT, KpiConfigDialogComponent, KpiWidgetComponent, LINE_CHART_BUCKET_MINUTES, LazyMarkdownComponent, LineChartConfigDialogComponent, LineChartSeriesEditorComponent, LineChartWidgetComponent, MAX_RECENT_ITEMS, MAX_SCOPE_HOPS, MESHBOARD_CHROME_ROUTE_DATA, MESHBOARD_DESCRIPTION_MARKER, MESHBOARD_EDIT_QUERY_PARAM, MESHBOARD_HEADER_MODE_ROUTE_DATA, MESHBOARD_LABEL_RESOLVER, MESHBOARD_LANGUAGE, MESHBOARD_MESSAGES, MESHBOARD_OPTIONS, MESHBOARD_TABLE_ROW_ACTION_HANDLER, MESHBOARD_TENANT_ID_PROVIDER, MarkdownConfigDialogComponent, MarkdownWidgetComponent, MeshBoardDataService, MeshBoardGridService, MeshBoardManagerDialogComponent, MeshBoardPersistenceService, MeshBoardSettingsDialogComponent, MeshBoardSettingsResult, MeshBoardStateService, MeshBoardViewComponent, NOT_AVAILABLE_TEXT, PieChartConfigDialogComponent, PieChartWidgetComponent, QueryExecutorService, QuerySelectorComponent, RecentItemsConfigDialogComponent, RecentItemsWidgetComponent, RuntimeEntitySelectorComponent, SERVICE_MANAGED_BLUEPRINT_PREFIX, STATE_STATUS_BY_KEY, ServiceHealthConfigDialogComponent, ServiceHealthWidgetComponent, ServicesHealthAttentionProvider, StatsGridConfigDialogComponent, StatsGridWidgetComponent, StatusIndicatorConfigDialogComponent, StatusIndicatorWidgetComponent, StatusListConfigDialogComponent, StatusListWidgetComponent, SummaryCardConfigDialogComponent, SummaryCardWidgetComponent, TableConfigDialogComponent, TableWidgetComponent, TableWidgetDataSourceDirective, UnregisteredPoolsAttentionProvider, ValueLabelsEditorComponent, WidgetFactoryService, WidgetGroupComponent, WidgetGroupConfigDialogComponent, WidgetNotConfiguredComponent, WidgetRegistryService, adapterKpi, adaptersInError, adaptersOffline, alignOnTimeGrid, blueprintUpdatesKpi, bucketStepMs, buildHourlyHistogram, categoryStatus, chartSeriesColors, circularReferenceMessage, ckModelKpi, classifyQuery, compareBlueprintVersions, compareMeshBoardNavigation, countFlowExecutions, countLabel, countPipelineExecutions, emptyQueryExecutionResult, enabledButNotInstalled, evaluateSeriesFormulas, executionKpi, failedExecutionsSeverity, formatCockpitMessage, formatCount, humanizeCategory, isAdapterAtRest, isAdapterExpectedToRun, isAdapterOnline, isCockpitWidgetType, isMeshBoardChrome, isMeshBoardHeaderMode, isPositiveMarkerValue, isServiceConfigured, joinEncodedDescription, kpiKindOf, latestStatisticsUpdate, legacyCockpitLinkTarget, loadNgxMarkdown, nameList, newMeshBoardConfig, normalizeNavigation, observeThemeChanges, orderSeriesFormulas, parseHostTimeRange, pickLocalizedText, pipelineExecutionInputs, plural, provideCockpitWidgetHost, provideCockpitWidgets, provideDefaultWidgets, provideMeshBoard, provideMeshBoardLanguage, provideMeshBoardMessages, provideProcessWidget, provideWidgetRegistrations, queryFamily, readMeshBoardNavigation, recentRelativeTime, registerCockpitWidgets, registerDefaultWidgets, registerProcessWidget, resolveChartColor, resolveCockpitWidgetMessages, resolveMeshBoardChrome, resolveMeshBoardHeaderMode, resolveMeshBoardLabel, resolveMeshBoardMessages, selectProviders, seriesFormulaOperands, serviceStateText, servicesHealthKpi, sortAttentionFindings, sparklineGeometry, splitBlueprintId, splitEncodedDescription, statusColor, summarizeAdapterOnline, tenantCountKpi, toBlueprintStatus, toServiceHealthStatus, truncationNote, validateSeriesFormulas, versionKpi, withMeshBoardNavigation };
48403
48790
  //# sourceMappingURL=meshmakers-octo-meshboard.mjs.map