@one-paragon/angular-utilities 2.8.3 → 2.8.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 (203) hide show
  1. package/karma.conf.js +43 -0
  2. package/ng-package.json +7 -0
  3. package/package.json +15 -27
  4. package/src/action-state/action-state-spinner/action-state-spinner.component.css +16 -0
  5. package/src/action-state/action-state-spinner/action-state-spinner.component.html +7 -0
  6. package/src/action-state/action-state-spinner/action-state-spinner.component.spec.ts +25 -0
  7. package/src/action-state/action-state-spinner/action-state-spinner.component.ts +26 -0
  8. package/src/action-state/action-state-ui/action-state-ui.module.ts +13 -0
  9. package/src/action-state/index.ts +8 -0
  10. package/src/action-state/ngrx-ext/ngrx-ext.module.ts +14 -0
  11. package/src/action-state/ngrx.ts +69 -0
  12. package/src/http-request-state/RequestStateFactory.ts +56 -0
  13. package/src/http-request-state/RequestStateStore.ts +360 -0
  14. package/src/http-request-state/deprecated.ts +20 -0
  15. package/src/http-request-state/directives/HttpStateDirectiveBase.ts +29 -0
  16. package/src/http-request-state/directives/http-error-state-directive.ts +21 -0
  17. package/src/http-request-state/directives/http-inProgress-state-directive.ts +19 -0
  18. package/src/http-request-state/directives/http-notStarted-state-directive.ts +19 -0
  19. package/src/http-request-state/directives/http-success-state-directive.ts +29 -0
  20. package/src/http-request-state/directives/index.ts +5 -0
  21. package/src/http-request-state/directives/request-state-directive.spec.ts +73 -0
  22. package/src/http-request-state/directives/request-state-directive.ts +78 -0
  23. package/src/http-request-state/documentation/CREATE-REQUESTOR.md +667 -0
  24. package/src/http-request-state/documentation/README.md +191 -0
  25. package/src/http-request-state/documentation/REQUEST-STATE-STORE-CONFIG.md +648 -0
  26. package/src/http-request-state/documentation/REQUESTOR.md +616 -0
  27. package/src/http-request-state/helpers.ts +30 -0
  28. package/src/http-request-state/http-state-module.ts +23 -0
  29. package/src/http-request-state/index.ts +7 -0
  30. package/src/http-request-state/models/view-context.ts +18 -0
  31. package/src/http-request-state/observable.spec.ts +43 -0
  32. package/src/http-request-state/request-state.ts +66 -0
  33. package/src/http-request-state/rxjs/getRequestorBody.ts +10 -0
  34. package/src/http-request-state/rxjs/getRequestorState.ts +8 -0
  35. package/src/http-request-state/rxjs/index.ts +4 -0
  36. package/src/http-request-state/rxjs/tapError.ts +16 -0
  37. package/src/http-request-state/rxjs/tapSuccess.ts +16 -0
  38. package/src/http-request-state/strategies.spec.ts +42 -0
  39. package/src/http-request-state/types.ts +54 -0
  40. package/src/ngrx/actionable-selector.ts +189 -0
  41. package/src/ngrx/index.ts +1 -0
  42. package/src/public-api.ts +40 -0
  43. package/src/rxjs/defaultShareReplay.ts +8 -0
  44. package/src/rxjs/index.ts +5 -0
  45. package/src/rxjs/mapError.ts +8 -0
  46. package/src/rxjs/rxjs-operators.ts +130 -0
  47. package/src/rxjs/subjectifier.ts +17 -0
  48. package/src/rxjs/subscriber.directive.ts +57 -0
  49. package/src/specs/clickSubject.spec.ts +99 -0
  50. package/src/specs/dialog.spec.ts +101 -0
  51. package/src/specs/toggleGroupDirective.spec.ts +229 -0
  52. package/src/table-builder/classes/DefaultSettings.ts +11 -0
  53. package/src/table-builder/classes/MatTableObservableDataSource.ts +23 -0
  54. package/src/table-builder/classes/TableBuilderConfig.ts +49 -0
  55. package/src/table-builder/classes/TableBuilderDataSource.ts +64 -0
  56. package/src/table-builder/classes/TableState.ts +96 -0
  57. package/src/table-builder/classes/data-store.ts +10 -0
  58. package/src/table-builder/classes/display-col.ts +5 -0
  59. package/src/table-builder/classes/filter-info.ts +129 -0
  60. package/src/table-builder/classes/table-builder-general-settings.ts +233 -0
  61. package/src/table-builder/classes/table-builder.ts +105 -0
  62. package/src/table-builder/classes/table-store.helpers.ts +109 -0
  63. package/src/table-builder/classes/table-store.ts +540 -0
  64. package/src/table-builder/components/array-column.component.ts +34 -0
  65. package/src/table-builder/components/column-builder/column-builder.component.html +109 -0
  66. package/src/table-builder/components/column-builder/column-builder.component.scss +43 -0
  67. package/src/table-builder/components/column-builder/column-builder.component.spec.ts +49 -0
  68. package/src/table-builder/components/column-builder/column-builder.component.ts +130 -0
  69. package/src/table-builder/components/column-builder/column-helpers.ts +54 -0
  70. package/src/table-builder/components/column-header-menu/column-header-menu.component.html +128 -0
  71. package/src/table-builder/components/column-header-menu/column-header-menu.component.scss +97 -0
  72. package/src/table-builder/components/column-header-menu/column-header-menu.component.ts +113 -0
  73. package/src/table-builder/components/date-filter/date-filter.component.html +39 -0
  74. package/src/table-builder/components/date-filter/date-filter.component.ts +33 -0
  75. package/src/table-builder/components/date-time-filter/date-time-filter.component.html +25 -0
  76. package/src/table-builder/components/date-time-filter/date-time-filter.component.ts +33 -0
  77. package/src/table-builder/components/filter/filter.component.html +120 -0
  78. package/src/table-builder/components/filter/filter.component.scss +60 -0
  79. package/src/table-builder/components/filter/filter.component.spec.ts +86 -0
  80. package/src/table-builder/components/filter/filter.component.ts +73 -0
  81. package/src/table-builder/components/filter/in-list/in-list-filter.component.ts +171 -0
  82. package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.html +60 -0
  83. package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.scss +57 -0
  84. package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.ts +44 -0
  85. package/src/table-builder/components/generic-table/generic-table.component.html +140 -0
  86. package/src/table-builder/components/generic-table/generic-table.component.scss +45 -0
  87. package/src/table-builder/components/generic-table/generic-table.component.ts +531 -0
  88. package/src/table-builder/components/generic-table/paginator.component.ts +125 -0
  89. package/src/table-builder/components/group-by-list/group-by-list.component.css +24 -0
  90. package/src/table-builder/components/group-by-list/group-by-list.component.html +21 -0
  91. package/src/table-builder/components/group-by-list/group-by-list.component.spec.ts +23 -0
  92. package/src/table-builder/components/group-by-list/group-by-list.component.ts +26 -0
  93. package/src/table-builder/components/in-filter/in-filter.component.css +22 -0
  94. package/src/table-builder/components/in-filter/in-filter.component.html +38 -0
  95. package/src/table-builder/components/in-filter/in-filter.component.ts +66 -0
  96. package/src/table-builder/components/index.ts +9 -0
  97. package/src/table-builder/components/initialization-component/initialization.component.html +78 -0
  98. package/src/table-builder/components/initialization-component/initialization.component.ts +28 -0
  99. package/src/table-builder/components/link-column.component.ts +42 -0
  100. package/src/table-builder/components/number-filter/number-filter.component.css +10 -0
  101. package/src/table-builder/components/number-filter/number-filter.component.html +32 -0
  102. package/src/table-builder/components/number-filter/number-filter.component.spec.ts +30 -0
  103. package/src/table-builder/components/number-filter/number-filter.component.ts +34 -0
  104. package/src/table-builder/components/profiles-menu/profiles-menu.component.html +77 -0
  105. package/src/table-builder/components/profiles-menu/profiles-menu.component.scss +126 -0
  106. package/src/table-builder/components/profiles-menu/profiles-menu.component.spec.ts +23 -0
  107. package/src/table-builder/components/profiles-menu/profiles-menu.component.ts +64 -0
  108. package/src/table-builder/components/reset-menu/reset-menu.component.css +3 -0
  109. package/src/table-builder/components/reset-menu/reset-menu.component.html +10 -0
  110. package/src/table-builder/components/reset-menu/reset-menu.component.ts +87 -0
  111. package/src/table-builder/components/scroll-strategy.ts +139 -0
  112. package/src/table-builder/components/sort-menu/sort-menu.component-store.ts +57 -0
  113. package/src/table-builder/components/sort-menu/sort-menu.component.html +115 -0
  114. package/src/table-builder/components/sort-menu/sort-menu.component.scss +119 -0
  115. package/src/table-builder/components/sort-menu/sort-menu.component.ts +88 -0
  116. package/src/table-builder/components/table-container/table-container.component.html +94 -0
  117. package/src/table-builder/components/table-container/table-container.component.scss +60 -0
  118. package/src/table-builder/components/table-container/table-container.component.ts +467 -0
  119. package/src/table-builder/components/table-container/table-container.helpers/data-state.helpers.ts +113 -0
  120. package/src/table-builder/components/table-container/table-container.helpers/filter-state.helpers.ts +125 -0
  121. package/src/table-builder/components/table-container/table-container.helpers/groupBy.helpers.ts +172 -0
  122. package/src/table-builder/components/table-container/table-container.helpers/meta-data.helpers.ts +19 -0
  123. package/src/table-builder/components/table-container/table-container.helpers/sort-state.helpers.ts +47 -0
  124. package/src/table-builder/components/table-container/tableProps.ts +21 -0
  125. package/src/table-builder/components/table-container/virtual-scroll-container.ts +216 -0
  126. package/src/table-builder/components/table-container-filter/filter-list/filter-list.component.html +42 -0
  127. package/src/table-builder/components/table-container-filter/filter-list/filter-list.component.ts +47 -0
  128. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.css +40 -0
  129. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.html +11 -0
  130. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.spec.ts +85 -0
  131. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.ts +35 -0
  132. package/src/table-builder/components/table-container-filter/table-wrapper-filter-store.ts +13 -0
  133. package/src/table-builder/components/table-header-menu/table-header-menu.component.css +21 -0
  134. package/src/table-builder/components/table-header-menu/table-header-menu.component.html +48 -0
  135. package/src/table-builder/components/table-header-menu/table-header-menu.component.ts +36 -0
  136. package/src/table-builder/directives/custom-cell-directive.ts +63 -0
  137. package/src/table-builder/directives/custom-header-directive.ts +16 -0
  138. package/src/table-builder/directives/group-row-directive.ts +91 -0
  139. package/src/table-builder/directives/index.ts +8 -0
  140. package/src/table-builder/directives/multi-sort.directive.spec.ts +124 -0
  141. package/src/table-builder/directives/multi-sort.directive.ts +58 -0
  142. package/src/table-builder/directives/resize-column.directive.ts +107 -0
  143. package/src/table-builder/directives/table-wrapper.directive.ts +13 -0
  144. package/src/table-builder/directives/tb-filter.directive.ts +376 -0
  145. package/src/table-builder/documentation/table-builder/CUSTOM-CELL.md +568 -0
  146. package/src/table-builder/documentation/table-builder/CUSTOM-GROUP-ROW.md +356 -0
  147. package/src/table-builder/documentation/table-builder/METADATA-DOCUMENTATION.md +517 -0
  148. package/src/table-builder/documentation/table-builder/STYLER-STYLE.md +228 -0
  149. package/src/table-builder/documentation/table-builder/TABLE-BUILDER-CONFIG.md +325 -0
  150. package/src/table-builder/documentation/table-builder/TABLE-BUILDER-SETTINGS.md +515 -0
  151. package/src/table-builder/documentation/table-builder/TABLE-BUILDER.md +430 -0
  152. package/src/table-builder/documentation/table-builder/TABLE-CONTAINER.md +628 -0
  153. package/src/table-builder/enums/filterTypes.ts +39 -0
  154. package/src/table-builder/functions/boolean-filter-function.ts +12 -0
  155. package/src/table-builder/functions/date-filter-function.ts +85 -0
  156. package/src/table-builder/functions/download-data.ts +11 -0
  157. package/src/table-builder/functions/null-filter-function.ts +9 -0
  158. package/src/table-builder/functions/number-filter-function.ts +47 -0
  159. package/src/table-builder/functions/sort-data-function.ts +80 -0
  160. package/src/table-builder/functions/string-filter-function.ts +59 -0
  161. package/src/table-builder/interfaces/ColumnInfo.ts +9 -0
  162. package/src/table-builder/interfaces/dictionary.ts +3 -0
  163. package/src/table-builder/interfaces/meta-data.ts +279 -0
  164. package/src/table-builder/ngrx/tableBuilderStateStore.ts +203 -0
  165. package/src/table-builder/pipes/column-total.pipe.ts +16 -0
  166. package/src/table-builder/pipes/format-filter-type.pipe.ts +12 -0
  167. package/src/table-builder/pipes/format-filter-value.pipe.ts +71 -0
  168. package/src/table-builder/pipes/key-display.ts +13 -0
  169. package/src/table-builder/services/all-values-filter-creator.service.ts +92 -0
  170. package/src/table-builder/services/export-to-csv.service.ts +117 -0
  171. package/src/table-builder/services/link-creator.service.ts +98 -0
  172. package/src/table-builder/services/table-template-service.ts +47 -0
  173. package/src/table-builder/services/transform-creator.ts +90 -0
  174. package/src/table-builder/specs/table-custom-filters.spec.ts +262 -0
  175. package/src/table-builder/styles/collapser.styles.scss +16 -0
  176. package/src/table-builder/table-builder.module.ts +42 -0
  177. package/src/table-builder/types/group-types.ts +42 -0
  178. package/src/table-builder/types/index.ts +1 -0
  179. package/src/test.ts +17 -0
  180. package/src/utilities/array-helpers.ts +13 -0
  181. package/src/utilities/directives/auto-focus.directive.ts +20 -0
  182. package/src/utilities/directives/clickEmitterDirective.ts +15 -0
  183. package/src/utilities/directives/clickSubject.ts +19 -0
  184. package/src/utilities/directives/conditional-classes.directive.ts +36 -0
  185. package/src/utilities/directives/dialog-service.ts +19 -0
  186. package/src/utilities/directives/dialog.ts +174 -0
  187. package/src/utilities/directives/mat-toggle-group-directive.ts +60 -0
  188. package/src/utilities/directives/prevent-enter.directive.ts +12 -0
  189. package/src/utilities/directives/stop-propagation.directive.ts +19 -0
  190. package/src/utilities/directives/styler.ts +45 -0
  191. package/src/utilities/directives/trim-whitespace.directive.ts +20 -0
  192. package/src/utilities/index.ts +22 -0
  193. package/src/utilities/module.ts +53 -0
  194. package/src/utilities/pipes/function.pipe.ts +21 -0
  195. package/src/utilities/pipes/phone.pipe.ts +20 -0
  196. package/src/utilities/pipes/space-case.pipes.spec.ts +47 -0
  197. package/src/utilities/pipes/space-case.pipes.ts +29 -0
  198. package/tsconfig.lib.json +20 -0
  199. package/tsconfig.lib.prod.json +10 -0
  200. package/tsconfig.spec.json +17 -0
  201. package/fesm2022/one-paragon-angular-utilities.mjs +0 -7328
  202. package/fesm2022/one-paragon-angular-utilities.mjs.map +0 -1
  203. package/types/one-paragon-angular-utilities.d.ts +0 -2197
@@ -0,0 +1,540 @@
1
+ import { FieldType, MetaData } from '../interfaces/meta-data';
2
+ import { Observable } from 'rxjs';
3
+ import { defaultTableState, InitializationState, PersistedTableState, TableState } from './TableState';
4
+ import { Injectable, Signal, computed, inject } from '@angular/core';
5
+ import { TableBuilderConfigToken } from './TableBuilderConfig';
6
+ import { CustomFilter, FilterInfo, isCustomFilter, isFilterInfo } from './filter-info';
7
+ import { Sort, SortDirection } from '@angular/material/sort' ;
8
+ import { ComponentStore } from '@ngrx/component-store' ;
9
+ import { Dictionary } from '../interfaces/dictionary';
10
+ import { distinctUntilChanged, tap } from 'rxjs/operators'
11
+ import { moveItemInArray } from '@angular/cdk/drag-drop';
12
+ import { NonFunctionProperties, NotPersistedTableSettings, parseTbSizeToPixels, PersistedTableSettings, TableBuilderSettings } from './table-builder-general-settings';
13
+ import { replaceInArrayWithClone } from '../../utilities/array-helpers';
14
+ import { sortsAreSame } from '../directives';
15
+ import { toObservable } from '@angular/core/rxjs-interop';
16
+ import { TableProps } from '../components/table-container/tableProps';
17
+ import { cleanPersistedState, createPreSort, initializeOrder, mapSaveableState, mergeMeta, orderedStateVisibleMetaData, orderMetaData } from './table-store.helpers';
18
+ import { TableBuilderSort } from '../components/table-container/table-container.helpers/sort-state.helpers';
19
+ import { merge } from 'lodash';
20
+ import { GroupedData } from '../types/group-types';
21
+
22
+ @Injectable()
23
+ export class TableStore extends ComponentStore<TableState> {
24
+ constructor() {
25
+ const config = inject(TableBuilderConfigToken);
26
+ const settingsFromConfig: Pick<TableState, 'notPersistedTableSettings' | 'persistedTableSettings'> =
27
+ {
28
+ persistedTableSettings: new PersistedTableSettings().merge(config.defaultTableSettings),
29
+ notPersistedTableSettings: new NotPersistedTableSettings().merge(config.defaultTableSettings),
30
+ };
31
+ if(config.defaultTableSettings?.pageSize){
32
+ settingsFromConfig.notPersistedTableSettings.paginatorSettings!.pageSize = config.defaultTableSettings?.pageSize;
33
+ }
34
+ const pageSize = settingsFromConfig.notPersistedTableSettings.paginatorSettings!.pageSize || defaultTableState.pageSize;
35
+ const showAll = settingsFromConfig.notPersistedTableSettings.paginatorSettings!.defaultAll || defaultTableState.showAll;
36
+ super( { ...defaultTableState, ...settingsFromConfig, pageSize, showAll });
37
+ }
38
+
39
+ $initializationState = this.selectSignal(state => state.initializationState);
40
+ $savableState = computed(() => {
41
+ const state = this.state();
42
+ return mapSaveableState(state);
43
+ });
44
+
45
+ //#region meta order and hidden
46
+ readonly showColumn = this.updater((state, key: string) => ({
47
+ ...state,
48
+ hiddenKeys: state.hiddenKeys.filter( k => k !== key),
49
+ }));
50
+ readonly hideColumn = this.updater((state, key: string) => ({
51
+ ...state,
52
+ hiddenKeys: [...state.hiddenKeys.filter( k => k !== key), key],
53
+ }));
54
+ readonly setHiddenColumns = this.updater((state, displayCols: {key: string, visible: boolean}[]) => {
55
+ return ({ ...state, hiddenKeys: displayCols.filter(d => !d.visible).map(d => d.key) })
56
+ });
57
+ readonly setUserDefinedOrder = this.updater((state, moved: { newOrder: number, oldOrder: number }) => {
58
+ const { newOrder, oldOrder } = moved;
59
+ const mdsArr = orderedStateVisibleMetaData(state);
60
+ moveItemInArray(mdsArr, oldOrder, newOrder);
61
+
62
+ const userDefinedOrder = mdsArr.reduce((aggregate: any, current, index) => {
63
+ aggregate[current.key] = index;
64
+ return aggregate
65
+ }, {});
66
+ return ({ ...state, userDefined: { ...state.userDefined, order: userDefinedOrder } })
67
+ })
68
+ $userDefinedOrder = this.selectSignal( state => state.userDefined.order);
69
+ metaData$ = this.select( state => state.metaData);
70
+ $metaData = this.selectSignal( state => state.metaData);
71
+ $metaDataArray = this.selectSignal(
72
+ this.$metaData,
73
+ this.$userDefinedOrder,
74
+ orderMetaData
75
+ );
76
+ $orderedCodeVisibleMetaDatas = this.selectSignal(
77
+ this.$metaDataArray, (mds) => mds.filter(m => m.fieldType !== FieldType.Hidden),
78
+ { equal: (a: MetaData[], b) => b.length === a.length && b.every((s, i) => a[i].key === s.key) }
79
+ )
80
+ $getMetaData = (key: string) => computed(() => {
81
+ const metaData = this.state().metaData[key];
82
+ if(!metaData)console.warn(`Meta data with key ${key} not found`);
83
+ return metaData;
84
+ });
85
+ $hiddenKeys = this.selectSignal( state => state.hiddenKeys);
86
+ $orderedVisibleColumns = this.selectSignal(this.$orderedCodeVisibleMetaDatas, this.$hiddenKeys,
87
+ (cs, hiddenKeys) => cs.filter(m => !hiddenKeys.includes(m.key)).map(m => m.key));
88
+ //#endregion meta order and hidden
89
+
90
+ //#region widths
91
+ readonly setUserDefinedWidth = this.updater((state, colWidths:{key: string, widthInPixel:number}[]) => {
92
+ const userDefinedWidths = { ...state.userDefined.widths };
93
+ colWidths.forEach(cw => {
94
+ userDefinedWidths[cw.key] = cw.widthInPixel;
95
+ });
96
+ return { ...state, userDefined: { ...state.userDefined, widths: userDefinedWidths } };
97
+ });
98
+ readonly setTableWidth = this.updater((state, widthInPixels:number) =>
99
+ ({ ...state, userDefined: { ...state.userDefined, table: { width: widthInPixels } } }));
100
+ $getUserDefinedWidths = this.selectSignal(state => state.userDefined.widths);
101
+ $tableSettingsMinWidth = this.selectSignal(state => parseTbSizeToPixels(state.notPersistedTableSettings.minColumnWidth));
102
+ $getUserDefinedWidth = (key:string) => this.selectSignal(this.$getUserDefinedWidths, widths => widths[key]);
103
+ $getUserDefinedTableWidth = this.selectSignal(state => state.userDefined.table.width);
104
+ getUserDefinedTableWidth$ = this.select(state => state.userDefined.table.width);
105
+ //#endregion widths
106
+
107
+ //#region filter
108
+ readonly addFilter = this.updater( (state, filter: FilterInfo | CustomFilter ) => {
109
+ return this.addFiltersToState(state, [filter]);
110
+ });
111
+
112
+ readonly addFilters = this.updater((state, filters:(FilterInfo | CustomFilter )[]) => {
113
+ return this.addFiltersToState(state, filters);
114
+ });
115
+ readonly removeFilter = this.updater( (state, filterId: string) => {
116
+ const filtersCopy = { ...state.filters };
117
+ delete filtersCopy[filterId];
118
+ return ({ ...state, filters: filtersCopy });
119
+ });
120
+
121
+ readonly removeFilters = this.updater( (state, filterIds: string[]) => {
122
+ const filtersCopy = { ...state.filters };
123
+ filterIds.forEach(id => { delete filtersCopy[id] })
124
+ return ({ ...state, filters: filtersCopy });
125
+ });
126
+ readonly clearFilters = this.updater((state) =>
127
+ ({ ...state, filters: {} }));
128
+ private addFiltersToState = (state:TableState, filters:(FilterInfo | CustomFilter)[]) : TableState => {
129
+
130
+ var customFilters = filters.filter(isCustomFilter);
131
+
132
+ var filterInfos = filters.filter(isFilterInfo);
133
+
134
+ const filtersObj = filterInfos
135
+ .filter(fltr => Object.keys(state.metaData).some(key => key === fltr.key) || console.warn(`Meta data with key ${fltr.key} not found`))
136
+ .reduce((filtersObj: {[k: string]: any}, filter) => {
137
+ if(!filter.filterId) {
138
+ filter.filterId = crypto.randomUUID();
139
+ }
140
+ const metaData = state.metaData[filter.key];
141
+ filter.filterBy = metaData.filterLogic?.filterBy === 'use map' ? metaData.map : metaData.filterLogic?.filterBy
142
+ filtersObj[filter.filterId] = filter;
143
+ return filtersObj;
144
+ }, {});
145
+
146
+ customFilters.forEach( fltr => {
147
+ if(!fltr.filterId) {
148
+ fltr.filterId = crypto.randomUUID();
149
+ }
150
+ filtersObj[fltr.filterId] = fltr;
151
+ })
152
+ return {
153
+ ...state,
154
+ filters: { ...state.filters, ...filtersObj }
155
+ };
156
+ }
157
+ $filters = this.selectSignal(state => state.filters);
158
+ $filtersArray = computed(() => Object.values(this.state().filters) || []);
159
+ filters$ = this.select(state => state.filters );
160
+ $getFilter = (filterId: string) : Signal<FilterInfo | CustomFilter | undefined> => {
161
+ return this.selectSignal(this.$filters, filters => filters[filterId] );
162
+ }
163
+ //#endregion filter
164
+
165
+ //#region sort
166
+ readonly setSort = this.updater<{key: string, direction?: SortDirection}>((state, { key, direction } ) => {
167
+ const sortArray = state.sorted.filter( s => s.active !== key );
168
+ if(direction) {
169
+ sortArray.unshift({ active: key, direction });
170
+ }
171
+ return {
172
+ ...state,
173
+ sorted: sortArray,
174
+ };
175
+ });
176
+ readonly setAllSort = this.updater((state, sortArray:Sort[]) => {
177
+ return {
178
+ ...state,
179
+ sorted: sortArray,
180
+ };
181
+ });
182
+ $preSort = computed(() => createPreSort(this.$metaData()));
183
+ _$selectSorted = this.selectSignal(state => state.sorted, {
184
+ equal: sortsAreSame
185
+ });
186
+ $selectSorted = computed<TableBuilderSort[]>(() => {
187
+ const metaDict = this.$metaData();
188
+ return this._$selectSorted().map(s => {
189
+ const meta = metaDict[s.active];
190
+ const sortLogic = meta.sortLogic;
191
+ const sortBy = sortLogic?.sortBy === 'use map' ? meta.map : sortLogic?.sortBy;
192
+ return ({ ...s, ...sortLogic, sortBy })
193
+ })
194
+ })
195
+ selectSorted$ = this.select(state => state.sorted).pipe(distinctUntilChanged(sortsAreSame));
196
+ $getSorts = this.selectSignal(() => this.$initializationState() !== InitializationState.Ready ? [] : this.$selectSorted());
197
+ sort$ = toObservable(this.$getSorts);
198
+ //#endregion sort
199
+
200
+ //#region groupBy
201
+ readonly addGroupByKey = this.updater((state, metaDataKey: string) => ({
202
+ ...state,
203
+ groupBy: [...state.groupBy, { key: metaDataKey, expandedHeaders: [], sort: '' }]
204
+ }));
205
+
206
+ readonly removeGroupByKey = this.updater((state, groupByKey: string) => {
207
+ const groupBy = state.groupBy.filter(key => groupByKey !== key.key);
208
+ return ({
209
+ ...state,
210
+ groupBy,
211
+ userDefined: { ...state.userDefined, noGroups: groupBy.length === 0 }
212
+ })});
213
+
214
+ readonly updateExpandedGroups = this.updater((state, data: { key: string, groupUniqueName: string, isExpanded: boolean }) => {
215
+ const gbk = replaceInArrayWithClone(state.groupBy, k => k.key === data.key, gk => {
216
+ if(data.isExpanded) {
217
+ if(gk.expandedHeaders === 'all' || gk.expandedHeaders.includes(data.groupUniqueName)) return;
218
+ gk.expandedHeaders = [...gk.expandedHeaders, data.groupUniqueName];
219
+ } else {
220
+ //we need to make sure it will not = all at this point. See generic table setExpanded
221
+ if(gk.expandedHeaders !== 'all') {
222
+ gk.expandedHeaders = gk.expandedHeaders.filter(g => g !== data.groupUniqueName);
223
+ }
224
+ }
225
+ });
226
+ return ({
227
+ ...state,
228
+ groupBy: gbk
229
+ })}
230
+ );
231
+ readonly expandOfGroup = this.updater((state, data: { groupKey: string, uniqueNameOfHeadersToExpand: string[] }[]) => {
232
+ const newGroupedData = state.groupBy.map(gb => ({
233
+ key: gb.key,
234
+ expandedHeaders: data.find(g => g.groupKey === gb.key)?.uniqueNameOfHeadersToExpand ?? gb.expandedHeaders,
235
+ sort: gb.sort,
236
+ } as GroupedData));
237
+ return ({ ...state, groupBy: newGroupedData });
238
+ });
239
+ readonly collapseAll = this.updater((state) => ({
240
+ ...state,
241
+ groupBy: state.groupBy.map(gb => ({ key: gb.key, expandedHeaders: [], sort: gb.sort }))
242
+ }));
243
+ readonly collapseAllOfKey = this.updater((state, data: { keys: string[] }) => ({
244
+ ...state,
245
+ groupBy: state.groupBy.map(gb => ({
246
+ key: gb.key,
247
+ expandedHeaders: data.keys.includes(gb.key) ? [] : gb.expandedHeaders,
248
+ sort: gb.sort,
249
+ }))
250
+ }));
251
+
252
+ updateGroupBySort = this.updater((state, data: { key: string, sort: SortDirection }) => {
253
+ const newGroupedData = replaceInArrayWithClone(state.groupBy, gb => gb.key === data.key, gb => {
254
+ gb.sort = data.sort;
255
+ });
256
+ return ({ ...state, groupBy: newGroupedData });
257
+ });
258
+
259
+ getGroupBySortDirection = (key: string) => computed(() => {
260
+ const groupBy = this.state().groupBy.find(gb => gb.key === key);
261
+ return groupBy ? groupBy.sort : '';
262
+ });
263
+
264
+ cycleGroupBySortDirection = this.updater((state, key: string) => {
265
+ const currentGroupBy = state.groupBy.find(gb => gb.key === key);
266
+ console.log(currentGroupBy);
267
+ if(!currentGroupBy) return state;
268
+
269
+ let nextSort: SortDirection;
270
+ switch (currentGroupBy.sort) {
271
+ case '':
272
+ case undefined:
273
+ nextSort = 'desc';
274
+ break;
275
+ case 'desc':
276
+ nextSort = 'asc';
277
+ break;
278
+ case 'asc':
279
+ nextSort = '';
280
+ break;
281
+ }
282
+
283
+ const newGroupedData = replaceInArrayWithClone(state.groupBy, gb => gb.key === key, gb => {
284
+ gb.sort = nextSort;
285
+ });
286
+ return ({ ...state, groupBy: newGroupedData });
287
+ });
288
+ #$groupBy = this.selectSignal(state => state.groupBy);
289
+ $groupByData = this.selectSignal(
290
+ this.#$groupBy,
291
+ this.$metaDataArray,
292
+ (gb, mds) => gb.filter(bg => mds.some(md => md.key === bg.key)),
293
+
294
+ {
295
+ equal: (prev: GroupedData[], curr: GroupedData[]) =>
296
+ prev.length === curr.length && curr.every((k, i) => prev[i].key === k.key)
297
+ }
298
+ );
299
+ groupByKeys$ = this.select(state => state.groupBy.map(gbk => gbk.key))
300
+ .pipe(distinctUntilChanged<string[]>((prev, curr) => prev.length === curr.length && curr.every((k, i) => prev[i] === k)));
301
+ $userDefinedNoGroups = this.selectSignal(state => state.userDefined.noGroups);
302
+ expandedGroups$ = this.select(state => state.groupBy).pipe(distinctUntilChanged((a, b) => {
303
+ const aa = a.flatMap(g => g.expandedHeaders);
304
+ const bb = b.flatMap(g => g.expandedHeaders);
305
+ return aa.length === bb.length && aa.every((k) => bb.includes(k));
306
+ }));
307
+ $expandGroups = this.selectSignal(state => state.groupBy, { equal: (a, b) => {
308
+ const aa = a.flatMap(g => g.expandedHeaders === 'all' ? ['all'] : g.expandedHeaders);
309
+ const bb = b.flatMap(g => g.expandedHeaders === 'all' ? ['all'] : g.expandedHeaders);
310
+ return aa.length === bb.length && aa.every((k) => bb.includes(k));
311
+ } });
312
+ $getIsExpanded = (columnKey: string, groupUniqueName: string) => {
313
+ return this.selectSignal(state => !!state.groupBy.filter(g => g.key === columnKey && (g.expandedHeaders.includes(groupUniqueName) || g.expandedHeaders === 'all')).length);
314
+ };
315
+ $expandedPropForKeyIsAll = (columnKey: string) =>
316
+ this.selectSignal(state => state.groupBy.find(g => g.key === columnKey)?.expandedHeaders === 'all');
317
+ $sortedGroupsUpdates = this.selectSignal(state => state.groupBy,
318
+ { equal: (a, b) =>
319
+ sortsAreSame(a.map(g => ({ active: g.key, direction: g.sort })), b.map(g => ({ active: g.key, direction: g.sort }))) }
320
+ );
321
+ //#endregion groupBy
322
+
323
+ //#region page paginator and show all
324
+ readonly setCurrentPage = this.updater((state, currentPage: number) => ({ ...state, currentPage }))
325
+ readonly setPageSize = this.updater((state, pageSize: number) =>
326
+ ({ ...state, pageSize }));
327
+ readonly setUserDefinedPageSize = this.updater((state, pageSize: number) =>
328
+ ({ ...state, userDefined: { ...state.userDefined, pageSize } }));
329
+ readonly setUserDefinedShowAll = this.updater((state, showAll: boolean) =>
330
+ ({ ...state, showAll, userDefined: { ...state.userDefined, showAll } }));
331
+ $isVirtual = this.selectSignal(state =>
332
+ state.notPersistedTableSettings.useVirtualScroll
333
+ || state.showAll
334
+ || state.userDefined?.showAll
335
+ );
336
+ $showAll = this.selectSignal(s => s.userDefined?.showAll ?? s.showAll);
337
+ $viewType = this.selectSignal<ViewType>(state => {
338
+ const usePaginator = state.notPersistedTableSettings.usePaginator;
339
+ const showAll = state.showAll || state.userDefined?.showAll;
340
+ const useVirtualScroll = state.notPersistedTableSettings.useVirtualScroll;
341
+ if(showAll || (useVirtualScroll && !usePaginator)){
342
+ return 'virtual all';
343
+ } else if(useVirtualScroll && usePaginator) {
344
+ return 'virtual paginator';
345
+ } else if(usePaginator) {
346
+ return 'paginator';
347
+ } else {
348
+ return 'all';
349
+ }
350
+ });
351
+ $userDefinedPageSize = this.selectSignal(state => (state.userDefined.pageSize));
352
+ $currentPage = this.selectSignal(state => state.currentPage);
353
+ $pageSize = this.selectSignal(s => s.userDefined?.pageSize || s.pageSize!);
354
+ //#endregion page paginator and show all
355
+
356
+ //#region table settings and props
357
+
358
+ //#region footer
359
+ addFooter = this.updater((state, key: string) => {
360
+ const meta = this.$metaData()[key];
361
+ if(!meta) return state;
362
+ if(meta.fieldType === FieldType.Currency || meta.fieldType === FieldType.Number){
363
+ meta.additional = { ...meta.additional ?? {}, footer: { type: 'sum' } }
364
+ }
365
+ return { ...state, metaData: { ...state.metaData, [key]: { ...meta } } }
366
+ })
367
+ //#end region footer
368
+
369
+ $tableSettings = this.selectSignal(state => {
370
+ const ts : NonFunctionProperties<PersistedTableSettings & NotPersistedTableSettings> =
371
+ { ...state.persistedTableSettings, ...state.notPersistedTableSettings };
372
+ return ts;
373
+ });
374
+ $notPersistedTableSettings = this.selectSignal(state => state.notPersistedTableSettings)
375
+ tableSettings$ = toObservable(this.$tableSettings);
376
+ $props = this.selectSignal(s => s.props);
377
+ //#endregion table settings and props
378
+ readonly setUserDefinedRowHeight = this.updater((state, rowHeight: number) => {
379
+ return ({ ...state, userDefined: { ...state.userDefined, rowHeight } });
380
+ });
381
+ readonly setUserDefinedHeaderHeight = this.updater((state, headerHeight: number) => {
382
+ return ({ ...state, userDefined: { ...state.userDefined, headerHeight } });
383
+ });
384
+ $userDefinedRowHeight = this.selectSignal(state => (state.userDefined.rowHeight));
385
+ $userDefinedHeaderHeight = this.selectSignal(state => (state.userDefined.headerHeight));
386
+ $footerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseFooter);
387
+ $headerCollapsed = this.selectSignal(state => state.persistedTableSettings.collapseHeader);
388
+
389
+ $getLinkInfo = (md:MetaData) => this.selectSignal(state => state.linkMaps[md.key]);
390
+
391
+ readonly resetState = this.updater((state) => {
392
+ const sorted = this.$preSort();
393
+ return ({ ...state, hiddenKeys: [], sorted, filters: {}, groupBy: [], userDefined: { widths: {}, order: {}, table: {} } });
394
+ });
395
+
396
+ readonly resetPart = this.updater((state, part: typeof resetable[number]) => {
397
+ const newState = { ...state };
398
+ switch (part){
399
+ case 'Sorting':
400
+ newState.sorted = this.$preSort();
401
+ return newState;
402
+ case 'Filters':
403
+ newState.filters = {};
404
+ return newState;
405
+ case 'Group By':
406
+ newState.groupBy = [];
407
+ newState.userDefined.noGroups = false;
408
+ return newState;
409
+ case 'Hidden Columns':
410
+ newState.hiddenKeys = [];
411
+ return newState;
412
+ case 'Column Widths':
413
+ newState.userDefined.widths = {};
414
+ newState.userDefined.table = {};
415
+ return newState;
416
+ case 'Column Order':
417
+ newState.userDefined.order = {};
418
+ return newState;
419
+ case 'Page Size':
420
+ delete newState.userDefined.pageSize;
421
+ return newState;
422
+ case 'Show All':
423
+ delete newState.userDefined.showAll;
424
+ return newState;
425
+ case 'Row Height':
426
+ delete newState.userDefined.rowHeight;
427
+ return newState;
428
+ case 'Header Height':
429
+ delete newState.userDefined.headerHeight;
430
+ return newState;
431
+ }
432
+ })
433
+
434
+ readonly updateStateFromPersistedState = this.updater( ( state: TableState, persistedState: PersistedTableState) : TableState => {
435
+ const incomingTableState: Partial<TableState> = cleanPersistedState(state, persistedState);
436
+ const newState = this.updateStateFunc(state, incomingTableState);
437
+ newState.initializationState = state.initializationState <= InitializationState.MetaDataLoaded ? InitializationState.TableSettingsLoaded : state.initializationState;
438
+ return newState;
439
+ });
440
+ private updateStateFunc = (state: TableState, incomingTableState: Partial<TableState>) : TableState => {
441
+ const metaData = state.metaData;
442
+ const sorted = incomingTableState.sorted?.length ? incomingTableState.sorted
443
+ : state.initializationState <= InitializationState.Created ? createPreSort(metaData) : state.sorted;
444
+ const groupBy = incomingTableState.groupBy?.length ? incomingTableState.groupBy : incomingTableState.userDefined?.noGroups ? [] : state.groupBy;
445
+ return { ...state, ...incomingTableState, metaData, sorted, groupBy };
446
+ };
447
+
448
+ readonly setTableSettings = this.updater((state, settings: TableBuilderSettings) => {
449
+ const s: TableState = {
450
+ ...state,
451
+ persistedTableSettings: state.persistedTableSettings.merge(settings),
452
+ notPersistedTableSettings: state.notPersistedTableSettings.merge(settings),
453
+ initializationState: InitializationState.TableSettingsLoaded
454
+ };
455
+ s.pageSize = settings.tableSettings?.paginatorSettings?.pageSize ?? s.pageSize;
456
+ s.showAll = settings.tableSettings?.paginatorSettings?.defaultAll ?? s.showAll;
457
+ s.groupBy = (settings.tableSettings?.groupBySettings || []).map(g => ({
458
+ expandedHeaders: g.expanded ? 'all' : [],
459
+ key: g.key,
460
+ sort: '' as SortDirection
461
+ } as GroupedData));
462
+ return s;
463
+ });
464
+
465
+ readonly setMetaData = this.updater((state, md: MetaData[]) => {
466
+ const metaData = md
467
+ .reduce((prev: Dictionary<MetaData>, curr) => {
468
+ if(prev[curr.key]) {
469
+ prev[curr.key] = mergeMeta(prev[curr.key], curr);
470
+ } else {
471
+ prev[curr.key] = curr;
472
+ }
473
+ return prev;
474
+ }, {});
475
+
476
+ const sortedInitialized = state.sorted.length > 0;
477
+ const sorted = sortedInitialized ? state.sorted : createPreSort(metaData);
478
+ const order = initializeOrder(state, metaData);
479
+ const initializationState = state.initializationState == InitializationState.Created ? InitializationState.MetaDataLoaded : state.initializationState;
480
+ return { ...state, initializationState, metaData, sorted, userDefined: { ...state.userDefined, order: order } };
481
+ });
482
+
483
+
484
+ readonly setProps = this.updater((state, props: TableProps) => {
485
+ return ({ ...state, props });
486
+ });
487
+
488
+
489
+ readonly setInitializationState = this.updater( (state, initializationState: InitializationState) => {
490
+ return { ...state, initializationState };
491
+ });
492
+
493
+ readonly toggleCollapseHeader = this.updater((state) => {
494
+ const tableSettings = { ...state.persistedTableSettings };
495
+ tableSettings.collapseHeader = !tableSettings.collapseHeader;
496
+ return ({ ...state, persistedTableSettings: new PersistedTableSettings(tableSettings) });
497
+ })
498
+ readonly toggleCollapseFooter = this.updater((state, options?: { collapseFooter: boolean } | void) => {
499
+ const tableSettings = { ...state.persistedTableSettings };
500
+ tableSettings.collapseFooter = options?.collapseFooter ?? !tableSettings.collapseFooter;
501
+ return ({ ...state, persistedTableSettings: new PersistedTableSettings(tableSettings) });
502
+ });
503
+
504
+ readonly setLinkMaps = this.updater((state, maps: any) => {
505
+ return ({ ...state, linkMaps: maps });
506
+ });
507
+
508
+ updateRowProps = this.updater((state, updates: Pick<NotPersistedTableSettings, 'rowClasses' | 'rowClick' | 'rowStyles'>) => {
509
+ const notPersistedTableSettings = merge(new NotPersistedTableSettings(), (state.notPersistedTableSettings));
510
+ if(updates.rowClasses)
511
+ notPersistedTableSettings.rowClasses = updates.rowClasses;
512
+ if(updates.rowClick)
513
+ notPersistedTableSettings.rowClick = updates.rowClick;
514
+ if(updates.rowStyles)
515
+ notPersistedTableSettings.rowStyles = updates.rowStyles;
516
+ return ({ ...state, notPersistedTableSettings });
517
+ });
518
+
519
+ on = <V>(srcObservable: Observable<V>, func: (obj: V) => void) => {
520
+ this.effect(() => srcObservable.pipe(
521
+ tap(func)
522
+ ));
523
+ return this;
524
+ };
525
+ }
526
+
527
+
528
+ export type ViewType = 'virtual paginator' | 'paginator' | 'virtual all' | 'all';
529
+ export const resetable = [
530
+ 'Sorting',
531
+ 'Filters',
532
+ 'Group By',
533
+ 'Hidden Columns',
534
+ 'Column Widths',
535
+ 'Column Order',
536
+ 'Row Height',
537
+ 'Header Height',
538
+ 'Page Size',
539
+ 'Show All',
540
+ ] as const
@@ -0,0 +1,34 @@
1
+ import { ChangeDetectionStrategy, Component, input, computed } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'tb-comma-array-column',
5
+ template: `
6
+ @for(val of displayArray(); track $index){
7
+ {{val + (!$last ? ',' : '')}}
8
+ }
9
+ `,
10
+ changeDetection: ChangeDetectionStrategy.OnPush
11
+ })
12
+ export class ArrayCommaColumnComponent {
13
+
14
+ value = input.required<(string | number)[]>();
15
+ additional = input(3);
16
+ displayArray = computed(() => (this.value() || []).slice(0, this.additional()))
17
+ }
18
+
19
+
20
+ @Component({
21
+ selector: 'tb-new-line-array-column',
22
+ template: `
23
+ @for(val of displayArray(); track $index){
24
+ {{val}}
25
+ @if(!$last){ <br/> }
26
+ }
27
+ `,
28
+ changeDetection: ChangeDetectionStrategy.OnPush
29
+ })
30
+ export class ArrayNewLineColumnComponent {
31
+ value = input.required<(string | number)[]>();
32
+ additional = input(3);
33
+ displayArray = computed(() => (this.value() || []).slice(0, this.additional()));
34
+ }
@@ -0,0 +1,109 @@
1
+ @let metaData = $metaData();
2
+ @let customCell = $customCell();
3
+ @let customHeader = $customHeader();
4
+ @let styles = $styles()!;
5
+
6
+ @if(metaData)
7
+ {
8
+ <ng-container [matColumnDef]="metaData.key">
9
+
10
+ <!-- header -->
11
+ <ng-template #myHeader matHeaderCellDef>
12
+ <mat-header-cell class="column-head" cdkDrag resizeColumn [style]='styles?.header' [key]="metaData.key"
13
+ [class]='metaData.additional?.columnPartClasses?.header'>
14
+ <div class="header-container" cdkDragHandle>
15
+ @let headerTemplate = customHeader?.template();
16
+ @if(!headerTemplate && !customCell?.columnDef?.headerCell)
17
+ {
18
+ @if((metaData.fieldType !== FieldType.NotMapped || !!metaData.sortLogic?.sortBy) && !metaData.noSort)
19
+ {
20
+ <div mat-sort-header style="width: 100%">
21
+ {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}
22
+ </div>
23
+ }
24
+ @else if(metaData.fieldType === FieldType.NotMapped || metaData.noSort)
25
+ {
26
+ <div style="width: 100%">
27
+ {{ metaData.displayName ? metaData.displayName : ( metaData.key | spaceCase ) }}
28
+ </div>
29
+ }
30
+ @if($showFilters())
31
+ {
32
+ <tb-header-menu #menu [metaData]='metaData' />
33
+ }
34
+ }
35
+ @else if(!customCell?.columnDef?.headerCell)
36
+ {
37
+ @if((metaData.fieldType !== FieldType.NotMapped || !!metaData.sortLogic?.sortBy) && !metaData.noSort)
38
+ {
39
+ <div mat-sort-header style="width: 100%">
40
+ <ng-container
41
+ *ngTemplateOutlet="headerTemplate; context: { $implicit: metaData, metaData: metaData, styles: styles?.header } " />
42
+ </div>
43
+ }
44
+ @else if(metaData.fieldType === FieldType.NotMapped || metaData.noSort)
45
+ {
46
+ <ng-container
47
+ *ngTemplateOutlet="headerTemplate; context: { $implicit: metaData, metaData: metaData, styles: styles?.header } " />
48
+ }
49
+ @if($showFilters())
50
+ {
51
+ <tb-header-menu #menu [metaData]='metaData' />
52
+ }
53
+ }
54
+ @else
55
+ {
56
+ <ng-container
57
+ *ngTemplateOutlet="customCell!.columnDef!.headerCell.template; context: {metaData: metaData, styles: styles?.header} " />
58
+ }
59
+ </div>
60
+ </mat-header-cell>
61
+ </ng-template>
62
+
63
+ <!-- body -->
64
+ <ng-container *matCellDef="let element;">
65
+ <ng-container *ngTemplateOutlet="$outerTemplate()!; context: { metaData: metaData, element: element , styles: styles?.body, $implicit: element }"/>
66
+ </ng-container>
67
+ <ng-template #body let-element='element' >
68
+ <mat-cell [matTooltip]="metaData.toolTip ? (getTooltip | func : element) : ''"
69
+ [conditionalClasses]='metaData.classes' [element]='element' [styler]='styles.body'
70
+ (click)='cellClicked(element, metaData.key, $event)' >
71
+ <ng-container *ngTemplateOutlet="$innerTemplate()!;
72
+ context: {
73
+ value: ($transform()! | func : element),
74
+ element: element,
75
+ additional: $additional(),
76
+ innerStyles: styles.innerBody,
77
+ $implicit: element
78
+ }; Injector: injector" />
79
+ </mat-cell>
80
+ </ng-template>
81
+
82
+ <!-- footer -->
83
+ <ng-template matFooterCellDef>
84
+ @if(customCell?.columnDef?.footerCell)
85
+ {
86
+ <ng-container
87
+ *ngTemplateOutlet="customCell!.columnDef!.footerCell.template;
88
+ context: {metaData: metaData, data: $data, styles : styles.footer }"/>
89
+ }
90
+ @else
91
+ {
92
+ @let data = $data();
93
+ <mat-footer-cell [style]='styles.footer' [class]='metaData.additional?.columnPartClasses?.footer'>
94
+ @if(!!data?.length && metaData.additional?.footer)
95
+ {
96
+ <span class="bold">
97
+ @switch (metaData.fieldType)
98
+ {
99
+ @case (FieldType.Currency) { {{ data | columnTotal: metaData | currency }} }
100
+ @case (FieldType.Number) { {{ data | columnTotal: metaData | number }} }
101
+ }
102
+ </span>
103
+ }
104
+
105
+ </mat-footer-cell>
106
+ }
107
+ </ng-template>
108
+ </ng-container>
109
+ }