@acorex/modules 20.7.20 → 20.7.21

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.
Files changed (41) hide show
  1. package/asset-management/index.d.ts +24 -33
  2. package/dashboard-management/index.d.ts +40 -5
  3. package/document-management/index.d.ts +1 -26
  4. package/fesm2022/acorex-modules-asset-management-asset.entity-D_w4zjNb.mjs +612 -0
  5. package/fesm2022/acorex-modules-asset-management-asset.entity-D_w4zjNb.mjs.map +1 -0
  6. package/fesm2022/acorex-modules-asset-management-manual-asset-category.entity-DyIV_vbE.mjs +267 -0
  7. package/fesm2022/acorex-modules-asset-management-manual-asset-category.entity-DyIV_vbE.mjs.map +1 -0
  8. package/fesm2022/acorex-modules-asset-management.mjs +59 -117
  9. package/fesm2022/acorex-modules-asset-management.mjs.map +1 -1
  10. package/fesm2022/acorex-modules-dashboard-management.mjs +454 -116
  11. package/fesm2022/acorex-modules-dashboard-management.mjs.map +1 -1
  12. package/fesm2022/acorex-modules-data-management.mjs +4 -2
  13. package/fesm2022/acorex-modules-data-management.mjs.map +1 -1
  14. package/fesm2022/acorex-modules-document-management.mjs +40 -99
  15. package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
  16. package/fesm2022/acorex-modules-maintenance-management.mjs +194 -103
  17. package/fesm2022/acorex-modules-maintenance-management.mjs.map +1 -1
  18. package/fesm2022/acorex-modules-notification-management.mjs +21 -6
  19. package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
  20. package/fesm2022/acorex-modules-reservation-management-acorex-modules-reservation-management-CkHGIQ38.mjs +2135 -0
  21. package/fesm2022/acorex-modules-reservation-management-acorex-modules-reservation-management-CkHGIQ38.mjs.map +1 -0
  22. package/fesm2022/acorex-modules-reservation-management-reservation-class-status.entity-Clyj7r2x.mjs +263 -0
  23. package/fesm2022/acorex-modules-reservation-management-reservation-class-status.entity-Clyj7r2x.mjs.map +1 -0
  24. package/fesm2022/acorex-modules-reservation-management-reservation-resource-type.entity-BXb0FTQ5.mjs +184 -0
  25. package/fesm2022/acorex-modules-reservation-management-reservation-resource-type.entity-BXb0FTQ5.mjs.map +1 -0
  26. package/fesm2022/acorex-modules-reservation-management-reservation-status-transition.entity-BT8GQ9MC.mjs +247 -0
  27. package/fesm2022/acorex-modules-reservation-management-reservation-status-transition.entity-BT8GQ9MC.mjs.map +1 -0
  28. package/fesm2022/acorex-modules-reservation-management.mjs +1 -3325
  29. package/fesm2022/acorex-modules-reservation-management.mjs.map +1 -1
  30. package/fesm2022/{acorex-modules-task-management-task-board.page-BOOY3qla.mjs → acorex-modules-task-management-task-board.page-BBKB4yir.mjs} +114 -62
  31. package/fesm2022/acorex-modules-task-management-task-board.page-BBKB4yir.mjs.map +1 -0
  32. package/fesm2022/acorex-modules-task-management.mjs +43 -13
  33. package/fesm2022/acorex-modules-task-management.mjs.map +1 -1
  34. package/maintenance-management/index.d.ts +7 -3
  35. package/package.json +2 -2
  36. package/reservation-management/index.d.ts +84 -338
  37. package/fesm2022/acorex-modules-asset-management-asset.entity-C57iN3Bo.mjs +0 -357
  38. package/fesm2022/acorex-modules-asset-management-asset.entity-C57iN3Bo.mjs.map +0 -1
  39. package/fesm2022/acorex-modules-asset-management-inspection.entity-CpDuN-qj.mjs +0 -198
  40. package/fesm2022/acorex-modules-asset-management-inspection.entity-CpDuN-qj.mjs.map +0 -1
  41. package/fesm2022/acorex-modules-task-management-task-board.page-BOOY3qla.mjs.map +0 -1
@@ -10,7 +10,7 @@ import { Injectable, inject, Injector, NgModule, input, signal, computed, effect
10
10
  import * as i4 from '@acorex/core/translation';
11
11
  import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
12
12
  import { AXPCommonMenuKeys, AXP_GLOBAL_SEARCH_CONFIG_TOKEN } from '@acorex/modules/common';
13
- import { firstValueFrom, interval, map, Observable, catchError, throwError, of, finalize, switchMap } from 'rxjs';
13
+ import { firstValueFrom, interval, map, Observable, catchError, throwError, of, finalize, switchMap, fromEvent } from 'rxjs';
14
14
  import * as i1 from '@acorex/components/tooltip';
15
15
  import { AXTooltipModule } from '@acorex/components/tooltip';
16
16
  import { AXMLocaleManagementService } from '@acorex/modules/locale-management';
@@ -57,6 +57,7 @@ import * as i1$4 from '@acorex/components/loading';
57
57
  import { AXLoadingModule } from '@acorex/components/loading';
58
58
  import { AXMSecurityManagementRolesEntityService, AXMUsersEntityService } from '@acorex/modules/security-management';
59
59
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
60
+ import { debounceTime } from 'rxjs/operators';
60
61
  import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
61
62
  import { AXBasePageComponent } from '@acorex/components/page';
62
63
  import { AXLabelModule } from '@acorex/components/label';
@@ -1032,12 +1033,27 @@ const AXPAnalogClockWidget = {
1032
1033
  },
1033
1034
  meta: {
1034
1035
  dimensions: {
1035
- width: 3,
1036
- height: 3,
1037
- minWidth: 3,
1038
- minHeight: 2,
1039
- maxWidth: 3,
1040
- maxHeight: 7,
1036
+ lg: {
1037
+ width: 3,
1038
+ height: 3,
1039
+ minWidth: 3,
1040
+ minHeight: 2,
1041
+ maxWidth: 3,
1042
+ maxHeight: 7,
1043
+ },
1044
+ md: {
1045
+ width: 3,
1046
+ height: 3,
1047
+ minWidth: 3,
1048
+ minHeight: 2,
1049
+ maxWidth: 3,
1050
+ maxHeight: 7,
1051
+ },
1052
+ sm: {
1053
+ height: 3,
1054
+ minHeight: 2,
1055
+ maxHeight: 7,
1056
+ },
1041
1057
  },
1042
1058
  },
1043
1059
  };
@@ -1372,12 +1388,27 @@ const AXPBarChartWidget = {
1372
1388
  },
1373
1389
  meta: {
1374
1390
  dimensions: {
1375
- width: 5,
1376
- height: 6,
1377
- minWidth: 2,
1378
- minHeight: 2,
1379
- maxWidth: 6,
1380
- maxHeight: 7,
1391
+ lg: {
1392
+ width: 5,
1393
+ height: 6,
1394
+ minWidth: 2,
1395
+ minHeight: 2,
1396
+ maxWidth: 6,
1397
+ maxHeight: 7,
1398
+ },
1399
+ md: {
1400
+ width: 5,
1401
+ height: 6,
1402
+ minWidth: 2,
1403
+ minHeight: 2,
1404
+ maxWidth: 6,
1405
+ maxHeight: 7,
1406
+ },
1407
+ sm: {
1408
+ height: 6,
1409
+ minHeight: 2,
1410
+ maxHeight: 7,
1411
+ },
1381
1412
  },
1382
1413
  },
1383
1414
  };
@@ -1720,12 +1751,27 @@ const AXPClockCalendarWidget = {
1720
1751
  },
1721
1752
  meta: {
1722
1753
  dimensions: {
1723
- width: 2,
1724
- height: 5,
1725
- minWidth: 2,
1726
- minHeight: 2,
1727
- maxWidth: 3,
1728
- maxHeight: 6,
1754
+ lg: {
1755
+ width: 2,
1756
+ height: 5,
1757
+ minWidth: 2,
1758
+ minHeight: 2,
1759
+ maxWidth: 3,
1760
+ maxHeight: 6,
1761
+ },
1762
+ md: {
1763
+ width: 2,
1764
+ height: 5,
1765
+ minWidth: 2,
1766
+ minHeight: 2,
1767
+ maxWidth: 3,
1768
+ maxHeight: 6,
1769
+ },
1770
+ sm: {
1771
+ height: 5,
1772
+ minHeight: 2,
1773
+ maxHeight: 6,
1774
+ },
1729
1775
  },
1730
1776
  },
1731
1777
  };
@@ -1888,12 +1934,27 @@ const AXPDashboardShortcutWidget = {
1888
1934
  ],
1889
1935
  meta: {
1890
1936
  dimensions: {
1891
- width: 2,
1892
- height: 2,
1893
- minWidth: 1,
1894
- minHeight: 1,
1895
- maxWidth: 3,
1896
- maxHeight: 2,
1937
+ lg: {
1938
+ width: 2,
1939
+ height: 2,
1940
+ minWidth: 1,
1941
+ minHeight: 1,
1942
+ maxWidth: 3,
1943
+ maxHeight: 2,
1944
+ },
1945
+ md: {
1946
+ width: 2,
1947
+ height: 2,
1948
+ minWidth: 1,
1949
+ minHeight: 1,
1950
+ maxWidth: 3,
1951
+ maxHeight: 2,
1952
+ },
1953
+ sm: {
1954
+ height: 2,
1955
+ minHeight: 1,
1956
+ maxHeight: 2,
1957
+ },
1897
1958
  },
1898
1959
  },
1899
1960
  components: {
@@ -2175,12 +2236,27 @@ const AXPDonutChartWidget = {
2175
2236
  },
2176
2237
  meta: {
2177
2238
  dimensions: {
2178
- width: 4,
2179
- height: 4,
2180
- minWidth: 2,
2181
- minHeight: 2,
2182
- maxWidth: 5,
2183
- maxHeight: 6,
2239
+ lg: {
2240
+ width: 4,
2241
+ height: 4,
2242
+ minWidth: 2,
2243
+ minHeight: 2,
2244
+ maxWidth: 5,
2245
+ maxHeight: 6,
2246
+ },
2247
+ md: {
2248
+ width: 4,
2249
+ height: 4,
2250
+ minWidth: 2,
2251
+ minHeight: 2,
2252
+ maxWidth: 5,
2253
+ maxHeight: 6,
2254
+ },
2255
+ sm: {
2256
+ height: 4,
2257
+ minHeight: 2,
2258
+ maxHeight: 6,
2259
+ },
2184
2260
  },
2185
2261
  },
2186
2262
  };
@@ -2453,12 +2529,27 @@ const AXPGaugeChartWidget = {
2453
2529
  },
2454
2530
  meta: {
2455
2531
  dimensions: {
2456
- width: 3,
2457
- height: 4,
2458
- minWidth: 2,
2459
- minHeight: 2,
2460
- maxWidth: 4,
2461
- maxHeight: 5,
2532
+ lg: {
2533
+ width: 3,
2534
+ height: 4,
2535
+ minWidth: 2,
2536
+ minHeight: 2,
2537
+ maxWidth: 4,
2538
+ maxHeight: 5,
2539
+ },
2540
+ md: {
2541
+ width: 3,
2542
+ height: 4,
2543
+ minWidth: 2,
2544
+ minHeight: 2,
2545
+ maxWidth: 4,
2546
+ maxHeight: 5,
2547
+ },
2548
+ sm: {
2549
+ height: 4,
2550
+ minHeight: 2,
2551
+ maxHeight: 5,
2552
+ },
2462
2553
  },
2463
2554
  },
2464
2555
  };
@@ -2884,12 +2975,27 @@ const AXPLineChartWidget = {
2884
2975
  },
2885
2976
  meta: {
2886
2977
  dimensions: {
2887
- width: 3,
2888
- height: 4,
2889
- minWidth: 2,
2890
- minHeight: 2,
2891
- maxWidth: 6,
2892
- maxHeight: 6,
2978
+ lg: {
2979
+ width: 3,
2980
+ height: 4,
2981
+ minWidth: 2,
2982
+ minHeight: 2,
2983
+ maxWidth: 6,
2984
+ maxHeight: 6,
2985
+ },
2986
+ md: {
2987
+ width: 3,
2988
+ height: 4,
2989
+ minWidth: 2,
2990
+ minHeight: 2,
2991
+ maxWidth: 6,
2992
+ maxHeight: 6,
2993
+ },
2994
+ sm: {
2995
+ height: 4,
2996
+ minHeight: 2,
2997
+ maxHeight: 6,
2998
+ },
2893
2999
  },
2894
3000
  },
2895
3001
  };
@@ -2951,7 +3057,7 @@ class AXPStickyNoteWidgetViewComponent extends AXPValueWidgetComponent {
2951
3057
  provide: AXGridLayoutWidgetComponent,
2952
3058
  useExisting: AXPStickyNoteWidgetViewComponent,
2953
3059
  },
2954
- ], viewQueries: [{ propertyName: "wysiwyg", first: true, predicate: ["wysiwyg"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\n class=\"sticky-note-container ax-size-full ax-rounded-lg ax-flex ax-flex-col ax-p-4 ax-shadow-md ax-transition-all ax-duration-300 hover:ax-shadow-lg\"\n [style.background-color]=\"bgColor()\"\n [style.color]=\"color()\"\n [class.ax-shadow-lg]=\"isEditing()\"\n [class.ax-scale-[1.02]]=\"isEditing()\"\n (dblclick)=\"activateEdit()\"\n>\n <!-- Header with timestamp -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <div class=\"ax-text-xs ax-opacity-70 ax-font-medium ax-flex ax-items-center ax-gap-1\">\n <i class=\"fa-regular fa-clock ax-text-[0.65rem]\"></i>\n {{ date() | format: 'datetime' : { format: 'short' } | async }}\n </div>\n </div>\n\n <!-- Content area -->\n <div class=\"ax-flex-1 ax-overflow-auto\">\n <ax-wysiwyg-container\n #wysiwyg\n [class]=\"isEditing() ? 'ax-pointer-events-auto ax-cursor-text' : 'ax-pointer-events-none !ax-cursor-pointer'\"\n class=\"ax-h-full\"\n placeHolder=\"start writing with double click...\"\n look=\"none\"\n (onValueChanged)=\"valueChange($event)\"\n [ngModel]=\"value()\"\n >\n <ax-wysiwyg-view class=\"!ax-size-full ax-border-b-0\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar></ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n\n <!-- Footer with color selector and save button -->\n @if (isEditing()) {\n <div class=\"ax-absolute ax-bottom-2 ax-left-2 ax-right-2 ax-flex ax-flex-wrap ax-gap-1 ax-text-xs\">\n <!-- Color selection bar when in edit mode -->\n <div class=\"ax-flex ax-w-full ax-mt-2 ax-border ax-border-gray-200 ax-overflow-hidden ax-rounded-md\">\n @for (preset of colorPresets; track preset) {\n <div\n class=\"ax-h-6 ax-flex-1 ax-cursor-pointer ax-transition-all ax-duration-200 ax-border-r ax-border-gray-200 last:ax-border-r-0 hover:ax-brightness-95\"\n [style.background-color]=\"preset\"\n [class.ax-ring-inset]=\"bgColor() === preset\"\n [class.ax-ring-2]=\"bgColor() === preset\"\n [class.ax-ring-primary]=\"bgColor() === preset\"\n (click)=\"setColor(preset)\"\n ></div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}:host ::ng-deep ax-wysiwyg-view{color:#2e2e2e!important}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$1.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXColorBoxModule }, { kind: "pipe", type: i2.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3060
+ ], viewQueries: [{ propertyName: "wysiwyg", first: true, predicate: ["wysiwyg"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\n class=\"sticky-note-container ax-size-full ax-rounded-lg ax-flex ax-flex-col ax-p-4 ax-shadow-md ax-transition-all ax-duration-300 hover:ax-shadow-lg\"\n [style.background-color]=\"bgColor()\"\n [style.color]=\"color()\"\n [class.ax-shadow-lg]=\"isEditing()\"\n [class.ax-scale-[1.02]]=\"isEditing()\"\n (dblclick)=\"activateEdit()\"\n>\n <!-- Header with timestamp -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <div class=\"ax-text-xs ax-opacity-70 ax-font-medium ax-flex ax-items-center ax-gap-1\">\n <i class=\"fa-regular fa-clock ax-text-[0.65rem]\"></i>\n {{ date() | format: 'datetime' : { format: 'short' } | async }}\n </div>\n </div>\n\n <!-- Content area -->\n <div class=\"ax-flex-1 ax-overflow-auto\">\n <ax-wysiwyg-container\n #wysiwyg\n [class]=\"isEditing() ? 'ax-pointer-events-auto ax-cursor-text' : 'ax-pointer-events-none !ax-cursor-pointer'\"\n class=\"ax-h-full\"\n placeHolder=\"start writing with double click...\"\n look=\"none\"\n (onValueChanged)=\"valueChange($event)\"\n [ngModel]=\"value()\"\n >\n <ax-wysiwyg-view class=\"!ax-size-full ax-border-b-0\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar class=\"ax-hidden\"></ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n\n <!-- Footer with color selector and save button -->\n @if (isEditing()) {\n <div class=\"ax-absolute ax-bottom-2 ax-left-2 ax-right-2 ax-flex ax-flex-wrap ax-gap-1 ax-text-xs\">\n <!-- Color selection bar when in edit mode -->\n <div class=\"ax-flex ax-w-full ax-mt-2 ax-border ax-border-gray-200 ax-overflow-hidden ax-rounded-md\">\n @for (preset of colorPresets; track preset) {\n <div\n class=\"ax-h-6 ax-flex-1 ax-cursor-pointer ax-transition-all ax-duration-200 ax-border-r ax-border-gray-200 last:ax-border-r-0 hover:ax-brightness-95\"\n [style.background-color]=\"preset\"\n [class.ax-ring-inset]=\"bgColor() === preset\"\n [class.ax-ring-2]=\"bgColor() === preset\"\n [class.ax-ring-primary]=\"bgColor() === preset\"\n (click)=\"setColor(preset)\"\n ></div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}:host ::ng-deep ax-wysiwyg-view{color:#2e2e2e!important}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "readonly", "disabled", "value", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view" }, { kind: "component", type: i1$1.AXWysiwygToolbarComponent, selector: "ax-wysiwyg-toolbar" }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXColorBoxModule }, { kind: "pipe", type: i2.AXFormatPipe, name: "format" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2955
3061
  }
2956
3062
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPStickyNoteWidgetViewComponent, decorators: [{
2957
3063
  type: Component,
@@ -2971,7 +3077,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2971
3077
  provide: AXGridLayoutWidgetComponent,
2972
3078
  useExisting: AXPStickyNoteWidgetViewComponent,
2973
3079
  },
2974
- ], template: "<div\n class=\"sticky-note-container ax-size-full ax-rounded-lg ax-flex ax-flex-col ax-p-4 ax-shadow-md ax-transition-all ax-duration-300 hover:ax-shadow-lg\"\n [style.background-color]=\"bgColor()\"\n [style.color]=\"color()\"\n [class.ax-shadow-lg]=\"isEditing()\"\n [class.ax-scale-[1.02]]=\"isEditing()\"\n (dblclick)=\"activateEdit()\"\n>\n <!-- Header with timestamp -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <div class=\"ax-text-xs ax-opacity-70 ax-font-medium ax-flex ax-items-center ax-gap-1\">\n <i class=\"fa-regular fa-clock ax-text-[0.65rem]\"></i>\n {{ date() | format: 'datetime' : { format: 'short' } | async }}\n </div>\n </div>\n\n <!-- Content area -->\n <div class=\"ax-flex-1 ax-overflow-auto\">\n <ax-wysiwyg-container\n #wysiwyg\n [class]=\"isEditing() ? 'ax-pointer-events-auto ax-cursor-text' : 'ax-pointer-events-none !ax-cursor-pointer'\"\n class=\"ax-h-full\"\n placeHolder=\"start writing with double click...\"\n look=\"none\"\n (onValueChanged)=\"valueChange($event)\"\n [ngModel]=\"value()\"\n >\n <ax-wysiwyg-view class=\"!ax-size-full ax-border-b-0\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar></ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n\n <!-- Footer with color selector and save button -->\n @if (isEditing()) {\n <div class=\"ax-absolute ax-bottom-2 ax-left-2 ax-right-2 ax-flex ax-flex-wrap ax-gap-1 ax-text-xs\">\n <!-- Color selection bar when in edit mode -->\n <div class=\"ax-flex ax-w-full ax-mt-2 ax-border ax-border-gray-200 ax-overflow-hidden ax-rounded-md\">\n @for (preset of colorPresets; track preset) {\n <div\n class=\"ax-h-6 ax-flex-1 ax-cursor-pointer ax-transition-all ax-duration-200 ax-border-r ax-border-gray-200 last:ax-border-r-0 hover:ax-brightness-95\"\n [style.background-color]=\"preset\"\n [class.ax-ring-inset]=\"bgColor() === preset\"\n [class.ax-ring-2]=\"bgColor() === preset\"\n [class.ax-ring-primary]=\"bgColor() === preset\"\n (click)=\"setColor(preset)\"\n ></div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}:host ::ng-deep ax-wysiwyg-view{color:#2e2e2e!important}\n"] }]
3080
+ ], template: "<div\n class=\"sticky-note-container ax-size-full ax-rounded-lg ax-flex ax-flex-col ax-p-4 ax-shadow-md ax-transition-all ax-duration-300 hover:ax-shadow-lg\"\n [style.background-color]=\"bgColor()\"\n [style.color]=\"color()\"\n [class.ax-shadow-lg]=\"isEditing()\"\n [class.ax-scale-[1.02]]=\"isEditing()\"\n (dblclick)=\"activateEdit()\"\n>\n <!-- Header with timestamp -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <div class=\"ax-text-xs ax-opacity-70 ax-font-medium ax-flex ax-items-center ax-gap-1\">\n <i class=\"fa-regular fa-clock ax-text-[0.65rem]\"></i>\n {{ date() | format: 'datetime' : { format: 'short' } | async }}\n </div>\n </div>\n\n <!-- Content area -->\n <div class=\"ax-flex-1 ax-overflow-auto\">\n <ax-wysiwyg-container\n #wysiwyg\n [class]=\"isEditing() ? 'ax-pointer-events-auto ax-cursor-text' : 'ax-pointer-events-none !ax-cursor-pointer'\"\n class=\"ax-h-full\"\n placeHolder=\"start writing with double click...\"\n look=\"none\"\n (onValueChanged)=\"valueChange($event)\"\n [ngModel]=\"value()\"\n >\n <ax-wysiwyg-view class=\"!ax-size-full ax-border-b-0\"></ax-wysiwyg-view>\n <ax-wysiwyg-toolbar class=\"ax-hidden\"></ax-wysiwyg-toolbar>\n </ax-wysiwyg-container>\n </div>\n\n <!-- Footer with color selector and save button -->\n @if (isEditing()) {\n <div class=\"ax-absolute ax-bottom-2 ax-left-2 ax-right-2 ax-flex ax-flex-wrap ax-gap-1 ax-text-xs\">\n <!-- Color selection bar when in edit mode -->\n <div class=\"ax-flex ax-w-full ax-mt-2 ax-border ax-border-gray-200 ax-overflow-hidden ax-rounded-md\">\n @for (preset of colorPresets; track preset) {\n <div\n class=\"ax-h-6 ax-flex-1 ax-cursor-pointer ax-transition-all ax-duration-200 ax-border-r ax-border-gray-200 last:ax-border-r-0 hover:ax-brightness-95\"\n [style.background-color]=\"preset\"\n [class.ax-ring-inset]=\"bgColor() === preset\"\n [class.ax-ring-2]=\"bgColor() === preset\"\n [class.ax-ring-primary]=\"bgColor() === preset\"\n (click)=\"setColor(preset)\"\n ></div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}:host ::ng-deep ax-wysiwyg-view{color:#2e2e2e!important}\n"] }]
2975
3081
  }], propDecorators: { wysiwyg: [{ type: i0.ViewChild, args: ['wysiwyg', { isSignal: true }] }], handleClickOutside: [{
2976
3082
  type: HostListener,
2977
3083
  args: ['document:click', ['$event']]
@@ -3007,12 +3113,27 @@ const AXPStickyNoteWidget = {
3007
3113
  },
3008
3114
  meta: {
3009
3115
  dimensions: {
3010
- width: 2,
3011
- height: 3,
3012
- minWidth: 2,
3013
- minHeight: 2,
3014
- maxWidth: 4,
3015
- maxHeight: 4,
3116
+ lg: {
3117
+ width: 2,
3118
+ height: 3,
3119
+ minWidth: 2,
3120
+ minHeight: 2,
3121
+ maxWidth: 4,
3122
+ maxHeight: 4,
3123
+ },
3124
+ md: {
3125
+ width: 2,
3126
+ height: 3,
3127
+ minWidth: 2,
3128
+ minHeight: 2,
3129
+ maxWidth: 4,
3130
+ maxHeight: 4,
3131
+ },
3132
+ sm: {
3133
+ height: 3,
3134
+ minHeight: 2,
3135
+ maxHeight: 4,
3136
+ },
3016
3137
  },
3017
3138
  },
3018
3139
  };
@@ -4101,12 +4222,27 @@ const AXPAdvancedWeatherWidget = {
4101
4222
  },
4102
4223
  meta: {
4103
4224
  dimensions: {
4104
- width: 3,
4105
- height: 5,
4106
- minWidth: 3,
4107
- minHeight: 5,
4108
- maxWidth: 5,
4109
- maxHeight: 7,
4225
+ lg: {
4226
+ width: 3,
4227
+ height: 5,
4228
+ minWidth: 3,
4229
+ minHeight: 5,
4230
+ maxWidth: 5,
4231
+ maxHeight: 7,
4232
+ },
4233
+ md: {
4234
+ width: 3,
4235
+ height: 5,
4236
+ minWidth: 3,
4237
+ minHeight: 5,
4238
+ maxWidth: 5,
4239
+ maxHeight: 7,
4240
+ },
4241
+ sm: {
4242
+ height: 5,
4243
+ minHeight: 5,
4244
+ maxHeight: 7,
4245
+ },
4110
4246
  },
4111
4247
  },
4112
4248
  };
@@ -4399,12 +4535,27 @@ const AXPMinimalWeatherWidget = {
4399
4535
  },
4400
4536
  meta: {
4401
4537
  dimensions: {
4402
- width: 2,
4403
- height: 2,
4404
- minWidth: 1,
4405
- minHeight: 2,
4406
- maxWidth: 2,
4407
- maxHeight: 3,
4538
+ lg: {
4539
+ width: 2,
4540
+ height: 2,
4541
+ minWidth: 1,
4542
+ minHeight: 2,
4543
+ maxWidth: 2,
4544
+ maxHeight: 3,
4545
+ },
4546
+ md: {
4547
+ width: 2,
4548
+ height: 2,
4549
+ minWidth: 1,
4550
+ minHeight: 2,
4551
+ maxWidth: 2,
4552
+ maxHeight: 3,
4553
+ },
4554
+ sm: {
4555
+ height: 2,
4556
+ minHeight: 2,
4557
+ maxHeight: 3,
4558
+ },
4408
4559
  },
4409
4560
  },
4410
4561
  };
@@ -4953,12 +5104,27 @@ const AXPWeatherWidget = {
4953
5104
  },
4954
5105
  meta: {
4955
5106
  dimensions: {
4956
- width: 3,
4957
- height: 7,
4958
- minWidth: 2,
4959
- minHeight: 4,
4960
- maxWidth: 4,
4961
- maxHeight: 8,
5107
+ lg: {
5108
+ width: 3,
5109
+ height: 7,
5110
+ minWidth: 2,
5111
+ minHeight: 4,
5112
+ maxWidth: 4,
5113
+ maxHeight: 8,
5114
+ },
5115
+ md: {
5116
+ width: 3,
5117
+ height: 7,
5118
+ minWidth: 2,
5119
+ minHeight: 4,
5120
+ maxWidth: 4,
5121
+ maxHeight: 8,
5122
+ },
5123
+ sm: {
5124
+ height: 7,
5125
+ minHeight: 4,
5126
+ maxHeight: 8,
5127
+ },
4962
5128
  },
4963
5129
  },
4964
5130
  };
@@ -5129,9 +5295,11 @@ class AXMDashboardWidgetWrapperComponent {
5129
5295
  this.widget = contentChild(AXPWidgetRendererDirective, ...(ngDevMode ? [{ debugName: "widget" }] : []));
5130
5296
  this.#init = afterNextRender(() => {
5131
5297
  this.widget()?.onOptionsChanged.subscribe((c) => {
5298
+ console.log(c);
5132
5299
  this.onOptionsChanged.emit(c.widget.options());
5133
5300
  });
5134
5301
  this.widget()?.onValueChanged.subscribe((c) => {
5302
+ console.log(c);
5135
5303
  this.onValueChanged.emit(c.widget.getValue());
5136
5304
  });
5137
5305
  });
@@ -5349,6 +5517,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5349
5517
  //#region ---- Imports ----
5350
5518
  //#endregion
5351
5519
  //#region ---- Utility Functions ----
5520
+ /** Width threshold for switching between lg (12 col) and md (6 col) breakpoints */
5521
+ const BREAKPOINT_MD_WIDTH = 768;
5522
+ const BREAKPOINT_MD_COLUMN = 6;
5523
+ const BREAKPOINT_SM_WIDTH = 576;
5524
+ const BREAKPOINT_SM_COLUMN = 1;
5525
+ /**
5526
+ * Returns the current dashboard breakpoint based on window width.
5527
+ * lg: > 768px (12 columns), md: 481–768px (6 columns), sm: <= 480px (1 column)
5528
+ */
5529
+ const getBreakpointFromWidth = () => {
5530
+ if (typeof window === 'undefined')
5531
+ return 'lg';
5532
+ const width = window.innerWidth;
5533
+ if (width <= BREAKPOINT_SM_WIDTH)
5534
+ return 'sm';
5535
+ if (width <= BREAKPOINT_MD_WIDTH)
5536
+ return 'md';
5537
+ return 'lg';
5538
+ };
5539
+ /**
5540
+ * Returns the grid column count for a given breakpoint.
5541
+ */
5542
+ const getColumnsForBreakpoint = (bp) => {
5543
+ switch (bp) {
5544
+ case 'sm':
5545
+ return BREAKPOINT_SM_COLUMN;
5546
+ case 'md':
5547
+ return BREAKPOINT_MD_COLUMN;
5548
+ case 'lg':
5549
+ default:
5550
+ return 12;
5551
+ }
5552
+ };
5352
5553
  /**
5353
5554
  * Creates the initial state for the dashboard store.
5354
5555
  */
@@ -5362,22 +5563,45 @@ const createInitialState = () => ({
5362
5563
  cellHeight: 75,
5363
5564
  gap: 5,
5364
5565
  minRow: 9,
5365
- column: 12,
5366
- responsiveLayout: [
5367
- { column: 4, width: 768 },
5368
- { column: 1, width: 480 },
5369
- ],
5566
+ column: getColumnsForBreakpoint(getBreakpointFromWidth()),
5370
5567
  },
5371
5568
  isLoading: false,
5569
+ currentBreakpoint: getBreakpointFromWidth(),
5570
+ isBreakpointTransitioning: false,
5372
5571
  });
5572
+ /**
5573
+ * Migrates a widget config from the old flat format to the new per-breakpoint format.
5574
+ * Old format: { id, x, y, width, height, minWidth, ... }
5575
+ * New format: { id, lg: { ... }, md: { ... }, sm: { ... } }
5576
+ */
5577
+ const migrateWidgetConfig = (widget) => {
5578
+ const config = widget.config;
5579
+ // Already in new format (has lg key as an object)
5580
+ if (config && typeof config.lg === 'object' && config.lg !== null) {
5581
+ return widget;
5582
+ }
5583
+ // Old flat format: convert to per-breakpoint
5584
+ const { id, ...rest } = config || {};
5585
+ const widgetId = id || AXPDataGenerator.uuid();
5586
+ return {
5587
+ ...widget,
5588
+ config: {
5589
+ id: widgetId,
5590
+ lg: { id: widgetId, ...rest },
5591
+ md: { id: widgetId, ...rest },
5592
+ sm: { id: widgetId, width: 1, height: rest.height || 2 },
5593
+ },
5594
+ };
5595
+ };
5373
5596
  /**
5374
5597
  * Maps an entity model to a dashboard layout model.
5598
+ * Automatically migrates old flat widget configs to the new per-breakpoint format.
5375
5599
  */
5376
5600
  const modelToDashboardLayout = (model) => ({
5377
5601
  id: model.id || '',
5378
5602
  title: model.title,
5379
5603
  description: model.description,
5380
- widgets: model.widgets || [],
5604
+ widgets: (model.widgets || []).map(migrateWidgetConfig),
5381
5605
  createdBy: model.userId ?? model.auditInfo?.created?.by?.id,
5382
5606
  roleIds: model.roleIds,
5383
5607
  isDeleted: model.isDeleted,
@@ -5457,23 +5681,22 @@ const hasMatchingRole = (dashboard, userRole) => {
5457
5681
  };
5458
5682
  /**
5459
5683
  * Computes effective layout options based on device, lock, admin and role restrictions.
5684
+ * Always derives drag/resize state from the dashboard model — never from base options.
5460
5685
  */
5461
5686
  const deriveLayoutOptions = (baseOptions, dashboard, isAdmin, isDesktop, userRole) => {
5687
+ const { disableDrag: _dd, disableResize: _dr, ...cleanBase } = baseOptions;
5462
5688
  if (!dashboard)
5463
- return baseOptions;
5464
- if (!isDesktop)
5465
- return { ...baseOptions, disableDrag: true, disableResize: true };
5466
- if (baseOptions.disableDrag !== undefined && baseOptions.disableResize !== undefined)
5467
- return baseOptions;
5689
+ return cleanBase;
5690
+ // if (!isDesktop) return { ...cleanBase, disableDrag: true, disableResize: true };
5468
5691
  if (dashboard.locked === true)
5469
- return { ...baseOptions, disableDrag: true, disableResize: true };
5692
+ return { ...cleanBase, disableDrag: true, disableResize: true };
5470
5693
  if (isAdmin)
5471
- return baseOptions;
5694
+ return cleanBase;
5472
5695
  const roleMatched = hasMatchingRole(dashboard, userRole);
5473
- if (!isAdmin && roleMatched && dashboard.scope === 'T') {
5474
- return { ...baseOptions, disableDrag: true, disableResize: true };
5696
+ if (roleMatched && dashboard.scope === 'T') {
5697
+ return { ...cleanBase, disableDrag: true, disableResize: true };
5475
5698
  }
5476
- return baseOptions;
5699
+ return cleanBase;
5477
5700
  };
5478
5701
  /**
5479
5702
  * Checks if a widget is locked for the current user based on dashboard and role context.
@@ -5536,7 +5759,25 @@ withComputed((state, sessionService = inject(AXPSessionService), deviceService =
5536
5759
  const baseOptions = state.dashboardsOption();
5537
5760
  const isDesktop = deviceService.isDesktopDevice();
5538
5761
  const userRole = readUserRole(sessionService);
5539
- return deriveLayoutOptions(baseOptions, currentDashboard || undefined, state.isAdmin(), isDesktop, userRole);
5762
+ // Dynamically set column count based on the current breakpoint
5763
+ const bp = state.currentBreakpoint();
5764
+ const optionsWithColumn = { ...baseOptions, column: getColumnsForBreakpoint(bp) };
5765
+ return deriveLayoutOptions(optionsWithColumn, currentDashboard || undefined, state.isAdmin(), isDesktop, userRole);
5766
+ }),
5767
+ /**
5768
+ * Returns the current dashboard's widgets with their resolved breakpoint options.
5769
+ * This computed depends on BOTH the dashboard widgets AND currentBreakpoint,
5770
+ * ensuring the @for source produces a new array when the breakpoint changes.
5771
+ */
5772
+ currentWidgets: computed(() => {
5773
+ const dashboard = state.dashboards().find((d) => d.id === state.currentDashboardId());
5774
+ const bp = state.currentBreakpoint();
5775
+ if (!dashboard?.widgets)
5776
+ return [];
5777
+ return dashboard.widgets.map((widget) => ({
5778
+ ...widget,
5779
+ resolvedOptions: widget.config[bp],
5780
+ }));
5540
5781
  }),
5541
5782
  canConfigureWidget: computed(() => (widget) => {
5542
5783
  const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
@@ -5558,6 +5799,52 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
5558
5799
  const isAdmin = store.isUserAdmin();
5559
5800
  loadDashboards(isAdmin);
5560
5801
  });
5802
+ // Track window resize and update currentBreakpoint signal.
5803
+ // Sets isBreakpointTransitioning to suppress onGridChange saves
5804
+ // while the grid settles after a breakpoint switch.
5805
+ let transitionTimer = null;
5806
+ // Queued save: ensures only one save is in-flight at a time.
5807
+ // If a new save is requested while one is running, it queues the latest and runs it after.
5808
+ let isSaving = false;
5809
+ let pendingSaveDashboard = null;
5810
+ async function persistDashboard(dashboard) {
5811
+ if (isSaving) {
5812
+ // Queue the latest dashboard for saving after current completes
5813
+ pendingSaveDashboard = dashboard;
5814
+ return;
5815
+ }
5816
+ isSaving = true;
5817
+ try {
5818
+ await dashboardService.updateOne(dashboard.id, dashboardLayoutToModel(dashboard));
5819
+ }
5820
+ catch (error) {
5821
+ console.error('Error saving dashboard layout:', error);
5822
+ }
5823
+ isSaving = false;
5824
+ // Process queued save if any
5825
+ if (pendingSaveDashboard) {
5826
+ const next = pendingSaveDashboard;
5827
+ pendingSaveDashboard = null;
5828
+ await persistDashboard(next);
5829
+ }
5830
+ }
5831
+ if (typeof window !== 'undefined') {
5832
+ fromEvent(window, 'resize')
5833
+ .pipe(debounceTime(100))
5834
+ .subscribe(() => {
5835
+ const bp = getBreakpointFromWidth();
5836
+ if (bp !== store.currentBreakpoint()) {
5837
+ if (transitionTimer)
5838
+ clearTimeout(transitionTimer);
5839
+ patchState(store, { currentBreakpoint: bp, isBreakpointTransitioning: true });
5840
+ // End transition after grid has settled (~500ms covers GridStack reflow + Angular CD)
5841
+ transitionTimer = setTimeout(() => {
5842
+ patchState(store, { isBreakpointTransitioning: false });
5843
+ transitionTimer = null;
5844
+ }, 500);
5845
+ }
5846
+ });
5847
+ }
5561
5848
  /**
5562
5849
  * Loads dashboards and sets current dashboard based on user settings.
5563
5850
  */
@@ -5772,18 +6059,41 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
5772
6059
  widget.path = `${widget.type}-${randomId}`;
5773
6060
  return widget;
5774
6061
  });
5775
- const convertedWidgets = filteredWidgets.map((widget) => ({
5776
- config: {
5777
- height: widget?.meta?.dimensions?.height ?? 2,
5778
- width: widget?.meta?.dimensions?.width ?? 2,
5779
- minHeight: widget?.meta?.dimensions?.minHeight,
5780
- minWidth: widget?.meta?.dimensions?.minWidth,
5781
- maxHeight: widget?.meta?.dimensions?.maxHeight,
5782
- maxWidth: widget?.meta?.dimensions?.maxWidth,
5783
- id: AXPDataGenerator.uuid(),
5784
- },
5785
- node: { ...widget, name: widget.name },
5786
- }));
6062
+ const convertedWidgets = filteredWidgets.map((widget) => {
6063
+ const id = AXPDataGenerator.uuid();
6064
+ const dims = widget?.meta?.dimensions;
6065
+ return {
6066
+ config: {
6067
+ id,
6068
+ lg: {
6069
+ id,
6070
+ height: dims?.lg?.height ?? 2,
6071
+ width: dims?.lg?.width ?? 2,
6072
+ minHeight: dims?.lg?.minHeight,
6073
+ minWidth: dims?.lg?.minWidth,
6074
+ maxHeight: dims?.lg?.maxHeight,
6075
+ maxWidth: dims?.lg?.maxWidth,
6076
+ },
6077
+ md: {
6078
+ id,
6079
+ height: dims?.md?.height ?? dims?.lg?.height ?? 2,
6080
+ width: dims?.md?.width ?? dims?.lg?.width ?? 2,
6081
+ minHeight: dims?.md?.minHeight ?? dims?.lg?.minHeight,
6082
+ minWidth: dims?.md?.minWidth ?? dims?.lg?.minWidth,
6083
+ maxHeight: dims?.md?.maxHeight ?? dims?.lg?.maxHeight,
6084
+ maxWidth: dims?.md?.maxWidth ?? dims?.lg?.maxWidth,
6085
+ },
6086
+ sm: {
6087
+ id,
6088
+ width: 1,
6089
+ height: dims?.sm?.height ?? dims?.lg?.height ?? 2,
6090
+ minHeight: dims?.sm?.minHeight ?? dims?.lg?.minHeight,
6091
+ maxHeight: dims?.sm?.maxHeight ?? dims?.lg?.maxHeight,
6092
+ },
6093
+ },
6094
+ node: { ...widget, name: widget.name },
6095
+ };
6096
+ });
5787
6097
  const currentDashboard = store.selectedDashboard();
5788
6098
  const updatedDashboard = {
5789
6099
  ...currentDashboard,
@@ -5870,22 +6180,51 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
5870
6180
  settingsService.scope(AXPPlatformScope.User).set(AXPHomeDashboardSetting$1.CurrentDashboard, dashboard.id);
5871
6181
  },
5872
6182
  /**
5873
- * Handles grid layout changes (drag/resize) on desktop and saves positions.
6183
+ * Handles grid layout changes (drag/resize) and saves positions for the current breakpoint.
6184
+ * Skips saving during breakpoint transitions to avoid persisting auto-reflowed layouts.
6185
+ * Persists immediately with queued writes to prevent concurrent save conflicts.
5874
6186
  */
5875
- async onGridChange(event) {
5876
- if (!deviceService.isDesktopDevice() || !store.selectedDashboard())
6187
+ onGridChange(event) {
6188
+ if (!store.selectedDashboard())
6189
+ return;
6190
+ // Skip saves during breakpoint transitions to avoid persisting auto-reflowed layouts
6191
+ if (store.isBreakpointTransitioning())
6192
+ return;
6193
+ // Skip if the live window breakpoint disagrees with the store
6194
+ const liveBp = getBreakpointFromWidth();
6195
+ const storeBp = store.currentBreakpoint();
6196
+ if (liveBp !== storeBp)
5877
6197
  return;
6198
+ const bp = storeBp;
5878
6199
  const nodes = event.nodes.map(({ element, ...rest }) => rest);
5879
6200
  const currentDashboard = store.selectedDashboard();
6201
+ let hasChanges = false;
5880
6202
  const updatedWidgets = currentDashboard.widgets.map((widget) => {
5881
6203
  const updatedNode = nodes.find((node) => node.id === widget.config.id);
5882
- return updatedNode ? { ...widget, config: updatedNode } : widget;
6204
+ if (!updatedNode)
6205
+ return widget;
6206
+ const existing = widget.config[bp];
6207
+ if (existing?.x === updatedNode.x &&
6208
+ existing?.y === updatedNode.y &&
6209
+ existing?.width === updatedNode.width &&
6210
+ existing?.height === updatedNode.height) {
6211
+ return widget;
6212
+ }
6213
+ hasChanges = true;
6214
+ return {
6215
+ ...widget,
6216
+ config: {
6217
+ ...widget.config,
6218
+ [bp]: { ...widget.config[bp], ...updatedNode, id: widget.config.id },
6219
+ },
6220
+ };
5883
6221
  });
6222
+ if (!hasChanges)
6223
+ return;
5884
6224
  const updatedDashboard = {
5885
6225
  ...currentDashboard,
5886
6226
  widgets: updatedWidgets,
5887
6227
  };
5888
- await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
5889
6228
  const updatedDashboards = store
5890
6229
  .dashboards()
5891
6230
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
@@ -5893,6 +6232,8 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
5893
6232
  .availableDashboards()
5894
6233
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
5895
6234
  patchState(store, { dashboards: updatedDashboards, allDashboards: updatedAllDashboards });
6235
+ // Persist to storage (queued to prevent concurrent writes)
6236
+ persistDashboard(updatedDashboard);
5896
6237
  },
5897
6238
  /**
5898
6239
  * Applies widget configuration changes returned from popup.
@@ -6013,23 +6354,18 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
6013
6354
  console.warn('User does not have permission to toggle lock for this dashboard');
6014
6355
  return;
6015
6356
  }
6016
- const newLockedState = !currentDashboard.locked;
6017
6357
  const updatedDashboard = {
6018
6358
  ...currentDashboard,
6019
- locked: newLockedState,
6359
+ locked: !currentDashboard.locked,
6020
6360
  };
6021
6361
  await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
6022
6362
  const updatedDashboards = store
6023
6363
  .dashboards()
6024
6364
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
6025
- const baseOptions = { ...store.dashboardsOption() };
6026
- patchState(store, { dashboards: updatedDashboards });
6027
- const updatedOptions = {
6028
- ...baseOptions,
6029
- disableDrag: newLockedState,
6030
- disableResize: newLockedState,
6031
- };
6032
- patchState(store, { dashboardsOption: updatedOptions });
6365
+ const updatedAllDashboards = store
6366
+ .availableDashboards()
6367
+ .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
6368
+ patchState(store, { dashboards: updatedDashboards, allDashboards: updatedAllDashboards });
6033
6369
  }
6034
6370
  catch (error) {
6035
6371
  console.error('Error toggling dashboard lock state:', error);
@@ -6202,11 +6538,11 @@ class AXMDashboardHomeComponent extends AXPPageLayoutBaseComponent {
6202
6538
  provide: AXPPageLayoutBase,
6203
6539
  useExisting: AXMDashboardHomeComponent,
6204
6540
  },
6205
- ], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n <!-- Loading State -->\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ '@dashboard:loading' | translate | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.currentLayoutOptions()\" (onChange)=\"store.onGridChange($event)\">\n <!-- No Dashboards State -->\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:empty-state.title'\"\n [description]=\"'@dashboard:empty-state.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-dashboard' })\" class=\"ax-underline\">\n {{ '@dashboard:add-first-dashboard' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- No Selected Dashboard State -->\n <!-- @else if (!store.selectedDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ '@dashboard:no-current-dashboard' | translate | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ '@dashboard:select-dashboard' | translate | async }}</p>\n </div>\n } -->\n <!-- No Widgets State -->\n @else if (!store.selectedDashboard()?.widgets || store.selectedDashboard()?.widgets?.length === 0) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:no-widgets.title'\"\n [description]=\"'@dashboard:no-widgets.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-widget' })\" class=\"ax-underline\">\n {{ '@dashboard:add-widget' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- Widgets Grid -->\n @else { @for(widget of store.selectedDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget\n [options]=\"widget.config\"\n class=\"dark:[--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lighter-surface)] [--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lightest-surface)]\"\n >\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.selectedDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1$4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i2$2.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i2$2.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXGridLayoutBuilderModule }, { kind: "component", type: i3$2.AXGridLayoutContainerComponent, selector: "ax-grid-layout-container", inputs: ["options", "isEmpty"], outputs: ["onAdded", "onRemoved", "onWidgetChange", "onChange", "onRender", "isEmptyChange"] }, { kind: "component", type: i3$2.AXGridLayoutWidgetComponent, selector: "ax-grid-layout-widget", inputs: ["options"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i4.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "component", type: AXMDashboardWidgetWrapperComponent, selector: "axm-dashboard-widget-wrapper", inputs: ["title", "hasConfiguration", "isLocked"], outputs: ["onDelete", "onConfiguration", "onValueChanged", "onOptionsChanged"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6541
+ ], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <axp-page-content class=\"ax-relative\">\n <!-- Loading State -->\n @if (store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ '@dashboard:loading' | translate | async }}</p>\n </div>\n }\n <!-- No Dashboards State -->\n @else if (!store.dashboards().length) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:empty-state.title'\"\n [description]=\"'@dashboard:empty-state.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-dashboard' })\" class=\"ax-underline\">\n {{ '@dashboard:add-first-dashboard' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- No Widgets State -->\n @else if (!store.selectedDashboard()?.widgets?.length) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:no-widgets.title'\"\n [description]=\"'@dashboard:no-widgets.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-widget' })\" class=\"ax-underline\">\n {{ '@dashboard:add-widget' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- Dashboard Grid -->\n @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container\n class=\"dark:[--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lighter-surface)] [--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lightest-surface)]\"\n [options]=\"store.currentLayoutOptions()\"\n (onChange)=\"store.onGridChange($event)\"\n >\n @for (widget of store.currentWidgets(); track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.resolvedOptions\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.selectedDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!, $event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!, $event)\"\n >\n @if (widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1$4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i2$2.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i2$2.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXGridLayoutBuilderModule }, { kind: "component", type: i3$2.AXGridLayoutContainerComponent, selector: "ax-grid-layout-container", inputs: ["options", "isEmpty"], outputs: ["onAdded", "onRemoved", "onWidgetChange", "onChange", "onRender", "isEmptyChange"] }, { kind: "component", type: i3$2.AXGridLayoutWidgetComponent, selector: "ax-grid-layout-widget", inputs: ["options"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i4.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "component", type: AXMDashboardWidgetWrapperComponent, selector: "axm-dashboard-widget-wrapper", inputs: ["title", "hasConfiguration", "isLocked"], outputs: ["onDelete", "onConfiguration", "onValueChanged", "onOptionsChanged"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6206
6542
  }
6207
6543
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMDashboardHomeComponent, decorators: [{
6208
6544
  type: Component,
6209
- args: [{ selector: 'axm-dashboard-home', standalone: true, imports: [
6545
+ args: [{ selector: 'axm-dashboard-home', imports: [
6210
6546
  CommonModule,
6211
6547
  AXLoadingModule,
6212
6548
  AXPWidgetCoreModule,
@@ -6229,7 +6565,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
6229
6565
  provide: AXPPageLayoutBase,
6230
6566
  useExisting: AXMDashboardHomeComponent,
6231
6567
  },
6232
- ], template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n <!-- Loading State -->\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ '@dashboard:loading' | translate | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.currentLayoutOptions()\" (onChange)=\"store.onGridChange($event)\">\n <!-- No Dashboards State -->\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:empty-state.title'\"\n [description]=\"'@dashboard:empty-state.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-dashboard' })\" class=\"ax-underline\">\n {{ '@dashboard:add-first-dashboard' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- No Selected Dashboard State -->\n <!-- @else if (!store.selectedDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ '@dashboard:no-current-dashboard' | translate | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ '@dashboard:select-dashboard' | translate | async }}</p>\n </div>\n } -->\n <!-- No Widgets State -->\n @else if (!store.selectedDashboard()?.widgets || store.selectedDashboard()?.widgets?.length === 0) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:no-widgets.title'\"\n [description]=\"'@dashboard:no-widgets.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-widget' })\" class=\"ax-underline\">\n {{ '@dashboard:add-widget' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- Widgets Grid -->\n @else { @for(widget of store.selectedDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget\n [options]=\"widget.config\"\n class=\"dark:[--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lighter-surface)] [--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lightest-surface)]\"\n >\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.selectedDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}\n"] }]
6568
+ ], template: "<axp-page-layout *translate=\"let t\">\n <axp-page-content class=\"ax-relative\">\n <!-- Loading State -->\n @if (store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ '@dashboard:loading' | translate | async }}</p>\n </div>\n }\n <!-- No Dashboards State -->\n @else if (!store.dashboards().length) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:empty-state.title'\"\n [description]=\"'@dashboard:empty-state.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-dashboard' })\" class=\"ax-underline\">\n {{ '@dashboard:add-first-dashboard' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- No Widgets State -->\n @else if (!store.selectedDashboard()?.widgets?.length) {\n <axp-state-message\n icon=\"fa-light fa-shapes\"\n [title]=\"'@dashboard:no-widgets.title'\"\n [description]=\"'@dashboard:no-widgets.description'\"\n >\n <div slot=\"actions\">\n <button (click)=\"execute({ name: 'new-widget' })\" class=\"ax-underline\">\n {{ '@dashboard:add-widget' | translate | async }}\n </button>\n </div>\n </axp-state-message>\n }\n <!-- Dashboard Grid -->\n @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container\n class=\"dark:[--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lighter-surface)] [--ax-comp-grid-layout-stack-item-content-bg-color:var(--ax-sys-color-lightest-surface)]\"\n [options]=\"store.currentLayoutOptions()\"\n (onChange)=\"store.onGridChange($event)\"\n >\n @for (widget of store.currentWidgets(); track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.resolvedOptions\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.selectedDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!, $event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!, $event)\"\n >\n @if (widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}\n"] }]
6233
6569
  }] });
6234
6570
 
6235
6571
  var homeDashboard = /*#__PURE__*/Object.freeze({
@@ -6237,6 +6573,8 @@ var homeDashboard = /*#__PURE__*/Object.freeze({
6237
6573
  AXMDashboardHomeComponent: AXMDashboardHomeComponent
6238
6574
  });
6239
6575
 
6576
+ //#endregion
6577
+
6240
6578
  class AXMAddDashboardPopup extends AXBasePageComponent {
6241
6579
  constructor() {
6242
6580
  super(...arguments);