@sankhyalabs/core 1.0.38 → 1.0.42

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 (156) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +34 -0
  3. package/README.md +54 -54
  4. package/dist/application/Application.d.ts +8 -0
  5. package/dist/application/Application.js +19 -0
  6. package/dist/application/Application.js.map +1 -0
  7. package/dist/dataunit/DataUnit.d.ts +82 -80
  8. package/dist/dataunit/DataUnit.js +278 -254
  9. package/dist/dataunit/DataUnit.js.map +1 -1
  10. package/dist/dataunit/metadata/DataType.d.ts +9 -9
  11. package/dist/dataunit/metadata/DataType.js +36 -36
  12. package/dist/dataunit/metadata/DataType.js.map +1 -1
  13. package/dist/dataunit/metadata/UnitMetadata.d.ts +71 -71
  14. package/dist/dataunit/metadata/UnitMetadata.js +31 -31
  15. package/dist/dataunit/state/HistReducer.d.ts +10 -10
  16. package/dist/dataunit/state/HistReducer.js +27 -27
  17. package/dist/dataunit/state/HistReducer.js.map +1 -1
  18. package/dist/dataunit/state/StateManager.d.ts +57 -57
  19. package/dist/dataunit/state/StateManager.js +96 -96
  20. package/dist/dataunit/state/action/DataUnitAction.d.ts +28 -27
  21. package/dist/dataunit/state/action/DataUnitAction.js +33 -32
  22. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  23. package/dist/dataunit/state/slice/AddedRecordsSlice.d.ts +11 -11
  24. package/dist/dataunit/state/slice/AddedRecordsSlice.js +25 -25
  25. package/dist/dataunit/state/slice/AddedRecordsSlice.js.map +1 -1
  26. package/dist/dataunit/state/slice/ChangesSlice.d.ts +12 -12
  27. package/dist/dataunit/state/slice/ChangesSlice.js +72 -72
  28. package/dist/dataunit/state/slice/ChangesSlice.js.map +1 -1
  29. package/dist/dataunit/state/slice/CurrentRecordsSlice.d.ts +11 -11
  30. package/dist/dataunit/state/slice/CurrentRecordsSlice.js +45 -45
  31. package/dist/dataunit/state/slice/CurrentRecordsSlice.js.map +1 -1
  32. package/dist/dataunit/state/slice/RecordsSlice.d.ts +10 -10
  33. package/dist/dataunit/state/slice/RecordsSlice.js +43 -37
  34. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  35. package/dist/dataunit/state/slice/RemovedRecordsSlice.d.ts +9 -9
  36. package/dist/dataunit/state/slice/RemovedRecordsSlice.js +24 -20
  37. package/dist/dataunit/state/slice/RemovedRecordsSlice.js.map +1 -1
  38. package/dist/dataunit/state/slice/SelectionSlice.d.ts +11 -11
  39. package/dist/dataunit/state/slice/SelectionSlice.js +111 -111
  40. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  41. package/dist/dataunit/state/slice/UnitMetadataSlice.d.ts +11 -11
  42. package/dist/dataunit/state/slice/UnitMetadataSlice.js +20 -20
  43. package/dist/dataunit/state/slice/UnitMetadataSlice.js.map +1 -1
  44. package/dist/http/AuthorizedServiceCaller.d.ts +11 -11
  45. package/dist/http/AuthorizedServiceCaller.js +53 -53
  46. package/dist/http/AuthorizedServiceCaller.js.map +1 -1
  47. package/dist/http/HttpProvider.d.ts +25 -25
  48. package/dist/http/HttpProvider.js +73 -73
  49. package/dist/http/HttpProvider.js.map +1 -1
  50. package/dist/http/RequestMetadata.d.ts +30 -30
  51. package/dist/http/RequestMetadata.js +24 -24
  52. package/dist/http/SkwHttpProvider.d.ts +9 -9
  53. package/dist/http/SkwHttpProvider.js +66 -67
  54. package/dist/http/SkwHttpProvider.js.map +1 -1
  55. package/dist/http/data-fetcher/HttpFetcher.d.ts +14 -0
  56. package/dist/http/data-fetcher/HttpFetcher.js +164 -0
  57. package/dist/http/data-fetcher/HttpFetcher.js.map +1 -0
  58. package/dist/http/data-fetcher/default/DefaultGraphQL.d.ts +3 -0
  59. package/dist/http/data-fetcher/default/DefaultGraphQL.js +18 -0
  60. package/dist/http/data-fetcher/default/DefaultGraphQL.js.map +1 -0
  61. package/dist/http/data-fetcher/default/application-config-fetcher.d.ts +6 -0
  62. package/dist/http/data-fetcher/default/application-config-fetcher.js +21 -0
  63. package/dist/http/data-fetcher/default/application-config-fetcher.js.map +1 -0
  64. package/dist/http/data-fetcher/default/data-unit-graphql.d.ts +3 -0
  65. package/dist/http/data-fetcher/default/data-unit-graphql.js +18 -0
  66. package/dist/http/data-fetcher/default/data-unit-graphql.js.map +1 -0
  67. package/dist/http/data-fetcher/default/dataunit-executor.d.ts +10 -0
  68. package/dist/http/data-fetcher/default/dataunit-executor.js +56 -0
  69. package/dist/http/data-fetcher/default/dataunit-executor.js.map +1 -0
  70. package/dist/http/data-fetcher/default/dataunit-fetcher.d.ts +9 -0
  71. package/dist/http/data-fetcher/default/dataunit-fetcher.js +69 -0
  72. package/dist/http/data-fetcher/default/dataunit-fetcher.js.map +1 -0
  73. package/dist/http/data-fetcher/default/form-config-fetcher.d.ts +2 -0
  74. package/dist/http/data-fetcher/default/form-config-fetcher.js +3 -0
  75. package/dist/http/data-fetcher/default/form-config-fetcher.js.map +1 -0
  76. package/dist/http/data-fetcher/default/grid-config-fetcher.d.ts +2 -0
  77. package/dist/http/data-fetcher/default/grid-config-fetcher.js +3 -0
  78. package/dist/http/data-fetcher/default/grid-config-fetcher.js.map +1 -0
  79. package/dist/http/data-fetcher/default/index.d.ts +0 -0
  80. package/dist/http/data-fetcher/default/index.js +2 -0
  81. package/dist/http/data-fetcher/default/index.js.map +1 -0
  82. package/dist/http/data-fetcher/default/sankhya-graphql.d.ts +3 -0
  83. package/dist/http/data-fetcher/default/sankhya-graphql.js +8 -0
  84. package/dist/http/data-fetcher/default/sankhya-graphql.js.map +1 -0
  85. package/dist/http/data-fetcher/graphql/DefaultGraphQl.d.ts +3 -0
  86. package/dist/http/data-fetcher/graphql/DefaultGraphQl.js +18 -0
  87. package/dist/http/data-fetcher/graphql/DefaultGraphQl.js.map +1 -0
  88. package/dist/http/data-fetcher/state/LoadStateManager.d.ts +23 -0
  89. package/dist/http/data-fetcher/state/LoadStateManager.js +78 -0
  90. package/dist/http/data-fetcher/state/LoadStateManager.js.map +1 -0
  91. package/dist/index.d.ts +16 -16
  92. package/dist/index.js +17 -17
  93. package/dist/index.js.map +1 -1
  94. package/dist/ui/FloatingManager.d.ts +24 -24
  95. package/dist/ui/FloatingManager.js +122 -123
  96. package/dist/ui/FloatingManager.js.map +1 -1
  97. package/dist/utils/ApplicationContext.d.ts +5 -5
  98. package/dist/utils/ApplicationContext.js +16 -16
  99. package/dist/utils/ApplicationContext.js.map +1 -1
  100. package/dist/utils/CriteriaModel.d.ts +109 -109
  101. package/dist/utils/CriteriaModel.js +173 -173
  102. package/dist/utils/CriteriaParameter.d.ts +69 -69
  103. package/dist/utils/CriteriaParameter.js +82 -84
  104. package/dist/utils/CriteriaParameter.js.map +1 -1
  105. package/dist/utils/DateUtils.d.ts +5 -5
  106. package/dist/utils/DateUtils.js +42 -42
  107. package/dist/utils/DateUtils.js.map +1 -1
  108. package/dist/utils/MaskFormatter.d.ts +126 -126
  109. package/dist/utils/MaskFormatter.js +275 -275
  110. package/dist/utils/NumberUtils.d.ts +53 -53
  111. package/dist/utils/NumberUtils.js +141 -146
  112. package/dist/utils/NumberUtils.js.map +1 -1
  113. package/dist/utils/StringUtils.d.ts +18 -18
  114. package/dist/utils/StringUtils.js +53 -53
  115. package/dist/utils/TimeFormatter.d.ts +33 -33
  116. package/dist/utils/TimeFormatter.js +97 -97
  117. package/dist/utils/TimeFormatter.js.map +1 -1
  118. package/jest.config.ts +16 -13
  119. package/mock/http/XMLHttpRequest-mock.js +25 -25
  120. package/package.json +37 -31
  121. package/src/dataunit/DataUnit.ts +356 -333
  122. package/src/dataunit/metadata/DataType.ts +37 -37
  123. package/src/dataunit/metadata/UnitMetadata.ts +82 -82
  124. package/src/dataunit/state/HistReducer.ts +33 -33
  125. package/src/dataunit/state/StateManager.ts +141 -141
  126. package/src/dataunit/state/action/DataUnitAction.ts +50 -48
  127. package/src/dataunit/state/slice/AddedRecordsSlice.ts +32 -32
  128. package/src/dataunit/state/slice/ChangesSlice.ts +90 -90
  129. package/src/dataunit/state/slice/CurrentRecordsSlice.ts +53 -53
  130. package/src/dataunit/state/slice/RecordsSlice.ts +56 -49
  131. package/src/dataunit/state/slice/RemovedRecordsSlice.ts +29 -25
  132. package/src/dataunit/state/slice/SelectionSlice.ts +130 -130
  133. package/src/dataunit/state/slice/UnitMetadataSlice.ts +29 -29
  134. package/src/http/AuthorizedServiceCaller.ts +58 -57
  135. package/src/http/HttpProvider.ts +93 -93
  136. package/src/http/RequestMetadata.ts +41 -41
  137. package/src/http/SkwHttpProvider.ts +77 -77
  138. package/src/index.ts +44 -44
  139. package/src/ui/FloatingManager.ts +165 -165
  140. package/src/utils/ApplicationContext.ts +18 -18
  141. package/src/utils/CriteriaModel.ts +207 -207
  142. package/src/utils/CriteriaParameter.ts +107 -107
  143. package/src/utils/DateUtils.ts +52 -52
  144. package/src/utils/MaskFormatter.ts +322 -322
  145. package/src/utils/NumberUtils.ts +175 -175
  146. package/src/utils/StringUtils.ts +60 -60
  147. package/src/utils/TimeFormatter.ts +97 -97
  148. package/test/http/HttpProvider.spec.ts +34 -34
  149. package/test/http/SkwHttpProvider.ts.spec.ts +33 -33
  150. package/test/util/CriteriaModel.spec.ts +231 -231
  151. package/test/util/CriteriaParameter.spec.ts +51 -51
  152. package/test/util/MaskFormatter.spec.ts +138 -138
  153. package/test/util/NumberUtils.spec.ts +156 -156
  154. package/test/util/StringUtils.spec.ts +43 -43
  155. package/test/util/TimeFormatter.spec.ts +25 -25
  156. package/tsconfig.json +15 -15
@@ -1,334 +1,357 @@
1
- import { UnitMetadata, FieldDescriptor, SortingProvider, FilterProvider, Sort, Filter } from "./metadata/UnitMetadata";
2
- import { convertType } from "./metadata/DataType";
3
-
4
- import { DataUnitAction, Action } from "./state/action/DataUnitAction";
5
- import StateManager from "./state/StateManager";
6
-
7
- import { HistReducer, canRedo, canUndo } from "./state/HistReducer";
8
- import { UnitMetadataReducer, getField, getMetadata } from "./state/slice/UnitMetadataSlice";
9
- import { RecordsReducer } from "./state/slice/RecordsSlice";
10
- import { SelectionReducer, getSelection, hasNext, hasPrevious } from "./state/slice/SelectionSlice";
11
- import { ChangesReducer, isDirty, getChangesToSave } from "./state/slice/ChangesSlice";
12
- import { RemovedRecordsReducer } from "./state/slice/RemovedRecordsSlice";
13
- import { AddedRecordsReducer, prepareAddedRecordId } from "./state/slice/AddedRecordsSlice";
14
- import { CurrentRecordsReducer, getCurrentRecords, getFieldValue } from "./state/slice/CurrentRecordsSlice";
15
-
16
- export default class DataUnit {
17
-
18
- private _name: string;
19
- private _observers: Array<(action: DataUnitAction) => void>;
20
- private _sortingProvider?: SortingProvider;
21
- private _filterProviders: Array<FilterProvider>;
22
- private _stateManager: StateManager;
23
- private _interceptors: Array<DUActionInterceptor>;
24
-
25
- public metadataLoader?: (dataUnit: DataUnit) => Promise<UnitMetadata>;
26
- public dataLoader?: (dataUnit: DataUnit, sort?: Array<Sort>, filters?: Array<Filter>) => Promise<Array<Record>>;
27
- public saveLoader?: (dataUnit: DataUnit, changes: Array<Change>) => Promise<Array<SavedRecord>>;
28
-
29
- constructor(name: string) {
30
- this._name = name;
31
- this._stateManager = new StateManager(
32
- [
33
- HistReducer,
34
- UnitMetadataReducer,
35
- RecordsReducer,
36
- RemovedRecordsReducer,
37
- AddedRecordsReducer,
38
- SelectionReducer,
39
- ChangesReducer,
40
- CurrentRecordsReducer
41
- ]
42
- );
43
- this._observers = [];
44
- this._filterProviders = [];
45
- this._sortingProvider = undefined;
46
- this._interceptors = [];
47
- }
48
-
49
- public get name(): string {
50
- return this._name;
51
- }
52
-
53
- // Métodos privados
54
- private validateAndTypeValue(fieldName: string, newValue: any): any {
55
- //FIXME: Validações devem ser feitas aqui
56
- const descriptor: FieldDescriptor | undefined = this.getField(fieldName);
57
- return descriptor ? convertType(descriptor.dataType, newValue) : newValue;
58
- }
59
-
60
- private getFilters(): Array<Filter> | undefined {
61
- let filters: Array<Filter> | undefined = undefined;
62
- this._filterProviders.forEach(p => {
63
- const f = p.getFilter(this.name);
64
- if (f) {
65
- filters = (filters || []).concat(f);
66
- }
67
- });
68
- return filters;
69
- }
70
-
71
- private getSort(): Array<Sort> | undefined {
72
- return this._sortingProvider ? this._sortingProvider.getSort(this._name) : undefined;
73
- }
74
-
75
- // Loaders
76
- public async loadMetadata(): Promise<UnitMetadata> {
77
- this.dispatchAction(Action.LOADING_METADATA);
78
- return new Promise((resolve, fail) => {
79
- if (this.metadataLoader) {
80
- this.metadataLoader(this).then(
81
- metadata => {
82
- this.metadata = metadata
83
- resolve(this.metadata);
84
- }
85
- ).catch(error => fail(error));
86
- }
87
- });
88
- }
89
-
90
- public async loadData(): Promise<Array<Record>> {
91
- this.dispatchAction(Action.LOADING_DATA);
92
- return new Promise((resolve, fail) => {
93
- if (this.dataLoader) {
94
- const sort = this.getSort();
95
- const filters = this.getFilters();
96
- this.dataLoader(this, sort, filters).then(
97
- records => {
98
- this.records = records;
99
- resolve(this.records);
100
- }
101
- ).catch(error => fail(error));
102
- }
103
- });
104
- }
105
-
106
- public async saveData(): Promise<void> {
107
-
108
- const changes: Array<Change> = getChangesToSave(this._name, this._stateManager);
109
-
110
- if (changes.length > 0) {
111
- this.dispatchAction(Action.SAVING_DATA);
112
- return new Promise((resolve, fail) => {
113
- if (this.saveLoader) {
114
- this.saveLoader(this, changes).then(
115
- records => this.dispatchAction(Action.DATA_SAVED, { changes, records })
116
- ).catch(error => fail(error));
117
- }
118
- });
119
- }
120
- return Promise.resolve();
121
- }
122
-
123
- // API
124
- public valueFromString(fieldName: string, value: string): any {
125
- const descriptor: FieldDescriptor | undefined = this.getField(fieldName);
126
- return descriptor ? convertType(descriptor.dataType, value) : value;
127
- }
128
-
129
- public addInterceptor(interceptor: DUActionInterceptor): void {
130
- this._interceptors.push(interceptor);
131
- }
132
-
133
- public addFilterProvider(provider: FilterProvider): void {
134
- this._filterProviders.push(provider);
135
- }
136
-
137
- public set sortingProvider(provider: SortingProvider) {
138
- this._sortingProvider = provider;
139
- }
140
-
141
- public set metadata(md: UnitMetadata) {
142
- this.dispatchAction(Action.METADATA_LOADED, md);
143
- }
144
-
145
- public get metadata(): UnitMetadata {
146
- return getMetadata(this._stateManager);
147
- }
148
-
149
- public set records(r: Array<Record>) {
150
- this.dispatchAction(Action.DATA_LOADED, r);
151
- }
152
-
153
- public get records(): Array<Record> {
154
- const records = getCurrentRecords(this._stateManager);
155
- return records ? Array.from(records.values()) : [];
156
- }
157
-
158
- public getField(fieldName: string): FieldDescriptor | undefined {
159
- return getField(this._stateManager, fieldName);
160
- }
161
-
162
- public addRecord(): void {
163
- this.dispatchAction(Action.RECORDS_ADDED, prepareAddedRecordId(this._stateManager, [{}]));
164
- }
165
-
166
- public copySelected(): void{
167
- const selectedRecords = this.getSelectedRecords();
168
- if(selectedRecords){
169
- this.dispatchAction(Action.RECORDS_COPIED, prepareAddedRecordId(this._stateManager, selectedRecords));
170
- }
171
- }
172
-
173
- public removeSelectedRecords(): void {
174
- const selection = getSelection(this._stateManager);
175
- if (selection) {
176
- this.dispatchAction(Action.RECORDS_REMOVED, selection);
177
- }
178
- }
179
-
180
- public getFieldValue(fieldName: string): any {
181
- return getFieldValue(this._stateManager, fieldName);
182
- }
183
-
184
- public setFieldValue(fieldName: string, newValue: any, records?: Array<string>): void {
185
-
186
- const typedValue = this.validateAndTypeValue(fieldName, newValue);
187
- const currentValue = this.getFieldValue(fieldName);
188
-
189
- if (currentValue !== typedValue) {
190
- this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records });
191
- }
192
- }
193
-
194
- public getSelection(): Array<string> {
195
- return getSelection(this._stateManager);
196
- }
197
-
198
- public setSelection(selection: Array<string>): void {
199
- this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection });
200
- }
201
-
202
- public setSelectionByIndex(selection: Array<number>): void {
203
- this.dispatchAction(Action.SELECTION_CHANGED, { type: "index", selection });
204
- }
205
-
206
- public getSelectedRecords(): Array<Record>|undefined{
207
- const selection: Array<string> = this.getSelection();
208
- if(selection){
209
- const currentRecords: Array<Record> = this.records;
210
- return currentRecords?.filter(r => selection.includes(r.__record__id__));
211
- }
212
- }
213
-
214
- public nextRecord(): void {
215
- this.dispatchAction(Action.NEXT_SELECTED);
216
- }
217
-
218
- public previousRecord(): void {
219
- this.dispatchAction(Action.PREVIOUS_SELECTED);
220
- }
221
-
222
- public cancelEdition(): void {
223
- this.dispatchAction(Action.EDITION_CANCELED);
224
- }
225
-
226
- public isDirty(): boolean {
227
- return isDirty(this._stateManager);
228
- }
229
-
230
- public hasNext(): boolean {
231
- return hasNext(this._stateManager);
232
- }
233
-
234
- public hasPrevious(): boolean {
235
- return hasPrevious(this._stateManager);
236
- }
237
-
238
- public canUndo(): boolean {
239
- return canUndo(this._stateManager);
240
- }
241
-
242
- public canRedo(): boolean {
243
- return canRedo(this._stateManager);
244
- }
245
-
246
- public undo() {
247
- this.dispatchAction(Action.CHANGE_UNDONE);
248
- }
249
-
250
- public redo() {
251
- this.dispatchAction(Action.CHANGE_REDONE);
252
- }
253
-
254
- public toString(){
255
- return this.name;
256
- }
257
-
258
- // Actions / State manager
259
- private dispatchAction(actionType: Action, payload?: any): void {
260
- let action = new DataUnitAction(actionType, payload);
261
-
262
- this._interceptors?.forEach(interceptor => {
263
- if(action){
264
- action = interceptor.interceptAction(action);
265
- }
266
- });
267
-
268
- if(action){
269
- this._stateManager.process(action);
270
- this._observers.forEach(f => f(action));
271
- }
272
- }
273
-
274
- public subscribe(observer: (action: DataUnitAction) => void) {
275
- this._observers.push(observer);
276
- }
277
-
278
- public unsubscribe(observer: Function) {
279
- this._observers = this._observers.filter(f => f !== observer);
280
- }
281
- }
282
-
283
- export interface DUActionInterceptor{
284
- interceptAction(action: DataUnitAction): DataUnitAction;
285
- }
286
-
287
- export interface Record {
288
- __record__id__: string;
289
- __parent__record__id__?: string;
290
- [key: string]: any;
291
- }
292
-
293
- export interface SavedRecord extends Record {
294
- __old__id__?: string;
295
- }
296
-
297
- export enum ChangeOperation {
298
- INSERT = "INSERT",
299
- UPDATE = "UPDATE",
300
- DELETE = "DELETE"
301
- }
302
-
303
- export class Change {
304
-
305
- public dataUnit: string;
306
- public record: Record;
307
- public updatingFields: any;
308
-
309
- private _operation: ChangeOperation;
310
-
311
- constructor(dataUnit: string, record: Record, updates: any, operation: ChangeOperation) {
312
- this.dataUnit = dataUnit;
313
- this.record = record;
314
- this.updatingFields = updates;
315
- this._operation = operation;
316
- }
317
-
318
- public get operation(): string{
319
- return this._operation.toString();
320
- }
321
-
322
- public isInsert(): boolean {
323
- return this._operation === ChangeOperation.INSERT;
324
- }
325
-
326
- public isDelete(): boolean {
327
- return this._operation === ChangeOperation.DELETE;
328
- }
329
-
330
- public isUpdate(): boolean {
331
- return this._operation === ChangeOperation.UPDATE;
332
- }
333
-
1
+ import { UnitMetadata, FieldDescriptor, SortingProvider, FilterProvider, Sort, Filter } from "./metadata/UnitMetadata.js";
2
+ import { convertType } from "./metadata/DataType.js";
3
+
4
+ import { DataUnitAction, Action } from "./state/action/DataUnitAction.js";
5
+ import StateManager from "./state/StateManager.js";
6
+
7
+ import { HistReducer, canRedo, canUndo } from "./state/HistReducer.js";
8
+ import { UnitMetadataReducer, getField, getMetadata } from "./state/slice/UnitMetadataSlice.js";
9
+ import { RecordsReducer } from "./state/slice/RecordsSlice.js";
10
+ import { SelectionReducer, getSelection, hasNext, hasPrevious } from "./state/slice/SelectionSlice.js";
11
+ import { ChangesReducer, isDirty, getChangesToSave } from "./state/slice/ChangesSlice.js";
12
+ import { RemovedRecordsReducer } from "./state/slice/RemovedRecordsSlice.js";
13
+ import { AddedRecordsReducer, prepareAddedRecordId } from "./state/slice/AddedRecordsSlice.js";
14
+ import { CurrentRecordsReducer, getCurrentRecords, getFieldValue } from "./state/slice/CurrentRecordsSlice.js";
15
+
16
+ export default class DataUnit {
17
+
18
+ private _name: string;
19
+ private _observers: Array<(action: DataUnitAction) => void>;
20
+ private _sortingProvider?: SortingProvider;
21
+ private _filterProviders: Array<FilterProvider>;
22
+ private _stateManager: StateManager;
23
+ private _interceptors: Array<DUActionInterceptor>;
24
+
25
+ public metadataLoader?: (dataUnit: DataUnit) => Promise<UnitMetadata>;
26
+ public dataLoader?: (dataUnit: DataUnit, sort?: Array<Sort>, filters?: Array<Filter>) => Promise<Array<Record>>;
27
+ public saveLoader?: (dataUnit: DataUnit, changes: Array<Change>) => Promise<Array<SavedRecord>>;
28
+ public removeLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<string>>;
29
+
30
+ constructor(name: string) {
31
+ this._name = name;
32
+ this._stateManager = new StateManager(
33
+ [
34
+ HistReducer,
35
+ UnitMetadataReducer,
36
+ RecordsReducer,
37
+ RemovedRecordsReducer,
38
+ AddedRecordsReducer,
39
+ SelectionReducer,
40
+ ChangesReducer,
41
+ CurrentRecordsReducer
42
+ ]
43
+ );
44
+ this._observers = [];
45
+ this._filterProviders = [];
46
+ this._sortingProvider = undefined;
47
+ this._interceptors = [];
48
+ }
49
+
50
+ public get name(): string {
51
+ return this._name;
52
+ }
53
+
54
+ // Métodos privados
55
+ private validateAndTypeValue(fieldName: string, newValue: any): any {
56
+ //FIXME: Validações devem ser feitas aqui
57
+ const descriptor: FieldDescriptor | undefined = this.getField(fieldName);
58
+ return descriptor ? convertType(descriptor.dataType, newValue) : newValue;
59
+ }
60
+
61
+ private getFilters(): Array<Filter> | undefined {
62
+ let filters: Array<Filter> | undefined = undefined;
63
+ this._filterProviders.forEach(p => {
64
+ const f = p.getFilter(this.name);
65
+ if (f) {
66
+ filters = (filters || []).concat(f);
67
+ }
68
+ });
69
+ return filters;
70
+ }
71
+
72
+ private getSort(): Array<Sort> | undefined {
73
+ return this._sortingProvider ? this._sortingProvider.getSort(this._name) : undefined;
74
+ }
75
+
76
+ // Loaders
77
+ public async loadMetadata(): Promise<UnitMetadata> {
78
+ this.dispatchAction(Action.LOADING_METADATA);
79
+ return new Promise((resolve, fail) => {
80
+ if (this.metadataLoader) {
81
+ this.metadataLoader(this).then(
82
+ metadata => {
83
+ this.metadata = metadata
84
+ resolve(this.metadata);
85
+ }
86
+ ).catch(error => fail(error));
87
+ }
88
+ });
89
+ }
90
+
91
+ public async loadData(): Promise<Array<Record>> {
92
+ this.dispatchAction(Action.LOADING_DATA);
93
+ return new Promise((resolve, fail) => {
94
+ if (this.dataLoader) {
95
+ const sort = this.getSort();
96
+ const filters = this.getFilters();
97
+ this.dataLoader(this, sort, filters).then(
98
+ records => {
99
+ this.records = records;
100
+ resolve(this.records);
101
+ }
102
+ ).catch(error => fail(error));
103
+ }
104
+ });
105
+ }
106
+
107
+ public async saveData(): Promise<void> {
108
+
109
+ const changes: Array<Change> = getChangesToSave(this._name, this._stateManager);
110
+
111
+ if (changes.length > 0) {
112
+ this.dispatchAction(Action.SAVING_DATA);
113
+ return new Promise((resolve, fail) => {
114
+ if (this.saveLoader) {
115
+ this.saveLoader(this, changes).then(
116
+ records => this.dispatchAction(Action.DATA_SAVED, { changes, records })
117
+ ).catch(error => fail(error));
118
+ }
119
+ });
120
+ }
121
+ return Promise.resolve();
122
+ }
123
+
124
+ public async removeSelectedRecords(buffered: boolean = false): Promise<Array<string>> {
125
+ const selection = getSelection(this._stateManager);
126
+ if (selection) {
127
+ return this.removeRecords(selection, buffered);
128
+ }
129
+ return Promise.resolve(selection);
130
+ }
131
+
132
+ public async removeRecords(records:Array<string>, buffered: boolean = false): Promise<Array<string>> {
133
+ if (records) {
134
+ if (buffered || !this.removeLoader) {
135
+ this.dispatchAction(Action.RECORDS_REMOVED, { records, buffered: true });
136
+ } else {
137
+ this.dispatchAction(Action.REMOVING_RECORDS);
138
+ return new Promise((resolve, fail) => {
139
+ if (this.removeLoader) {
140
+ this.removeLoader(this, records).then(
141
+ records => {
142
+ this.dispatchAction(Action.RECORDS_REMOVED, { records, buffered: false });
143
+ resolve(records);
144
+ }
145
+ ).catch(error => fail(error));
146
+ }
147
+ });
148
+ }
149
+ }
150
+ return Promise.resolve(records);
151
+ }
152
+
153
+ // API
154
+ public valueFromString(fieldName: string, value: string): any {
155
+ const descriptor: FieldDescriptor | undefined = this.getField(fieldName);
156
+ return descriptor ? convertType(descriptor.dataType, value) : value;
157
+ }
158
+
159
+ public addInterceptor(interceptor: DUActionInterceptor): void {
160
+ this._interceptors.push(interceptor);
161
+ }
162
+
163
+ public addFilterProvider(provider: FilterProvider): void {
164
+ this._filterProviders.push(provider);
165
+ }
166
+
167
+ public set sortingProvider(provider: SortingProvider) {
168
+ this._sortingProvider = provider;
169
+ }
170
+
171
+ public set metadata(md: UnitMetadata) {
172
+ this.dispatchAction(Action.METADATA_LOADED, md);
173
+ }
174
+
175
+ public get metadata(): UnitMetadata {
176
+ return getMetadata(this._stateManager);
177
+ }
178
+
179
+ public set records(r: Array<Record>) {
180
+ this.dispatchAction(Action.DATA_LOADED, r);
181
+ }
182
+
183
+ public get records(): Array<Record> {
184
+ const records = getCurrentRecords(this._stateManager);
185
+ return records ? Array.from(records.values()) : [];
186
+ }
187
+
188
+ public getField(fieldName: string): FieldDescriptor | undefined {
189
+ return getField(this._stateManager, fieldName);
190
+ }
191
+
192
+ public addRecord(): void {
193
+ this.dispatchAction(Action.RECORDS_ADDED, prepareAddedRecordId(this._stateManager, [{}]));
194
+ }
195
+
196
+ public copySelected(): void {
197
+ const selectedRecords = this.getSelectedRecords();
198
+ if (selectedRecords) {
199
+ this.dispatchAction(Action.RECORDS_COPIED, prepareAddedRecordId(this._stateManager, selectedRecords));
200
+ }
201
+ }
202
+
203
+ public getFieldValue(fieldName: string): any {
204
+ return getFieldValue(this._stateManager, fieldName);
205
+ }
206
+
207
+ public setFieldValue(fieldName: string, newValue: any, records?: Array<string>): void {
208
+
209
+ const typedValue = this.validateAndTypeValue(fieldName, newValue);
210
+ const currentValue = this.getFieldValue(fieldName);
211
+
212
+ if (currentValue !== typedValue) {
213
+ this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records });
214
+ }
215
+ }
216
+
217
+ public getSelection(): Array<string> {
218
+ return getSelection(this._stateManager);
219
+ }
220
+
221
+ public setSelection(selection: Array<string>): void {
222
+ this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection });
223
+ }
224
+
225
+ public setSelectionByIndex(selection: Array<number>): void {
226
+ this.dispatchAction(Action.SELECTION_CHANGED, { type: "index", selection });
227
+ }
228
+
229
+ public getSelectedRecords(): Array<Record> | undefined {
230
+ const selection: Array<string> = this.getSelection();
231
+ if (selection) {
232
+ const currentRecords: Array<Record> = this.records;
233
+ return currentRecords?.filter(r => selection.includes(r.__record__id__));
234
+ }
235
+ }
236
+
237
+ public nextRecord(): void {
238
+ this.dispatchAction(Action.NEXT_SELECTED);
239
+ }
240
+
241
+ public previousRecord(): void {
242
+ this.dispatchAction(Action.PREVIOUS_SELECTED);
243
+ }
244
+
245
+ public cancelEdition(): void {
246
+ this.dispatchAction(Action.EDITION_CANCELED);
247
+ }
248
+
249
+ public isDirty(): boolean {
250
+ return isDirty(this._stateManager);
251
+ }
252
+
253
+ public hasNext(): boolean {
254
+ return hasNext(this._stateManager);
255
+ }
256
+
257
+ public hasPrevious(): boolean {
258
+ return hasPrevious(this._stateManager);
259
+ }
260
+
261
+ public canUndo(): boolean {
262
+ return canUndo(this._stateManager);
263
+ }
264
+
265
+ public canRedo(): boolean {
266
+ return canRedo(this._stateManager);
267
+ }
268
+
269
+ public undo() {
270
+ this.dispatchAction(Action.CHANGE_UNDONE);
271
+ }
272
+
273
+ public redo() {
274
+ this.dispatchAction(Action.CHANGE_REDONE);
275
+ }
276
+
277
+ public toString() {
278
+ return this.name;
279
+ }
280
+
281
+ // Actions / State manager
282
+ private dispatchAction(actionType: Action, payload?: any): void {
283
+ let action = new DataUnitAction(actionType, payload);
284
+
285
+ this._interceptors?.forEach(interceptor => {
286
+ if (action) {
287
+ action = interceptor.interceptAction(action);
288
+ }
289
+ });
290
+
291
+ if (action) {
292
+ this._stateManager.process(action);
293
+ this._observers.forEach(f => f(action));
294
+ }
295
+ }
296
+
297
+ public subscribe(observer: (action: DataUnitAction) => void) {
298
+ this._observers.push(observer);
299
+ }
300
+
301
+ public unsubscribe(observer: Function) {
302
+ this._observers = this._observers.filter(f => f !== observer);
303
+ }
304
+ }
305
+
306
+ export interface DUActionInterceptor {
307
+ interceptAction(action: DataUnitAction): DataUnitAction;
308
+ }
309
+
310
+ export interface Record {
311
+ __record__id__: string;
312
+ __parent__record__id__?: string;
313
+ [key: string]: any;
314
+ }
315
+
316
+ export interface SavedRecord extends Record {
317
+ __old__id__?: string;
318
+ }
319
+
320
+ export enum ChangeOperation {
321
+ INSERT = "INSERT",
322
+ UPDATE = "UPDATE",
323
+ DELETE = "DELETE"
324
+ }
325
+
326
+ export class Change {
327
+
328
+ public dataUnit: string;
329
+ public record: Record;
330
+ public updatingFields: any;
331
+
332
+ private _operation: ChangeOperation;
333
+
334
+ constructor(dataUnit: string, record: Record, updates: any, operation: ChangeOperation) {
335
+ this.dataUnit = dataUnit;
336
+ this.record = record;
337
+ this.updatingFields = updates;
338
+ this._operation = operation;
339
+ }
340
+
341
+ public get operation(): string {
342
+ return this._operation.toString();
343
+ }
344
+
345
+ public isInsert(): boolean {
346
+ return this._operation === ChangeOperation.INSERT;
347
+ }
348
+
349
+ public isDelete(): boolean {
350
+ return this._operation === ChangeOperation.DELETE;
351
+ }
352
+
353
+ public isUpdate(): boolean {
354
+ return this._operation === ChangeOperation.UPDATE;
355
+ }
356
+
334
357
  }