@masterteam/dashboard-builder 0.0.14 → 0.0.16

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,8 +46,10 @@ 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
- import { EntityPreview } from '@masterteam/components/entities';
51
+ import { Avatar } from '@masterteam/components/avatar';
52
+ import { EntitiesPreview, EntityPreview } from '@masterteam/components/entities';
53
53
  import * as i2$3 from 'primeng/button';
54
54
  import { ButtonModule } from 'primeng/button';
55
55
  import { rxResource } from '@angular/core/rxjs-interop';
@@ -81,6 +81,10 @@ class DashboardBuilderService {
81
81
  * Tree data cache for building selector name map
82
82
  */
83
83
  treeData = signal([], ...(ngDevMode ? [{ debugName: "treeData" }] : []));
84
+ /**
85
+ * Optional services filter for the modules tree request.
86
+ */
87
+ modulesTreeServices = signal(null, ...(ngDevMode ? [{ debugName: "modulesTreeServices" }] : []));
84
88
  /**
85
89
  * Fixed selections that cannot be removed or edited in SelectionConfiguration.
86
90
  * These selections are always shown and are read-only.
@@ -146,6 +150,13 @@ class DashboardBuilderService {
146
150
  clearFixedSelections() {
147
151
  this.fixedSelections.set([]);
148
152
  }
153
+ setModulesTreeServices(services) {
154
+ if (services?.length) {
155
+ this.modulesTreeServices.set([...services]);
156
+ return;
157
+ }
158
+ this.modulesTreeServices.set(null);
159
+ }
149
160
  /**
150
161
  * Add a single fixed selection
151
162
  * @param selection Selection to add as fixed
@@ -266,7 +277,11 @@ class DashboardBuilderService {
266
277
  * This returns the complete tree structure for efficient caching
267
278
  */
268
279
  getModulesTree() {
269
- return this.http.get('metadata/modules/tree?services=pplus', { context: this.gatewayContext });
280
+ const services = this.modulesTreeServices();
281
+ const servicesQuery = services?.length
282
+ ? `?services=${services.map(encodeURIComponent).join(',')}`
283
+ : '';
284
+ return this.http.get(`metadata/modules/tree${servicesQuery}`, { context: this.gatewayContext });
270
285
  }
271
286
  /**
272
287
  * Get modules for a specific service
@@ -1035,13 +1050,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
1035
1050
  TranslocoDirective,
1036
1051
  Button,
1037
1052
  Icon,
1038
- Card,
1039
1053
  SelectField,
1040
1054
  TextField,
1041
1055
  NumberField,
1042
1056
  CheckboxField,
1043
1057
  TextareaField,
1044
- Tooltip,
1045
1058
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1046
1059
  {
1047
1060
  provide: NG_VALUE_ACCESSOR,
@@ -1125,7 +1138,7 @@ const CHART_TYPES = [
1125
1138
  componentName: 'cardsStatistic',
1126
1139
  functionName: 'handleOverviewCard',
1127
1140
  requestType: 'custom',
1128
- category: 'card',
1141
+ category: 'special',
1129
1142
  products: ['pplus', 'splus', 'report'],
1130
1143
  hasManageItem: true,
1131
1144
  defaultSize: { cols: 6, rows: 2 },
@@ -1311,13 +1324,14 @@ const CHART_TYPES = [
1311
1324
  requestType: 'custom',
1312
1325
  category: 'table',
1313
1326
  products: ['pplus', 'splus', 'report'],
1327
+ hideInList: true,
1314
1328
  hasManageItem: true,
1315
1329
  defaultSize: { cols: 18, rows: 6 },
1316
1330
  },
1317
1331
  {
1318
1332
  id: 'chart-map-chart',
1319
1333
  name: 'Map Chart',
1320
- icon: 'maps.globe-01',
1334
+ icon: 'map.globe-01',
1321
1335
  serviceType: 'TableView',
1322
1336
  componentName: 'map',
1323
1337
  functionName: 'handleLeafletMap',
@@ -1330,7 +1344,7 @@ const CHART_TYPES = [
1330
1344
  // ===================== SPECIAL =====================
1331
1345
  {
1332
1346
  id: 'entity-preview',
1333
- name: 'Entity Preview',
1347
+ name: 'Properties View',
1334
1348
  icon: 'file.file-05',
1335
1349
  serviceType: 'Properties',
1336
1350
  componentName: 'entityPreview',
@@ -1344,7 +1358,7 @@ const CHART_TYPES = [
1344
1358
  {
1345
1359
  id: 'entity-preview-with-formula',
1346
1360
  name: 'Entity Preview with Formula',
1347
- icon: 'media.calculator',
1361
+ icon: 'education.calculator',
1348
1362
  serviceType: 'BarV2Chart',
1349
1363
  componentName: 'entityPreviewWithFormula',
1350
1364
  functionName: 'handleEntityPreviewWithFormula',
@@ -1364,15 +1378,16 @@ const CHART_TYPES = [
1364
1378
  requestType: 'levelCards',
1365
1379
  category: 'special',
1366
1380
  products: ['pplus'],
1381
+ hideInList: true,
1367
1382
  hasManageItem: true,
1368
1383
  defaultSize: { cols: 18, rows: 4 },
1369
1384
  },
1370
1385
  {
1371
1386
  id: 'entity-preview-levelCards2',
1372
- name: 'Filterable Level Cards',
1387
+ name: 'Properties Card',
1373
1388
  icon: 'layout.grid-01',
1374
1389
  serviceType: 'TableView',
1375
- componentName: 'listOfLevelCards',
1390
+ componentName: 'entitiesPreview',
1376
1391
  functionName: 'handlelevelCardsWithFilter',
1377
1392
  requestType: 'custom',
1378
1393
  category: 'special',
@@ -1390,13 +1405,14 @@ const CHART_TYPES = [
1390
1405
  requestType: 'custom',
1391
1406
  category: 'special',
1392
1407
  products: ['splus'],
1408
+ hideInList: true,
1393
1409
  hasManageItem: true,
1394
1410
  defaultSize: { cols: 18, rows: 4 },
1395
1411
  },
1396
1412
  {
1397
1413
  id: 'last-history-level-card',
1398
1414
  name: 'Progress Update',
1399
- icon: 'time.history',
1415
+ icon: 'time.clock-refresh',
1400
1416
  serviceType: 'TableView',
1401
1417
  componentName: 'lastHistoryLevelCard',
1402
1418
  functionName: 'handleTableView',
@@ -1416,13 +1432,14 @@ const CHART_TYPES = [
1416
1432
  requestType: 'custom',
1417
1433
  category: 'special',
1418
1434
  products: ['pplus', 'splus'],
1435
+ hideInList: true,
1419
1436
  hasManageItem: true,
1420
1437
  defaultSize: { cols: 18, rows: 4 },
1421
1438
  },
1422
1439
  {
1423
1440
  id: 'phase-gate-stepper-card',
1424
1441
  name: 'Phase Gate Stepper',
1425
- icon: 'general.sliders-02',
1442
+ icon: 'media.sliders-02',
1426
1443
  serviceType: 'phaseGate',
1427
1444
  componentName: 'phaseGateStepperCard',
1428
1445
  functionName: 'handlePhaseGateStepperCard',
@@ -1624,7 +1641,7 @@ class ManageItemService {
1624
1641
  this.selectedType.set({
1625
1642
  id: 'custom-type',
1626
1643
  name: 'Custom Type',
1627
- icon: 'general.question-mark',
1644
+ icon: 'general.help-circle',
1628
1645
  serviceType: config.serviceConfig.chartType,
1629
1646
  componentName: config.clientConfig.componentName,
1630
1647
  functionName: config.clientConfig.functionName,
@@ -1794,6 +1811,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
1794
1811
  type: Injectable
1795
1812
  }] });
1796
1813
 
1814
+ function createDefaultPropsConfigItem() {
1815
+ return {
1816
+ width: '',
1817
+ colorAsProperty: '',
1818
+ hidden: false,
1819
+ border: [],
1820
+ };
1821
+ }
1797
1822
  /**
1798
1823
  * Display Settings Component
1799
1824
  *
@@ -1847,12 +1872,13 @@ class DisplaySettings {
1847
1872
  // Snapshot
1848
1873
  snapShot_chart: 'advanced,format,overrideLabels,configAd,defaultColors,centerHeader,advancedHeaderConfig,borderTop,cardStyleConfig',
1849
1874
  // Level Cards
1850
- levelCards_listOfLevelCards: 'advanced,configAd,centerHeader,advancedHeaderConfig,cardStyleConfig,cardListConfig',
1851
- TableView_listOfLevelCards: 'advanced,configAd,centerHeader,advancedHeaderConfig,cardStyleConfig,cardListConfig',
1875
+ levelCards_listOfLevelCards: 'advanced,propsConfigAsIndex,configAd,centerHeader,advancedHeaderConfig,cardStyleConfig,cardListConfig',
1876
+ TableView_listOfLevelCards: 'advanced,propsConfigAsIndex,configAd,centerHeader,advancedHeaderConfig,cardStyleConfig',
1877
+ TableView_entitiesPreview: 'advanced,propsConfigAsIndex,configAd,centerHeader,advancedHeaderConfig,cardStyleConfig',
1852
1878
  // Component Cards
1853
1879
  componentCards_listComponentSplusCard: 'cardStyleConfig',
1854
1880
  // Entity Preview
1855
- Properties_entityPreview: 'advanced,propsConfigAsIndex,propertyTranslations,configAd,centerHeader,advancedHeaderConfig,borderTop,cardStyleConfig',
1881
+ Properties_entityPreview: 'advanced,propsConfigAsIndex,configAd,centerHeader,advancedHeaderConfig,borderTop,cardStyleConfig',
1856
1882
  // Level Cards with Static
1857
1883
  TableView_levelCardsWithStatic: 'advanced,labelCenter,propertyTranslations,format,toggleAssociation,propertyColors',
1858
1884
  // Ring Gauge
@@ -1887,6 +1913,18 @@ class DisplaySettings {
1887
1913
  shouldShowField(fieldName) {
1888
1914
  return this.fieldsToShow().split(',').includes(fieldName);
1889
1915
  }
1916
+ shouldShowPropertiesViewSettings() {
1917
+ if (this.shouldShowField('propsConfigAsIndex')) {
1918
+ return true;
1919
+ }
1920
+ const chartType = this.chartType();
1921
+ if (!chartType) {
1922
+ return false;
1923
+ }
1924
+ return (chartType.componentName === 'entitiesPreview' ||
1925
+ chartType.componentName === 'listOfLevelCards' ||
1926
+ chartType.componentName === 'entityPreview');
1927
+ }
1890
1928
  /** Position options */
1891
1929
  positionOptions = [
1892
1930
  { label: 'Start', value: 'start' },
@@ -2105,12 +2143,17 @@ class DisplaySettings {
2105
2143
  toggleAssociation = computed(() => this.configAsType()['toggleAssociation'] || false, ...(ngDevMode ? [{ debugName: "toggleAssociation" }] : []));
2106
2144
  /** Selected properties resolved from input or config */
2107
2145
  resolvedSelectedProperties = computed(() => {
2108
- const props = this.selectedProperties();
2109
- if (props?.length)
2146
+ const props = this.selectedProperties()
2147
+ .map((prop) => this.resolvePropertyKey(prop))
2148
+ .filter((prop) => !!prop);
2149
+ if (props.length)
2110
2150
  return props;
2111
2151
  const fromConfig = this.config()?.serviceConfig?.query?.['selectedProperties'];
2112
- if (Array.isArray(fromConfig))
2113
- return fromConfig;
2152
+ if (Array.isArray(fromConfig)) {
2153
+ return fromConfig
2154
+ .map((prop) => this.resolvePropertyKey(prop))
2155
+ .filter((prop) => !!prop);
2156
+ }
2114
2157
  return [];
2115
2158
  }, ...(ngDevMode ? [{ debugName: "resolvedSelectedProperties" }] : []));
2116
2159
  /** Available properties resolved from input or selected properties */
@@ -2123,21 +2166,50 @@ class DisplaySettings {
2123
2166
  name: key,
2124
2167
  }));
2125
2168
  }, ...(ngDevMode ? [{ debugName: "resolvedAvailableProperties" }] : []));
2126
- /** Available properties as options */
2127
- propertyOptions = computed(() => {
2169
+ /** Selected properties as ordered options */
2170
+ selectedPropertyOptions = computed(() => {
2128
2171
  const selected = this.resolvedSelectedProperties();
2172
+ if (!selected.length)
2173
+ return [];
2129
2174
  const allProps = this.resolvedAvailableProperties();
2175
+ return selected.map((key) => {
2176
+ const prop = allProps.find((item) => this.resolvePropertyKey(item) === key ||
2177
+ item.key === key ||
2178
+ item.value === key);
2179
+ return {
2180
+ label: prop?.name || prop?.label || key,
2181
+ value: key,
2182
+ };
2183
+ });
2184
+ }, ...(ngDevMode ? [{ debugName: "selectedPropertyOptions" }] : []));
2185
+ /** Available properties as options */
2186
+ propertyOptions = computed(() => {
2187
+ const selected = this.selectedPropertyOptions();
2130
2188
  if (selected.length > 0) {
2131
- return selected.map((key) => {
2132
- const prop = allProps.find((p) => p.key === key || p.value === key);
2133
- return { label: prop?.name || prop?.label || key, value: key };
2134
- });
2189
+ return selected;
2135
2190
  }
2191
+ const allProps = this.resolvedAvailableProperties();
2136
2192
  return allProps.map((prop) => ({
2137
2193
  label: prop?.name || prop?.label || prop?.key || prop?.value || String(prop),
2138
2194
  value: prop?.key || prop?.value || String(prop),
2139
2195
  }));
2140
2196
  }, ...(ngDevMode ? [{ debugName: "propertyOptions" }] : []));
2197
+ /** Properties view rows driven by selected properties order */
2198
+ propertiesViewRows = computed(() => this.selectedPropertyOptions().map((property, index) => ({
2199
+ key: property.value,
2200
+ label: property.label,
2201
+ index,
2202
+ config: this.propsConfigAsIndex()[index] || createDefaultPropsConfigItem(),
2203
+ })), ...(ngDevMode ? [{ debugName: "propertiesViewRows" }] : []));
2204
+ /** Property translations rows driven by selected properties order */
2205
+ propertyTranslationRows = computed(() => this.selectedPropertyOptions().map((property) => ({
2206
+ key: property.value,
2207
+ label: property.label,
2208
+ translation: this.propertyTranslations()[property.value] || {
2209
+ ar: '',
2210
+ en: '',
2211
+ },
2212
+ })), ...(ngDevMode ? [{ debugName: "propertyTranslationRows" }] : []));
2141
2213
  /** Available translation options (exclude used) */
2142
2214
  availableTranslationOptions = computed(() => {
2143
2215
  const used = new Set(Object.keys(this.propertyTranslations()));
@@ -2690,28 +2762,12 @@ class DisplaySettings {
2690
2762
  this.updateNestedConfigAsType('cardListConfig', 'hideProperties', properties);
2691
2763
  }
2692
2764
  // ============ Props Config As Index Methods ============
2693
- /** Add props config item */
2694
- addPropsConfigItem() {
2695
- const items = [...this.propsConfigAsIndex()];
2696
- items.push({
2697
- width: '',
2698
- colorAsProperty: '',
2699
- hidden: false,
2700
- border: [],
2701
- });
2702
- this.updateConfigAsType('propsConfigAsIndex', items);
2703
- }
2704
- /** Remove props config item */
2705
- removePropsConfigItem(index) {
2706
- const items = [...this.propsConfigAsIndex()];
2707
- items.splice(index, 1);
2708
- this.updateConfigAsType('propsConfigAsIndex', items);
2709
- }
2710
2765
  /** Update props config item */
2711
2766
  updatePropsConfigItem(index, key, value) {
2712
2767
  const items = [...this.propsConfigAsIndex()];
2713
- if (!items[index])
2714
- return;
2768
+ while (items.length <= index) {
2769
+ items.push(createDefaultPropsConfigItem());
2770
+ }
2715
2771
  items[index] = {
2716
2772
  ...items[index],
2717
2773
  [key]: value,
@@ -2865,12 +2921,11 @@ class DisplaySettings {
2865
2921
  const translations = {
2866
2922
  ...(configAsType['overrideSelectedPropertiesLabels'] || {}),
2867
2923
  };
2868
- if (translations[propertyKey]) {
2869
- translations[propertyKey] = {
2870
- ...translations[propertyKey],
2871
- [lang]: value,
2872
- };
2873
- }
2924
+ const currentTranslation = translations[propertyKey] || { ar: '', en: '' };
2925
+ translations[propertyKey] = {
2926
+ ...currentTranslation,
2927
+ [lang]: value,
2928
+ };
2874
2929
  this.clientConfigChange.emit({
2875
2930
  configAsType: {
2876
2931
  ...configAsType,
@@ -3050,8 +3105,29 @@ class DisplaySettings {
3050
3105
  selectedPropertyForTranslation = signal('', ...(ngDevMode ? [{ debugName: "selectedPropertyForTranslation" }] : []));
3051
3106
  /** Selected property for adding colors */
3052
3107
  selectedPropertyForColor = signal('', ...(ngDevMode ? [{ debugName: "selectedPropertyForColor" }] : []));
3108
+ resolvePropertyKey(value) {
3109
+ if (typeof value === 'string') {
3110
+ return value;
3111
+ }
3112
+ if (value && typeof value === 'object') {
3113
+ const record = value;
3114
+ const key = record['key'];
3115
+ const normalizedKey = record['normalizedKey'];
3116
+ const valueKey = record['value'];
3117
+ if (typeof key === 'string') {
3118
+ return key;
3119
+ }
3120
+ if (typeof normalizedKey === 'string') {
3121
+ return normalizedKey;
3122
+ }
3123
+ if (typeof valueKey === 'string') {
3124
+ return valueKey;
3125
+ }
3126
+ }
3127
+ return '';
3128
+ }
3053
3129
  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 });
3130
+ 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 class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\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 lg:grid-cols-2 gap-5\">\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 lg:grid-cols-2 gap-5\">\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 md:grid-cols-2 gap-5\">\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 gap-5 mb-6\">\r\n <mt-slider-field\r\n [label]=\"t('borderRadius')\"\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 unit=\"px\"\r\n />\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\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(\"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 md:grid-cols-2 gap-4\">\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 <div class=\"md:col-span-2\">\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 </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 lg:grid-cols-2 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\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(\"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 lg:grid-cols-2 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\"\r\n >{{ t(\"quickAdd\") }}:</span\r\n >\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 lg:grid-cols-2 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 lg:grid-cols-2 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 lg:grid-cols-2 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 lg:grid-cols-2 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 lg:grid-cols-2 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\r\n class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\"\r\n >\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\r\n class=\"flex flex-wrap items-center justify-between gap-2 mb-3\"\r\n >\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\r\n class=\"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-3 items-end\"\r\n >\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 (shouldShowPropertiesViewSettings()) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n @if (propertiesViewRows().length === 0) {\r\n <div class=\"py-4 text-sm text-muted-color\">\r\n {{ t(\"selectPropertiesFirst\") }}\r\n </div>\r\n } @else {\r\n <div class=\"space-y-4\">\r\n @for (property of propertiesViewRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"property.config.width || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'width', $event)\r\n \"\r\n [placeholder]=\"'100%'\"\r\n size=\"small\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"property.config.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(\r\n property.index,\r\n 'colorAsProperty',\r\n $event\r\n )\r\n \"\r\n [options]=\"selectedPropertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColorProperty')\"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n size=\"small\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"property.config.border || []\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'border', $event)\r\n \"\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]=\"property.config.hidden || false\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'hidden', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n }\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 <div class=\"space-y-4\">\r\n @for (property of propertyTranslationRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"property.translation.en\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'en', $event)\r\n \"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"property.translation.ar\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'ar', $event)\r\n \"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (propertyTranslationRows().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </div>\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", "inputId", "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
3131
  }
3056
3132
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DisplaySettings, decorators: [{
3057
3133
  type: Component,
@@ -3070,11 +3146,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
3070
3146
  ToggleField,
3071
3147
  IconField,
3072
3148
  Card,
3073
- Tooltip$1,
3074
- ], 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" }]
3149
+ Tooltip,
3150
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\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 lg:grid-cols-2 gap-5\">\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 lg:grid-cols-2 gap-5\">\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 md:grid-cols-2 gap-5\">\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 gap-5 mb-6\">\r\n <mt-slider-field\r\n [label]=\"t('borderRadius')\"\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 unit=\"px\"\r\n />\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\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(\"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 md:grid-cols-2 gap-4\">\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 <div class=\"md:col-span-2\">\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 </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 lg:grid-cols-2 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\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(\"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 lg:grid-cols-2 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\"\r\n >{{ t(\"quickAdd\") }}:</span\r\n >\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 lg:grid-cols-2 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 lg:grid-cols-2 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 lg:grid-cols-2 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 lg:grid-cols-2 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 lg:grid-cols-2 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\r\n class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\"\r\n >\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\r\n class=\"flex flex-wrap items-center justify-between gap-2 mb-3\"\r\n >\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\r\n class=\"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-3 items-end\"\r\n >\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 (shouldShowPropertiesViewSettings()) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n @if (propertiesViewRows().length === 0) {\r\n <div class=\"py-4 text-sm text-muted-color\">\r\n {{ t(\"selectPropertiesFirst\") }}\r\n </div>\r\n } @else {\r\n <div class=\"space-y-4\">\r\n @for (property of propertiesViewRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"property.config.width || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'width', $event)\r\n \"\r\n [placeholder]=\"'100%'\"\r\n size=\"small\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"property.config.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(\r\n property.index,\r\n 'colorAsProperty',\r\n $event\r\n )\r\n \"\r\n [options]=\"selectedPropertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColorProperty')\"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n size=\"small\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"property.config.border || []\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'border', $event)\r\n \"\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]=\"property.config.hidden || false\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'hidden', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n }\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 <div class=\"space-y-4\">\r\n @for (property of propertyTranslationRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"property.translation.en\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'en', $event)\r\n \"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"property.translation.ar\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'ar', $event)\r\n \"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (propertyTranslationRows().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </div>\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
3151
  }], 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
3152
 
3077
3153
  class DefaultControlUi {
3154
+ showIconSettings = input(false, ...(ngDevMode ? [{ debugName: "showIconSettings" }] : []));
3155
+ layoutComponent = input(null, ...(ngDevMode ? [{ debugName: "layoutComponent" }] : []));
3078
3156
  config = signal({
3079
3157
  title: '',
3080
3158
  titleFontSize: 16,
@@ -3083,6 +3161,9 @@ class DefaultControlUi {
3083
3161
  subtitle: '',
3084
3162
  subtitleFontSize: 14,
3085
3163
  subtitleColor: '#666666',
3164
+ icon: '',
3165
+ iconColor: '#4caf50',
3166
+ iconBackgroundColor: 'rgba(76, 175, 80, 0.1)',
3086
3167
  backgroundColor: '#ffffff',
3087
3168
  borderColor: '#e0e0e0',
3088
3169
  borderRadius: 8,
@@ -3100,6 +3181,9 @@ class DefaultControlUi {
3100
3181
  ];
3101
3182
  onChange = () => { };
3102
3183
  onTouched = () => { };
3184
+ supportsSubtitle = computed(() => {
3185
+ return this.layoutComponent() === 'topbar';
3186
+ }, ...(ngDevMode ? [{ debugName: "supportsSubtitle" }] : []));
3103
3187
  writeValue(value) {
3104
3188
  if (value) {
3105
3189
  this.config.set({ ...this.config(), ...value });
@@ -3118,13 +3202,13 @@ class DefaultControlUi {
3118
3202
  this.onTouched();
3119
3203
  }
3120
3204
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DefaultControlUi, deps: [], target: i0.ɵɵFactoryTarget.Component });
3121
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DefaultControlUi, isStandalone: true, selector: "mt-default-control-ui", providers: [
3205
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DefaultControlUi, isStandalone: true, selector: "mt-default-control-ui", inputs: { showIconSettings: { classPropertyName: "showIconSettings", publicName: "showIconSettings", isSignal: true, isRequired: false, transformFunction: null }, layoutComponent: { classPropertyName: "layoutComponent", publicName: "layoutComponent", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3122
3206
  {
3123
3207
  provide: NG_VALUE_ACCESSOR,
3124
3208
  useExisting: forwardRef(() => DefaultControlUi),
3125
3209
  multi: true,
3126
3210
  },
3127
- ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls'\"\r\n>\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <!-- Chart Title -->\r\n <mt-text-field\r\n [label]=\"t('chartTitle')\"\r\n [ngModel]=\"config().title\"\r\n (ngModelChange)=\"updateConfig({ title: $event })\"\r\n [placeholder]=\"t('chartTitlePlaceholder')\"\r\n />\r\n\r\n <!-- Title Font Size -->\r\n <mt-select-field\r\n [label]=\"t('titleFontSize')\"\r\n [ngModel]=\"config().titleFontSize\"\r\n (ngModelChange)=\"updateConfig({ titleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n />\r\n\r\n <!-- Title Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('titleColor')\"\r\n [ngModel]=\"config().titleColor\"\r\n (ngModelChange)=\"updateConfig({ titleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <!-- Show Subtitle Toggle -->\r\n <mt-toggle-field\r\n [label]=\"t('showSubtitle')\"\r\n [ngModel]=\"config().showSubtitle\"\r\n (ngModelChange)=\"updateConfig({ showSubtitle: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (config().showSubtitle) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <!-- Subtitle -->\r\n <mt-text-field\r\n [label]=\"t('subtitle')\"\r\n [ngModel]=\"config().subtitle\"\r\n (ngModelChange)=\"updateConfig({ subtitle: $event })\"\r\n [placeholder]=\"t('subtitlePlaceholder')\"\r\n />\r\n\r\n <!-- Subtitle Font Size -->\r\n <mt-select-field\r\n [label]=\"t('subtitleFontSize')\"\r\n [ngModel]=\"config().subtitleFontSize\"\r\n (ngModelChange)=\"updateConfig({ subtitleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n />\r\n\r\n <!-- Subtitle Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('subtitleColor')\"\r\n [ngModel]=\"config().subtitleColor\"\r\n (ngModelChange)=\"updateConfig({ subtitleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <!-- Background Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"config().backgroundColor\"\r\n (ngModelChange)=\"updateConfig({ backgroundColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <!-- Border Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('borderColor')\"\r\n [ngModel]=\"config().borderColor\"\r\n (ngModelChange)=\"updateConfig({ borderColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <!-- Border Radius -->\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"50\"\r\n />\r\n\r\n <!-- Padding -->\r\n <mt-number-field\r\n [label]=\"t('padding')\"\r\n [ngModel]=\"config().padding\"\r\n (ngModelChange)=\"updateConfig({ padding: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\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.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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3211
+ ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls'\"\r\n>\r\n <mt-card [title]=\"t('chartTitle')\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <mt-text-field\r\n [label]=\"t('chartTitle')\"\r\n [ngModel]=\"config().title\"\r\n (ngModelChange)=\"updateConfig({ title: $event })\"\r\n [placeholder]=\"t('chartTitlePlaceholder')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('titleFontSize')\"\r\n [ngModel]=\"config().titleFontSize\"\r\n (ngModelChange)=\"updateConfig({ titleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('titleColor')\"\r\n [ngModel]=\"config().titleColor\"\r\n (ngModelChange)=\"updateConfig({ titleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n </div>\r\n </mt-card>\r\n\r\n @if (showIconSettings()) {\r\n <mt-card [title]=\"t('icon')\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-3\">\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"config().icon\"\r\n (ngModelChange)=\"updateConfig({ icon: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"config().iconColor\"\r\n (ngModelChange)=\"updateConfig({ iconColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('iconBackgroundColor')\"\r\n [ngModel]=\"config().iconBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ iconBackgroundColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n @if (supportsSubtitle()) {\r\n <mt-card [title]=\"t('subtitle')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showSubtitle')\"\r\n [ngModel]=\"config().showSubtitle\"\r\n (ngModelChange)=\"updateConfig({ showSubtitle: $event })\"\r\n toggleShape=\"card\"\r\n size=\"small\"\r\n />\r\n\r\n <div\r\n class=\"grid grid-cols-1 gap-4 rounded-xl border border-surface-200 bg-surface-50 p-4 transition-opacity xl:grid-cols-2\"\r\n [class.opacity-60]=\"!config().showSubtitle\"\r\n >\r\n <mt-text-field\r\n [label]=\"t('subtitle')\"\r\n [ngModel]=\"config().subtitle\"\r\n (ngModelChange)=\"updateConfig({ subtitle: $event })\"\r\n [placeholder]=\"t('subtitlePlaceholder')\"\r\n [disabled]=\"!config().showSubtitle\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('subtitleFontSize')\"\r\n [ngModel]=\"config().subtitleFontSize\"\r\n (ngModelChange)=\"updateConfig({ subtitleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n [disabled]=\"!config().showSubtitle\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('subtitleColor')\"\r\n [ngModel]=\"config().subtitleColor\"\r\n (ngModelChange)=\"updateConfig({ subtitleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n [disabled]=\"!config().showSubtitle\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <mt-card [title]=\"t('backgroundColor')\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"config().backgroundColor\"\r\n (ngModelChange)=\"updateConfig({ backgroundColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('borderColor')\"\r\n [ngModel]=\"config().borderColor\"\r\n (ngModelChange)=\"updateConfig({ borderColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"50\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('padding')\"\r\n [ngModel]=\"config().padding\"\r\n (ngModelChange)=\"updateConfig({ padding: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\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.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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], 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: IconField, selector: "mt-icon-field", inputs: ["label", "required"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3128
3212
  }
3129
3213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DefaultControlUi, decorators: [{
3130
3214
  type: Component,
@@ -3137,14 +3221,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
3137
3221
  ColorPickerField,
3138
3222
  ToggleField,
3139
3223
  NumberField,
3140
- ], providers: [
3224
+ IconField,
3225
+ Card,
3226
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3141
3227
  {
3142
3228
  provide: NG_VALUE_ACCESSOR,
3143
3229
  useExisting: forwardRef(() => DefaultControlUi),
3144
3230
  multi: true,
3145
3231
  },
3146
- ], template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls'\"\r\n>\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <!-- Chart Title -->\r\n <mt-text-field\r\n [label]=\"t('chartTitle')\"\r\n [ngModel]=\"config().title\"\r\n (ngModelChange)=\"updateConfig({ title: $event })\"\r\n [placeholder]=\"t('chartTitlePlaceholder')\"\r\n />\r\n\r\n <!-- Title Font Size -->\r\n <mt-select-field\r\n [label]=\"t('titleFontSize')\"\r\n [ngModel]=\"config().titleFontSize\"\r\n (ngModelChange)=\"updateConfig({ titleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n />\r\n\r\n <!-- Title Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('titleColor')\"\r\n [ngModel]=\"config().titleColor\"\r\n (ngModelChange)=\"updateConfig({ titleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <!-- Show Subtitle Toggle -->\r\n <mt-toggle-field\r\n [label]=\"t('showSubtitle')\"\r\n [ngModel]=\"config().showSubtitle\"\r\n (ngModelChange)=\"updateConfig({ showSubtitle: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (config().showSubtitle) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <!-- Subtitle -->\r\n <mt-text-field\r\n [label]=\"t('subtitle')\"\r\n [ngModel]=\"config().subtitle\"\r\n (ngModelChange)=\"updateConfig({ subtitle: $event })\"\r\n [placeholder]=\"t('subtitlePlaceholder')\"\r\n />\r\n\r\n <!-- Subtitle Font Size -->\r\n <mt-select-field\r\n [label]=\"t('subtitleFontSize')\"\r\n [ngModel]=\"config().subtitleFontSize\"\r\n (ngModelChange)=\"updateConfig({ subtitleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n />\r\n\r\n <!-- Subtitle Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('subtitleColor')\"\r\n [ngModel]=\"config().subtitleColor\"\r\n (ngModelChange)=\"updateConfig({ subtitleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <!-- Background Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"config().backgroundColor\"\r\n (ngModelChange)=\"updateConfig({ backgroundColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <!-- Border Color -->\r\n <mt-color-picker-field\r\n [label]=\"t('borderColor')\"\r\n [ngModel]=\"config().borderColor\"\r\n (ngModelChange)=\"updateConfig({ borderColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <!-- Border Radius -->\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"50\"\r\n />\r\n\r\n <!-- Padding -->\r\n <mt-number-field\r\n [label]=\"t('padding')\"\r\n [ngModel]=\"config().padding\"\r\n (ngModelChange)=\"updateConfig({ padding: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n" }]
3147
- }] });
3232
+ ], template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls'\"\r\n>\r\n <mt-card [title]=\"t('chartTitle')\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <mt-text-field\r\n [label]=\"t('chartTitle')\"\r\n [ngModel]=\"config().title\"\r\n (ngModelChange)=\"updateConfig({ title: $event })\"\r\n [placeholder]=\"t('chartTitlePlaceholder')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('titleFontSize')\"\r\n [ngModel]=\"config().titleFontSize\"\r\n (ngModelChange)=\"updateConfig({ titleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('titleColor')\"\r\n [ngModel]=\"config().titleColor\"\r\n (ngModelChange)=\"updateConfig({ titleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n </div>\r\n </mt-card>\r\n\r\n @if (showIconSettings()) {\r\n <mt-card [title]=\"t('icon')\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-3\">\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"config().icon\"\r\n (ngModelChange)=\"updateConfig({ icon: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"config().iconColor\"\r\n (ngModelChange)=\"updateConfig({ iconColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('iconBackgroundColor')\"\r\n [ngModel]=\"config().iconBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ iconBackgroundColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n @if (supportsSubtitle()) {\r\n <mt-card [title]=\"t('subtitle')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showSubtitle')\"\r\n [ngModel]=\"config().showSubtitle\"\r\n (ngModelChange)=\"updateConfig({ showSubtitle: $event })\"\r\n toggleShape=\"card\"\r\n size=\"small\"\r\n />\r\n\r\n <div\r\n class=\"grid grid-cols-1 gap-4 rounded-xl border border-surface-200 bg-surface-50 p-4 transition-opacity xl:grid-cols-2\"\r\n [class.opacity-60]=\"!config().showSubtitle\"\r\n >\r\n <mt-text-field\r\n [label]=\"t('subtitle')\"\r\n [ngModel]=\"config().subtitle\"\r\n (ngModelChange)=\"updateConfig({ subtitle: $event })\"\r\n [placeholder]=\"t('subtitlePlaceholder')\"\r\n [disabled]=\"!config().showSubtitle\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('subtitleFontSize')\"\r\n [ngModel]=\"config().subtitleFontSize\"\r\n (ngModelChange)=\"updateConfig({ subtitleFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFontSize')\"\r\n [disabled]=\"!config().showSubtitle\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('subtitleColor')\"\r\n [ngModel]=\"config().subtitleColor\"\r\n (ngModelChange)=\"updateConfig({ subtitleColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n [disabled]=\"!config().showSubtitle\"\r\n />\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <mt-card [title]=\"t('backgroundColor')\">\r\n <div class=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"config().backgroundColor\"\r\n (ngModelChange)=\"updateConfig({ backgroundColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('borderColor')\"\r\n [ngModel]=\"config().borderColor\"\r\n (ngModelChange)=\"updateConfig({ borderColor: $event })\"\r\n [placeholder]=\"t('colorPlaceholder')\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"50\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('padding')\"\r\n [ngModel]=\"config().padding\"\r\n (ngModelChange)=\"updateConfig({ padding: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </mt-card>\r\n</div>\r\n" }]
3233
+ }], propDecorators: { showIconSettings: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIconSettings", required: false }] }], layoutComponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "layoutComponent", required: false }] }] } });
3148
3234
 
3149
3235
  class PieControlUi {
3150
3236
  config = signal({
@@ -3264,7 +3350,7 @@ class PieControlUi {
3264
3350
  useExisting: forwardRef(() => PieControlUi),
3265
3351
  multi: true,
3266
3352
  },
3267
- ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.pie'\"\r\n>\r\n <!-- Basic Chart Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"pieSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('radius')\"\r\n [ngModel]=\"config().radius\"\r\n (ngModelChange)=\"updateConfig({ radius: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('thickness')\"\r\n [ngModel]=\"config().thickness\"\r\n (ngModelChange)=\"updateConfig({ thickness: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('padAngle')\"\r\n [ngModel]=\"config().padAngle\"\r\n (ngModelChange)=\"updateConfig({ padAngle: $event })\"\r\n [min]=\"0\"\r\n [max]=\"20\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"50\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('centerX')\"\r\n [ngModel]=\"config().centerX\"\r\n (ngModelChange)=\"updateConfig({ centerX: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('centerY')\"\r\n [ngModel]=\"config().centerY\"\r\n (ngModelChange)=\"updateConfig({ centerY: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('startAngle')\"\r\n [ngModel]=\"config().startAngle\"\r\n (ngModelChange)=\"updateConfig({ startAngle: $event })\"\r\n [min]=\"0\"\r\n [max]=\"360\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('endAngle')\"\r\n [ngModel]=\"config().endAngle\"\r\n (ngModelChange)=\"updateConfig({ endAngle: $event })\"\r\n [min]=\"0\"\r\n [max]=\"360\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('roseType')\"\r\n [ngModel]=\"config().roseType\"\r\n (ngModelChange)=\"updateConfig({ roseType: $event })\"\r\n [options]=\"roseTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Legend Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"legendSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('useEnhancedLegend')\"\r\n [ngModel]=\"config().useEnhancedLegend\"\r\n (ngModelChange)=\"updateConfig({ useEnhancedLegend: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"config().legendPosition\"\r\n (ngModelChange)=\"updateConfig({ legendPosition: $event })\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendVerticalAlign')\"\r\n [ngModel]=\"config().legendVerticalAlign\"\r\n (ngModelChange)=\"updateConfig({ legendVerticalAlign: $event })\"\r\n [options]=\"legendVerticalAlignOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendOrientation')\"\r\n [ngModel]=\"config().legendOrientation\"\r\n (ngModelChange)=\"updateConfig({ legendOrientation: $event })\"\r\n [options]=\"legendOrientationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendType')\"\r\n [ngModel]=\"config().legendType\"\r\n (ngModelChange)=\"updateConfig({ legendType: $event })\"\r\n [options]=\"legendTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendFontSize')\"\r\n [ngModel]=\"config().legendFontSize\"\r\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('legendFontColor')\"\r\n [ngModel]=\"config().legendFontColor\"\r\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendIcon')\"\r\n [ngModel]=\"config().legendIcon\"\r\n (ngModelChange)=\"updateConfig({ legendIcon: $event })\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Label Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"labelSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"config().labelPosition\"\r\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFontSize')\"\r\n [ngModel]=\"config().labelFontSize\"\r\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('totalValueFontSize')\"\r\n [ngModel]=\"config().totalValueFontSize\"\r\n (ngModelChange)=\"updateConfig({ totalValueFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('labelFontColor')\"\r\n [ngModel]=\"config().labelFontColor\"\r\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFormatter')\"\r\n [ngModel]=\"config().labelFormatter\"\r\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\r\n [options]=\"labelFormatterOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('showLabelLine')\"\r\n [ngModel]=\"config().showLabelLine\"\r\n (ngModelChange)=\"updateConfig({ showLabelLine: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Tooltip Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"tooltipSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('tooltipTrigger')\"\r\n [ngModel]=\"config().tooltipTrigger\"\r\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\r\n [options]=\"tooltipTriggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBackgroundColor')\"\r\n [ngModel]=\"config().tooltipBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBorderColor')\"\r\n [ngModel]=\"config().tooltipBorderColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('tooltipBorderWidth')\"\r\n [ngModel]=\"config().tooltipBorderWidth\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\r\n [min]=\"0\"\r\n [max]=\"10\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Animation Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"animationSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('animation')\"\r\n [ngModel]=\"config().animation\"\r\n (ngModelChange)=\"updateConfig({ animation: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('animationDuration')\"\r\n [ngModel]=\"config().animationDuration\"\r\n (ngModelChange)=\"updateConfig({ animationDuration: $event })\"\r\n [min]=\"0\"\r\n [max]=\"5000\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('explode')\"\r\n [ngModel]=\"config().explode\"\r\n (ngModelChange)=\"updateConfig({ explode: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\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.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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3353
+ ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.pie'\"\r\n>\r\n <!-- Basic Chart Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"pieSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('radius')\"\r\n [ngModel]=\"config().radius\"\r\n (ngModelChange)=\"updateConfig({ radius: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('thickness')\"\r\n [ngModel]=\"config().thickness\"\r\n (ngModelChange)=\"updateConfig({ thickness: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('padAngle')\"\r\n [ngModel]=\"config().padAngle\"\r\n (ngModelChange)=\"updateConfig({ padAngle: $event })\"\r\n [min]=\"0\"\r\n [max]=\"20\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"50\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('centerX')\"\r\n [ngModel]=\"config().centerX\"\r\n (ngModelChange)=\"updateConfig({ centerX: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('centerY')\"\r\n [ngModel]=\"config().centerY\"\r\n (ngModelChange)=\"updateConfig({ centerY: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('startAngle')\"\r\n [ngModel]=\"config().startAngle\"\r\n (ngModelChange)=\"updateConfig({ startAngle: $event })\"\r\n [min]=\"0\"\r\n [max]=\"360\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('endAngle')\"\r\n [ngModel]=\"config().endAngle\"\r\n (ngModelChange)=\"updateConfig({ endAngle: $event })\"\r\n [min]=\"0\"\r\n [max]=\"360\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('roseType')\"\r\n [ngModel]=\"config().roseType\"\r\n (ngModelChange)=\"updateConfig({ roseType: $event })\"\r\n [options]=\"roseTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Legend Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"legendSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('useEnhancedLegend')\"\r\n [ngModel]=\"config().useEnhancedLegend\"\r\n (ngModelChange)=\"updateConfig({ useEnhancedLegend: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"config().legendPosition\"\r\n (ngModelChange)=\"updateConfig({ legendPosition: $event })\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendVerticalAlign')\"\r\n [ngModel]=\"config().legendVerticalAlign\"\r\n (ngModelChange)=\"updateConfig({ legendVerticalAlign: $event })\"\r\n [options]=\"legendVerticalAlignOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendOrientation')\"\r\n [ngModel]=\"config().legendOrientation\"\r\n (ngModelChange)=\"updateConfig({ legendOrientation: $event })\"\r\n [options]=\"legendOrientationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendType')\"\r\n [ngModel]=\"config().legendType\"\r\n (ngModelChange)=\"updateConfig({ legendType: $event })\"\r\n [options]=\"legendTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendFontSize')\"\r\n [ngModel]=\"config().legendFontSize\"\r\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('legendFontColor')\"\r\n [ngModel]=\"config().legendFontColor\"\r\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendIcon')\"\r\n [ngModel]=\"config().legendIcon\"\r\n (ngModelChange)=\"updateConfig({ legendIcon: $event })\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Label Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"labelSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"config().labelPosition\"\r\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFontSize')\"\r\n [ngModel]=\"config().labelFontSize\"\r\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('totalValueFontSize')\"\r\n [ngModel]=\"config().totalValueFontSize\"\r\n (ngModelChange)=\"updateConfig({ totalValueFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('labelFontColor')\"\r\n [ngModel]=\"config().labelFontColor\"\r\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFormatter')\"\r\n [ngModel]=\"config().labelFormatter\"\r\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\r\n [options]=\"labelFormatterOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('showLabelLine')\"\r\n [ngModel]=\"config().showLabelLine\"\r\n (ngModelChange)=\"updateConfig({ showLabelLine: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Tooltip Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"tooltipSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('tooltipTrigger')\"\r\n [ngModel]=\"config().tooltipTrigger\"\r\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\r\n [options]=\"tooltipTriggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBackgroundColor')\"\r\n [ngModel]=\"config().tooltipBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBorderColor')\"\r\n [ngModel]=\"config().tooltipBorderColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('tooltipBorderWidth')\"\r\n [ngModel]=\"config().tooltipBorderWidth\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\r\n [min]=\"0\"\r\n [max]=\"10\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Animation Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"animationSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('animation')\"\r\n [ngModel]=\"config().animation\"\r\n (ngModelChange)=\"updateConfig({ animation: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('animationDuration')\"\r\n [ngModel]=\"config().animationDuration\"\r\n (ngModelChange)=\"updateConfig({ animationDuration: $event })\"\r\n [min]=\"0\"\r\n [max]=\"5000\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('explode')\"\r\n [ngModel]=\"config().explode\"\r\n (ngModelChange)=\"updateConfig({ explode: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\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.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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3268
3354
  }
3269
3355
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PieControlUi, decorators: [{
3270
3356
  type: Component,
@@ -3392,7 +3478,7 @@ class BarControlUi {
3392
3478
  useExisting: forwardRef(() => BarControlUi),
3393
3479
  multi: true,
3394
3480
  },
3395
- ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.bar'\"\r\n>\r\n <!-- Bar Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"barSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('barWidth')\"\r\n [ngModel]=\"config().barWidth\"\r\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('barType')\"\r\n [ngModel]=\"config().barType\"\r\n (ngModelChange)=\"updateConfig({ barType: $event })\"\r\n [options]=\"barTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('isGrouped')\"\r\n [ngModel]=\"config().isGrouped\"\r\n (ngModelChange)=\"updateConfig({ isGrouped: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- X-Axis Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"xAxisSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('xAxisShow')\"\r\n [ngModel]=\"config().xAxisShow\"\r\n (ngModelChange)=\"updateConfig({ xAxisShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('xAxisFontSize')\"\r\n [ngModel]=\"config().xAxisFontSize\"\r\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('xAxisFontColor')\"\r\n [ngModel]=\"config().xAxisFontColor\"\r\n (ngModelChange)=\"updateConfig({ xAxisFontColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('xAxisLineColor')\"\r\n [ngModel]=\"config().xAxisLineColor\"\r\n (ngModelChange)=\"updateConfig({ xAxisLineColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Y-Axis Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"yAxisSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('yAxisShow')\"\r\n [ngModel]=\"config().yAxisShow\"\r\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n @if (config().yAxisShow) {\r\n <mt-select-field\r\n [label]=\"t('yAxisFormat')\"\r\n [ngModel]=\"config().yAxisFormat\"\r\n (ngModelChange)=\"onYAxisFormatChange($event)\"\r\n [options]=\"yAxisFormatOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n @if (config().yAxisFormat === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"config().showCurrency\"\r\n (ngModelChange)=\"updateConfig({ showCurrency: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n }\r\n }\r\n\r\n <mt-select-field\r\n [label]=\"t('yAxisFontSize')\"\r\n [ngModel]=\"config().yAxisFontSize\"\r\n (ngModelChange)=\"updateConfig({ yAxisFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('yAxisFontColor')\"\r\n [ngModel]=\"config().yAxisFontColor\"\r\n (ngModelChange)=\"updateConfig({ yAxisFontColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('yAxisLineColor')\"\r\n [ngModel]=\"config().yAxisLineColor\"\r\n (ngModelChange)=\"updateConfig({ yAxisLineColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Grid Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"gridSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('gridTop')\"\r\n [ngModel]=\"config().gridTop\"\r\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridBottom')\"\r\n [ngModel]=\"config().gridBottom\"\r\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridLeft')\"\r\n [ngModel]=\"config().gridLeft\"\r\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridRight')\"\r\n [ngModel]=\"config().gridRight\"\r\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Label Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"labelSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('labelShow')\"\r\n [ngModel]=\"config().labelShow\"\r\n (ngModelChange)=\"updateConfig({ labelShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"config().labelPosition\"\r\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFontSize')\"\r\n [ngModel]=\"config().labelFontSize\"\r\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('labelFontColor')\"\r\n [ngModel]=\"config().labelFontColor\"\r\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFormatter')\"\r\n [ngModel]=\"config().labelFormatter\"\r\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\r\n [options]=\"labelFormatterOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Tooltip Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"tooltipSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('tooltipShow')\"\r\n [ngModel]=\"config().tooltipShow\"\r\n (ngModelChange)=\"updateConfig({ tooltipShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('showValueOnlyInTooltip')\"\r\n [ngModel]=\"config().showValueOnlyInTooltip\"\r\n (ngModelChange)=\"updateConfig({ showValueOnlyInTooltip: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('maxCharsPerLine')\"\r\n [ngModel]=\"config().maxCharsPerLine\"\r\n (ngModelChange)=\"updateConfig({ maxCharsPerLine: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('tooltipTrigger')\"\r\n [ngModel]=\"config().tooltipTrigger\"\r\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\r\n [options]=\"tooltipTriggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBackgroundColor')\"\r\n [ngModel]=\"config().tooltipBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBorderColor')\"\r\n [ngModel]=\"config().tooltipBorderColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('tooltipBorderWidth')\"\r\n [ngModel]=\"config().tooltipBorderWidth\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\r\n [min]=\"0\"\r\n [max]=\"10\"\r\n />\r\n </div>\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.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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3481
+ ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.bar'\"\r\n>\r\n <!-- Bar Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"barSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('barWidth')\"\r\n [ngModel]=\"config().barWidth\"\r\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('barType')\"\r\n [ngModel]=\"config().barType\"\r\n (ngModelChange)=\"updateConfig({ barType: $event })\"\r\n [options]=\"barTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('isGrouped')\"\r\n [ngModel]=\"config().isGrouped\"\r\n (ngModelChange)=\"updateConfig({ isGrouped: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- X-Axis Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"xAxisSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('xAxisShow')\"\r\n [ngModel]=\"config().xAxisShow\"\r\n (ngModelChange)=\"updateConfig({ xAxisShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('xAxisFontSize')\"\r\n [ngModel]=\"config().xAxisFontSize\"\r\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('xAxisFontColor')\"\r\n [ngModel]=\"config().xAxisFontColor\"\r\n (ngModelChange)=\"updateConfig({ xAxisFontColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('xAxisLineColor')\"\r\n [ngModel]=\"config().xAxisLineColor\"\r\n (ngModelChange)=\"updateConfig({ xAxisLineColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Y-Axis Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"yAxisSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('yAxisShow')\"\r\n [ngModel]=\"config().yAxisShow\"\r\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n @if (config().yAxisShow) {\r\n <mt-select-field\r\n [label]=\"t('yAxisFormat')\"\r\n [ngModel]=\"config().yAxisFormat\"\r\n (ngModelChange)=\"onYAxisFormatChange($event)\"\r\n [options]=\"yAxisFormatOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n @if (config().yAxisFormat === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"config().showCurrency\"\r\n (ngModelChange)=\"updateConfig({ showCurrency: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n }\r\n }\r\n\r\n <mt-select-field\r\n [label]=\"t('yAxisFontSize')\"\r\n [ngModel]=\"config().yAxisFontSize\"\r\n (ngModelChange)=\"updateConfig({ yAxisFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('yAxisFontColor')\"\r\n [ngModel]=\"config().yAxisFontColor\"\r\n (ngModelChange)=\"updateConfig({ yAxisFontColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('yAxisLineColor')\"\r\n [ngModel]=\"config().yAxisLineColor\"\r\n (ngModelChange)=\"updateConfig({ yAxisLineColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Grid Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"gridSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('gridTop')\"\r\n [ngModel]=\"config().gridTop\"\r\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridBottom')\"\r\n [ngModel]=\"config().gridBottom\"\r\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridLeft')\"\r\n [ngModel]=\"config().gridLeft\"\r\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridRight')\"\r\n [ngModel]=\"config().gridRight\"\r\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Label Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"labelSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('labelShow')\"\r\n [ngModel]=\"config().labelShow\"\r\n (ngModelChange)=\"updateConfig({ labelShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"config().labelPosition\"\r\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFontSize')\"\r\n [ngModel]=\"config().labelFontSize\"\r\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('labelFontColor')\"\r\n [ngModel]=\"config().labelFontColor\"\r\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFormatter')\"\r\n [ngModel]=\"config().labelFormatter\"\r\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\r\n [options]=\"labelFormatterOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Tooltip Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"tooltipSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('tooltipShow')\"\r\n [ngModel]=\"config().tooltipShow\"\r\n (ngModelChange)=\"updateConfig({ tooltipShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('showValueOnlyInTooltip')\"\r\n [ngModel]=\"config().showValueOnlyInTooltip\"\r\n (ngModelChange)=\"updateConfig({ showValueOnlyInTooltip: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('maxCharsPerLine')\"\r\n [ngModel]=\"config().maxCharsPerLine\"\r\n (ngModelChange)=\"updateConfig({ maxCharsPerLine: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('tooltipTrigger')\"\r\n [ngModel]=\"config().tooltipTrigger\"\r\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\r\n [options]=\"tooltipTriggerOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBackgroundColor')\"\r\n [ngModel]=\"config().tooltipBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBorderColor')\"\r\n [ngModel]=\"config().tooltipBorderColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('tooltipBorderWidth')\"\r\n [ngModel]=\"config().tooltipBorderWidth\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\r\n [min]=\"0\"\r\n [max]=\"10\"\r\n />\r\n </div>\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.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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3396
3482
  }
3397
3483
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: BarControlUi, decorators: [{
3398
3484
  type: Component,
@@ -3503,7 +3589,7 @@ class StackBarControlUi {
3503
3589
  useExisting: forwardRef(() => StackBarControlUi),
3504
3590
  multi: true,
3505
3591
  },
3506
- ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.stackBar'\"\r\n>\r\n <!-- Bar Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"barSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('isStacked')\"\r\n [ngModel]=\"config().isStacked\"\r\n (ngModelChange)=\"updateConfig({ isStacked: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('hasLines')\"\r\n [ngModel]=\"config().hasLines\"\r\n (ngModelChange)=\"updateConfig({ hasLines: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('barType')\"\r\n [ngModel]=\"config().barType\"\r\n (ngModelChange)=\"updateConfig({ barType: $event })\"\r\n [options]=\"barTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('barWidth')\"\r\n [ngModel]=\"config().barWidth\"\r\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Grid Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"gridSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('gridLeft')\"\r\n [ngModel]=\"config().gridLeft\"\r\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridRight')\"\r\n [ngModel]=\"config().gridRight\"\r\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridTop')\"\r\n [ngModel]=\"config().gridTop\"\r\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridBottom')\"\r\n [ngModel]=\"config().gridBottom\"\r\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Axis Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"axisSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('yAxisShow')\"\r\n [ngModel]=\"config().yAxisShow\"\r\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('yAxisFormat')\"\r\n [ngModel]=\"config().yAxisFormat?.type\"\r\n (ngModelChange)=\"onYAxisFormatChange($event)\"\r\n [options]=\"yAxisFormatOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('xAxisLabelRotate')\"\r\n [ngModel]=\"config().xAxisLabelRotate\"\r\n (ngModelChange)=\"updateConfig({ xAxisLabelRotate: $event })\"\r\n [min]=\"-90\"\r\n [max]=\"90\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('xAxisFontSize')\"\r\n [ngModel]=\"config().xAxisFontSize\"\r\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Legend Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"legendSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('legendPositionY')\"\r\n [ngModel]=\"config().legendPositionY\"\r\n (ngModelChange)=\"updateConfig({ legendPositionY: $event })\"\r\n [options]=\"legendPositionYOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendPositionX')\"\r\n [ngModel]=\"config().legendPositionX\"\r\n (ngModelChange)=\"updateConfig({ legendPositionX: $event })\"\r\n [options]=\"legendPositionXOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendFontSize')\"\r\n [ngModel]=\"config().legendFontSize\"\r\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('legendFontColor')\"\r\n [ngModel]=\"config().legendFontColor\"\r\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Label Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"labelSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabel')\"\r\n [ngModel]=\"config().showLabel\"\r\n (ngModelChange)=\"updateConfig({ showLabel: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFontSize')\"\r\n [ngModel]=\"config().labelFontSize\"\r\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('labelFontColor')\"\r\n [ngModel]=\"config().labelFontColor\"\r\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Tooltip Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"tooltipSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBackgroundColor')\"\r\n [ngModel]=\"config().tooltipBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBorderColor')\"\r\n [ngModel]=\"config().tooltipBorderColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('tooltipBorderWidth')\"\r\n [ngModel]=\"config().tooltipBorderWidth\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\r\n [min]=\"0\"\r\n [max]=\"10\"\r\n />\r\n </div>\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.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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3592
+ ], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-5\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.stackBar'\"\r\n>\r\n <!-- Bar Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"barSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('isStacked')\"\r\n [ngModel]=\"config().isStacked\"\r\n (ngModelChange)=\"updateConfig({ isStacked: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-toggle-field\r\n [label]=\"t('hasLines')\"\r\n [ngModel]=\"config().hasLines\"\r\n (ngModelChange)=\"updateConfig({ hasLines: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('barType')\"\r\n [ngModel]=\"config().barType\"\r\n (ngModelChange)=\"updateConfig({ barType: $event })\"\r\n [options]=\"barTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('barWidth')\"\r\n [ngModel]=\"config().barWidth\"\r\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\r\n [min]=\"10\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"config().borderRadius\"\r\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Grid Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"gridSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-number-field\r\n [label]=\"t('gridLeft')\"\r\n [ngModel]=\"config().gridLeft\"\r\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridRight')\"\r\n [ngModel]=\"config().gridRight\"\r\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridTop')\"\r\n [ngModel]=\"config().gridTop\"\r\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('gridBottom')\"\r\n [ngModel]=\"config().gridBottom\"\r\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Axis Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"axisSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('yAxisShow')\"\r\n [ngModel]=\"config().yAxisShow\"\r\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('yAxisFormat')\"\r\n [ngModel]=\"config().yAxisFormat?.type\"\r\n (ngModelChange)=\"onYAxisFormatChange($event)\"\r\n [options]=\"yAxisFormatOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('xAxisLabelRotate')\"\r\n [ngModel]=\"config().xAxisLabelRotate\"\r\n (ngModelChange)=\"updateConfig({ xAxisLabelRotate: $event })\"\r\n [min]=\"-90\"\r\n [max]=\"90\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('xAxisFontSize')\"\r\n [ngModel]=\"config().xAxisFontSize\"\r\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Legend Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"legendSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('legendPositionY')\"\r\n [ngModel]=\"config().legendPositionY\"\r\n (ngModelChange)=\"updateConfig({ legendPositionY: $event })\"\r\n [options]=\"legendPositionYOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendPositionX')\"\r\n [ngModel]=\"config().legendPositionX\"\r\n (ngModelChange)=\"updateConfig({ legendPositionX: $event })\"\r\n [options]=\"legendPositionXOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('legendFontSize')\"\r\n [ngModel]=\"config().legendFontSize\"\r\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('legendFontColor')\"\r\n [ngModel]=\"config().legendFontColor\"\r\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Label Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"labelSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabel')\"\r\n [ngModel]=\"config().showLabel\"\r\n (ngModelChange)=\"updateConfig({ showLabel: $event })\"\r\n labelPosition=\"start\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('labelFontSize')\"\r\n [ngModel]=\"config().labelFontSize\"\r\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\r\n [options]=\"fontSizeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('labelFontColor')\"\r\n [ngModel]=\"config().labelFontColor\"\r\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Tooltip Settings -->\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\r\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\r\n {{ t(\"tooltipSettings\") }}\r\n </h4>\r\n\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBackgroundColor')\"\r\n [ngModel]=\"config().tooltipBackgroundColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\r\n />\r\n\r\n <mt-color-picker-field\r\n [label]=\"t('tooltipBorderColor')\"\r\n [ngModel]=\"config().tooltipBorderColor\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\r\n />\r\n\r\n <mt-number-field\r\n [label]=\"t('tooltipBorderWidth')\"\r\n [ngModel]=\"config().tooltipBorderWidth\"\r\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\r\n [min]=\"0\"\r\n [max]=\"10\"\r\n />\r\n </div>\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.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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
3507
3593
  }
3508
3594
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: StackBarControlUi, decorators: [{
3509
3595
  type: Component,
@@ -3547,15 +3633,41 @@ class ChartSettingsDrawer {
3547
3633
  if (configItem) {
3548
3634
  // Deep clone to avoid mutating original
3549
3635
  this.item.set(JSON.parse(JSON.stringify(configItem)));
3636
+ if (this.isLayoutComponent(configItem.config?.clientConfig?.componentName)) {
3637
+ this.activeTab.set('chartControls');
3638
+ }
3550
3639
  }
3551
3640
  }
3552
3641
  /** Active tab: 'display' or 'chartControls' */
3553
3642
  activeTab = signal('display', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
3554
- /** Tab options - always show Display, show Chart Controls only when a chart control UI exists */
3643
+ /** Layout widgets use quick controls only */
3644
+ showDisplayTab = computed(() => {
3645
+ const chartType = this.resolvedChartType();
3646
+ if (chartType?.category === 'layout')
3647
+ return false;
3648
+ const componentName = this.item()?.config?.clientConfig?.componentName;
3649
+ return !this.isLayoutComponent(componentName);
3650
+ }, ...(ngDevMode ? [{ debugName: "showDisplayTab" }] : []));
3651
+ isLayoutItem = computed(() => {
3652
+ const chartType = this.resolvedChartType();
3653
+ if (chartType?.category === 'layout')
3654
+ return true;
3655
+ const componentName = this.item()?.config?.clientConfig?.componentName;
3656
+ return this.isLayoutComponent(componentName);
3657
+ }, ...(ngDevMode ? [{ debugName: "isLayoutItem" }] : []));
3658
+ layoutComponentName = computed(() => {
3659
+ const componentName = this.item()?.config?.clientConfig?.componentName;
3660
+ if (componentName === 'header' || componentName === 'topbar') {
3661
+ return componentName;
3662
+ }
3663
+ return null;
3664
+ }, ...(ngDevMode ? [{ debugName: "layoutComponentName" }] : []));
3665
+ /** Tab options - hide Display for layout widgets, show Chart Controls when a chart control UI exists */
3555
3666
  tabOptions = computed(() => {
3556
- const tabs = [
3557
- { label: 'Display', value: 'display', icon: 'design.palette' },
3558
- ];
3667
+ const tabs = [];
3668
+ if (this.showDisplayTab()) {
3669
+ tabs.push({ label: 'Display', value: 'display', icon: 'design.palette' });
3670
+ }
3559
3671
  if (this.manageType() !== null) {
3560
3672
  tabs.push({
3561
3673
  label: 'Chart Controls',
@@ -3606,10 +3718,37 @@ class ChartSettingsDrawer {
3606
3718
  }
3607
3719
  return null;
3608
3720
  }, ...(ngDevMode ? [{ debugName: "manageType" }] : []));
3609
- /** Default config (full config for DefaultControlUi) */
3610
- defaultConfig = computed(() => {
3611
- return this.item()?.config || {};
3612
- }, ...(ngDevMode ? [{ debugName: "defaultConfig" }] : []));
3721
+ /** Default control config mapped from item config */
3722
+ defaultControlConfig = computed(() => {
3723
+ const clientConfig = this.item()?.config?.clientConfig;
3724
+ const componentName = clientConfig?.componentName;
3725
+ const styleConfig = clientConfig?.displayConfig?.StyleConfig ?? {};
3726
+ const configAsType = clientConfig?.configAsType ?? {};
3727
+ const cardStyleConfig = configAsType['cardStyleConfig'] ??
3728
+ {};
3729
+ const subtitleConfig = clientConfig?.['subtitle'];
3730
+ return {
3731
+ title: clientConfig?.title?.['en'] || clientConfig?.title?.['ar'] || '',
3732
+ titleFontSize: Number(styleConfig['font-size-title'] ??
3733
+ (componentName === 'header' ? 20 : 18)),
3734
+ titleColor: String(styleConfig['color'] || ''),
3735
+ showSubtitle: Boolean(configAsType['showSubtitle']),
3736
+ subtitle: typeof subtitleConfig === 'string'
3737
+ ? subtitleConfig
3738
+ : subtitleConfig?.['en'] || subtitleConfig?.['ar'] || '',
3739
+ subtitleFontSize: Number(configAsType['subtitleFontSize'] ?? 14),
3740
+ subtitleColor: String(configAsType['subtitleColor'] || ''),
3741
+ icon: String(configAsType['icon'] || ''),
3742
+ iconColor: String(styleConfig['iconColor'] || ''),
3743
+ iconBackgroundColor: String(styleConfig['iconBgColor'] || ''),
3744
+ backgroundColor: String(cardStyleConfig['backgroundColor'] ||
3745
+ styleConfig['background-color'] ||
3746
+ ''),
3747
+ borderColor: String(styleConfig['border-color'] || ''),
3748
+ borderRadius: Number(cardStyleConfig['borderRadius'] ?? 0),
3749
+ padding: Number(configAsType['padding'] ?? 16),
3750
+ };
3751
+ }, ...(ngDevMode ? [{ debugName: "defaultControlConfig" }] : []));
3613
3752
  /** Pie chart config - note: typo "Overried" matches old implementation */
3614
3753
  pieConfig = computed(() => {
3615
3754
  return this.item()?.config?.clientConfig?.['pieConfigOverried'] || {};
@@ -3629,12 +3768,56 @@ class ChartSettingsDrawer {
3629
3768
  /** Update default config */
3630
3769
  onDefaultConfigChange(config) {
3631
3770
  const currentItem = this.item();
3632
- if (currentItem) {
3633
- this.item.set({
3634
- ...currentItem,
3635
- config: { ...currentItem.config, ...config },
3636
- });
3637
- }
3771
+ const currentConfig = currentItem?.config;
3772
+ if (!currentItem || !currentConfig)
3773
+ return;
3774
+ const currentClientConfig = currentConfig.clientConfig ?? {};
3775
+ const currentStyleConfig = currentClientConfig.displayConfig?.StyleConfig ?? {};
3776
+ const currentConfigAsType = currentClientConfig.configAsType ?? {};
3777
+ const currentCardStyleConfig = currentConfigAsType['cardStyleConfig'] ?? {};
3778
+ this.item.set({
3779
+ ...currentItem,
3780
+ config: {
3781
+ ...currentConfig,
3782
+ clientConfig: {
3783
+ ...currentClientConfig,
3784
+ title: {
3785
+ ...currentClientConfig.title,
3786
+ en: config.title,
3787
+ ar: config.title,
3788
+ },
3789
+ subtitle: {
3790
+ en: config.subtitle,
3791
+ ar: config.subtitle,
3792
+ },
3793
+ displayConfig: {
3794
+ ...currentClientConfig.displayConfig,
3795
+ StyleConfig: {
3796
+ ...currentStyleConfig,
3797
+ color: config.titleColor,
3798
+ 'font-size-title': config.titleFontSize,
3799
+ 'background-color': config.backgroundColor,
3800
+ 'border-color': config.borderColor,
3801
+ iconColor: config.iconColor,
3802
+ iconBgColor: config.iconBackgroundColor,
3803
+ },
3804
+ },
3805
+ configAsType: {
3806
+ ...currentConfigAsType,
3807
+ icon: config.icon,
3808
+ showSubtitle: config.showSubtitle,
3809
+ subtitleFontSize: config.subtitleFontSize,
3810
+ subtitleColor: config.subtitleColor,
3811
+ padding: config.padding,
3812
+ cardStyleConfig: {
3813
+ ...currentCardStyleConfig,
3814
+ backgroundColor: config.backgroundColor,
3815
+ borderRadius: config.borderRadius,
3816
+ },
3817
+ },
3818
+ },
3819
+ },
3820
+ });
3638
3821
  }
3639
3822
  /** Update pie chart config - note: typo "Overried" matches old implementation */
3640
3823
  onPieConfigChange(config) {
@@ -3728,8 +3911,11 @@ class ChartSettingsDrawer {
3728
3911
  close() {
3729
3912
  this.dialogRef.close(null);
3730
3913
  }
3914
+ isLayoutComponent(componentName) {
3915
+ return componentName === 'header' || componentName === 'topbar';
3916
+ }
3731
3917
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ChartSettingsDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3732
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ChartSettingsDrawer, isStandalone: true, selector: "mt-chart-settings-drawer", ngImport: i0, template: "<div\r\n [class]=\"modal.contentClass + ' flex h-full min-h-0 flex-col p-0'\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\r\n class=\"sticky top-0 z-10 border-b border-surface-200 bg-surface-0 px-4 pb-3 pt-4\"\r\n >\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-3\">\r\n <!-- Display Tab -->\r\n <div [hidden]=\"activeTab() !== 'display'\" class=\"flex flex-col gap-3\">\r\n <mt-display-settings\r\n [config]=\"itemConfig()\"\r\n [chartType]=\"resolvedChartType()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <!-- Chart Controls Tab -->\r\n <div\r\n [hidden]=\"activeTab() !== 'chartControls'\"\r\n class=\"flex flex-col gap-3\"\r\n >\r\n @switch (manageType()) {\r\n @case (\"default\") {\r\n <mt-default-control-ui\r\n [ngModel]=\"defaultConfig()\"\r\n (ngModelChange)=\"onDefaultConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"pie\") {\r\n <mt-pie-control-ui\r\n [ngModel]=\"pieConfig()\"\r\n (ngModelChange)=\"onPieConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"bar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"barConfig()\"\r\n (ngModelChange)=\"onBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"stackBar\") {\r\n <mt-stack-bar-control-ui\r\n [ngModel]=\"stackBarConfig()\"\r\n (ngModelChange)=\"onStackBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"snapshotBar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"snapshotBarConfig()\"\r\n (ngModelChange)=\"onSnapshotBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @default {\r\n <div class=\"p-4 text-center text-muted-color\">\r\n {{ t(\"noSettingsAvailable\") }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div\r\n [class]=\"\r\n modal.footerClass +\r\n ' border-t border-surface-200 bg-surface-0 px-4 py-3'\r\n \"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <mt-button [label]=\"t('apply')\" icon=\"general.check\" (onClick)=\"apply()\" />\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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DisplaySettings, selector: "mt-display-settings", inputs: ["config", "chartType", "availableProperties", "selectedProperties", "lookups"], outputs: ["clientConfigChange"] }, { kind: "component", type: DefaultControlUi, selector: "mt-default-control-ui" }, { kind: "component", type: PieControlUi, selector: "mt-pie-control-ui" }, { kind: "component", type: BarControlUi, selector: "mt-bar-control-ui" }, { kind: "component", type: StackBarControlUi, selector: "mt-stack-bar-control-ui" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3918
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ChartSettingsDrawer, isStandalone: true, selector: "mt-chart-settings-drawer", ngImport: i0, template: "<div\r\n [class]=\"modal.contentClass + ' flex h-full min-h-0 flex-col p-0'\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\r\n class=\"sticky top-0 z-10 border-b border-surface-200 bg-surface-0 px-4 pb-3 pt-4\"\r\n >\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-3\">\r\n @if (showDisplayTab()) {\r\n <!-- Display Tab -->\r\n <div [hidden]=\"activeTab() !== 'display'\" class=\"flex flex-col gap-3\">\r\n <mt-display-settings\r\n [config]=\"itemConfig()\"\r\n [chartType]=\"resolvedChartType()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Chart Controls Tab -->\r\n <div [hidden]=\"activeTab() !== 'chartControls'\" class=\"flex flex-col gap-3\">\r\n @switch (manageType()) {\r\n @case (\"default\") {\r\n <mt-default-control-ui\r\n [ngModel]=\"defaultControlConfig()\"\r\n [showIconSettings]=\"isLayoutItem()\"\r\n [layoutComponent]=\"layoutComponentName()\"\r\n (ngModelChange)=\"onDefaultConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"pie\") {\r\n <mt-pie-control-ui\r\n [ngModel]=\"pieConfig()\"\r\n (ngModelChange)=\"onPieConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"bar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"barConfig()\"\r\n (ngModelChange)=\"onBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"stackBar\") {\r\n <mt-stack-bar-control-ui\r\n [ngModel]=\"stackBarConfig()\"\r\n (ngModelChange)=\"onStackBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"snapshotBar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"snapshotBarConfig()\"\r\n (ngModelChange)=\"onSnapshotBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @default {\r\n <div class=\"p-4 text-center text-muted-color\">\r\n {{ t(\"noSettingsAvailable\") }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div\r\n [class]=\"\r\n modal.footerClass + ' border-t border-surface-200 bg-surface-0 px-4 py-3'\r\n \"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <mt-button [label]=\"t('apply')\" icon=\"general.check\" (onClick)=\"apply()\" />\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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DisplaySettings, selector: "mt-display-settings", inputs: ["config", "chartType", "availableProperties", "selectedProperties", "lookups"], outputs: ["clientConfigChange"] }, { kind: "component", type: DefaultControlUi, selector: "mt-default-control-ui", inputs: ["showIconSettings", "layoutComponent"] }, { kind: "component", type: PieControlUi, selector: "mt-pie-control-ui" }, { kind: "component", type: BarControlUi, selector: "mt-bar-control-ui" }, { kind: "component", type: StackBarControlUi, selector: "mt-stack-bar-control-ui" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3733
3919
  }
3734
3920
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ChartSettingsDrawer, decorators: [{
3735
3921
  type: Component,
@@ -3744,7 +3930,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
3744
3930
  PieControlUi,
3745
3931
  BarControlUi,
3746
3932
  StackBarControlUi,
3747
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\r\n [class]=\"modal.contentClass + ' flex h-full min-h-0 flex-col p-0'\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\r\n class=\"sticky top-0 z-10 border-b border-surface-200 bg-surface-0 px-4 pb-3 pt-4\"\r\n >\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-3\">\r\n <!-- Display Tab -->\r\n <div [hidden]=\"activeTab() !== 'display'\" class=\"flex flex-col gap-3\">\r\n <mt-display-settings\r\n [config]=\"itemConfig()\"\r\n [chartType]=\"resolvedChartType()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <!-- Chart Controls Tab -->\r\n <div\r\n [hidden]=\"activeTab() !== 'chartControls'\"\r\n class=\"flex flex-col gap-3\"\r\n >\r\n @switch (manageType()) {\r\n @case (\"default\") {\r\n <mt-default-control-ui\r\n [ngModel]=\"defaultConfig()\"\r\n (ngModelChange)=\"onDefaultConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"pie\") {\r\n <mt-pie-control-ui\r\n [ngModel]=\"pieConfig()\"\r\n (ngModelChange)=\"onPieConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"bar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"barConfig()\"\r\n (ngModelChange)=\"onBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"stackBar\") {\r\n <mt-stack-bar-control-ui\r\n [ngModel]=\"stackBarConfig()\"\r\n (ngModelChange)=\"onStackBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"snapshotBar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"snapshotBarConfig()\"\r\n (ngModelChange)=\"onSnapshotBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @default {\r\n <div class=\"p-4 text-center text-muted-color\">\r\n {{ t(\"noSettingsAvailable\") }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div\r\n [class]=\"\r\n modal.footerClass +\r\n ' border-t border-surface-200 bg-surface-0 px-4 py-3'\r\n \"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <mt-button [label]=\"t('apply')\" icon=\"general.check\" (onClick)=\"apply()\" />\r\n</div>\r\n" }]
3933
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\r\n [class]=\"modal.contentClass + ' flex h-full min-h-0 flex-col p-0'\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\r\n class=\"sticky top-0 z-10 border-b border-surface-200 bg-surface-0 px-4 pb-3 pt-4\"\r\n >\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-3\">\r\n @if (showDisplayTab()) {\r\n <!-- Display Tab -->\r\n <div [hidden]=\"activeTab() !== 'display'\" class=\"flex flex-col gap-3\">\r\n <mt-display-settings\r\n [config]=\"itemConfig()\"\r\n [chartType]=\"resolvedChartType()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Chart Controls Tab -->\r\n <div [hidden]=\"activeTab() !== 'chartControls'\" class=\"flex flex-col gap-3\">\r\n @switch (manageType()) {\r\n @case (\"default\") {\r\n <mt-default-control-ui\r\n [ngModel]=\"defaultControlConfig()\"\r\n [showIconSettings]=\"isLayoutItem()\"\r\n [layoutComponent]=\"layoutComponentName()\"\r\n (ngModelChange)=\"onDefaultConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"pie\") {\r\n <mt-pie-control-ui\r\n [ngModel]=\"pieConfig()\"\r\n (ngModelChange)=\"onPieConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"bar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"barConfig()\"\r\n (ngModelChange)=\"onBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"stackBar\") {\r\n <mt-stack-bar-control-ui\r\n [ngModel]=\"stackBarConfig()\"\r\n (ngModelChange)=\"onStackBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"snapshotBar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"snapshotBarConfig()\"\r\n (ngModelChange)=\"onSnapshotBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @default {\r\n <div class=\"p-4 text-center text-muted-color\">\r\n {{ t(\"noSettingsAvailable\") }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div\r\n [class]=\"\r\n modal.footerClass + ' border-t border-surface-200 bg-surface-0 px-4 py-3'\r\n \"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <mt-button [label]=\"t('apply')\" icon=\"general.check\" (onClick)=\"apply()\" />\r\n</div>\r\n" }]
3748
3934
  }], ctorParameters: () => [] });
3749
3935
 
3750
3936
  /**
@@ -3882,10 +4068,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
3882
4068
  CommonModule,
3883
4069
  FormsModule,
3884
4070
  TranslocoDirective,
3885
- Button,
3886
4071
  TextField,
3887
- SelectField,
3888
- CheckboxField,
3889
4072
  Card,
3890
4073
  TooltipModule,
3891
4074
  Icon,
@@ -4687,7 +4870,7 @@ class SelectionConfiguration {
4687
4870
  useExisting: forwardRef(() => SelectionConfiguration),
4688
4871
  multi: true,
4689
4872
  },
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 });
4873
+ ], 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
4874
  }
4692
4875
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SelectionConfiguration, decorators: [{
4693
4876
  type: Component,
@@ -4698,12 +4881,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
4698
4881
  TranslocoDirective,
4699
4882
  Button,
4700
4883
  SelectField,
4701
- TextField,
4702
4884
  NumberField,
4703
4885
  TextareaField,
4704
4886
  FilterValueField,
4705
4887
  Card,
4706
- Tooltip$1,
4888
+ Tooltip,
4707
4889
  Skeleton,
4708
4890
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
4709
4891
  {
@@ -5010,7 +5192,7 @@ class SourceLinkConfiguration {
5010
5192
  useExisting: forwardRef(() => SourceLinkConfiguration),
5011
5193
  multi: true,
5012
5194
  },
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 });
5195
+ ], 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", "inputId", "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
5196
  }
5015
5197
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SourceLinkConfiguration, decorators: [{
5016
5198
  type: Component,
@@ -5024,7 +5206,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5024
5206
  ToggleField,
5025
5207
  Card,
5026
5208
  Tabs,
5027
- Tooltip$1,
5209
+ Tooltip,
5028
5210
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5029
5211
  {
5030
5212
  provide: NG_VALUE_ACCESSOR,
@@ -5114,7 +5296,7 @@ class CustomApiConfiguration {
5114
5296
  useExisting: forwardRef(() => CustomApiConfiguration),
5115
5297
  multi: true,
5116
5298
  },
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 });
5299
+ ], 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
5300
  }
5119
5301
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CustomApiConfiguration, decorators: [{
5120
5302
  type: Component,
@@ -5131,7 +5313,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5131
5313
  useExisting: forwardRef(() => CustomApiConfiguration),
5132
5314
  multi: true,
5133
5315
  },
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" }]
5316
+ ], 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
5317
  }] });
5136
5318
 
5137
5319
  /**
@@ -5408,7 +5590,7 @@ class GeneralQuery {
5408
5590
  useExisting: forwardRef(() => GeneralQuery),
5409
5591
  multi: true,
5410
5592
  },
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 });
5593
+ ], 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", "inputId", "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
5594
  }
5413
5595
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: GeneralQuery, decorators: [{
5414
5596
  type: Component,
@@ -5423,8 +5605,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5423
5605
  ToggleField,
5424
5606
  ColorPickerField,
5425
5607
  MultiSelectField,
5426
- Card,
5427
- Tooltip$1,
5608
+ Tooltip,
5428
5609
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5429
5610
  {
5430
5611
  provide: NG_VALUE_ACCESSOR,
@@ -5566,7 +5747,7 @@ class TableQuery {
5566
5747
  useExisting: forwardRef(() => TableQuery),
5567
5748
  multi: true,
5568
5749
  },
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 });
5750
+ ], 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
5751
  }
5571
5752
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TableQuery, decorators: [{
5572
5753
  type: Component,
@@ -5579,7 +5760,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5579
5760
  SelectField,
5580
5761
  MultiSelectField,
5581
5762
  Card,
5582
- Tooltip$1,
5763
+ Tooltip,
5583
5764
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5584
5765
  {
5585
5766
  provide: NG_VALUE_ACCESSOR,
@@ -5667,7 +5848,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5667
5848
  TranslocoDirective,
5668
5849
  SelectField,
5669
5850
  MultiSelectField,
5670
- Card,
5671
5851
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5672
5852
  {
5673
5853
  provide: NG_VALUE_ACCESSOR,
@@ -5738,13 +5918,7 @@ class PropertiesQuery {
5738
5918
  }
5739
5919
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesQuery, decorators: [{
5740
5920
  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: [
5921
+ args: [{ selector: 'mt-properties-query', standalone: true, imports: [CommonModule, FormsModule, TranslocoDirective, MultiSelectField], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5748
5922
  {
5749
5923
  provide: NG_VALUE_ACCESSOR,
5750
5924
  useExisting: forwardRef(() => PropertiesQuery),
@@ -5828,7 +6002,7 @@ class SnapshotQuery {
5828
6002
  useExisting: forwardRef(() => SnapshotQuery),
5829
6003
  multi: true,
5830
6004
  },
5831
- ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <!-- Level ID -->\r\n <mt-text-field\r\n [label]=\"t('levelId')\"\r\n [placeholder]=\"t('enterLevelId')\"\r\n [ngModel]=\"query().levelId\"\r\n (ngModelChange)=\"updateField('levelId', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n\r\n <!-- Time Frame -->\r\n <mt-select-field\r\n [label]=\"t('timeFrame')\"\r\n [options]=\"timeFrameOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectTimeFrame')\"\r\n [ngModel]=\"query().timeFrame\"\r\n (ngModelChange)=\"updateField('timeFrame', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n\r\n <!-- Year -->\r\n <mt-select-field\r\n [label]=\"t('year')\"\r\n [options]=\"yearOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectYear')\"\r\n [ngModel]=\"query().year\"\r\n (ngModelChange)=\"updateField('year', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n\r\n <!-- Get Average Per Period -->\r\n <div class=\"flex items-end pb-2\">\r\n <mt-toggle-field\r\n [label]=\"t('getAveragePerPeriod')\"\r\n [ngModel]=\"query().getAveragePerPeriod\"\r\n (ngModelChange)=\"updateField('getAveragePerPeriod', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n </div>\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('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 [filter]=\"true\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [ngModel]=\"query().selectedProperties\"\r\n (ngModelChange)=\"updateField('selectedProperties', $event)\"\r\n [disabled]=\"disabled\"\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.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: 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: 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6005
+ ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <!-- Level ID -->\r\n <mt-text-field\r\n [label]=\"t('levelId')\"\r\n [placeholder]=\"t('enterLevelId')\"\r\n [ngModel]=\"query().levelId\"\r\n (ngModelChange)=\"updateField('levelId', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n\r\n <!-- Time Frame -->\r\n <mt-select-field\r\n [label]=\"t('timeFrame')\"\r\n [options]=\"timeFrameOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectTimeFrame')\"\r\n [ngModel]=\"query().timeFrame\"\r\n (ngModelChange)=\"updateField('timeFrame', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n\r\n <!-- Year -->\r\n <mt-select-field\r\n [label]=\"t('year')\"\r\n [options]=\"yearOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectYear')\"\r\n [ngModel]=\"query().year\"\r\n (ngModelChange)=\"updateField('year', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n\r\n <!-- Get Average Per Period -->\r\n <div class=\"flex items-end pb-2\">\r\n <mt-toggle-field\r\n [label]=\"t('getAveragePerPeriod')\"\r\n [ngModel]=\"query().getAveragePerPeriod\"\r\n (ngModelChange)=\"updateField('getAveragePerPeriod', $event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n </div>\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('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 [filter]=\"true\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [ngModel]=\"query().selectedProperties\"\r\n (ngModelChange)=\"updateField('selectedProperties', $event)\"\r\n [disabled]=\"disabled\"\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.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: 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: 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", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5832
6006
  }
5833
6007
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SnapshotQuery, decorators: [{
5834
6008
  type: Component,
@@ -5840,7 +6014,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5840
6014
  MultiSelectField,
5841
6015
  TextField,
5842
6016
  ToggleField,
5843
- Card,
5844
6017
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5845
6018
  {
5846
6019
  provide: NG_VALUE_ACCESSOR,
@@ -5924,7 +6097,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
5924
6097
  TranslocoDirective,
5925
6098
  SelectField,
5926
6099
  MultiSelectField,
5927
- Card,
5928
6100
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
5929
6101
  {
5930
6102
  provide: NG_VALUE_ACCESSOR,
@@ -6015,7 +6187,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
6015
6187
  TranslocoDirective,
6016
6188
  SelectField,
6017
6189
  TextField,
6018
- Card,
6019
6190
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
6020
6191
  {
6021
6192
  provide: NG_VALUE_ACCESSOR,
@@ -6458,7 +6629,7 @@ class DataSourceSettings {
6458
6629
  return chartType.componentName || '';
6459
6630
  }
6460
6631
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DataSourceSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
6461
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DataSourceSettings, isStandalone: true, selector: "mt-data-source-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { serviceConfigChange: "serviceConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Data Source Type Tabs (hidden for layout, snapshot, phaseGate types) -->\r\n @if (!hideSelectionConfig()) {\r\n <mt-tabs\r\n [options]=\"tabOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"id\"\r\n [active]=\"activeTab()\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n }\r\n\r\n <!-- Custom API Configuration Tab -->\r\n @if (!hideSelectionConfig()) {\r\n <div [hidden]=\"activeTab() !== 'customApi'\">\r\n <mt-custom-api-configuration\r\n [ngModel]=\"customApi()\"\r\n (ngModelChange)=\"onCustomApiChange($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Selection Configuration Tab -->\r\n <div [hidden]=\"activeTab() !== 'selection'\">\r\n <!-- Selection Configuration (hidden for layout, snapshot, phaseGate types) -->\r\n @if (!hideSelectionConfig()) {\r\n <mt-selection-configuration\r\n [modulesProperties]=\"modulesProperties()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [ngModel]=\"selections()\"\r\n (ngModelChange)=\"onSelectionsChange($event)\"\r\n (moduleChange)=\"onModuleChange($event)\"\r\n />\r\n\r\n <!-- Source Link Configuration (shown when multiple selections) -->\r\n @if (showSourceLinks()) {\r\n <mt-source-link-configuration\r\n [selectionModules]=\"selectionModules()\"\r\n [ngModel]=\"sourceLinks()\"\r\n (ngModelChange)=\"onSourceLinksChange($event)\"\r\n />\r\n }\r\n }\r\n\r\n <!-- Loading Skeleton for Query Configuration -->\r\n @if (loadingProperties()) {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton for field labels and inputs -->\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"120px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"grid grid-cols-2 gap-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"90px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"140px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <!-- Query Configuration based on chart type -->\r\n @switch (queryComponentType()) {\r\n @case (\"general\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"mb-4 flex items-center\">\r\n <mt-toggle-field\r\n [label]=\"t('isNormalized')\"\r\n [ngModel]=\"isNormalized()\"\r\n (ngModelChange)=\"onIsNormalizedChange($event)\"\r\n />\r\n </div>\r\n <mt-general-query\r\n [chartType]=\"getChartTypeId()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"table\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <!-- Group By Multiple (for non-report table views) -->\r\n @if (showGroupByMultiple()) {\r\n <div class=\"mb-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('groupByMultiple')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectGroupByProperties')\"\r\n [filter]=\"true\"\r\n [ngModel]=\"groupByMultiple()\"\r\n (ngModelChange)=\"onGroupByMultipleChange($event)\"\r\n />\r\n </div>\r\n }\r\n <mt-table-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTableQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timeline\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-timeline-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTimelineQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timelineMultiLevel\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-layers-three-01 text-3xl mb-2 block\"></i>\r\n <p>{{ t(\"timelineMultiLevelQueryPlaceholder\") }}</p>\r\n <p class=\"text-sm mt-2\">{{ t(\"comingSoon\") }}</p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"map\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-map-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onMapQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"splitter\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-splitter-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSplitterQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"properties\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-properties-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onPropertiesQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"snapshot\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-snapshot-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSnapshotQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"phaseGate\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-git-branch-01 text-3xl mb-2 block\"></i>\r\n <p>{{ t(\"phaseGateQueryPlaceholder\") }}</p>\r\n <p class=\"text-sm mt-2\">{{ t(\"comingSoon\") }}</p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"repeater\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('selectDashboard')\"\r\n [options]=\"availableDashboards()\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectDashboardPlaceholder')\"\r\n [ngModel]=\"repeaterDashboardId()\"\r\n (ngModelChange)=\"onRepeaterDashboardChange($event)\"\r\n />\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"repeaterDescription\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"none\") {\r\n <!-- No query configuration needed for layout components -->\r\n }\r\n }\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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { 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: 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: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: SelectionConfiguration, selector: "mt-selection-configuration", inputs: ["modulesProperties", "propertiesFlat"], outputs: ["moduleChange"] }, { kind: "component", type: SourceLinkConfiguration, selector: "mt-source-link-configuration", inputs: ["selectionModules"] }, { kind: "component", type: CustomApiConfiguration, selector: "mt-custom-api-configuration" }, { kind: "component", type: GeneralQuery, selector: "mt-general-query", inputs: ["chartType", "propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TableQuery, selector: "mt-table-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TimelineQuery, selector: "mt-timeline-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: PropertiesQuery, selector: "mt-properties-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SnapshotQuery, selector: "mt-snapshot-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: MapQuery, selector: "mt-map-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SplitterQuery, selector: "mt-splitter-query", inputs: ["propertiesFlat", "propertiesGrouped"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6632
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DataSourceSettings, isStandalone: true, selector: "mt-data-source-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { serviceConfigChange: "serviceConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Data Source Type Tabs (hidden for layout, snapshot, phaseGate types) -->\r\n @if (!hideSelectionConfig()) {\r\n <mt-tabs\r\n [options]=\"tabOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"id\"\r\n [active]=\"activeTab()\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n }\r\n\r\n <!-- Custom API Configuration Tab -->\r\n @if (!hideSelectionConfig()) {\r\n <div [hidden]=\"activeTab() !== 'customApi'\">\r\n <mt-custom-api-configuration\r\n [ngModel]=\"customApi()\"\r\n (ngModelChange)=\"onCustomApiChange($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Selection Configuration Tab -->\r\n <div [hidden]=\"activeTab() !== 'selection'\">\r\n <!-- Selection Configuration (hidden for layout, snapshot, phaseGate types) -->\r\n @if (!hideSelectionConfig()) {\r\n <mt-selection-configuration\r\n [modulesProperties]=\"modulesProperties()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [ngModel]=\"selections()\"\r\n (ngModelChange)=\"onSelectionsChange($event)\"\r\n (moduleChange)=\"onModuleChange($event)\"\r\n />\r\n\r\n <!-- Source Link Configuration (shown when multiple selections) -->\r\n @if (showSourceLinks()) {\r\n <mt-source-link-configuration\r\n [selectionModules]=\"selectionModules()\"\r\n [ngModel]=\"sourceLinks()\"\r\n (ngModelChange)=\"onSourceLinksChange($event)\"\r\n />\r\n }\r\n }\r\n\r\n <!-- Loading Skeleton for Query Configuration -->\r\n @if (loadingProperties()) {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton for field labels and inputs -->\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"120px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"grid grid-cols-2 gap-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"90px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"140px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <!-- Query Configuration based on chart type -->\r\n @switch (queryComponentType()) {\r\n @case (\"general\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"mb-4 flex items-center\">\r\n <mt-toggle-field\r\n [label]=\"t('isNormalized')\"\r\n [ngModel]=\"isNormalized()\"\r\n (ngModelChange)=\"onIsNormalizedChange($event)\"\r\n />\r\n </div>\r\n <mt-general-query\r\n [chartType]=\"getChartTypeId()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"table\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <!-- Group By Multiple (for non-report table views) -->\r\n @if (showGroupByMultiple()) {\r\n <div class=\"mb-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('groupByMultiple')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectGroupByProperties')\"\r\n [filter]=\"true\"\r\n [ngModel]=\"groupByMultiple()\"\r\n (ngModelChange)=\"onGroupByMultipleChange($event)\"\r\n />\r\n </div>\r\n }\r\n <mt-table-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTableQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timeline\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-timeline-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTimelineQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timelineMultiLevel\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-layers-three-01 text-3xl mb-2 block\"></i>\r\n <p>{{ t(\"timelineMultiLevelQueryPlaceholder\") }}</p>\r\n <p class=\"text-sm mt-2\">{{ t(\"comingSoon\") }}</p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"map\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-map-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onMapQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"splitter\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-splitter-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSplitterQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"properties\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-properties-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onPropertiesQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"snapshot\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-snapshot-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSnapshotQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"phaseGate\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-git-branch-01 text-3xl mb-2 block\"></i>\r\n <p>{{ t(\"phaseGateQueryPlaceholder\") }}</p>\r\n <p class=\"text-sm mt-2\">{{ t(\"comingSoon\") }}</p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"repeater\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('selectDashboard')\"\r\n [options]=\"availableDashboards()\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectDashboardPlaceholder')\"\r\n [ngModel]=\"repeaterDashboardId()\"\r\n (ngModelChange)=\"onRepeaterDashboardChange($event)\"\r\n />\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"repeaterDescription\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"none\") {\r\n <!-- No query configuration needed for layout components -->\r\n }\r\n }\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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { 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", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], 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: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: SelectionConfiguration, selector: "mt-selection-configuration", inputs: ["modulesProperties", "propertiesFlat"], outputs: ["moduleChange"] }, { kind: "component", type: SourceLinkConfiguration, selector: "mt-source-link-configuration", inputs: ["selectionModules"] }, { kind: "component", type: CustomApiConfiguration, selector: "mt-custom-api-configuration" }, { kind: "component", type: GeneralQuery, selector: "mt-general-query", inputs: ["chartType", "propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TableQuery, selector: "mt-table-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TimelineQuery, selector: "mt-timeline-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: PropertiesQuery, selector: "mt-properties-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SnapshotQuery, selector: "mt-snapshot-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: MapQuery, selector: "mt-map-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SplitterQuery, selector: "mt-splitter-query", inputs: ["propertiesFlat", "propertiesGrouped"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6462
6633
  }
6463
6634
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DataSourceSettings, decorators: [{
6464
6635
  type: Component,
@@ -6468,11 +6639,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
6468
6639
  ReactiveFormsModule,
6469
6640
  TranslocoDirective,
6470
6641
  Skeleton,
6471
- Button,
6472
6642
  SelectField,
6473
6643
  ToggleField,
6474
6644
  MultiSelectField,
6475
- TextField,
6476
6645
  Card,
6477
6646
  Tabs,
6478
6647
  SelectionConfiguration,
@@ -6777,18 +6946,17 @@ class ActionsSettings {
6777
6946
  return index;
6778
6947
  }
6779
6948
  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 });
6949
+ 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
6950
  }
6782
6951
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ActionsSettings, decorators: [{
6783
6952
  type: Component,
6784
6953
  args: [{ selector: 'mt-actions-settings', standalone: true, imports: [
6785
6954
  FormsModule,
6786
6955
  TranslocoDirective,
6787
- Tooltip$1,
6956
+ Tooltip,
6788
6957
  Button,
6789
6958
  TextField,
6790
6959
  SelectField,
6791
- ToggleField,
6792
6960
  Card,
6793
6961
  Icon,
6794
6962
  ], 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" }]
@@ -15229,9 +15397,8 @@ class ActionService {
15229
15397
  */
15230
15398
  showDialog(action, data, config) {
15231
15399
  const actionData = this.handleActionsConfig(action.config, data, config);
15232
- debugger;
15233
15400
  // Dynamically import DashboardDialogComponent to avoid circular dependency
15234
- import('./masterteam-dashboard-builder-dashboard-dialog.component-CF1Lnyxf.mjs').then(({ DashboardDialogComponent }) => {
15401
+ import('./masterteam-dashboard-builder-dashboard-dialog.component-CMNlOHiK.mjs').then(({ DashboardDialogComponent }) => {
15235
15402
  // Open dialog using ModalService
15236
15403
  this.modalService.openModal(DashboardDialogComponent, 'dialog', {
15237
15404
  header: config.clientConfig?.title?.['en'] || '',
@@ -15476,7 +15643,7 @@ class CardContentComponent {
15476
15643
  }
15477
15644
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CardContentComponent, decorators: [{
15478
15645
  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"] }]
15646
+ 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
15647
  }], 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
15648
 
15482
15649
  /**
@@ -16326,11 +16493,11 @@ class CardInfoComponent {
16326
16493
  <i class="pi pi-info-circle"></i>
16327
16494
  </span>
16328
16495
  }
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 });
16496
+ `, 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
16497
  }
16331
16498
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CardInfoComponent, decorators: [{
16332
16499
  type: Component,
16333
- args: [{ selector: 'mt-card-info', standalone: true, imports: [CommonModule, Tooltip], template: `
16500
+ args: [{ selector: 'mt-card-info', standalone: true, imports: [CommonModule, Tooltip$1], template: `
16334
16501
  @if (showInfo()) {
16335
16502
  <span
16336
16503
  class="card-info-icon"
@@ -17039,7 +17206,7 @@ class EntityInfoComponent {
17039
17206
  }
17040
17207
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityInfoComponent, decorators: [{
17041
17208
  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"] }]
17209
+ 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
17210
  }], 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
17211
 
17045
17212
  /**
@@ -17714,6 +17881,10 @@ class HeaderCardComponent {
17714
17881
  cardStyleConfig = computed(() => {
17715
17882
  return (this.configurationItem()?.clientConfig?.configAsType?.['cardStyleConfig'] || {});
17716
17883
  }, ...(ngDevMode ? [{ debugName: "cardStyleConfig" }] : []));
17884
+ /** Config as type */
17885
+ configAsType = computed(() => {
17886
+ return this.configurationItem()?.clientConfig?.configAsType || {};
17887
+ }, ...(ngDevMode ? [{ debugName: "configAsType" }] : []));
17717
17888
  /** Cols from dimensions */
17718
17889
  cols = computed(() => {
17719
17890
  return (this.configurationItem()?.clientConfig?.displayConfig?.['dimensions']?.['cols'] || 36);
@@ -17756,6 +17927,22 @@ class HeaderCardComponent {
17756
17927
  iconBgColor = computed(() => {
17757
17928
  return this.styleConfig()?.['iconBgColor'] || 'rgba(76, 175, 80, 0.1)';
17758
17929
  }, ...(ngDevMode ? [{ debugName: "iconBgColor" }] : []));
17930
+ /** Inner card padding */
17931
+ padding = computed(() => {
17932
+ return Number(this.configAsType()['padding'] ?? 16);
17933
+ }, ...(ngDevMode ? [{ debugName: "padding" }] : []));
17934
+ /** Quick border color */
17935
+ borderColor = computed(() => {
17936
+ return String(this.styleConfig()?.['border-color'] || '');
17937
+ }, ...(ngDevMode ? [{ debugName: "borderColor" }] : []));
17938
+ /** Whether explicit side borders are configured */
17939
+ hasExplicitSideBorders = computed(() => {
17940
+ const style = this.styleConfig();
17941
+ return Boolean(style?.['border-top-show'] ||
17942
+ style?.['border-right-show'] ||
17943
+ style?.['border-bottom-show'] ||
17944
+ style?.['border-left-show']);
17945
+ }, ...(ngDevMode ? [{ debugName: "hasExplicitSideBorders" }] : []));
17759
17946
  /** Font size for title */
17760
17947
  fontSizeTitle = computed(() => {
17761
17948
  const size = this.styleConfig()?.['font-size-title'];
@@ -17806,8 +17993,14 @@ class HeaderCardComponent {
17806
17993
  if (config?.shadows) {
17807
17994
  styles['box-shadow'] = config.shadows;
17808
17995
  }
17809
- if (config?.borderRadius) {
17810
- styles['border-radius'] = config.borderRadius;
17996
+ if (config?.borderRadius !== undefined && config?.borderRadius !== null) {
17997
+ styles['border-radius'] = `${config.borderRadius}px`;
17998
+ }
17999
+ if (this.padding() >= 0) {
18000
+ styles['padding'] = `${this.padding()}px`;
18001
+ }
18002
+ if (this.borderColor() && !this.hasExplicitSideBorders()) {
18003
+ styles['border'] = `1px solid ${this.borderColor()}`;
17811
18004
  }
17812
18005
  return styles;
17813
18006
  }, ...(ngDevMode ? [{ debugName: "cardStyles" }] : []));
@@ -17888,11 +18081,11 @@ class HeaderCardComponent {
17888
18081
  this.onAction.emit({ type: 'click', data: {} });
17889
18082
  }
17890
18083
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: HeaderCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17891
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: HeaderCardComponent, isStandalone: true, selector: "mt-header-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<div class=\"header-container\" [ngStyle]=\"containerStyles()\">\r\n <div\r\n class=\"header-card\"\r\n [class.clickable]=\"isClickable()\"\r\n [ngStyle]=\"cardStyles()\"\r\n >\r\n <!-- Logo or Icon Display -->\r\n @if (logoUrl() || icon()) {\r\n <div class=\"header-icon-wrapper\">\r\n @if (logoUrl()) {\r\n <img [src]=\"logoUrl()\" alt=\"Logo\" class=\"header-logo\" />\r\n } @else if (icon()) {\r\n <div\r\n class=\"header-icon\"\r\n [ngStyle]=\"{\r\n 'background-color': iconBgColor(),\r\n 'font-size': fontSizeTitle(),\r\n }\"\r\n >\r\n <i\r\n [class]=\"'mti mti-' + icon()\"\r\n [ngStyle]=\"{ color: iconColor() }\"\r\n ></i>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"header-content\" [class.label-title]=\"!isFullWidth()\">\r\n <span\r\n class=\"header-title\"\r\n [ngStyle]=\"{ 'font-size': fontSizeTitle() }\"\r\n (click)=\"onTitleClick()\"\r\n >\r\n {{ title() }}\r\n </span>\r\n\r\n <!-- Status Indicators -->\r\n @if (statuses().length > 0) {\r\n <div class=\"status-list\">\r\n @for (status of statuses(); track status.label) {\r\n <div class=\"status-item\">\r\n @if (status.iconClass) {\r\n <span\r\n [class]=\"status.iconClass\"\r\n class=\"status-icon\"\r\n [style.color]=\"status.color\"\r\n [style.font-size.px]=\"status.iconSize || 14\"\r\n ></span>\r\n } @else {\r\n <span\r\n class=\"status-dot\"\r\n [class.circle]=\"status.shape === 'circle' || !status.shape\"\r\n [class.square]=\"\r\n status.shape === 'square' || status.shape === 'rect'\r\n \"\r\n [class.rectangul]=\"status.shape === 'rectangul'\"\r\n [class.rhombic]=\"status.shape === 'rhombic'\"\r\n [ngStyle]=\"{\r\n 'background-color': status.color,\r\n 'border-color': status.borderColor,\r\n 'border-bottom-color': status.borderBottomColor,\r\n }\"\r\n ></span>\r\n }\r\n <span class=\"status-label\">{{ status.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showArrow()) {\r\n <div class=\"header-arrow\" (click)=\"onArrowClick()\">\r\n <i class=\"pi pi-angle-right\"></i>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".header-container{height:100%}.header-card{display:flex;align-items:center;gap:.5rem;height:100%}.header-card.clickable{cursor:pointer}.header-icon-wrapper{display:flex;align-items:center}.header-logo{width:50px;height:50px;object-fit:contain;margin:0 .5rem}.header-icon{display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:.5rem;margin:0 .5rem}.header-content{display:flex;justify-content:space-between;align-items:center;flex:1}.header-content.label-title{flex-direction:column;align-items:flex-start}.header-title{margin:0;font-weight:600;line-height:1.2}.status-list{display:flex;gap:1rem;flex-wrap:wrap}.status-item{display:flex;align-items:center;gap:.25rem}.status-dot{width:.5rem;height:.5rem;border-radius:50%}.status-dot.circle{border-radius:50%}.status-dot.square,.status-dot.rect{border-radius:2px}.status-dot.rectangul{border-radius:2px;width:.75rem;height:.375rem}.status-dot.rhombic{transform:rotate(45deg);border-radius:2px}.status-icon{display:inline-flex;align-items:center;justify-content:center}.status-label{font-size:.75rem;color:#666}.header-arrow{font-size:1.5rem;color:#999;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18084
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: HeaderCardComponent, isStandalone: true, selector: "mt-header-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<div class=\"header-container\" [ngStyle]=\"containerStyles()\">\r\n <div\r\n class=\"header-card\"\r\n [class.clickable]=\"isClickable()\"\r\n [ngStyle]=\"cardStyles()\"\r\n [style.box-sizing]=\"'border-box'\"\r\n >\r\n <!-- Logo or Icon Display -->\r\n @if (logoUrl() || icon()) {\r\n <div class=\"header-icon-wrapper\">\r\n @if (logoUrl()) {\r\n <img [src]=\"logoUrl()\" alt=\"Logo\" class=\"header-logo\" />\r\n } @else if (icon()) {\r\n <mt-avatar\r\n class=\"header-icon\"\r\n [icon]=\"icon()\"\r\n size=\"large\"\r\n shape=\"square\"\r\n [style.--p-avatar-background]=\"iconBgColor()\"\r\n [style.--p-avatar-color]=\"iconColor()\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"header-content\" [class.label-title]=\"!isFullWidth()\">\r\n <span\r\n class=\"header-title\"\r\n [ngStyle]=\"{ 'font-size': fontSizeTitle() }\"\r\n (click)=\"onTitleClick()\"\r\n >\r\n {{ title() }}\r\n </span>\r\n\r\n <!-- Status Indicators -->\r\n @if (statuses().length > 0) {\r\n <div class=\"status-list\">\r\n @for (status of statuses(); track status.label) {\r\n <div class=\"status-item\">\r\n @if (status.iconClass) {\r\n <span\r\n [class]=\"status.iconClass\"\r\n class=\"status-icon\"\r\n [style.color]=\"status.color\"\r\n [style.font-size.px]=\"status.iconSize || 14\"\r\n ></span>\r\n } @else {\r\n <span\r\n class=\"status-dot\"\r\n [class.circle]=\"status.shape === 'circle' || !status.shape\"\r\n [class.square]=\"\r\n status.shape === 'square' || status.shape === 'rect'\r\n \"\r\n [class.rectangul]=\"status.shape === 'rectangul'\"\r\n [class.rhombic]=\"status.shape === 'rhombic'\"\r\n [ngStyle]=\"{\r\n 'background-color': status.color,\r\n 'border-color': status.borderColor,\r\n 'border-bottom-color': status.borderBottomColor,\r\n }\"\r\n ></span>\r\n }\r\n <span class=\"status-label\">{{ status.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showArrow()) {\r\n <div class=\"header-arrow\" (click)=\"onArrowClick()\">\r\n <i class=\"pi pi-angle-right\"></i>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".header-container{height:100%}.header-card{display:flex;align-items:center;gap:.5rem;height:100%}.header-card.clickable{cursor:pointer}.header-icon-wrapper{display:flex;align-items:center}.header-logo{width:50px;height:50px;object-fit:contain;margin:0 .5rem}.header-icon{margin:0 .5rem}.header-content{display:flex;justify-content:space-between;align-items:center;flex:1}.header-content.label-title{flex-direction:column;align-items:flex-start}.header-title{margin:0;font-weight:600;line-height:1.2}.status-list{display:flex;gap:1rem;flex-wrap:wrap}.status-item{display:flex;align-items:center;gap:.25rem}.status-dot{width:.5rem;height:.5rem;border-radius:50%}.status-dot.circle{border-radius:50%}.status-dot.square,.status-dot.rect{border-radius:2px}.status-dot.rectangul{border-radius:2px;width:.75rem;height:.375rem}.status-dot.rhombic{transform:rotate(45deg);border-radius:2px}.status-icon{display:inline-flex;align-items:center;justify-content:center}.status-label{font-size:.75rem;color:#666}.header-arrow{font-size:1.5rem;color:#999;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17892
18085
  }
17893
18086
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: HeaderCardComponent, decorators: [{
17894
18087
  type: Component,
17895
- args: [{ selector: 'mt-header-card', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"header-container\" [ngStyle]=\"containerStyles()\">\r\n <div\r\n class=\"header-card\"\r\n [class.clickable]=\"isClickable()\"\r\n [ngStyle]=\"cardStyles()\"\r\n >\r\n <!-- Logo or Icon Display -->\r\n @if (logoUrl() || icon()) {\r\n <div class=\"header-icon-wrapper\">\r\n @if (logoUrl()) {\r\n <img [src]=\"logoUrl()\" alt=\"Logo\" class=\"header-logo\" />\r\n } @else if (icon()) {\r\n <div\r\n class=\"header-icon\"\r\n [ngStyle]=\"{\r\n 'background-color': iconBgColor(),\r\n 'font-size': fontSizeTitle(),\r\n }\"\r\n >\r\n <i\r\n [class]=\"'mti mti-' + icon()\"\r\n [ngStyle]=\"{ color: iconColor() }\"\r\n ></i>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"header-content\" [class.label-title]=\"!isFullWidth()\">\r\n <span\r\n class=\"header-title\"\r\n [ngStyle]=\"{ 'font-size': fontSizeTitle() }\"\r\n (click)=\"onTitleClick()\"\r\n >\r\n {{ title() }}\r\n </span>\r\n\r\n <!-- Status Indicators -->\r\n @if (statuses().length > 0) {\r\n <div class=\"status-list\">\r\n @for (status of statuses(); track status.label) {\r\n <div class=\"status-item\">\r\n @if (status.iconClass) {\r\n <span\r\n [class]=\"status.iconClass\"\r\n class=\"status-icon\"\r\n [style.color]=\"status.color\"\r\n [style.font-size.px]=\"status.iconSize || 14\"\r\n ></span>\r\n } @else {\r\n <span\r\n class=\"status-dot\"\r\n [class.circle]=\"status.shape === 'circle' || !status.shape\"\r\n [class.square]=\"\r\n status.shape === 'square' || status.shape === 'rect'\r\n \"\r\n [class.rectangul]=\"status.shape === 'rectangul'\"\r\n [class.rhombic]=\"status.shape === 'rhombic'\"\r\n [ngStyle]=\"{\r\n 'background-color': status.color,\r\n 'border-color': status.borderColor,\r\n 'border-bottom-color': status.borderBottomColor,\r\n }\"\r\n ></span>\r\n }\r\n <span class=\"status-label\">{{ status.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showArrow()) {\r\n <div class=\"header-arrow\" (click)=\"onArrowClick()\">\r\n <i class=\"pi pi-angle-right\"></i>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".header-container{height:100%}.header-card{display:flex;align-items:center;gap:.5rem;height:100%}.header-card.clickable{cursor:pointer}.header-icon-wrapper{display:flex;align-items:center}.header-logo{width:50px;height:50px;object-fit:contain;margin:0 .5rem}.header-icon{display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:.5rem;margin:0 .5rem}.header-content{display:flex;justify-content:space-between;align-items:center;flex:1}.header-content.label-title{flex-direction:column;align-items:flex-start}.header-title{margin:0;font-weight:600;line-height:1.2}.status-list{display:flex;gap:1rem;flex-wrap:wrap}.status-item{display:flex;align-items:center;gap:.25rem}.status-dot{width:.5rem;height:.5rem;border-radius:50%}.status-dot.circle{border-radius:50%}.status-dot.square,.status-dot.rect{border-radius:2px}.status-dot.rectangul{border-radius:2px;width:.75rem;height:.375rem}.status-dot.rhombic{transform:rotate(45deg);border-radius:2px}.status-icon{display:inline-flex;align-items:center;justify-content:center}.status-label{font-size:.75rem;color:#666}.header-arrow{font-size:1.5rem;color:#999;cursor:pointer}\n"] }]
18088
+ args: [{ selector: 'mt-header-card', standalone: true, imports: [CommonModule, Avatar], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"header-container\" [ngStyle]=\"containerStyles()\">\r\n <div\r\n class=\"header-card\"\r\n [class.clickable]=\"isClickable()\"\r\n [ngStyle]=\"cardStyles()\"\r\n [style.box-sizing]=\"'border-box'\"\r\n >\r\n <!-- Logo or Icon Display -->\r\n @if (logoUrl() || icon()) {\r\n <div class=\"header-icon-wrapper\">\r\n @if (logoUrl()) {\r\n <img [src]=\"logoUrl()\" alt=\"Logo\" class=\"header-logo\" />\r\n } @else if (icon()) {\r\n <mt-avatar\r\n class=\"header-icon\"\r\n [icon]=\"icon()\"\r\n size=\"large\"\r\n shape=\"square\"\r\n [style.--p-avatar-background]=\"iconBgColor()\"\r\n [style.--p-avatar-color]=\"iconColor()\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"header-content\" [class.label-title]=\"!isFullWidth()\">\r\n <span\r\n class=\"header-title\"\r\n [ngStyle]=\"{ 'font-size': fontSizeTitle() }\"\r\n (click)=\"onTitleClick()\"\r\n >\r\n {{ title() }}\r\n </span>\r\n\r\n <!-- Status Indicators -->\r\n @if (statuses().length > 0) {\r\n <div class=\"status-list\">\r\n @for (status of statuses(); track status.label) {\r\n <div class=\"status-item\">\r\n @if (status.iconClass) {\r\n <span\r\n [class]=\"status.iconClass\"\r\n class=\"status-icon\"\r\n [style.color]=\"status.color\"\r\n [style.font-size.px]=\"status.iconSize || 14\"\r\n ></span>\r\n } @else {\r\n <span\r\n class=\"status-dot\"\r\n [class.circle]=\"status.shape === 'circle' || !status.shape\"\r\n [class.square]=\"\r\n status.shape === 'square' || status.shape === 'rect'\r\n \"\r\n [class.rectangul]=\"status.shape === 'rectangul'\"\r\n [class.rhombic]=\"status.shape === 'rhombic'\"\r\n [ngStyle]=\"{\r\n 'background-color': status.color,\r\n 'border-color': status.borderColor,\r\n 'border-bottom-color': status.borderBottomColor,\r\n }\"\r\n ></span>\r\n }\r\n <span class=\"status-label\">{{ status.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showArrow()) {\r\n <div class=\"header-arrow\" (click)=\"onArrowClick()\">\r\n <i class=\"pi pi-angle-right\"></i>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".header-container{height:100%}.header-card{display:flex;align-items:center;gap:.5rem;height:100%}.header-card.clickable{cursor:pointer}.header-icon-wrapper{display:flex;align-items:center}.header-logo{width:50px;height:50px;object-fit:contain;margin:0 .5rem}.header-icon{margin:0 .5rem}.header-content{display:flex;justify-content:space-between;align-items:center;flex:1}.header-content.label-title{flex-direction:column;align-items:flex-start}.header-title{margin:0;font-weight:600;line-height:1.2}.status-list{display:flex;gap:1rem;flex-wrap:wrap}.status-item{display:flex;align-items:center;gap:.25rem}.status-dot{width:.5rem;height:.5rem;border-radius:50%}.status-dot.circle{border-radius:50%}.status-dot.square,.status-dot.rect{border-radius:2px}.status-dot.rectangul{border-radius:2px;width:.75rem;height:.375rem}.status-dot.rhombic{transform:rotate(45deg);border-radius:2px}.status-icon{display:inline-flex;align-items:center;justify-content:center}.status-label{font-size:.75rem;color:#666}.header-arrow{font-size:1.5rem;color:#999;cursor:pointer}\n"] }]
17896
18089
  }], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }], onAction: [{ type: i0.Output, args: ["onAction"] }] } });
17897
18090
 
17898
18091
  /**
@@ -17989,8 +18182,297 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
17989
18182
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".skeleton-container{display:flex;flex-wrap:wrap;gap:1rem;width:100%;padding:1rem}.skeleton-item{background:#f5f5f5;border-radius:.5rem;overflow:hidden;position:relative}.skeleton-animation{position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent);animation:shimmer 1.5s infinite}@keyframes shimmer{0%{transform:translate(-100%)}to{transform:translate(100%)}}\n"] }]
17990
18183
  }], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }] } });
17991
18184
 
18185
+ class PropertiesCardComponent {
18186
+ storeService = inject(DashboardItemStoreService);
18187
+ transloco = inject(TranslocoService);
18188
+ subscription = new Subscription();
18189
+ dashboardId = input.required(...(ngDevMode ? [{ debugName: "dashboardId" }] : []));
18190
+ inGroup = input(false, ...(ngDevMode ? [{ debugName: "inGroup" }] : []));
18191
+ onAction = output();
18192
+ configurationItem = signal(null, ...(ngDevMode ? [{ debugName: "configurationItem" }] : []));
18193
+ cardData = signal([], ...(ngDevMode ? [{ debugName: "cardData" }] : []));
18194
+ tabSelected = signal(0, ...(ngDevMode ? [{ debugName: "tabSelected" }] : []));
18195
+ langCode = computed(() => this.transloco.getActiveLang() || 'en', ...(ngDevMode ? [{ debugName: "langCode" }] : []));
18196
+ isPropertiesCard = computed(() => this.configurationItem()?.clientConfig?.functionName ===
18197
+ 'handlelevelCardsWithFilter', ...(ngDevMode ? [{ debugName: "isPropertiesCard" }] : []));
18198
+ galleryMode = computed(() => !!this.configurationItem()?.clientConfig?.configAsType?.['galleryMode'], ...(ngDevMode ? [{ debugName: "galleryMode" }] : []));
18199
+ currentTabItems = computed(() => {
18200
+ const data = this.cardData();
18201
+ return data[this.tabSelected()] ?? data[0] ?? [];
18202
+ }, ...(ngDevMode ? [{ debugName: "currentTabItems" }] : []));
18203
+ selectedProperties = computed(() => {
18204
+ const selected = this.configurationItem()?.serviceConfig?.query?.['selectedProperties'];
18205
+ if (!Array.isArray(selected))
18206
+ return [];
18207
+ return selected
18208
+ .map((item) => typeof item === 'string'
18209
+ ? item
18210
+ : typeof item?.key === 'string'
18211
+ ? item.key
18212
+ : '')
18213
+ .filter((item) => !!item);
18214
+ }, ...(ngDevMode ? [{ debugName: "selectedProperties" }] : []));
18215
+ propsConfigAsIndex = computed(() => {
18216
+ const config = this.configurationItem()?.clientConfig?.configAsType?.['propsConfigAsIndex'];
18217
+ return Array.isArray(config) ? config : [];
18218
+ }, ...(ngDevMode ? [{ debugName: "propsConfigAsIndex" }] : []));
18219
+ tabOptions = computed(() => this.cardData().map((tabItems, index) => ({
18220
+ label: this.resolveTabLabel(tabItems, index),
18221
+ value: index,
18222
+ })), ...(ngDevMode ? [{ debugName: "tabOptions" }] : []));
18223
+ showTabs = computed(() => !this.inGroup() && this.tabOptions().length > 1, ...(ngDevMode ? [{ debugName: "showTabs" }] : []));
18224
+ currentTabCards = computed(() => {
18225
+ const cards = this.extractCards(this.currentTabItems());
18226
+ const selectedProperties = this.selectedProperties();
18227
+ const propsConfigAsIndex = this.propsConfigAsIndex();
18228
+ const propertiesMode = this.isPropertiesCard();
18229
+ return cards.map((card, index) => ({
18230
+ trackId: card.id ?? index,
18231
+ card,
18232
+ entities: propertiesMode
18233
+ ? this.buildPropertiesCardEntities(card, selectedProperties, propsConfigAsIndex)
18234
+ : [],
18235
+ bodyProps: propertiesMode ? [] : this.buildLegacyBodyProps(card),
18236
+ attachments: propertiesMode ? [] : this.getAttachments(card),
18237
+ hasCounters: propertiesMode ? false : this.hasCounters(card),
18238
+ }));
18239
+ }, ...(ngDevMode ? [{ debugName: "currentTabCards" }] : []));
18240
+ constructor() {
18241
+ effect(() => {
18242
+ const tabs = this.tabOptions();
18243
+ const selectedTab = this.tabSelected();
18244
+ if (!tabs.length) {
18245
+ if (selectedTab !== 0) {
18246
+ this.tabSelected.set(0);
18247
+ }
18248
+ return;
18249
+ }
18250
+ if (selectedTab < 0 || selectedTab >= tabs.length) {
18251
+ this.tabSelected.set(0);
18252
+ }
18253
+ });
18254
+ }
18255
+ ngOnInit() {
18256
+ const id = this.dashboardId();
18257
+ this.subscription.add(this.storeService
18258
+ .selectItemProperty$(id, 'ConfigurationItem')
18259
+ .subscribe((config) => {
18260
+ this.configurationItem.set(config || null);
18261
+ }));
18262
+ this.subscription.add(this.storeService
18263
+ .selectItemProperty$(id, 'DataHandled')
18264
+ .subscribe((data) => {
18265
+ if (Array.isArray(data)) {
18266
+ this.cardData.set(data);
18267
+ }
18268
+ else {
18269
+ this.cardData.set([]);
18270
+ }
18271
+ }));
18272
+ }
18273
+ ngOnDestroy() {
18274
+ this.subscription.unsubscribe();
18275
+ }
18276
+ onCardClick(card) {
18277
+ this.onAction.emit({ type: 'click', data: card });
18278
+ }
18279
+ normalizePropertyKey(value) {
18280
+ return value?.toLowerCase().trim() || '';
18281
+ }
18282
+ clampEntitySize(value) {
18283
+ return Math.max(1, Math.min(24, Math.round(value)));
18284
+ }
18285
+ resolveEntitySize(width, fallback) {
18286
+ const fallbackSize = this.clampEntitySize(fallback ?? 24);
18287
+ if (!width)
18288
+ return fallbackSize;
18289
+ const normalizedWidth = width.trim();
18290
+ if (!normalizedWidth)
18291
+ return fallbackSize;
18292
+ if (normalizedWidth.endsWith('%')) {
18293
+ const percentage = Number.parseFloat(normalizedWidth.slice(0, -1));
18294
+ if (!Number.isNaN(percentage) && percentage > 0) {
18295
+ return this.clampEntitySize((percentage / 100) * 24);
18296
+ }
18297
+ return fallbackSize;
18298
+ }
18299
+ const numericWidth = Number.parseFloat(normalizedWidth);
18300
+ if (Number.isNaN(numericWidth) || numericWidth <= 0) {
18301
+ return fallbackSize;
18302
+ }
18303
+ if (numericWidth <= 24) {
18304
+ return this.clampEntitySize(numericWidth);
18305
+ }
18306
+ if (numericWidth <= 100) {
18307
+ return this.clampEntitySize((numericWidth / 100) * 24);
18308
+ }
18309
+ return fallbackSize;
18310
+ }
18311
+ isCardGroup(item) {
18312
+ return Array.isArray(item?.data);
18313
+ }
18314
+ extractCards(items) {
18315
+ const cards = [];
18316
+ items.forEach((item) => {
18317
+ if (this.isCardGroup(item)) {
18318
+ cards.push(...(Array.isArray(item.data) ? item.data : []));
18319
+ return;
18320
+ }
18321
+ cards.push(item);
18322
+ });
18323
+ return cards;
18324
+ }
18325
+ getCardProps(card) {
18326
+ if (Array.isArray(card.props))
18327
+ return card.props;
18328
+ if (Array.isArray(card.properties))
18329
+ return card.properties;
18330
+ return [];
18331
+ }
18332
+ orderProperties(props, selectedProperties) {
18333
+ if (!selectedProperties.length)
18334
+ return props;
18335
+ const propsByKey = new Map();
18336
+ props.forEach((prop) => {
18337
+ [prop.normalizedKey, prop.key].forEach((key) => {
18338
+ const normalized = this.normalizePropertyKey(key);
18339
+ if (normalized && !propsByKey.has(normalized)) {
18340
+ propsByKey.set(normalized, prop);
18341
+ }
18342
+ });
18343
+ });
18344
+ const ordered = selectedProperties
18345
+ .map((key) => propsByKey.get(this.normalizePropertyKey(key)))
18346
+ .filter((prop) => !!prop);
18347
+ if (!ordered.length)
18348
+ return props;
18349
+ const orderedSet = new Set(ordered);
18350
+ return [...ordered, ...props.filter((prop) => !orderedSet.has(prop))];
18351
+ }
18352
+ buildPropertiesCardEntities(card, selectedProperties, propsConfigAsIndex) {
18353
+ const props = this.getCardProps(card);
18354
+ const orderedProps = this.orderProperties(props, selectedProperties);
18355
+ return orderedProps
18356
+ .map((prop, index) => {
18357
+ const uiConfig = propsConfigAsIndex[index] || {};
18358
+ if (uiConfig.hidden)
18359
+ return null;
18360
+ const baseConfiguration = prop.configuration && typeof prop.configuration === 'object'
18361
+ ? prop.configuration
18362
+ : {};
18363
+ const normalizedProp = this.normalizeEntityProperty(prop);
18364
+ return {
18365
+ ...normalizedProp,
18366
+ order: index,
18367
+ configuration: {
18368
+ ...baseConfiguration,
18369
+ size: this.resolveEntitySize(uiConfig.width, typeof baseConfiguration.size === 'number'
18370
+ ? baseConfiguration.size
18371
+ : undefined),
18372
+ },
18373
+ };
18374
+ })
18375
+ .filter((prop) => !!prop);
18376
+ }
18377
+ buildLegacyBodyProps(card) {
18378
+ return this.getCardProps(card)
18379
+ .filter((prop) => {
18380
+ if (prop.viewType === 'Attachment')
18381
+ return false;
18382
+ const normalized = this.normalizePropertyKey(prop.normalizedKey || prop.key);
18383
+ if (normalized === 'name' || normalized === 'status')
18384
+ return false;
18385
+ const displayAreas = prop.displayAreas || prop.displayArea || [];
18386
+ return displayAreas.some((area) => area?.key === 'levelCard_body');
18387
+ })
18388
+ .sort((a, b) => {
18389
+ const aArea = (a.displayAreas || a.displayArea || []).find((area) => area?.key === 'levelCard_body');
18390
+ const bArea = (b.displayAreas || b.displayArea || []).find((area) => area?.key === 'levelCard_body');
18391
+ return (aArea?.order || 0) - (bArea?.order || 0);
18392
+ });
18393
+ }
18394
+ getAttachments(card) {
18395
+ const attachmentProp = this.getCardProps(card).find((prop) => prop.viewType === 'Attachment');
18396
+ return Array.isArray(attachmentProp?.value) ? attachmentProp.value : [];
18397
+ }
18398
+ hasCounters(card) {
18399
+ return !!(card.issuesCounts || card.risksCounts || card.milestonesCounts);
18400
+ }
18401
+ resolveTabLabel(tabItems, index) {
18402
+ const firstItem = tabItems[0];
18403
+ if (firstItem && this.isCardGroup(firstItem)) {
18404
+ const firstCard = Array.isArray(firstItem.data)
18405
+ ? firstItem.data[0]
18406
+ : null;
18407
+ return (this.readLocalizedText(firstItem.label) ||
18408
+ this.readLocalizedText(firstItem.name) ||
18409
+ this.readString(firstItem.title) ||
18410
+ this.readLocalizedText(firstCard?.name) ||
18411
+ this.readLocalizedText(firstCard?.label) ||
18412
+ `${index + 1}`);
18413
+ }
18414
+ const firstCard = firstItem;
18415
+ return (this.readLocalizedText(firstCard?.name) ||
18416
+ this.readLocalizedText(firstCard?.label) ||
18417
+ `${index + 1}`);
18418
+ }
18419
+ readString(value) {
18420
+ return typeof value === 'string' ? value.trim() : '';
18421
+ }
18422
+ normalizeEntityProperty(prop) {
18423
+ const resolvedName = this.resolveEntityName(prop);
18424
+ if (!resolvedName) {
18425
+ return prop;
18426
+ }
18427
+ return {
18428
+ ...prop,
18429
+ name: resolvedName,
18430
+ };
18431
+ }
18432
+ resolveEntityName(prop) {
18433
+ const currentName = this.readLocalizedText(prop.name);
18434
+ if (currentName) {
18435
+ return currentName;
18436
+ }
18437
+ const fallbackLabel = this.readLocalizedText(prop.label);
18438
+ if (fallbackLabel) {
18439
+ return fallbackLabel;
18440
+ }
18441
+ return (this.readLocalizedText(prop.key) ||
18442
+ this.readLocalizedText(prop.normalizedKey) ||
18443
+ '');
18444
+ }
18445
+ readLocalizedText(value) {
18446
+ if (typeof value === 'string') {
18447
+ return value.trim();
18448
+ }
18449
+ if (value && typeof value === 'object') {
18450
+ const localized = value;
18451
+ const langCode = this.langCode();
18452
+ const candidate = localized[langCode] ?? localized['en'] ?? localized['ar'];
18453
+ if (typeof candidate === 'string') {
18454
+ return candidate.trim();
18455
+ }
18456
+ }
18457
+ return '';
18458
+ }
18459
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18460
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PropertiesCardComponent, isStandalone: true, selector: "mt-properties-card, mt-entities-preview-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\n @if (showTabs()) {\n <div class=\"mb-3\">\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\n </div>\n }\n\n <div\n class=\"overflow-y-auto overflow-x-hidden\"\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\n >\n @if (currentTabCards().length === 0) {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n } @else {\n <div class=\"flex flex-wrap\">\n @for (cardView of currentTabCards(); track cardView.trackId) {\n <div\n class=\"mb-2 p-2\"\n [class.card-col]=\"!galleryMode()\"\n [class.gallery-card-col]=\"galleryMode()\"\n [class.w-full]=\"!galleryMode()\"\n [class.md:w-1/2]=\"!galleryMode()\"\n [class.lg:w-1/3]=\"!galleryMode()\"\n >\n @if (isPropertiesCard()) {\n <div\n class=\"h-full cursor-pointer rounded-lg bg-white p-3 shadow-sm transition-all hover:shadow-md\"\n (click)=\"onCardClick(cardView.card)\"\n >\n @if (cardView.entities.length > 0) {\n <mt-entities-preview [entities]=\"cardView.entities\" />\n } @else {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n }\n </div>\n } @else {\n <div\n class=\"h-full cursor-pointer rounded-lg bg-white shadow-sm transition-all hover:shadow-md\"\n (click)=\"onCardClick(cardView.card)\"\n >\n <div\n class=\"flex items-center justify-between border-b p-3\"\n [style.border-left-color]=\"\n cardView.card.status?.value?.details?.color || '#64b735'\n \"\n [style.border-left-width]=\"'4px'\"\n >\n <div class=\"min-w-0 flex-1\">\n <h6 class=\"truncate text-sm font-semibold text-gray-800\">\n {{ cardView.card.name }}\n </h6>\n </div>\n <div class=\"ml-2 flex items-center gap-2\">\n @if (cardView.card.status?.value?.name) {\n <span\n class=\"whitespace-nowrap rounded-full px-2 py-0.5 text-xs font-medium text-white\"\n [style.background-color]=\"\n cardView.card.status?.value?.details?.color ||\n '#64b735'\n \"\n [pTooltip]=\"\n cardView.card.status?.value?.details?.description\n \"\n >\n {{ cardView.card.status?.value?.name }}\n </span>\n }\n @if (cardView.card.currentPhase) {\n <span\n class=\"rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-600\"\n >\n {{ cardView.card.currentPhase }}\n </span>\n }\n </div>\n </div>\n\n <div class=\"p-3\">\n @for (prop of cardView.bodyProps; track prop.key) {\n <div class=\"mb-2 flex items-start text-sm\">\n <span class=\"mr-2 font-medium text-gray-500\">\n {{ prop.key }}:\n </span>\n <span class=\"flex-1 text-gray-700\">\n <mt-entity-info\n [viewType]=\"prop.viewType\"\n [value]=\"prop.value\"\n [langCode]=\"langCode()\"\n />\n </span>\n </div>\n }\n </div>\n\n @if (galleryMode() && cardView.attachments.length > 0) {\n <div class=\"flex gap-2 overflow-x-auto p-3 pt-0\">\n @for (attachment of cardView.attachments; track $index) {\n <img\n [src]=\"'api/Uploader/' + attachment['path']\"\n alt=\"Attachment\"\n class=\"h-16 w-16 flex-shrink-0 rounded object-cover\"\n />\n }\n </div>\n }\n\n @if (cardView.hasCounters) {\n <div class=\"flex justify-around border-t p-2 text-xs\">\n @if (cardView.card.issuesCounts) {\n <div class=\"text-center\">\n <div class=\"font-medium text-red-500\">\n {{ cardView.card.issuesCounts.value }}\n </div>\n <div class=\"text-gray-400\">{{ t(\"issues\") }}</div>\n </div>\n }\n @if (cardView.card.risksCounts) {\n <div class=\"text-center\">\n <div class=\"font-medium text-orange-500\">\n {{ cardView.card.risksCounts.value }}\n </div>\n <div class=\"text-gray-400\">{{ t(\"risks\") }}</div>\n </div>\n }\n @if (cardView.card.milestonesCounts) {\n <div class=\"text-center\">\n <div class=\"font-medium text-blue-500\">\n {{ cardView.card.milestonesCounts.value }}\n </div>\n <div class=\"text-gray-400\">{{ t(\"milestones\") }}</div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-container>\n", styles: [":host{display:block;height:100%}.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: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape"] }, { kind: "component", type: EntityInfoComponent, selector: "mt-entity-info", inputs: ["data", "displayType", "extraInfoData", "limitWords", "customClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18461
+ }
18462
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesCardComponent, decorators: [{
18463
+ type: Component,
18464
+ args: [{ selector: 'mt-properties-card, mt-entities-preview-card', standalone: true, imports: [
18465
+ CommonModule,
18466
+ TooltipModule,
18467
+ TranslocoDirective,
18468
+ Tabs,
18469
+ EntitiesPreview,
18470
+ EntityInfoComponent,
18471
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\n @if (showTabs()) {\n <div class=\"mb-3\">\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\n </div>\n }\n\n <div\n class=\"overflow-y-auto overflow-x-hidden\"\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\n >\n @if (currentTabCards().length === 0) {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n } @else {\n <div class=\"flex flex-wrap\">\n @for (cardView of currentTabCards(); track cardView.trackId) {\n <div\n class=\"mb-2 p-2\"\n [class.card-col]=\"!galleryMode()\"\n [class.gallery-card-col]=\"galleryMode()\"\n [class.w-full]=\"!galleryMode()\"\n [class.md:w-1/2]=\"!galleryMode()\"\n [class.lg:w-1/3]=\"!galleryMode()\"\n >\n @if (isPropertiesCard()) {\n <div\n class=\"h-full cursor-pointer rounded-lg bg-white p-3 shadow-sm transition-all hover:shadow-md\"\n (click)=\"onCardClick(cardView.card)\"\n >\n @if (cardView.entities.length > 0) {\n <mt-entities-preview [entities]=\"cardView.entities\" />\n } @else {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n }\n </div>\n } @else {\n <div\n class=\"h-full cursor-pointer rounded-lg bg-white shadow-sm transition-all hover:shadow-md\"\n (click)=\"onCardClick(cardView.card)\"\n >\n <div\n class=\"flex items-center justify-between border-b p-3\"\n [style.border-left-color]=\"\n cardView.card.status?.value?.details?.color || '#64b735'\n \"\n [style.border-left-width]=\"'4px'\"\n >\n <div class=\"min-w-0 flex-1\">\n <h6 class=\"truncate text-sm font-semibold text-gray-800\">\n {{ cardView.card.name }}\n </h6>\n </div>\n <div class=\"ml-2 flex items-center gap-2\">\n @if (cardView.card.status?.value?.name) {\n <span\n class=\"whitespace-nowrap rounded-full px-2 py-0.5 text-xs font-medium text-white\"\n [style.background-color]=\"\n cardView.card.status?.value?.details?.color ||\n '#64b735'\n \"\n [pTooltip]=\"\n cardView.card.status?.value?.details?.description\n \"\n >\n {{ cardView.card.status?.value?.name }}\n </span>\n }\n @if (cardView.card.currentPhase) {\n <span\n class=\"rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-600\"\n >\n {{ cardView.card.currentPhase }}\n </span>\n }\n </div>\n </div>\n\n <div class=\"p-3\">\n @for (prop of cardView.bodyProps; track prop.key) {\n <div class=\"mb-2 flex items-start text-sm\">\n <span class=\"mr-2 font-medium text-gray-500\">\n {{ prop.key }}:\n </span>\n <span class=\"flex-1 text-gray-700\">\n <mt-entity-info\n [viewType]=\"prop.viewType\"\n [value]=\"prop.value\"\n [langCode]=\"langCode()\"\n />\n </span>\n </div>\n }\n </div>\n\n @if (galleryMode() && cardView.attachments.length > 0) {\n <div class=\"flex gap-2 overflow-x-auto p-3 pt-0\">\n @for (attachment of cardView.attachments; track $index) {\n <img\n [src]=\"'api/Uploader/' + attachment['path']\"\n alt=\"Attachment\"\n class=\"h-16 w-16 flex-shrink-0 rounded object-cover\"\n />\n }\n </div>\n }\n\n @if (cardView.hasCounters) {\n <div class=\"flex justify-around border-t p-2 text-xs\">\n @if (cardView.card.issuesCounts) {\n <div class=\"text-center\">\n <div class=\"font-medium text-red-500\">\n {{ cardView.card.issuesCounts.value }}\n </div>\n <div class=\"text-gray-400\">{{ t(\"issues\") }}</div>\n </div>\n }\n @if (cardView.card.risksCounts) {\n <div class=\"text-center\">\n <div class=\"font-medium text-orange-500\">\n {{ cardView.card.risksCounts.value }}\n </div>\n <div class=\"text-gray-400\">{{ t(\"risks\") }}</div>\n </div>\n }\n @if (cardView.card.milestonesCounts) {\n <div class=\"text-center\">\n <div class=\"font-medium text-blue-500\">\n {{ cardView.card.milestonesCounts.value }}\n </div>\n <div class=\"text-gray-400\">{{ t(\"milestones\") }}</div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-container>\n", styles: [":host{display:block;height:100%}.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"] }]
18472
+ }], ctorParameters: () => [], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }], inGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "inGroup", required: false }] }], onAction: [{ type: i0.Output, args: ["onAction"] }] } });
18473
+
17992
18474
  /**
17993
- * Entity Preview Card Component
18475
+ * Properties View Card Component
17994
18476
  *
17995
18477
  * Displays entity properties in a card layout.
17996
18478
  * Used by the entityPreview componentName.
@@ -18089,6 +18571,7 @@ class EntityPreviewCardComponent {
18089
18571
  const propConfig = {
18090
18572
  ...(propsConfigAsIndex[index] || {}),
18091
18573
  };
18574
+ const propInfo = this.normalizeEntityProperty(prop);
18092
18575
  // Mobile adjustments
18093
18576
  if (isMobilePlatform()) {
18094
18577
  if (!propConfig.width || parseInt(propConfig.width, 10) < 50) {
@@ -18096,7 +18579,7 @@ class EntityPreviewCardComponent {
18096
18579
  }
18097
18580
  }
18098
18581
  return {
18099
- propInfo: prop,
18582
+ propInfo,
18100
18583
  config: propConfig,
18101
18584
  };
18102
18585
  });
@@ -18109,8 +18592,45 @@ class EntityPreviewCardComponent {
18109
18592
  getLanguageCode() {
18110
18593
  return (this.transloco.getActiveLang() || localStorage.getItem('langCode') || 'en');
18111
18594
  }
18595
+ normalizeEntityProperty(prop) {
18596
+ const resolvedName = this.resolveEntityName(prop);
18597
+ if (!resolvedName) {
18598
+ return prop;
18599
+ }
18600
+ return {
18601
+ ...prop,
18602
+ name: resolvedName,
18603
+ };
18604
+ }
18605
+ resolveEntityName(prop) {
18606
+ const currentName = this.readLocalizedText(prop.name);
18607
+ if (currentName) {
18608
+ return currentName;
18609
+ }
18610
+ const fallbackLabel = this.readLocalizedText(prop.label);
18611
+ if (fallbackLabel) {
18612
+ return fallbackLabel;
18613
+ }
18614
+ return (this.readLocalizedText(prop.key) ||
18615
+ this.readLocalizedText(prop.normalizedKey) ||
18616
+ '');
18617
+ }
18618
+ readLocalizedText(value) {
18619
+ if (typeof value === 'string') {
18620
+ return value.trim();
18621
+ }
18622
+ if (value && typeof value === 'object') {
18623
+ const localized = value;
18624
+ const languageCode = this.getLanguageCode();
18625
+ const candidate = localized[languageCode] ?? localized['en'] ?? localized['ar'];
18626
+ if (typeof candidate === 'string') {
18627
+ return candidate.trim();
18628
+ }
18629
+ }
18630
+ return '';
18631
+ }
18112
18632
  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 });
18633
+ 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
18634
  }
18115
18635
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPreviewCardComponent, decorators: [{
18116
18636
  type: Component,
@@ -18119,132 +18639,118 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
18119
18639
  TranslocoDirective,
18120
18640
  CardContentComponent,
18121
18641
  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"] }]
18642
+ ], 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
18643
  }], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }] } });
18124
18644
 
18125
- /**
18126
- * Level Card List Component
18127
- *
18128
- * Displays a list of level cards with properties.
18129
- * Matches old app-build-level-card behavior.
18130
- */
18131
- class LevelCardListComponent {
18132
- storeService = inject(DashboardItemStoreService);
18133
- transloco = inject(TranslocoService);
18645
+ class TopbarCardComponent {
18646
+ storeService = inject(DashboardStoreService);
18647
+ itemStoreService = inject(DashboardItemStoreService);
18134
18648
  subscription = new Subscription();
18135
- /** Dashboard ID */
18136
18649
  dashboardId = input.required(...(ngDevMode ? [{ debugName: "dashboardId" }] : []));
18137
- /** Whether inside a group */
18138
- inGroup = input(false, ...(ngDevMode ? [{ debugName: "inGroup" }] : []));
18139
- /** Properties to hide */
18140
- hideProperties = input([], ...(ngDevMode ? [{ debugName: "hideProperties" }] : []));
18141
- /** Action event output */
18142
- onAction = output();
18143
- /** Configuration item */
18650
+ defaultBreadcrumbLabel = input('', ...(ngDevMode ? [{ debugName: "defaultBreadcrumbLabel" }] : []));
18144
18651
  configurationItem = signal(null, ...(ngDevMode ? [{ debugName: "configurationItem" }] : []));
18145
- /** Card data from handler */
18146
- cardData = signal([], ...(ngDevMode ? [{ debugName: "cardData" }] : []));
18147
- /** Currently selected tab index */
18148
- tabSelected = signal(0, ...(ngDevMode ? [{ debugName: "tabSelected" }] : []));
18149
- /** Language code */
18150
- langCode = computed(() => this.transloco.getActiveLang(), ...(ngDevMode ? [{ debugName: "langCode" }] : []));
18151
- /** Gallery mode flag */
18152
- galleryMode = computed(() => {
18153
- return !!this.configurationItem()?.clientConfig?.configAsType?.['galleryMode'];
18154
- }, ...(ngDevMode ? [{ debugName: "galleryMode" }] : []));
18155
- /** Tabs from config */
18156
- tabs = computed(() => {
18157
- const config = this.configurationItem();
18158
- if (!config)
18652
+ languageCode = computed(() => this.storeService.languageCode(), ...(ngDevMode ? [{ debugName: "languageCode" }] : []));
18653
+ queryParams = computed(() => this.storeService.queryParams(), ...(ngDevMode ? [{ debugName: "queryParams" }] : []));
18654
+ styleConfig = computed(() => {
18655
+ return (this.configurationItem()?.clientConfig?.displayConfig?.['StyleConfig'] ||
18656
+ {});
18657
+ }, ...(ngDevMode ? [{ debugName: "styleConfig" }] : []));
18658
+ configAsType = computed(() => {
18659
+ return this.configurationItem()?.clientConfig?.configAsType || {};
18660
+ }, ...(ngDevMode ? [{ debugName: "configAsType" }] : []));
18661
+ cardStyleConfig = computed(() => {
18662
+ return this.configAsType()['cardStyleConfig'] || {};
18663
+ }, ...(ngDevMode ? [{ debugName: "cardStyleConfig" }] : []));
18664
+ title = computed(() => {
18665
+ const config = this.configurationItem()?.clientConfig;
18666
+ const lang = this.languageCode();
18667
+ const title = config?.title?.[lang] || config?.title?.['en'] || '';
18668
+ return dynamicTextReplace(title, this.queryParams());
18669
+ }, ...(ngDevMode ? [{ debugName: "title" }] : []));
18670
+ subtitleText = computed(() => {
18671
+ const subtitle = this.configurationItem()?.clientConfig?.['subtitle'];
18672
+ const lang = this.languageCode();
18673
+ const value = typeof subtitle === 'string'
18674
+ ? subtitle
18675
+ : subtitle?.[lang] || subtitle?.['en'] || subtitle?.['ar'] || '';
18676
+ return dynamicTextReplace(value, this.queryParams());
18677
+ }, ...(ngDevMode ? [{ debugName: "subtitleText" }] : []));
18678
+ showSubtitle = computed(() => {
18679
+ return (Boolean(this.configAsType()['showSubtitle']) && !!this.subtitleText());
18680
+ }, ...(ngDevMode ? [{ debugName: "showSubtitle" }] : []));
18681
+ icon = computed(() => {
18682
+ return this.configAsType()['icon'] || '';
18683
+ }, ...(ngDevMode ? [{ debugName: "icon" }] : []));
18684
+ iconColor = computed(() => {
18685
+ return this.styleConfig()['iconColor'] || '#4caf50';
18686
+ }, ...(ngDevMode ? [{ debugName: "iconColor" }] : []));
18687
+ iconBackgroundColor = computed(() => {
18688
+ return this.styleConfig()['iconBgColor'] || 'rgba(76, 175, 80, 0.1)';
18689
+ }, ...(ngDevMode ? [{ debugName: "iconBackgroundColor" }] : []));
18690
+ borderColor = computed(() => {
18691
+ return this.styleConfig()['border-color'] || '';
18692
+ }, ...(ngDevMode ? [{ debugName: "borderColor" }] : []));
18693
+ borderWidth = computed(() => {
18694
+ return this.borderColor() ? 1 : 0;
18695
+ }, ...(ngDevMode ? [{ debugName: "borderWidth" }] : []));
18696
+ padding = computed(() => {
18697
+ return Number(this.configAsType()['padding'] ?? 16);
18698
+ }, ...(ngDevMode ? [{ debugName: "padding" }] : []));
18699
+ titleFontSize = computed(() => {
18700
+ return Number(this.styleConfig()['font-size-title'] ?? 18);
18701
+ }, ...(ngDevMode ? [{ debugName: "titleFontSize" }] : []));
18702
+ subtitleFontSize = computed(() => {
18703
+ return Number(this.configAsType()['subtitleFontSize'] ?? 14);
18704
+ }, ...(ngDevMode ? [{ debugName: "subtitleFontSize" }] : []));
18705
+ subtitleColor = computed(() => {
18706
+ return this.configAsType()['subtitleColor'] || '#666666';
18707
+ }, ...(ngDevMode ? [{ debugName: "subtitleColor" }] : []));
18708
+ breadcrumbs = computed(() => {
18709
+ const lang = this.languageCode();
18710
+ const params = this.queryParams();
18711
+ const raw = this.configAsType()['breadcrumb'];
18712
+ const fallbackLabel = dynamicTextReplace(this.defaultBreadcrumbLabel(), params) || this.title();
18713
+ if (!Array.isArray(raw))
18159
18714
  return [];
18160
- return [
18161
- {
18162
- ar: config.clientConfig?.title?.['ar'],
18163
- en: config.clientConfig?.title?.['en'],
18164
- },
18165
- ];
18166
- }, ...(ngDevMode ? [{ debugName: "tabs" }] : []));
18167
- /** Current tab data */
18168
- currentTabData = computed(() => {
18169
- const data = this.cardData();
18170
- const tab = this.tabSelected();
18171
- return data[tab] || [];
18172
- }, ...(ngDevMode ? [{ debugName: "currentTabData" }] : []));
18715
+ return raw
18716
+ .map((item) => {
18717
+ const rawLabel = typeof item?.label === 'string'
18718
+ ? item.label
18719
+ : item?.label?.[lang] ||
18720
+ item?.label?.['en'] ||
18721
+ item?.label?.['ar'] ||
18722
+ '';
18723
+ const rawLink = typeof item?.link === 'string' ? item.link : '';
18724
+ return {
18725
+ label: dynamicTextReplace(rawLabel, params) || fallbackLabel,
18726
+ link: dynamicTextReplace(rawLink, params),
18727
+ };
18728
+ })
18729
+ .filter((item) => item.label);
18730
+ }, ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : []));
18173
18731
  ngOnInit() {
18174
18732
  const id = this.dashboardId();
18175
- // Subscribe to configuration
18176
- this.subscription.add(this.storeService
18733
+ this.subscription.add(this.itemStoreService
18177
18734
  .selectItemProperty$(id, 'ConfigurationItem')
18178
18735
  .subscribe((config) => {
18179
18736
  if (config) {
18180
18737
  this.configurationItem.set(config);
18181
18738
  }
18182
18739
  }));
18183
- // Subscribe to data
18184
- this.subscription.add(this.storeService
18185
- .selectItemProperty$(id, 'DataHandled')
18186
- .subscribe((data) => {
18187
- if (data && Array.isArray(data)) {
18188
- this.cardData.set(data);
18189
- }
18190
- }));
18191
18740
  }
18192
18741
  ngOnDestroy() {
18193
18742
  this.subscription.unsubscribe();
18194
18743
  }
18195
- /**
18196
- * Get properties for card body (displayArea: levelCard_body)
18197
- */
18198
- getBodyProps(card) {
18199
- const hideProps = this.hideProperties();
18200
- return (card.props || [])
18201
- .filter((prop) => {
18202
- // Skip attachments - shown separately in gallery mode
18203
- if (prop.viewType === 'Attachment')
18204
- return false;
18205
- // Skip hidden properties
18206
- if (hideProps.includes(prop.key))
18207
- return false;
18208
- // Skip name and status - shown in header
18209
- const normalized = prop.normalizedKey?.toLowerCase();
18210
- if (normalized === 'name' || normalized === 'status')
18211
- return false;
18212
- // Check if should display in levelCard_body
18213
- const displayAreas = prop.displayAreas || prop.displayArea || [];
18214
- return displayAreas.some((area) => area?.key === 'levelCard_body');
18215
- })
18216
- .sort((a, b) => {
18217
- const aArea = (a.displayAreas || a.displayArea || []).find((area) => area?.key === 'levelCard_body');
18218
- const bArea = (b.displayAreas || b.displayArea || []).find((area) => area?.key === 'levelCard_body');
18219
- return (aArea?.order || 0) - (bArea?.order || 0);
18220
- });
18744
+ isExternalLink(link) {
18745
+ return /^https?:\/\//i.test(link);
18221
18746
  }
18222
- /**
18223
- * Get attachments for gallery mode
18224
- */
18225
- getAttachments(card) {
18226
- const attachmentProp = (card.props || []).find((p) => p.viewType === 'Attachment');
18227
- return attachmentProp?.value || [];
18228
- }
18229
- /**
18230
- * Check if card has any counters
18231
- */
18232
- hasCounters(card) {
18233
- return !!(card.issuesCounts || card.risksCounts || card.milestonesCounts);
18234
- }
18235
- /**
18236
- * Handle card click
18237
- */
18238
- onCardClick(card) {
18239
- this.onAction.emit({ type: 'click', data: card });
18240
- }
18241
- 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 });
18747
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TopbarCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18748
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TopbarCardComponent, isStandalone: true, selector: "mt-topbar-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null }, defaultBreadcrumbLabel: { classPropertyName: "defaultBreadcrumbLabel", publicName: "defaultBreadcrumbLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"flex h-full flex-col gap-3 md:flex-row md:items-center md:justify-between\"\n [style.background-color]=\"\n cardStyleConfig()['backgroundColor'] || styleConfig()['background-color']\n \"\n [style.border-radius.px]=\"cardStyleConfig()['borderRadius']\"\n [style.border-color]=\"borderColor()\"\n [style.border-style]=\"borderWidth() ? 'solid' : null\"\n [style.border-width.px]=\"borderWidth()\"\n [style.color]=\"styleConfig()['color'] || 'inherit'\"\n [style.padding.px]=\"padding()\"\n>\n <div class=\"flex min-w-0 flex-1 items-center gap-3\">\n @if (icon()) {\n <mt-avatar\n [icon]=\"icon()\"\n size=\"normal\"\n shape=\"square\"\n [style.--p-avatar-background]=\"iconBackgroundColor()\"\n [style.--p-avatar-color]=\"iconColor()\"\n />\n }\n\n <div class=\"min-w-0\">\n @if (title()) {\n <h3\n class=\"m-0 truncate font-semibold leading-tight\"\n [style.font-size.px]=\"titleFontSize()\"\n >\n {{ title() }}\n </h3>\n }\n\n @if (showSubtitle()) {\n <p\n class=\"m-0 truncate leading-tight\"\n [style.font-size.px]=\"subtitleFontSize()\"\n [style.color]=\"subtitleColor()\"\n >\n {{ subtitleText() }}\n </p>\n }\n </div>\n </div>\n\n @if (breadcrumbs().length > 0) {\n <nav class=\"min-w-0 md:max-w-[60%]\">\n <ol class=\"flex flex-wrap items-center gap-2 text-sm\">\n @for (\n breadcrumb of breadcrumbs();\n track breadcrumb.label + $index;\n let last = $last\n ) {\n <li class=\"flex min-w-0 items-center gap-2\">\n @if (breadcrumb.link) {\n <a\n class=\"max-w-[12rem] truncate text-muted-color transition-colors hover:text-primary\"\n [href]=\"breadcrumb.link\"\n [target]=\"isExternalLink(breadcrumb.link) ? '_blank' : null\"\n [rel]=\"isExternalLink(breadcrumb.link) ? 'noreferrer' : null\"\n >\n {{ breadcrumb.label }}\n </a>\n } @else {\n <span class=\"max-w-[12rem] truncate text-muted-color\">\n {{ breadcrumb.label }}\n </span>\n }\n\n @if (!last) {\n <i class=\"mti mti-chevron-right text-xs text-muted-color\"></i>\n }\n </li>\n }\n </ol>\n </nav>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
18243
18749
  }
18244
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: LevelCardListComponent, decorators: [{
18750
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TopbarCardComponent, decorators: [{
18245
18751
  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"] }]
18247
- }], 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"] }] } });
18752
+ args: [{ selector: 'mt-topbar-card', standalone: true, imports: [CommonModule, Avatar], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"flex h-full flex-col gap-3 md:flex-row md:items-center md:justify-between\"\n [style.background-color]=\"\n cardStyleConfig()['backgroundColor'] || styleConfig()['background-color']\n \"\n [style.border-radius.px]=\"cardStyleConfig()['borderRadius']\"\n [style.border-color]=\"borderColor()\"\n [style.border-style]=\"borderWidth() ? 'solid' : null\"\n [style.border-width.px]=\"borderWidth()\"\n [style.color]=\"styleConfig()['color'] || 'inherit'\"\n [style.padding.px]=\"padding()\"\n>\n <div class=\"flex min-w-0 flex-1 items-center gap-3\">\n @if (icon()) {\n <mt-avatar\n [icon]=\"icon()\"\n size=\"normal\"\n shape=\"square\"\n [style.--p-avatar-background]=\"iconBackgroundColor()\"\n [style.--p-avatar-color]=\"iconColor()\"\n />\n }\n\n <div class=\"min-w-0\">\n @if (title()) {\n <h3\n class=\"m-0 truncate font-semibold leading-tight\"\n [style.font-size.px]=\"titleFontSize()\"\n >\n {{ title() }}\n </h3>\n }\n\n @if (showSubtitle()) {\n <p\n class=\"m-0 truncate leading-tight\"\n [style.font-size.px]=\"subtitleFontSize()\"\n [style.color]=\"subtitleColor()\"\n >\n {{ subtitleText() }}\n </p>\n }\n </div>\n </div>\n\n @if (breadcrumbs().length > 0) {\n <nav class=\"min-w-0 md:max-w-[60%]\">\n <ol class=\"flex flex-wrap items-center gap-2 text-sm\">\n @for (\n breadcrumb of breadcrumbs();\n track breadcrumb.label + $index;\n let last = $last\n ) {\n <li class=\"flex min-w-0 items-center gap-2\">\n @if (breadcrumb.link) {\n <a\n class=\"max-w-[12rem] truncate text-muted-color transition-colors hover:text-primary\"\n [href]=\"breadcrumb.link\"\n [target]=\"isExternalLink(breadcrumb.link) ? '_blank' : null\"\n [rel]=\"isExternalLink(breadcrumb.link) ? 'noreferrer' : null\"\n >\n {{ breadcrumb.label }}\n </a>\n } @else {\n <span class=\"max-w-[12rem] truncate text-muted-color\">\n {{ breadcrumb.label }}\n </span>\n }\n\n @if (!last) {\n <i class=\"mti mti-chevron-right text-xs text-muted-color\"></i>\n }\n </li>\n }\n </ol>\n </nav>\n }\n</div>\n" }]
18753
+ }], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }], defaultBreadcrumbLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultBreadcrumbLabel", required: false }] }] } });
18248
18754
 
18249
18755
  class DashboardItem {
18250
18756
  storeService = inject(DashboardStoreService);
@@ -18263,6 +18769,8 @@ class DashboardItem {
18263
18769
  chartTypeId = input(undefined, ...(ngDevMode ? [{ debugName: "chartTypeId" }] : []));
18264
18770
  /** Read-only mode */
18265
18771
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
18772
+ /** Parent page/dashboard name for topbar breadcrumb fallbacks */
18773
+ pageName = input('', ...(ngDevMode ? [{ debugName: "pageName" }] : []));
18266
18774
  /** Whether this item is inside a group */
18267
18775
  inGroup = input(false, ...(ngDevMode ? [{ debugName: "inGroup" }] : []));
18268
18776
  /** Whether this item is rendered inside a dialog */
@@ -18553,25 +19061,24 @@ class DashboardItem {
18553
19061
  return merged;
18554
19062
  }
18555
19063
  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 });
19064
+ 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 }, pageName: { classPropertyName: "pageName", publicName: "pageName", 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-properties-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-properties-card>\r\n }\r\n\r\n @case (\"entitiesPreview\") {\r\n <mt-properties-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-properties-card>\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 <mt-topbar-card\r\n [dashboardId]=\"dashboardId()\"\r\n [defaultBreadcrumbLabel]=\"pageName()\"\r\n ></mt-topbar-card>\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 <!-- Entity Preview With Formula -->\r\n @case (\"entityPreviewWithFormula\") {\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: TopbarCardComponent, selector: "mt-topbar-card", inputs: ["dashboardId", "defaultBreadcrumbLabel"] }, { kind: "component", type: SkeletonCardComponent, selector: "mt-skeleton-card", inputs: ["dashboardId"] }, { kind: "component", type: PropertiesCardComponent, selector: "mt-properties-card, mt-entities-preview-card", inputs: ["dashboardId", "inGroup"], outputs: ["onAction"] }, { kind: "component", type: EntityPreviewCardComponent, selector: "mt-entity-preview-card", inputs: ["dashboardId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
18557
19065
  }
18558
19066
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardItem, decorators: [{
18559
19067
  type: Component,
18560
19068
  args: [{ selector: 'mt-dashboard-item', standalone: true, imports: [
18561
19069
  CommonModule,
18562
- TranslocoDirective,
18563
19070
  Button,
18564
19071
  Icon,
18565
19072
  ChartCardComponent,
18566
19073
  TableCardComponent,
18567
19074
  ListStatisticCardComponent,
18568
- StatisticCardComponent,
18569
19075
  HeaderCardComponent,
19076
+ TopbarCardComponent,
18570
19077
  SkeletonCardComponent,
19078
+ PropertiesCardComponent,
18571
19079
  EntityPreviewCardComponent,
18572
- 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"] }]
18574
- }], 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"] }] } });
19080
+ ], 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-properties-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-properties-card>\r\n }\r\n\r\n @case (\"entitiesPreview\") {\r\n <mt-properties-card\r\n [dashboardId]=\"dashboardId()\"\r\n [inGroup]=\"inGroup()\"\r\n (onAction)=\"doActions($event.data, $event.type)\"\r\n >\r\n </mt-properties-card>\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 <mt-topbar-card\r\n [dashboardId]=\"dashboardId()\"\r\n [defaultBreadcrumbLabel]=\"pageName()\"\r\n ></mt-topbar-card>\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 <!-- Entity Preview With Formula -->\r\n @case (\"entityPreviewWithFormula\") {\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"] }]
19081
+ }], 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 }] }], pageName: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageName", 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
19082
 
18576
19083
  /**
18577
19084
  * Chart Viewer Component
@@ -18594,11 +19101,11 @@ class ChartViewer {
18594
19101
  }, 500);
18595
19102
  }
18596
19103
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ChartViewer, deps: [], target: i0.ɵɵFactoryTarget.Component });
18597
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ChartViewer, isStandalone: true, selector: "mt-chart-viewer", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartTypeId: { classPropertyName: "chartTypeId", publicName: "chartTypeId", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"h-full flex flex-col bg-surface-50 border-l border-surface-200\">\r\n <!-- Header -->\r\n <div\r\n class=\"flex items-center justify-between px-4 py-3 bg-surface-0 border-b border-surface-200\"\r\n >\r\n <span class=\"text-sm font-medium text-surface-700\">{{\r\n t(\"preview\")\r\n }}</span>\r\n <mt-button\r\n icon=\"arrow.refresh-cw-01\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n severity=\"help\"\r\n [tooltip]=\"t('refresh')\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div class=\"flex-1 p-4 overflow-auto\">\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <mt-icon\r\n icon=\"general.loading-02\"\r\n class=\"text-3xl text-primary animate-spin\"\r\n />\r\n </div>\r\n } @else if (config() && chartTypeId()) {\r\n <div\r\n class=\"h-full bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden\"\r\n >\r\n <mt-dashboard-item\r\n [config]=\"config()\"\r\n [chartTypeId]=\"chartTypeId()\"\r\n [readonly]=\"true\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-full text-muted-color\"\r\n >\r\n <mt-icon icon=\"chart.bar-chart-10\" class=\"text-4xl mb-3 opacity-50\" />\r\n <p class=\"text-sm\">{{ t(\"noPreviewAvailable\") }}</p>\r\n <p class=\"text-xs opacity-70\">{{ t(\"configureChartToPreview\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-container>\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: 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: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19104
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ChartViewer, isStandalone: true, selector: "mt-chart-viewer", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartTypeId: { classPropertyName: "chartTypeId", publicName: "chartTypeId", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"h-full flex flex-col bg-surface-50 border-l border-surface-200\">\r\n <!-- Header -->\r\n <div\r\n class=\"flex items-center justify-between px-4 py-3 bg-surface-0 border-b border-surface-200\"\r\n >\r\n <span class=\"text-sm font-medium text-surface-700\">{{\r\n t(\"preview\")\r\n }}</span>\r\n <mt-button\r\n icon=\"arrow.refresh-cw-01\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n severity=\"help\"\r\n [tooltip]=\"t('refresh')\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div class=\"flex-1 p-4 overflow-auto\">\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <mt-icon\r\n icon=\"general.loading-02\"\r\n class=\"text-3xl text-primary animate-spin\"\r\n />\r\n </div>\r\n } @else if (config() && chartTypeId()) {\r\n <div\r\n class=\"h-full bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden\"\r\n >\r\n <mt-dashboard-item\r\n [config]=\"config()\"\r\n [chartTypeId]=\"chartTypeId()\"\r\n [readonly]=\"true\"\r\n [pageName]=\"\r\n config()?.clientConfig?.title?.['en'] ||\r\n config()?.clientConfig?.title?.['ar'] ||\r\n ''\r\n \"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-full text-muted-color\"\r\n >\r\n <mt-icon icon=\"chart.bar-chart-10\" class=\"text-4xl mb-3 opacity-50\" />\r\n <p class=\"text-sm\">{{ t(\"noPreviewAvailable\") }}</p>\r\n <p class=\"text-xs opacity-70\">{{ t(\"configureChartToPreview\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-container>\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: 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: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "pageName", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
18598
19105
  }
18599
19106
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ChartViewer, decorators: [{
18600
19107
  type: Component,
18601
- args: [{ selector: 'mt-chart-viewer', standalone: true, imports: [CommonModule, TranslocoDirective, Button, Icon, DashboardItem], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"h-full flex flex-col bg-surface-50 border-l border-surface-200\">\r\n <!-- Header -->\r\n <div\r\n class=\"flex items-center justify-between px-4 py-3 bg-surface-0 border-b border-surface-200\"\r\n >\r\n <span class=\"text-sm font-medium text-surface-700\">{{\r\n t(\"preview\")\r\n }}</span>\r\n <mt-button\r\n icon=\"arrow.refresh-cw-01\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n severity=\"help\"\r\n [tooltip]=\"t('refresh')\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div class=\"flex-1 p-4 overflow-auto\">\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <mt-icon\r\n icon=\"general.loading-02\"\r\n class=\"text-3xl text-primary animate-spin\"\r\n />\r\n </div>\r\n } @else if (config() && chartTypeId()) {\r\n <div\r\n class=\"h-full bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden\"\r\n >\r\n <mt-dashboard-item\r\n [config]=\"config()\"\r\n [chartTypeId]=\"chartTypeId()\"\r\n [readonly]=\"true\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-full text-muted-color\"\r\n >\r\n <mt-icon icon=\"chart.bar-chart-10\" class=\"text-4xl mb-3 opacity-50\" />\r\n <p class=\"text-sm\">{{ t(\"noPreviewAvailable\") }}</p>\r\n <p class=\"text-xs opacity-70\">{{ t(\"configureChartToPreview\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}\n"] }]
19108
+ args: [{ selector: 'mt-chart-viewer', standalone: true, imports: [CommonModule, TranslocoDirective, Button, Icon, DashboardItem], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"h-full flex flex-col bg-surface-50 border-l border-surface-200\">\r\n <!-- Header -->\r\n <div\r\n class=\"flex items-center justify-between px-4 py-3 bg-surface-0 border-b border-surface-200\"\r\n >\r\n <span class=\"text-sm font-medium text-surface-700\">{{\r\n t(\"preview\")\r\n }}</span>\r\n <mt-button\r\n icon=\"arrow.refresh-cw-01\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n severity=\"help\"\r\n [tooltip]=\"t('refresh')\"\r\n (onClick)=\"refresh()\"\r\n />\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div class=\"flex-1 p-4 overflow-auto\">\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <mt-icon\r\n icon=\"general.loading-02\"\r\n class=\"text-3xl text-primary animate-spin\"\r\n />\r\n </div>\r\n } @else if (config() && chartTypeId()) {\r\n <div\r\n class=\"h-full bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden\"\r\n >\r\n <mt-dashboard-item\r\n [config]=\"config()\"\r\n [chartTypeId]=\"chartTypeId()\"\r\n [readonly]=\"true\"\r\n [pageName]=\"\r\n config()?.clientConfig?.title?.['en'] ||\r\n config()?.clientConfig?.title?.['ar'] ||\r\n ''\r\n \"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-full text-muted-color\"\r\n >\r\n <mt-icon icon=\"chart.bar-chart-10\" class=\"text-4xl mb-3 opacity-50\" />\r\n <p class=\"text-sm\">{{ t(\"noPreviewAvailable\") }}</p>\r\n <p class=\"text-xs opacity-70\">{{ t(\"configureChartToPreview\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}\n"] }]
18602
19109
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], chartTypeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartTypeId", required: false }] }] } });
18603
19110
 
18604
19111
  /**
@@ -18676,6 +19183,8 @@ class ManageItem {
18676
19183
  // Check for dialog config data (when opened via DynamicDialog)
18677
19184
  const dialogData = this._dialogConfig?.data;
18678
19185
  const inputData = this.data();
19186
+ const services = inputData?.services ?? dialogData?.services ?? null;
19187
+ this._dashboardService.setModulesTreeServices(services);
18679
19188
  // Get pre-selected chart type if available
18680
19189
  const preselectedType = inputData?.chartType ?? dialogData?.chartType;
18681
19190
  if (dialogData?.chart) {
@@ -18724,6 +19233,9 @@ class ManageItem {
18724
19233
  this._manageItemService.updateClientConfig(partialConfig.clientConfig);
18725
19234
  }
18726
19235
  }
19236
+ onChartTypeChange(type) {
19237
+ this._manageItemService.selectType(type);
19238
+ }
18727
19239
  /** Update service config */
18728
19240
  onServiceConfigUpdate(partialConfig) {
18729
19241
  this._manageItemService.updateServiceConfig(partialConfig);
@@ -18733,7 +19245,7 @@ class ManageItem {
18733
19245
  this._manageItemService.updateClientConfig(partialConfig);
18734
19246
  }
18735
19247
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ManageItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
18736
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ManageItem, isStandalone: true, selector: "mt-manage-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ManageItemService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\r\n <!-- Main Layout: 60% Config | 40% Preview -->\r\n <div class=\"flex flex-1\">\r\n <!-- Left Side: Configuration (60%) -->\r\n <div class=\"w-[60%] flex flex-col border-r border-surface-200\">\r\n <!-- Content -->\r\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\r\n <!-- Chart Type Badge -->\r\n @if (selectedChartType()) {\r\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\r\n <span\r\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\r\n >\r\n <mt-icon\r\n [icon]=\"selectedChartType()?.icon\"\r\n class=\"text-xl\"\r\n ></mt-icon>\r\n </span>\r\n <div class=\"flex-1\">\r\n <h3 class=\"text-sm font-semibold text-surface-700\">\r\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\r\n </h3>\r\n <p class=\"text-xs text-muted-color\">\r\n {{ selectedChartType()?.name }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Tabs -->\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n\r\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\r\n <div [hidden]=\"activeTab() !== 'general'\">\r\n <mt-general-settings\r\n [config]=\"config()\"\r\n [isDialog]=\"isDialog()\"\r\n [hasPreselectedType]=\"hasPreselectedType()\"\r\n (configChange)=\"onConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'dataSource'\">\r\n <mt-data-source-settings\r\n [config]=\"config()\"\r\n [chartType]=\"selectedChartType()\"\r\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'actions'\">\r\n <mt-actions-settings\r\n [config]=\"config()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Chart Preview (40%) -->\r\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\r\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <!-- Validation Status -->\r\n <div class=\"flex items-center gap-2 text-sm flex-1\">\r\n @if (isValid()) {\r\n <span class=\"flex items-center gap-1 text-green-600\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"ready\") }}\r\n </span>\r\n } @else {\r\n <span class=\"flex items-center gap-1 text-amber-600\">\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"incomplete\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n [text]=\"true\"\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"!isValid()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: GeneralSettings, selector: "mt-general-settings", inputs: ["config", "isDialog", "hasPreselectedType"], outputs: ["configChange", "chartTypeChange"] }, { kind: "component", type: DataSourceSettings, selector: "mt-data-source-settings", inputs: ["config", "chartType"], outputs: ["serviceConfigChange"] }, { kind: "component", type: ActionsSettings, selector: "mt-actions-settings", inputs: ["config"], outputs: ["clientConfigChange"] }, { kind: "component", type: ChartViewer, selector: "mt-chart-viewer", inputs: ["config", "chartTypeId"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19248
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ManageItem, isStandalone: true, selector: "mt-manage-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ManageItemService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\r\n <!-- Main Layout: 60% Config | 40% Preview -->\r\n <div class=\"flex flex-1\">\r\n <!-- Left Side: Configuration (60%) -->\r\n <div class=\"w-[60%] flex flex-col border-r border-surface-200\">\r\n <!-- Content -->\r\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\r\n <!-- Chart Type Badge -->\r\n @if (selectedChartType()) {\r\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\r\n <span\r\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\r\n >\r\n <mt-icon\r\n [icon]=\"selectedChartType()?.icon\"\r\n class=\"text-xl\"\r\n ></mt-icon>\r\n </span>\r\n <div class=\"flex-1\">\r\n <h3 class=\"text-sm font-semibold text-surface-700\">\r\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\r\n </h3>\r\n <p class=\"text-xs text-muted-color\">\r\n {{ selectedChartType()?.name }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Tabs -->\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n\r\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\r\n <div [hidden]=\"activeTab() !== 'general'\">\r\n <mt-general-settings\r\n [config]=\"config()\"\r\n [isDialog]=\"isDialog()\"\r\n [hasPreselectedType]=\"hasPreselectedType()\"\r\n (configChange)=\"onConfigUpdate($event)\"\r\n (chartTypeChange)=\"onChartTypeChange($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'dataSource'\">\r\n <mt-data-source-settings\r\n [config]=\"config()\"\r\n [chartType]=\"selectedChartType()\"\r\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'actions'\">\r\n <mt-actions-settings\r\n [config]=\"config()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Chart Preview (40%) -->\r\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\r\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <!-- Validation Status -->\r\n <div class=\"flex items-center gap-2 text-sm flex-1\">\r\n @if (isValid()) {\r\n <span class=\"flex items-center gap-1 text-green-600\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"ready\") }}\r\n </span>\r\n } @else {\r\n <span class=\"flex items-center gap-1 text-amber-600\">\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"incomplete\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n [text]=\"true\"\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"!isValid()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: GeneralSettings, selector: "mt-general-settings", inputs: ["config", "isDialog", "hasPreselectedType"], outputs: ["configChange", "chartTypeChange"] }, { kind: "component", type: DataSourceSettings, selector: "mt-data-source-settings", inputs: ["config", "chartType"], outputs: ["serviceConfigChange"] }, { kind: "component", type: ActionsSettings, selector: "mt-actions-settings", inputs: ["config"], outputs: ["clientConfigChange"] }, { kind: "component", type: ChartViewer, selector: "mt-chart-viewer", inputs: ["config", "chartTypeId"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
18737
19249
  }
18738
19250
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ManageItem, decorators: [{
18739
19251
  type: Component,
@@ -18743,16 +19255,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
18743
19255
  TranslocoDirective,
18744
19256
  Button,
18745
19257
  Tabs,
18746
- Card,
18747
- TextField,
18748
- SelectField,
18749
- CheckboxField,
18750
19258
  GeneralSettings,
18751
19259
  DataSourceSettings,
18752
19260
  ActionsSettings,
18753
19261
  ChartViewer,
18754
19262
  Icon,
18755
- ], providers: [ManageItemService], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\r\n <!-- Main Layout: 60% Config | 40% Preview -->\r\n <div class=\"flex flex-1\">\r\n <!-- Left Side: Configuration (60%) -->\r\n <div class=\"w-[60%] flex flex-col border-r border-surface-200\">\r\n <!-- Content -->\r\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\r\n <!-- Chart Type Badge -->\r\n @if (selectedChartType()) {\r\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\r\n <span\r\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\r\n >\r\n <mt-icon\r\n [icon]=\"selectedChartType()?.icon\"\r\n class=\"text-xl\"\r\n ></mt-icon>\r\n </span>\r\n <div class=\"flex-1\">\r\n <h3 class=\"text-sm font-semibold text-surface-700\">\r\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\r\n </h3>\r\n <p class=\"text-xs text-muted-color\">\r\n {{ selectedChartType()?.name }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Tabs -->\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n\r\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\r\n <div [hidden]=\"activeTab() !== 'general'\">\r\n <mt-general-settings\r\n [config]=\"config()\"\r\n [isDialog]=\"isDialog()\"\r\n [hasPreselectedType]=\"hasPreselectedType()\"\r\n (configChange)=\"onConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'dataSource'\">\r\n <mt-data-source-settings\r\n [config]=\"config()\"\r\n [chartType]=\"selectedChartType()\"\r\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'actions'\">\r\n <mt-actions-settings\r\n [config]=\"config()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Chart Preview (40%) -->\r\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\r\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <!-- Validation Status -->\r\n <div class=\"flex items-center gap-2 text-sm flex-1\">\r\n @if (isValid()) {\r\n <span class=\"flex items-center gap-1 text-green-600\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"ready\") }}\r\n </span>\r\n } @else {\r\n <span class=\"flex items-center gap-1 text-amber-600\">\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"incomplete\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n [text]=\"true\"\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"!isValid()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</ng-container>\r\n" }]
19263
+ ], providers: [ManageItemService], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\r\n <!-- Main Layout: 60% Config | 40% Preview -->\r\n <div class=\"flex flex-1\">\r\n <!-- Left Side: Configuration (60%) -->\r\n <div class=\"w-[60%] flex flex-col border-r border-surface-200\">\r\n <!-- Content -->\r\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\r\n <!-- Chart Type Badge -->\r\n @if (selectedChartType()) {\r\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\r\n <span\r\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\r\n >\r\n <mt-icon\r\n [icon]=\"selectedChartType()?.icon\"\r\n class=\"text-xl\"\r\n ></mt-icon>\r\n </span>\r\n <div class=\"flex-1\">\r\n <h3 class=\"text-sm font-semibold text-surface-700\">\r\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\r\n </h3>\r\n <p class=\"text-xs text-muted-color\">\r\n {{ selectedChartType()?.name }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Tabs -->\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n\r\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\r\n <div [hidden]=\"activeTab() !== 'general'\">\r\n <mt-general-settings\r\n [config]=\"config()\"\r\n [isDialog]=\"isDialog()\"\r\n [hasPreselectedType]=\"hasPreselectedType()\"\r\n (configChange)=\"onConfigUpdate($event)\"\r\n (chartTypeChange)=\"onChartTypeChange($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'dataSource'\">\r\n <mt-data-source-settings\r\n [config]=\"config()\"\r\n [chartType]=\"selectedChartType()\"\r\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'actions'\">\r\n <mt-actions-settings\r\n [config]=\"config()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Chart Preview (40%) -->\r\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\r\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <!-- Validation Status -->\r\n <div class=\"flex items-center gap-2 text-sm flex-1\">\r\n @if (isValid()) {\r\n <span class=\"flex items-center gap-1 text-green-600\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"ready\") }}\r\n </span>\r\n } @else {\r\n <span class=\"flex items-center gap-1 text-amber-600\">\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"incomplete\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n [text]=\"true\"\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"!isValid()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</ng-container>\r\n" }]
18756
19264
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
18757
19265
 
18758
19266
  /**
@@ -18795,20 +19303,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
18795
19303
  class WidgetPaletteComponent {
18796
19304
  modal = inject(ModalService);
18797
19305
  ref = inject(ModalRef, { optional: true });
19306
+ translocoService = inject(TranslocoService);
18798
19307
  /** Product filter - filters chart types by product (pplus, splus, report) */
18799
19308
  product = input(null, ...(ngDevMode ? [{ debugName: "product" }] : []));
18800
19309
  /** Search filter */
18801
19310
  searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
18802
19311
  /** Active tab (category) */
18803
- activeTab = signal('chart', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
19312
+ activeTab = signal('layout', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
18804
19313
  /** 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
- ];
19314
+ tabOptions = computed(() => [
19315
+ {
19316
+ label: this.translocoService.translate('dashboardBuilder.categoryLayout'),
19317
+ value: 'layout',
19318
+ },
19319
+ {
19320
+ label: this.translocoService.translate('dashboardBuilder.categoryCommon'),
19321
+ value: 'special',
19322
+ },
19323
+ {
19324
+ label: this.translocoService.translate('dashboardBuilder.categoryCharts'),
19325
+ value: 'chart',
19326
+ },
19327
+ {
19328
+ label: this.translocoService.translate('dashboardBuilder.categoryTables'),
19329
+ value: 'table',
19330
+ },
19331
+ ], ...(ngDevMode ? [{ debugName: "tabOptions" }] : []));
18812
19332
  /** All chart types filtered by product */
18813
19333
  filteredChartTypes = computed(() => {
18814
19334
  const prod = this.product();
@@ -18838,7 +19358,6 @@ class WidgetPaletteComponent {
18838
19358
  const types = this.filteredChartTypes().filter((t) => !t.hideInList);
18839
19359
  return {
18840
19360
  chart: types.filter((t) => t.category === 'chart').length,
18841
- card: types.filter((t) => t.category === 'card').length,
18842
19361
  table: types.filter((t) => t.category === 'table').length,
18843
19362
  special: types.filter((t) => t.category === 'special').length,
18844
19363
  layout: types.filter((t) => t.category === 'layout').length,
@@ -18870,11 +19389,11 @@ class WidgetPaletteComponent {
18870
19389
  this.ref?.close(null);
18871
19390
  }
18872
19391
  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 });
19392
+ 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
19393
  }
18875
19394
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WidgetPaletteComponent, decorators: [{
18876
19395
  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" }]
19396
+ 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
19397
  }], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: false }] }] } });
18879
19398
 
18880
19399
  /**
@@ -18907,6 +19426,8 @@ class DashboardBuilder {
18907
19426
  pageId = input(null, ...(ngDevMode ? [{ debugName: "pageId" }] : []));
18908
19427
  /** Standalone mode (when true, builder runs without API calls) */
18909
19428
  standalone = input(false, ...(ngDevMode ? [{ debugName: "standalone" }] : []));
19429
+ /** Optional services filter used by manage-item metadata tree loading */
19430
+ services = input(null, ...(ngDevMode ? [{ debugName: "services" }] : []));
18910
19431
  /** Standalone dashboard data model */
18911
19432
  dashboardData = model(null, ...(ngDevMode ? [{ debugName: "dashboardData" }] : []));
18912
19433
  /** Read-only mode */
@@ -19027,6 +19548,9 @@ class DashboardBuilder {
19027
19548
  dragStartY = 0;
19028
19549
  applyingDashboardData = false;
19029
19550
  emittingDashboardData = false;
19551
+ boundHandleDragOver = (event) => this.handleDragOver(event);
19552
+ boundHandleDrop = (event) => this.handleDrop(event);
19553
+ boundHandleDragEnd = (event) => this.handleDragEnd(event);
19030
19554
  // ============================================
19031
19555
  // Context Menu Items
19032
19556
  // ============================================
@@ -19076,14 +19600,14 @@ class DashboardBuilder {
19076
19600
  this.storeService.updateStopActions(false);
19077
19601
  }
19078
19602
  setupEventListeners() {
19079
- window.addEventListener('dragover', this.handleDragOver.bind(this));
19080
- window.addEventListener('drop', this.handleDrop.bind(this));
19081
- window.addEventListener('dragend', this.handleDragEnd.bind(this));
19603
+ window.addEventListener('dragover', this.boundHandleDragOver);
19604
+ window.addEventListener('drop', this.boundHandleDrop);
19605
+ window.addEventListener('dragend', this.boundHandleDragEnd);
19082
19606
  }
19083
19607
  removeEventListeners() {
19084
- window.removeEventListener('dragover', this.handleDragOver);
19085
- window.removeEventListener('drop', this.handleDrop);
19086
- window.removeEventListener('dragend', this.handleDragEnd);
19608
+ window.removeEventListener('dragover', this.boundHandleDragOver);
19609
+ window.removeEventListener('drop', this.boundHandleDrop);
19610
+ window.removeEventListener('dragend', this.boundHandleDragEnd);
19087
19611
  }
19088
19612
  loadPageIfNeeded() {
19089
19613
  if (this.standalone()) {
@@ -19392,7 +19916,10 @@ class DashboardBuilder {
19392
19916
  position: 'end',
19393
19917
  dismissible: true,
19394
19918
  inputValues: {
19395
- data: { isNew: true },
19919
+ data: {
19920
+ isNew: true,
19921
+ services: this.services(),
19922
+ },
19396
19923
  },
19397
19924
  });
19398
19925
  ref.onClose.subscribe((result) => {
@@ -19411,7 +19938,12 @@ class DashboardBuilder {
19411
19938
  dismissible: true,
19412
19939
  position: 'end',
19413
19940
  inputValues: {
19414
- data: { chart, isDialog: false, isNew: false },
19941
+ data: {
19942
+ chart,
19943
+ isDialog: false,
19944
+ isNew: false,
19945
+ services: this.services(),
19946
+ },
19415
19947
  },
19416
19948
  });
19417
19949
  ref.onClose.subscribe((result) => {
@@ -19609,7 +20141,7 @@ class DashboardBuilder {
19609
20141
  header: this.transloco.translate('dashboardBuilder.widgetPalette.title'),
19610
20142
  styleClass: '!w-1/3 !absolute',
19611
20143
  dismissible: true,
19612
- modal: false,
20144
+ modal: true,
19613
20145
  appendTo: '#page-content',
19614
20146
  });
19615
20147
  this.widgetPaletteRef.onClose.subscribe((result) => {
@@ -19674,6 +20206,7 @@ class DashboardBuilder {
19674
20206
  isNew: true,
19675
20207
  chartType: widgetType, // Pass the pre-selected type
19676
20208
  defaultSize: widgetType.defaultSize,
20209
+ services: this.services(),
19677
20210
  },
19678
20211
  },
19679
20212
  });
@@ -19820,6 +20353,7 @@ class DashboardBuilder {
19820
20353
  },
19821
20354
  isDialog: true,
19822
20355
  isNew: false,
20356
+ services: this.services(),
19823
20357
  },
19824
20358
  },
19825
20359
  });
@@ -20042,7 +20576,7 @@ class DashboardBuilder {
20042
20576
  this.emittingDashboardData = false;
20043
20577
  }
20044
20578
  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 });
20579
+ 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 [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\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 [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\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", "pageName", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }, { kind: "pipe", type: FilterByGroupPipe, name: "filterByGroup" }, { kind: "pipe", type: GetChartActionsPipe, name: "getChartActions" }], encapsulation: i0.ViewEncapsulation.None });
20046
20580
  }
20047
20581
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardBuilder, decorators: [{
20048
20582
  type: Component,
@@ -20052,18 +20586,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
20052
20586
  TranslocoDirective,
20053
20587
  GridsterModule,
20054
20588
  Button,
20055
- Tabs,
20056
- Card,
20057
- Tooltip,
20058
20589
  Page,
20059
- Menu,
20060
20590
  Popover,
20061
20591
  ContextMenuModule,
20062
20592
  FilterByGroupPipe,
20063
20593
  GetChartActionsPipe,
20064
20594
  DashboardItem,
20065
- ], 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: [{
20595
+ ], 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 [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\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 [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\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"] }]
20596
+ }], 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
20597
  type: HostListener,
20068
20598
  args: ['window:keydown', ['$event']]
20069
20599
  }] } });
@@ -20405,12 +20935,6 @@ class DashboardViewer {
20405
20935
  getItemIcon(item) {
20406
20936
  return item.config?.clientConfig?.configAsType?.icon || null;
20407
20937
  }
20408
- /**
20409
- * Get breadcrumb items for topbar
20410
- */
20411
- getBreadcrumb(item) {
20412
- return item.config?.clientConfig?.configAsType?.breadcrumb || [];
20413
- }
20414
20938
  /**
20415
20939
  * Get chart type
20416
20940
  */
@@ -20454,7 +20978,7 @@ class DashboardViewer {
20454
20978
  });
20455
20979
  }
20456
20980
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardViewer, deps: [], target: i0.ɵɵFactoryTarget.Component });
20457
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardViewer, isStandalone: true, selector: "mt-dashboard-viewer", 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 }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: false, transformFunction: null }, chartsData: { classPropertyName: "chartsData", publicName: "chartsData", isSignal: true, isRequired: false, transformFunction: null }, dialogsData: { classPropertyName: "dialogsData", publicName: "dialogsData", isSignal: true, isRequired: false, transformFunction: null }, filtersData: { classPropertyName: "filtersData", publicName: "filtersData", isSignal: true, isRequired: false, transformFunction: null }, extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: true, isRequired: false, transformFunction: null }, showFilters: { classPropertyName: "showFilters", publicName: "showFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageLoaded: "pageLoaded", onBack: "onBack", chartClick: "chartClick" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\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('dashboard')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n }\r\n\r\n <!-- Reusable viewer content template -->\r\n <ng-template #viewerContent>\r\n <div class=\"relative h-full min-h-[600px] mt-dashboard-viewer\">\r\n @if (!loading() && hasRenderableContent()) {\r\n <div class=\"dashboard-viewer-layout-wrapper\">\r\n <div\r\n class=\"dashboard-viewer-layout\"\r\n [style.min-height]=\"layoutHeight()\"\r\n >\r\n @for (\r\n item of visibleItems();\r\n track trackByDashboardId($index, item)\r\n ) {\r\n <div\r\n class=\"dashboard-viewer-item\"\r\n [class.dashboard-viewer-item--group]=\"isGroup(item)\"\r\n [class.dashboard-viewer-item--header]=\"isHeader(item)\"\r\n [class.dashboard-viewer-item--topbar]=\"isTopbar(item)\"\r\n [style.grid-column]=\"getGridColumn(item)\"\r\n [style.grid-row]=\"getGridRow(item)\"\r\n >\r\n <!-- Group Container -->\r\n @if (isGroup(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"group-container h-full flex flex-col rounded-lg border border-surface-200 overflow-hidden\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'var(--surface-card)'\r\n \"\r\n >\r\n <!-- Group Header with Tabs -->\r\n <div\r\n class=\"group-header flex items-center justify-between px-4 py-2 bg-surface-50 border-b border-surface-200\"\r\n >\r\n <span class=\"font-medium text-sm\">{{\r\n getGroupTitle(item)\r\n }}</span>\r\n <div class=\"group-tabs flex items-center gap-1\">\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let gIndex = $index\r\n ) {\r\n @if (getItemIcon(child); as icon) {\r\n <button\r\n type=\"button\"\r\n class=\"w-8 h-8 flex items-center justify-center rounded transition-colors\"\r\n [class.bg-primary-100]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-primary-600]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-muted-color]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [class.hover:bg-surface-100]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n >\r\n <i class=\"mti mti-{{ icon }}\"></i>\r\n </button>\r\n } @else {\r\n <button\r\n pButton\r\n type=\"button\"\r\n class=\"p-button-text p-button-sm\"\r\n [class.p-button-primary]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.p-button-secondary]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [label]=\"getItemTitle(child)\"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n ></button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Group Body - Selected Child Content -->\r\n <div class=\"group-body flex-1 min-h-0\">\r\n @if (\r\n item.selectedGroupIndex !== null &&\r\n item.selectedGroupIndex !== undefined\r\n ) {\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let cIndex = $index\r\n ) {\r\n @if (\r\n cIndex === item.selectedGroupIndex &&\r\n !child.loading\r\n ) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"child.config\"\r\n [chartTypeId]=\"\r\n child.config?.serviceConfig?.dashboardId ||\r\n child.id\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig\r\n ?.ignoreQueryFilter ?? false\r\n \"\r\n [inGroup]=\"true\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n <!-- Header Item -->\r\n @else if (isHeader(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"header-item flex items-center h-full px-4 border-b-2 border-primary\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'transparent'\r\n \"\r\n [style.color]=\"getStyleConfig(item)['color'] || 'inherit'\"\r\n >\r\n <h3 class=\"font-semibold text-lg m-0\">\r\n {{ getItemTitle(item) }}\r\n </h3>\r\n </div>\r\n }\r\n }\r\n <!-- Topbar Item -->\r\n @else if (isTopbar(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"topbar-item flex items-center h-full px-4 bg-surface-50\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'var(--surface-50)'\r\n \"\r\n >\r\n <nav class=\"flex items-center gap-2 text-sm\">\r\n @for (\r\n crumb of getBreadcrumb(item);\r\n track $index;\r\n let last = $last\r\n ) {\r\n <span\r\n class=\"text-muted-color hover:text-primary cursor-pointer transition-colors\"\r\n >\r\n {{\r\n crumb.label?.[languageCode()] ||\r\n crumb.label?.[\"en\"] ||\r\n crumb.label\r\n }}\r\n </span>\r\n @if (!last) {\r\n <i\r\n class=\"mti mti-chevron-right text-xs text-muted-color\"\r\n ></i>\r\n }\r\n }\r\n @if (getBreadcrumb(item).length === 0) {\r\n <span class=\"text-muted-color italic\">{{\r\n t(\"noBreadcrumb\")\r\n }}</span>\r\n }\r\n </nav>\r\n </div>\r\n }\r\n }\r\n <!-- Regular Chart Item -->\r\n @else {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden Dialogs (for modal rendering) -->\r\n @if (dialogs().length > 0) {\r\n <div class=\"hidden\">\r\n @for (\r\n dialog of dialogs();\r\n track dialog.config?.serviceConfig?.dashboardId\r\n ) {\r\n <!-- Dialog placeholder - will be rendered in modal when triggered -->\r\n <div\r\n [attr.data-dialog-id]=\"\r\n dialog.config?.serviceConfig?.dashboardId\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Filters Sidebar Placeholder -->\r\n @if (showFilters() && filters().length > 0) {\r\n <div\r\n class=\"filters-sidebar fixed end-0 top-0 bottom-0 w-64 bg-surface-card border-s border-surface-200 p-4 shadow-lg z-50 hidden\"\r\n >\r\n <!-- Filter sidebar content - integrate with actual filter component -->\r\n <h4 class=\"font-semibold mb-4\">{{ t(\"filters\") }}</h4>\r\n @for (filter of filters(); track $index) {\r\n <div class=\"filter-item mb-3 p-2 bg-surface-50 rounded\">\r\n <span class=\"text-sm\">{{\r\n filter.label || filter.propertyKey\r\n }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n } @else if (loading()) {\r\n <!-- Loading State -->\r\n <div class=\"flex items-center justify-center h-64\">\r\n <div class=\"text-center\">\r\n <i\r\n class=\"mti mti-loader-2 text-4xl text-primary animate-spin mb-2\"\r\n ></i>\r\n <p class=\"text-muted-color\">{{ t(\"loading\") }}</p>\r\n </div>\r\n </div>\r\n } @else {\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: [".mt-dashboard-viewer{width:100%;height:100%}.dashboard-viewer-layout-wrapper{width:100%}.dashboard-viewer-layout{display:grid;grid-template-columns:repeat(36,minmax(0,1fr));grid-auto-rows:60px;gap:10px;width:100%;align-items:stretch}.dashboard-viewer-item{display:flex;min-width:0;min-height:0}.dashboard-viewer-item>*{width:100%;height:100%}.dashboard-viewer-content-item{display:block;flex:1 1 auto;min-width:0;min-height:0;width:100%;height:100%}.dashboard-viewer-item--header{z-index:1}.dashboard-viewer-item--topbar{z-index:2}.group-container{background-color:var(--surface-card)}.group-header{flex-shrink:0}.group-tabs{flex-wrap:wrap}.group-body{background-color:var(--surface-0)}.header-item{background-color:transparent}.topbar-item{background-color:var(--surface-50)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.filters-sidebar{transform:translate(100%);transition:transform .3s ease-in-out}.filters-sidebar.open{transform:translate(0)}[dir=rtl] .filters-sidebar{transform:translate(-100%)}[dir=rtl] .filters-sidebar.open{transform:translate(0)}.table-responsive{max-height:75vh;overflow-y:auto;overflow-x:auto}.modal-content{border:0!important}.custom-donut-chart{display:flex;justify-content:center;height:auto!important}.custom-donut-chart canvas{margin-top:-1.5rem!important}@media(max-width:768px){.dashboard-viewer-layout{display:flex;flex-direction:column;min-height:0!important}.dashboard-viewer-item{min-height:220px}.dashboard-viewer-item--header,.dashboard-viewer-item--topbar{min-height:72px}.dashboard-viewer-item--group{min-height:280px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$3.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20981
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardViewer, isStandalone: true, selector: "mt-dashboard-viewer", 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 }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: false, transformFunction: null }, chartsData: { classPropertyName: "chartsData", publicName: "chartsData", isSignal: true, isRequired: false, transformFunction: null }, dialogsData: { classPropertyName: "dialogsData", publicName: "dialogsData", isSignal: true, isRequired: false, transformFunction: null }, filtersData: { classPropertyName: "filtersData", publicName: "filtersData", isSignal: true, isRequired: false, transformFunction: null }, extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: true, isRequired: false, transformFunction: null }, showFilters: { classPropertyName: "showFilters", publicName: "showFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageLoaded: "pageLoaded", onBack: "onBack", chartClick: "chartClick" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\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('dashboard')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n }\r\n\r\n <!-- Reusable viewer content template -->\r\n <ng-template #viewerContent>\r\n <div class=\"relative h-full min-h-[600px] mt-dashboard-viewer\">\r\n @if (!loading() && hasRenderableContent()) {\r\n <div class=\"dashboard-viewer-layout-wrapper\">\r\n <div\r\n class=\"dashboard-viewer-layout\"\r\n [style.min-height]=\"layoutHeight()\"\r\n >\r\n @for (\r\n item of visibleItems();\r\n track trackByDashboardId($index, item)\r\n ) {\r\n <div\r\n class=\"dashboard-viewer-item\"\r\n [class.dashboard-viewer-item--group]=\"isGroup(item)\"\r\n [class.dashboard-viewer-item--header]=\"isHeader(item)\"\r\n [class.dashboard-viewer-item--topbar]=\"isTopbar(item)\"\r\n [style.grid-column]=\"getGridColumn(item)\"\r\n [style.grid-row]=\"getGridRow(item)\"\r\n >\r\n <!-- Group Container -->\r\n @if (isGroup(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"group-container h-full flex flex-col rounded-lg border border-surface-200 overflow-hidden\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'var(--surface-card)'\r\n \"\r\n >\r\n <!-- Group Header with Tabs -->\r\n <div\r\n class=\"group-header flex items-center justify-between px-4 py-2 bg-surface-50 border-b border-surface-200\"\r\n >\r\n <span class=\"font-medium text-sm\">{{\r\n getGroupTitle(item)\r\n }}</span>\r\n <div class=\"group-tabs flex items-center gap-1\">\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let gIndex = $index\r\n ) {\r\n @if (getItemIcon(child); as icon) {\r\n <button\r\n type=\"button\"\r\n class=\"w-8 h-8 flex items-center justify-center rounded transition-colors\"\r\n [class.bg-primary-100]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-primary-600]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-muted-color]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [class.hover:bg-surface-100]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n >\r\n <i class=\"mti mti-{{ icon }}\"></i>\r\n </button>\r\n } @else {\r\n <button\r\n pButton\r\n type=\"button\"\r\n class=\"p-button-text p-button-sm\"\r\n [class.p-button-primary]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.p-button-secondary]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [label]=\"getItemTitle(child)\"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n ></button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Group Body - Selected Child Content -->\r\n <div class=\"group-body flex-1 min-h-0\">\r\n @if (\r\n item.selectedGroupIndex !== null &&\r\n item.selectedGroupIndex !== undefined\r\n ) {\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let cIndex = $index\r\n ) {\r\n @if (\r\n cIndex === item.selectedGroupIndex &&\r\n !child.loading\r\n ) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"child.config\"\r\n [chartTypeId]=\"\r\n child.config?.serviceConfig?.dashboardId ||\r\n child.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig\r\n ?.ignoreQueryFilter ?? false\r\n \"\r\n [inGroup]=\"true\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n <!-- Header Item -->\r\n @else if (isHeader(item)) {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n <!-- Topbar Item -->\r\n @else if (isTopbar(item)) {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n <!-- Regular Chart Item -->\r\n @else {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden Dialogs (for modal rendering) -->\r\n @if (dialogs().length > 0) {\r\n <div class=\"hidden\">\r\n @for (\r\n dialog of dialogs();\r\n track dialog.config?.serviceConfig?.dashboardId\r\n ) {\r\n <!-- Dialog placeholder - will be rendered in modal when triggered -->\r\n <div\r\n [attr.data-dialog-id]=\"\r\n dialog.config?.serviceConfig?.dashboardId\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Filters Sidebar Placeholder -->\r\n @if (showFilters() && filters().length > 0) {\r\n <div\r\n class=\"filters-sidebar fixed end-0 top-0 bottom-0 w-64 bg-surface-card border-s border-surface-200 p-4 shadow-lg z-50 hidden\"\r\n >\r\n <!-- Filter sidebar content - integrate with actual filter component -->\r\n <h4 class=\"font-semibold mb-4\">{{ t(\"filters\") }}</h4>\r\n @for (filter of filters(); track $index) {\r\n <div class=\"filter-item mb-3 p-2 bg-surface-50 rounded\">\r\n <span class=\"text-sm\">{{\r\n filter.label || filter.propertyKey\r\n }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n } @else if (loading()) {\r\n <!-- Loading State -->\r\n <div class=\"flex items-center justify-center h-64\">\r\n <div class=\"text-center\">\r\n <i\r\n class=\"mti mti-loader-2 text-4xl text-primary animate-spin mb-2\"\r\n ></i>\r\n <p class=\"text-muted-color\">{{ t(\"loading\") }}</p>\r\n </div>\r\n </div>\r\n } @else {\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: [".mt-dashboard-viewer{width:100%;height:100%}.dashboard-viewer-layout-wrapper{width:100%}.dashboard-viewer-layout{display:grid;grid-template-columns:repeat(36,minmax(0,1fr));grid-auto-rows:60px;gap:10px;width:100%;align-items:stretch}.dashboard-viewer-item{display:flex;min-width:0;min-height:0}.dashboard-viewer-item>*{width:100%;height:100%}.dashboard-viewer-content-item{display:block;flex:1 1 auto;min-width:0;min-height:0;width:100%;height:100%}.dashboard-viewer-item--header{z-index:1}.dashboard-viewer-item--topbar{z-index:2}.group-container{background-color:var(--surface-card)}.group-header{flex-shrink:0}.group-tabs{flex-wrap:wrap}.group-body{background-color:var(--surface-0)}.header-item{background-color:transparent}.topbar-item{background-color:var(--surface-50)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.filters-sidebar{transform:translate(100%);transition:transform .3s ease-in-out}.filters-sidebar.open{transform:translate(0)}[dir=rtl] .filters-sidebar{transform:translate(-100%)}[dir=rtl] .filters-sidebar.open{transform:translate(0)}.table-responsive{max-height:75vh;overflow-y:auto;overflow-x:auto}.modal-content{border:0!important}.custom-donut-chart{display:flex;justify-content:center;height:auto!important}.custom-donut-chart canvas{margin-top:-1.5rem!important}@media(max-width:768px){.dashboard-viewer-layout{display:flex;flex-direction:column;min-height:0!important}.dashboard-viewer-item{min-height:220px}.dashboard-viewer-item--header,.dashboard-viewer-item--topbar{min-height:72px}.dashboard-viewer-item--group{min-height:280px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2$3.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "pageName", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter"], outputs: ["actionTriggered"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20458
20982
  }
20459
20983
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardViewer, decorators: [{
20460
20984
  type: Component,
@@ -20464,7 +20988,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
20464
20988
  ButtonModule,
20465
20989
  DashboardItem,
20466
20990
  Page,
20467
- ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\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('dashboard')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n }\r\n\r\n <!-- Reusable viewer content template -->\r\n <ng-template #viewerContent>\r\n <div class=\"relative h-full min-h-[600px] mt-dashboard-viewer\">\r\n @if (!loading() && hasRenderableContent()) {\r\n <div class=\"dashboard-viewer-layout-wrapper\">\r\n <div\r\n class=\"dashboard-viewer-layout\"\r\n [style.min-height]=\"layoutHeight()\"\r\n >\r\n @for (\r\n item of visibleItems();\r\n track trackByDashboardId($index, item)\r\n ) {\r\n <div\r\n class=\"dashboard-viewer-item\"\r\n [class.dashboard-viewer-item--group]=\"isGroup(item)\"\r\n [class.dashboard-viewer-item--header]=\"isHeader(item)\"\r\n [class.dashboard-viewer-item--topbar]=\"isTopbar(item)\"\r\n [style.grid-column]=\"getGridColumn(item)\"\r\n [style.grid-row]=\"getGridRow(item)\"\r\n >\r\n <!-- Group Container -->\r\n @if (isGroup(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"group-container h-full flex flex-col rounded-lg border border-surface-200 overflow-hidden\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'var(--surface-card)'\r\n \"\r\n >\r\n <!-- Group Header with Tabs -->\r\n <div\r\n class=\"group-header flex items-center justify-between px-4 py-2 bg-surface-50 border-b border-surface-200\"\r\n >\r\n <span class=\"font-medium text-sm\">{{\r\n getGroupTitle(item)\r\n }}</span>\r\n <div class=\"group-tabs flex items-center gap-1\">\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let gIndex = $index\r\n ) {\r\n @if (getItemIcon(child); as icon) {\r\n <button\r\n type=\"button\"\r\n class=\"w-8 h-8 flex items-center justify-center rounded transition-colors\"\r\n [class.bg-primary-100]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-primary-600]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-muted-color]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [class.hover:bg-surface-100]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n >\r\n <i class=\"mti mti-{{ icon }}\"></i>\r\n </button>\r\n } @else {\r\n <button\r\n pButton\r\n type=\"button\"\r\n class=\"p-button-text p-button-sm\"\r\n [class.p-button-primary]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.p-button-secondary]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [label]=\"getItemTitle(child)\"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n ></button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Group Body - Selected Child Content -->\r\n <div class=\"group-body flex-1 min-h-0\">\r\n @if (\r\n item.selectedGroupIndex !== null &&\r\n item.selectedGroupIndex !== undefined\r\n ) {\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let cIndex = $index\r\n ) {\r\n @if (\r\n cIndex === item.selectedGroupIndex &&\r\n !child.loading\r\n ) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"child.config\"\r\n [chartTypeId]=\"\r\n child.config?.serviceConfig?.dashboardId ||\r\n child.id\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig\r\n ?.ignoreQueryFilter ?? false\r\n \"\r\n [inGroup]=\"true\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n <!-- Header Item -->\r\n @else if (isHeader(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"header-item flex items-center h-full px-4 border-b-2 border-primary\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'transparent'\r\n \"\r\n [style.color]=\"getStyleConfig(item)['color'] || 'inherit'\"\r\n >\r\n <h3 class=\"font-semibold text-lg m-0\">\r\n {{ getItemTitle(item) }}\r\n </h3>\r\n </div>\r\n }\r\n }\r\n <!-- Topbar Item -->\r\n @else if (isTopbar(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"topbar-item flex items-center h-full px-4 bg-surface-50\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'var(--surface-50)'\r\n \"\r\n >\r\n <nav class=\"flex items-center gap-2 text-sm\">\r\n @for (\r\n crumb of getBreadcrumb(item);\r\n track $index;\r\n let last = $last\r\n ) {\r\n <span\r\n class=\"text-muted-color hover:text-primary cursor-pointer transition-colors\"\r\n >\r\n {{\r\n crumb.label?.[languageCode()] ||\r\n crumb.label?.[\"en\"] ||\r\n crumb.label\r\n }}\r\n </span>\r\n @if (!last) {\r\n <i\r\n class=\"mti mti-chevron-right text-xs text-muted-color\"\r\n ></i>\r\n }\r\n }\r\n @if (getBreadcrumb(item).length === 0) {\r\n <span class=\"text-muted-color italic\">{{\r\n t(\"noBreadcrumb\")\r\n }}</span>\r\n }\r\n </nav>\r\n </div>\r\n }\r\n }\r\n <!-- Regular Chart Item -->\r\n @else {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden Dialogs (for modal rendering) -->\r\n @if (dialogs().length > 0) {\r\n <div class=\"hidden\">\r\n @for (\r\n dialog of dialogs();\r\n track dialog.config?.serviceConfig?.dashboardId\r\n ) {\r\n <!-- Dialog placeholder - will be rendered in modal when triggered -->\r\n <div\r\n [attr.data-dialog-id]=\"\r\n dialog.config?.serviceConfig?.dashboardId\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Filters Sidebar Placeholder -->\r\n @if (showFilters() && filters().length > 0) {\r\n <div\r\n class=\"filters-sidebar fixed end-0 top-0 bottom-0 w-64 bg-surface-card border-s border-surface-200 p-4 shadow-lg z-50 hidden\"\r\n >\r\n <!-- Filter sidebar content - integrate with actual filter component -->\r\n <h4 class=\"font-semibold mb-4\">{{ t(\"filters\") }}</h4>\r\n @for (filter of filters(); track $index) {\r\n <div class=\"filter-item mb-3 p-2 bg-surface-50 rounded\">\r\n <span class=\"text-sm\">{{\r\n filter.label || filter.propertyKey\r\n }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n } @else if (loading()) {\r\n <!-- Loading State -->\r\n <div class=\"flex items-center justify-center h-64\">\r\n <div class=\"text-center\">\r\n <i\r\n class=\"mti mti-loader-2 text-4xl text-primary animate-spin mb-2\"\r\n ></i>\r\n <p class=\"text-muted-color\">{{ t(\"loading\") }}</p>\r\n </div>\r\n </div>\r\n } @else {\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: [".mt-dashboard-viewer{width:100%;height:100%}.dashboard-viewer-layout-wrapper{width:100%}.dashboard-viewer-layout{display:grid;grid-template-columns:repeat(36,minmax(0,1fr));grid-auto-rows:60px;gap:10px;width:100%;align-items:stretch}.dashboard-viewer-item{display:flex;min-width:0;min-height:0}.dashboard-viewer-item>*{width:100%;height:100%}.dashboard-viewer-content-item{display:block;flex:1 1 auto;min-width:0;min-height:0;width:100%;height:100%}.dashboard-viewer-item--header{z-index:1}.dashboard-viewer-item--topbar{z-index:2}.group-container{background-color:var(--surface-card)}.group-header{flex-shrink:0}.group-tabs{flex-wrap:wrap}.group-body{background-color:var(--surface-0)}.header-item{background-color:transparent}.topbar-item{background-color:var(--surface-50)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.filters-sidebar{transform:translate(100%);transition:transform .3s ease-in-out}.filters-sidebar.open{transform:translate(0)}[dir=rtl] .filters-sidebar{transform:translate(-100%)}[dir=rtl] .filters-sidebar.open{transform:translate(0)}.table-responsive{max-height:75vh;overflow-y:auto;overflow-x:auto}.modal-content{border:0!important}.custom-donut-chart{display:flex;justify-content:center;height:auto!important}.custom-donut-chart canvas{margin-top:-1.5rem!important}@media(max-width:768px){.dashboard-viewer-layout{display:flex;flex-direction:column;min-height:0!important}.dashboard-viewer-item{min-height:220px}.dashboard-viewer-item--header,.dashboard-viewer-item--topbar{min-height:72px}.dashboard-viewer-item--group{min-height:280px}}\n"] }]
20991
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\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('dashboard')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"viewerContent\" />\r\n }\r\n\r\n <!-- Reusable viewer content template -->\r\n <ng-template #viewerContent>\r\n <div class=\"relative h-full min-h-[600px] mt-dashboard-viewer\">\r\n @if (!loading() && hasRenderableContent()) {\r\n <div class=\"dashboard-viewer-layout-wrapper\">\r\n <div\r\n class=\"dashboard-viewer-layout\"\r\n [style.min-height]=\"layoutHeight()\"\r\n >\r\n @for (\r\n item of visibleItems();\r\n track trackByDashboardId($index, item)\r\n ) {\r\n <div\r\n class=\"dashboard-viewer-item\"\r\n [class.dashboard-viewer-item--group]=\"isGroup(item)\"\r\n [class.dashboard-viewer-item--header]=\"isHeader(item)\"\r\n [class.dashboard-viewer-item--topbar]=\"isTopbar(item)\"\r\n [style.grid-column]=\"getGridColumn(item)\"\r\n [style.grid-row]=\"getGridRow(item)\"\r\n >\r\n <!-- Group Container -->\r\n @if (isGroup(item)) {\r\n @if (!item.loading) {\r\n <div\r\n class=\"group-container h-full flex flex-col rounded-lg border border-surface-200 overflow-hidden\"\r\n [style.background-color]=\"\r\n getStyleConfig(item)['background-color'] ||\r\n 'var(--surface-card)'\r\n \"\r\n >\r\n <!-- Group Header with Tabs -->\r\n <div\r\n class=\"group-header flex items-center justify-between px-4 py-2 bg-surface-50 border-b border-surface-200\"\r\n >\r\n <span class=\"font-medium text-sm\">{{\r\n getGroupTitle(item)\r\n }}</span>\r\n <div class=\"group-tabs flex items-center gap-1\">\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let gIndex = $index\r\n ) {\r\n @if (getItemIcon(child); as icon) {\r\n <button\r\n type=\"button\"\r\n class=\"w-8 h-8 flex items-center justify-center rounded transition-colors\"\r\n [class.bg-primary-100]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-primary-600]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.text-muted-color]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [class.hover:bg-surface-100]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n >\r\n <i class=\"mti mti-{{ icon }}\"></i>\r\n </button>\r\n } @else {\r\n <button\r\n pButton\r\n type=\"button\"\r\n class=\"p-button-text p-button-sm\"\r\n [class.p-button-primary]=\"\r\n item.selectedGroupIndex === gIndex\r\n \"\r\n [class.p-button-secondary]=\"\r\n item.selectedGroupIndex !== gIndex\r\n \"\r\n [label]=\"getItemTitle(child)\"\r\n (click)=\"selectGroupChild(item, gIndex)\"\r\n ></button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Group Body - Selected Child Content -->\r\n <div class=\"group-body flex-1 min-h-0\">\r\n @if (\r\n item.selectedGroupIndex !== null &&\r\n item.selectedGroupIndex !== undefined\r\n ) {\r\n @for (\r\n child of getGroupChildren(item);\r\n track child.config?.serviceConfig?.dashboardId;\r\n let cIndex = $index\r\n ) {\r\n @if (\r\n cIndex === item.selectedGroupIndex &&\r\n !child.loading\r\n ) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"child.config\"\r\n [chartTypeId]=\"\r\n child.config?.serviceConfig?.dashboardId ||\r\n child.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig\r\n ?.ignoreQueryFilter ?? false\r\n \"\r\n [inGroup]=\"true\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n <!-- Header Item -->\r\n @else if (isHeader(item)) {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n <!-- Topbar Item -->\r\n @else if (isTopbar(item)) {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n <!-- Regular Chart Item -->\r\n @else {\r\n @if (!item.loading) {\r\n <mt-dashboard-item\r\n class=\"dashboard-viewer-content-item\"\r\n [config]=\"item.config\"\r\n [chartTypeId]=\"\r\n item.config?.serviceConfig?.dashboardId || item.id\r\n \"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n [extraFilters]=\"extraFilters()\"\r\n [ignoreQueryFilter]=\"\r\n pageConfig()?.dashboardConfig?.ignoreQueryFilter ??\r\n false\r\n \"\r\n [inGroup]=\"false\"\r\n >\r\n </mt-dashboard-item>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden Dialogs (for modal rendering) -->\r\n @if (dialogs().length > 0) {\r\n <div class=\"hidden\">\r\n @for (\r\n dialog of dialogs();\r\n track dialog.config?.serviceConfig?.dashboardId\r\n ) {\r\n <!-- Dialog placeholder - will be rendered in modal when triggered -->\r\n <div\r\n [attr.data-dialog-id]=\"\r\n dialog.config?.serviceConfig?.dashboardId\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Filters Sidebar Placeholder -->\r\n @if (showFilters() && filters().length > 0) {\r\n <div\r\n class=\"filters-sidebar fixed end-0 top-0 bottom-0 w-64 bg-surface-card border-s border-surface-200 p-4 shadow-lg z-50 hidden\"\r\n >\r\n <!-- Filter sidebar content - integrate with actual filter component -->\r\n <h4 class=\"font-semibold mb-4\">{{ t(\"filters\") }}</h4>\r\n @for (filter of filters(); track $index) {\r\n <div class=\"filter-item mb-3 p-2 bg-surface-50 rounded\">\r\n <span class=\"text-sm\">{{\r\n filter.label || filter.propertyKey\r\n }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n } @else if (loading()) {\r\n <!-- Loading State -->\r\n <div class=\"flex items-center justify-center h-64\">\r\n <div class=\"text-center\">\r\n <i\r\n class=\"mti mti-loader-2 text-4xl text-primary animate-spin mb-2\"\r\n ></i>\r\n <p class=\"text-muted-color\">{{ t(\"loading\") }}</p>\r\n </div>\r\n </div>\r\n } @else {\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: [".mt-dashboard-viewer{width:100%;height:100%}.dashboard-viewer-layout-wrapper{width:100%}.dashboard-viewer-layout{display:grid;grid-template-columns:repeat(36,minmax(0,1fr));grid-auto-rows:60px;gap:10px;width:100%;align-items:stretch}.dashboard-viewer-item{display:flex;min-width:0;min-height:0}.dashboard-viewer-item>*{width:100%;height:100%}.dashboard-viewer-content-item{display:block;flex:1 1 auto;min-width:0;min-height:0;width:100%;height:100%}.dashboard-viewer-item--header{z-index:1}.dashboard-viewer-item--topbar{z-index:2}.group-container{background-color:var(--surface-card)}.group-header{flex-shrink:0}.group-tabs{flex-wrap:wrap}.group-body{background-color:var(--surface-0)}.header-item{background-color:transparent}.topbar-item{background-color:var(--surface-50)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.filters-sidebar{transform:translate(100%);transition:transform .3s ease-in-out}.filters-sidebar.open{transform:translate(0)}[dir=rtl] .filters-sidebar{transform:translate(-100%)}[dir=rtl] .filters-sidebar.open{transform:translate(0)}.table-responsive{max-height:75vh;overflow-y:auto;overflow-x:auto}.modal-content{border:0!important}.custom-donut-chart{display:flex;justify-content:center;height:auto!important}.custom-donut-chart canvas{margin-top:-1.5rem!important}@media(max-width:768px){.dashboard-viewer-layout{display:flex;flex-direction:column;min-height:0!important}.dashboard-viewer-item{min-height:220px}.dashboard-viewer-item--header,.dashboard-viewer-item--topbar{min-height:72px}.dashboard-viewer-item--group{min-height:280px}}\n"] }]
20468
20992
  }], 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 }] }], dashboardData: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardData", required: false }] }], chartsData: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartsData", required: false }] }], dialogsData: [{ type: i0.Input, args: [{ isSignal: true, alias: "dialogsData", required: false }] }], filtersData: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtersData", required: false }] }], extraFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraFilters", required: false }] }], showFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilters", required: false }] }], pageLoaded: [{ type: i0.Output, args: ["pageLoaded"] }], onBack: [{ type: i0.Output, args: ["onBack"] }], chartClick: [{ type: i0.Output, args: ["chartClick"] }] } });
20469
20993
 
20470
20994
  /**
@@ -20671,7 +21195,7 @@ class DashboardList {
20671
21195
  this.dashboards.reload();
20672
21196
  }
20673
21197
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardList, deps: [], target: i0.ɵɵFactoryTarget.Component });
20674
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardList, isStandalone: true, selector: "mt-dashboard-list", inputs: { isPage: { classPropertyName: "isPage", publicName: "isPage", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, baseRoute: { classPropertyName: "baseRoute", publicName: "baseRoute", isSignal: true, isRequired: false, transformFunction: null }, showCreateButton: { classPropertyName: "showCreateButton", publicName: "showCreateButton", isSignal: true, isRequired: false, transformFunction: null }, showViewButton: { classPropertyName: "showViewButton", publicName: "showViewButton", isSignal: true, isRequired: false, transformFunction: null }, showEditButton: { classPropertyName: "showEditButton", publicName: "showEditButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dashboardAction: "dashboardAction", dashboardCreated: "dashboardCreated" }, viewQueries: [{ propertyName: "nameTpl", first: true, predicate: ["nameTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder.dashboard'\">\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page [title]=\"pageTitle() || t('dashboards')\">\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n @if (showCreateButton()) {\r\n <mt-button\r\n [label]=\"t('createDashboard')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"openCreateModal()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <div class=\"dashboard-list space-y-3\">\r\n <!-- Header -->\r\n <div class=\"flex justify-between items-center gap-4\">\r\n <h2 class=\"text-2xl font-semibold text-surface-900 dark:text-surface-0\">\r\n {{ t(\"dashboards\") }}\r\n </h2>\r\n\r\n @if (showCreateButton()) {\r\n <mt-button\r\n [label]=\"t('createDashboard')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"openCreateModal()\"\r\n severity=\"primary\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </div>\r\n }\r\n\r\n <!-- Reusable table content template -->\r\n <ng-template #tableContent>\r\n <!-- Custom cell templates -->\r\n <ng-template #nameTpl let-row>\r\n <span class=\"font-semibold text-surface-900 dark:text-surface-0\">\r\n {{ getDashboardName(row) }}\r\n </span>\r\n </ng-template>\r\n\r\n <!-- Dashboard Table -->\r\n <mt-table\r\n [data]=\"dashboardList()\"\r\n [columns]=\"tableColumns()\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"isLoading()\"\r\n [showFilters]=\"true\"\r\n [generalSearch]=\"true\"\r\n dataKey=\"id\"\r\n />\r\n </ng-template>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "actionShape", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
21198
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: DashboardList, isStandalone: true, selector: "mt-dashboard-list", inputs: { isPage: { classPropertyName: "isPage", publicName: "isPage", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, baseRoute: { classPropertyName: "baseRoute", publicName: "baseRoute", isSignal: true, isRequired: false, transformFunction: null }, showCreateButton: { classPropertyName: "showCreateButton", publicName: "showCreateButton", isSignal: true, isRequired: false, transformFunction: null }, showViewButton: { classPropertyName: "showViewButton", publicName: "showViewButton", isSignal: true, isRequired: false, transformFunction: null }, showEditButton: { classPropertyName: "showEditButton", publicName: "showEditButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dashboardAction: "dashboardAction", dashboardCreated: "dashboardCreated" }, viewQueries: [{ propertyName: "nameTpl", first: true, predicate: ["nameTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder.dashboard'\">\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page [title]=\"pageTitle() || t('dashboards')\">\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n @if (showCreateButton()) {\r\n <mt-button\r\n [label]=\"t('createDashboard')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"openCreateModal()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <div class=\"dashboard-list space-y-3\">\r\n <!-- Header -->\r\n <div class=\"flex justify-between items-center gap-4\">\r\n <h2 class=\"text-2xl font-semibold text-surface-900 dark:text-surface-0\">\r\n {{ t(\"dashboards\") }}\r\n </h2>\r\n\r\n @if (showCreateButton()) {\r\n <mt-button\r\n [label]=\"t('createDashboard')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"openCreateModal()\"\r\n severity=\"primary\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </div>\r\n }\r\n\r\n <!-- Reusable table content template -->\r\n <ng-template #tableContent>\r\n <!-- Custom cell templates -->\r\n <ng-template #nameTpl let-row>\r\n <span class=\"font-semibold text-surface-900 dark:text-surface-0\">\r\n {{ getDashboardName(row) }}\r\n </span>\r\n </ng-template>\r\n\r\n <!-- Dashboard Table -->\r\n <mt-table\r\n [data]=\"dashboardList()\"\r\n [columns]=\"tableColumns()\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"isLoading()\"\r\n [showFilters]=\"true\"\r\n [generalSearch]=\"true\"\r\n dataKey=\"id\"\r\n />\r\n </ng-template>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "exportable", "exportFilename", "actionShape", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20675
21199
  }
20676
21200
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DashboardList, decorators: [{
20677
21201
  type: Component,
@@ -20700,5 +21224,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
20700
21224
  * Generated bundle index. Do not edit.
20701
21225
  */
20702
21226
 
20703
- export { ActionsSettings, BarChartHandler, BarControlUi, CHART_TYPES, CardContentComponent, CardFilterComponent, CardInfoComponent, ChartCardComponent, ChartDataService, ChartSettingsDrawer, ChartViewer, ComparisonChartHandler, DashboardBuilder, DashboardBuilderService, DashboardItem, DashboardItemStoreService, DashboardList, DashboardStoreService, DashboardViewer, DataSourceSettings, DefaultControlUi, DisplaySettings, DynamicFiltersComponent, DynamicFiltersConfig, EChartComponent, EntityInfoComponent, EntityPreviewCardComponent, FilterByGroupPipe, GaugeChartHandler, GeneralSettings, GetChartActionsPipe, HTTPMethod, HeaderCardComponent, LevelCardHandler, LevelCardListComponent, LineChartHandler, ListStatisticCardComponent, ManageBreadcrumb, ManageFilterOnPage, ManageItem, ManageItemService, ManagePages, MapChartHandler, OverviewCardHandler, PhaseGateStepperHandler, PieChartHandler, PieControlUi, RingGaugeChartHandler, SPlusChartHandler, SkeletonCardComponent, SnapshotHandler, SplitterChartHandler, StackBarChartHandler, StackBarControlUi, StaticFiltersComponent, StatisticCardComponent, TableCardComponent, TableViewHandler, TimelineHandler, addCommasToNumber, axisFormatters, cloneDeep$1 as cloneDeep, createAxisFormatter, createTooltipFormatter, dynamicReorder, dynamicTextReplace, formatCurrency, formatDate, formatNumber, formatPercentage, formatValue, formatWordsUnderBar, formatXAxis, generalConfiguration, getColorFromConditions, getLanguageCode, getLocalizedTitle, getNestedData, groupDatesByYearAndMonth, handleFilterForCard, handleFilterForSnapshot, handleFiltersForCustom, isMobilePlatform$1 as isMobilePlatform, sortChartData, sortDataTableView, switchAllKeysSmall$1 as switchAllKeysSmall, switchAllKeysToLower };
21227
+ export { ActionsSettings, BarChartHandler, BarControlUi, CHART_TYPES, CardContentComponent, CardFilterComponent, CardInfoComponent, ChartCardComponent, ChartDataService, ChartSettingsDrawer, ChartViewer, ComparisonChartHandler, DashboardBuilder, DashboardBuilderService, DashboardItem, DashboardItemStoreService, DashboardList, DashboardStoreService, DashboardViewer, DataSourceSettings, DefaultControlUi, DisplaySettings, DynamicFiltersComponent, DynamicFiltersConfig, EChartComponent, PropertiesCardComponent as EntitiesPreviewCardComponent, EntityInfoComponent, EntityPreviewCardComponent, FilterByGroupPipe, GaugeChartHandler, GeneralSettings, GetChartActionsPipe, HTTPMethod, HeaderCardComponent, LevelCardHandler, LineChartHandler, ListStatisticCardComponent, ManageBreadcrumb, ManageFilterOnPage, ManageItem, ManageItemService, ManagePages, MapChartHandler, OverviewCardHandler, PhaseGateStepperHandler, PieChartHandler, PieControlUi, PropertiesCardComponent, RingGaugeChartHandler, SPlusChartHandler, SkeletonCardComponent, SnapshotHandler, SplitterChartHandler, StackBarChartHandler, StackBarControlUi, StaticFiltersComponent, StatisticCardComponent, TableCardComponent, TableViewHandler, TimelineHandler, TopbarCardComponent, addCommasToNumber, axisFormatters, cloneDeep$1 as cloneDeep, createAxisFormatter, createTooltipFormatter, dynamicReorder, dynamicTextReplace, formatCurrency, formatDate, formatNumber, formatPercentage, formatValue, formatWordsUnderBar, formatXAxis, generalConfiguration, getColorFromConditions, getLanguageCode, getLocalizedTitle, getNestedData, groupDatesByYearAndMonth, handleFilterForCard, handleFilterForSnapshot, handleFiltersForCustom, isMobilePlatform$1 as isMobilePlatform, sortChartData, sortDataTableView, switchAllKeysSmall$1 as switchAllKeysSmall, switchAllKeysToLower };
20704
21228
  //# sourceMappingURL=masterteam-dashboard-builder.mjs.map