@acorex/platform 19.1.2 → 19.1.4

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 (162) hide show
  1. package/common/index.d.ts +2 -0
  2. package/common/lib/app/application.types.d.ts +12 -10
  3. package/common/lib/configs/app.config.d.ts +0 -1
  4. package/common/lib/file-storage/file-storage.service.d.ts +13 -0
  5. package/common/lib/file-storage/file-storage.types.d.ts +143 -0
  6. package/common/lib/file-storage/index.d.ts +2 -0
  7. package/common/lib/filters/filters.service.d.ts +8 -0
  8. package/common/lib/filters/filters.types.d.ts +19 -0
  9. package/common/lib/filters/index.d.ts +2 -0
  10. package/common/lib/settings/setting-definition.provider.d.ts +13 -4
  11. package/common/lib/settings/setting.builder.d.ts +7 -8
  12. package/common/lib/settings/settings.provider.d.ts +2 -7
  13. package/common/lib/settings/settings.service.d.ts +19 -7
  14. package/common/lib/settings/settings.types.d.ts +15 -2
  15. package/core/utils/highlighter.d.ts +1 -1
  16. package/fesm2022/acorex-platform-auth.mjs +5 -4
  17. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-common.mjs +264 -87
  19. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-core.mjs +2 -2
  21. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-layout-builder.mjs +286 -440
  23. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  24. package/fesm2022/acorex-platform-layout-designer.mjs +18 -18
  25. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  26. package/fesm2022/acorex-platform-layout-entity.mjs +335 -232
  27. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  28. package/fesm2022/acorex-platform-layout-filters.mjs +124 -0
  29. package/fesm2022/acorex-platform-layout-filters.mjs.map +1 -0
  30. package/fesm2022/acorex-platform-layout-setting.mjs +219 -132
  31. package/fesm2022/acorex-platform-layout-setting.mjs.map +1 -1
  32. package/fesm2022/acorex-platform-layouts.mjs +4 -5
  33. package/fesm2022/acorex-platform-layouts.mjs.map +1 -1
  34. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-K9B_-q_K.mjs +108 -0
  35. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-K9B_-q_K.mjs.map +1 -0
  36. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DAmHq1bt.mjs +369 -0
  37. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DAmHq1bt.mjs.map +1 -0
  38. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Cd2gxLZt.mjs +87 -0
  39. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Cd2gxLZt.mjs.map +1 -0
  40. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-6sZdw013.mjs +130 -0
  41. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-6sZdw013.mjs.map +1 -0
  42. package/fesm2022/acorex-platform-themes-default-setting-page.component-BYpCgHZb.mjs +74 -0
  43. package/fesm2022/acorex-platform-themes-default-setting-page.component-BYpCgHZb.mjs.map +1 -0
  44. package/fesm2022/acorex-platform-themes-default-setting-view.component-CdmIphX1.mjs +73 -0
  45. package/fesm2022/acorex-platform-themes-default-setting-view.component-CdmIphX1.mjs.map +1 -0
  46. package/fesm2022/acorex-platform-themes-default.mjs +40 -114
  47. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  48. package/fesm2022/acorex-platform-themes-shared.mjs +465 -157
  49. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  50. package/fesm2022/{acorex-platform-widgets-checkbox-widget-column.component-05nKV-UV.mjs → acorex-platform-widgets-checkbox-widget-column.component-jeZBOEhl.mjs} +18 -14
  51. package/fesm2022/acorex-platform-widgets-checkbox-widget-column.component-jeZBOEhl.mjs.map +1 -0
  52. package/fesm2022/{acorex-platform-widgets-checkbox-widget-designer.component-juhKoygA.mjs → acorex-platform-widgets-checkbox-widget-designer.component-RCi5IJOR.mjs} +5 -5
  53. package/fesm2022/acorex-platform-widgets-checkbox-widget-designer.component-RCi5IJOR.mjs.map +1 -0
  54. package/fesm2022/acorex-platform-widgets-checkbox-widget-view.component-DU1niJES.mjs +64 -0
  55. package/fesm2022/acorex-platform-widgets-checkbox-widget-view.component-DU1niJES.mjs.map +1 -0
  56. package/fesm2022/{acorex-platform-widgets-color-box-widget-designer.component-B2g0ct24.mjs → acorex-platform-widgets-color-box-widget-designer.component-CWhbgmDV.mjs} +4 -4
  57. package/fesm2022/acorex-platform-widgets-color-box-widget-designer.component-CWhbgmDV.mjs.map +1 -0
  58. package/fesm2022/acorex-platform-widgets.mjs +1396 -286
  59. package/fesm2022/acorex-platform-widgets.mjs.map +1 -1
  60. package/fesm2022/acorex-platform-workflow.mjs +9 -3
  61. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  62. package/layout/builder/lib/builder/builder.module.d.ts +6 -7
  63. package/layout/builder/lib/builder/builder.service.d.ts +9 -10
  64. package/layout/builder/lib/builder/context-store.service.d.ts +33 -0
  65. package/layout/builder/lib/builder/index.d.ts +4 -2
  66. package/layout/builder/lib/builder/widget-catalog.d.ts +1 -1
  67. package/layout/builder/lib/builder/widget-container.component.d.ts +34 -9
  68. package/layout/builder/lib/builder/widget-groups.d.ts +1 -0
  69. package/layout/builder/lib/builder/widget-map.d.ts +43 -0
  70. package/layout/builder/lib/builder/{widget-renderer.component.directive.d.ts → widget-renderer.directive.d.ts} +29 -4
  71. package/layout/builder/lib/builder/widget-status.types.d.ts +14 -0
  72. package/layout/builder/lib/builder/widget.types.d.ts +51 -59
  73. package/layout/designer/lib/preview/preview-viewer.component.d.ts +2 -2
  74. package/layout/designer/lib/property-viewer/widget-property-viewer.component.d.ts +2 -2
  75. package/layout/entity/lib/entity-master-list.viewmodel.d.ts +8 -2
  76. package/layout/entity/lib/widgets/lookup-widget/lookup-widget-edit.component.d.ts +0 -1
  77. package/layout/entity/lib/workflows/modify-entity.workflow.d.ts +14 -0
  78. package/layout/filters/README.md +3 -0
  79. package/layout/filters/index.d.ts +1 -0
  80. package/layout/filters/lib/filters.viewmodel.d.ts +30 -0
  81. package/layout/setting/lib/convert-setting-data.d.ts +0 -20
  82. package/layout/setting/lib/setting.viewmodel.d.ts +85 -22
  83. package/layouts/lib/admin/entity-layout/entity-details-view/entity-details-view.component.d.ts +15 -5
  84. package/package.json +13 -9
  85. package/themes/default/index.d.ts +0 -1
  86. package/themes/default/lib/layouts/base/simple-page/simple-page.layout.d.ts +20 -10
  87. package/themes/default/lib/layouts/entity-layouts/entity-detail-list-view/entity-detail-list-view.component.d.ts +15 -5
  88. package/themes/default/lib/layouts/entity-layouts/entity-master-create-view/entity-master-create-view.component.d.ts +2 -1
  89. package/themes/default/lib/layouts/entity-layouts/entity-master-list-view/entity-master-list-view.component.d.ts +17 -6
  90. package/themes/default/lib/layouts/entity-layouts/entity-master-list-view/list-view-option-filters/list-view-option-filters.component.d.ts +14 -0
  91. package/themes/default/lib/layouts/entity-layouts/entity-master-modify-view/entity-master-modify-view.component.d.ts +2 -1
  92. package/themes/default/lib/layouts/entity-layouts/entity-master-single-view/entity-master-single-view.component.d.ts +15 -5
  93. package/themes/default/lib/layouts/filters-layout/simple-filter-builder/filters-view.component.d.ts +13 -0
  94. package/themes/default/lib/layouts/root-layout/components/header/header.component.d.ts +15 -5
  95. package/themes/default/lib/layouts/root-layout/root-layout.component.d.ts +15 -5
  96. package/themes/default/lib/layouts/setting-layout/setting-page/setting-page.component.d.ts +2 -4
  97. package/themes/default/lib/layouts/setting-layout/setting-view/setting-view.component.d.ts +57 -0
  98. package/themes/shared/index.d.ts +3 -1
  99. package/themes/shared/lib/components/layout-elements/index.d.ts +5 -3
  100. package/themes/shared/lib/components/layout-elements/{layout-page-actions.component.d.ts → layout-actions.component.d.ts} +5 -5
  101. package/themes/shared/lib/components/layout-elements/layout-blocks.component.d.ts +1 -1
  102. package/themes/shared/lib/components/layout-elements/layout-header.component.d.ts +12 -0
  103. package/themes/shared/lib/components/layout-elements/layout-list-component.d.ts +13 -0
  104. package/themes/shared/lib/components/layout-elements/layout-section.component.d.ts +9 -0
  105. package/themes/shared/lib/components/layout-elements/layout-side.component.d.ts +9 -0
  106. package/themes/shared/lib/components/theme-slot.component.d.ts +23 -13
  107. package/themes/shared/lib/palette.provider.d.ts +9 -0
  108. package/themes/shared/lib/setting.keys.d.ts +7 -2
  109. package/themes/shared/lib/setting.provider.d.ts +1 -0
  110. package/themes/shared/lib/shared.module.d.ts +5 -2
  111. package/themes/shared/lib/{services/theme.service.d.ts → theme.service.d.ts} +16 -24
  112. package/themes/shared/lib/theme.types.d.ts +25 -0
  113. package/themes/shared/lib/widgets/theme-color-selection/index.d.ts +2 -0
  114. package/themes/shared/lib/widgets/theme-color-selection/theme-color-selection-widget-edit.component.d.ts +6 -0
  115. package/themes/shared/lib/widgets/theme-color-selection/theme-color-selection-widget.config.d.ts +7 -0
  116. package/widgets/lib/properties/editors.props.d.ts +2 -0
  117. package/widgets/lib/properties/layout.props.d.ts +1 -0
  118. package/widgets/lib/widgets/advance/avatar/avatar-widget-column.component.d.ts +6 -0
  119. package/widgets/lib/widgets/advance/avatar/avatar-widget-designer.component.d.ts +6 -0
  120. package/widgets/lib/widgets/advance/avatar/avatar-widget-edit.component.d.ts +18 -0
  121. package/widgets/lib/widgets/advance/avatar/avatar-widget-print.component.d.ts +6 -0
  122. package/widgets/lib/widgets/advance/avatar/avatar-widget-view.component.d.ts +6 -0
  123. package/widgets/lib/widgets/advance/avatar/avatar-widget.config.d.ts +7 -0
  124. package/widgets/lib/widgets/advance/avatar/index.d.ts +6 -0
  125. package/widgets/lib/widgets/advance/map/map-box-widget-edit.component.d.ts +9 -5
  126. package/widgets/lib/widgets/advance/map/map-box-widget-view.component.d.ts +6 -4
  127. package/widgets/lib/widgets/editors/number/number-box-widget-edit.component.d.ts +1 -7
  128. package/widgets/lib/widgets/editors/select/select-box-widget-edit.component.d.ts +1 -0
  129. package/widgets/lib/widgets/editors/toggle/toggle-widget-edit.component.d.ts +0 -2
  130. package/widgets/lib/widgets/filters/operations/operations.component.d.ts +9 -0
  131. package/widgets/lib/widgets/filters/string-filter/index.d.ts +2 -0
  132. package/widgets/lib/widgets/filters/string-filter/string-filter-widget-edit.component.d.ts +11 -0
  133. package/widgets/lib/widgets/filters/string-filter/string-filter-widget.config.d.ts +7 -0
  134. package/widgets/lib/widgets/index.d.ts +5 -1
  135. package/widgets/lib/widgets/property-editors/border/border-widget-editor.component.d.ts +29 -6
  136. package/widgets/lib/widgets/property-editors/flex-options/flex-options-widget-editor.component.d.ts +31 -0
  137. package/widgets/lib/widgets/property-editors/flex-options/flex-options-widget.config.d.ts +7 -0
  138. package/widgets/lib/widgets/property-editors/flex-options/flex-options-widget.type.d.ts +15 -0
  139. package/widgets/lib/widgets/property-editors/flex-options/index.d.ts +3 -0
  140. package/widgets/lib/widgets/property-editors/property-editor-helper.d.ts +72 -0
  141. package/widgets/lib/widgets/property-editors/property-editor.type.d.ts +35 -0
  142. package/widgets/lib/widgets/property-editors/spacing/index.d.ts +0 -1
  143. package/widgets/lib/widgets/property-editors/spacing/spacing-widget-editor.component.d.ts +20 -7
  144. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-B13KvLX4.mjs +0 -108
  145. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-B13KvLX4.mjs.map +0 -1
  146. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-B6MXHPWi.mjs +0 -305
  147. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-B6MXHPWi.mjs.map +0 -1
  148. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-tKCGSRQT.mjs +0 -87
  149. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-tKCGSRQT.mjs.map +0 -1
  150. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-CHvC0IAV.mjs +0 -130
  151. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-CHvC0IAV.mjs.map +0 -1
  152. package/fesm2022/acorex-platform-widgets-checkbox-widget-column.component-05nKV-UV.mjs.map +0 -1
  153. package/fesm2022/acorex-platform-widgets-checkbox-widget-designer.component-juhKoygA.mjs.map +0 -1
  154. package/fesm2022/acorex-platform-widgets-checkbox-widget-view.component-BkWcZ4K9.mjs +0 -72
  155. package/fesm2022/acorex-platform-widgets-checkbox-widget-view.component-BkWcZ4K9.mjs.map +0 -1
  156. package/fesm2022/acorex-platform-widgets-color-box-widget-designer.component-B2g0ct24.mjs.map +0 -1
  157. package/layout/builder/lib/builder/widget-renderer.component.d.ts +0 -48
  158. package/themes/default/lib/layouts/setting-layout/index.d.ts +0 -1
  159. package/themes/shared/lib/components/layout-elements/layout-page-header.component.d.ts +0 -11
  160. package/themes/shared/lib/components/layout-elements/layout-page-side.component.d.ts +0 -5
  161. package/widgets/lib/widgets/property-editors/border/border-widget-type.d.ts +0 -18
  162. package/widgets/lib/widgets/property-editors/spacing/spacing-widget-type.d.ts +0 -10
@@ -0,0 +1,124 @@
1
+ import { AXPFiltersProviderService } from '@acorex/platform/common';
2
+ import { moveItemInArray } from '@angular/cdk/drag-drop';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, signal, computed, effect, Injectable } from '@angular/core';
5
+ import { isEqual, cloneDeep } from 'lodash-es';
6
+
7
+ class AXPFiltersViewModel {
8
+ constructor() {
9
+ this.filterProviderService = inject(AXPFiltersProviderService);
10
+ this.context = signal({}, { equal: isEqual });
11
+ this.availableFilters = signal([]);
12
+ this.activeFilters = signal([]);
13
+ this.newFilters = signal([]);
14
+ this.activeFiltersCount = computed(() => this.activeFilters().length);
15
+ this.#effect = effect(() => {
16
+ console.log(this.context());
17
+ this.filters.update((prev) => ({ ...prev, filters: this.convertContextToQueries(this.context()) }));
18
+ });
19
+ this.#effect1 = effect(() => {
20
+ this.initializeContext();
21
+ console.log(this.filters().filters);
22
+ this.activeFilters.update((prev) => {
23
+ return this.convertFiltersToDefinition(this.filters().filters || []);
24
+ });
25
+ });
26
+ }
27
+ onChoosingFiltersChange(e) {
28
+ if (e.isUserInteraction) {
29
+ this.newFilters.set(e.component.selectedItems);
30
+ }
31
+ }
32
+ onChoosingFiltersConfirm() {
33
+ this.filters.update((prev) => ({
34
+ ...prev,
35
+ filters: [
36
+ ...(prev.filters || []),
37
+ ...this.newFilters().filter((newFilter) => !prev.filters?.some((existing) => existing.field === newFilter.field)),
38
+ ],
39
+ }));
40
+ }
41
+ convertFiltersToDefinition(filters) {
42
+ const availableFiltersMap = new Map(this.availableFilters().map((af) => [af.field, af]));
43
+ return filters
44
+ .map((df) => {
45
+ const af = availableFiltersMap.get(df.field);
46
+ if (!af)
47
+ return null;
48
+ return {
49
+ field: df.field,
50
+ operator: df.operator,
51
+ filters: df.filters,
52
+ logic: df.logic,
53
+ value: df.value,
54
+ title: af.title,
55
+ widget: af.widget,
56
+ isParametric: af.isParametric,
57
+ };
58
+ })
59
+ .filter((filter) => filter !== null);
60
+ }
61
+ setAvailableFilters(availableFilters) {
62
+ this.availableFilters.set(availableFilters);
63
+ }
64
+ setFiltersModel(filters) {
65
+ this.filters = filters;
66
+ }
67
+ drop(event) {
68
+ const cloned = cloneDeep(this.activeFilters());
69
+ moveItemInArray(cloned, event.previousIndex, event.currentIndex);
70
+ this.activeFilters.set(cloned);
71
+ }
72
+ convertContextToQueries(context) {
73
+ const contextKeys = Object.keys(context);
74
+ return contextKeys.map((c) => ({
75
+ field: c,
76
+ value: context[c].value,
77
+ operator: {
78
+ type: context[c].operation,
79
+ },
80
+ }));
81
+ }
82
+ resetFilterFields() {
83
+ this.newFilters.set(this.activeFilters());
84
+ }
85
+ removeCondition(selectedFilter) {
86
+ this.activeFilters.update((prev) => prev.filter((filter) => filter.field !== selectedFilter.field));
87
+ this.context.update((prev) => {
88
+ const newContext = { ...prev };
89
+ delete newContext[selectedFilter.field];
90
+ return newContext;
91
+ });
92
+ }
93
+ #effect;
94
+ #effect1;
95
+ initializeContext() {
96
+ const context = {};
97
+ if (this.filters()?.filters?.length) {
98
+ this.filters().filters?.forEach((f) => {
99
+ context[f.field] = {
100
+ value: f.value,
101
+ operation: f.operator.type,
102
+ };
103
+ });
104
+ }
105
+ this.context.set(context);
106
+ }
107
+ initializeFilters() {
108
+ this.initializeContext();
109
+ this.activeFilters.update((prev) => this.convertFiltersToDefinition(this.filters().filters || []));
110
+ }
111
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPFiltersViewModel, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
112
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPFiltersViewModel, providedIn: 'root' }); }
113
+ }
114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPFiltersViewModel, decorators: [{
115
+ type: Injectable,
116
+ args: [{ providedIn: 'root' }]
117
+ }] });
118
+
119
+ /**
120
+ * Generated bundle index. Do not edit.
121
+ */
122
+
123
+ export { AXPFiltersViewModel };
124
+ //# sourceMappingURL=acorex-platform-layout-filters.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-layout-filters.mjs","sources":["../../../../libs/platform/layout/filters/src/lib/filters.viewmodel.ts","../../../../libs/platform/layout/filters/src/acorex-platform-layout-filters.ts"],"sourcesContent":["import { AXValueChangedEvent } from '@acorex/components/common';\nimport { AXPFilterDefinition, AXPFilterQuery, AXPFiltersProviderService } from '@acorex/platform/common';\nimport { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { computed, effect, inject, Injectable, ModelSignal, signal, WritableSignal } from '@angular/core';\nimport { cloneDeep, isEqual } from 'lodash-es';\n\n@Injectable({ providedIn: 'root' })\nexport class AXPFiltersViewModel {\n private readonly filterProviderService = inject(AXPFiltersProviderService);\n\n context: WritableSignal<{ [key: string]: any }> = signal({}, { equal: isEqual });\n\n readonly availableFilters: WritableSignal<AXPFilterDefinition[]> = signal([]);\n readonly activeFilters: WritableSignal<AXPFilterDefinition[]> = signal([]);\n readonly newFilters: WritableSignal<AXPFilterDefinition[]> = signal([]);\n\n protected filters!: ModelSignal<AXPFilterQuery>;\n\n readonly activeFiltersCount = computed(() => this.activeFilters().length);\n\n onChoosingFiltersChange(e: AXValueChangedEvent<any>) {\n if (e.isUserInteraction) {\n this.newFilters.set(e.component.selectedItems);\n }\n }\n\n onChoosingFiltersConfirm() {\n this.filters.update((prev) => ({\n ...prev,\n filters: [\n ...(prev.filters || []),\n ...this.newFilters().filter(\n (newFilter) => !prev.filters?.some((existing) => existing.field === newFilter.field)\n ),\n ],\n }));\n }\n\n convertFiltersToDefinition(filters: AXPFilterQuery[]): AXPFilterDefinition[] {\n const availableFiltersMap = new Map(this.availableFilters().map((af) => [af.field, af]));\n return filters\n .map((df) => {\n const af = availableFiltersMap.get(df.field);\n if (!af) return null;\n return {\n field: df.field,\n operator: df.operator,\n filters: df.filters,\n logic: df.logic,\n value: df.value,\n title: af.title,\n widget: af.widget,\n isParametric: af.isParametric,\n };\n })\n .filter((filter) => filter !== null) as AXPFilterDefinition[];\n }\n\n setAvailableFilters(availableFilters: AXPFilterDefinition[]) {\n this.availableFilters.set(availableFilters);\n }\n\n setFiltersModel(filters: ModelSignal<AXPFilterQuery>) {\n this.filters = filters;\n }\n\n drop(event: CdkDragDrop<unknown[]>) {\n const cloned = cloneDeep(this.activeFilters());\n moveItemInArray(cloned, event.previousIndex, event.currentIndex);\n this.activeFilters.set(cloned);\n }\n\n convertContextToQueries(context: any): AXPFilterQuery[] {\n const contextKeys = Object.keys(context);\n return contextKeys.map((c) => ({\n field: c,\n value: context[c].value,\n operator: {\n type: context[c].operation,\n },\n }));\n }\n\n resetFilterFields() {\n this.newFilters.set(this.activeFilters());\n }\n\n removeCondition(selectedFilter: AXPFilterDefinition) {\n this.activeFilters.update((prev) => prev.filter((filter) => filter.field !== selectedFilter.field));\n this.context.update((prev) => {\n const newContext = { ...prev };\n delete newContext[selectedFilter.field];\n return newContext;\n });\n }\n\n #effect = effect(() => {\n console.log(this.context());\n this.filters.update((prev) => ({ ...prev, filters: this.convertContextToQueries(this.context()) }));\n });\n\n #effect1 = effect(() => {\n this.initializeContext();\n console.log(this.filters().filters);\n this.activeFilters.update((prev) => {\n return this.convertFiltersToDefinition(this.filters().filters || []);\n });\n });\n\n private initializeContext() {\n const context: any = {};\n\n if (this.filters()?.filters?.length) {\n this.filters().filters?.forEach((f) => {\n context[f.field] = {\n value: f.value,\n operation: f.operator.type,\n };\n });\n }\n this.context.set(context);\n }\n\n initializeFilters(): void {\n this.initializeContext();\n this.activeFilters.update((prev) => this.convertFiltersToDefinition(this.filters().filters || []));\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,72 +1,15 @@
1
1
  import { AXToastService } from '@acorex/components/toast';
2
- import { AXPlatform } from '@acorex/core/platform';
3
- import { AXPSettingDefinitionProviderService, AXPSettingValueProviderService } from '@acorex/platform/common';
2
+ import { AXPSettingScope, AXPSettingDefinitionProviderService, AXPSettingValueProviderService } from '@acorex/platform/common';
4
3
  import { AXHighlightService } from '@acorex/platform/core';
5
4
  import * as i0 from '@angular/core';
6
5
  import { inject, signal, computed, effect, Injectable } from '@angular/core';
7
- import { Router, NavigationEnd } from '@angular/router';
6
+ import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
8
7
  import { filter, take } from 'rxjs';
9
- import { isEmpty, isEqual } from 'lodash-es';
8
+ import { isNil, isEmpty, get, isEqual } from 'lodash-es';
9
+ import { AXPPageStatus } from '@acorex/platform/layout/builder';
10
+ import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
11
+ import { AXDialogService } from '@acorex/components/dialog';
10
12
 
11
- /**
12
- * Converts a list of AXPSettingDefinitionGroup into a tree structure of AXTreeViewSchema.
13
- * This function processes groups and their nested sub-groups, recursively creating a tree.
14
- *
15
- * @param groups - Array of top-level setting groups to be converted into tree view schema.
16
- * @param parentId - The parent ID for nested groups, passed down recursively. (Optional, default is undefined)
17
- *
18
- * @returns An array of AXTreeViewSchema representing the hierarchical structure of groups.
19
- */
20
- function convertToTreeViewSchema(groups, parentId) {
21
- // Helper function to traverse and convert a single group (and its sub-groups)
22
- const traverseGroups = (group, parent) => {
23
- const currentId = group.name;
24
- // Schema for the current group
25
- const schema = {
26
- id: currentId, // Unique identifier for the group (using group name)
27
- parentId: parent, // Parent group ID, passed down recursively
28
- text: group.title, // Display title of the group
29
- //tooltip: group.description, // Optional description as tooltip
30
- hasChild: group.groups.length > 0, // Whether the group has child groups
31
- isExpanded: false, // Default state for expansion (optional)
32
- icon: group.icon,
33
- childrens: group.groups.length > 0 ? [] : undefined, // Child groups array (undefined if no children)
34
- };
35
- // Recursively process nested groups (sub-groups inside the current group)
36
- group.groups.forEach((subGroup) => {
37
- const childSchema = traverseGroups(subGroup, currentId); // Create schema for sub-group
38
- schema.childrens?.push(childSchema); // Add the child schema to the parent group's children
39
- });
40
- return schema; // Return the group schema with its children (if any)
41
- };
42
- // Initialize an array to hold the top-level groups' schemas
43
- const treeViewSchemas = [];
44
- // Process each top-level group and convert it into tree view schema
45
- groups.forEach((group) => {
46
- treeViewSchemas.push(traverseGroups(group, parentId)); // Add the schema for each group
47
- });
48
- // Return the resulting hierarchical structure
49
- return treeViewSchemas;
50
- }
51
- /**
52
- * Recursively searches for a specific `id` in a tree structure and updates its `active` property to `true`.
53
- * Additionally, ensures all other nodes have their `active` property set to `false`.
54
- *
55
- * @param tree - The tree structure to search, represented as an array of AXTreeViewSchema nodes.
56
- * @param targetId - The `id` of the node to activate.
57
- * @returns The updated tree structure with the target node activated and others deactivated.
58
- */
59
- function setActiveByValueField(tree, targetId) {
60
- return tree.map((node) => {
61
- // Set active property for the target node
62
- node.active = node.id === targetId;
63
- // Recursively process children if they exist
64
- if (node.childrens && node.childrens.length > 0) {
65
- node.childrens = setActiveByValueField(node.childrens, targetId);
66
- }
67
- return node;
68
- });
69
- }
70
13
  function searchSettings(groups, search) {
71
14
  const sectionMatchResult = [];
72
15
  const settingMatchResult = [];
@@ -114,6 +57,18 @@ function searchSettings(groups, search) {
114
57
  }
115
58
 
116
59
  class AXPSettingsViewModel {
60
+ resolveScopeKey(name) {
61
+ const scopeMap = {
62
+ environment: AXPSettingScope.Environment,
63
+ global: AXPSettingScope.Global,
64
+ tenant: AXPSettingScope.Tenant,
65
+ user: AXPSettingScope.User,
66
+ };
67
+ return scopeMap[name.toLowerCase()] ?? AXPSettingScope.User;
68
+ }
69
+ resolveScope() {
70
+ return this.resolveScopeKey(this.scopeName());
71
+ }
117
72
  #effect2;
118
73
  /**
119
74
  * @ignore
@@ -122,106 +77,210 @@ class AXPSettingsViewModel {
122
77
  this.router = inject(Router);
123
78
  this.settingDefinitionService = inject(AXPSettingDefinitionProviderService);
124
79
  this.settingValueService = inject(AXPSettingValueProviderService);
125
- this.platform = inject(AXPlatform);
126
80
  this.toastService = inject(AXToastService);
81
+ this.dialogService = inject(AXDialogService);
127
82
  this.highlightService = inject(AXHighlightService);
128
- this.isMobile = signal(this.platform.is('MD'));
129
- this.fullRoute = this.router.url.split('/settings')[0] + '/settings/';
130
- this.search = signal('');
131
- this.searchResult = signal(undefined);
132
- this.activatedGroup = signal(undefined);
83
+ this.layout = inject(AXPLayoutThemeService);
84
+ this.activatedRoute = inject(ActivatedRoute);
85
+ this.searchExpression = signal('');
86
+ this.isValidQuery = (expression) => !isNil(expression) && !isEmpty(expression);
87
+ this.isSearching = computed(() => this.isValidQuery(this.searchExpression()));
88
+ this.searchResult = signal([]);
89
+ this.isSaving = signal(false);
90
+ this.isBusy = signal(false);
91
+ this.activateGroup = signal(undefined);
92
+ this.activeScope = signal('U');
133
93
  this.loadedItems = signal(null);
134
- this.formattedData = signal([]);
94
+ this.scopeName = () => {
95
+ return this.activatedRoute?.snapshot?.paramMap?.get('scope')?.trim().toLowerCase() ?? 'user';
96
+ };
97
+ this.title = computed(() => {
98
+ // fake change detect simulate
99
+ this.activeScope();
100
+ //
101
+ return `settings.${this.scopeName()}.title`;
102
+ });
135
103
  this.groups = computed(() => {
136
- if (this.activatedGroup()) {
137
- return this.settingDefinitionService.findGroup(this.activatedGroup());
104
+ if (this.activateGroup()) {
105
+ return this.settingDefinitionService.findGroup(this.activeScope(), this.activateGroup());
138
106
  }
139
107
  else {
140
108
  return null;
141
109
  }
142
110
  ;
143
111
  });
112
+ this.hasGroup = computed(() => this.activateGroup() != null);
113
+ this.showSide = computed(() => this.layout.isLarge() && this.hasGroup());
144
114
  this.#effect2 = effect(() => {
145
- if (this.search()) {
146
- this.searchResult.set(searchSettings(this.loadedItems(), this.search()));
115
+ if (this.searchExpression()) {
116
+ this.searchResult.set(searchSettings(this.loadedItems(), this.searchExpression()));
147
117
  }
148
- setTimeout(() => {
149
- this.highlightService.highlight('#ax-settings', this.search());
150
- });
151
118
  });
152
119
  this.context = signal({});
153
120
  this.previousContext = signal({});
154
- this.isSaving = signal(false);
155
- this.canCancel = computed(() => isEmpty(this.context()));
156
- this.canSave = computed(() => !this.isSaving() &&
157
- !isEmpty(this.context()) &&
158
- !isEqual(this.context(), this.previousContext()));
159
- this.settingValueService.onChanged.subscribe(async () => {
160
- const currentContext = await this.settingValueService.all();
161
- this.context.update((ctx) => ({ ...ctx, ...currentContext }));
121
+ this.settingValueService.onChanged.pipe(filter(c => c.scope == this.resolveScope())).subscribe((e) => {
122
+ e.keys.forEach(k => {
123
+ const currentValue = e.values[k];
124
+ const contextValue = get(this.context(), k);
125
+ const previousValue = get(this.previousContext(), k);
126
+ // Update only if there are actual changes
127
+ if (!isEqual(previousValue, currentValue) || !isEqual(currentValue, contextValue)) {
128
+ this.previousContext.update(prev => ({
129
+ ...prev,
130
+ [k]: currentValue, // Use backend-provided value
131
+ }));
132
+ this.context.update(ctx => ({
133
+ ...ctx,
134
+ [k]: currentValue,
135
+ }));
136
+ }
137
+ });
162
138
  });
163
- }
164
- async initializeService(activatedRoute) {
165
- // Initial setup
166
- await this.load();
167
- this.activatedRoute = activatedRoute;
139
+ this.load();
168
140
  //
169
- this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
170
- this.updateGroupParam();
141
+ this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(async () => {
142
+ await this.updateGroupParam();
171
143
  });
172
- //
173
- this.updateGroupParam();
174
144
  }
175
- // Fetch settings data
176
145
  async load() {
177
- const items = await this.settingDefinitionService.items();
146
+ //
147
+ this.activeScope.set(this.resolveScope());
148
+ //
149
+ const items = await this.settingDefinitionService.getListAsync(this.activeScope());
178
150
  this.loadedItems.set(items);
179
- const formattedData = convertToTreeViewSchema(this.loadedItems());
180
- this.formattedData.set(formattedData);
181
- const currentContext = await this.settingValueService.all();
182
- const defaults = this.settingDefinitionService.defaultValues();
151
+ const currentContext = await this.settingValueService.scope(this.resolveScope()).all();
152
+ const defaults = await this.settingValueService.scope(this.resolveScope()).defaultValues();
183
153
  this.context.set({ ...defaults, ...currentContext });
184
154
  this.previousContext.set(this.context());
155
+ //
156
+ await this.updateGroupParam();
157
+ if (!this.activateGroup() && this.layout.isLarge() && !this.isSearching()) {
158
+ await this.redirectToFirstGroup();
159
+ }
185
160
  }
186
- // Update group param logic
187
- updateGroupParam() {
188
- // If no child routes exist, set groupParam to null
161
+ async updateGroupParam() {
162
+ const query = this.activatedRoute.snapshot.queryParams["q"];
163
+ const scope = this.resolveScope();
164
+ const group = this.activatedRoute.snapshot.paramMap.get("group");
165
+ if ((this.activeScope() && this.activeScope() != scope) || (this.activateGroup() != group)) {
166
+ this.activateGroup.set(undefined);
167
+ await this.load();
168
+ return;
169
+ }
170
+ if (this.isValidQuery(query)) {
171
+ this.searchExpression.set(query);
172
+ }
173
+ if (this.isSearching()) {
174
+ setTimeout(() => {
175
+ this.highlightService.highlight('#ax-settings', this.searchExpression());
176
+ }, 100);
177
+ }
178
+ else {
179
+ this.highlightService.clear();
180
+ }
181
+ // If no child routes exist, set activateGroup to undefined
189
182
  if (this.activatedRoute.children.length === 0) {
190
- this.activatedGroup.set(undefined);
183
+ this.activateGroup.set(undefined);
191
184
  return;
192
185
  }
193
186
  // Traverse child routes to check for the group parameter
194
- this.activatedRoute.children.forEach((childRoute) => {
195
- childRoute.paramMap.pipe(take(1)).subscribe(async (params) => {
196
- const group = params.get('group');
197
- this.activatedGroup.update(() => group || undefined);
198
- if (group) {
199
- this.formattedData.set(setActiveByValueField(this.formattedData(), group));
200
- }
201
- });
202
- });
187
+ for (const childRoute of this.activatedRoute.children) {
188
+ const params = await childRoute.paramMap.pipe(take(1)).toPromise();
189
+ const group = params?.get('group');
190
+ if (group) {
191
+ this.activateGroup.set(group);
192
+ }
193
+ }
194
+ }
195
+ async redirectToFirstGroup() {
196
+ const firstGroup = this.determineFirstGroup();
197
+ if (firstGroup) {
198
+ const app = this.activatedRoute.snapshot.params['app'];
199
+ const scope = this.activatedRoute.snapshot.params['scope'];
200
+ await this.router.navigate([app, 'settings', scope, firstGroup], { replaceUrl: true });
201
+ }
202
+ }
203
+ async navigateUpLevel() {
204
+ const func = async () => {
205
+ const app = this.activatedRoute.snapshot.params['app'];
206
+ const scope = this.activatedRoute.snapshot.params['scope'];
207
+ await this.router.navigate([app, 'settings', scope]);
208
+ };
209
+ if (this.isDirty()) {
210
+ const dialogResult = await this.dialogService.confirm('Unsaved Changes', 'You have unsaved changes. Are you sure you want to go back without saving?', 'warning');
211
+ if (dialogResult.result) {
212
+ await func();
213
+ }
214
+ }
215
+ else {
216
+ await func();
217
+ }
218
+ }
219
+ determineFirstGroup() {
220
+ const groups = this.loadedItems();
221
+ return groups && groups.length > 0 ? groups[0].name : null;
203
222
  }
204
223
  handleSelectGroup(item) {
205
- const value = item.data?.['id'];
206
- this.router.navigate([`${value}`], { relativeTo: this.activatedRoute });
207
- this.search.set('');
224
+ this.router.navigate([`${item.name}`], { relativeTo: this.activatedRoute });
225
+ this.searchExpression.set('');
208
226
  }
209
- handleContextChanged(e) {
210
- if (e.init) {
227
+ async handleContextChanged(e) {
228
+ if (e.state == 'initiated') {
211
229
  this.previousContext.set(e.data);
212
230
  }
213
231
  else {
214
232
  this.context.set(e.data);
215
233
  }
216
234
  }
235
+ isDirty(section) {
236
+ if (section) {
237
+ // Check for changes in the specific section
238
+ return section.settings.some(c => !isEqual(get(this.context(), c.name), get(this.previousContext(), c.name)));
239
+ }
240
+ else {
241
+ // Check for changes globally based on loadedItems keys
242
+ return this.loadedItems()?.some(group => group.sections.some(sec => sec.settings.some(setting => {
243
+ const currentValue = get(this.context(), setting.name);
244
+ const previousValue = get(this.previousContext(), setting.name);
245
+ return !isEqual(currentValue, previousValue);
246
+ }))) || false;
247
+ }
248
+ }
217
249
  // Save settings logic
218
- async apply() {
250
+ async apply(section) {
219
251
  try {
220
- // Update the previous context and set the saving state
221
- this.previousContext.set(this.context());
222
252
  this.isSaving.set(true);
223
- // Save the settings
224
- await this.settingValueService.set(this.context());
253
+ this.builder.setStatus(AXPPageStatus.Submitting);
254
+ const formResult = await this.form.validate();
255
+ if (!formResult.result) {
256
+ this.toastService.show({
257
+ color: 'danger',
258
+ title: 'Review Needed',
259
+ content: 'Invalid configuration detected. Please review your inputs.',
260
+ location: 'bottom-center',
261
+ closeButton: true,
262
+ timeOut: 3000,
263
+ timeOutProgress: true,
264
+ });
265
+ this.isSaving.set(false);
266
+ this.builder.setStatus(AXPPageStatus.Error);
267
+ return;
268
+ }
269
+ if (section) {
270
+ // Apply changes for the specific section
271
+ const changes = {};
272
+ section.settings.forEach(c => {
273
+ changes[c.name] = get(this.context(), c.name);
274
+ });
275
+ if (!isEmpty(changes)) {
276
+ await this.settingValueService.scope(this.resolveScope()).set(changes);
277
+ }
278
+ }
279
+ else {
280
+ // Save the settings
281
+ await this.settingValueService.scope(this.resolveScope()).set(this.context());
282
+ }
283
+ this.builder.setStatus(AXPPageStatus.Submitted);
225
284
  // Show success notification
226
285
  this.toastService.show({
227
286
  color: 'success',
@@ -235,6 +294,7 @@ class AXPSettingsViewModel {
235
294
  }
236
295
  catch (error) {
237
296
  // Handle and show errors
297
+ this.builder.setStatus(AXPPageStatus.Error);
238
298
  console.error('Error saving settings:', error);
239
299
  this.toastService.show({
240
300
  color: 'danger',
@@ -247,25 +307,52 @@ class AXPSettingsViewModel {
247
307
  });
248
308
  }
249
309
  finally {
250
- // Reset the saving state
251
310
  this.isSaving.set(false);
252
311
  }
253
312
  }
254
- // Cancel settings logic
255
- reset() {
256
- this.context.set(this.previousContext());
313
+ // discard settings logic
314
+ async discard(section) {
315
+ this.form.resetErrors();
316
+ if (section) {
317
+ // Discard changes for the specific section
318
+ section.settings.forEach(c => {
319
+ const previousValue = get(this.previousContext(), c.name);
320
+ this.context.update(ctx => ({
321
+ ...ctx,
322
+ [c.name]: previousValue
323
+ }));
324
+ });
325
+ }
326
+ else {
327
+ // Discard changes for all sections
328
+ this.context.set(this.previousContext());
329
+ }
257
330
  }
258
331
  // Cancel settings logic
259
- resetToDefault() {
260
- const defaults = this.settingDefinitionService.defaultValues();
332
+ async resetToDefault() {
333
+ const defaults = await this.settingValueService.scope(this.resolveScope()).defaultValues();
334
+ // Update the context with the defaults
261
335
  this.context.set(defaults);
336
+ //
337
+ await this.apply();
338
+ }
339
+ async search(expression) {
340
+ this.searchExpression.set(expression);
341
+ const app = this.activatedRoute.snapshot.params['app'];
342
+ const scope = this.activatedRoute.snapshot.params['scope'];
343
+ //
344
+ if (this.isValidQuery(expression)) {
345
+ await this.router.navigate([app, 'settings', scope, this.activateGroup() ?? ''], { queryParams: { q: expression } });
346
+ }
347
+ else {
348
+ await this.router.navigate([app, 'settings', scope, this.activateGroup() ?? '']);
349
+ }
262
350
  }
263
351
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPSettingsViewModel, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
264
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPSettingsViewModel, providedIn: 'root' }); }
352
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPSettingsViewModel }); }
265
353
  }
266
354
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPSettingsViewModel, decorators: [{
267
- type: Injectable,
268
- args: [{ providedIn: 'root' }]
355
+ type: Injectable
269
356
  }], ctorParameters: () => [] });
270
357
 
271
358
  /**