@masterteam/dashboard-builder 0.0.14 → 0.0.15

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.
@@ -8,12 +8,8 @@ import { TranslocoService, TranslocoDirective } from '@jsverse/transloco';
8
8
  import * as i2$2 from 'angular-gridster2';
9
9
  import { GridsterModule } from 'angular-gridster2';
10
10
  import { Button } from '@masterteam/components/button';
11
- import { Tabs } from '@masterteam/components/tabs';
12
- import { Card } from '@masterteam/components/card';
13
- import { Tooltip } from '@masterteam/components/tooltip';
14
11
  import { ModalService } from '@masterteam/components/modal';
15
12
  import { Page } from '@masterteam/components/page';
16
- import { Menu } from '@masterteam/components/menu';
17
13
  import * as i3$1 from 'primeng/contextmenu';
18
14
  import { ContextMenuModule } from 'primeng/contextmenu';
19
15
  import * as i5 from 'primeng/popover';
@@ -30,14 +26,16 @@ import { NumberField } from '@masterteam/components/number-field';
30
26
  import { TextareaField } from '@masterteam/components/textarea-field';
31
27
  import { DynamicDialogRef, DynamicDialogConfig } from 'primeng/dynamicdialog';
32
28
  import { DynamicDrawerConfig } from '@masterteam/components/dynamic-drawer';
29
+ import { Tabs } from '@masterteam/components/tabs';
33
30
  import { catchError, tap, map as map$1, filter, distinctUntilChanged, share, groupBy as groupBy$1, mergeMap, debounceTime, retry, finalize, shareReplay, takeUntil } from 'rxjs/operators';
34
31
  import { MultiSelectField } from '@masterteam/components/multi-select-field';
35
32
  import { ColorPickerField } from '@masterteam/components/color-picker-field';
36
33
  import { SliderField } from '@masterteam/components/slider-field';
37
34
  import { ToggleField } from '@masterteam/components/toggle-field';
38
35
  import { IconField } from '@masterteam/components/icon-field';
36
+ import { Card } from '@masterteam/components/card';
39
37
  import * as i2$1 from 'primeng/tooltip';
40
- import { Tooltip as Tooltip$1, TooltipModule } from 'primeng/tooltip';
38
+ import { Tooltip, TooltipModule } from 'primeng/tooltip';
41
39
  import { Skeleton } from 'primeng/skeleton';
42
40
  import * as i2 from 'primeng/inputtext';
43
41
  import { InputTextModule } from 'primeng/inputtext';
@@ -48,6 +46,7 @@ import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
48
46
  import * as i6 from 'primeng/select';
49
47
  import { SelectModule } from 'primeng/select';
50
48
  import { Router, ActivatedRoute } from '@angular/router';
49
+ import { Tooltip as Tooltip$1 } from '@masterteam/components/tooltip';
51
50
  import * as mtIcons from '@masterteam/icons/assets/select-icons.json';
52
51
  import { EntityPreview } from '@masterteam/components/entities';
53
52
  import * as i2$3 from 'primeng/button';
@@ -81,6 +80,10 @@ class DashboardBuilderService {
81
80
  * Tree data cache for building selector name map
82
81
  */
83
82
  treeData = signal([], ...(ngDevMode ? [{ debugName: "treeData" }] : []));
83
+ /**
84
+ * Optional services filter for the modules tree request.
85
+ */
86
+ modulesTreeServices = signal(null, ...(ngDevMode ? [{ debugName: "modulesTreeServices" }] : []));
84
87
  /**
85
88
  * Fixed selections that cannot be removed or edited in SelectionConfiguration.
86
89
  * These selections are always shown and are read-only.
@@ -146,6 +149,13 @@ class DashboardBuilderService {
146
149
  clearFixedSelections() {
147
150
  this.fixedSelections.set([]);
148
151
  }
152
+ setModulesTreeServices(services) {
153
+ if (services?.length) {
154
+ this.modulesTreeServices.set([...services]);
155
+ return;
156
+ }
157
+ this.modulesTreeServices.set(null);
158
+ }
149
159
  /**
150
160
  * Add a single fixed selection
151
161
  * @param selection Selection to add as fixed
@@ -266,7 +276,11 @@ class DashboardBuilderService {
266
276
  * This returns the complete tree structure for efficient caching
267
277
  */
268
278
  getModulesTree() {
269
- return this.http.get('metadata/modules/tree?services=pplus', { context: this.gatewayContext });
279
+ const services = this.modulesTreeServices();
280
+ const servicesQuery = services?.length
281
+ ? `?services=${services.map(encodeURIComponent).join(',')}`
282
+ : '';
283
+ return this.http.get(`metadata/modules/tree${servicesQuery}`, { context: this.gatewayContext });
270
284
  }
271
285
  /**
272
286
  * Get modules for a specific service
@@ -1035,13 +1049,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
1035
1049
  TranslocoDirective,
1036
1050
  Button,
1037
1051
  Icon,
1038
- Card,
1039
1052
  SelectField,
1040
1053
  TextField,
1041
1054
  NumberField,
1042
1055
  CheckboxField,
1043
1056
  TextareaField,
1044
- Tooltip,
1045
1057
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1046
1058
  {
1047
1059
  provide: NG_VALUE_ACCESSOR,
@@ -3051,7 +3063,7 @@ class DisplaySettings {
3051
3063
  /** Selected property for adding colors */
3052
3064
  selectedPropertyForColor = signal('', ...(ngDevMode ? [{ debugName: "selectedPropertyForColor" }] : []));
3053
3065
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DisplaySettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
3054
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DisplaySettings, isStandalone: true, selector: "mt-display-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null }, availableProperties: { classPropertyName: "availableProperties", publicName: "availableProperties", isSignal: true, isRequired: false, transformFunction: null }, selectedProperties: { classPropertyName: "selectedProperties", publicName: "selectedProperties", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clientConfigChange: "clientConfigChange" }, ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <!-- Header Configuration -->\r\n @if (\r\n shouldShowField(\"centerHeader\") || shouldShowField(\"advancedHeaderConfig\")\r\n ) {\r\n <mt-card [title]=\"t('headerConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n @if (shouldShowField(\"centerHeader\")) {\r\n <mt-toggle-field\r\n [label]=\"t('centerHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderCentered || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderCentered', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"advancedHeaderConfig\")) {\r\n <mt-toggle-field\r\n [label]=\"t('hideHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderHidden || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderHidden', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerColor')\"\r\n [ngModel]=\"headerCardConfig().headerColor || ''\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerColor', $event)\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('headerFontSize')\"\r\n [ngModel]=\"headerCardConfig().headerFontSize || 14\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerFontSize', $event)\"\r\n [min]=\"10\"\r\n [max]=\"48\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Colors Section (for cards) -->\r\n @if (\r\n shouldShowField(\"bgColor\") ||\r\n shouldShowField(\"textColor\") ||\r\n shouldShowField(\"icon\")\r\n ) {\r\n <mt-card [title]=\"t('cardColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n @if (shouldShowField(\"bgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"styleConfig()['background-color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('background-color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"textColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"styleConfig()['color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"icon\")) {\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"configAsType()['icon'] || ''\"\r\n (ngModelChange)=\"updateConfigAsType('icon', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"styleConfig()['iconColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconBgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconBgColor')\"\r\n [ngModel]=\"styleConfig()['iconBgColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconBgColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"positionTitle\")) {\r\n <mt-select-field\r\n [label]=\"t('positionTitle')\"\r\n [ngModel]=\"styleConfig()['justify-content'] || 'start'\"\r\n (ngModelChange)=\"updateStyleConfig('justify-content', $event)\"\r\n [options]=\"positionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Border Top Section -->\r\n @if (shouldShowField(\"borderTop\")) {\r\n <mt-card [title]=\"t('borderTop')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showBorderTop')\"\r\n [ngModel]=\"styleConfig()['border-top-show'] || false\"\r\n (ngModelChange)=\"updateBorderTopShow($event)\"\r\n />\r\n @if (styleConfig()[\"border-top-show\"]) {\r\n <mt-color-picker-field\r\n [label]=\"t('borderTopColor')\"\r\n [ngModel]=\"\r\n styleConfig()['border-top-color'] ||\r\n styleConfig()['border-color'] ||\r\n '#3b82f6'\r\n \"\r\n (ngModelChange)=\"updateBorderTopColor($event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Style Configuration -->\r\n @if (shouldShowField(\"cardStyleConfig\")) {\r\n <mt-card [title]=\"t('cardStyle')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4 mb-4\">\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"borderRadius\") }}:\r\n {{ cardStyleConfig().borderRadius || 8 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"cardStyleConfig().borderRadius || 8\"\r\n (ngModelChange)=\"updateCardStyleConfig('borderRadius', $event)\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <mt-color-picker-field\r\n [label]=\"t('cardBackgroundColor')\"\r\n [ngModel]=\"cardStyleConfig().backgroundColor || ''\"\r\n (ngModelChange)=\"updateCardStyleConfig('backgroundColor', $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Shadows -->\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"font-medium\">{{ t(\"shadows\") }}</span>\r\n <mt-button\r\n [label]=\"t('addShadow')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addShadow()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n shadow of cardStyleConfig().shadows || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"shadow\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeShadow(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-5 gap-2\">\r\n <mt-number-field\r\n [label]=\"t('x')\"\r\n [ngModel]=\"shadow.x\"\r\n (ngModelChange)=\"updateShadow(i, 'x', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('y')\"\r\n [ngModel]=\"shadow.y\"\r\n (ngModelChange)=\"updateShadow(i, 'y', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('blur')\"\r\n [ngModel]=\"shadow.blur\"\r\n (ngModelChange)=\"updateShadow(i, 'blur', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('spread')\"\r\n [ngModel]=\"shadow.spread\"\r\n (ngModelChange)=\"updateShadow(i, 'spread', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"shadow.color\"\r\n (ngModelChange)=\"updateShadow(i, 'color', $event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Legend Settings -->\r\n @if (shouldShowField(\"legend\")) {\r\n <mt-card [title]=\"t('legendSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLegend')\"\r\n [ngModel]=\"legendConfig().show || false\"\r\n (ngModelChange)=\"updateLegend('show', $event)\"\r\n />\r\n @if (legendConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"legendConfig().position || 'bottom'\"\r\n (ngModelChange)=\"updateLegend('position', $event)\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"legendIconType\")) {\r\n <mt-select-field\r\n [label]=\"t('legendIconType')\"\r\n [ngModel]=\"legendConfig().iconType || 'circle'\"\r\n (ngModelChange)=\"updateLegend('iconType', $event)\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Settings -->\r\n @if (shouldShowField(\"label\")) {\r\n <mt-card [title]=\"t('labelSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabels')\"\r\n [ngModel]=\"labelConfig().show || false\"\r\n (ngModelChange)=\"updateLabel('show', $event)\"\r\n />\r\n @if (labelConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"labelConfig().position || 'inside'\"\r\n (ngModelChange)=\"updateLabel('position', $event)\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"showTotal\")) {\r\n <mt-toggle-field\r\n [label]=\"t('showTotalInTop')\"\r\n [ngModel]=\"labelConfig().showTotalInTop || false\"\r\n (ngModelChange)=\"updateLabel('showTotalInTop', $event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Center (for Pie/Donut charts) -->\r\n @if (shouldShowField(\"labelCenter\")) {\r\n <mt-card [title]=\"t('labelCenter')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideLabelCenter')\"\r\n [ngModel]=\"labelCenterConfig().hide || false\"\r\n (ngModelChange)=\"updateLabelCenterConfig('hide', $event)\"\r\n />\r\n @if (!labelCenterConfig().hide) {\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextEn')\"\r\n [ngModel]=\"labelCenterConfig().text?.en || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('en', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextAr')\"\r\n [ngModel]=\"labelCenterConfig().text?.ar || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('ar', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Override Labels -->\r\n @if (shouldShowField(\"overrideLabels\")) {\r\n <mt-card [title]=\"t('overrideLabels')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"overrideLabelsDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addLabel')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOverrideLabel()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n label of overrideLabels();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"label\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeOverrideLabel(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"label.en\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'en', $event)\"\r\n [placeholder]=\"t('enterLabelEn')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"label.ar\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'ar', $event)\"\r\n [placeholder]=\"t('enterLabelAr')\"\r\n dir=\"rtl\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (overrideLabels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOverrideLabels\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Sort Data Bars -->\r\n @if (shouldShowField(\"sortDataBars\")) {\r\n <mt-card [title]=\"t('sortDataBars')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableSorting')\"\r\n [ngModel]=\"sortDataBarsConfig().enable || false\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('enable', $event)\"\r\n />\r\n @if (sortDataBarsConfig().enable) {\r\n <mt-text-field\r\n [label]=\"t('sortBy')\"\r\n [ngModel]=\"sortDataBarsConfig().sortBy || ''\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('sortBy', $event)\"\r\n [placeholder]=\"t('propertyKey')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('order')\"\r\n [ngModel]=\"sortDataBarsConfig().order || 'asc'\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('order', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Default Colors (for charts) -->\r\n @if (shouldShowField(\"defaultColors\")) {\r\n <mt-card [title]=\"t('defaultColors')\">\r\n <div class=\"flex flex-wrap gap-2 mb-4\">\r\n @for (\r\n color of defaultColors();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 p-2 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-color-picker-field\r\n [ngModel]=\"color\"\r\n (ngModelChange)=\"updateDefaultColor(i, $event)\"\r\n />\r\n <mt-button\r\n icon=\"general.x-close\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeDefaultColor(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"flex flex-wrap gap-2 items-center\">\r\n <span class=\"text-sm text-muted-color xl:mr-2\">{{ t(\"quickAdd\") }}:</span>\r\n @for (color of defaultColorPalette; track color) {\r\n <button\r\n type=\"button\"\r\n class=\"w-6 h-6 rounded cursor-pointer border border-surface-300 hover:scale-110 transition-transform\"\r\n [style.background-color]=\"color\"\r\n (click)=\"addDefaultColor(color)\"\r\n [pTooltip]=\"color\"\r\n tooltipPosition=\"top\"\r\n ></button>\r\n }\r\n </div>\r\n\r\n @if (defaultColors().length === 0) {\r\n <div class=\"text-center py-2 text-muted-color text-sm mt-2\">\r\n {{ t(\"noColorsSelected\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Info -->\r\n @if (shouldShowField(\"cardInfo\")) {\r\n <mt-card [title]=\"t('cardInfo')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showCardInfo')\"\r\n [ngModel]=\"cardInfo().show || false\"\r\n (ngModelChange)=\"updateCardInfoConfig('show', $event)\"\r\n />\r\n @if (cardInfo().show) {\r\n <mt-text-field\r\n [label]=\"t('cardInfoValue')\"\r\n [ngModel]=\"cardInfo().value || ''\"\r\n (ngModelChange)=\"updateCardInfoConfig('value', $event)\"\r\n [placeholder]=\"t('enterCardInfoValue')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Settings -->\r\n @if (shouldShowField(\"hideIndex\")) {\r\n <mt-card [title]=\"t('tableSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideIndex')\"\r\n [ngModel]=\"configAsType()['hideIndex'] || false\"\r\n (ngModelChange)=\"updateConfigAsType('hideIndex', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Map Settings -->\r\n @if (shouldShowField(\"mapChart\")) {\r\n <mt-card [title]=\"t('mapSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('mapType')\"\r\n [ngModel]=\"config()?.clientConfig?.['map'] || 'SaudiArabia'\"\r\n (ngModelChange)=\"updateMapType($event)\"\r\n [options]=\"mapOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Format Configuration -->\r\n @if (shouldShowField(\"format\")) {\r\n <mt-card [title]=\"t('formatConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatConfig().type\"\r\n (ngModelChange)=\"updateFormatConfig('type', $event)\"\r\n [options]=\"formatTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n\r\n @if (formatConfig().type === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"formatConfig().showCurrency || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrency', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showCurrencyTooltip')\"\r\n [ngModel]=\"formatConfig().showCurrencyTooltip || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrencyTooltip', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('handleLanguage')\"\r\n [ngModel]=\"formatConfig().handleLang || false\"\r\n (ngModelChange)=\"updateFormatConfig('handleLang', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hideSuffixes')\"\r\n [ngModel]=\"formatConfig().hideSuffixes || false\"\r\n (ngModelChange)=\"updateFormatConfig('hideSuffixes', $event)\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"custom\") {\r\n <mt-text-field\r\n [label]=\"t('customText')\"\r\n [ngModel]=\"formatConfig().customText || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customText', $event)\"\r\n [placeholder]=\"t('enterCustomText')\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"date\") {\r\n <mt-text-field\r\n [label]=\"t('dateFormat')\"\r\n [ngModel]=\"formatConfig().customDateFormat || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customDateFormat', $event)\"\r\n [placeholder]=\"'YYYY-MM-DD'\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Format Configuration -->\r\n @if (shouldShowField(\"tableFormat\")) {\r\n <mt-card [title]=\"t('tableFormatConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <!-- Colors -->\r\n <mt-color-picker-field\r\n [label]=\"t('headerTextColor')\"\r\n [ngModel]=\"tableFormatConfig().thTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().thBackgroundColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thBackgroundColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cellTextColor')\"\r\n [ngModel]=\"tableFormatConfig().tdTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().groupBackgroundColor || ''\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('groupBackgroundColor', $event)\r\n \"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupTextColor')\"\r\n [ngModel]=\"tableFormatConfig().groupTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('groupTextColor', $event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n <!-- Font Settings -->\r\n <mt-toggle-field\r\n [label]=\"t('boldHeaderFont')\"\r\n [ngModel]=\"tableFormatConfig().thFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontBold', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('boldCellFont')\"\r\n [ngModel]=\"tableFormatConfig().tdFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontBold', $event)\"\r\n />\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"headerFontSize\") }}:\r\n {{ tableFormatConfig().thFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().thFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"cellFontSize\") }}:\r\n {{ tableFormatConfig().tdFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().tdFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n <!-- Options -->\r\n <mt-toggle-field\r\n [label]=\"t('hideTableSubheader')\"\r\n [ngModel]=\"tableFormatConfig().hideTableSubheader || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('hideTableSubheader', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('disableCurrencyFormat')\"\r\n [ngModel]=\"tableFormatConfig().disableCurrencyFormat || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('disableCurrencyFormat', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageAsProgressBar')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageAsProgressBar || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageAsProgressBar', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageStatus')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageStatus || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageStatus', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <!-- Sort & Hidden Columns -->\r\n <mt-select-field\r\n [label]=\"t('sortColumn')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.column || ''\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('column', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumn')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('sortDirection')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.direction || 'asc'\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('direction', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenColumns')\"\r\n [ngModel]=\"tableFormatConfig().hiddenColumns || []\"\r\n (ngModelChange)=\"updateTableFormatConfig('hiddenColumns', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumns')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <mt-button\r\n [label]=\"t('resetToDefault')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"resetTableFormat()\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Color By Condition -->\r\n @if (shouldShowField(\"colorByCondition\")) {\r\n <mt-card [title]=\"t('colorByCondition')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"colorByConditionDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('add')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addColorConditionIndex()\"\r\n />\r\n </div>\r\n\r\n @for (barIndex of getColorConditionIndexes(); track barIndex) {\r\n <div class=\"mb-4 border border-surface-200 rounded-lg\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\">\r\n <div class=\"flex items-center gap-2\">\r\n <button\r\n type=\"button\"\r\n class=\"text-sm text-muted-color\"\r\n (click)=\"toggleColorConditionExpanded(barIndex)\"\r\n >\r\n {{ isColorConditionExpanded(barIndex) ? \"-\" : \"+\" }}\r\n </button>\r\n <span class=\"font-medium text-sm\"\r\n >{{ t(\"bar\") }} {{ barIndex }}</span\r\n >\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n addColorCondition(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeColorConditionIndex(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (isColorConditionExpanded(barIndex)) {\r\n <div class=\"p-3\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"conditions\") }}</span>\r\n <mt-button\r\n [label]=\"t('addCondition')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addColorCondition(barIndex)\"\r\n />\r\n </div>\r\n\r\n @for (\r\n condition of colorByCondition()[barIndex] || [];\r\n track trackByIndex($index);\r\n let condIndex = $index\r\n ) {\r\n <div class=\"p-3 border border-surface-200 rounded-lg mb-3\">\r\n <div class=\"grid grid-cols-1 2xl:grid-cols-6 gap-3 items-end\">\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"condition.color\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'color',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('condition')\"\r\n [ngModel]=\"condition.type\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'type',\r\n $event\r\n )\r\n \"\r\n [options]=\"colorConditionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-number-field\r\n [label]=\"\r\n condition.type === 'between' ? t('from') : t('value')\r\n \"\r\n [ngModel]=\"condition.value1\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value1',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n @if (condition.type === \"between\") {\r\n <mt-number-field\r\n [label]=\"t('to')\"\r\n [ngModel]=\"condition.value2\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value2',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n }\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeColorCondition(barIndex, condIndex)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3 mt-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"condition.labelEn || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelEn',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"condition.labelAr || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelAr',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((colorByCondition()[barIndex] || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (getColorConditionIndexes().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Timeline Header Colors -->\r\n @if (shouldShowField(\"timelineHeaderColorsConfig\")) {\r\n <mt-card [title]=\"t('timelineHeaderColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().bgColor || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('bgColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().color || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('color', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Ring Gauge Configuration -->\r\n @if (shouldShowField(\"ringGaugeConfig\")) {\r\n <mt-card [title]=\"t('ringGaugeConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('centerProperty')\"\r\n [ngModel]=\"ringGaugeConfig().centerProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('centerProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('statusProperty')\"\r\n [ngModel]=\"ringGaugeConfig().statusProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('statusProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"mt-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenProperties')\"\r\n [ngModel]=\"ringGaugeConfig().hiddenProperties || []\"\r\n (ngModelChange)=\"updateRingGaugeConfig('hiddenProperties', $event)\"\r\n [options]=\"ringGaugeHiddenOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Order Configuration -->\r\n @if (shouldShowField(\"orderConfig\")) {\r\n <mt-card [title]=\"t('orderConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4 mb-4\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n [ngModel]=\"orderConfig().operation || 'deleteNotEqual'\"\r\n (ngModelChange)=\"updateOrderConfig('operation', $event)\"\r\n [options]=\"orderOperationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('orderBy')\"\r\n [ngModel]=\"orderConfig().orderBy || ''\"\r\n (ngModelChange)=\"updateOrderConfig('orderBy', $event)\"\r\n [placeholder]=\"t('enterPropertyKey')\"\r\n />\r\n </div>\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"orderConfigurationDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addOrderItem')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOrderItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of orderConfig().order || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 flex flex-col gap-3 rounded-lg border border-surface-200 bg-surface-50 p-4 xl:flex-row xl:items-center\"\r\n >\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n <span class=\"text-sm font-medium w-auto xl:w-8\">{{ i + 1 }}.</span>\r\n <mt-text-field\r\n [ngModel]=\"item\"\r\n (ngModelChange)=\"updateOrderItem(i, $event)\"\r\n [placeholder]=\"t('enterPropertyKey')\"\r\n size=\"small\"\r\n class=\"min-w-0 flex-1\"\r\n />\r\n </div>\r\n <div class=\"flex items-center justify-end gap-1\">\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === 0\"\r\n (onClick)=\"moveOrderItemUp(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === (orderConfig().order || []).length - 1\"\r\n (onClick)=\"moveOrderItemDown(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeOrderItem(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((orderConfig().order || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOrderItems\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card List Configuration -->\r\n @if (shouldShowField(\"cardListConfig\")) {\r\n <mt-card [title]=\"t('cardListConfiguration')\">\r\n <mt-multi-select-field\r\n [label]=\"t('hideProperties')\"\r\n [ngModel]=\"cardListConfig().hideProperties || []\"\r\n (ngModelChange)=\"updateCardListHideProperties($event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertiesToHide')\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Props Config As Index -->\r\n @if (shouldShowField(\"propsConfigAsIndex\")) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"text-sm text-muted-color\">{{ t(\"properties\") }}</span>\r\n <mt-button\r\n [label]=\"t('addProperty')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addPropsConfigItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of propsConfigAsIndex();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"property\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropsConfigItem(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 2xl:grid-cols-4 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"item.width || ''\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'width', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"item.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(i, 'colorAsProperty', $event)\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"item.border || []\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'border', $event)\"\r\n [options]=\"borderOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hidden')\"\r\n [ngModel]=\"item.hidden || false\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'hidden', $event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Toggle Association -->\r\n @if (shouldShowField(\"toggleAssociation\")) {\r\n <mt-card [title]=\"t('toggleAssociation')\">\r\n <mt-toggle-field\r\n [label]=\"t('enableToggleAssociation')\"\r\n [ngModel]=\"toggleAssociation()\"\r\n (ngModelChange)=\"updateToggleAssociation($event)\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Translations -->\r\n @if (\r\n shouldShowField(\"propertyTranslations\") &&\r\n resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyTranslations')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyTranslations()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyTranslationsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyTranslationsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyTranslationsPasteText()\"\r\n (ngModelChange)=\"propertyTranslationsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyTranslationsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyTranslationsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyTranslationsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyTranslationsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForTranslation()\"\r\n (ngModelChange)=\"selectedPropertyForTranslation.set($event)\"\r\n [options]=\"availableTranslationOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertyToTranslate')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForTranslation()\"\r\n (onClick)=\"\r\n addPropertyTranslation(selectedPropertyForTranslation());\r\n selectedPropertyForTranslation.set('')\r\n \"\r\n [pTooltip]=\"t('addTranslation')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Translation List -->\r\n @for (propKey of getPropertyTranslationKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyTranslation(propKey)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"propertyTranslations()[propKey]?.ar || ''\"\r\n (ngModelChange)=\"updatePropertyTranslation(propKey, 'ar', $event)\"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"propertyTranslations()[propKey]?.en || ''\"\r\n (ngModelChange)=\"updatePropertyTranslation(propKey, 'en', $event)\"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getPropertyTranslationKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Colors -->\r\n @if (\r\n shouldShowField(\"propertyColors\") && resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyColors')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyColors()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyColorsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyColorsPasteText()\"\r\n (ngModelChange)=\"propertyColorsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyColorsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyColorsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyColorsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForColor()\"\r\n (ngModelChange)=\"selectedPropertyForColor.set($event)\"\r\n [options]=\"availableColorOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForColor()\"\r\n (onClick)=\"\r\n addPropertyColor(selectedPropertyForColor());\r\n selectedPropertyForColor.set('')\r\n \"\r\n [pTooltip]=\"t('addProperty')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Property Color List -->\r\n @for (propKey of getPropertyColorKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyColor(propKey)\"\r\n />\r\n </div>\r\n <mt-select-field\r\n [label]=\"t('selectColorProperty')\"\r\n [ngModel]=\"propertyColors()[propKey]?.selectedKey || ''\"\r\n (ngModelChange)=\"updatePropertyColor(propKey, $event)\"\r\n [options]=\"allPropertyKeyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (getPropertyColorKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyColors\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Format X-Axis Configuration -->\r\n @if (shouldShowField(\"formatXAxis\")) {\r\n <mt-card [title]=\"t('formatXAxisConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatXAxisConfig().type\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('type', $event)\"\r\n [options]=\"formatXAxisTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n @if (\r\n formatXAxisConfig().type === \"dateToMonth\" ||\r\n formatXAxisConfig().type === \"month\"\r\n ) {\r\n <mt-toggle-field\r\n [label]=\"t('shortFormat')\"\r\n [ngModel]=\"formatXAxisConfig().shortFormate || false\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('shortFormate', $event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Extra Column From Lookup -->\r\n @if (shouldShowField(\"extraColumnFromLookup\")) {\r\n <mt-card [title]=\"t('extraColumnFromLookup')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableExtraColumnFromLookup')\"\r\n [ngModel]=\"tableColumnsConfig().extraCoulmnFromLookup || false\"\r\n (ngModelChange)=\"\r\n updateTableColumnsConfig('extraCoulmnFromLookup', $event)\r\n \"\r\n />\r\n\r\n @if (tableColumnsConfig().extraCoulmnFromLookup) {\r\n <mt-select-field\r\n [label]=\"t('lookup')\"\r\n [ngModel]=\"tableColumnsConfig().lookupId\"\r\n (ngModelChange)=\"updateTableColumnsConfig('lookupId', $event)\"\r\n [options]=\"lookups()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectLookup')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('groupedBy')\"\r\n [ngModel]=\"tableColumnsConfig().groupedBy\"\r\n (ngModelChange)=\"updateTableColumnsConfig('groupedBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"tableColumnsConfig().propKey\"\r\n (ngModelChange)=\"updateTableColumnsConfig('propKey', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "animate", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "pInputs", "required"], outputs: ["onChange", "onSlideEnd"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: IconField, selector: "mt-icon-field", inputs: ["label", "required"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip$1, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3066
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DisplaySettings, isStandalone: true, selector: "mt-display-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null }, availableProperties: { classPropertyName: "availableProperties", publicName: "availableProperties", isSignal: true, isRequired: false, transformFunction: null }, selectedProperties: { classPropertyName: "selectedProperties", publicName: "selectedProperties", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clientConfigChange: "clientConfigChange" }, ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <!-- Header Configuration -->\r\n @if (\r\n shouldShowField(\"centerHeader\") || shouldShowField(\"advancedHeaderConfig\")\r\n ) {\r\n <mt-card [title]=\"t('headerConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n @if (shouldShowField(\"centerHeader\")) {\r\n <mt-toggle-field\r\n [label]=\"t('centerHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderCentered || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderCentered', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"advancedHeaderConfig\")) {\r\n <mt-toggle-field\r\n [label]=\"t('hideHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderHidden || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderHidden', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerColor')\"\r\n [ngModel]=\"headerCardConfig().headerColor || ''\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerColor', $event)\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('headerFontSize')\"\r\n [ngModel]=\"headerCardConfig().headerFontSize || 14\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerFontSize', $event)\"\r\n [min]=\"10\"\r\n [max]=\"48\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Colors Section (for cards) -->\r\n @if (\r\n shouldShowField(\"bgColor\") ||\r\n shouldShowField(\"textColor\") ||\r\n shouldShowField(\"icon\")\r\n ) {\r\n <mt-card [title]=\"t('cardColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n @if (shouldShowField(\"bgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"styleConfig()['background-color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('background-color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"textColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"styleConfig()['color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"icon\")) {\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"configAsType()['icon'] || ''\"\r\n (ngModelChange)=\"updateConfigAsType('icon', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"styleConfig()['iconColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconBgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconBgColor')\"\r\n [ngModel]=\"styleConfig()['iconBgColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconBgColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"positionTitle\")) {\r\n <mt-select-field\r\n [label]=\"t('positionTitle')\"\r\n [ngModel]=\"styleConfig()['justify-content'] || 'start'\"\r\n (ngModelChange)=\"updateStyleConfig('justify-content', $event)\"\r\n [options]=\"positionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Border Top Section -->\r\n @if (shouldShowField(\"borderTop\")) {\r\n <mt-card [title]=\"t('borderTop')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showBorderTop')\"\r\n [ngModel]=\"styleConfig()['border-top-show'] || false\"\r\n (ngModelChange)=\"updateBorderTopShow($event)\"\r\n />\r\n @if (styleConfig()[\"border-top-show\"]) {\r\n <mt-color-picker-field\r\n [label]=\"t('borderTopColor')\"\r\n [ngModel]=\"\r\n styleConfig()['border-top-color'] ||\r\n styleConfig()['border-color'] ||\r\n '#3b82f6'\r\n \"\r\n (ngModelChange)=\"updateBorderTopColor($event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Style Configuration -->\r\n @if (shouldShowField(\"cardStyleConfig\")) {\r\n <mt-card [title]=\"t('cardStyle')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4 mb-4\">\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"borderRadius\") }}:\r\n {{ cardStyleConfig().borderRadius || 8 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"cardStyleConfig().borderRadius || 8\"\r\n (ngModelChange)=\"updateCardStyleConfig('borderRadius', $event)\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <mt-color-picker-field\r\n [label]=\"t('cardBackgroundColor')\"\r\n [ngModel]=\"cardStyleConfig().backgroundColor || ''\"\r\n (ngModelChange)=\"updateCardStyleConfig('backgroundColor', $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Shadows -->\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"font-medium\">{{ t(\"shadows\") }}</span>\r\n <mt-button\r\n [label]=\"t('addShadow')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addShadow()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n shadow of cardStyleConfig().shadows || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"shadow\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeShadow(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-5 gap-2\">\r\n <mt-number-field\r\n [label]=\"t('x')\"\r\n [ngModel]=\"shadow.x\"\r\n (ngModelChange)=\"updateShadow(i, 'x', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('y')\"\r\n [ngModel]=\"shadow.y\"\r\n (ngModelChange)=\"updateShadow(i, 'y', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('blur')\"\r\n [ngModel]=\"shadow.blur\"\r\n (ngModelChange)=\"updateShadow(i, 'blur', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('spread')\"\r\n [ngModel]=\"shadow.spread\"\r\n (ngModelChange)=\"updateShadow(i, 'spread', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"shadow.color\"\r\n (ngModelChange)=\"updateShadow(i, 'color', $event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Legend Settings -->\r\n @if (shouldShowField(\"legend\")) {\r\n <mt-card [title]=\"t('legendSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLegend')\"\r\n [ngModel]=\"legendConfig().show || false\"\r\n (ngModelChange)=\"updateLegend('show', $event)\"\r\n />\r\n @if (legendConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"legendConfig().position || 'bottom'\"\r\n (ngModelChange)=\"updateLegend('position', $event)\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"legendIconType\")) {\r\n <mt-select-field\r\n [label]=\"t('legendIconType')\"\r\n [ngModel]=\"legendConfig().iconType || 'circle'\"\r\n (ngModelChange)=\"updateLegend('iconType', $event)\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Settings -->\r\n @if (shouldShowField(\"label\")) {\r\n <mt-card [title]=\"t('labelSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabels')\"\r\n [ngModel]=\"labelConfig().show || false\"\r\n (ngModelChange)=\"updateLabel('show', $event)\"\r\n />\r\n @if (labelConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"labelConfig().position || 'inside'\"\r\n (ngModelChange)=\"updateLabel('position', $event)\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"showTotal\")) {\r\n <mt-toggle-field\r\n [label]=\"t('showTotalInTop')\"\r\n [ngModel]=\"labelConfig().showTotalInTop || false\"\r\n (ngModelChange)=\"updateLabel('showTotalInTop', $event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Center (for Pie/Donut charts) -->\r\n @if (shouldShowField(\"labelCenter\")) {\r\n <mt-card [title]=\"t('labelCenter')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideLabelCenter')\"\r\n [ngModel]=\"labelCenterConfig().hide || false\"\r\n (ngModelChange)=\"updateLabelCenterConfig('hide', $event)\"\r\n />\r\n @if (!labelCenterConfig().hide) {\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextEn')\"\r\n [ngModel]=\"labelCenterConfig().text?.en || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('en', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextAr')\"\r\n [ngModel]=\"labelCenterConfig().text?.ar || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('ar', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Override Labels -->\r\n @if (shouldShowField(\"overrideLabels\")) {\r\n <mt-card [title]=\"t('overrideLabels')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"overrideLabelsDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addLabel')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOverrideLabel()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n label of overrideLabels();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"label\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeOverrideLabel(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"label.en\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'en', $event)\"\r\n [placeholder]=\"t('enterLabelEn')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"label.ar\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'ar', $event)\"\r\n [placeholder]=\"t('enterLabelAr')\"\r\n dir=\"rtl\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (overrideLabels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOverrideLabels\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Sort Data Bars -->\r\n @if (shouldShowField(\"sortDataBars\")) {\r\n <mt-card [title]=\"t('sortDataBars')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableSorting')\"\r\n [ngModel]=\"sortDataBarsConfig().enable || false\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('enable', $event)\"\r\n />\r\n @if (sortDataBarsConfig().enable) {\r\n <mt-text-field\r\n [label]=\"t('sortBy')\"\r\n [ngModel]=\"sortDataBarsConfig().sortBy || ''\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('sortBy', $event)\"\r\n [placeholder]=\"t('propertyKey')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('order')\"\r\n [ngModel]=\"sortDataBarsConfig().order || 'asc'\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('order', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Default Colors (for charts) -->\r\n @if (shouldShowField(\"defaultColors\")) {\r\n <mt-card [title]=\"t('defaultColors')\">\r\n <div class=\"flex flex-wrap gap-2 mb-4\">\r\n @for (\r\n color of defaultColors();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 p-2 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-color-picker-field\r\n [ngModel]=\"color\"\r\n (ngModelChange)=\"updateDefaultColor(i, $event)\"\r\n />\r\n <mt-button\r\n icon=\"general.x-close\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeDefaultColor(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"flex flex-wrap gap-2 items-center\">\r\n <span class=\"text-sm text-muted-color xl:mr-2\">{{ t(\"quickAdd\") }}:</span>\r\n @for (color of defaultColorPalette; track color) {\r\n <button\r\n type=\"button\"\r\n class=\"w-6 h-6 rounded cursor-pointer border border-surface-300 hover:scale-110 transition-transform\"\r\n [style.background-color]=\"color\"\r\n (click)=\"addDefaultColor(color)\"\r\n [pTooltip]=\"color\"\r\n tooltipPosition=\"top\"\r\n ></button>\r\n }\r\n </div>\r\n\r\n @if (defaultColors().length === 0) {\r\n <div class=\"text-center py-2 text-muted-color text-sm mt-2\">\r\n {{ t(\"noColorsSelected\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Info -->\r\n @if (shouldShowField(\"cardInfo\")) {\r\n <mt-card [title]=\"t('cardInfo')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showCardInfo')\"\r\n [ngModel]=\"cardInfo().show || false\"\r\n (ngModelChange)=\"updateCardInfoConfig('show', $event)\"\r\n />\r\n @if (cardInfo().show) {\r\n <mt-text-field\r\n [label]=\"t('cardInfoValue')\"\r\n [ngModel]=\"cardInfo().value || ''\"\r\n (ngModelChange)=\"updateCardInfoConfig('value', $event)\"\r\n [placeholder]=\"t('enterCardInfoValue')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Settings -->\r\n @if (shouldShowField(\"hideIndex\")) {\r\n <mt-card [title]=\"t('tableSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideIndex')\"\r\n [ngModel]=\"configAsType()['hideIndex'] || false\"\r\n (ngModelChange)=\"updateConfigAsType('hideIndex', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Map Settings -->\r\n @if (shouldShowField(\"mapChart\")) {\r\n <mt-card [title]=\"t('mapSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('mapType')\"\r\n [ngModel]=\"config()?.clientConfig?.['map'] || 'SaudiArabia'\"\r\n (ngModelChange)=\"updateMapType($event)\"\r\n [options]=\"mapOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Format Configuration -->\r\n @if (shouldShowField(\"format\")) {\r\n <mt-card [title]=\"t('formatConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatConfig().type\"\r\n (ngModelChange)=\"updateFormatConfig('type', $event)\"\r\n [options]=\"formatTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n\r\n @if (formatConfig().type === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"formatConfig().showCurrency || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrency', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showCurrencyTooltip')\"\r\n [ngModel]=\"formatConfig().showCurrencyTooltip || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrencyTooltip', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('handleLanguage')\"\r\n [ngModel]=\"formatConfig().handleLang || false\"\r\n (ngModelChange)=\"updateFormatConfig('handleLang', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hideSuffixes')\"\r\n [ngModel]=\"formatConfig().hideSuffixes || false\"\r\n (ngModelChange)=\"updateFormatConfig('hideSuffixes', $event)\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"custom\") {\r\n <mt-text-field\r\n [label]=\"t('customText')\"\r\n [ngModel]=\"formatConfig().customText || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customText', $event)\"\r\n [placeholder]=\"t('enterCustomText')\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"date\") {\r\n <mt-text-field\r\n [label]=\"t('dateFormat')\"\r\n [ngModel]=\"formatConfig().customDateFormat || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customDateFormat', $event)\"\r\n [placeholder]=\"'YYYY-MM-DD'\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Format Configuration -->\r\n @if (shouldShowField(\"tableFormat\")) {\r\n <mt-card [title]=\"t('tableFormatConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <!-- Colors -->\r\n <mt-color-picker-field\r\n [label]=\"t('headerTextColor')\"\r\n [ngModel]=\"tableFormatConfig().thTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().thBackgroundColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thBackgroundColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cellTextColor')\"\r\n [ngModel]=\"tableFormatConfig().tdTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().groupBackgroundColor || ''\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('groupBackgroundColor', $event)\r\n \"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupTextColor')\"\r\n [ngModel]=\"tableFormatConfig().groupTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('groupTextColor', $event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n <!-- Font Settings -->\r\n <mt-toggle-field\r\n [label]=\"t('boldHeaderFont')\"\r\n [ngModel]=\"tableFormatConfig().thFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontBold', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('boldCellFont')\"\r\n [ngModel]=\"tableFormatConfig().tdFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontBold', $event)\"\r\n />\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"headerFontSize\") }}:\r\n {{ tableFormatConfig().thFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().thFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"cellFontSize\") }}:\r\n {{ tableFormatConfig().tdFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().tdFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n <!-- Options -->\r\n <mt-toggle-field\r\n [label]=\"t('hideTableSubheader')\"\r\n [ngModel]=\"tableFormatConfig().hideTableSubheader || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('hideTableSubheader', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('disableCurrencyFormat')\"\r\n [ngModel]=\"tableFormatConfig().disableCurrencyFormat || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('disableCurrencyFormat', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageAsProgressBar')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageAsProgressBar || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageAsProgressBar', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageStatus')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageStatus || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageStatus', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <!-- Sort & Hidden Columns -->\r\n <mt-select-field\r\n [label]=\"t('sortColumn')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.column || ''\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('column', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumn')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('sortDirection')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.direction || 'asc'\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('direction', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenColumns')\"\r\n [ngModel]=\"tableFormatConfig().hiddenColumns || []\"\r\n (ngModelChange)=\"updateTableFormatConfig('hiddenColumns', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumns')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <mt-button\r\n [label]=\"t('resetToDefault')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"resetTableFormat()\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Color By Condition -->\r\n @if (shouldShowField(\"colorByCondition\")) {\r\n <mt-card [title]=\"t('colorByCondition')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"colorByConditionDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('add')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addColorConditionIndex()\"\r\n />\r\n </div>\r\n\r\n @for (barIndex of getColorConditionIndexes(); track barIndex) {\r\n <div class=\"mb-4 border border-surface-200 rounded-lg\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\">\r\n <div class=\"flex items-center gap-2\">\r\n <button\r\n type=\"button\"\r\n class=\"text-sm text-muted-color\"\r\n (click)=\"toggleColorConditionExpanded(barIndex)\"\r\n >\r\n {{ isColorConditionExpanded(barIndex) ? \"-\" : \"+\" }}\r\n </button>\r\n <span class=\"font-medium text-sm\"\r\n >{{ t(\"bar\") }} {{ barIndex }}</span\r\n >\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n addColorCondition(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeColorConditionIndex(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (isColorConditionExpanded(barIndex)) {\r\n <div class=\"p-3\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"conditions\") }}</span>\r\n <mt-button\r\n [label]=\"t('addCondition')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addColorCondition(barIndex)\"\r\n />\r\n </div>\r\n\r\n @for (\r\n condition of colorByCondition()[barIndex] || [];\r\n track trackByIndex($index);\r\n let condIndex = $index\r\n ) {\r\n <div class=\"p-3 border border-surface-200 rounded-lg mb-3\">\r\n <div class=\"grid grid-cols-1 2xl:grid-cols-6 gap-3 items-end\">\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"condition.color\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'color',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('condition')\"\r\n [ngModel]=\"condition.type\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'type',\r\n $event\r\n )\r\n \"\r\n [options]=\"colorConditionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-number-field\r\n [label]=\"\r\n condition.type === 'between' ? t('from') : t('value')\r\n \"\r\n [ngModel]=\"condition.value1\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value1',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n @if (condition.type === \"between\") {\r\n <mt-number-field\r\n [label]=\"t('to')\"\r\n [ngModel]=\"condition.value2\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value2',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n }\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeColorCondition(barIndex, condIndex)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3 mt-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"condition.labelEn || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelEn',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"condition.labelAr || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelAr',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((colorByCondition()[barIndex] || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (getColorConditionIndexes().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Timeline Header Colors -->\r\n @if (shouldShowField(\"timelineHeaderColorsConfig\")) {\r\n <mt-card [title]=\"t('timelineHeaderColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().bgColor || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('bgColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().color || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('color', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Ring Gauge Configuration -->\r\n @if (shouldShowField(\"ringGaugeConfig\")) {\r\n <mt-card [title]=\"t('ringGaugeConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('centerProperty')\"\r\n [ngModel]=\"ringGaugeConfig().centerProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('centerProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('statusProperty')\"\r\n [ngModel]=\"ringGaugeConfig().statusProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('statusProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"mt-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenProperties')\"\r\n [ngModel]=\"ringGaugeConfig().hiddenProperties || []\"\r\n (ngModelChange)=\"updateRingGaugeConfig('hiddenProperties', $event)\"\r\n [options]=\"ringGaugeHiddenOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Order Configuration -->\r\n @if (shouldShowField(\"orderConfig\")) {\r\n <mt-card [title]=\"t('orderConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4 mb-4\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n [ngModel]=\"orderConfig().operation || 'deleteNotEqual'\"\r\n (ngModelChange)=\"updateOrderConfig('operation', $event)\"\r\n [options]=\"orderOperationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('orderBy')\"\r\n [ngModel]=\"orderConfig().orderBy || ''\"\r\n (ngModelChange)=\"updateOrderConfig('orderBy', $event)\"\r\n [placeholder]=\"t('enterPropertyKey')\"\r\n />\r\n </div>\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"orderConfigurationDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addOrderItem')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOrderItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of orderConfig().order || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 flex flex-col gap-3 rounded-lg border border-surface-200 bg-surface-50 p-4 xl:flex-row xl:items-center\"\r\n >\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n <span class=\"text-sm font-medium w-auto xl:w-8\">{{ i + 1 }}.</span>\r\n <mt-text-field\r\n [ngModel]=\"item\"\r\n (ngModelChange)=\"updateOrderItem(i, $event)\"\r\n [placeholder]=\"t('enterPropertyKey')\"\r\n size=\"small\"\r\n class=\"min-w-0 flex-1\"\r\n />\r\n </div>\r\n <div class=\"flex items-center justify-end gap-1\">\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === 0\"\r\n (onClick)=\"moveOrderItemUp(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === (orderConfig().order || []).length - 1\"\r\n (onClick)=\"moveOrderItemDown(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeOrderItem(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((orderConfig().order || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOrderItems\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card List Configuration -->\r\n @if (shouldShowField(\"cardListConfig\")) {\r\n <mt-card [title]=\"t('cardListConfiguration')\">\r\n <mt-multi-select-field\r\n [label]=\"t('hideProperties')\"\r\n [ngModel]=\"cardListConfig().hideProperties || []\"\r\n (ngModelChange)=\"updateCardListHideProperties($event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertiesToHide')\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Props Config As Index -->\r\n @if (shouldShowField(\"propsConfigAsIndex\")) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"text-sm text-muted-color\">{{ t(\"properties\") }}</span>\r\n <mt-button\r\n [label]=\"t('addProperty')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addPropsConfigItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of propsConfigAsIndex();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"property\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropsConfigItem(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 2xl:grid-cols-4 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"item.width || ''\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'width', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"item.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(i, 'colorAsProperty', $event)\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"item.border || []\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'border', $event)\"\r\n [options]=\"borderOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hidden')\"\r\n [ngModel]=\"item.hidden || false\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'hidden', $event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Toggle Association -->\r\n @if (shouldShowField(\"toggleAssociation\")) {\r\n <mt-card [title]=\"t('toggleAssociation')\">\r\n <mt-toggle-field\r\n [label]=\"t('enableToggleAssociation')\"\r\n [ngModel]=\"toggleAssociation()\"\r\n (ngModelChange)=\"updateToggleAssociation($event)\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Translations -->\r\n @if (\r\n shouldShowField(\"propertyTranslations\") &&\r\n resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyTranslations')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyTranslations()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyTranslationsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyTranslationsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyTranslationsPasteText()\"\r\n (ngModelChange)=\"propertyTranslationsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyTranslationsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyTranslationsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyTranslationsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyTranslationsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForTranslation()\"\r\n (ngModelChange)=\"selectedPropertyForTranslation.set($event)\"\r\n [options]=\"availableTranslationOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertyToTranslate')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForTranslation()\"\r\n (onClick)=\"\r\n addPropertyTranslation(selectedPropertyForTranslation());\r\n selectedPropertyForTranslation.set('')\r\n \"\r\n [pTooltip]=\"t('addTranslation')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Translation List -->\r\n @for (propKey of getPropertyTranslationKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyTranslation(propKey)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"propertyTranslations()[propKey]?.ar || ''\"\r\n (ngModelChange)=\"updatePropertyTranslation(propKey, 'ar', $event)\"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"propertyTranslations()[propKey]?.en || ''\"\r\n (ngModelChange)=\"updatePropertyTranslation(propKey, 'en', $event)\"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getPropertyTranslationKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Colors -->\r\n @if (\r\n shouldShowField(\"propertyColors\") && resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyColors')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyColors()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyColorsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyColorsPasteText()\"\r\n (ngModelChange)=\"propertyColorsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyColorsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyColorsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyColorsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForColor()\"\r\n (ngModelChange)=\"selectedPropertyForColor.set($event)\"\r\n [options]=\"availableColorOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForColor()\"\r\n (onClick)=\"\r\n addPropertyColor(selectedPropertyForColor());\r\n selectedPropertyForColor.set('')\r\n \"\r\n [pTooltip]=\"t('addProperty')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Property Color List -->\r\n @for (propKey of getPropertyColorKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyColor(propKey)\"\r\n />\r\n </div>\r\n <mt-select-field\r\n [label]=\"t('selectColorProperty')\"\r\n [ngModel]=\"propertyColors()[propKey]?.selectedKey || ''\"\r\n (ngModelChange)=\"updatePropertyColor(propKey, $event)\"\r\n [options]=\"allPropertyKeyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (getPropertyColorKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyColors\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Format X-Axis Configuration -->\r\n @if (shouldShowField(\"formatXAxis\")) {\r\n <mt-card [title]=\"t('formatXAxisConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatXAxisConfig().type\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('type', $event)\"\r\n [options]=\"formatXAxisTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n @if (\r\n formatXAxisConfig().type === \"dateToMonth\" ||\r\n formatXAxisConfig().type === \"month\"\r\n ) {\r\n <mt-toggle-field\r\n [label]=\"t('shortFormat')\"\r\n [ngModel]=\"formatXAxisConfig().shortFormate || false\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('shortFormate', $event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Extra Column From Lookup -->\r\n @if (shouldShowField(\"extraColumnFromLookup\")) {\r\n <mt-card [title]=\"t('extraColumnFromLookup')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableExtraColumnFromLookup')\"\r\n [ngModel]=\"tableColumnsConfig().extraCoulmnFromLookup || false\"\r\n (ngModelChange)=\"\r\n updateTableColumnsConfig('extraCoulmnFromLookup', $event)\r\n \"\r\n />\r\n\r\n @if (tableColumnsConfig().extraCoulmnFromLookup) {\r\n <mt-select-field\r\n [label]=\"t('lookup')\"\r\n [ngModel]=\"tableColumnsConfig().lookupId\"\r\n (ngModelChange)=\"updateTableColumnsConfig('lookupId', $event)\"\r\n [options]=\"lookups()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectLookup')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('groupedBy')\"\r\n [ngModel]=\"tableColumnsConfig().groupedBy\"\r\n (ngModelChange)=\"updateTableColumnsConfig('groupedBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"tableColumnsConfig().propKey\"\r\n (ngModelChange)=\"updateTableColumnsConfig('propKey', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "animate", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "pInputs", "required"], outputs: ["onChange", "onSlideEnd"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: IconField, selector: "mt-icon-field", inputs: ["label", "required"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3055
3067
  }
3056
3068
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DisplaySettings, decorators: [{
3057
3069
  type: Component,
@@ -3070,7 +3082,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
3070
3082
  ToggleField,
3071
3083
  IconField,
3072
3084
  Card,
3073
- Tooltip$1,
3085
+ Tooltip,
3074
3086
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <!-- Header Configuration -->\r\n @if (\r\n shouldShowField(\"centerHeader\") || shouldShowField(\"advancedHeaderConfig\")\r\n ) {\r\n <mt-card [title]=\"t('headerConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n @if (shouldShowField(\"centerHeader\")) {\r\n <mt-toggle-field\r\n [label]=\"t('centerHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderCentered || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderCentered', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"advancedHeaderConfig\")) {\r\n <mt-toggle-field\r\n [label]=\"t('hideHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderHidden || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderHidden', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerColor')\"\r\n [ngModel]=\"headerCardConfig().headerColor || ''\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerColor', $event)\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('headerFontSize')\"\r\n [ngModel]=\"headerCardConfig().headerFontSize || 14\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerFontSize', $event)\"\r\n [min]=\"10\"\r\n [max]=\"48\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Colors Section (for cards) -->\r\n @if (\r\n shouldShowField(\"bgColor\") ||\r\n shouldShowField(\"textColor\") ||\r\n shouldShowField(\"icon\")\r\n ) {\r\n <mt-card [title]=\"t('cardColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n @if (shouldShowField(\"bgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"styleConfig()['background-color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('background-color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"textColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"styleConfig()['color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"icon\")) {\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"configAsType()['icon'] || ''\"\r\n (ngModelChange)=\"updateConfigAsType('icon', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"styleConfig()['iconColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconBgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconBgColor')\"\r\n [ngModel]=\"styleConfig()['iconBgColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconBgColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"positionTitle\")) {\r\n <mt-select-field\r\n [label]=\"t('positionTitle')\"\r\n [ngModel]=\"styleConfig()['justify-content'] || 'start'\"\r\n (ngModelChange)=\"updateStyleConfig('justify-content', $event)\"\r\n [options]=\"positionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Border Top Section -->\r\n @if (shouldShowField(\"borderTop\")) {\r\n <mt-card [title]=\"t('borderTop')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showBorderTop')\"\r\n [ngModel]=\"styleConfig()['border-top-show'] || false\"\r\n (ngModelChange)=\"updateBorderTopShow($event)\"\r\n />\r\n @if (styleConfig()[\"border-top-show\"]) {\r\n <mt-color-picker-field\r\n [label]=\"t('borderTopColor')\"\r\n [ngModel]=\"\r\n styleConfig()['border-top-color'] ||\r\n styleConfig()['border-color'] ||\r\n '#3b82f6'\r\n \"\r\n (ngModelChange)=\"updateBorderTopColor($event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Style Configuration -->\r\n @if (shouldShowField(\"cardStyleConfig\")) {\r\n <mt-card [title]=\"t('cardStyle')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4 mb-4\">\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"borderRadius\") }}:\r\n {{ cardStyleConfig().borderRadius || 8 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"cardStyleConfig().borderRadius || 8\"\r\n (ngModelChange)=\"updateCardStyleConfig('borderRadius', $event)\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <mt-color-picker-field\r\n [label]=\"t('cardBackgroundColor')\"\r\n [ngModel]=\"cardStyleConfig().backgroundColor || ''\"\r\n (ngModelChange)=\"updateCardStyleConfig('backgroundColor', $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Shadows -->\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"font-medium\">{{ t(\"shadows\") }}</span>\r\n <mt-button\r\n [label]=\"t('addShadow')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addShadow()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n shadow of cardStyleConfig().shadows || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"shadow\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeShadow(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-5 gap-2\">\r\n <mt-number-field\r\n [label]=\"t('x')\"\r\n [ngModel]=\"shadow.x\"\r\n (ngModelChange)=\"updateShadow(i, 'x', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('y')\"\r\n [ngModel]=\"shadow.y\"\r\n (ngModelChange)=\"updateShadow(i, 'y', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('blur')\"\r\n [ngModel]=\"shadow.blur\"\r\n (ngModelChange)=\"updateShadow(i, 'blur', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('spread')\"\r\n [ngModel]=\"shadow.spread\"\r\n (ngModelChange)=\"updateShadow(i, 'spread', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"shadow.color\"\r\n (ngModelChange)=\"updateShadow(i, 'color', $event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Legend Settings -->\r\n @if (shouldShowField(\"legend\")) {\r\n <mt-card [title]=\"t('legendSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLegend')\"\r\n [ngModel]=\"legendConfig().show || false\"\r\n (ngModelChange)=\"updateLegend('show', $event)\"\r\n />\r\n @if (legendConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"legendConfig().position || 'bottom'\"\r\n (ngModelChange)=\"updateLegend('position', $event)\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"legendIconType\")) {\r\n <mt-select-field\r\n [label]=\"t('legendIconType')\"\r\n [ngModel]=\"legendConfig().iconType || 'circle'\"\r\n (ngModelChange)=\"updateLegend('iconType', $event)\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Settings -->\r\n @if (shouldShowField(\"label\")) {\r\n <mt-card [title]=\"t('labelSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabels')\"\r\n [ngModel]=\"labelConfig().show || false\"\r\n (ngModelChange)=\"updateLabel('show', $event)\"\r\n />\r\n @if (labelConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"labelConfig().position || 'inside'\"\r\n (ngModelChange)=\"updateLabel('position', $event)\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"showTotal\")) {\r\n <mt-toggle-field\r\n [label]=\"t('showTotalInTop')\"\r\n [ngModel]=\"labelConfig().showTotalInTop || false\"\r\n (ngModelChange)=\"updateLabel('showTotalInTop', $event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Center (for Pie/Donut charts) -->\r\n @if (shouldShowField(\"labelCenter\")) {\r\n <mt-card [title]=\"t('labelCenter')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideLabelCenter')\"\r\n [ngModel]=\"labelCenterConfig().hide || false\"\r\n (ngModelChange)=\"updateLabelCenterConfig('hide', $event)\"\r\n />\r\n @if (!labelCenterConfig().hide) {\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextEn')\"\r\n [ngModel]=\"labelCenterConfig().text?.en || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('en', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextAr')\"\r\n [ngModel]=\"labelCenterConfig().text?.ar || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('ar', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Override Labels -->\r\n @if (shouldShowField(\"overrideLabels\")) {\r\n <mt-card [title]=\"t('overrideLabels')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"overrideLabelsDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addLabel')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOverrideLabel()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n label of overrideLabels();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"label\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeOverrideLabel(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"label.en\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'en', $event)\"\r\n [placeholder]=\"t('enterLabelEn')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"label.ar\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'ar', $event)\"\r\n [placeholder]=\"t('enterLabelAr')\"\r\n dir=\"rtl\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (overrideLabels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOverrideLabels\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Sort Data Bars -->\r\n @if (shouldShowField(\"sortDataBars\")) {\r\n <mt-card [title]=\"t('sortDataBars')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableSorting')\"\r\n [ngModel]=\"sortDataBarsConfig().enable || false\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('enable', $event)\"\r\n />\r\n @if (sortDataBarsConfig().enable) {\r\n <mt-text-field\r\n [label]=\"t('sortBy')\"\r\n [ngModel]=\"sortDataBarsConfig().sortBy || ''\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('sortBy', $event)\"\r\n [placeholder]=\"t('propertyKey')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('order')\"\r\n [ngModel]=\"sortDataBarsConfig().order || 'asc'\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('order', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Default Colors (for charts) -->\r\n @if (shouldShowField(\"defaultColors\")) {\r\n <mt-card [title]=\"t('defaultColors')\">\r\n <div class=\"flex flex-wrap gap-2 mb-4\">\r\n @for (\r\n color of defaultColors();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 p-2 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-color-picker-field\r\n [ngModel]=\"color\"\r\n (ngModelChange)=\"updateDefaultColor(i, $event)\"\r\n />\r\n <mt-button\r\n icon=\"general.x-close\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeDefaultColor(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"flex flex-wrap gap-2 items-center\">\r\n <span class=\"text-sm text-muted-color xl:mr-2\">{{ t(\"quickAdd\") }}:</span>\r\n @for (color of defaultColorPalette; track color) {\r\n <button\r\n type=\"button\"\r\n class=\"w-6 h-6 rounded cursor-pointer border border-surface-300 hover:scale-110 transition-transform\"\r\n [style.background-color]=\"color\"\r\n (click)=\"addDefaultColor(color)\"\r\n [pTooltip]=\"color\"\r\n tooltipPosition=\"top\"\r\n ></button>\r\n }\r\n </div>\r\n\r\n @if (defaultColors().length === 0) {\r\n <div class=\"text-center py-2 text-muted-color text-sm mt-2\">\r\n {{ t(\"noColorsSelected\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Info -->\r\n @if (shouldShowField(\"cardInfo\")) {\r\n <mt-card [title]=\"t('cardInfo')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showCardInfo')\"\r\n [ngModel]=\"cardInfo().show || false\"\r\n (ngModelChange)=\"updateCardInfoConfig('show', $event)\"\r\n />\r\n @if (cardInfo().show) {\r\n <mt-text-field\r\n [label]=\"t('cardInfoValue')\"\r\n [ngModel]=\"cardInfo().value || ''\"\r\n (ngModelChange)=\"updateCardInfoConfig('value', $event)\"\r\n [placeholder]=\"t('enterCardInfoValue')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Settings -->\r\n @if (shouldShowField(\"hideIndex\")) {\r\n <mt-card [title]=\"t('tableSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideIndex')\"\r\n [ngModel]=\"configAsType()['hideIndex'] || false\"\r\n (ngModelChange)=\"updateConfigAsType('hideIndex', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Map Settings -->\r\n @if (shouldShowField(\"mapChart\")) {\r\n <mt-card [title]=\"t('mapSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('mapType')\"\r\n [ngModel]=\"config()?.clientConfig?.['map'] || 'SaudiArabia'\"\r\n (ngModelChange)=\"updateMapType($event)\"\r\n [options]=\"mapOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Format Configuration -->\r\n @if (shouldShowField(\"format\")) {\r\n <mt-card [title]=\"t('formatConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatConfig().type\"\r\n (ngModelChange)=\"updateFormatConfig('type', $event)\"\r\n [options]=\"formatTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n\r\n @if (formatConfig().type === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"formatConfig().showCurrency || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrency', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showCurrencyTooltip')\"\r\n [ngModel]=\"formatConfig().showCurrencyTooltip || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrencyTooltip', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('handleLanguage')\"\r\n [ngModel]=\"formatConfig().handleLang || false\"\r\n (ngModelChange)=\"updateFormatConfig('handleLang', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hideSuffixes')\"\r\n [ngModel]=\"formatConfig().hideSuffixes || false\"\r\n (ngModelChange)=\"updateFormatConfig('hideSuffixes', $event)\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"custom\") {\r\n <mt-text-field\r\n [label]=\"t('customText')\"\r\n [ngModel]=\"formatConfig().customText || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customText', $event)\"\r\n [placeholder]=\"t('enterCustomText')\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"date\") {\r\n <mt-text-field\r\n [label]=\"t('dateFormat')\"\r\n [ngModel]=\"formatConfig().customDateFormat || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customDateFormat', $event)\"\r\n [placeholder]=\"'YYYY-MM-DD'\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Format Configuration -->\r\n @if (shouldShowField(\"tableFormat\")) {\r\n <mt-card [title]=\"t('tableFormatConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <!-- Colors -->\r\n <mt-color-picker-field\r\n [label]=\"t('headerTextColor')\"\r\n [ngModel]=\"tableFormatConfig().thTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().thBackgroundColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thBackgroundColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cellTextColor')\"\r\n [ngModel]=\"tableFormatConfig().tdTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().groupBackgroundColor || ''\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('groupBackgroundColor', $event)\r\n \"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupTextColor')\"\r\n [ngModel]=\"tableFormatConfig().groupTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('groupTextColor', $event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n <!-- Font Settings -->\r\n <mt-toggle-field\r\n [label]=\"t('boldHeaderFont')\"\r\n [ngModel]=\"tableFormatConfig().thFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontBold', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('boldCellFont')\"\r\n [ngModel]=\"tableFormatConfig().tdFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontBold', $event)\"\r\n />\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"headerFontSize\") }}:\r\n {{ tableFormatConfig().thFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().thFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"cellFontSize\") }}:\r\n {{ tableFormatConfig().tdFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().tdFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-4 gap-4\">\r\n <!-- Options -->\r\n <mt-toggle-field\r\n [label]=\"t('hideTableSubheader')\"\r\n [ngModel]=\"tableFormatConfig().hideTableSubheader || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('hideTableSubheader', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('disableCurrencyFormat')\"\r\n [ngModel]=\"tableFormatConfig().disableCurrencyFormat || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('disableCurrencyFormat', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageAsProgressBar')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageAsProgressBar || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageAsProgressBar', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageStatus')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageStatus || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageStatus', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-4\">\r\n <!-- Sort & Hidden Columns -->\r\n <mt-select-field\r\n [label]=\"t('sortColumn')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.column || ''\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('column', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumn')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('sortDirection')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.direction || 'asc'\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('direction', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenColumns')\"\r\n [ngModel]=\"tableFormatConfig().hiddenColumns || []\"\r\n (ngModelChange)=\"updateTableFormatConfig('hiddenColumns', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumns')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <mt-button\r\n [label]=\"t('resetToDefault')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"resetTableFormat()\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Color By Condition -->\r\n @if (shouldShowField(\"colorByCondition\")) {\r\n <mt-card [title]=\"t('colorByCondition')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"colorByConditionDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('add')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addColorConditionIndex()\"\r\n />\r\n </div>\r\n\r\n @for (barIndex of getColorConditionIndexes(); track barIndex) {\r\n <div class=\"mb-4 border border-surface-200 rounded-lg\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\">\r\n <div class=\"flex items-center gap-2\">\r\n <button\r\n type=\"button\"\r\n class=\"text-sm text-muted-color\"\r\n (click)=\"toggleColorConditionExpanded(barIndex)\"\r\n >\r\n {{ isColorConditionExpanded(barIndex) ? \"-\" : \"+\" }}\r\n </button>\r\n <span class=\"font-medium text-sm\"\r\n >{{ t(\"bar\") }} {{ barIndex }}</span\r\n >\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n addColorCondition(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeColorConditionIndex(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (isColorConditionExpanded(barIndex)) {\r\n <div class=\"p-3\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"conditions\") }}</span>\r\n <mt-button\r\n [label]=\"t('addCondition')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addColorCondition(barIndex)\"\r\n />\r\n </div>\r\n\r\n @for (\r\n condition of colorByCondition()[barIndex] || [];\r\n track trackByIndex($index);\r\n let condIndex = $index\r\n ) {\r\n <div class=\"p-3 border border-surface-200 rounded-lg mb-3\">\r\n <div class=\"grid grid-cols-1 2xl:grid-cols-6 gap-3 items-end\">\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"condition.color\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'color',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('condition')\"\r\n [ngModel]=\"condition.type\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'type',\r\n $event\r\n )\r\n \"\r\n [options]=\"colorConditionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-number-field\r\n [label]=\"\r\n condition.type === 'between' ? t('from') : t('value')\r\n \"\r\n [ngModel]=\"condition.value1\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value1',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n @if (condition.type === \"between\") {\r\n <mt-number-field\r\n [label]=\"t('to')\"\r\n [ngModel]=\"condition.value2\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value2',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n }\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeColorCondition(barIndex, condIndex)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3 mt-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"condition.labelEn || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelEn',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"condition.labelAr || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelAr',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((colorByCondition()[barIndex] || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (getColorConditionIndexes().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Timeline Header Colors -->\r\n @if (shouldShowField(\"timelineHeaderColorsConfig\")) {\r\n <mt-card [title]=\"t('timelineHeaderColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().bgColor || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('bgColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().color || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('color', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Ring Gauge Configuration -->\r\n @if (shouldShowField(\"ringGaugeConfig\")) {\r\n <mt-card [title]=\"t('ringGaugeConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('centerProperty')\"\r\n [ngModel]=\"ringGaugeConfig().centerProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('centerProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('statusProperty')\"\r\n [ngModel]=\"ringGaugeConfig().statusProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('statusProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"mt-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenProperties')\"\r\n [ngModel]=\"ringGaugeConfig().hiddenProperties || []\"\r\n (ngModelChange)=\"updateRingGaugeConfig('hiddenProperties', $event)\"\r\n [options]=\"ringGaugeHiddenOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Order Configuration -->\r\n @if (shouldShowField(\"orderConfig\")) {\r\n <mt-card [title]=\"t('orderConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4 mb-4\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n [ngModel]=\"orderConfig().operation || 'deleteNotEqual'\"\r\n (ngModelChange)=\"updateOrderConfig('operation', $event)\"\r\n [options]=\"orderOperationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('orderBy')\"\r\n [ngModel]=\"orderConfig().orderBy || ''\"\r\n (ngModelChange)=\"updateOrderConfig('orderBy', $event)\"\r\n [placeholder]=\"t('enterPropertyKey')\"\r\n />\r\n </div>\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"orderConfigurationDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addOrderItem')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOrderItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of orderConfig().order || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 flex flex-col gap-3 rounded-lg border border-surface-200 bg-surface-50 p-4 xl:flex-row xl:items-center\"\r\n >\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n <span class=\"text-sm font-medium w-auto xl:w-8\">{{ i + 1 }}.</span>\r\n <mt-text-field\r\n [ngModel]=\"item\"\r\n (ngModelChange)=\"updateOrderItem(i, $event)\"\r\n [placeholder]=\"t('enterPropertyKey')\"\r\n size=\"small\"\r\n class=\"min-w-0 flex-1\"\r\n />\r\n </div>\r\n <div class=\"flex items-center justify-end gap-1\">\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === 0\"\r\n (onClick)=\"moveOrderItemUp(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === (orderConfig().order || []).length - 1\"\r\n (onClick)=\"moveOrderItemDown(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeOrderItem(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((orderConfig().order || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOrderItems\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card List Configuration -->\r\n @if (shouldShowField(\"cardListConfig\")) {\r\n <mt-card [title]=\"t('cardListConfiguration')\">\r\n <mt-multi-select-field\r\n [label]=\"t('hideProperties')\"\r\n [ngModel]=\"cardListConfig().hideProperties || []\"\r\n (ngModelChange)=\"updateCardListHideProperties($event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertiesToHide')\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Props Config As Index -->\r\n @if (shouldShowField(\"propsConfigAsIndex\")) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"text-sm text-muted-color\">{{ t(\"properties\") }}</span>\r\n <mt-button\r\n [label]=\"t('addProperty')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addPropsConfigItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of propsConfigAsIndex();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"property\") }} {{ i + 1 }}</span\r\n >\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropsConfigItem(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 2xl:grid-cols-4 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"item.width || ''\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'width', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"item.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(i, 'colorAsProperty', $event)\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"item.border || []\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'border', $event)\"\r\n [options]=\"borderOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hidden')\"\r\n [ngModel]=\"item.hidden || false\"\r\n (ngModelChange)=\"updatePropsConfigItem(i, 'hidden', $event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Toggle Association -->\r\n @if (shouldShowField(\"toggleAssociation\")) {\r\n <mt-card [title]=\"t('toggleAssociation')\">\r\n <mt-toggle-field\r\n [label]=\"t('enableToggleAssociation')\"\r\n [ngModel]=\"toggleAssociation()\"\r\n (ngModelChange)=\"updateToggleAssociation($event)\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Translations -->\r\n @if (\r\n shouldShowField(\"propertyTranslations\") &&\r\n resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyTranslations')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyTranslations()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyTranslationsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyTranslationsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyTranslationsPasteText()\"\r\n (ngModelChange)=\"propertyTranslationsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyTranslationsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyTranslationsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyTranslationsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyTranslationsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForTranslation()\"\r\n (ngModelChange)=\"selectedPropertyForTranslation.set($event)\"\r\n [options]=\"availableTranslationOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertyToTranslate')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForTranslation()\"\r\n (onClick)=\"\r\n addPropertyTranslation(selectedPropertyForTranslation());\r\n selectedPropertyForTranslation.set('')\r\n \"\r\n [pTooltip]=\"t('addTranslation')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Translation List -->\r\n @for (propKey of getPropertyTranslationKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyTranslation(propKey)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"propertyTranslations()[propKey]?.ar || ''\"\r\n (ngModelChange)=\"updatePropertyTranslation(propKey, 'ar', $event)\"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"propertyTranslations()[propKey]?.en || ''\"\r\n (ngModelChange)=\"updatePropertyTranslation(propKey, 'en', $event)\"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getPropertyTranslationKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Colors -->\r\n @if (\r\n shouldShowField(\"propertyColors\") && resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyColors')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyColors()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyColorsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyColorsPasteText()\"\r\n (ngModelChange)=\"propertyColorsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyColorsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyColorsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyColorsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForColor()\"\r\n (ngModelChange)=\"selectedPropertyForColor.set($event)\"\r\n [options]=\"availableColorOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForColor()\"\r\n (onClick)=\"\r\n addPropertyColor(selectedPropertyForColor());\r\n selectedPropertyForColor.set('')\r\n \"\r\n [pTooltip]=\"t('addProperty')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Property Color List -->\r\n @for (propKey of getPropertyColorKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyColor(propKey)\"\r\n />\r\n </div>\r\n <mt-select-field\r\n [label]=\"t('selectColorProperty')\"\r\n [ngModel]=\"propertyColors()[propKey]?.selectedKey || ''\"\r\n (ngModelChange)=\"updatePropertyColor(propKey, $event)\"\r\n [options]=\"allPropertyKeyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (getPropertyColorKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyColors\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Format X-Axis Configuration -->\r\n @if (shouldShowField(\"formatXAxis\")) {\r\n <mt-card [title]=\"t('formatXAxisConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatXAxisConfig().type\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('type', $event)\"\r\n [options]=\"formatXAxisTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n @if (\r\n formatXAxisConfig().type === \"dateToMonth\" ||\r\n formatXAxisConfig().type === \"month\"\r\n ) {\r\n <mt-toggle-field\r\n [label]=\"t('shortFormat')\"\r\n [ngModel]=\"formatXAxisConfig().shortFormate || false\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('shortFormate', $event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Extra Column From Lookup -->\r\n @if (shouldShowField(\"extraColumnFromLookup\")) {\r\n <mt-card [title]=\"t('extraColumnFromLookup')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableExtraColumnFromLookup')\"\r\n [ngModel]=\"tableColumnsConfig().extraCoulmnFromLookup || false\"\r\n (ngModelChange)=\"\r\n updateTableColumnsConfig('extraCoulmnFromLookup', $event)\r\n \"\r\n />\r\n\r\n @if (tableColumnsConfig().extraCoulmnFromLookup) {\r\n <mt-select-field\r\n [label]=\"t('lookup')\"\r\n [ngModel]=\"tableColumnsConfig().lookupId\"\r\n (ngModelChange)=\"updateTableColumnsConfig('lookupId', $event)\"\r\n [options]=\"lookups()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectLookup')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('groupedBy')\"\r\n [ngModel]=\"tableColumnsConfig().groupedBy\"\r\n (ngModelChange)=\"updateTableColumnsConfig('groupedBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"tableColumnsConfig().propKey\"\r\n (ngModelChange)=\"updateTableColumnsConfig('propKey', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n</div>\r\n" }]
3075
3087
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], chartType: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartType", required: false }] }], availableProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableProperties", required: false }] }], selectedProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedProperties", required: false }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], clientConfigChange: [{ type: i0.Output, args: ["clientConfigChange"] }] } });
3076
3088
 
@@ -3882,10 +3894,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
3882
3894
  CommonModule,
3883
3895
  FormsModule,
3884
3896
  TranslocoDirective,
3885
- Button,
3886
3897
  TextField,
3887
- SelectField,
3888
- CheckboxField,
3889
3898
  Card,
3890
3899
  TooltipModule,
3891
3900
  Icon,
@@ -4687,7 +4696,7 @@ class SelectionConfiguration {
4687
4696
  useExisting: forwardRef(() => SelectionConfiguration),
4688
4697
  multi: true,
4689
4698
  },
4690
- ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isFixedSelection(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module (grouped by module type) -->\r\n <mt-select-field\r\n [label]=\"t('module')\"\r\n formControlName=\"selector\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [loading]=\"loadingTree()\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isFixedSelection(selection.value.id)\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (ngModelChange)=\"onModuleChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required"] }, { kind: "component", type: FilterValueField, selector: "mt-filter-value-field", inputs: ["label", "placeholder", "extraProperties"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip$1, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4699
+ ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isFixedSelection(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module (grouped by module type) -->\r\n <mt-select-field\r\n [label]=\"t('module')\"\r\n formControlName=\"selector\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [loading]=\"loadingTree()\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isFixedSelection(selection.value.id)\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (ngModelChange)=\"onModuleChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required"] }, { kind: "component", type: FilterValueField, selector: "mt-filter-value-field", inputs: ["label", "placeholder", "extraProperties"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4691
4700
  }
4692
4701
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SelectionConfiguration, decorators: [{
4693
4702
  type: Component,
@@ -4698,12 +4707,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
4698
4707
  TranslocoDirective,
4699
4708
  Button,
4700
4709
  SelectField,
4701
- TextField,
4702
4710
  NumberField,
4703
4711
  TextareaField,
4704
4712
  FilterValueField,
4705
4713
  Card,
4706
- Tooltip$1,
4714
+ Tooltip,
4707
4715
  Skeleton,
4708
4716
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
4709
4717
  {
@@ -5010,7 +5018,7 @@ class SourceLinkConfiguration {
5010
5018
  useExisting: forwardRef(() => SourceLinkConfiguration),
5011
5019
  multi: true,
5012
5020
  },
5013
- ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('sourceLinks')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addSourceLink()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addSourceLink')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"sourceLinksForm\">\r\n <div formArrayName=\"sourceLinks\">\r\n @for (\r\n link of sourceLinksArray.controls;\r\n track trackByIndex(i);\r\n let i = $index;\r\n let first = $first\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"link.invalid\"\r\n [class.border-surface-200]=\"!link.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Link Header with Type Tabs -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-3\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n\r\n <!-- Link Type Tabs (only show for non-first links) -->\r\n @if (!first) {\r\n <mt-tabs\r\n [active]=\"getLinkType(i)\"\r\n (activeChange)=\"onLinkTypeChange(i, $event)\"\r\n [options]=\"getLinkTypeOptions(i)\"\r\n size=\"small\"\r\n />\r\n } @else {\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n {{ t(\"selectionToSelection\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSourceLink(i)\"\r\n />\r\n </div>\r\n\r\n <!-- Source Selections based on link type -->\r\n @if (getLinkType(i) === \"selection\") {\r\n <!-- Selection to Selection Mode -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source1')\"\r\n formControlName=\"source1SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n } @else {\r\n <!-- Chained Mode: Previous Link to Selection -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source Link (previous link) -->\r\n <mt-select-field\r\n [label]=\"t('previousLink')\"\r\n formControlName=\"sourceLinkId\"\r\n [options]=\"getAvailableSourceLinks(i)\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"index\"\r\n [placeholder]=\"t('selectPreviousLink')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Link Properties -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Property -->\r\n <mt-select-field\r\n [label]=\"t('source1LinkProperty')\"\r\n formControlName=\"source1PropertyKey\"\r\n [options]=\"getSource1PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n\r\n <!-- Source 2 Property -->\r\n <mt-select-field\r\n [label]=\"t('source2LinkProperty')\"\r\n formControlName=\"source2PropertyKey\"\r\n [options]=\"getSource2PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Join Options -->\r\n <div class=\"flex items-center gap-6\">\r\n <mt-toggle-field\r\n [label]=\"t('isLeftJoin')\"\r\n formControlName=\"isLeftJoin\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('isFilterLinkage')\"\r\n formControlName=\"isFilterLinkage\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (sourceLinksArray.length === 0) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-link-01 text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSourceLinksConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSourceLink')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSourceLink()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "directive", type: Tooltip$1, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5021
+ ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('sourceLinks')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addSourceLink()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addSourceLink')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"sourceLinksForm\">\r\n <div formArrayName=\"sourceLinks\">\r\n @for (\r\n link of sourceLinksArray.controls;\r\n track trackByIndex(i);\r\n let i = $index;\r\n let first = $first\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"link.invalid\"\r\n [class.border-surface-200]=\"!link.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Link Header with Type Tabs -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-3\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n\r\n <!-- Link Type Tabs (only show for non-first links) -->\r\n @if (!first) {\r\n <mt-tabs\r\n [active]=\"getLinkType(i)\"\r\n (activeChange)=\"onLinkTypeChange(i, $event)\"\r\n [options]=\"getLinkTypeOptions(i)\"\r\n size=\"small\"\r\n />\r\n } @else {\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n {{ t(\"selectionToSelection\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSourceLink(i)\"\r\n />\r\n </div>\r\n\r\n <!-- Source Selections based on link type -->\r\n @if (getLinkType(i) === \"selection\") {\r\n <!-- Selection to Selection Mode -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source1')\"\r\n formControlName=\"source1SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n } @else {\r\n <!-- Chained Mode: Previous Link to Selection -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source Link (previous link) -->\r\n <mt-select-field\r\n [label]=\"t('previousLink')\"\r\n formControlName=\"sourceLinkId\"\r\n [options]=\"getAvailableSourceLinks(i)\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"index\"\r\n [placeholder]=\"t('selectPreviousLink')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Link Properties -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Property -->\r\n <mt-select-field\r\n [label]=\"t('source1LinkProperty')\"\r\n formControlName=\"source1PropertyKey\"\r\n [options]=\"getSource1PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n\r\n <!-- Source 2 Property -->\r\n <mt-select-field\r\n [label]=\"t('source2LinkProperty')\"\r\n formControlName=\"source2PropertyKey\"\r\n [options]=\"getSource2PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Join Options -->\r\n <div class=\"flex items-center gap-6\">\r\n <mt-toggle-field\r\n [label]=\"t('isLeftJoin')\"\r\n formControlName=\"isLeftJoin\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('isFilterLinkage')\"\r\n formControlName=\"isFilterLinkage\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (sourceLinksArray.length === 0) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-link-01 text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSourceLinksConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSourceLink')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSourceLink()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5014
5022
  }
5015
5023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SourceLinkConfiguration, decorators: [{
5016
5024
  type: Component,
@@ -5024,7 +5032,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5024
5032
  ToggleField,
5025
5033
  Card,
5026
5034
  Tabs,
5027
- Tooltip$1,
5035
+ Tooltip,
5028
5036
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5029
5037
  {
5030
5038
  provide: NG_VALUE_ACCESSOR,
@@ -5114,7 +5122,7 @@ class CustomApiConfiguration {
5114
5122
  useExisting: forwardRef(() => CustomApiConfiguration),
5115
5123
  multi: true,
5116
5124
  },
5117
- ], ngImport: i0, template: "<mt-card [title]=\"'Custom API'\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col gap-4\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"customApiDescription\") }}\r\n </p>\r\n\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <!-- HTTP Method -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('httpMethod')\"\r\n [options]=\"methodOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [ngModel]=\"method()\"\r\n (ngModelChange)=\"onMethodChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n\r\n <!-- Custom API URL -->\r\n <div class=\"col-span-9\">\r\n <mt-text-field\r\n [label]=\"t('customApiUrl')\"\r\n [placeholder]=\"t('customApiUrlPlaceholder')\"\r\n [ngModel]=\"customApiUrl()\"\r\n (ngModelChange)=\"onUrlChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</mt-card>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5125
+ ], ngImport: i0, template: "<mt-card\r\n [title]=\"t('customApi')\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div class=\"flex flex-col gap-4\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"customApiDescription\") }}\r\n </p>\r\n\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <!-- HTTP Method -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('httpMethod')\"\r\n [options]=\"methodOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [ngModel]=\"method()\"\r\n (ngModelChange)=\"onMethodChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n\r\n <!-- Custom API URL -->\r\n <div class=\"col-span-9\">\r\n <mt-text-field\r\n [label]=\"t('customApiUrl')\"\r\n [placeholder]=\"t('customApiUrlPlaceholder')\"\r\n [ngModel]=\"customApiUrl()\"\r\n (ngModelChange)=\"onUrlChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</mt-card>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5118
5126
  }
5119
5127
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CustomApiConfiguration, decorators: [{
5120
5128
  type: Component,
@@ -5131,7 +5139,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5131
5139
  useExisting: forwardRef(() => CustomApiConfiguration),
5132
5140
  multi: true,
5133
5141
  },
5134
- ], template: "<mt-card [title]=\"'Custom API'\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col gap-4\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"customApiDescription\") }}\r\n </p>\r\n\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <!-- HTTP Method -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('httpMethod')\"\r\n [options]=\"methodOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [ngModel]=\"method()\"\r\n (ngModelChange)=\"onMethodChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n\r\n <!-- Custom API URL -->\r\n <div class=\"col-span-9\">\r\n <mt-text-field\r\n [label]=\"t('customApiUrl')\"\r\n [placeholder]=\"t('customApiUrlPlaceholder')\"\r\n [ngModel]=\"customApiUrl()\"\r\n (ngModelChange)=\"onUrlChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</mt-card>\r\n" }]
5142
+ ], template: "<mt-card\r\n [title]=\"t('customApi')\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div class=\"flex flex-col gap-4\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"customApiDescription\") }}\r\n </p>\r\n\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <!-- HTTP Method -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('httpMethod')\"\r\n [options]=\"methodOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [ngModel]=\"method()\"\r\n (ngModelChange)=\"onMethodChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n\r\n <!-- Custom API URL -->\r\n <div class=\"col-span-9\">\r\n <mt-text-field\r\n [label]=\"t('customApiUrl')\"\r\n [placeholder]=\"t('customApiUrlPlaceholder')\"\r\n [ngModel]=\"customApiUrl()\"\r\n (ngModelChange)=\"onUrlChange($event)\"\r\n [disabled]=\"disabled()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n</mt-card>\r\n" }]
5135
5143
  }] });
5136
5144
 
5137
5145
  /**
@@ -5408,7 +5416,7 @@ class GeneralQuery {
5408
5416
  useExisting: forwardRef(() => GeneralQuery),
5409
5417
  multi: true,
5410
5418
  },
5411
- ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-4\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n [formGroup]=\"queryForm\"\r\n>\r\n <!-- Category Property (shown for certain chart types) -->\r\n @if (shouldShowField(\"categoryProperty\")) {\r\n <div class=\"mb-2\">\r\n <mt-select-field\r\n [label]=\"t('categoryProperty')\"\r\n formControlName=\"categoryProperty\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectCategoryProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Add Series Button -->\r\n @if (chartType() !== \"overview\" || seriesArray.length === 0) {\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSeries')\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSeries()\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Series List -->\r\n <div formArrayName=\"series\" class=\"flex flex-col gap-4\">\r\n @for (\r\n series of seriesArray.controls;\r\n track trackByIndex(i);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all\"\r\n [class.border-red-500]=\"series.invalid\"\r\n [class.border-surface-200]=\"!series.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Series Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">{{\r\n t(\"series\")\r\n }}</span>\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.settings-02\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"toggleAdvanced(i)\"\r\n [pTooltip]=\"t('advancedSettings')\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"deleteSeries(i)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n <!-- Auto Stack Toggle -->\r\n @if (shouldShowField(\"autoStack\")) {\r\n <div class=\"md:col-span-2 lg:col-span-3\">\r\n <mt-toggle-field\r\n [label]=\"t('autoStack')\"\r\n formControlName=\"autoStack\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Value Property -->\r\n @if (shouldShowField(\"valueProperty\") || series.value.autoStack) {\r\n <mt-select-field\r\n [label]=\"t('valueProperty')\"\r\n formControlName=\"valueProperty\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectValueProperty')\"\r\n [filter]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Aggregate Function -->\r\n @if (shouldShowField(\"aggregateFunction\")) {\r\n <mt-select-field\r\n [label]=\"t('aggregateFunction')\"\r\n formControlName=\"aggregateFunction\"\r\n [options]=\"aggregateFunctions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n\r\n <!-- Color Picker -->\r\n @if (shouldShowField(\"color\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('seriesColor')\"\r\n formControlName=\"color\"\r\n />\r\n }\r\n\r\n <!-- Bar Type (for stacked bar charts) -->\r\n @if (shouldShowField(\"barType\")) {\r\n <mt-select-field\r\n [label]=\"t('barType')\"\r\n formControlName=\"barType\"\r\n [options]=\"barTypes\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n />\r\n }\r\n\r\n <!-- Auto Stack By Property -->\r\n @if (\r\n shouldShowField(\"autoStackByProperty\") && series.value.autoStack\r\n ) {\r\n <mt-select-field\r\n [label]=\"t('autoStackByProperty')\"\r\n formControlName=\"autoStackByProperty\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Group By Properties -->\r\n @if (shouldShowField(\"groupByProperties\")) {\r\n <div class=\"col-span-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('groupByProperties')\"\r\n formControlName=\"groupByProperties\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Stack Properties (for stacked charts) -->\r\n @if (shouldShowField(\"stackProperties\")) {\r\n <div class=\"col-span-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('stackProperties')\"\r\n formControlName=\"stackProperties\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Extra Properties -->\r\n @if (shouldShowField(\"extraProperties\")) {\r\n <div class=\"col-span-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('extraProperties')\"\r\n formControlName=\"extraProperties\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Advanced Settings (Formula) -->\r\n @if (series.value.showAdvancedSettings && shouldShowField(\"formula\")) {\r\n <div\r\n class=\"mt-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <div class=\"text-sm font-medium mb-2\">\r\n {{ t(\"advancedSettings\") }}\r\n </div>\r\n <mt-text-field\r\n [label]=\"t('formula')\"\r\n formControlName=\"formula\"\r\n [placeholder]=\"t('enterFormula')\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Filters Section -->\r\n @if (shouldShowField(\"filters\")) {\r\n <div class=\"mt-4 border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"seriesFilters\") }}</span>\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(series).controls;\r\n track trackByIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"grid grid-cols-12 gap-2 p-3 bg-surface-50 rounded-lg border border-surface-100\"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Property Key -->\r\n <div class=\"col-span-4\">\r\n <mt-select-field\r\n [label]=\"j === 0 ? t('property') : ''\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"\r\n useGroupedSelect()\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"j === 0 ? t('operator') : ''\"\r\n formControlName=\"operator\"\r\n [options]=\"operators\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n\r\n <!-- Value -->\r\n <div class=\"col-span-4\">\r\n <mt-text-field\r\n [label]=\"j === 0 ? t('value') : ''\"\r\n formControlName=\"value\"\r\n [placeholder]=\"t('enterValue')\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter -->\r\n <div class=\"col-span-2 flex items-end justify-end pb-1\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(series).length === 0) {\r\n <div class=\"text-center py-3 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (seriesArray.length === 0) {\r\n <div\r\n class=\"text-center py-8 text-muted-color border border-dashed border-surface-300 rounded-lg\"\r\n >\r\n <i class=\"mti mti-chart-bar text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSeriesConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSeries')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSeries()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "directive", type: Tooltip$1, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5419
+ ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-4\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n [formGroup]=\"queryForm\"\r\n>\r\n <!-- Category Property (shown for certain chart types) -->\r\n @if (shouldShowField(\"categoryProperty\")) {\r\n <div class=\"mb-2\">\r\n <mt-select-field\r\n [label]=\"t('categoryProperty')\"\r\n formControlName=\"categoryProperty\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectCategoryProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Add Series Button -->\r\n @if (chartType() !== \"overview\" || seriesArray.length === 0) {\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSeries')\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSeries()\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Series List -->\r\n <div formArrayName=\"series\" class=\"flex flex-col gap-4\">\r\n @for (\r\n series of seriesArray.controls;\r\n track trackByIndex(i);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all\"\r\n [class.border-red-500]=\"series.invalid\"\r\n [class.border-surface-200]=\"!series.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Series Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">{{\r\n t(\"series\")\r\n }}</span>\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.settings-02\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"toggleAdvanced(i)\"\r\n [pTooltip]=\"t('advancedSettings')\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"deleteSeries(i)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n <!-- Auto Stack Toggle -->\r\n @if (shouldShowField(\"autoStack\")) {\r\n <div class=\"md:col-span-2 lg:col-span-3\">\r\n <mt-toggle-field\r\n [label]=\"t('autoStack')\"\r\n formControlName=\"autoStack\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Value Property -->\r\n @if (shouldShowField(\"valueProperty\") || series.value.autoStack) {\r\n <mt-select-field\r\n [label]=\"t('valueProperty')\"\r\n formControlName=\"valueProperty\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectValueProperty')\"\r\n [filter]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Aggregate Function -->\r\n @if (shouldShowField(\"aggregateFunction\")) {\r\n <mt-select-field\r\n [label]=\"t('aggregateFunction')\"\r\n formControlName=\"aggregateFunction\"\r\n [options]=\"aggregateFunctions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n\r\n <!-- Color Picker -->\r\n @if (shouldShowField(\"color\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('seriesColor')\"\r\n formControlName=\"color\"\r\n />\r\n }\r\n\r\n <!-- Bar Type (for stacked bar charts) -->\r\n @if (shouldShowField(\"barType\")) {\r\n <mt-select-field\r\n [label]=\"t('barType')\"\r\n formControlName=\"barType\"\r\n [options]=\"barTypes\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n />\r\n }\r\n\r\n <!-- Auto Stack By Property -->\r\n @if (\r\n shouldShowField(\"autoStackByProperty\") && series.value.autoStack\r\n ) {\r\n <mt-select-field\r\n [label]=\"t('autoStackByProperty')\"\r\n formControlName=\"autoStackByProperty\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Group By Properties -->\r\n @if (shouldShowField(\"groupByProperties\")) {\r\n <div class=\"col-span-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('groupByProperties')\"\r\n formControlName=\"groupByProperties\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Stack Properties (for stacked charts) -->\r\n @if (shouldShowField(\"stackProperties\")) {\r\n <div class=\"col-span-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('stackProperties')\"\r\n formControlName=\"stackProperties\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Extra Properties -->\r\n @if (shouldShowField(\"extraProperties\")) {\r\n <div class=\"col-span-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('extraProperties')\"\r\n formControlName=\"extraProperties\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Advanced Settings (Formula) -->\r\n @if (series.value.showAdvancedSettings && shouldShowField(\"formula\")) {\r\n <div\r\n class=\"mt-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <div class=\"text-sm font-medium mb-2\">\r\n {{ t(\"advancedSettings\") }}\r\n </div>\r\n <mt-text-field\r\n [label]=\"t('formula')\"\r\n formControlName=\"formula\"\r\n [placeholder]=\"t('enterFormula')\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Filters Section -->\r\n @if (shouldShowField(\"filters\")) {\r\n <div class=\"mt-4 border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"seriesFilters\") }}</span>\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(series).controls;\r\n track trackByIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"grid grid-cols-12 gap-2 p-3 bg-surface-50 rounded-lg border border-surface-100\"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Property Key -->\r\n <div class=\"col-span-4\">\r\n <mt-select-field\r\n [label]=\"j === 0 ? t('property') : ''\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"\r\n useGroupedSelect()\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"j === 0 ? t('operator') : ''\"\r\n formControlName=\"operator\"\r\n [options]=\"operators\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n\r\n <!-- Value -->\r\n <div class=\"col-span-4\">\r\n <mt-text-field\r\n [label]=\"j === 0 ? t('value') : ''\"\r\n formControlName=\"value\"\r\n [placeholder]=\"t('enterValue')\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter -->\r\n <div class=\"col-span-2 flex items-end justify-end pb-1\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(series).length === 0) {\r\n <div class=\"text-center py-3 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (seriesArray.length === 0) {\r\n <div\r\n class=\"text-center py-8 text-muted-color border border-dashed border-surface-300 rounded-lg\"\r\n >\r\n <i class=\"mti mti-chart-bar text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSeriesConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSeries')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSeries()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5412
5420
  }
5413
5421
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GeneralQuery, decorators: [{
5414
5422
  type: Component,
@@ -5423,8 +5431,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5423
5431
  ToggleField,
5424
5432
  ColorPickerField,
5425
5433
  MultiSelectField,
5426
- Card,
5427
- Tooltip$1,
5434
+ Tooltip,
5428
5435
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5429
5436
  {
5430
5437
  provide: NG_VALUE_ACCESSOR,
@@ -5566,7 +5573,7 @@ class TableQuery {
5566
5573
  useExisting: forwardRef(() => TableQuery),
5567
5574
  multi: true,
5568
5575
  },
5569
- ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-4\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n [formGroup]=\"queryForm\"\r\n>\r\n <!-- Lookup Property -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('lookupProperty')\"\r\n formControlName=\"lookupProperty\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectLookupProperty')\"\r\n [filter]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Selected Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('properties')\"\r\n formControlName=\"selectedProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n @if (\r\n queryForm.get(\"selectedProperties\")?.invalid &&\r\n queryForm.get(\"selectedProperties\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n t(\"atLeastOnePropertyRequired\")\r\n }}</small>\r\n }\r\n </div>\r\n\r\n <!-- Pivot Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('pivotProperties')\"\r\n formControlName=\"PivotProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectPivotProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Aggregation Properties -->\r\n <mt-card [title]=\"t('aggregationProperties')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addAggregation()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addAggregation')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"AggregationProperties\">\r\n @for (\r\n agg of aggregationArray.controls;\r\n track trackByIndex(i);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"grid grid-cols-12 gap-3 p-3 bg-surface-50 rounded-lg border border-surface-100\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('property') : ''\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Aggregate Function -->\r\n <div class=\"col-span-4\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('aggregateFunction') : ''\"\r\n formControlName=\"aggregateFunction\"\r\n [options]=\"aggregateFunctions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n\r\n <!-- Remove -->\r\n <div class=\"col-span-3 flex items-end justify-end pb-1\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeAggregation(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (aggregationArray.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noAggregationsConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip$1, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5576
+ ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-4\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n [formGroup]=\"queryForm\"\r\n>\r\n <!-- Lookup Property -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('lookupProperty')\"\r\n formControlName=\"lookupProperty\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectLookupProperty')\"\r\n [filter]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Selected Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('properties')\"\r\n formControlName=\"selectedProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n @if (\r\n queryForm.get(\"selectedProperties\")?.invalid &&\r\n queryForm.get(\"selectedProperties\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n t(\"atLeastOnePropertyRequired\")\r\n }}</small>\r\n }\r\n </div>\r\n\r\n <!-- Pivot Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('pivotProperties')\"\r\n formControlName=\"PivotProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectPivotProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Aggregation Properties -->\r\n <mt-card [title]=\"t('aggregationProperties')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addAggregation()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addAggregation')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"AggregationProperties\">\r\n @for (\r\n agg of aggregationArray.controls;\r\n track trackByIndex(i);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"grid grid-cols-12 gap-3 p-3 bg-surface-50 rounded-lg border border-surface-100\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('property') : ''\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Aggregate Function -->\r\n <div class=\"col-span-4\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('aggregateFunction') : ''\"\r\n formControlName=\"aggregateFunction\"\r\n [options]=\"aggregateFunctions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n\r\n <!-- Remove -->\r\n <div class=\"col-span-3 flex items-end justify-end pb-1\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeAggregation(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (aggregationArray.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noAggregationsConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5570
5577
  }
5571
5578
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TableQuery, decorators: [{
5572
5579
  type: Component,
@@ -5579,7 +5586,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5579
5586
  SelectField,
5580
5587
  MultiSelectField,
5581
5588
  Card,
5582
- Tooltip$1,
5589
+ Tooltip,
5583
5590
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5584
5591
  {
5585
5592
  provide: NG_VALUE_ACCESSOR,
@@ -5667,7 +5674,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5667
5674
  TranslocoDirective,
5668
5675
  SelectField,
5669
5676
  MultiSelectField,
5670
- Card,
5671
5677
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5672
5678
  {
5673
5679
  provide: NG_VALUE_ACCESSOR,
@@ -5738,13 +5744,7 @@ class PropertiesQuery {
5738
5744
  }
5739
5745
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesQuery, decorators: [{
5740
5746
  type: Component,
5741
- args: [{ selector: 'mt-properties-query', standalone: true, imports: [
5742
- CommonModule,
5743
- FormsModule,
5744
- TranslocoDirective,
5745
- MultiSelectField,
5746
- Card,
5747
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5747
+ args: [{ selector: 'mt-properties-query', standalone: true, imports: [CommonModule, FormsModule, TranslocoDirective, MultiSelectField], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5748
5748
  {
5749
5749
  provide: NG_VALUE_ACCESSOR,
5750
5750
  useExisting: forwardRef(() => PropertiesQuery),
@@ -5840,7 +5840,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5840
5840
  MultiSelectField,
5841
5841
  TextField,
5842
5842
  ToggleField,
5843
- Card,
5844
5843
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5845
5844
  {
5846
5845
  provide: NG_VALUE_ACCESSOR,
@@ -5924,7 +5923,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5924
5923
  TranslocoDirective,
5925
5924
  SelectField,
5926
5925
  MultiSelectField,
5927
- Card,
5928
5926
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5929
5927
  {
5930
5928
  provide: NG_VALUE_ACCESSOR,
@@ -6015,7 +6013,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
6015
6013
  TranslocoDirective,
6016
6014
  SelectField,
6017
6015
  TextField,
6018
- Card,
6019
6016
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
6020
6017
  {
6021
6018
  provide: NG_VALUE_ACCESSOR,
@@ -6468,11 +6465,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
6468
6465
  ReactiveFormsModule,
6469
6466
  TranslocoDirective,
6470
6467
  Skeleton,
6471
- Button,
6472
6468
  SelectField,
6473
6469
  ToggleField,
6474
6470
  MultiSelectField,
6475
- TextField,
6476
6471
  Card,
6477
6472
  Tabs,
6478
6473
  SelectionConfiguration,
@@ -6777,18 +6772,17 @@ class ActionsSettings {
6777
6772
  return index;
6778
6773
  }
6779
6774
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ActionsSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
6780
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ActionsSettings, isStandalone: true, selector: "mt-actions-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clientConfigChange: "clientConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('actions')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addAction()\"\r\n [pTooltip]=\"t('addAction')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Actions List -->\r\n @for (\r\n action of actions();\r\n track $index;\r\n let i = $index;\r\n let first = $first;\r\n let last = $last\r\n ) {\r\n <div\r\n class=\"p-4 bg-surface-50 rounded-lg border border-surface-200 hover:border-surface-300 transition-all\"\r\n >\r\n <!-- Action Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"w-6 h-6 flex items-center justify-center bg-primary-100 text-primary-600 rounded-full text-sm font-medium\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <span class=\"font-medium text-sm\">\r\n {{ getActionTypeLabel(action.actionType) }}\r\n </span>\r\n <span class=\"text-xs text-muted-color\">\r\n ({{ getTriggerLabel(action.type) }})\r\n </span>\r\n </div>\r\n <div class=\"flex items-center gap-1\">\r\n <!-- Move Up -->\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"first\"\r\n (onClick)=\"moveActionUp(i)\"\r\n [pTooltip]=\"t('moveUp')\"\r\n />\r\n <!-- Move Down -->\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"last\"\r\n (onClick)=\"moveActionDown(i)\"\r\n [pTooltip]=\"t('moveDown')\"\r\n />\r\n <!-- Duplicate -->\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"duplicateAction(i)\"\r\n [pTooltip]=\"t('duplicate')\"\r\n />\r\n <!-- Remove -->\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeAction(i)\"\r\n [pTooltip]=\"t('remove')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Action Configuration -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n <!-- Trigger Type -->\r\n <mt-select-field\r\n [label]=\"t('trigger')\"\r\n [ngModel]=\"action.type\"\r\n (ngModelChange)=\"updateAction(i, 'type', $event)\"\r\n [options]=\"triggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <!-- Action Type -->\r\n <mt-select-field\r\n [label]=\"t('actionType')\"\r\n [ngModel]=\"action.actionType\"\r\n (ngModelChange)=\"updateAction(i, 'actionType', $event)\"\r\n [options]=\"actionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <!-- Target ID (for dialog/navigation) -->\r\n @if (\r\n action.actionType === \"openDialog\" ||\r\n action.actionType === \"navigateToPage\"\r\n ) {\r\n <mt-text-field\r\n [label]=\"t('targetId')\"\r\n [ngModel]=\"action.id || ''\"\r\n (ngModelChange)=\"updateAction(i, 'id', $event)\"\r\n [placeholder]=\"t('enterTargetId')\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Dynamic Keys Section -->\r\n @if (\r\n action.actionType === \"navigateToPage\" ||\r\n action.actionType === \"openDialog\"\r\n ) {\r\n <div class=\"mt-4 pt-4 border-t border-surface-200\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"dynamicKeys\") }}</span>\r\n <mt-button\r\n [label]=\"t('addKey')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addDynamicKey(i)\"\r\n />\r\n </div>\r\n @for (\r\n key of action.config?.dynamicKeys ?? [];\r\n track $index;\r\n let keyIndex = $index\r\n ) {\r\n <div class=\"flex items-center gap-2 mb-2\">\r\n <mt-text-field\r\n [label]=\"t('propertyKey')\"\r\n [ngModel]=\"key.propertyKey\"\r\n (ngModelChange)=\"\r\n updateDynamicKey(i, keyIndex, 'propertyKey', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"key.propertyValue\"\r\n (ngModelChange)=\"\r\n updateDynamicKey(i, keyIndex, 'propertyValue', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n (onClick)=\"removeDynamicKey(i, keyIndex)\"\r\n />\r\n </div>\r\n }\r\n @if ((action.config?.dynamicKeys ?? []).length === 0) {\r\n <p class=\"text-xs text-muted-color\">{{ t(\"noDynamicKeys\") }}</p>\r\n }\r\n </div>\r\n\r\n <!-- Static Keys Section -->\r\n <div class=\"mt-4 pt-4 border-t border-surface-200\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"staticKeys\") }}</span>\r\n <mt-button\r\n [label]=\"t('addKey')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addStaticKey(i)\"\r\n />\r\n </div>\r\n @for (\r\n key of action.config?.staticKeys ?? [];\r\n track $index;\r\n let keyIndex = $index\r\n ) {\r\n <div class=\"flex items-center gap-2 mb-2\">\r\n <mt-text-field\r\n [label]=\"t('propertyKey')\"\r\n [ngModel]=\"key.propertyKey\"\r\n (ngModelChange)=\"\r\n updateStaticKey(i, keyIndex, 'propertyKey', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"key.propertyValue\"\r\n (ngModelChange)=\"\r\n updateStaticKey(i, keyIndex, 'propertyValue', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n (onClick)=\"removeStaticKey(i, keyIndex)\"\r\n />\r\n </div>\r\n }\r\n @if ((action.config?.staticKeys ?? []).length === 0) {\r\n <p class=\"text-xs text-muted-color\">{{ t(\"noStaticKeys\") }}</p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (actions().length === 0) {\r\n <div class=\"text-center py-12 text-muted-color\">\r\n <mt-icon icon=\"editor.cursor-click-01\" class=\"text-4xl mb-3\" />\r\n <p class=\"mb-4\">{{ t(\"noActionsConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addAction')\"\r\n severity=\"secondary\"\r\n (onClick)=\"addAction()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n\r\n <!-- Actions Help Card -->\r\n <mt-card [title]=\"t('actionsHelp')\">\r\n <div class=\"text-sm text-muted-color space-y-2\">\r\n <p>\r\n <strong>{{ t(\"openDialog\") }}:</strong> {{ t(\"openDialogDesc\") }}\r\n </p>\r\n <p>\r\n <strong>{{ t(\"navigate\") }}:</strong> {{ t(\"navigateDesc\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "directive", type: Tooltip$1, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6775
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ActionsSettings, isStandalone: true, selector: "mt-actions-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clientConfigChange: "clientConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('actions')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addAction()\"\r\n [pTooltip]=\"t('addAction')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Actions List -->\r\n @for (\r\n action of actions();\r\n track $index;\r\n let i = $index;\r\n let first = $first;\r\n let last = $last\r\n ) {\r\n <div\r\n class=\"p-4 bg-surface-50 rounded-lg border border-surface-200 hover:border-surface-300 transition-all\"\r\n >\r\n <!-- Action Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"w-6 h-6 flex items-center justify-center bg-primary-100 text-primary-600 rounded-full text-sm font-medium\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <span class=\"font-medium text-sm\">\r\n {{ getActionTypeLabel(action.actionType) }}\r\n </span>\r\n <span class=\"text-xs text-muted-color\">\r\n ({{ getTriggerLabel(action.type) }})\r\n </span>\r\n </div>\r\n <div class=\"flex items-center gap-1\">\r\n <!-- Move Up -->\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"first\"\r\n (onClick)=\"moveActionUp(i)\"\r\n [pTooltip]=\"t('moveUp')\"\r\n />\r\n <!-- Move Down -->\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"last\"\r\n (onClick)=\"moveActionDown(i)\"\r\n [pTooltip]=\"t('moveDown')\"\r\n />\r\n <!-- Duplicate -->\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"duplicateAction(i)\"\r\n [pTooltip]=\"t('duplicate')\"\r\n />\r\n <!-- Remove -->\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeAction(i)\"\r\n [pTooltip]=\"t('remove')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Action Configuration -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n <!-- Trigger Type -->\r\n <mt-select-field\r\n [label]=\"t('trigger')\"\r\n [ngModel]=\"action.type\"\r\n (ngModelChange)=\"updateAction(i, 'type', $event)\"\r\n [options]=\"triggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <!-- Action Type -->\r\n <mt-select-field\r\n [label]=\"t('actionType')\"\r\n [ngModel]=\"action.actionType\"\r\n (ngModelChange)=\"updateAction(i, 'actionType', $event)\"\r\n [options]=\"actionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <!-- Target ID (for dialog/navigation) -->\r\n @if (\r\n action.actionType === \"openDialog\" ||\r\n action.actionType === \"navigateToPage\"\r\n ) {\r\n <mt-text-field\r\n [label]=\"t('targetId')\"\r\n [ngModel]=\"action.id || ''\"\r\n (ngModelChange)=\"updateAction(i, 'id', $event)\"\r\n [placeholder]=\"t('enterTargetId')\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Dynamic Keys Section -->\r\n @if (\r\n action.actionType === \"navigateToPage\" ||\r\n action.actionType === \"openDialog\"\r\n ) {\r\n <div class=\"mt-4 pt-4 border-t border-surface-200\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"dynamicKeys\") }}</span>\r\n <mt-button\r\n [label]=\"t('addKey')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addDynamicKey(i)\"\r\n />\r\n </div>\r\n @for (\r\n key of action.config?.dynamicKeys ?? [];\r\n track $index;\r\n let keyIndex = $index\r\n ) {\r\n <div class=\"flex items-center gap-2 mb-2\">\r\n <mt-text-field\r\n [label]=\"t('propertyKey')\"\r\n [ngModel]=\"key.propertyKey\"\r\n (ngModelChange)=\"\r\n updateDynamicKey(i, keyIndex, 'propertyKey', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"key.propertyValue\"\r\n (ngModelChange)=\"\r\n updateDynamicKey(i, keyIndex, 'propertyValue', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n (onClick)=\"removeDynamicKey(i, keyIndex)\"\r\n />\r\n </div>\r\n }\r\n @if ((action.config?.dynamicKeys ?? []).length === 0) {\r\n <p class=\"text-xs text-muted-color\">{{ t(\"noDynamicKeys\") }}</p>\r\n }\r\n </div>\r\n\r\n <!-- Static Keys Section -->\r\n <div class=\"mt-4 pt-4 border-t border-surface-200\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"staticKeys\") }}</span>\r\n <mt-button\r\n [label]=\"t('addKey')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addStaticKey(i)\"\r\n />\r\n </div>\r\n @for (\r\n key of action.config?.staticKeys ?? [];\r\n track $index;\r\n let keyIndex = $index\r\n ) {\r\n <div class=\"flex items-center gap-2 mb-2\">\r\n <mt-text-field\r\n [label]=\"t('propertyKey')\"\r\n [ngModel]=\"key.propertyKey\"\r\n (ngModelChange)=\"\r\n updateStaticKey(i, keyIndex, 'propertyKey', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"key.propertyValue\"\r\n (ngModelChange)=\"\r\n updateStaticKey(i, keyIndex, 'propertyValue', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n (onClick)=\"removeStaticKey(i, keyIndex)\"\r\n />\r\n </div>\r\n }\r\n @if ((action.config?.staticKeys ?? []).length === 0) {\r\n <p class=\"text-xs text-muted-color\">{{ t(\"noStaticKeys\") }}</p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (actions().length === 0) {\r\n <div class=\"text-center py-12 text-muted-color\">\r\n <mt-icon icon=\"editor.cursor-click-01\" class=\"text-4xl mb-3\" />\r\n <p class=\"mb-4\">{{ t(\"noActionsConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addAction')\"\r\n severity=\"secondary\"\r\n (onClick)=\"addAction()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n\r\n <!-- Actions Help Card -->\r\n <mt-card [title]=\"t('actionsHelp')\">\r\n <div class=\"text-sm text-muted-color space-y-2\">\r\n <p>\r\n <strong>{{ t(\"openDialog\") }}:</strong> {{ t(\"openDialogDesc\") }}\r\n </p>\r\n <p>\r\n <strong>{{ t(\"navigate\") }}:</strong> {{ t(\"navigateDesc\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6781
6776
  }
6782
6777
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ActionsSettings, decorators: [{
6783
6778
  type: Component,
6784
6779
  args: [{ selector: 'mt-actions-settings', standalone: true, imports: [
6785
6780
  FormsModule,
6786
6781
  TranslocoDirective,
6787
- Tooltip$1,
6782
+ Tooltip,
6788
6783
  Button,
6789
6784
  TextField,
6790
6785
  SelectField,
6791
- ToggleField,
6792
6786
  Card,
6793
6787
  Icon,
6794
6788
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('actions')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addAction()\"\r\n [pTooltip]=\"t('addAction')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Actions List -->\r\n @for (\r\n action of actions();\r\n track $index;\r\n let i = $index;\r\n let first = $first;\r\n let last = $last\r\n ) {\r\n <div\r\n class=\"p-4 bg-surface-50 rounded-lg border border-surface-200 hover:border-surface-300 transition-all\"\r\n >\r\n <!-- Action Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"w-6 h-6 flex items-center justify-center bg-primary-100 text-primary-600 rounded-full text-sm font-medium\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <span class=\"font-medium text-sm\">\r\n {{ getActionTypeLabel(action.actionType) }}\r\n </span>\r\n <span class=\"text-xs text-muted-color\">\r\n ({{ getTriggerLabel(action.type) }})\r\n </span>\r\n </div>\r\n <div class=\"flex items-center gap-1\">\r\n <!-- Move Up -->\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"first\"\r\n (onClick)=\"moveActionUp(i)\"\r\n [pTooltip]=\"t('moveUp')\"\r\n />\r\n <!-- Move Down -->\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"last\"\r\n (onClick)=\"moveActionDown(i)\"\r\n [pTooltip]=\"t('moveDown')\"\r\n />\r\n <!-- Duplicate -->\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"duplicateAction(i)\"\r\n [pTooltip]=\"t('duplicate')\"\r\n />\r\n <!-- Remove -->\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeAction(i)\"\r\n [pTooltip]=\"t('remove')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Action Configuration -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n <!-- Trigger Type -->\r\n <mt-select-field\r\n [label]=\"t('trigger')\"\r\n [ngModel]=\"action.type\"\r\n (ngModelChange)=\"updateAction(i, 'type', $event)\"\r\n [options]=\"triggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <!-- Action Type -->\r\n <mt-select-field\r\n [label]=\"t('actionType')\"\r\n [ngModel]=\"action.actionType\"\r\n (ngModelChange)=\"updateAction(i, 'actionType', $event)\"\r\n [options]=\"actionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <!-- Target ID (for dialog/navigation) -->\r\n @if (\r\n action.actionType === \"openDialog\" ||\r\n action.actionType === \"navigateToPage\"\r\n ) {\r\n <mt-text-field\r\n [label]=\"t('targetId')\"\r\n [ngModel]=\"action.id || ''\"\r\n (ngModelChange)=\"updateAction(i, 'id', $event)\"\r\n [placeholder]=\"t('enterTargetId')\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Dynamic Keys Section -->\r\n @if (\r\n action.actionType === \"navigateToPage\" ||\r\n action.actionType === \"openDialog\"\r\n ) {\r\n <div class=\"mt-4 pt-4 border-t border-surface-200\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"dynamicKeys\") }}</span>\r\n <mt-button\r\n [label]=\"t('addKey')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addDynamicKey(i)\"\r\n />\r\n </div>\r\n @for (\r\n key of action.config?.dynamicKeys ?? [];\r\n track $index;\r\n let keyIndex = $index\r\n ) {\r\n <div class=\"flex items-center gap-2 mb-2\">\r\n <mt-text-field\r\n [label]=\"t('propertyKey')\"\r\n [ngModel]=\"key.propertyKey\"\r\n (ngModelChange)=\"\r\n updateDynamicKey(i, keyIndex, 'propertyKey', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"key.propertyValue\"\r\n (ngModelChange)=\"\r\n updateDynamicKey(i, keyIndex, 'propertyValue', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n (onClick)=\"removeDynamicKey(i, keyIndex)\"\r\n />\r\n </div>\r\n }\r\n @if ((action.config?.dynamicKeys ?? []).length === 0) {\r\n <p class=\"text-xs text-muted-color\">{{ t(\"noDynamicKeys\") }}</p>\r\n }\r\n </div>\r\n\r\n <!-- Static Keys Section -->\r\n <div class=\"mt-4 pt-4 border-t border-surface-200\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"staticKeys\") }}</span>\r\n <mt-button\r\n [label]=\"t('addKey')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addStaticKey(i)\"\r\n />\r\n </div>\r\n @for (\r\n key of action.config?.staticKeys ?? [];\r\n track $index;\r\n let keyIndex = $index\r\n ) {\r\n <div class=\"flex items-center gap-2 mb-2\">\r\n <mt-text-field\r\n [label]=\"t('propertyKey')\"\r\n [ngModel]=\"key.propertyKey\"\r\n (ngModelChange)=\"\r\n updateStaticKey(i, keyIndex, 'propertyKey', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"key.propertyValue\"\r\n (ngModelChange)=\"\r\n updateStaticKey(i, keyIndex, 'propertyValue', $event)\r\n \"\r\n size=\"small\"\r\n class=\"flex-1\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n (onClick)=\"removeStaticKey(i, keyIndex)\"\r\n />\r\n </div>\r\n }\r\n @if ((action.config?.staticKeys ?? []).length === 0) {\r\n <p class=\"text-xs text-muted-color\">{{ t(\"noStaticKeys\") }}</p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (actions().length === 0) {\r\n <div class=\"text-center py-12 text-muted-color\">\r\n <mt-icon icon=\"editor.cursor-click-01\" class=\"text-4xl mb-3\" />\r\n <p class=\"mb-4\">{{ t(\"noActionsConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addAction')\"\r\n severity=\"secondary\"\r\n (onClick)=\"addAction()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n\r\n <!-- Actions Help Card -->\r\n <mt-card [title]=\"t('actionsHelp')\">\r\n <div class=\"text-sm text-muted-color space-y-2\">\r\n <p>\r\n <strong>{{ t(\"openDialog\") }}:</strong> {{ t(\"openDialogDesc\") }}\r\n </p>\r\n <p>\r\n <strong>{{ t(\"navigate\") }}:</strong> {{ t(\"navigateDesc\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n</div>\r\n" }]
@@ -15231,7 +15225,7 @@ class ActionService {
15231
15225
  const actionData = this.handleActionsConfig(action.config, data, config);
15232
15226
  debugger;
15233
15227
  // Dynamically import DashboardDialogComponent to avoid circular dependency
15234
- import('./masterteam-dashboard-builder-dashboard-dialog.component-CF1Lnyxf.mjs').then(({ DashboardDialogComponent }) => {
15228
+ import('./masterteam-dashboard-builder-dashboard-dialog.component-gcemrzq8.mjs').then(({ DashboardDialogComponent }) => {
15235
15229
  // Open dialog using ModalService
15236
15230
  this.modalService.openModal(DashboardDialogComponent, 'dialog', {
15237
15231
  header: config.clientConfig?.title?.['en'] || '',
@@ -15476,7 +15470,7 @@ class CardContentComponent {
15476
15470
  }
15477
15471
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CardContentComponent, decorators: [{
15478
15472
  type: Component,
15479
- args: [{ selector: 'mt-card-content', standalone: true, imports: [CommonModule, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"db-card-content\"\r\n [class.in-group]=\"inGroup()\"\r\n [class.no-header]=\"!showHeaderState()\"\r\n [ngStyle]=\"cardStyles()\"\r\n [style]=\"borderRadiusStyle()\"\r\n>\r\n <!-- Header -->\r\n @if (showHeaderState()) {\r\n <div\r\n class=\"db-card-header\"\r\n [class.clickable]=\"headerClickableState()\"\r\n [class.center-title]=\"headerConfig()?.isHeaderCentered && isNoTopEnd()\"\r\n [ngStyle]=\"headerRowStyles()\"\r\n (click)=\"onHeaderClick()\"\r\n >\r\n <div\r\n class=\"db-card-title-section\"\r\n [class.center-mode]=\"headerConfig()?.isHeaderCentered\"\r\n [class.force-full-width]=\"isNoTopEnd()\"\r\n >\r\n @if (headerConfig()?.icon) {\r\n <span\r\n class=\"db-card-icon\"\r\n [style.color]=\"\r\n headerConfig()?.iconColor || styleConfig()?.iconColor || 'inherit'\r\n \"\r\n [style.background-color]=\"styleConfig()?.iconBgColor\"\r\n >\r\n <i [class]=\"headerConfig()?.icon\"></i>\r\n </span>\r\n }\r\n <h3\r\n class=\"db-card-title\"\r\n [style.color]=\"\r\n headerConfig()?.headerColor ||\r\n headerConfig()?.titleColor ||\r\n 'inherit'\r\n \"\r\n [style.font-size]=\"\r\n headerConfig()?.headerFontSize\r\n ? headerConfig()?.headerFontSize + 'px'\r\n : null\r\n \"\r\n [attr.title]=\"title()\"\r\n >\r\n {{ title() }}\r\n </h3>\r\n </div>\r\n\r\n <div class=\"db-card-top-end\">\r\n <ng-content select=\"[topEnd]\"></ng-content>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Body -->\r\n <div\r\n class=\"db-card-body\"\r\n [class.no-top-end]=\"isNoTopEnd()\"\r\n [class.is-chart]=\"isChart()\"\r\n >\r\n <ng-content select=\"[body]\"></ng-content>\r\n </div>\r\n\r\n <!-- Footer (optional) -->\r\n <div class=\"db-card-footer\">\r\n <ng-content select=\"[footer]\"></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".db-card-content{display:flex;flex-direction:column;height:100%;background:#fff;border-radius:.5rem;box-shadow:0 1px 3px #0000001a;overflow:hidden}.db-card-content.in-group{box-shadow:none;border-radius:0}.db-card-content.no-header .db-card-body{padding-top:1rem}.db-card-header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid #f0f0f0;min-height:3rem}.db-card-header.clickable{cursor:pointer;transition:background-color .15s ease}.db-card-header.clickable:hover{background-color:#f9f9f9}.db-card-title-section{display:flex;align-items:center;gap:.5rem;flex:1;min-width:0}.db-card-title-section.center-mode{justify-content:center}.db-card-title-section.force-full-width{width:100%}.db-card-header.center-title{justify-content:center}.db-card-icon{font-size:1.25rem;flex-shrink:0}.db-card-title{margin:0;font-size:.95rem;font-weight:600;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.db-card-top-end{display:flex;align-items:center;gap:.5rem;flex-shrink:0;max-width:45%}.db-card-body{flex:1;padding:.75rem 1rem;overflow:auto;min-height:0}.db-card-body.is-chart{overflow-y:hidden}.db-card-body.no-top-end{padding-top:1rem}.db-card-footer:empty{display:none}.db-card-footer{padding:.5rem 1rem;border-top:1px solid #f0f0f0}\n"] }]
15473
+ args: [{ selector: 'mt-card-content', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"db-card-content\"\r\n [class.in-group]=\"inGroup()\"\r\n [class.no-header]=\"!showHeaderState()\"\r\n [ngStyle]=\"cardStyles()\"\r\n [style]=\"borderRadiusStyle()\"\r\n>\r\n <!-- Header -->\r\n @if (showHeaderState()) {\r\n <div\r\n class=\"db-card-header\"\r\n [class.clickable]=\"headerClickableState()\"\r\n [class.center-title]=\"headerConfig()?.isHeaderCentered && isNoTopEnd()\"\r\n [ngStyle]=\"headerRowStyles()\"\r\n (click)=\"onHeaderClick()\"\r\n >\r\n <div\r\n class=\"db-card-title-section\"\r\n [class.center-mode]=\"headerConfig()?.isHeaderCentered\"\r\n [class.force-full-width]=\"isNoTopEnd()\"\r\n >\r\n @if (headerConfig()?.icon) {\r\n <span\r\n class=\"db-card-icon\"\r\n [style.color]=\"\r\n headerConfig()?.iconColor || styleConfig()?.iconColor || 'inherit'\r\n \"\r\n [style.background-color]=\"styleConfig()?.iconBgColor\"\r\n >\r\n <i [class]=\"headerConfig()?.icon\"></i>\r\n </span>\r\n }\r\n <h3\r\n class=\"db-card-title\"\r\n [style.color]=\"\r\n headerConfig()?.headerColor ||\r\n headerConfig()?.titleColor ||\r\n 'inherit'\r\n \"\r\n [style.font-size]=\"\r\n headerConfig()?.headerFontSize\r\n ? headerConfig()?.headerFontSize + 'px'\r\n : null\r\n \"\r\n [attr.title]=\"title()\"\r\n >\r\n {{ title() }}\r\n </h3>\r\n </div>\r\n\r\n <div class=\"db-card-top-end\">\r\n <ng-content select=\"[topEnd]\"></ng-content>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Body -->\r\n <div\r\n class=\"db-card-body\"\r\n [class.no-top-end]=\"isNoTopEnd()\"\r\n [class.is-chart]=\"isChart()\"\r\n >\r\n <ng-content select=\"[body]\"></ng-content>\r\n </div>\r\n\r\n <!-- Footer (optional) -->\r\n <div class=\"db-card-footer\">\r\n <ng-content select=\"[footer]\"></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".db-card-content{display:flex;flex-direction:column;height:100%;background:#fff;border-radius:.5rem;box-shadow:0 1px 3px #0000001a;overflow:hidden}.db-card-content.in-group{box-shadow:none;border-radius:0}.db-card-content.no-header .db-card-body{padding-top:1rem}.db-card-header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid #f0f0f0;min-height:3rem}.db-card-header.clickable{cursor:pointer;transition:background-color .15s ease}.db-card-header.clickable:hover{background-color:#f9f9f9}.db-card-title-section{display:flex;align-items:center;gap:.5rem;flex:1;min-width:0}.db-card-title-section.center-mode{justify-content:center}.db-card-title-section.force-full-width{width:100%}.db-card-header.center-title{justify-content:center}.db-card-icon{font-size:1.25rem;flex-shrink:0}.db-card-title{margin:0;font-size:.95rem;font-weight:600;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.db-card-top-end{display:flex;align-items:center;gap:.5rem;flex-shrink:0;max-width:45%}.db-card-body{flex:1;padding:.75rem 1rem;overflow:auto;min-height:0}.db-card-body.is-chart{overflow-y:hidden}.db-card-body.no-top-end{padding-top:1rem}.db-card-footer:empty{display:none}.db-card-footer{padding:.5rem 1rem;border-top:1px solid #f0f0f0}\n"] }]
15480
15474
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], inGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "inGroup", required: false }] }], headerConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerConfig", required: false }] }], styleConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleConfig", required: false }] }], cardStyleConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardStyleConfig", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], headerClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerClickable", required: false }] }], isNoTopEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "isNoTopEnd", required: false }] }], isChart: [{ type: i0.Input, args: [{ isSignal: true, alias: "isChart", required: false }] }], headerClick: [{ type: i0.Output, args: ["headerClick"] }] } });
15481
15475
 
15482
15476
  /**
@@ -16326,11 +16320,11 @@ class CardInfoComponent {
16326
16320
  <i class="pi pi-info-circle"></i>
16327
16321
  </span>
16328
16322
  }
16329
- `, isInline: true, styles: [".card-info-icon{display:inline-flex;align-items:center;justify-content:center;cursor:help;color:#666;font-size:1rem;transition:color .15s ease}.card-info-icon:hover{color:#333}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16323
+ `, isInline: true, styles: [".card-info-icon{display:inline-flex;align-items:center;justify-content:center;cursor:help;color:#666;font-size:1rem;transition:color .15s ease}.card-info-icon:hover{color:#333}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: Tooltip$1, selector: "[mtTooltip]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16330
16324
  }
16331
16325
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CardInfoComponent, decorators: [{
16332
16326
  type: Component,
16333
- args: [{ selector: 'mt-card-info', standalone: true, imports: [CommonModule, Tooltip], template: `
16327
+ args: [{ selector: 'mt-card-info', standalone: true, imports: [CommonModule, Tooltip$1], template: `
16334
16328
  @if (showInfo()) {
16335
16329
  <span
16336
16330
  class="card-info-icon"
@@ -17039,7 +17033,7 @@ class EntityInfoComponent {
17039
17033
  }
17040
17034
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityInfoComponent, decorators: [{
17041
17035
  type: Component,
17042
- args: [{ selector: 'mt-entity-info', standalone: true, imports: [CommonModule, TranslocoDirective, DecimalPipe, DatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"entity-info-wrapper w-full\" *transloco=\"let t; prefix: 'dashboard'\">\r\n @switch (viewTypeLower()) {\r\n <!-- Text Types -->\r\n @case (\"text\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"float\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"longtext\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"title\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"phasegate\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Number -->\r\n @case (\"number\") {\r\n <ng-container *ngTemplateOutlet=\"numberTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Date Types -->\r\n @case (\"date\") {\r\n <ng-container *ngTemplateOutlet=\"dateTemplate\"></ng-container>\r\n }\r\n @case (\"datetime\") {\r\n <ng-container *ngTemplateOutlet=\"dateTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Currency -->\r\n @case (\"currency\") {\r\n <ng-container *ngTemplateOutlet=\"currencyTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Time -->\r\n @case (\"time\") {\r\n <ng-container *ngTemplateOutlet=\"timeTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Lookup -->\r\n @case (\"lookup\") {\r\n <ng-container *ngTemplateOutlet=\"lookupTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Checkbox -->\r\n @case (\"checkbox\") {\r\n <ng-container *ngTemplateOutlet=\"checkboxTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Status -->\r\n @case (\"status\") {\r\n <ng-container *ngTemplateOutlet=\"statusTemplate\"></ng-container>\r\n }\r\n @case (\"request_status\") {\r\n <ng-container *ngTemplateOutlet=\"statusTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Percentage -->\r\n @case (\"percentage\") {\r\n <ng-container *ngTemplateOutlet=\"percentageTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Slider -->\r\n @case (\"slider\") {\r\n <ng-container *ngTemplateOutlet=\"sliderTemplate\"></ng-container>\r\n }\r\n\r\n <!-- User -->\r\n @case (\"user\") {\r\n <ng-container *ngTemplateOutlet=\"userTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Multi-select lookup -->\r\n @case (\"lookupmultiselect\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"lookupMultiselectTemplate\"\r\n ></ng-container>\r\n }\r\n\r\n <!-- Multi user -->\r\n @case (\"multiuser\") {\r\n <ng-container *ngTemplateOutlet=\"multiUserTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Dynamic List -->\r\n @case (\"dynamiclist\") {\r\n <ng-container *ngTemplateOutlet=\"dynamicListTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Location -->\r\n @case (\"location\") {\r\n <ng-container *ngTemplateOutlet=\"locationTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Default: treat as text -->\r\n @default {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- Text Template -->\r\n<ng-template #textTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div\r\n class=\"font-semibold\"\r\n [class.text-ellipsis]=\"limitWords()\"\r\n [class.overflow-hidden]=\"limitWords()\"\r\n [class.whitespace-nowrap]=\"limitWords()\"\r\n [style.max-width]=\"limitWords() ? '200px' : 'auto'\"\r\n [title]=\"textValue()\"\r\n >\r\n {{ textValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Number Template -->\r\n<ng-template #numberTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ numericValue() !== null ? (numericValue() | number) : \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Date Template -->\r\n<ng-template #dateTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ dateDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Currency Template -->\r\n<ng-template #currencyTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ currencyDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Time Template -->\r\n<ng-template #timeTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ timeDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Lookup Template -->\r\n<ng-template #lookupTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (lookupName()) {\r\n <span class=\"flex items-center gap-1\" [style.color]=\"lookupColor()\">\r\n @if (displayType() === \"entity\" && lookupColor()) {\r\n <span\r\n class=\"w-2 h-2 rounded-full inline-block\"\r\n [style.backgroundColor]=\"lookupColor()\"\r\n ></span>\r\n }\r\n {{ lookupName() }}\r\n </span>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Checkbox Template -->\r\n<ng-template #checkboxTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center\">\r\n <i\r\n [class]=\"\r\n checkboxValue()\r\n ? 'pi pi-check-square text-primary'\r\n : 'pi pi-stop text-muted-color'\r\n \"\r\n ></i>\r\n <span class=\"ml-2\">{{ checkboxValue() ? \"Yes\" : \"No\" }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Status Template -->\r\n<ng-template #statusTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center gap-2\">\r\n @if (statusColor()) {\r\n <span\r\n class=\"w-2.5 h-2.5 rounded-full flex-shrink-0\"\r\n [style.backgroundColor]=\"statusColor()\"\r\n ></span>\r\n }\r\n <span [style.color]=\"statusColor()\">\r\n {{ statusName() || \"__\" }}\r\n </span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Percentage Template -->\r\n<ng-template #percentageTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center gap-2\">\r\n @if (\r\n displayType() !== \"inTable\" ||\r\n extraInfoData()?.showPercentageAsProgressBar\r\n ) {\r\n <div\r\n class=\"flex-1 h-2 bg-surface-200 rounded-full overflow-hidden max-w-24\"\r\n >\r\n <div\r\n class=\"h-full rounded-full transition-all\"\r\n [style.width.%]=\"percentageValue() || 0\"\r\n [style.backgroundColor]=\"percentageColor() || 'var(--primary-color)'\"\r\n ></div>\r\n </div>\r\n }\r\n @if (\r\n extraInfoData()?.showPercentageStatus &&\r\n !extraInfoData()?.showPercentageAsProgressBar\r\n ) {\r\n <span\r\n class=\"w-2.5 h-2.5 rounded-full\"\r\n [style.backgroundColor]=\"percentageColor() || '#000'\"\r\n ></span>\r\n }\r\n <span [style.color]=\"percentageColor()\">\r\n {{\r\n percentageValue() !== null\r\n ? (percentageValue() | number: \"1.0-0\") + \"%\"\r\n : \"__\"\r\n }}\r\n </span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Slider Template -->\r\n<ng-template #sliderTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center gap-2\">\r\n <div\r\n class=\"flex-1 h-2 bg-surface-200 rounded-full overflow-hidden max-w-32\"\r\n >\r\n <div\r\n class=\"h-full bg-primary rounded-full transition-all\"\r\n [style.width.%]=\"sliderValue() || 0\"\r\n ></div>\r\n </div>\r\n <span class=\"text-sm\">{{ sliderValue() || 0 }}%</span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- User Template -->\r\n<ng-template #userTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (userData()) {\r\n <div class=\"flex items-center gap-2\">\r\n @if (userData()?.avatar || userData()?.image) {\r\n <img\r\n [src]=\"userData()?.avatar || userData()?.image\"\r\n alt=\"User avatar\"\r\n class=\"w-8 h-8 rounded-full object-cover\"\r\n />\r\n } @else {\r\n <div\r\n class=\"w-8 h-8 rounded-full bg-primary/20 flex items-center justify-center text-primary font-semibold text-sm\"\r\n >\r\n {{ userInitials() }}\r\n </div>\r\n }\r\n <span class=\"font-medium\">{{ userName() }}</span>\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Lookup Multiselect Template -->\r\n<ng-template #lookupMultiselectTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (multiselectValues()?.length) {\r\n <div class=\"flex flex-wrap gap-1\">\r\n @for (item of multiselectValues(); track item.key || $index) {\r\n <span\r\n class=\"px-2 py-0.5 rounded-full text-xs font-medium\"\r\n [style.backgroundColor]=\"(item.details?.color || '#6b7280') + '20'\"\r\n [style.color]=\"item.details?.color || '#6b7280'\"\r\n >\r\n {{ item.name || item.display || item }}\r\n </span>\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Multi User Template -->\r\n<ng-template #multiUserTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (multiUserValues()?.length) {\r\n <div class=\"flex items-center -space-x-2\">\r\n @for (user of multiUserValues().slice(0, 5); track user.id || $index) {\r\n @if (user.avatar || user.image) {\r\n <img\r\n [src]=\"user.avatar || user.image\"\r\n [alt]=\"user.name || user.displayName\"\r\n class=\"w-7 h-7 rounded-full border-2 border-white object-cover\"\r\n />\r\n } @else {\r\n <div\r\n class=\"w-7 h-7 rounded-full border-2 border-white bg-primary/20 flex items-center justify-center text-primary font-semibold text-xs\"\r\n >\r\n {{ getInitials(user.name || user.displayName) }}\r\n </div>\r\n }\r\n }\r\n @if (multiUserValues().length > 5) {\r\n <div\r\n class=\"w-7 h-7 rounded-full border-2 border-white bg-surface-300 flex items-center justify-center text-xs font-medium\"\r\n >\r\n +{{ multiUserValues().length - 5 }}\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Dynamic List Template -->\r\n<ng-template #dynamicListTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (dynamicListValues()?.length) {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (item of dynamicListValues(); track $index) {\r\n <div class=\"text-sm\">\r\n {{ item?.label || item?.name || item }}\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Location Template -->\r\n<ng-template #locationTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ locationDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block}.text-ellipsis{text-overflow:ellipsis}\n"] }]
17036
+ args: [{ selector: 'mt-entity-info', standalone: true, imports: [CommonModule, TranslocoDirective, DecimalPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"entity-info-wrapper w-full\" *transloco=\"let t; prefix: 'dashboard'\">\r\n @switch (viewTypeLower()) {\r\n <!-- Text Types -->\r\n @case (\"text\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"float\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"longtext\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"title\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n @case (\"phasegate\") {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Number -->\r\n @case (\"number\") {\r\n <ng-container *ngTemplateOutlet=\"numberTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Date Types -->\r\n @case (\"date\") {\r\n <ng-container *ngTemplateOutlet=\"dateTemplate\"></ng-container>\r\n }\r\n @case (\"datetime\") {\r\n <ng-container *ngTemplateOutlet=\"dateTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Currency -->\r\n @case (\"currency\") {\r\n <ng-container *ngTemplateOutlet=\"currencyTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Time -->\r\n @case (\"time\") {\r\n <ng-container *ngTemplateOutlet=\"timeTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Lookup -->\r\n @case (\"lookup\") {\r\n <ng-container *ngTemplateOutlet=\"lookupTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Checkbox -->\r\n @case (\"checkbox\") {\r\n <ng-container *ngTemplateOutlet=\"checkboxTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Status -->\r\n @case (\"status\") {\r\n <ng-container *ngTemplateOutlet=\"statusTemplate\"></ng-container>\r\n }\r\n @case (\"request_status\") {\r\n <ng-container *ngTemplateOutlet=\"statusTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Percentage -->\r\n @case (\"percentage\") {\r\n <ng-container *ngTemplateOutlet=\"percentageTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Slider -->\r\n @case (\"slider\") {\r\n <ng-container *ngTemplateOutlet=\"sliderTemplate\"></ng-container>\r\n }\r\n\r\n <!-- User -->\r\n @case (\"user\") {\r\n <ng-container *ngTemplateOutlet=\"userTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Multi-select lookup -->\r\n @case (\"lookupmultiselect\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"lookupMultiselectTemplate\"\r\n ></ng-container>\r\n }\r\n\r\n <!-- Multi user -->\r\n @case (\"multiuser\") {\r\n <ng-container *ngTemplateOutlet=\"multiUserTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Dynamic List -->\r\n @case (\"dynamiclist\") {\r\n <ng-container *ngTemplateOutlet=\"dynamicListTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Location -->\r\n @case (\"location\") {\r\n <ng-container *ngTemplateOutlet=\"locationTemplate\"></ng-container>\r\n }\r\n\r\n <!-- Default: treat as text -->\r\n @default {\r\n <ng-container *ngTemplateOutlet=\"textTemplate\"></ng-container>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- Text Template -->\r\n<ng-template #textTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div\r\n class=\"font-semibold\"\r\n [class.text-ellipsis]=\"limitWords()\"\r\n [class.overflow-hidden]=\"limitWords()\"\r\n [class.whitespace-nowrap]=\"limitWords()\"\r\n [style.max-width]=\"limitWords() ? '200px' : 'auto'\"\r\n [title]=\"textValue()\"\r\n >\r\n {{ textValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Number Template -->\r\n<ng-template #numberTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ numericValue() !== null ? (numericValue() | number) : \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Date Template -->\r\n<ng-template #dateTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ dateDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Currency Template -->\r\n<ng-template #currencyTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ currencyDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Time Template -->\r\n<ng-template #timeTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ timeDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Lookup Template -->\r\n<ng-template #lookupTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (lookupName()) {\r\n <span class=\"flex items-center gap-1\" [style.color]=\"lookupColor()\">\r\n @if (displayType() === \"entity\" && lookupColor()) {\r\n <span\r\n class=\"w-2 h-2 rounded-full inline-block\"\r\n [style.backgroundColor]=\"lookupColor()\"\r\n ></span>\r\n }\r\n {{ lookupName() }}\r\n </span>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Checkbox Template -->\r\n<ng-template #checkboxTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center\">\r\n <i\r\n [class]=\"\r\n checkboxValue()\r\n ? 'pi pi-check-square text-primary'\r\n : 'pi pi-stop text-muted-color'\r\n \"\r\n ></i>\r\n <span class=\"ml-2\">{{ checkboxValue() ? \"Yes\" : \"No\" }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Status Template -->\r\n<ng-template #statusTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center gap-2\">\r\n @if (statusColor()) {\r\n <span\r\n class=\"w-2.5 h-2.5 rounded-full flex-shrink-0\"\r\n [style.backgroundColor]=\"statusColor()\"\r\n ></span>\r\n }\r\n <span [style.color]=\"statusColor()\">\r\n {{ statusName() || \"__\" }}\r\n </span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Percentage Template -->\r\n<ng-template #percentageTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center gap-2\">\r\n @if (\r\n displayType() !== \"inTable\" ||\r\n extraInfoData()?.showPercentageAsProgressBar\r\n ) {\r\n <div\r\n class=\"flex-1 h-2 bg-surface-200 rounded-full overflow-hidden max-w-24\"\r\n >\r\n <div\r\n class=\"h-full rounded-full transition-all\"\r\n [style.width.%]=\"percentageValue() || 0\"\r\n [style.backgroundColor]=\"percentageColor() || 'var(--primary-color)'\"\r\n ></div>\r\n </div>\r\n }\r\n @if (\r\n extraInfoData()?.showPercentageStatus &&\r\n !extraInfoData()?.showPercentageAsProgressBar\r\n ) {\r\n <span\r\n class=\"w-2.5 h-2.5 rounded-full\"\r\n [style.backgroundColor]=\"percentageColor() || '#000'\"\r\n ></span>\r\n }\r\n <span [style.color]=\"percentageColor()\">\r\n {{\r\n percentageValue() !== null\r\n ? (percentageValue() | number: \"1.0-0\") + \"%\"\r\n : \"__\"\r\n }}\r\n </span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Slider Template -->\r\n<ng-template #sliderTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"flex items-center gap-2\">\r\n <div\r\n class=\"flex-1 h-2 bg-surface-200 rounded-full overflow-hidden max-w-32\"\r\n >\r\n <div\r\n class=\"h-full bg-primary rounded-full transition-all\"\r\n [style.width.%]=\"sliderValue() || 0\"\r\n ></div>\r\n </div>\r\n <span class=\"text-sm\">{{ sliderValue() || 0 }}%</span>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- User Template -->\r\n<ng-template #userTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (userData()) {\r\n <div class=\"flex items-center gap-2\">\r\n @if (userData()?.avatar || userData()?.image) {\r\n <img\r\n [src]=\"userData()?.avatar || userData()?.image\"\r\n alt=\"User avatar\"\r\n class=\"w-8 h-8 rounded-full object-cover\"\r\n />\r\n } @else {\r\n <div\r\n class=\"w-8 h-8 rounded-full bg-primary/20 flex items-center justify-center text-primary font-semibold text-sm\"\r\n >\r\n {{ userInitials() }}\r\n </div>\r\n }\r\n <span class=\"font-medium\">{{ userName() }}</span>\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Lookup Multiselect Template -->\r\n<ng-template #lookupMultiselectTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (multiselectValues()?.length) {\r\n <div class=\"flex flex-wrap gap-1\">\r\n @for (item of multiselectValues(); track item.key || $index) {\r\n <span\r\n class=\"px-2 py-0.5 rounded-full text-xs font-medium\"\r\n [style.backgroundColor]=\"(item.details?.color || '#6b7280') + '20'\"\r\n [style.color]=\"item.details?.color || '#6b7280'\"\r\n >\r\n {{ item.name || item.display || item }}\r\n </span>\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Multi User Template -->\r\n<ng-template #multiUserTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (multiUserValues()?.length) {\r\n <div class=\"flex items-center -space-x-2\">\r\n @for (user of multiUserValues().slice(0, 5); track user.id || $index) {\r\n @if (user.avatar || user.image) {\r\n <img\r\n [src]=\"user.avatar || user.image\"\r\n [alt]=\"user.name || user.displayName\"\r\n class=\"w-7 h-7 rounded-full border-2 border-white object-cover\"\r\n />\r\n } @else {\r\n <div\r\n class=\"w-7 h-7 rounded-full border-2 border-white bg-primary/20 flex items-center justify-center text-primary font-semibold text-xs\"\r\n >\r\n {{ getInitials(user.name || user.displayName) }}\r\n </div>\r\n }\r\n }\r\n @if (multiUserValues().length > 5) {\r\n <div\r\n class=\"w-7 h-7 rounded-full border-2 border-white bg-surface-300 flex items-center justify-center text-xs font-medium\"\r\n >\r\n +{{ multiUserValues().length - 5 }}\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Dynamic List Template -->\r\n<ng-template #dynamicListTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n @if (dynamicListValues()?.length) {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (item of dynamicListValues(); track $index) {\r\n <div class=\"text-sm\">\r\n {{ item?.label || item?.name || item }}\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"font-semibold\">__</span>\r\n }\r\n</ng-template>\r\n\r\n<!-- Location Template -->\r\n<ng-template #locationTemplate>\r\n @if (displayType() === \"entity\") {\r\n <div class=\"text-muted-color text-sm font-semibold mb-1\">\r\n {{ data()?.label }}\r\n </div>\r\n }\r\n <div class=\"font-semibold\">\r\n {{ locationDisplayValue() || \"__\" }}\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block}.text-ellipsis{text-overflow:ellipsis}\n"] }]
17043
17037
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], displayType: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayType", required: false }] }], extraInfoData: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraInfoData", required: false }] }], limitWords: [{ type: i0.Input, args: [{ isSignal: true, alias: "limitWords", required: false }] }], customClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "customClass", required: false }] }] } });
17044
17038
 
17045
17039
  /**
@@ -18110,7 +18104,7 @@ class EntityPreviewCardComponent {
18110
18104
  return (this.transloco.getActiveLang() || localStorage.getItem('langCode') || 'en');
18111
18105
  }
18112
18106
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPreviewCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18113
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityPreviewCardComponent, isStandalone: true, selector: "mt-entity-preview-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<mt-card-content\r\n [inGroup]=\"false\"\r\n [headerConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['headerCardConfig']\r\n \"\r\n [styleConfig]=\"\r\n configurationItem()?.clientConfig?.displayConfig?.['StyleConfig']\r\n \"\r\n [cardStyleConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['cardStyleConfig']\r\n \"\r\n [title]=\"title()\"\r\n>\r\n <ng-container body>\r\n <div\r\n class=\"flex flex-wrap flex-1 p-4 pb-5\"\r\n *transloco=\"let t; prefix: 'dashboard'\"\r\n >\r\n @for (item of props(); track item.propInfo.key) {\n @if (!item.config?.hidden) {\n <div\n [style.width]=\"item.config?.width || '100%'\"\n style=\"min-width: 180px\"\n [class.border]=\"item.config?.border?.includes('all')\"\r\n [class.border-t]=\"item.config?.border?.includes('top')\"\r\n [class.border-l]=\"item.config?.border?.includes('left')\"\r\n [class.border-b]=\"item.config?.border?.includes('bottom')\"\n [class.border-r]=\"item.config?.border?.includes('right')\"\n class=\"flex items-center p-2\"\n >\n <mt-entity-preview [data]=\"item.propInfo\" class=\"w-full\">\n </mt-entity-preview>\n </div>\n }\n }\n\r\n @if (props().length === 0) {\r\n <div\r\n class=\"no-data-container w-full flex items-center justify-center py-8 text-muted-color\"\r\n >\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n <span>{{ t(\"noData\") }}</span>\r\n </div>\r\n }\r\n </div>\r\n </ng-container>\r\n</mt-card-content>\r\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: CardContentComponent, selector: "mt-card-content", inputs: ["title", "inGroup", "headerConfig", "styleConfig", "cardStyleConfig", "showHeader", "headerClickable", "isNoTopEnd", "isChart"], outputs: ["headerClick"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18107
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityPreviewCardComponent, isStandalone: true, selector: "mt-entity-preview-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<mt-card-content\r\n [inGroup]=\"false\"\r\n [headerConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['headerCardConfig']\r\n \"\r\n [styleConfig]=\"\r\n configurationItem()?.clientConfig?.displayConfig?.['StyleConfig']\r\n \"\r\n [cardStyleConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['cardStyleConfig']\r\n \"\r\n [title]=\"title()\"\r\n>\r\n <ng-container body>\r\n <div\r\n class=\"flex flex-wrap flex-1 p-4 pb-5\"\r\n *transloco=\"let t; prefix: 'dashboard'\"\r\n >\r\n @for (item of props(); track item.propInfo.key) {\r\n @if (!item.config?.hidden) {\r\n <div\r\n [style.width]=\"item.config?.width || '100%'\"\r\n style=\"min-width: 180px\"\r\n [class.border]=\"item.config?.border?.includes('all')\"\r\n [class.border-t]=\"item.config?.border?.includes('top')\"\r\n [class.border-l]=\"item.config?.border?.includes('left')\"\r\n [class.border-b]=\"item.config?.border?.includes('bottom')\"\r\n [class.border-r]=\"item.config?.border?.includes('right')\"\r\n class=\"flex items-center p-2\"\r\n >\r\n <mt-entity-preview [data]=\"item.propInfo\" class=\"w-full\">\r\n </mt-entity-preview>\r\n </div>\r\n }\r\n }\r\n\r\n @if (props().length === 0) {\r\n <div\r\n class=\"no-data-container w-full flex items-center justify-center py-8 text-muted-color\"\r\n >\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n <span>{{ t(\"noData\") }}</span>\r\n </div>\r\n }\r\n </div>\r\n </ng-container>\r\n</mt-card-content>\r\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: CardContentComponent, selector: "mt-card-content", inputs: ["title", "inGroup", "headerConfig", "styleConfig", "cardStyleConfig", "showHeader", "headerClickable", "isNoTopEnd", "isChart"], outputs: ["headerClick"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18114
18108
  }
18115
18109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPreviewCardComponent, decorators: [{
18116
18110
  type: Component,
@@ -18119,7 +18113,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
18119
18113
  TranslocoDirective,
18120
18114
  CardContentComponent,
18121
18115
  EntityPreview,
18122
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mt-card-content\r\n [inGroup]=\"false\"\r\n [headerConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['headerCardConfig']\r\n \"\r\n [styleConfig]=\"\r\n configurationItem()?.clientConfig?.displayConfig?.['StyleConfig']\r\n \"\r\n [cardStyleConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['cardStyleConfig']\r\n \"\r\n [title]=\"title()\"\r\n>\r\n <ng-container body>\r\n <div\r\n class=\"flex flex-wrap flex-1 p-4 pb-5\"\r\n *transloco=\"let t; prefix: 'dashboard'\"\r\n >\r\n @for (item of props(); track item.propInfo.key) {\n @if (!item.config?.hidden) {\n <div\n [style.width]=\"item.config?.width || '100%'\"\n style=\"min-width: 180px\"\n [class.border]=\"item.config?.border?.includes('all')\"\r\n [class.border-t]=\"item.config?.border?.includes('top')\"\r\n [class.border-l]=\"item.config?.border?.includes('left')\"\r\n [class.border-b]=\"item.config?.border?.includes('bottom')\"\n [class.border-r]=\"item.config?.border?.includes('right')\"\n class=\"flex items-center p-2\"\n >\n <mt-entity-preview [data]=\"item.propInfo\" class=\"w-full\">\n </mt-entity-preview>\n </div>\n }\n }\n\r\n @if (props().length === 0) {\r\n <div\r\n class=\"no-data-container w-full flex items-center justify-center py-8 text-muted-color\"\r\n >\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n <span>{{ t(\"noData\") }}</span>\r\n </div>\r\n }\r\n </div>\r\n </ng-container>\r\n</mt-card-content>\r\n", styles: [":host{display:block;height:100%}\n"] }]
18116
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mt-card-content\r\n [inGroup]=\"false\"\r\n [headerConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['headerCardConfig']\r\n \"\r\n [styleConfig]=\"\r\n configurationItem()?.clientConfig?.displayConfig?.['StyleConfig']\r\n \"\r\n [cardStyleConfig]=\"\r\n configurationItem()?.clientConfig?.configAsType?.['cardStyleConfig']\r\n \"\r\n [title]=\"title()\"\r\n>\r\n <ng-container body>\r\n <div\r\n class=\"flex flex-wrap flex-1 p-4 pb-5\"\r\n *transloco=\"let t; prefix: 'dashboard'\"\r\n >\r\n @for (item of props(); track item.propInfo.key) {\r\n @if (!item.config?.hidden) {\r\n <div\r\n [style.width]=\"item.config?.width || '100%'\"\r\n style=\"min-width: 180px\"\r\n [class.border]=\"item.config?.border?.includes('all')\"\r\n [class.border-t]=\"item.config?.border?.includes('top')\"\r\n [class.border-l]=\"item.config?.border?.includes('left')\"\r\n [class.border-b]=\"item.config?.border?.includes('bottom')\"\r\n [class.border-r]=\"item.config?.border?.includes('right')\"\r\n class=\"flex items-center p-2\"\r\n >\r\n <mt-entity-preview [data]=\"item.propInfo\" class=\"w-full\">\r\n </mt-entity-preview>\r\n </div>\r\n }\r\n }\r\n\r\n @if (props().length === 0) {\r\n <div\r\n class=\"no-data-container w-full flex items-center justify-center py-8 text-muted-color\"\r\n >\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n <span>{{ t(\"noData\") }}</span>\r\n </div>\r\n }\r\n </div>\r\n </ng-container>\r\n</mt-card-content>\r\n", styles: [":host{display:block;height:100%}\n"] }]
18123
18117
  }], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }] } });
18124
18118
 
18125
18119
  /**
@@ -18239,11 +18233,16 @@ class LevelCardListComponent {
18239
18233
  this.onAction.emit({ type: 'click', data: card });
18240
18234
  }
18241
18235
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LevelCardListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18242
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: LevelCardListComponent, isStandalone: true, selector: "mt-level-card-list", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null }, hideProperties: { classPropertyName: "hideProperties", publicName: "hideProperties", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<!-- Tabs (only shown if not in group) -->\r\n@if (tabs().length > 0 && !inGroup()) {\r\n <ul class=\"flex border-b\">\r\n @for (tab of tabs(); track $index; let i = $index) {\r\n <li\r\n class=\"cursor-pointer px-4 py-2 transition-colors\"\r\n [class.border-b-2]=\"i === tabSelected()\"\r\n [class.border-primary]=\"i === tabSelected()\"\r\n [class.text-primary]=\"i === tabSelected()\"\r\n [class.text-gray-600]=\"i !== tabSelected()\"\r\n (click)=\"tabSelected.set(i)\"\r\n >\r\n {{ tab[langCode()] }}\r\n </li>\r\n }\r\n </ul>\r\n}\r\n\r\n<!-- Cards Container -->\r\n<div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n>\r\n @for (group of currentTabData(); track $index) {\r\n <div class=\"flex flex-wrap\">\r\n @for (card of group?.data; track card.id) {\r\n <div\r\n class=\"mb-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\r\n [class.p-2]=\"true\"\r\n >\r\n <div\r\n class=\"h-full cursor-pointer rounded-lg bg-white shadow-sm transition-all hover:shadow-md\"\r\n (click)=\"onCardClick(card)\"\r\n >\r\n <!-- Card Header -->\r\n <div\r\n class=\"flex items-center justify-between border-b p-3\"\r\n [style.border-left-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [style.border-left-width]=\"'4px'\"\r\n >\r\n <div class=\"min-w-0 flex-1\">\r\n <h6 class=\"truncate text-sm font-semibold text-gray-800\">\r\n {{ card.name }}\r\n </h6>\r\n </div>\r\n <div class=\"ml-2 flex items-center gap-2\">\r\n @if (card.status?.value?.name) {\r\n <span\r\n class=\"whitespace-nowrap rounded-full px-2 py-0.5 text-xs font-medium text-white\"\r\n [style.background-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [pTooltip]=\"card.status?.value?.details?.description\"\r\n >\r\n {{ card.status?.value?.name }}\r\n </span>\r\n }\r\n @if (card.currentPhase) {\r\n <span\r\n class=\"rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-600\"\r\n >\r\n {{ card.currentPhase }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Card Body - Properties -->\r\n <div class=\"p-3\">\r\n @for (prop of getBodyProps(card); track prop.key) {\r\n <div class=\"mb-2 flex items-start text-sm\">\r\n <span class=\"mr-2 font-medium text-gray-500\">\r\n {{ prop.key }}:\r\n </span>\r\n <span class=\"flex-1 text-gray-700\">\r\n <mt-entity-info\r\n [viewType]=\"prop.viewType\"\r\n [value]=\"prop.value\"\r\n [langCode]=\"langCode()\"\r\n />\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Gallery Mode Images -->\r\n @if (galleryMode() && getAttachments(card).length > 0) {\r\n <div class=\"flex gap-2 overflow-x-auto p-3 pt-0\">\r\n @for (img of getAttachments(card); track $index) {\r\n <img\r\n [src]=\"'api/Uploader/' + img.path\"\r\n alt=\"Attachment\"\r\n class=\"h-16 w-16 flex-shrink-0 rounded object-cover\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Counts Row (issues, risks, milestones) -->\r\n @if (hasCounters(card)) {\r\n <div class=\"flex justify-around border-t p-2 text-xs\">\r\n @if (card.issuesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-red-500\">\r\n {{ card.issuesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">Issues</div>\r\n </div>\r\n }\r\n @if (card.risksCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-orange-500\">\r\n {{ card.risksCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">Risks</div>\r\n </div>\r\n }\r\n @if (card.milestonesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-blue-500\">\r\n {{ card.milestonesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">Milestones</div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".card-col{flex:0 0 100%}@media(min-width:768px){.card-col{flex:0 0 50%}}@media(min-width:1024px){.card-col{flex:0 0 33.333%}}.gallery-card-col{flex:0 0 100%}@media(min-width:640px){.gallery-card-col{flex:0 0 50%}}@media(min-width:1024px){.gallery-card-col{flex:0 0 25%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: EntityInfoComponent, selector: "mt-entity-info", inputs: ["data", "displayType", "extraInfoData", "limitWords", "customClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: LevelCardListComponent, isStandalone: true, selector: "mt-level-card-list", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null }, hideProperties: { classPropertyName: "hideProperties", publicName: "hideProperties", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<!-- Tabs (only shown if not in group) -->\r\n<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n @if (tabs().length > 0 && !inGroup()) {\r\n <ul class=\"flex border-b\">\r\n @for (tab of tabs(); track $index; let i = $index) {\r\n <li\r\n class=\"cursor-pointer px-4 py-2 transition-colors\"\r\n [class.border-b-2]=\"i === tabSelected()\"\r\n [class.border-primary]=\"i === tabSelected()\"\r\n [class.text-primary]=\"i === tabSelected()\"\r\n [class.text-gray-600]=\"i !== tabSelected()\"\r\n (click)=\"tabSelected.set(i)\"\r\n >\r\n {{ tab[langCode()] }}\r\n </li>\r\n }\r\n </ul>\r\n }\r\n\r\n <!-- Cards Container -->\r\n <div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n >\r\n @for (group of currentTabData(); track $index) {\r\n <div class=\"flex flex-wrap\">\r\n @for (card of group?.data; track card.id) {\r\n <div\r\n class=\"mb-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\r\n [class.p-2]=\"true\"\r\n >\r\n <div\r\n class=\"h-full cursor-pointer rounded-lg bg-white shadow-sm transition-all hover:shadow-md\"\r\n (click)=\"onCardClick(card)\"\r\n >\r\n <!-- Card Header -->\r\n <div\r\n class=\"flex items-center justify-between border-b p-3\"\r\n [style.border-left-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [style.border-left-width]=\"'4px'\"\r\n >\r\n <div class=\"min-w-0 flex-1\">\r\n <h6 class=\"truncate text-sm font-semibold text-gray-800\">\r\n {{ card.name }}\r\n </h6>\r\n </div>\r\n <div class=\"ml-2 flex items-center gap-2\">\r\n @if (card.status?.value?.name) {\r\n <span\r\n class=\"whitespace-nowrap rounded-full px-2 py-0.5 text-xs font-medium text-white\"\r\n [style.background-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [pTooltip]=\"card.status?.value?.details?.description\"\r\n >\r\n {{ card.status?.value?.name }}\r\n </span>\r\n }\r\n @if (card.currentPhase) {\r\n <span\r\n class=\"rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-600\"\r\n >\r\n {{ card.currentPhase }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Card Body - Properties -->\r\n <div class=\"p-3\">\r\n @for (prop of getBodyProps(card); track prop.key) {\r\n <div class=\"mb-2 flex items-start text-sm\">\r\n <span class=\"mr-2 font-medium text-gray-500\">\r\n {{ prop.key }}:\r\n </span>\r\n <span class=\"flex-1 text-gray-700\">\r\n <mt-entity-info\r\n [viewType]=\"prop.viewType\"\r\n [value]=\"prop.value\"\r\n [langCode]=\"langCode()\"\r\n />\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Gallery Mode Images -->\r\n @if (galleryMode() && getAttachments(card).length > 0) {\r\n <div class=\"flex gap-2 overflow-x-auto p-3 pt-0\">\r\n @for (img of getAttachments(card); track $index) {\r\n <img\r\n [src]=\"'api/Uploader/' + img.path\"\r\n alt=\"Attachment\"\r\n class=\"h-16 w-16 flex-shrink-0 rounded object-cover\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Counts Row (issues, risks, milestones) -->\r\n @if (hasCounters(card)) {\r\n <div class=\"flex justify-around border-t p-2 text-xs\">\r\n @if (card.issuesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-red-500\">\r\n {{ card.issuesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">{{ t(\"issues\") }}</div>\r\n </div>\r\n }\r\n @if (card.risksCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-orange-500\">\r\n {{ card.risksCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">{{ t(\"risks\") }}</div>\r\n </div>\r\n }\r\n @if (card.milestonesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-blue-500\">\r\n {{ card.milestonesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">{{ t(\"milestones\") }}</div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-container>\r\n", styles: [".card-col{flex:0 0 100%}@media(min-width:768px){.card-col{flex:0 0 50%}}@media(min-width:1024px){.card-col{flex:0 0 33.333%}}.gallery-card-col{flex:0 0 100%}@media(min-width:640px){.gallery-card-col{flex:0 0 50%}}@media(min-width:1024px){.gallery-card-col{flex:0 0 25%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: EntityInfoComponent, selector: "mt-entity-info", inputs: ["data", "displayType", "extraInfoData", "limitWords", "customClass"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18243
18237
  }
18244
18238
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LevelCardListComponent, decorators: [{
18245
18239
  type: Component,
18246
- args: [{ selector: 'mt-level-card-list', standalone: true, imports: [CommonModule, TooltipModule, EntityInfoComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Tabs (only shown if not in group) -->\r\n@if (tabs().length > 0 && !inGroup()) {\r\n <ul class=\"flex border-b\">\r\n @for (tab of tabs(); track $index; let i = $index) {\r\n <li\r\n class=\"cursor-pointer px-4 py-2 transition-colors\"\r\n [class.border-b-2]=\"i === tabSelected()\"\r\n [class.border-primary]=\"i === tabSelected()\"\r\n [class.text-primary]=\"i === tabSelected()\"\r\n [class.text-gray-600]=\"i !== tabSelected()\"\r\n (click)=\"tabSelected.set(i)\"\r\n >\r\n {{ tab[langCode()] }}\r\n </li>\r\n }\r\n </ul>\r\n}\r\n\r\n<!-- Cards Container -->\r\n<div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n>\r\n @for (group of currentTabData(); track $index) {\r\n <div class=\"flex flex-wrap\">\r\n @for (card of group?.data; track card.id) {\r\n <div\r\n class=\"mb-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\r\n [class.p-2]=\"true\"\r\n >\r\n <div\r\n class=\"h-full cursor-pointer rounded-lg bg-white shadow-sm transition-all hover:shadow-md\"\r\n (click)=\"onCardClick(card)\"\r\n >\r\n <!-- Card Header -->\r\n <div\r\n class=\"flex items-center justify-between border-b p-3\"\r\n [style.border-left-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [style.border-left-width]=\"'4px'\"\r\n >\r\n <div class=\"min-w-0 flex-1\">\r\n <h6 class=\"truncate text-sm font-semibold text-gray-800\">\r\n {{ card.name }}\r\n </h6>\r\n </div>\r\n <div class=\"ml-2 flex items-center gap-2\">\r\n @if (card.status?.value?.name) {\r\n <span\r\n class=\"whitespace-nowrap rounded-full px-2 py-0.5 text-xs font-medium text-white\"\r\n [style.background-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [pTooltip]=\"card.status?.value?.details?.description\"\r\n >\r\n {{ card.status?.value?.name }}\r\n </span>\r\n }\r\n @if (card.currentPhase) {\r\n <span\r\n class=\"rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-600\"\r\n >\r\n {{ card.currentPhase }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Card Body - Properties -->\r\n <div class=\"p-3\">\r\n @for (prop of getBodyProps(card); track prop.key) {\r\n <div class=\"mb-2 flex items-start text-sm\">\r\n <span class=\"mr-2 font-medium text-gray-500\">\r\n {{ prop.key }}:\r\n </span>\r\n <span class=\"flex-1 text-gray-700\">\r\n <mt-entity-info\r\n [viewType]=\"prop.viewType\"\r\n [value]=\"prop.value\"\r\n [langCode]=\"langCode()\"\r\n />\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Gallery Mode Images -->\r\n @if (galleryMode() && getAttachments(card).length > 0) {\r\n <div class=\"flex gap-2 overflow-x-auto p-3 pt-0\">\r\n @for (img of getAttachments(card); track $index) {\r\n <img\r\n [src]=\"'api/Uploader/' + img.path\"\r\n alt=\"Attachment\"\r\n class=\"h-16 w-16 flex-shrink-0 rounded object-cover\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Counts Row (issues, risks, milestones) -->\r\n @if (hasCounters(card)) {\r\n <div class=\"flex justify-around border-t p-2 text-xs\">\r\n @if (card.issuesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-red-500\">\r\n {{ card.issuesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">Issues</div>\r\n </div>\r\n }\r\n @if (card.risksCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-orange-500\">\r\n {{ card.risksCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">Risks</div>\r\n </div>\r\n }\r\n @if (card.milestonesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-blue-500\">\r\n {{ card.milestonesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">Milestones</div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".card-col{flex:0 0 100%}@media(min-width:768px){.card-col{flex:0 0 50%}}@media(min-width:1024px){.card-col{flex:0 0 33.333%}}.gallery-card-col{flex:0 0 100%}@media(min-width:640px){.gallery-card-col{flex:0 0 50%}}@media(min-width:1024px){.gallery-card-col{flex:0 0 25%}}\n"] }]
18240
+ args: [{ selector: 'mt-level-card-list', standalone: true, imports: [
18241
+ CommonModule,
18242
+ TooltipModule,
18243
+ EntityInfoComponent,
18244
+ TranslocoDirective,
18245
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Tabs (only shown if not in group) -->\r\n<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n @if (tabs().length > 0 && !inGroup()) {\r\n <ul class=\"flex border-b\">\r\n @for (tab of tabs(); track $index; let i = $index) {\r\n <li\r\n class=\"cursor-pointer px-4 py-2 transition-colors\"\r\n [class.border-b-2]=\"i === tabSelected()\"\r\n [class.border-primary]=\"i === tabSelected()\"\r\n [class.text-primary]=\"i === tabSelected()\"\r\n [class.text-gray-600]=\"i !== tabSelected()\"\r\n (click)=\"tabSelected.set(i)\"\r\n >\r\n {{ tab[langCode()] }}\r\n </li>\r\n }\r\n </ul>\r\n }\r\n\r\n <!-- Cards Container -->\r\n <div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n >\r\n @for (group of currentTabData(); track $index) {\r\n <div class=\"flex flex-wrap\">\r\n @for (card of group?.data; track card.id) {\r\n <div\r\n class=\"mb-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\r\n [class.p-2]=\"true\"\r\n >\r\n <div\r\n class=\"h-full cursor-pointer rounded-lg bg-white shadow-sm transition-all hover:shadow-md\"\r\n (click)=\"onCardClick(card)\"\r\n >\r\n <!-- Card Header -->\r\n <div\r\n class=\"flex items-center justify-between border-b p-3\"\r\n [style.border-left-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [style.border-left-width]=\"'4px'\"\r\n >\r\n <div class=\"min-w-0 flex-1\">\r\n <h6 class=\"truncate text-sm font-semibold text-gray-800\">\r\n {{ card.name }}\r\n </h6>\r\n </div>\r\n <div class=\"ml-2 flex items-center gap-2\">\r\n @if (card.status?.value?.name) {\r\n <span\r\n class=\"whitespace-nowrap rounded-full px-2 py-0.5 text-xs font-medium text-white\"\r\n [style.background-color]=\"\r\n card.status?.value?.details?.color || '#64b735'\r\n \"\r\n [pTooltip]=\"card.status?.value?.details?.description\"\r\n >\r\n {{ card.status?.value?.name }}\r\n </span>\r\n }\r\n @if (card.currentPhase) {\r\n <span\r\n class=\"rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-600\"\r\n >\r\n {{ card.currentPhase }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Card Body - Properties -->\r\n <div class=\"p-3\">\r\n @for (prop of getBodyProps(card); track prop.key) {\r\n <div class=\"mb-2 flex items-start text-sm\">\r\n <span class=\"mr-2 font-medium text-gray-500\">\r\n {{ prop.key }}:\r\n </span>\r\n <span class=\"flex-1 text-gray-700\">\r\n <mt-entity-info\r\n [viewType]=\"prop.viewType\"\r\n [value]=\"prop.value\"\r\n [langCode]=\"langCode()\"\r\n />\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Gallery Mode Images -->\r\n @if (galleryMode() && getAttachments(card).length > 0) {\r\n <div class=\"flex gap-2 overflow-x-auto p-3 pt-0\">\r\n @for (img of getAttachments(card); track $index) {\r\n <img\r\n [src]=\"'api/Uploader/' + img.path\"\r\n alt=\"Attachment\"\r\n class=\"h-16 w-16 flex-shrink-0 rounded object-cover\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Counts Row (issues, risks, milestones) -->\r\n @if (hasCounters(card)) {\r\n <div class=\"flex justify-around border-t p-2 text-xs\">\r\n @if (card.issuesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-red-500\">\r\n {{ card.issuesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">{{ t(\"issues\") }}</div>\r\n </div>\r\n }\r\n @if (card.risksCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-orange-500\">\r\n {{ card.risksCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">{{ t(\"risks\") }}</div>\r\n </div>\r\n }\r\n @if (card.milestonesCounts) {\r\n <div class=\"text-center\">\r\n <div class=\"font-medium text-blue-500\">\r\n {{ card.milestonesCounts.value }}\r\n </div>\r\n <div class=\"text-gray-400\">{{ t(\"milestones\") }}</div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-container>\r\n", styles: [".card-col{flex:0 0 100%}@media(min-width:768px){.card-col{flex:0 0 50%}}@media(min-width:1024px){.card-col{flex:0 0 33.333%}}.gallery-card-col{flex:0 0 100%}@media(min-width:640px){.gallery-card-col{flex:0 0 50%}}@media(min-width:1024px){.gallery-card-col{flex:0 0 25%}}\n"] }]
18247
18246
  }], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }], inGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "inGroup", required: false }] }], hideProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideProperties", required: false }] }], onAction: [{ type: i0.Output, args: ["onAction"] }] } });
18248
18247
 
18249
18248
  class DashboardItem {
@@ -18553,24 +18552,22 @@ class DashboardItem {
18553
18552
  return merged;
18554
18553
  }
18555
18554
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
18556
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardItem, isStandalone: true, selector: "mt-dashboard-item", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartTypeId: { classPropertyName: "chartTypeId", publicName: "chartTypeId", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null }, isDialog: { classPropertyName: "isDialog", publicName: "isDialog", isSignal: true, isRequired: false, transformFunction: null }, queryParams: { classPropertyName: "queryParams", publicName: "queryParams", isSignal: true, isRequired: false, transformFunction: null }, extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: true, isRequired: false, transformFunction: null }, ignoreQueryFilter: { classPropertyName: "ignoreQueryFilter", publicName: "ignoreQueryFilter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionTriggered: "actionTriggered" }, ngImport: i0, template: "@if (isLoading()) {\r\n <mt-skeleton-card [dashboardId]=\"dashboardId()\"></mt-skeleton-card>\r\n} @else if (hasError()) {\r\n <div class=\"flex flex-col items-center justify-center h-full p-4 text-center\">\r\n <mt-icon\r\n icon=\"general.alert-circle\"\r\n class=\"text-4xl text-red-500 mb-2\"\r\n ></mt-icon>\r\n <p class=\"text-red-500 font-medium\">\r\n {{ errorMessage() || \"Error loading data\" }}\r\n </p>\r\n <mt-button\r\n class=\"mt-2\"\r\n [label]=\"'Retry'\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n icon=\"arrow.refresh-cw-01\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n} @else {\r\n @switch (componentName()) {\r\n <!-- Chart Types -->\r\n @case (\"chart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Map Chart -->\r\n @case (\"map\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Background Text -->\r\n @case (\"BackgroundTextChart\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Chart Custom With Card Info -->\r\n @case (\"chartCustomWithCardInfo\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Charts -->\r\n @case (\"listOfcharts\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Cards Statistic -->\r\n @case (\"listOfCardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Cards Statistic (single) -->\r\n @case (\"cardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Header -->\r\n @case (\"header\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Footer (same as header) -->\r\n @case (\"footer\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Label (same as header) -->\r\n @case (\"label\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- List of Level Cards -->\r\n @case (\"listOfLevelCards\") {\r\n <mt-level-card-list\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-level-card-list>\r\n }\r\n\r\n <!-- Table -->\r\n @case (\"table\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Phase Gate Table -->\r\n @case (\"phaseGateTable\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Topbar -->\r\n @case (\"topbar\") {\r\n <!-- Topbar handled at viewer level -->\r\n }\r\n\r\n <!-- Timeline -->\r\n @case (\"timeline\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Timeline Project Dependencies -->\r\n @case (\"timelineProjectDependencies\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Last History Level Card -->\r\n @case (\"lastHistoryLevelCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Entity Preview -->\r\n @case (\"entityPreview\") {\r\n <mt-entity-preview-card [dashboardId]=\"dashboardId()\">\r\n </mt-entity-preview-card>\r\n }\r\n\r\n <!-- Cluster Stacked Chart -->\r\n @case (\"clusterStackedChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List Component S+ Card -->\r\n @case (\"listComponentSplusCard\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Splitter Chart -->\r\n @case (\"splitterChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Repeater (same as header) -->\r\n @case (\"repeater\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Level Cards With Static -->\r\n @case (\"levelCardsWithStatic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Phase Gate Stepper Card -->\r\n @case (\"phaseGateStepperCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Dialog -->\r\n @case (\"dialog\") {\r\n <!-- Dialog handled separately via ModalService -->\r\n }\r\n\r\n <!-- Default: try chart -->\r\n @default {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n }\r\n}\r\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: ChartCardComponent, selector: "mt-chart-card", inputs: ["dashboardId", "inGroup", "isConfigMode"], outputs: ["onAction"] }, { kind: "component", type: TableCardComponent, selector: "mt-table-card", inputs: ["dashboardId", "inGroup"], outputs: ["onAction"] }, { kind: "component", type: ListStatisticCardComponent, selector: "mt-list-statistic-card", inputs: ["dashboardId"] }, { kind: "component", type: HeaderCardComponent, selector: "mt-header-card", inputs: ["dashboardId"], outputs: ["onAction"] }, { kind: "component", type: SkeletonCardComponent, selector: "mt-skeleton-card", inputs: ["dashboardId"] }, { kind: "component", type: EntityPreviewCardComponent, selector: "mt-entity-preview-card", inputs: ["dashboardId"] }, { kind: "component", type: LevelCardListComponent, selector: "mt-level-card-list", inputs: ["dashboardId", "inGroup", "hideProperties"], outputs: ["onAction"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
18555
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardItem, isStandalone: true, selector: "mt-dashboard-item", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartTypeId: { classPropertyName: "chartTypeId", publicName: "chartTypeId", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null }, isDialog: { classPropertyName: "isDialog", publicName: "isDialog", isSignal: true, isRequired: false, transformFunction: null }, queryParams: { classPropertyName: "queryParams", publicName: "queryParams", isSignal: true, isRequired: false, transformFunction: null }, extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: true, isRequired: false, transformFunction: null }, ignoreQueryFilter: { classPropertyName: "ignoreQueryFilter", publicName: "ignoreQueryFilter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionTriggered: "actionTriggered" }, ngImport: i0, template: "@if (isLoading()) {\r\n <mt-skeleton-card [dashboardId]=\"dashboardId()\"></mt-skeleton-card>\r\n} @else if (hasError()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-full p-4 text-center\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n >\r\n <mt-icon\r\n icon=\"general.alert-circle\"\r\n class=\"text-4xl text-red-500 mb-2\"\r\n ></mt-icon>\r\n <p class=\"text-red-500 font-medium\">\r\n {{ errorMessage() || t(\"error-loading-data\") }}\r\n </p>\r\n <mt-button\r\n class=\"mt-2\"\r\n [label]=\"t('retry')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n icon=\"arrow.refresh-cw-01\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n} @else {\r\n @switch (componentName()) {\r\n <!-- Chart Types -->\r\n @case (\"chart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Map Chart -->\r\n @case (\"map\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Background Text -->\r\n @case (\"BackgroundTextChart\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Chart Custom With Card Info -->\r\n @case (\"chartCustomWithCardInfo\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Charts -->\r\n @case (\"listOfcharts\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Cards Statistic -->\r\n @case (\"listOfCardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Cards Statistic (single) -->\r\n @case (\"cardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Header -->\r\n @case (\"header\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Footer (same as header) -->\r\n @case (\"footer\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Label (same as header) -->\r\n @case (\"label\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- List of Level Cards -->\r\n @case (\"listOfLevelCards\") {\r\n <mt-level-card-list\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-level-card-list>\r\n }\r\n\r\n <!-- Table -->\r\n @case (\"table\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Phase Gate Table -->\r\n @case (\"phaseGateTable\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Topbar -->\r\n @case (\"topbar\") {\r\n <!-- Topbar handled at viewer level -->\r\n }\r\n\r\n <!-- Timeline -->\r\n @case (\"timeline\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Timeline Project Dependencies -->\r\n @case (\"timelineProjectDependencies\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Last History Level Card -->\r\n @case (\"lastHistoryLevelCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Entity Preview -->\r\n @case (\"entityPreview\") {\r\n <mt-entity-preview-card [dashboardId]=\"dashboardId()\">\r\n </mt-entity-preview-card>\r\n }\r\n\r\n <!-- Cluster Stacked Chart -->\r\n @case (\"clusterStackedChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List Component S+ Card -->\r\n @case (\"listComponentSplusCard\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Splitter Chart -->\r\n @case (\"splitterChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Repeater (same as header) -->\r\n @case (\"repeater\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Level Cards With Static -->\r\n @case (\"levelCardsWithStatic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Phase Gate Stepper Card -->\r\n @case (\"phaseGateStepperCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Dialog -->\r\n @case (\"dialog\") {\r\n <!-- Dialog handled separately via ModalService -->\r\n }\r\n\r\n <!-- Default: try chart -->\r\n @default {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n }\r\n}\r\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: ChartCardComponent, selector: "mt-chart-card", inputs: ["dashboardId", "inGroup", "isConfigMode"], outputs: ["onAction"] }, { kind: "component", type: TableCardComponent, selector: "mt-table-card", inputs: ["dashboardId", "inGroup"], outputs: ["onAction"] }, { kind: "component", type: ListStatisticCardComponent, selector: "mt-list-statistic-card", inputs: ["dashboardId"] }, { kind: "component", type: HeaderCardComponent, selector: "mt-header-card", inputs: ["dashboardId"], outputs: ["onAction"] }, { kind: "component", type: SkeletonCardComponent, selector: "mt-skeleton-card", inputs: ["dashboardId"] }, { kind: "component", type: EntityPreviewCardComponent, selector: "mt-entity-preview-card", inputs: ["dashboardId"] }, { kind: "component", type: LevelCardListComponent, selector: "mt-level-card-list", inputs: ["dashboardId", "inGroup", "hideProperties"], outputs: ["onAction"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
18557
18556
  }
18558
18557
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardItem, decorators: [{
18559
18558
  type: Component,
18560
18559
  args: [{ selector: 'mt-dashboard-item', standalone: true, imports: [
18561
18560
  CommonModule,
18562
- TranslocoDirective,
18563
18561
  Button,
18564
18562
  Icon,
18565
18563
  ChartCardComponent,
18566
18564
  TableCardComponent,
18567
18565
  ListStatisticCardComponent,
18568
- StatisticCardComponent,
18569
18566
  HeaderCardComponent,
18570
18567
  SkeletonCardComponent,
18571
18568
  EntityPreviewCardComponent,
18572
18569
  LevelCardListComponent,
18573
- ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isLoading()) {\r\n <mt-skeleton-card [dashboardId]=\"dashboardId()\"></mt-skeleton-card>\r\n} @else if (hasError()) {\r\n <div class=\"flex flex-col items-center justify-center h-full p-4 text-center\">\r\n <mt-icon\r\n icon=\"general.alert-circle\"\r\n class=\"text-4xl text-red-500 mb-2\"\r\n ></mt-icon>\r\n <p class=\"text-red-500 font-medium\">\r\n {{ errorMessage() || \"Error loading data\" }}\r\n </p>\r\n <mt-button\r\n class=\"mt-2\"\r\n [label]=\"'Retry'\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n icon=\"arrow.refresh-cw-01\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n} @else {\r\n @switch (componentName()) {\r\n <!-- Chart Types -->\r\n @case (\"chart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Map Chart -->\r\n @case (\"map\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Background Text -->\r\n @case (\"BackgroundTextChart\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Chart Custom With Card Info -->\r\n @case (\"chartCustomWithCardInfo\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Charts -->\r\n @case (\"listOfcharts\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Cards Statistic -->\r\n @case (\"listOfCardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Cards Statistic (single) -->\r\n @case (\"cardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Header -->\r\n @case (\"header\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Footer (same as header) -->\r\n @case (\"footer\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Label (same as header) -->\r\n @case (\"label\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- List of Level Cards -->\r\n @case (\"listOfLevelCards\") {\r\n <mt-level-card-list\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-level-card-list>\r\n }\r\n\r\n <!-- Table -->\r\n @case (\"table\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Phase Gate Table -->\r\n @case (\"phaseGateTable\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Topbar -->\r\n @case (\"topbar\") {\r\n <!-- Topbar handled at viewer level -->\r\n }\r\n\r\n <!-- Timeline -->\r\n @case (\"timeline\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Timeline Project Dependencies -->\r\n @case (\"timelineProjectDependencies\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Last History Level Card -->\r\n @case (\"lastHistoryLevelCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Entity Preview -->\r\n @case (\"entityPreview\") {\r\n <mt-entity-preview-card [dashboardId]=\"dashboardId()\">\r\n </mt-entity-preview-card>\r\n }\r\n\r\n <!-- Cluster Stacked Chart -->\r\n @case (\"clusterStackedChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List Component S+ Card -->\r\n @case (\"listComponentSplusCard\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Splitter Chart -->\r\n @case (\"splitterChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Repeater (same as header) -->\r\n @case (\"repeater\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Level Cards With Static -->\r\n @case (\"levelCardsWithStatic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Phase Gate Stepper Card -->\r\n @case (\"phaseGateStepperCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Dialog -->\r\n @case (\"dialog\") {\r\n <!-- Dialog handled separately via ModalService -->\r\n }\r\n\r\n <!-- Default: try chart -->\r\n @default {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n }\r\n}\r\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
18570
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isLoading()) {\r\n <mt-skeleton-card [dashboardId]=\"dashboardId()\"></mt-skeleton-card>\r\n} @else if (hasError()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-full p-4 text-center\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n >\r\n <mt-icon\r\n icon=\"general.alert-circle\"\r\n class=\"text-4xl text-red-500 mb-2\"\r\n ></mt-icon>\r\n <p class=\"text-red-500 font-medium\">\r\n {{ errorMessage() || t(\"error-loading-data\") }}\r\n </p>\r\n <mt-button\r\n class=\"mt-2\"\r\n [label]=\"t('retry')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n icon=\"arrow.refresh-cw-01\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n} @else {\r\n @switch (componentName()) {\r\n <!-- Chart Types -->\r\n @case (\"chart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Map Chart -->\r\n @case (\"map\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Background Text -->\r\n @case (\"BackgroundTextChart\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Chart Custom With Card Info -->\r\n @case (\"chartCustomWithCardInfo\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Charts -->\r\n @case (\"listOfcharts\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List of Cards Statistic -->\r\n @case (\"listOfCardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Cards Statistic (single) -->\r\n @case (\"cardsStatistic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Header -->\r\n @case (\"header\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Footer (same as header) -->\r\n @case (\"footer\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Label (same as header) -->\r\n @case (\"label\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- List of Level Cards -->\r\n @case (\"listOfLevelCards\") {\r\n <mt-level-card-list\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-level-card-list>\r\n }\r\n\r\n <!-- Table -->\r\n @case (\"table\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Phase Gate Table -->\r\n @case (\"phaseGateTable\") {\r\n <mt-table-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-table-card>\r\n }\r\n\r\n <!-- Topbar -->\r\n @case (\"topbar\") {\r\n <!-- Topbar handled at viewer level -->\r\n }\r\n\r\n <!-- Timeline -->\r\n @case (\"timeline\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Timeline Project Dependencies -->\r\n @case (\"timelineProjectDependencies\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Last History Level Card -->\r\n @case (\"lastHistoryLevelCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Entity Preview -->\r\n @case (\"entityPreview\") {\r\n <mt-entity-preview-card [dashboardId]=\"dashboardId()\">\r\n </mt-entity-preview-card>\r\n }\r\n\r\n <!-- Cluster Stacked Chart -->\r\n @case (\"clusterStackedChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- List Component S+ Card -->\r\n @case (\"listComponentSplusCard\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Splitter Chart -->\r\n @case (\"splitterChart\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Repeater (same as header) -->\r\n @case (\"repeater\") {\r\n <mt-header-card [dashboardId]=\"dashboardId()\"> </mt-header-card>\r\n }\r\n\r\n <!-- Level Cards With Static -->\r\n @case (\"levelCardsWithStatic\") {\r\n <mt-list-statistic-card [dashboardId]=\"dashboardId()\">\r\n </mt-list-statistic-card>\r\n }\r\n\r\n <!-- Phase Gate Stepper Card -->\r\n @case (\"phaseGateStepperCard\") {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n\r\n <!-- Dialog -->\r\n @case (\"dialog\") {\r\n <!-- Dialog handled separately via ModalService -->\r\n }\r\n\r\n <!-- Default: try chart -->\r\n @default {\r\n <mt-chart-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-chart-card>\r\n }\r\n }\r\n}\r\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
18574
18571
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], chartTypeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartTypeId", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], inGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "inGroup", required: false }] }], isDialog: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDialog", required: false }] }], queryParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryParams", required: false }] }], extraFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraFilters", required: false }] }], ignoreQueryFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "ignoreQueryFilter", required: false }] }], actionTriggered: [{ type: i0.Output, args: ["actionTriggered"] }] } });
18575
18572
 
18576
18573
  /**
@@ -18676,6 +18673,8 @@ class ManageItem {
18676
18673
  // Check for dialog config data (when opened via DynamicDialog)
18677
18674
  const dialogData = this._dialogConfig?.data;
18678
18675
  const inputData = this.data();
18676
+ const services = inputData?.services ?? dialogData?.services ?? null;
18677
+ this._dashboardService.setModulesTreeServices(services);
18679
18678
  // Get pre-selected chart type if available
18680
18679
  const preselectedType = inputData?.chartType ?? dialogData?.chartType;
18681
18680
  if (dialogData?.chart) {
@@ -18743,10 +18742,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
18743
18742
  TranslocoDirective,
18744
18743
  Button,
18745
18744
  Tabs,
18746
- Card,
18747
- TextField,
18748
- SelectField,
18749
- CheckboxField,
18750
18745
  GeneralSettings,
18751
18746
  DataSourceSettings,
18752
18747
  ActionsSettings,
@@ -18795,6 +18790,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
18795
18790
  class WidgetPaletteComponent {
18796
18791
  modal = inject(ModalService);
18797
18792
  ref = inject(ModalRef, { optional: true });
18793
+ translocoService = inject(TranslocoService);
18798
18794
  /** Product filter - filters chart types by product (pplus, splus, report) */
18799
18795
  product = input(null, ...(ngDevMode ? [{ debugName: "product" }] : []));
18800
18796
  /** Search filter */
@@ -18802,13 +18798,28 @@ class WidgetPaletteComponent {
18802
18798
  /** Active tab (category) */
18803
18799
  activeTab = signal('chart', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
18804
18800
  /** Tab options for categories */
18805
- tabOptions = [
18806
- { label: 'Charts', value: 'chart' },
18807
- { label: 'Cards', value: 'card' },
18808
- { label: 'Tables', value: 'table' },
18809
- { label: 'Special', value: 'special' },
18810
- { label: 'Layout', value: 'layout' },
18811
- ];
18801
+ tabOptions = computed(() => [
18802
+ {
18803
+ label: this.translocoService.translate('dashboardBuilder.categoryCharts'),
18804
+ value: 'chart',
18805
+ },
18806
+ {
18807
+ label: this.translocoService.translate('dashboardBuilder.categoryCards'),
18808
+ value: 'card',
18809
+ },
18810
+ {
18811
+ label: this.translocoService.translate('dashboardBuilder.categoryTables'),
18812
+ value: 'table',
18813
+ },
18814
+ {
18815
+ label: this.translocoService.translate('dashboardBuilder.categorySpecial'),
18816
+ value: 'special',
18817
+ },
18818
+ {
18819
+ label: this.translocoService.translate('dashboardBuilder.categoryLayout'),
18820
+ value: 'layout',
18821
+ },
18822
+ ], ...(ngDevMode ? [{ debugName: "tabOptions" }] : []));
18812
18823
  /** All chart types filtered by product */
18813
18824
  filteredChartTypes = computed(() => {
18814
18825
  const prod = this.product();
@@ -18870,11 +18881,11 @@ class WidgetPaletteComponent {
18870
18881
  this.ref?.close(null);
18871
18882
  }
18872
18883
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WidgetPaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18873
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WidgetPaletteComponent, isStandalone: true, selector: "mt-widget-palette", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Content -->\r\n <div class=\"flex flex-col gap-4 p-4\" [class]=\"modal.contentClass\">\r\n <!-- Search -->\r\n <mt-text-field\r\n [placeholder]=\"t('widgetPalette.searchPlaceholder')\"\r\n [icon]=\"'general.search-lg'\"\r\n [(value)]=\"searchTerm\"\r\n />\r\n\r\n <!-- Category Tabs -->\r\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" size=\"small\" fluid />\r\n\r\n <!-- Widgets Grid -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <div class=\"grid grid-cols-3 gap-3\">\r\n @for (widget of widgets(); track widget.id) {\r\n <div\r\n class=\"flex flex-col items-center justify-center gap-2 p-4 rounded-lg cursor-pointer border border-surface-200 bg-white select-none transition-all hover:border-primary-400 hover:shadow-md hover:bg-primary-50\"\r\n draggable=\"true\"\r\n (dragstart)=\"onDragStart($event, widget)\"\r\n (click)=\"onWidgetClick(widget)\"\r\n [title]=\"widget.name\"\r\n >\r\n <div\r\n class=\"w-10 h-10 flex items-center justify-center text-primary-500\"\r\n >\r\n <mt-icon [icon]=\"widget.icon\" class=\"text-2xl\" />\r\n </div>\r\n <span\r\n class=\"text-xs font-medium text-color text-center leading-tight\"\r\n >{{ widget.name }}</span\r\n >\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (widgets().length === 0) {\r\n <div class=\"p-8 text-center text-muted-color\">\r\n <mt-icon icon=\"general.search-lg\" class=\"text-3xl mb-2\" />\r\n <p>{{ t(\"widgetPalette.noResults\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Hint -->\r\n <div\r\n class=\"text-xs text-muted-color text-center py-2 border-t border-surface-200\"\r\n >\r\n {{ t(\"widgetPalette.dragHint\") }}\r\n </div>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18884
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: WidgetPaletteComponent, isStandalone: true, selector: "mt-widget-palette", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Content -->\r\n <div class=\"flex flex-col gap-4 p-4\" [class]=\"modal.contentClass\">\r\n <!-- Search -->\r\n <mt-text-field\r\n [placeholder]=\"t('widgetPalette.searchPlaceholder')\"\r\n [icon]=\"'general.search-lg'\"\r\n [(value)]=\"searchTerm\"\r\n />\r\n\r\n <!-- Category Tabs -->\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n size=\"small\"\r\n fluid\r\n />\r\n\r\n <!-- Widgets Grid -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <div class=\"grid grid-cols-3 gap-3\">\r\n @for (widget of widgets(); track widget.id) {\r\n <div\r\n class=\"flex flex-col items-center justify-center gap-2 p-4 rounded-lg cursor-pointer border border-surface-200 bg-white select-none transition-all hover:border-primary-400 hover:shadow-md hover:bg-primary-50\"\r\n draggable=\"true\"\r\n (dragstart)=\"onDragStart($event, widget)\"\r\n (click)=\"onWidgetClick(widget)\"\r\n [title]=\"widget.name\"\r\n >\r\n <div\r\n class=\"w-10 h-10 flex items-center justify-center text-primary-500\"\r\n >\r\n <mt-icon [icon]=\"widget.icon\" class=\"text-2xl\" />\r\n </div>\r\n <span\r\n class=\"text-xs font-medium text-color text-center leading-tight\"\r\n >{{ widget.name }}</span\r\n >\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (widgets().length === 0) {\r\n <div class=\"p-8 text-center text-muted-color\">\r\n <mt-icon icon=\"general.search-lg\" class=\"text-3xl mb-2\" />\r\n <p>{{ t(\"widgetPalette.noResults\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Hint -->\r\n <div\r\n class=\"text-xs text-muted-color text-center py-2 border-t border-surface-200\"\r\n >\r\n {{ t(\"widgetPalette.dragHint\") }}\r\n </div>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18874
18885
  }
18875
18886
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WidgetPaletteComponent, decorators: [{
18876
18887
  type: Component,
18877
- args: [{ selector: 'mt-widget-palette', standalone: true, imports: [TranslocoDirective, Button, TextField, Tabs, Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Content -->\r\n <div class=\"flex flex-col gap-4 p-4\" [class]=\"modal.contentClass\">\r\n <!-- Search -->\r\n <mt-text-field\r\n [placeholder]=\"t('widgetPalette.searchPlaceholder')\"\r\n [icon]=\"'general.search-lg'\"\r\n [(value)]=\"searchTerm\"\r\n />\r\n\r\n <!-- Category Tabs -->\r\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions\" size=\"small\" fluid />\r\n\r\n <!-- Widgets Grid -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <div class=\"grid grid-cols-3 gap-3\">\r\n @for (widget of widgets(); track widget.id) {\r\n <div\r\n class=\"flex flex-col items-center justify-center gap-2 p-4 rounded-lg cursor-pointer border border-surface-200 bg-white select-none transition-all hover:border-primary-400 hover:shadow-md hover:bg-primary-50\"\r\n draggable=\"true\"\r\n (dragstart)=\"onDragStart($event, widget)\"\r\n (click)=\"onWidgetClick(widget)\"\r\n [title]=\"widget.name\"\r\n >\r\n <div\r\n class=\"w-10 h-10 flex items-center justify-center text-primary-500\"\r\n >\r\n <mt-icon [icon]=\"widget.icon\" class=\"text-2xl\" />\r\n </div>\r\n <span\r\n class=\"text-xs font-medium text-color text-center leading-tight\"\r\n >{{ widget.name }}</span\r\n >\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (widgets().length === 0) {\r\n <div class=\"p-8 text-center text-muted-color\">\r\n <mt-icon icon=\"general.search-lg\" class=\"text-3xl mb-2\" />\r\n <p>{{ t(\"widgetPalette.noResults\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Hint -->\r\n <div\r\n class=\"text-xs text-muted-color text-center py-2 border-t border-surface-200\"\r\n >\r\n {{ t(\"widgetPalette.dragHint\") }}\r\n </div>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </div>\r\n</ng-container>\r\n" }]
18888
+ args: [{ selector: 'mt-widget-palette', standalone: true, imports: [TranslocoDirective, Button, TextField, Tabs, Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Content -->\r\n <div class=\"flex flex-col gap-4 p-4\" [class]=\"modal.contentClass\">\r\n <!-- Search -->\r\n <mt-text-field\r\n [placeholder]=\"t('widgetPalette.searchPlaceholder')\"\r\n [icon]=\"'general.search-lg'\"\r\n [(value)]=\"searchTerm\"\r\n />\r\n\r\n <!-- Category Tabs -->\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n size=\"small\"\r\n fluid\r\n />\r\n\r\n <!-- Widgets Grid -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <div class=\"grid grid-cols-3 gap-3\">\r\n @for (widget of widgets(); track widget.id) {\r\n <div\r\n class=\"flex flex-col items-center justify-center gap-2 p-4 rounded-lg cursor-pointer border border-surface-200 bg-white select-none transition-all hover:border-primary-400 hover:shadow-md hover:bg-primary-50\"\r\n draggable=\"true\"\r\n (dragstart)=\"onDragStart($event, widget)\"\r\n (click)=\"onWidgetClick(widget)\"\r\n [title]=\"widget.name\"\r\n >\r\n <div\r\n class=\"w-10 h-10 flex items-center justify-center text-primary-500\"\r\n >\r\n <mt-icon [icon]=\"widget.icon\" class=\"text-2xl\" />\r\n </div>\r\n <span\r\n class=\"text-xs font-medium text-color text-center leading-tight\"\r\n >{{ widget.name }}</span\r\n >\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (widgets().length === 0) {\r\n <div class=\"p-8 text-center text-muted-color\">\r\n <mt-icon icon=\"general.search-lg\" class=\"text-3xl mb-2\" />\r\n <p>{{ t(\"widgetPalette.noResults\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Hint -->\r\n <div\r\n class=\"text-xs text-muted-color text-center py-2 border-t border-surface-200\"\r\n >\r\n {{ t(\"widgetPalette.dragHint\") }}\r\n </div>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </div>\r\n</ng-container>\r\n" }]
18878
18889
  }], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: false }] }] } });
18879
18890
 
18880
18891
  /**
@@ -18907,6 +18918,8 @@ class DashboardBuilder {
18907
18918
  pageId = input(null, ...(ngDevMode ? [{ debugName: "pageId" }] : []));
18908
18919
  /** Standalone mode (when true, builder runs without API calls) */
18909
18920
  standalone = input(false, ...(ngDevMode ? [{ debugName: "standalone" }] : []));
18921
+ /** Optional services filter used by manage-item metadata tree loading */
18922
+ services = input(null, ...(ngDevMode ? [{ debugName: "services" }] : []));
18910
18923
  /** Standalone dashboard data model */
18911
18924
  dashboardData = model(null, ...(ngDevMode ? [{ debugName: "dashboardData" }] : []));
18912
18925
  /** Read-only mode */
@@ -19392,7 +19405,10 @@ class DashboardBuilder {
19392
19405
  position: 'end',
19393
19406
  dismissible: true,
19394
19407
  inputValues: {
19395
- data: { isNew: true },
19408
+ data: {
19409
+ isNew: true,
19410
+ services: this.services(),
19411
+ },
19396
19412
  },
19397
19413
  });
19398
19414
  ref.onClose.subscribe((result) => {
@@ -19411,7 +19427,12 @@ class DashboardBuilder {
19411
19427
  dismissible: true,
19412
19428
  position: 'end',
19413
19429
  inputValues: {
19414
- data: { chart, isDialog: false, isNew: false },
19430
+ data: {
19431
+ chart,
19432
+ isDialog: false,
19433
+ isNew: false,
19434
+ services: this.services(),
19435
+ },
19415
19436
  },
19416
19437
  });
19417
19438
  ref.onClose.subscribe((result) => {
@@ -19674,6 +19695,7 @@ class DashboardBuilder {
19674
19695
  isNew: true,
19675
19696
  chartType: widgetType, // Pass the pre-selected type
19676
19697
  defaultSize: widgetType.defaultSize,
19698
+ services: this.services(),
19677
19699
  },
19678
19700
  },
19679
19701
  });
@@ -19820,6 +19842,7 @@ class DashboardBuilder {
19820
19842
  },
19821
19843
  isDialog: true,
19822
19844
  isNew: false,
19845
+ services: this.services(),
19823
19846
  },
19824
19847
  },
19825
19848
  });
@@ -20042,7 +20065,7 @@ class DashboardBuilder {
20042
20065
  this.emittingDashboardData = false;
20043
20066
  }
20044
20067
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
20045
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardBuilder, isStandalone: true, selector: "mt-dashboard-builder", inputs: { isPage: { classPropertyName: "isPage", publicName: "isPage", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, backButton: { classPropertyName: "backButton", publicName: "backButton", isSignal: true, isRequired: false, transformFunction: null }, pageId: { classPropertyName: "pageId", publicName: "pageId", isSignal: true, isRequired: false, transformFunction: null }, standalone: { classPropertyName: "standalone", publicName: "standalone", isSignal: true, isRequired: false, transformFunction: null }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dashboardData: "dashboardDataChange", pageChange: "pageChange", chartsChange: "chartsChange", onSave: "onSave", onBack: "onBack", onAddChart: "onAddChart", onEditChart: "onEditChart" }, host: { listeners: { "window:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true, isSignal: true }, { propertyName: "gridsterContainer", first: true, predicate: ["gridsterContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\r\n [item]=\"chart\"\r\n class=\"bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden transition-all duration-200 hover:shadow-md hover:border-surface-300\"\r\n [class.ring-2]=\"isSelected(chart)\"\r\n [class.ring-primary]=\"isSelected(chart)\"\r\n [class.ring-offset-2]=\"isSelected(chart)\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Action Buttons -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"absolute top-1 right-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Quick Manage Button -->\r\n @if (showQuickManageButton(chart)) {\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('quickManage')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Breadcrumb Button (for topbar) -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Edit Button -->\r\n @if (\r\n chart.config?.clientConfig?.componentName !== \"header\" &&\r\n chart.config?.clientConfig?.componentName !== \"topbar\" &&\r\n chart.config?.clientConfig?.componentName !== \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('edit')\"\r\n (onClick)=\"editItem(chart)\"\r\n severity=\"warn\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Delete Button -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n } @else {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Advanced/Dialog Actions Button (pipe handles all conditions) -->\r\n @let dialogActions =\r\n chart | getChartActions: chartActionsContext;\r\n @if (dialogActions.length > 0) {\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n [tooltip]=\"t('advanced')\"\r\n (onClick)=\"advancedPopover.toggle($event)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <p-popover #advancedPopover appendTo=\"body\">\r\n <div class=\"flex flex-col gap-1 min-w-[160px]\">\r\n @for (action of dialogActions; track action.label) {\r\n <mt-button\r\n [label]=\"action.label\"\r\n [icon]=\"action.icon\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n action.command?.({\r\n originalEvent: $event,\r\n item: action,\r\n });\r\n advancedPopover.hide()\r\n \"\r\n />\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: GridsterModule }, { kind: "component", type: i2$2.GridsterComponent, selector: "gridster", inputs: ["options"] }, { kind: "component", type: i2$2.GridsterItemComponent, selector: "gridster-item", inputs: ["item"], outputs: ["itemInit", "itemChange", "itemResize"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i3$1.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }, { kind: "pipe", type: FilterByGroupPipe, name: "filterByGroup" }, { kind: "pipe", type: GetChartActionsPipe, name: "getChartActions" }], encapsulation: i0.ViewEncapsulation.None });
20068
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardBuilder, isStandalone: true, selector: "mt-dashboard-builder", inputs: { isPage: { classPropertyName: "isPage", publicName: "isPage", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, backButton: { classPropertyName: "backButton", publicName: "backButton", isSignal: true, isRequired: false, transformFunction: null }, pageId: { classPropertyName: "pageId", publicName: "pageId", isSignal: true, isRequired: false, transformFunction: null }, standalone: { classPropertyName: "standalone", publicName: "standalone", isSignal: true, isRequired: false, transformFunction: null }, services: { classPropertyName: "services", publicName: "services", isSignal: true, isRequired: false, transformFunction: null }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dashboardData: "dashboardDataChange", pageChange: "pageChange", chartsChange: "chartsChange", onSave: "onSave", onBack: "onBack", onAddChart: "onAddChart", onEditChart: "onEditChart" }, host: { listeners: { "window:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true, isSignal: true }, { propertyName: "gridsterContainer", first: true, predicate: ["gridsterContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\r\n [item]=\"chart\"\r\n class=\"bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden transition-all duration-200 hover:shadow-md hover:border-surface-300\"\r\n [class.ring-2]=\"isSelected(chart)\"\r\n [class.ring-primary]=\"isSelected(chart)\"\r\n [class.ring-offset-2]=\"isSelected(chart)\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Action Buttons -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"absolute top-1 right-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Quick Manage Button -->\r\n @if (showQuickManageButton(chart)) {\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('quickManage')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Breadcrumb Button (for topbar) -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Edit Button -->\r\n @if (\r\n chart.config?.clientConfig?.componentName !== \"header\" &&\r\n chart.config?.clientConfig?.componentName !== \"topbar\" &&\r\n chart.config?.clientConfig?.componentName !== \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('edit')\"\r\n (onClick)=\"editItem(chart)\"\r\n severity=\"warn\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Delete Button -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n } @else {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Advanced/Dialog Actions Button (pipe handles all conditions) -->\r\n @let dialogActions =\r\n chart | getChartActions: chartActionsContext;\r\n @if (dialogActions.length > 0) {\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n [tooltip]=\"t('advanced')\"\r\n (onClick)=\"advancedPopover.toggle($event)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <p-popover #advancedPopover appendTo=\"body\">\r\n <div class=\"flex flex-col gap-1 min-w-[160px]\">\r\n @for (action of dialogActions; track action.label) {\r\n <mt-button\r\n [label]=\"action.label\"\r\n [icon]=\"action.icon\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n action.command?.({\r\n originalEvent: $event,\r\n item: action,\r\n });\r\n advancedPopover.hide()\r\n \"\r\n />\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: GridsterModule }, { kind: "component", type: i2$2.GridsterComponent, selector: "gridster", inputs: ["options"] }, { kind: "component", type: i2$2.GridsterItemComponent, selector: "gridster-item", inputs: ["item"], outputs: ["itemInit", "itemChange", "itemResize"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i3$1.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }, { kind: "pipe", type: FilterByGroupPipe, name: "filterByGroup" }, { kind: "pipe", type: GetChartActionsPipe, name: "getChartActions" }], encapsulation: i0.ViewEncapsulation.None });
20046
20069
  }
20047
20070
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardBuilder, decorators: [{
20048
20071
  type: Component,
@@ -20052,18 +20075,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
20052
20075
  TranslocoDirective,
20053
20076
  GridsterModule,
20054
20077
  Button,
20055
- Tabs,
20056
- Card,
20057
- Tooltip,
20058
20078
  Page,
20059
- Menu,
20060
20079
  Popover,
20061
20080
  ContextMenuModule,
20062
20081
  FilterByGroupPipe,
20063
20082
  GetChartActionsPipe,
20064
20083
  DashboardItem,
20065
20084
  ], encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\r\n [item]=\"chart\"\r\n class=\"bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden transition-all duration-200 hover:shadow-md hover:border-surface-300\"\r\n [class.ring-2]=\"isSelected(chart)\"\r\n [class.ring-primary]=\"isSelected(chart)\"\r\n [class.ring-offset-2]=\"isSelected(chart)\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Action Buttons -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"absolute top-1 right-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Quick Manage Button -->\r\n @if (showQuickManageButton(chart)) {\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('quickManage')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Breadcrumb Button (for topbar) -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Edit Button -->\r\n @if (\r\n chart.config?.clientConfig?.componentName !== \"header\" &&\r\n chart.config?.clientConfig?.componentName !== \"topbar\" &&\r\n chart.config?.clientConfig?.componentName !== \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('edit')\"\r\n (onClick)=\"editItem(chart)\"\r\n severity=\"warn\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Delete Button -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n } @else {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!-- Advanced/Dialog Actions Button (pipe handles all conditions) -->\r\n @let dialogActions =\r\n chart | getChartActions: chartActionsContext;\r\n @if (dialogActions.length > 0) {\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n [tooltip]=\"t('advanced')\"\r\n (onClick)=\"advancedPopover.toggle($event)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <p-popover #advancedPopover appendTo=\"body\">\r\n <div class=\"flex flex-col gap-1 min-w-[160px]\">\r\n @for (action of dialogActions; track action.label) {\r\n <mt-button\r\n [label]=\"action.label\"\r\n [icon]=\"action.icon\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n action.command?.({\r\n originalEvent: $event,\r\n item: action,\r\n });\r\n advancedPopover.hide()\r\n \"\r\n />\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}\n"] }]
20066
- }], ctorParameters: () => [], propDecorators: { isPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPage", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], backButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButton", required: false }] }], pageId: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageId", required: false }] }], standalone: [{ type: i0.Input, args: [{ isSignal: true, alias: "standalone", required: false }] }], dashboardData: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardData", required: false }] }, { type: i0.Output, args: ["dashboardDataChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], chartsChange: [{ type: i0.Output, args: ["chartsChange"] }], onSave: [{ type: i0.Output, args: ["onSave"] }], onBack: [{ type: i0.Output, args: ["onBack"] }], onAddChart: [{ type: i0.Output, args: ["onAddChart"] }], onEditChart: [{ type: i0.Output, args: ["onEditChart"] }], contextMenu: [{ type: i0.ViewChild, args: ['contextMenu', { isSignal: true }] }], gridsterContainer: [{ type: i0.ViewChild, args: ['gridsterContainer', { isSignal: true }] }], onKeyDown: [{
20085
+ }], ctorParameters: () => [], propDecorators: { isPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPage", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], backButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButton", required: false }] }], pageId: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageId", required: false }] }], standalone: [{ type: i0.Input, args: [{ isSignal: true, alias: "standalone", required: false }] }], services: [{ type: i0.Input, args: [{ isSignal: true, alias: "services", required: false }] }], dashboardData: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardData", required: false }] }, { type: i0.Output, args: ["dashboardDataChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], chartsChange: [{ type: i0.Output, args: ["chartsChange"] }], onSave: [{ type: i0.Output, args: ["onSave"] }], onBack: [{ type: i0.Output, args: ["onBack"] }], onAddChart: [{ type: i0.Output, args: ["onAddChart"] }], onEditChart: [{ type: i0.Output, args: ["onEditChart"] }], contextMenu: [{ type: i0.ViewChild, args: ['contextMenu', { isSignal: true }] }], gridsterContainer: [{ type: i0.ViewChild, args: ['gridsterContainer', { isSignal: true }] }], onKeyDown: [{
20067
20086
  type: HostListener,
20068
20087
  args: ['window:keydown', ['$event']]
20069
20088
  }] } });