@sankhyalabs/core 5.17.3 → 5.18.0-ms.1

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 (140) hide show
  1. package/.docs/classes/Change.md +11 -11
  2. package/.docs/classes/ColumnFilterManager.md +145 -0
  3. package/.docs/classes/DataUnit.md +334 -136
  4. package/.docs/classes/DataUnitInMemoryLoader.md +303 -0
  5. package/.docs/classes/DataUnitLoaderUtils.md +151 -0
  6. package/.docs/classes/FieldComparator.md +2 -2
  7. package/.docs/classes/IDBRepository.md +22 -0
  8. package/.docs/classes/LockManager.md +249 -0
  9. package/.docs/classes/MaskFormatter.md +66 -14
  10. package/.docs/classes/ObjectUtils.md +95 -2
  11. package/.docs/classes/SelectionInfo.md +25 -11
  12. package/.docs/classes/ServiceCanceledException.md +193 -0
  13. package/.docs/classes/ServiceUtils.md +67 -0
  14. package/.docs/classes/SilentException.md +193 -0
  15. package/.docs/classes/UserAgentUtils.md +15 -1
  16. package/.docs/enumerations/Action.md +32 -22
  17. package/.docs/enumerations/ChangeOperation.md +4 -4
  18. package/.docs/enumerations/LockManagerOperation.md +33 -0
  19. package/.docs/enumerations/RECORD_DATE_FORMAT.md +27 -0
  20. package/.docs/enumerations/SelectionMode.md +2 -2
  21. package/.docs/enumerations/StorageType.md +37 -0
  22. package/.docs/globals.md +12 -0
  23. package/.docs/interfaces/DUActionInterceptor.md +1 -1
  24. package/.docs/interfaces/DataUnitInMemoryLoaderConfig.md +37 -0
  25. package/.docs/interfaces/IRepository.md +18 -0
  26. package/.docs/interfaces/LoadDataRequest.md +1 -1
  27. package/.docs/interfaces/PageRequest.md +3 -3
  28. package/.docs/interfaces/PaginationInfo.md +25 -0
  29. package/.docs/interfaces/PaginationInfoBuilderParams.md +37 -0
  30. package/.docs/interfaces/QuickFilter.md +3 -3
  31. package/.docs/interfaces/Record.md +4 -4
  32. package/.docs/interfaces/SavedRecord.md +5 -5
  33. package/.docs/interfaces/WaitingChange.md +3 -3
  34. package/.docs/namespaces/MaskFormatter/type-aliases/MaskCharacter.md +1 -1
  35. package/.docs/namespaces/MaskFormatter/variables/MaskCharacter.md +1 -1
  36. package/.docs/type-aliases/DataUnitEventOptions.md +1 -1
  37. package/.releaserc +1 -0
  38. package/bun.lockb +0 -0
  39. package/dist/dataunit/DataUnit.d.ts +60 -10
  40. package/dist/dataunit/DataUnit.js +156 -48
  41. package/dist/dataunit/DataUnit.js.map +1 -1
  42. package/dist/dataunit/formatting/PrettyFormatter.js +8 -2
  43. package/dist/dataunit/formatting/PrettyFormatter.js.map +1 -1
  44. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.d.ts +9 -0
  45. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js +6 -0
  46. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js.map +1 -0
  47. package/dist/dataunit/loader/dataUnitInMemoryLoader.d.ts +25 -0
  48. package/dist/dataunit/loader/dataUnitInMemoryLoader.js +131 -0
  49. package/dist/dataunit/loader/dataUnitInMemoryLoader.js.map +1 -0
  50. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.d.ts +20 -0
  51. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js +62 -0
  52. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js.map +1 -0
  53. package/dist/dataunit/loading/LoadDataRequest.d.ts +1 -1
  54. package/dist/dataunit/loading/PaginationInfo.d.ts +8 -0
  55. package/dist/dataunit/sorting/FieldComparator.d.ts +2 -2
  56. package/dist/dataunit/sorting/FieldComparator.js +4 -9
  57. package/dist/dataunit/sorting/FieldComparator.js.map +1 -1
  58. package/dist/dataunit/state/action/DataUnitAction.d.ts +1 -0
  59. package/dist/dataunit/state/action/DataUnitAction.js +1 -0
  60. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  61. package/dist/dataunit/state/slice/LoadingControlSlice.js +16 -0
  62. package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -1
  63. package/dist/dataunit/state/slice/RecordsSlice.js +1 -1
  64. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  65. package/dist/dataunit/state/slice/SelectionSlice.js +2 -2
  66. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  67. package/dist/exceptions/ServiceCanceledException.d.ts +14 -0
  68. package/dist/exceptions/ServiceCanceledException.js +13 -0
  69. package/dist/exceptions/ServiceCanceledException.js.map +1 -0
  70. package/dist/exceptions/SilentException.d.ts +14 -0
  71. package/dist/exceptions/SilentException.js +13 -0
  72. package/dist/exceptions/SilentException.js.map +1 -0
  73. package/dist/index.d.ts +10 -1
  74. package/dist/index.js +10 -1
  75. package/dist/index.js.map +1 -1
  76. package/dist/repository/IRepository.d.ts +6 -0
  77. package/dist/repository/indexeddb/IDBRepository.d.ts +1 -0
  78. package/dist/repository/indexeddb/IDBRepository.js +3 -0
  79. package/dist/repository/indexeddb/IDBRepository.js.map +1 -1
  80. package/dist/utils/CacheManager/index.d.ts +52 -0
  81. package/dist/utils/CacheManager/index.js +101 -0
  82. package/dist/utils/CacheManager/index.js.map +1 -0
  83. package/dist/utils/CacheManager/interfaces/index.d.ts +5 -0
  84. package/dist/utils/CacheManager/interfaces/index.js +7 -0
  85. package/dist/utils/CacheManager/interfaces/index.js.map +1 -0
  86. package/dist/utils/ColumnFilterManager.d.ts +19 -0
  87. package/dist/utils/ColumnFilterManager.js +73 -0
  88. package/dist/utils/ColumnFilterManager.js.map +1 -0
  89. package/dist/utils/LockManager.d.ts +58 -0
  90. package/dist/utils/LockManager.js +191 -0
  91. package/dist/utils/LockManager.js.map +1 -0
  92. package/dist/utils/MaskFormatter.d.ts +16 -1
  93. package/dist/utils/MaskFormatter.js +82 -2
  94. package/dist/utils/MaskFormatter.js.map +1 -1
  95. package/dist/utils/ObjectUtils.d.ts +24 -0
  96. package/dist/utils/ObjectUtils.js +33 -0
  97. package/dist/utils/ObjectUtils.js.map +1 -1
  98. package/dist/utils/ServiceUtils.d.ts +24 -0
  99. package/dist/utils/ServiceUtils.js +40 -0
  100. package/dist/utils/ServiceUtils.js.map +1 -0
  101. package/dist/utils/SortingUtils.d.ts +9 -0
  102. package/dist/utils/SortingUtils.js +24 -0
  103. package/dist/utils/SortingUtils.js.map +1 -0
  104. package/dist/utils/UserAgentUtils/index.d.ts +1 -0
  105. package/dist/utils/UserAgentUtils/index.js +5 -0
  106. package/dist/utils/UserAgentUtils/index.js.map +1 -1
  107. package/package.json +1 -1
  108. package/reports/test-report.xml +142 -78
  109. package/src/dataunit/DataUnit.ts +193 -64
  110. package/src/dataunit/formatting/PrettyFormatter.ts +10 -2
  111. package/src/dataunit/loader/DataUnitInMemoryLoaderConfig.ts +10 -0
  112. package/src/dataunit/loader/dataUnitInMemoryLoader.ts +176 -0
  113. package/src/dataunit/loader/utils/dataUnitLoaderUtils.ts +86 -0
  114. package/src/dataunit/loading/LoadDataRequest.ts +1 -1
  115. package/src/dataunit/loading/PaginationInfo.ts +10 -0
  116. package/src/dataunit/sorting/FieldComparator.ts +18 -32
  117. package/src/dataunit/state/action/DataUnitAction.ts +1 -0
  118. package/src/dataunit/state/slice/LoadingControlSlice.ts +42 -0
  119. package/src/dataunit/state/slice/RecordsSlice.ts +1 -1
  120. package/src/dataunit/state/slice/SelectionSlice.ts +2 -2
  121. package/src/dataunit/state/slice/test/RecordsSlice.spec.ts +45 -0
  122. package/src/dataunit/test/DataUnit.spec.ts +44 -0
  123. package/src/exceptions/ServiceCanceledException.ts +25 -0
  124. package/src/exceptions/SilentException.ts +25 -0
  125. package/src/index.ts +22 -1
  126. package/src/repository/IRepository.ts +7 -0
  127. package/src/repository/indexeddb/IDBRepository.ts +4 -0
  128. package/src/utils/CacheManager/index.ts +103 -0
  129. package/src/utils/CacheManager/interfaces/index.ts +5 -0
  130. package/src/utils/ColumnFilterManager.ts +104 -0
  131. package/src/utils/LockManager.ts +213 -0
  132. package/src/utils/MaskFormatter.ts +93 -2
  133. package/src/utils/ObjectUtils.ts +36 -0
  134. package/src/utils/ServiceUtils.ts +36 -0
  135. package/src/utils/SortingUtils.ts +30 -0
  136. package/src/utils/UserAgentUtils/index.ts +6 -1
  137. package/src/utils/test/objectUtils.spec.ts +109 -0
  138. package/test/dataunit/loader/dataUnitInMemoryLoader.spec.ts +221 -0
  139. package/test/dataunit/loader/utils/dataUnitLoaderUtils.spec.ts +158 -0
  140. package/test/util/ColumnFilterManager.spec.ts +133 -0
@@ -26,6 +26,9 @@ import { v4 as uuid } from "uuid";
26
26
  import { DataUnitStorage } from "./DataUnitStorage.js";
27
27
  import { getInvalidFieldMessage, InvalidFieldsReducer } from "./state/slice/InvalidFieldsSlice.js";
28
28
  import { getLoadingProperties, LoadingPropertiesReducer } from "./state/slice/LoadingProperties.js";
29
+ import SortingUtils from "../utils/SortingUtils.js";
30
+ import ServiceCanceledException from "../exceptions/ServiceCanceledException.js";
31
+ import SilentException from "../exceptions/SilentException.js";
29
32
 
30
33
  /***
31
34
  * `DataUnit`: Atua como uma camada de abstração entre o back-end e a interface do usuário.
@@ -33,11 +36,12 @@ import { getLoadingProperties, LoadingPropertiesReducer } from "./state/slice/Lo
33
36
  export default class DataUnit {
34
37
 
35
38
  public static CHANGING_PAGE_LOADING_SOURCE = "CHANGING_PAGE_LOADING_SOURCE";
39
+ public static ALL_RECORDS_SELECTION_SOURCE = "ALL_RECORDS_SELECTION_SOURCE";
36
40
  public static DEFAULT_DATAUNIT_NAME = "dataunit";
37
41
 
38
42
  private _uuid: string;
39
43
  private _name: string;
40
- private _observers: Array<(action: DataUnitAction, options?:DataUnitEventOptions) => void>;
44
+ private _observers: Map<string, (action: DataUnitAction, options?: DataUnitEventOptions) => void>;
41
45
  private _sortingProvider?: SortingProvider;
42
46
  private _filterProviders: Map<string, FilterProvider>;
43
47
  private _stateManager: StateManager;
@@ -49,12 +53,15 @@ export default class DataUnit {
49
53
  private _savingLockers: Promise<any>[] = [];
50
54
  private _defaultSorting: Array<Sort>;
51
55
  private _allowReleaseCallbacks: boolean;
56
+ private _waitingToReload: boolean = false;
57
+ private _cancelPagination: boolean = false;
52
58
 
53
59
  public metadataLoader?: (dataUnit: DataUnit) => Promise<UnitMetadata>;
54
60
  public dataLoader?: (dataUnit: DataUnit, request: LoadDataRequest) => Promise<LoadDataResponse>;
55
61
  public saveLoader?: (dataUnit: DataUnit, changes: Array<Change>) => Promise<Array<SavedRecord>>;
56
62
  public removeLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<string>>;
57
63
  public recordLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<Record>>;
64
+ public allRecordsLoader?: (dataUnit: DataUnit) => Array<Record> | undefined;
58
65
 
59
66
  constructor(name: string = DataUnit.DEFAULT_DATAUNIT_NAME, parentDataUnit?: DataUnit) {
60
67
  this._uuid = uuid()
@@ -76,7 +83,7 @@ export default class DataUnit {
76
83
  SnapshotReducer
77
84
  ]
78
85
  );
79
- this._observers = [];
86
+ this._observers = new Map();
80
87
  this._filterProviders = new Map<string, FilterProvider>();
81
88
  this._sortingProvider = undefined;
82
89
  this._defaultSorting = [];
@@ -114,7 +121,7 @@ export default class DataUnit {
114
121
  public releaseCallbacks(){
115
122
  if(!this._allowReleaseCallbacks) return;
116
123
 
117
- this._observers = [];
124
+ this._observers = new Map();
118
125
  this._filterProviders = new Map<string, FilterProvider>();
119
126
  this._sortingProvider = undefined;
120
127
  this._interceptors = new Map();
@@ -146,6 +153,36 @@ export default class DataUnit {
146
153
  return this._uuid;
147
154
  }
148
155
 
156
+
157
+ /**
158
+ * Retorna se o dataUnit está com recarregamento pendente.
159
+ */
160
+ public isWaitingToReload(): boolean {
161
+ return this._waitingToReload;
162
+ }
163
+
164
+ /**
165
+ * Define se o dataUnit tem um recarregamento pendente.
166
+ * @param isWaiting
167
+ */
168
+ public setWaitingToReload(isWaiting: boolean){
169
+ this._waitingToReload = isWaiting;
170
+ }
171
+
172
+ /**
173
+ * Informa se a paginação deve ser cancelada.
174
+ */
175
+ public get cancelPagination(): boolean {
176
+ return this._cancelPagination;
177
+ }
178
+
179
+ /**
180
+ * Informa se a paginação deve ser cancelada.
181
+ */
182
+ public set cancelPagination(cancelPagination: boolean) {
183
+ this._cancelPagination = cancelPagination;
184
+ }
185
+
149
186
  /**
150
187
  *
151
188
  * Obtém o nome de identificação do DataUnit (geralmente em formato de URI - Uniform Resource Identifier).
@@ -350,6 +387,9 @@ export default class DataUnit {
350
387
  *
351
388
  */
352
389
  public async gotoPage(page: number, executionCtx?: ExecutionContext): Promise<LoadDataResponse | void> {
390
+ if(this._pageSize === 0) {
391
+ return;
392
+ }
353
393
 
354
394
  let request = getCurrentRequest(this._stateManager);
355
395
 
@@ -482,6 +522,14 @@ export default class DataUnit {
482
522
  const {errorCode} = cause;
483
523
  this.dispatchAction(Action.SAVING_ERROR);
484
524
  this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
525
+ if(cause instanceof ServiceCanceledException){
526
+ console.debug("Service canceled: " + cause.message);
527
+ resolve();
528
+ }
529
+ if(cause instanceof SilentException){
530
+ fail(cause);
531
+ return;
532
+ }
485
533
  fail(new ErrorException("Erro ao salvar alterações", cause, errorCode));
486
534
  });
487
535
  } else {
@@ -551,8 +599,8 @@ export default class DataUnit {
551
599
  if(selection.isAllRecords()){
552
600
  throw new Error("Exclusão remota não implementada.");
553
601
  }
554
- const records = selection?.records || [];
555
- const recordIds = selection?.recordIds || [];
602
+ const records = selection?.records as Array<Record> || [];
603
+ const recordIds = selection?.recordIds as Array<string> || [];
556
604
  return this.removeRecords(recordIds, records, buffered, undefined, silent);
557
605
  }
558
606
  return Promise.resolve([]);
@@ -655,13 +703,13 @@ export default class DataUnit {
655
703
  */
656
704
  public getFormattedValue(fieldName: string, value?: any): string {
657
705
  const descriptor = this.getField(fieldName);
658
- if (value === undefined) {
706
+ if (value == undefined) {
659
707
  value = this.getFieldValue(fieldName);
660
708
  } else if (typeof value === "string" && descriptor?.dataType != DataType.TEXT){
661
709
  value = this.valueFromString(fieldName, value);
662
710
  }
663
711
 
664
- if(value === undefined){
712
+ if(value == undefined){
665
713
  return "";
666
714
  }
667
715
 
@@ -732,6 +780,7 @@ export default class DataUnit {
732
780
  return this.dispatchAction(Action.PAGINATION_UPDATED, info, undefined);
733
781
  }
734
782
 
783
+
735
784
  /**
736
785
  *
737
786
  * Define a lógica de ordenação dos registros.
@@ -796,7 +845,8 @@ export default class DataUnit {
796
845
  *
797
846
  */
798
847
  public set records(records: Array<Record>) {
799
- this.dispatchAction(Action.DATA_LOADED, { records }, undefined);
848
+ const paginationInfo = this.getPaginationInfo();
849
+ this.dispatchAction(Action.DATA_LOADED, { records, paginationInfo }, undefined);
800
850
  }
801
851
 
802
852
  /**
@@ -889,8 +939,12 @@ export default class DataUnit {
889
939
  public copySelected(executionCtx?: ExecutionContext): void {
890
940
  const selectionInfo = this.getSelectionInfo();
891
941
  if (selectionInfo) {
892
- const selectedRecords = selectionInfo.records;
942
+ if(selectionInfo.isAllRecords()){
943
+ throw new Error("Erro interno: Impossível copiar os registros selecionados pois a seleção atual é virtual.");
944
+ }
945
+ const selectedRecords = selectionInfo.records as Array<Record>;
893
946
  if(selectedRecords){
947
+
894
948
  this.dispatchAction(Action.RECORDS_COPIED, prepareCopiedRecord(this._stateManager, selectedRecords, this.getParentRecordId()), executionCtx);
895
949
  }
896
950
  }
@@ -956,21 +1010,31 @@ export default class DataUnit {
956
1010
  * @param fieldName -Identificador do campo a ser modificado.
957
1011
  * @param newValue - Valor a ser inserido no campo.
958
1012
  * @param records - Indica quais registros foram afetados pela alteração no valor do campo.
1013
+ * @param options - Configurações do evento
959
1014
  * @returns - Promise que será resolvida quando o novo valor for persistido no state.
960
- *
961
- */
1015
+ *
1016
+ */
962
1017
  public async setFieldValue(fieldName: string, newValue: any, records?: Array<string>, options?:DataUnitEventOptions): Promise<boolean> {
1018
+ const noRecordSelected = !this.hasNewRecord() && !this.getSelectedRecord();
1019
+
1020
+ const suppressCreateNewRecord = options?.suppressCreateNewRecord;
1021
+
1022
+ if(noRecordSelected && suppressCreateNewRecord) return Promise.resolve(false);
1023
+
1024
+ if(noRecordSelected) await this.addRecord();
963
1025
 
964
- if(!this.hasNewRecord() && !this.getSelectedRecord()) await this.addRecord();
965
-
966
1026
  const typedValue = this.validateAndTypeValue(fieldName, newValue);
967
1027
  const currentValue = this.getFieldValue(fieldName);
968
-
1028
+
1029
+ if(!(newValue instanceof Promise) && ObjectUtils.hasEquivalentProps(currentValue, typedValue)){
1030
+ return Promise.resolve(false);
1031
+ }
1032
+
969
1033
  if(newValue instanceof Promise){
970
1034
  const promise:Promise<boolean> = new Promise(accept => {
971
1035
  newValue.then(resolvedValue => {
972
1036
  this.dispatchAction(Action.DATA_RESOLVED, { [fieldName]: resolvedValue, records }, undefined);
973
- accept(this.setFieldValue(fieldName, resolvedValue, records));
1037
+ accept(this.setFieldValue(fieldName, resolvedValue, records, options));
974
1038
  });
975
1039
  });
976
1040
  this._savingLockers.push(promise);
@@ -999,6 +1063,18 @@ export default class DataUnit {
999
1063
  this.dispatchAction(Action.FIELD_INVALIDATED, { fieldName, message, recordId }, undefined);
1000
1064
  }
1001
1065
 
1066
+ /**
1067
+ *
1068
+ * Cancela o saving exibindo os campos invalidos.
1069
+ *
1070
+ * @param filds - Lista dos campos
1071
+ * @param recordId - Indica qual registro está com os campos inválido.
1072
+ *
1073
+ */
1074
+ public savingCanceled(fields: Array<{name: string, message: string}>, recordId: string): void {
1075
+ this.dispatchAction(Action.SAVING_CANCELED, { fields, recordId }, undefined);
1076
+ }
1077
+
1002
1078
  /**
1003
1079
  *
1004
1080
  * Limpa campos inválidos.
@@ -1106,7 +1182,7 @@ export default class DataUnit {
1106
1182
  public setSelection(selection: Array<string> | SelectionMode.ALL_RECORDS, executionCtx?: ExecutionContext): Promise<SelectionInfo> {
1107
1183
  return new Promise(resolve => {
1108
1184
  this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection }, executionCtx)
1109
- .then(()=>resolve(getSelectionInfo(this._stateManager)));
1185
+ .then(()=>resolve(this.getSelectionInfo()));
1110
1186
  });
1111
1187
  }
1112
1188
 
@@ -1127,35 +1203,53 @@ export default class DataUnit {
1127
1203
  *
1128
1204
  * @param selection - IDs dos registros selecionados no snapshot atual
1129
1205
  * @param executionCtx - Contexto de execução da seleção dos registros do DataUnit.
1130
- *
1131
1206
  * @returns - Informações sobre a seleção.
1132
1207
  */
1133
1208
  public updatePageSelection(selection: Array<string>, executionCtx?: ExecutionContext): Promise<SelectionInfo|undefined>{
1134
-
1135
- if(!selection){
1136
- return Promise.resolve(this.getSelectionInfo());
1137
- }
1209
+ if(!selection) return Promise.resolve(this.getSelectionInfo());
1138
1210
 
1139
1211
  return new Promise(resolve => {
1140
- const newSelection: Set<string> = new Set(getSelection(this._stateManager));
1141
- const currentRecords = getCurrentRecords(this._stateManager) || new Map();
1142
- Array.from(currentRecords.keys()).forEach(
1143
- recordId => {
1144
- if(selection.includes(recordId)){
1145
- newSelection.add(recordId);
1146
- } else {
1147
- newSelection.delete(recordId);
1148
- }
1149
- }
1150
- );
1212
+ const newSelection: Set<string> = new Set(selection);
1151
1213
 
1152
1214
  this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection: Array.from(newSelection) }, executionCtx)
1153
- .then(()=>{
1154
- resolve(this.getSelectionInfo())
1155
- });
1215
+ .then(()=> resolve(this.getSelectionInfo()));
1216
+ });
1217
+ }
1218
+
1219
+
1220
+ private updatePageSelectionAll(addRecords: boolean): Promise<SelectionInfo|undefined>{
1221
+ return new Promise(resolve => {
1222
+ const newSelection: Set<string> = new Set<string>();
1223
+
1224
+ const cachedSelection = getSelection(this._stateManager);
1225
+ cachedSelection.forEach(item => newSelection.add(item));
1226
+
1227
+ const recordsIds = this.records.map(r => r.__record__id__);
1228
+ recordsIds.forEach(id => addRecords ? newSelection.add(id): newSelection.delete(id));
1229
+
1230
+ this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection: Array.from(newSelection) })
1231
+ .then(()=> resolve(this.getSelectionInfo()));
1156
1232
  });
1157
1233
  }
1158
1234
 
1235
+ /**
1236
+ * Seleciona todos os registros da página.
1237
+ *
1238
+ * @returns - Informações sobre a seleção.
1239
+ */
1240
+ public selectAllRecords(): Promise<SelectionInfo|undefined>{
1241
+ return this.updatePageSelectionAll(true);
1242
+ }
1243
+
1244
+ /**
1245
+ * Desseleciona todos os registros da página.
1246
+ *
1247
+ * @returns - Informações sobre a seleção.
1248
+ */
1249
+ public unSelectAllRecords(): Promise<SelectionInfo|undefined>{
1250
+ return this.updatePageSelectionAll(false);
1251
+ }
1252
+
1159
1253
  /**
1160
1254
  *
1161
1255
  * Obtém informações sobre a seleção atual.
@@ -1163,8 +1257,16 @@ export default class DataUnit {
1163
1257
  * @returns - Objeto com informações como registros selecionados e seleção por critério.
1164
1258
  *
1165
1259
  **/
1166
- public getSelectionInfo(): SelectionInfo | undefined {
1167
- return getSelectionInfo(this._stateManager)
1260
+ public getSelectionInfo(): SelectionInfo{
1261
+ const selectionInfo: SelectionInfo = getSelectionInfo(this._stateManager);
1262
+ selectionInfo.getAllRecords = () => this.allRecordsLoader?.(this);
1263
+
1264
+ if (selectionInfo.sort != undefined && selectionInfo.sort.length > 0) {
1265
+ const sortingFunction = SortingUtils.getSortingFunction(this, selectionInfo.sort)
1266
+ selectionInfo.records?.sort(sortingFunction)
1267
+ }
1268
+
1269
+ return selectionInfo;
1168
1270
  }
1169
1271
 
1170
1272
  /**
@@ -1520,10 +1622,7 @@ export default class DataUnit {
1520
1622
  this._stateManager.process(action);
1521
1623
  this?._parentDataUnit?.dispatchAction(Action.CHILD_CHANGED, { srcAction: action, srcDataUnit: this });
1522
1624
  this._observers.forEach(f => {
1523
- /*
1524
- if some observer throws exceptions,
1525
- should be continued
1526
- */
1625
+ //if some observer throws exceptions, should be continued
1527
1626
  try {
1528
1627
  f(action, options);
1529
1628
  } catch (e) {
@@ -1562,10 +1661,17 @@ export default class DataUnit {
1562
1661
  * Ela vai ser chamada sempre que uma ação for despachada (dispatchAction()).
1563
1662
  *
1564
1663
  * @param observer - Função que recebe como parâmetro as ações que serão monitoradas.
1565
- *
1664
+ * @param uuid - Identificador do observer. Quando não informado, será gerado um identificador aleatório.
1566
1665
  */
1567
- public subscribe(observer: (action: DataUnitAction, options?:DataUnitEventOptions) => void | Promise<void>) {
1568
- this._observers.push(observer);
1666
+ public subscribe(observer: (action: DataUnitAction, options?: DataUnitEventOptions) => void | Promise<void>, uuid?: string): string {
1667
+ if (uuid) {
1668
+ this._observers.set(uuid, observer);
1669
+ } else {
1670
+ uuid = StringUtils.generateUUID();
1671
+ this._observers.set(uuid, observer);
1672
+ }
1673
+
1674
+ return uuid;
1569
1675
  }
1570
1676
 
1571
1677
  /**
@@ -1573,10 +1679,18 @@ export default class DataUnit {
1573
1679
  * Remove um observer existente.
1574
1680
  *
1575
1681
  * @param observer - Observer que se deseja remover.
1576
- *
1682
+ * @param uuid - Identificador do observer. Quando não informado o delete removera com base no equals do observer.
1577
1683
  */
1578
- public unsubscribe(observer: Function) {
1579
- this._observers = this._observers.filter(f => f !== observer);
1684
+ public unsubscribe(observer: Function, uuid?: string) {
1685
+ if (uuid) {
1686
+ this._observers.delete(uuid);
1687
+ } else {
1688
+ this._observers.forEach((valor, chave) => {
1689
+ if (valor == observer) {
1690
+ this._observers.delete(chave);
1691
+ }
1692
+ });
1693
+ }
1580
1694
  }
1581
1695
 
1582
1696
  /**
@@ -1589,18 +1703,21 @@ export default class DataUnit {
1589
1703
  public reloadCurrentRecord(): Promise<Array<Record>>{
1590
1704
  return new Promise(async (resolve, fail) => {
1591
1705
  const selection = getSelection(this._stateManager);
1592
- this.dispatchAction(Action.LOADING_RECORD, selection);
1706
+ await this.dispatchAction(Action.LOADING_RECORD, selection);
1593
1707
 
1594
1708
  if(!this.recordLoader || !this.dataLoader) {
1595
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1709
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1710
+ resolve([]);
1596
1711
  return;
1597
1712
  }
1598
1713
 
1599
- this.recordLoader(this, selection).then(response => {
1600
- this.dispatchAction(Action.RECORD_LOADED, response)
1601
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1602
- }).catch(cause => {
1603
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1714
+ this.recordLoader(this, selection).then(async response => {
1715
+ await this.dispatchAction(Action.RECORD_LOADED, response)
1716
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1717
+
1718
+ resolve(response);
1719
+ }).catch(async cause => {
1720
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1604
1721
  const {errorCode} = cause;
1605
1722
  fail(new ErrorException("Erro ao recarregar registro", cause, errorCode));
1606
1723
  });
@@ -1695,11 +1812,12 @@ export default class DataUnit {
1695
1812
  * @param fieldName - nome do campo para ficar invisível.
1696
1813
  *
1697
1814
  */
1698
- public hideField(fieldName:string) {
1815
+ public hideField(fieldName:string, options:HideFieldOptions) {
1699
1816
  const fieldDescriptor = this.getField(fieldName);
1700
1817
 
1701
1818
  if(fieldDescriptor?.visible === true){
1702
1819
  fieldDescriptor.visible = false;
1820
+ fieldDescriptor.properties = {...fieldDescriptor.properties, visibleOnConfig: options.visibleOnConfig };
1703
1821
  this.metadata = {...this.metadata};
1704
1822
  }
1705
1823
  }
@@ -1739,7 +1857,7 @@ export default class DataUnit {
1739
1857
  }
1740
1858
 
1741
1859
  if (selection) {
1742
- return selection.records;
1860
+ return selection.records as Array<Record>;
1743
1861
  }
1744
1862
  }
1745
1863
 
@@ -1757,12 +1875,15 @@ export default class DataUnit {
1757
1875
  public getSelection(): Array<string> {
1758
1876
  console.warn("DataUnit: O método `getSelection` foi descontinuado. Use o método `getSelectionInfo`.");
1759
1877
  const selection = this.getSelectionInfo();
1878
+ if(selection == undefined){
1879
+ return [];
1880
+ }
1760
1881
 
1761
- if(selection != undefined && selection.isAllRecords()){
1882
+ if(selection.isAllRecords()){
1762
1883
  throw new Error("Erro interno: Impossível retornar os registros selecionados. A seleção atual é virtual. Use o método `getSelectionInfo`.");
1763
1884
  }
1764
1885
 
1765
- return selection?.recordIds || [];
1886
+ return selection?.recordIds as Array<string>;
1766
1887
  }
1767
1888
 
1768
1889
  /**
@@ -1943,12 +2064,13 @@ export enum SelectionMode{
1943
2064
 
1944
2065
  export class SelectionInfo{
1945
2066
 
1946
- private _records: Array<Record>;
1947
2067
  public mode: SelectionMode;
1948
- private _total?: number;
1949
2068
  public filters?: Array<Filter>;
1950
2069
  public sort?: Array<Sort>;
1951
-
2070
+ public getAllRecords?: () => Array<Record> | undefined;
2071
+ private _records: Array<Record>;
2072
+ private _total?: number;
2073
+
1952
2074
  constructor(records: Array<Record>, mode: SelectionMode = SelectionMode.SOME_RECORDS, total?:number, filters?: Array<Filter>, sort?: Array<Sort>){
1953
2075
  this._records = records;
1954
2076
  this._total = total;
@@ -1959,7 +2081,10 @@ export class SelectionInfo{
1959
2081
 
1960
2082
  public get records(): Array<Record> | undefined{
1961
2083
  if(this.isAllRecords()){
1962
- throw new Error("Erro interno: [ALL_RECORDS] - Impossível retornar os registros selecionados numa seleção virtual.")
2084
+ if(this.getAllRecords != undefined){
2085
+ return this.getAllRecords();
2086
+ }
2087
+ throw new Error("Erro interno: Impossível retornar os registros selecionados numa seleção virtual.");
1963
2088
  }
1964
2089
  return this._records;
1965
2090
  }
@@ -1978,7 +2103,7 @@ export class SelectionInfo{
1978
2103
  if(this.isAllRecords()){
1979
2104
  return this._total || 0;
1980
2105
  }
1981
- return this.records == undefined ? 0: this.records.length;
2106
+ return this.records == undefined ? 0 : (this.records as Array<Record>).length;
1982
2107
  }
1983
2108
 
1984
2109
  public isAllRecords(): boolean{
@@ -1990,4 +2115,8 @@ export class SelectionInfo{
1990
2115
  }
1991
2116
  }
1992
2117
 
1993
- export type DataUnitEventOptions = {[key:string]: any};
2118
+ export type DataUnitEventOptions = {[key:string]: any};
2119
+
2120
+ export type HideFieldOptions = {
2121
+ visibleOnConfig: boolean
2122
+ };
@@ -1,6 +1,7 @@
1
1
  import DateUtils from '../../utils/DateUtils.js';
2
2
  import { MaskFormatter } from '../../utils/MaskFormatter.js';
3
3
  import { NumberUtils } from '../../utils/NumberUtils.js';
4
+ import { TimeFormatter } from '../../utils/TimeFormatter.js';
4
5
  import { DataType, toString } from '../metadata/DataType.js';
5
6
  import { FieldDescriptor, UserInterface } from '../metadata/UnitMetadata.js';
6
7
 
@@ -13,7 +14,10 @@ export const getFormattedValue = (value: any, descriptor?: FieldDescriptor) => {
13
14
  if(value && Object.hasOwn(value, "value")){
14
15
  return getSearchFormat(value, descriptor);
15
16
  }
16
- return !value ? "" : value.toString();
17
+
18
+ if(value === null || value === undefined) return "";
19
+
20
+ return value.toString();
17
21
  }
18
22
 
19
23
  if(descriptor?.userInterface === UserInterface.OPTIONSELECTOR){
@@ -36,6 +40,10 @@ export const getFormattedValue = (value: any, descriptor?: FieldDescriptor) => {
36
40
  return DateUtils.formatTime(value);
37
41
  }
38
42
 
43
+ if(descriptor?.userInterface === UserInterface.ELAPSEDTIME){
44
+ return TimeFormatter.prepareValue(value, true);
45
+ }
46
+
39
47
  if(descriptor?.userInterface === UserInterface.DATETIME){
40
48
  return DateUtils.formatDateTime(value);
41
49
  }
@@ -43,7 +51,7 @@ export const getFormattedValue = (value: any, descriptor?: FieldDescriptor) => {
43
51
  const mask = getMask(value, descriptor);
44
52
  if(mask != undefined){
45
53
  try{
46
- return new MaskFormatter(mask).format(value);
54
+ return new MaskFormatter(mask).format(value, true);
47
55
  } catch(error){
48
56
  console.warn(`Erro ao formatar valor: ${value}. Mascara: ${mask}. Erro: ${error}`);
49
57
  }
@@ -0,0 +1,10 @@
1
+ export interface DataUnitInMemoryLoaderConfig {
2
+ autoLoad?: boolean;
3
+ pageSize?: number;
4
+ recordDateFormat?: RECORD_DATE_FORMAT;
5
+ }
6
+
7
+ export enum RECORD_DATE_FORMAT {
8
+ DD_MM_YYYY = 'DD/MM/YYYY',
9
+ ISO = 'ISO'
10
+ }