@sankhyalabs/core 1.0.71 → 2.0.0

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 (75) hide show
  1. package/.eslintrc.cjs +2 -1
  2. package/dist/dataunit/DataUnit.d.ts +35 -18
  3. package/dist/dataunit/DataUnit.js +236 -93
  4. package/dist/dataunit/DataUnit.js.map +1 -1
  5. package/dist/dataunit/loading/LoadDataRequest.d.ts +9 -0
  6. package/dist/dataunit/loading/LoadDataRequest.js +2 -0
  7. package/dist/dataunit/loading/LoadDataRequest.js.map +1 -0
  8. package/dist/dataunit/loading/LoadDataResponse.d.ts +6 -0
  9. package/dist/dataunit/loading/LoadDataResponse.js +2 -0
  10. package/dist/dataunit/loading/LoadDataResponse.js.map +1 -0
  11. package/dist/dataunit/loading/PaginationInfo.d.ts +7 -0
  12. package/dist/dataunit/loading/PaginationInfo.js +2 -0
  13. package/dist/dataunit/loading/PaginationInfo.js.map +1 -0
  14. package/dist/dataunit/metadata/DataType.d.ts +1 -0
  15. package/dist/dataunit/metadata/DataType.js +14 -3
  16. package/dist/dataunit/metadata/DataType.js.map +1 -1
  17. package/dist/dataunit/state/action/DataUnitAction.d.ts +7 -1
  18. package/dist/dataunit/state/action/DataUnitAction.js +2 -0
  19. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  20. package/dist/dataunit/state/slice/ChangesSlice.d.ts +1 -0
  21. package/dist/dataunit/state/slice/ChangesSlice.js +3 -0
  22. package/dist/dataunit/state/slice/ChangesSlice.js.map +1 -1
  23. package/dist/dataunit/state/slice/LoadingControlSlice.d.ts +19 -0
  24. package/dist/dataunit/state/slice/LoadingControlSlice.js +45 -0
  25. package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -0
  26. package/dist/dataunit/state/slice/RecordsSlice.js +10 -2
  27. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  28. package/dist/dataunit/state/slice/SelectionSlice.js +0 -4
  29. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  30. package/dist/dataunit/state/slice/WaitingChangesSlice.js.map +1 -1
  31. package/dist/exceptions/ErrorException.d.ts +2 -1
  32. package/dist/exceptions/ErrorException.js +2 -1
  33. package/dist/exceptions/ErrorException.js.map +1 -1
  34. package/dist/exceptions/WarningException.d.ts +2 -1
  35. package/dist/exceptions/WarningException.js +2 -1
  36. package/dist/exceptions/WarningException.js.map +1 -1
  37. package/dist/index.d.ts +7 -3
  38. package/dist/index.js +3 -2
  39. package/dist/index.js.map +1 -1
  40. package/dist/ui/FloatingManager.d.ts +10 -0
  41. package/dist/ui/FloatingManager.js +62 -1
  42. package/dist/ui/FloatingManager.js.map +1 -1
  43. package/dist/utils/ArrayUtils.d.ts +14 -0
  44. package/dist/utils/ArrayUtils.js +30 -0
  45. package/dist/utils/ArrayUtils.js.map +1 -0
  46. package/dist/utils/DateUtils.d.ts +2 -0
  47. package/dist/utils/DateUtils.js +14 -0
  48. package/dist/utils/DateUtils.js.map +1 -1
  49. package/dist/utils/NumberUtils.d.ts +17 -0
  50. package/dist/utils/NumberUtils.js +27 -0
  51. package/dist/utils/NumberUtils.js.map +1 -1
  52. package/dist/utils/StringUtils.d.ts +14 -2
  53. package/dist/utils/StringUtils.js +30 -2
  54. package/dist/utils/StringUtils.js.map +1 -1
  55. package/jest.config.ts +4 -4
  56. package/package.json +1 -1
  57. package/src/dataunit/DataUnit.ts +258 -102
  58. package/src/dataunit/loading/LoadDataRequest.ts +10 -0
  59. package/src/dataunit/loading/LoadDataResponse.ts +7 -0
  60. package/src/dataunit/loading/PaginationInfo.ts +8 -0
  61. package/src/dataunit/metadata/DataType.ts +28 -15
  62. package/src/dataunit/state/action/DataUnitAction.ts +8 -1
  63. package/src/dataunit/state/slice/ChangesSlice.ts +4 -0
  64. package/src/dataunit/state/slice/LoadingControlSlice.ts +60 -0
  65. package/src/dataunit/state/slice/RecordsSlice.ts +12 -5
  66. package/src/dataunit/state/slice/SelectionSlice.ts +0 -5
  67. package/src/dataunit/state/slice/WaitingChangesSlice.ts +0 -1
  68. package/src/exceptions/ErrorException.ts +3 -1
  69. package/src/exceptions/WarningException.ts +4 -1
  70. package/src/index.ts +15 -3
  71. package/src/ui/FloatingManager.ts +75 -5
  72. package/src/utils/ArrayUtils.ts +32 -0
  73. package/src/utils/DateUtils.ts +19 -3
  74. package/src/utils/NumberUtils.ts +33 -0
  75. package/src/utils/StringUtils.ts +35 -3
@@ -1,21 +1,25 @@
1
- import { UnitMetadata, FieldDescriptor, SortingProvider, FilterProvider, Sort, Filter } from "./metadata/UnitMetadata.js";
2
1
  import { convertType, toString } from "./metadata/DataType.js";
2
+ import { FieldDescriptor, Filter, FilterProvider, Sort, SortingProvider, UnitMetadata } from "./metadata/UnitMetadata.js";
3
3
 
4
- import { DataUnitAction, Action } from "./state/action/DataUnitAction.js";
4
+ import { Action, DataUnitAction, ExecutionContext } from "./state/action/DataUnitAction.js";
5
5
  import StateManager from "./state/StateManager.js";
6
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, prepareCopiedRecord } from "./state/slice/AddedRecordsSlice.js";
14
- import { CurrentRecordsReducer, getCurrentRecords, getFieldValue, getModifiedRecords } from "./state/slice/CurrentRecordsSlice.js";
15
- import { getBlockingWaitingChanges, getWaitingChangePromisses, getWaitingChanges, isWaiting, WaitingChangesReducer } from "./state/slice/WaitingChangesSlice.js";
16
- import WaitingChangeException from "../exceptions/WaitingChangeException.js";
17
7
  import ErrorException from "../exceptions/ErrorException.js";
8
+ import WaitingChangeException from "../exceptions/WaitingChangeException.js";
18
9
  import { StringUtils } from "../utils/StringUtils.js";
10
+ import { LoadDataRequest } from "./loading/LoadDataRequest.js";
11
+ import { LoadDataResponse } from "./loading/LoadDataResponse.js";
12
+ import { PaginationInfo } from "./loading/PaginationInfo.js";
13
+ import { AddedRecordsReducer, prepareAddedRecordId, prepareCopiedRecord } from "./state/slice/AddedRecordsSlice.js";
14
+ import { ChangesReducer, getChangesToSave, isDirty, hasDirtyRecords } from "./state/slice/ChangesSlice.js";
15
+ import { CurrentRecordsReducer, getCurrentRecords, getFieldValue, getModifiedRecords } from "./state/slice/CurrentRecordsSlice.js";
16
+ import { getCurrentPage, getLastPage, getPaginationInfo, getCurrentRequest, LoadingControlReducer, hasMorePages, hasPreviousPages } from "./state/slice/LoadingControlSlice.js";
17
+ import { RecordsReducer } from "./state/slice/RecordsSlice.js";
18
+ import { RemovedRecordsReducer } from "./state/slice/RemovedRecordsSlice.js";
19
+ import { getSelection, hasNext, hasPrevious, SelectionReducer } from "./state/slice/SelectionSlice.js";
20
+ import { getField, getMetadata, UnitMetadataReducer } from "./state/slice/UnitMetadataSlice.js";
21
+ import { getBlockingWaitingChanges, getWaitingChangePromisses, isWaiting, WaitingChangesReducer } from "./state/slice/WaitingChangesSlice.js";
22
+ import { canRedo, canUndo, HistReducer } from "./state/HistReducer.js";
19
23
 
20
24
  export default class DataUnit {
21
25
 
@@ -25,18 +29,22 @@ export default class DataUnit {
25
29
  private _filterProviders: Map<string, FilterProvider>;
26
30
  private _stateManager: StateManager;
27
31
  private _interceptors: Array<DUActionInterceptor>;
32
+ private _pageSize: number;
28
33
 
29
34
  public metadataLoader?: (dataUnit: DataUnit) => Promise<UnitMetadata>;
30
- public dataLoader?: (dataUnit: DataUnit, page?: PageRequest, sort?: Array<Sort>, filters?: Array<Filter>) => Promise<PageResponse>;
35
+ public dataLoader?: (dataUnit: DataUnit, request: LoadDataRequest) => Promise<LoadDataResponse>;
31
36
  public saveLoader?: (dataUnit: DataUnit, changes: Array<Change>) => Promise<Array<SavedRecord>>;
32
37
  public removeLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<string>>;
38
+ public recordLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<Record>>;
33
39
 
34
40
  constructor(name: string) {
35
41
  this._name = name;
42
+ this._pageSize = 0;
36
43
  this._stateManager = new StateManager(
37
44
  [
38
45
  HistReducer,
39
46
  UnitMetadataReducer,
47
+ LoadingControlReducer,
40
48
  RecordsReducer,
41
49
  RemovedRecordsReducer,
42
50
  AddedRecordsReducer,
@@ -58,7 +66,6 @@ export default class DataUnit {
58
66
 
59
67
  // Métodos privados
60
68
  private validateAndTypeValue(fieldName: string, newValue: any): any {
61
- //FIXME: Validações devem ser feitas aqui
62
69
  const descriptor: FieldDescriptor | undefined = this.getField(fieldName);
63
70
  return descriptor ? convertType(descriptor.dataType, newValue) : newValue;
64
71
  }
@@ -78,16 +85,34 @@ export default class DataUnit {
78
85
  return this._sortingProvider ? this._sortingProvider.getSort(this._name) : undefined;
79
86
  }
80
87
 
81
- private getFielterProviderKey(provider:FilterProvider):string{
82
- if(provider.getKey){
88
+ private getFielterProviderKey(provider: FilterProvider): string {
89
+ if (provider.getKey) {
83
90
  return provider.getKey();
84
91
  }
85
92
  return StringUtils.hashCode(provider.getFilter.toString());
86
93
  }
87
94
 
95
+ private executeLoadData(request: LoadDataRequest, executionCtx?: ExecutionContext): Promise<LoadDataResponse> {
96
+ return new Promise(async (resolve, fail) => {
97
+ if (await this.dispatchAction(Action.LOADING_DATA, request, executionCtx)) {
98
+ if (this.dataLoader) {
99
+ this.dataLoader(this, request).then(
100
+ response => {
101
+ this.dispatchAction(Action.DATA_LOADED, response, executionCtx);
102
+ resolve(response);
103
+ }
104
+ ).catch(error => {
105
+ const {errorCode} = error;
106
+ fail(new ErrorException("Problema carregando registros", error, errorCode))
107
+ });
108
+ }
109
+ }
110
+ });
111
+ }
112
+
88
113
  // Loaders
89
- public async loadMetadata(): Promise<UnitMetadata|void> {
90
- if(this.dispatchAction(Action.LOADING_METADATA)){
114
+ public async loadMetadata(executionCtx?: ExecutionContext): Promise<UnitMetadata | void> {
115
+ if (await this.dispatchAction(Action.LOADING_METADATA, undefined, executionCtx)) {
91
116
  return new Promise((resolve, fail) => {
92
117
  if (this.metadataLoader) {
93
118
  this.metadataLoader(this).then(
@@ -95,30 +120,60 @@ export default class DataUnit {
95
120
  this.metadata = metadata
96
121
  resolve(this.metadata);
97
122
  }
98
- ).catch(error => fail(new ErrorException("Problema carregando metadados", error)));
123
+ ).catch(error => {
124
+ const {errorCode} = error;
125
+ fail(new ErrorException("Problema carregando metadados", error, errorCode))
126
+ });
99
127
  }
100
128
  });
101
129
  }
102
130
  }
103
131
 
104
- public async loadData(page?: PageRequest): Promise<PageResponse|void> {
105
- if(this.dispatchAction(Action.LOADING_DATA)){
106
- return new Promise((resolve, fail) => {
107
- if (this.dataLoader) {
108
- const sort = this.getSort();
109
- const filters = this.getFilters();
110
- this.dataLoader(this, page, sort, filters).then(
111
- pageRes => {
112
- this.records = pageRes.records;
113
- resolve(pageRes);
114
- }
115
- ).catch(error => fail(new ErrorException("Problema carregando registros", error)));
116
- }
117
- });
132
+ public async loadData(quickFilter?: QuickFilter, executionCtx?: ExecutionContext): Promise<LoadDataResponse> {
133
+
134
+ const loadDataRequest: LoadDataRequest = {
135
+ quickFilter,
136
+ filters: this.getFilters(),
137
+ sort: this.getSort()
138
+ };
139
+
140
+ if (this._pageSize > 0) {
141
+ loadDataRequest.limit = this._pageSize
142
+ loadDataRequest.offset = 0;
143
+ }
144
+
145
+ return this.executeLoadData(loadDataRequest, executionCtx);
146
+ }
147
+
148
+ public async gotoPage(page: number, executionCtx?: ExecutionContext): Promise<LoadDataResponse | void> {
149
+
150
+ let request = getCurrentRequest(this._stateManager);
151
+
152
+ if (!request) {
153
+ request = {
154
+ filters: this.getFilters(),
155
+ sort: this.getSort()
156
+ }
157
+ }
158
+
159
+ if (page >= 0 && page <= getLastPage(this._stateManager, this._pageSize)) {
160
+ return this.executeLoadData({
161
+ ...request,
162
+ limit: this._pageSize,
163
+ offset: page * this._pageSize
164
+ }, executionCtx);
118
165
  }
119
166
  }
120
167
 
121
- public async saveData(): Promise<void> {
168
+ public async nextPage(executionCtx?: ExecutionContext): Promise<LoadDataResponse | void> {
169
+ return this.gotoPage(getCurrentPage(this._stateManager) + 1, executionCtx);
170
+ }
171
+
172
+ public async previousPage(executionCtx?: ExecutionContext): Promise<LoadDataResponse | void> {
173
+ return this.gotoPage(getCurrentPage(this._stateManager) - 1, executionCtx);
174
+ }
175
+
176
+ public async saveData(executionCtx?: ExecutionContext): Promise<void> {
122
177
  const blockingWaitingChanges = getBlockingWaitingChanges(this._stateManager);
123
178
 
124
179
  if (blockingWaitingChanges && blockingWaitingChanges.size > 0) {
@@ -126,8 +181,8 @@ export default class DataUnit {
126
181
  return Promise.reject(new WaitingChangeException("Aguardando alteração de campo", (waitingChange as WaitingChange).waitmessage));
127
182
  } else {
128
183
  if (isDirty(this._stateManager)) {
129
-
130
- if (this.dispatchAction(Action.SAVING_DATA)) {
184
+
185
+ if (await this.dispatchAction(Action.SAVING_DATA, undefined, executionCtx)) {
131
186
  const promisses = getWaitingChangePromisses(this._stateManager);
132
187
  return new Promise((resolve, fail) => {
133
188
  Promise.all(promisses || []).then(() => {
@@ -135,10 +190,13 @@ export default class DataUnit {
135
190
  const changes: Array<Change> = getChangesToSave(this._name, this._stateManager);
136
191
  this.saveLoader(this, changes).then(
137
192
  records => {
138
- this.dispatchAction(Action.DATA_SAVED, { changes, records });
193
+ this.dispatchAction(Action.DATA_SAVED, { changes, records }, executionCtx);
139
194
  resolve();
140
195
  }
141
- ).catch(cause => fail(new ErrorException("Erro salvando alterações", cause)));
196
+ ).catch(cause => {
197
+ const {errorCode} = cause;
198
+ fail(new ErrorException("Erro salvando alterações", cause, errorCode));
199
+ });
142
200
  } else {
143
201
  resolve();
144
202
  }
@@ -154,44 +212,48 @@ export default class DataUnit {
154
212
  public async removeSelectedRecords(buffered: boolean = false): Promise<Array<string>> {
155
213
  const selection = getSelection(this._stateManager);
156
214
  if (selection) {
157
- return this.removeRecords(selection, buffered);
215
+ const records = this.getSelectedRecords() || [];
216
+ return this.removeRecords(selection, records, buffered);
158
217
  }
159
218
  return Promise.resolve(selection);
160
219
  }
161
220
 
162
- public async removeRecords(records: Array<string>, buffered: boolean = false): Promise<Array<string>> {
163
- if (records) {
221
+ public async removeRecords(recordIds: Array<string>, cachedRecords: Array<Record>, buffered: boolean = false, executionCtx?: ExecutionContext): Promise<Array<string>> {
222
+ if (recordIds) {
164
223
  if (buffered || !this.removeLoader) {
165
- this.dispatchAction(Action.RECORDS_REMOVED, { records, buffered: true });
224
+ this.dispatchAction(Action.RECORDS_REMOVED, { records: recordIds, cachedRecords, buffered: true }, executionCtx);
166
225
  } else {
167
- if (this.dispatchAction(Action.REMOVING_RECORDS)) {
226
+ if (await this.dispatchAction(Action.REMOVING_RECORDS, undefined, executionCtx)) {
168
227
 
169
228
  return new Promise((resolve, fail) => {
170
229
  if (this.removeLoader) {
171
- this.removeLoader(this, records).then(
172
- records => {
230
+ this.removeLoader(this, recordIds).then(
231
+ removedIds => {
173
232
  let currentIndex = 0;
174
233
  const removedIndex: Array<number> = [];
175
234
  const currentRecords = getCurrentRecords(this._stateManager);
176
235
 
177
236
  currentRecords.forEach((value, key) => {
178
- if (records.includes(key)) {
237
+ if (removedIds.includes(key)) {
179
238
  removedIndex.push(currentIndex);
180
239
  }
181
240
 
182
241
  currentIndex++
183
242
  });
184
243
 
185
- this.dispatchAction(Action.RECORDS_REMOVED, { records, removedIndex, buffered: false });
186
- resolve(records);
244
+ this.dispatchAction(Action.RECORDS_REMOVED, { records: removedIds, cachedRecords, removedIndex, buffered: false }, executionCtx);
245
+ resolve(removedIds);
187
246
  }
188
- ).catch(error => fail(new ErrorException("Problema removendo registros", error)));
247
+ ).catch(error => {
248
+ const {errorCode} = error;
249
+ fail(new ErrorException("Problema removendo registros", error, errorCode))
250
+ });
189
251
  }
190
252
  });
191
253
  }
192
254
  }
193
255
  }
194
- return Promise.resolve(records);
256
+ return Promise.resolve(recordIds);
195
257
  }
196
258
 
197
259
  // API
@@ -217,12 +279,16 @@ export default class DataUnit {
217
279
  this._filterProviders.set(this.getFielterProviderKey(provider), provider);
218
280
  }
219
281
 
282
+ public getPaginationInfo(): PaginationInfo | void {
283
+ return getPaginationInfo(this._stateManager);
284
+ }
285
+
220
286
  public set sortingProvider(provider: SortingProvider) {
221
287
  this._sortingProvider = provider;
222
288
  }
223
289
 
224
290
  public set metadata(md: UnitMetadata) {
225
- this.dispatchAction(Action.METADATA_LOADED, md);
291
+ this.dispatchAction(Action.METADATA_LOADED, md, undefined);
226
292
  }
227
293
 
228
294
  public get metadata(): UnitMetadata {
@@ -230,7 +296,7 @@ export default class DataUnit {
230
296
  }
231
297
 
232
298
  public set records(r: Array<Record>) {
233
- this.dispatchAction(Action.DATA_LOADED, r);
299
+ this.dispatchAction(Action.DATA_LOADED, { records: this.records }, undefined);
234
300
  }
235
301
 
236
302
  public get records(): Array<Record> {
@@ -238,6 +304,14 @@ export default class DataUnit {
238
304
  return records ? Array.from(records.values()) : [];
239
305
  }
240
306
 
307
+ public set pageSize(size: number) {
308
+ this._pageSize = size;
309
+ }
310
+
311
+ public get pageSize(): number {
312
+ return this._pageSize;
313
+ }
314
+
241
315
  public getModifiedRecords(): Array<Record> {
242
316
  const modified = getModifiedRecords(this._stateManager);
243
317
  return modified || [];
@@ -247,14 +321,14 @@ export default class DataUnit {
247
321
  return getField(this._stateManager, fieldName);
248
322
  }
249
323
 
250
- public addRecord(): void {
251
- this.dispatchAction(Action.RECORDS_ADDED, prepareAddedRecordId(this._stateManager, [{}]));
324
+ public addRecord(executionCtx?: ExecutionContext): void {
325
+ this.dispatchAction(Action.RECORDS_ADDED, prepareAddedRecordId(this._stateManager, [{}]), executionCtx);
252
326
  }
253
327
 
254
- public copySelected(): void {
328
+ public copySelected(executionCtx?: ExecutionContext): void {
255
329
  const selectedRecords = this.getSelectedRecords();
256
330
  if (selectedRecords) {
257
- this.dispatchAction(Action.RECORDS_COPIED, prepareCopiedRecord(this._stateManager, selectedRecords));
331
+ this.dispatchAction(Action.RECORDS_COPIED, prepareCopiedRecord(this._stateManager, selectedRecords), executionCtx);
258
332
  }
259
333
  }
260
334
 
@@ -272,38 +346,42 @@ export default class DataUnit {
272
346
  const currentValue = this.getFieldValue(fieldName);
273
347
 
274
348
  if (currentValue !== typedValue) {
275
- this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records });
349
+ this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records }, undefined);
276
350
  }
277
351
  }
278
352
 
279
353
  public startChange(fieldName: string, waitingChange: WaitingChange): void {
280
- this.dispatchAction(Action.CHANGING_DATA, { [fieldName]: waitingChange });
354
+ this.dispatchAction(Action.CHANGING_DATA, { [fieldName]: waitingChange }, undefined);
281
355
  }
282
356
 
283
357
  public cancelWaitingChange(fieldName: string): void {
284
- this.dispatchAction(Action.WAITING_CHANGE_CANCELED, { fieldName });
358
+ this.dispatchAction(Action.WAITING_CHANGE_CANCELED, { fieldName }, undefined);
285
359
  }
286
360
 
287
361
  public getSelection(): Array<string> {
288
362
  return getSelection(this._stateManager);
289
363
  }
290
364
 
291
- public setSelection(selection: Array<string>): void {
292
- this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection });
365
+ public setSelection(selection: Array<string>, executionCtx?: ExecutionContext): void {
366
+ this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection }, executionCtx);
293
367
  }
294
368
 
295
- public selectFirst(): void {
296
- if(this.records.length > 0){
297
- this.dispatchAction(Action.SELECTION_CHANGED, { type: "index", selection: [0] });
369
+ public selectFirst(executionCtx?: ExecutionContext): void {
370
+ if (this.records.length > 0) {
371
+ this.setSelectionByIndex([0], executionCtx);
298
372
  }
299
373
  }
300
374
 
301
- public selectLast(): void {
302
- if(this.records.length > 0){
303
- this.dispatchAction(Action.SELECTION_CHANGED, { type: "index", selection: [this.records.length - 1] });
375
+ public selectLast(executionCtx?: ExecutionContext): void {
376
+ if (this.records.length > 0) {
377
+ this.setSelectionByIndex([this.records.length - 1], executionCtx);
304
378
  }
305
379
  }
306
380
 
381
+ public setSelectionByIndex(selection: Array<number>, executionCtx?: ExecutionContext): void {
382
+ this.dispatchAction(Action.SELECTION_CHANGED, { type: "index", selection }, executionCtx);
383
+ }
384
+
307
385
  public getSelectedRecords(): Array<Record> | undefined {
308
386
  const selection: Array<string> = this.getSelection();
309
387
  if (selection) {
@@ -312,28 +390,72 @@ export default class DataUnit {
312
390
  }
313
391
  }
314
392
 
315
- public nextRecord(): void {
316
- this.dispatchAction(Action.NEXT_SELECTED);
393
+ public nextRecord(executionCtx?: ExecutionContext): void {
394
+ if(!hasNext(this._stateManager)){
395
+ if(hasMorePages(this._stateManager)){
396
+ this.nextPage({
397
+ before: act =>{
398
+ if(executionCtx && executionCtx.before){
399
+ act = executionCtx.before(act);
400
+ }
401
+ return act;
402
+ },
403
+ after: act => {
404
+ this.selectFirst(executionCtx);
405
+ }
406
+ });
407
+ }
408
+ } else {
409
+ this.dispatchAction(Action.NEXT_SELECTED, undefined, executionCtx);
410
+ }
317
411
  }
318
412
 
319
- public previousRecord(): void {
320
- this.dispatchAction(Action.PREVIOUS_SELECTED);
413
+ public previousRecord(executionCtx?: ExecutionContext): void {
414
+ if(!hasPrevious(this._stateManager)){
415
+ if(hasPreviousPages(this._stateManager)){
416
+ this.previousPage({
417
+ before: act =>{
418
+ if(executionCtx && executionCtx.before){
419
+ act = executionCtx.before(act);
420
+ }
421
+ return act;
422
+ },
423
+ after: act => {
424
+ this.selectLast(executionCtx);
425
+ }
426
+ });
427
+ }
428
+ } else {
429
+ this.dispatchAction(Action.PREVIOUS_SELECTED, undefined, executionCtx);
430
+ }
321
431
  }
322
432
 
323
- public cancelEdition(): void {
324
- this.dispatchAction(Action.EDITION_CANCELED);
433
+ public cancelEdition(executionCtx?: ExecutionContext): void {
434
+ this.dispatchAction(Action.EDITION_CANCELED, undefined, executionCtx);
325
435
  }
326
436
 
327
437
  public isDirty(): boolean {
328
438
  return isDirty(this._stateManager);
329
439
  }
330
440
 
441
+ public hasDirtyRecords(): boolean {
442
+ return hasDirtyRecords(this._stateManager);
443
+ }
444
+
331
445
  public hasNext(): boolean {
332
- return hasNext(this._stateManager);
446
+ let result = hasNext(this._stateManager);
447
+ if(!result){
448
+ result = hasMorePages(this._stateManager);
449
+ }
450
+ return result;
333
451
  }
334
452
 
335
453
  public hasPrevious(): boolean {
336
- return hasPrevious(this._stateManager);
454
+ let result = hasPrevious(this._stateManager);
455
+ if(!result){
456
+ result = hasPreviousPages(this._stateManager);
457
+ }
458
+ return result;
337
459
  }
338
460
 
339
461
  public canUndo(): boolean {
@@ -344,12 +466,12 @@ export default class DataUnit {
344
466
  return canRedo(this._stateManager);
345
467
  }
346
468
 
347
- public undo() {
348
- this.dispatchAction(Action.CHANGE_UNDONE);
469
+ public undo(executionCtx?: ExecutionContext) {
470
+ this.dispatchAction(Action.CHANGE_UNDONE, undefined, executionCtx);
349
471
  }
350
472
 
351
- public redo() {
352
- this.dispatchAction(Action.CHANGE_REDONE);
473
+ public redo(executionCtx?: ExecutionContext) {
474
+ this.dispatchAction(Action.CHANGE_REDONE, undefined, executionCtx);
353
475
  }
354
476
 
355
477
  public toString() {
@@ -357,33 +479,50 @@ export default class DataUnit {
357
479
  }
358
480
 
359
481
  // Actions / State manager
360
- private dispatchAction(actionType: Action, payload?: any): boolean {
361
- let action = new DataUnitAction(actionType, payload);
362
-
363
- this._interceptors?.forEach(interceptor => {
482
+ private async dispatchAction(actionType: Action, payload?: any, executionCtx?: ExecutionContext): Promise<boolean> {
483
+ return new Promise(async resolve => {
484
+ let action = new DataUnitAction(actionType, payload);
485
+ if (executionCtx && executionCtx.before) {
486
+ action = executionCtx.before(action);
487
+ }
488
+ if (action && this._interceptors && this._interceptors.length > 0) {
489
+ action = await this.intercept(action, this._interceptors.values());
490
+ }
364
491
  if (action) {
365
- action = interceptor.interceptAction(action);
492
+ this.doDispatchAction(action);
493
+ if (executionCtx && executionCtx.after) {
494
+ executionCtx.after(action)
495
+ }
496
+ resolve(true);
497
+ } else {
498
+ resolve(false);
366
499
  }
367
500
  });
501
+ }
368
502
 
369
- if (!action) {
370
- return false;
371
- } else {
503
+ private async intercept(action: DataUnitAction, interceptors: IterableIterator<DUActionInterceptor>): Promise<DataUnitAction> {
504
+ return new Promise(async resolve => {
505
+ let ite;
506
+ while (action && !(ite = interceptors.next()).done) {
507
+ action = await ite.value.interceptAction(action);
508
+ }
509
+ resolve(action);
510
+ });
511
+ }
372
512
 
373
- this._stateManager.process(action);
374
- this._observers.forEach(f => {
375
- /*
376
- if some observer throws exceptions,
377
- should be continued
378
- */
379
- try {
380
- f(action);
381
- } catch (e) {
382
- console.warn("[DataUnit] error while call observer", e);
383
- }
384
- });
385
- }
386
- return true;
513
+ private doDispatchAction(action: DataUnitAction) {
514
+ this._stateManager.process(action);
515
+ this._observers.forEach(f => {
516
+ /*
517
+ if some observer throws exceptions,
518
+ should be continued
519
+ */
520
+ try {
521
+ f(action);
522
+ } catch (e) {
523
+ console.warn("[DataUnit] error while call observer", e);
524
+ }
525
+ });
387
526
  }
388
527
 
389
528
  public subscribe(observer: (action: DataUnitAction) => void) {
@@ -393,10 +532,27 @@ export default class DataUnit {
393
532
  public unsubscribe(observer: Function) {
394
533
  this._observers = this._observers.filter(f => f !== observer);
395
534
  }
535
+
536
+ public reloadCurrentRecord(): Promise<Array<Record>>{
537
+ return new Promise(async (resolve, fail) => {
538
+ const selection = this.getSelection();
539
+ this.dispatchAction(Action.LOADING_RECORD, selection);
540
+
541
+ if(!this.dataLoader) return;
542
+ if(!this.recordLoader) return;
543
+
544
+ this.recordLoader(this, selection).then(response => {
545
+ this.dispatchAction(Action.RECORD_LOADED, response)
546
+ }).catch(cause => {
547
+ const {errorCode} = cause;
548
+ fail(new ErrorException("Erro recarregando registro", cause, errorCode));
549
+ });
550
+ });
551
+ }
396
552
  }
397
553
 
398
554
  export interface DUActionInterceptor {
399
- interceptAction(action: DataUnitAction): DataUnitAction;
555
+ interceptAction(action: DataUnitAction): DataUnitAction | Promise<DataUnitAction>;
400
556
  }
401
557
 
402
558
  export interface Record {
@@ -0,0 +1,10 @@
1
+ import { QuickFilter } from "../DataUnit.js";
2
+ import { Filter, Sort } from "../metadata/UnitMetadata.js";
3
+
4
+ export interface LoadDataRequest {
5
+ offset?: number;
6
+ limit?: number;
7
+ quickFilter?: QuickFilter;
8
+ filters?: Array<Filter>;
9
+ sort?: Array<Sort>;
10
+ }
@@ -0,0 +1,7 @@
1
+ import { Record } from "../DataUnit.js";
2
+ import { PaginationInfo } from "./PaginationInfo.js";
3
+
4
+ export interface LoadDataResponse {
5
+ records: Array<Record>;
6
+ paginationInfo?: PaginationInfo;
7
+ }
@@ -0,0 +1,8 @@
1
+
2
+ export interface PaginationInfo {
3
+ currentPage: number;
4
+ firstRecord: number;
5
+ lastRecord: number;
6
+ total: number;
7
+ hasMore: boolean;
8
+ }