@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.
- package/asset-management/index.d.ts +24 -33
- package/dashboard-management/index.d.ts +40 -5
- package/document-management/index.d.ts +1 -26
- package/fesm2022/acorex-modules-asset-management-asset.entity-D_w4zjNb.mjs +612 -0
- package/fesm2022/acorex-modules-asset-management-asset.entity-D_w4zjNb.mjs.map +1 -0
- package/fesm2022/acorex-modules-asset-management-manual-asset-category.entity-DyIV_vbE.mjs +267 -0
- package/fesm2022/acorex-modules-asset-management-manual-asset-category.entity-DyIV_vbE.mjs.map +1 -0
- package/fesm2022/acorex-modules-asset-management.mjs +59 -117
- package/fesm2022/acorex-modules-asset-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-dashboard-management.mjs +454 -116
- package/fesm2022/acorex-modules-dashboard-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-data-management.mjs +4 -2
- package/fesm2022/acorex-modules-data-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-document-management.mjs +40 -99
- package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-maintenance-management.mjs +194 -103
- package/fesm2022/acorex-modules-maintenance-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-notification-management.mjs +21 -6
- package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-reservation-management-acorex-modules-reservation-management-CkHGIQ38.mjs +2135 -0
- package/fesm2022/acorex-modules-reservation-management-acorex-modules-reservation-management-CkHGIQ38.mjs.map +1 -0
- package/fesm2022/acorex-modules-reservation-management-reservation-class-status.entity-Clyj7r2x.mjs +263 -0
- package/fesm2022/acorex-modules-reservation-management-reservation-class-status.entity-Clyj7r2x.mjs.map +1 -0
- package/fesm2022/acorex-modules-reservation-management-reservation-resource-type.entity-BXb0FTQ5.mjs +184 -0
- package/fesm2022/acorex-modules-reservation-management-reservation-resource-type.entity-BXb0FTQ5.mjs.map +1 -0
- package/fesm2022/acorex-modules-reservation-management-reservation-status-transition.entity-BT8GQ9MC.mjs +247 -0
- package/fesm2022/acorex-modules-reservation-management-reservation-status-transition.entity-BT8GQ9MC.mjs.map +1 -0
- package/fesm2022/acorex-modules-reservation-management.mjs +1 -3325
- package/fesm2022/acorex-modules-reservation-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-task-management-task-board.page-BOOY3qla.mjs → acorex-modules-task-management-task-board.page-BBKB4yir.mjs} +114 -62
- package/fesm2022/acorex-modules-task-management-task-board.page-BBKB4yir.mjs.map +1 -0
- package/fesm2022/acorex-modules-task-management.mjs +43 -13
- package/fesm2022/acorex-modules-task-management.mjs.map +1 -1
- package/maintenance-management/index.d.ts +7 -3
- package/package.json +2 -2
- package/reservation-management/index.d.ts +84 -338
- package/fesm2022/acorex-modules-asset-management-asset.entity-C57iN3Bo.mjs +0 -357
- package/fesm2022/acorex-modules-asset-management-asset.entity-C57iN3Bo.mjs.map +0 -1
- package/fesm2022/acorex-modules-asset-management-inspection.entity-CpDuN-qj.mjs +0 -198
- package/fesm2022/acorex-modules-asset-management-inspection.entity-CpDuN-qj.mjs.map +0 -1
- 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
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
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
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
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
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
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
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
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
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
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
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
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
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
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
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
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
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
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
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
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:
|
|
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
|
|
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 { ...
|
|
5692
|
+
return { ...cleanBase, disableDrag: true, disableResize: true };
|
|
5470
5693
|
if (isAdmin)
|
|
5471
|
-
return
|
|
5694
|
+
return cleanBase;
|
|
5472
5695
|
const roleMatched = hasMatchingRole(dashboard, userRole);
|
|
5473
|
-
if (
|
|
5474
|
-
return { ...
|
|
5696
|
+
if (roleMatched && dashboard.scope === 'T') {
|
|
5697
|
+
return { ...cleanBase, disableDrag: true, disableResize: true };
|
|
5475
5698
|
}
|
|
5476
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
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)
|
|
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
|
-
|
|
5876
|
-
if (!
|
|
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
|
-
|
|
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:
|
|
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
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
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
|
|
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',
|
|
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
|
|
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);
|