@sankhyalabs/core 5.17.4 → 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 (135) 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/ServiceUtils.md +67 -0
  13. package/.docs/classes/SilentException.md +193 -0
  14. package/.docs/classes/UserAgentUtils.md +15 -1
  15. package/.docs/enumerations/Action.md +32 -22
  16. package/.docs/enumerations/ChangeOperation.md +4 -4
  17. package/.docs/enumerations/LockManagerOperation.md +33 -0
  18. package/.docs/enumerations/RECORD_DATE_FORMAT.md +27 -0
  19. package/.docs/enumerations/SelectionMode.md +2 -2
  20. package/.docs/enumerations/StorageType.md +37 -0
  21. package/.docs/globals.md +11 -0
  22. package/.docs/interfaces/DUActionInterceptor.md +1 -1
  23. package/.docs/interfaces/DataUnitInMemoryLoaderConfig.md +37 -0
  24. package/.docs/interfaces/IRepository.md +18 -0
  25. package/.docs/interfaces/LoadDataRequest.md +1 -1
  26. package/.docs/interfaces/PageRequest.md +3 -3
  27. package/.docs/interfaces/PaginationInfo.md +25 -0
  28. package/.docs/interfaces/PaginationInfoBuilderParams.md +37 -0
  29. package/.docs/interfaces/QuickFilter.md +3 -3
  30. package/.docs/interfaces/Record.md +4 -4
  31. package/.docs/interfaces/SavedRecord.md +5 -5
  32. package/.docs/interfaces/WaitingChange.md +3 -3
  33. package/.docs/namespaces/MaskFormatter/type-aliases/MaskCharacter.md +1 -1
  34. package/.docs/namespaces/MaskFormatter/variables/MaskCharacter.md +1 -1
  35. package/.docs/type-aliases/DataUnitEventOptions.md +1 -1
  36. package/.releaserc +1 -0
  37. package/bun.lockb +0 -0
  38. package/dist/dataunit/DataUnit.d.ts +60 -10
  39. package/dist/dataunit/DataUnit.js +151 -50
  40. package/dist/dataunit/DataUnit.js.map +1 -1
  41. package/dist/dataunit/formatting/PrettyFormatter.js +8 -2
  42. package/dist/dataunit/formatting/PrettyFormatter.js.map +1 -1
  43. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.d.ts +9 -0
  44. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js +6 -0
  45. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js.map +1 -0
  46. package/dist/dataunit/loader/dataUnitInMemoryLoader.d.ts +25 -0
  47. package/dist/dataunit/loader/dataUnitInMemoryLoader.js +131 -0
  48. package/dist/dataunit/loader/dataUnitInMemoryLoader.js.map +1 -0
  49. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.d.ts +20 -0
  50. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js +62 -0
  51. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js.map +1 -0
  52. package/dist/dataunit/loading/LoadDataRequest.d.ts +1 -1
  53. package/dist/dataunit/loading/PaginationInfo.d.ts +8 -0
  54. package/dist/dataunit/sorting/FieldComparator.d.ts +2 -2
  55. package/dist/dataunit/sorting/FieldComparator.js +4 -9
  56. package/dist/dataunit/sorting/FieldComparator.js.map +1 -1
  57. package/dist/dataunit/state/action/DataUnitAction.d.ts +1 -0
  58. package/dist/dataunit/state/action/DataUnitAction.js +1 -0
  59. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  60. package/dist/dataunit/state/slice/LoadingControlSlice.js +16 -0
  61. package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -1
  62. package/dist/dataunit/state/slice/RecordsSlice.js +1 -1
  63. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  64. package/dist/dataunit/state/slice/SelectionSlice.js +2 -2
  65. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  66. package/dist/exceptions/SilentException.d.ts +14 -0
  67. package/dist/exceptions/SilentException.js +13 -0
  68. package/dist/exceptions/SilentException.js.map +1 -0
  69. package/dist/index.d.ts +9 -1
  70. package/dist/index.js +9 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/repository/IRepository.d.ts +6 -0
  73. package/dist/repository/indexeddb/IDBRepository.d.ts +1 -0
  74. package/dist/repository/indexeddb/IDBRepository.js +3 -0
  75. package/dist/repository/indexeddb/IDBRepository.js.map +1 -1
  76. package/dist/utils/CacheManager/index.d.ts +52 -0
  77. package/dist/utils/CacheManager/index.js +101 -0
  78. package/dist/utils/CacheManager/index.js.map +1 -0
  79. package/dist/utils/CacheManager/interfaces/index.d.ts +5 -0
  80. package/dist/utils/CacheManager/interfaces/index.js +7 -0
  81. package/dist/utils/CacheManager/interfaces/index.js.map +1 -0
  82. package/dist/utils/ColumnFilterManager.d.ts +19 -0
  83. package/dist/utils/ColumnFilterManager.js +73 -0
  84. package/dist/utils/ColumnFilterManager.js.map +1 -0
  85. package/dist/utils/LockManager.d.ts +58 -0
  86. package/dist/utils/LockManager.js +191 -0
  87. package/dist/utils/LockManager.js.map +1 -0
  88. package/dist/utils/MaskFormatter.d.ts +16 -1
  89. package/dist/utils/MaskFormatter.js +82 -2
  90. package/dist/utils/MaskFormatter.js.map +1 -1
  91. package/dist/utils/ObjectUtils.d.ts +24 -0
  92. package/dist/utils/ObjectUtils.js +33 -0
  93. package/dist/utils/ObjectUtils.js.map +1 -1
  94. package/dist/utils/ServiceUtils.d.ts +24 -0
  95. package/dist/utils/ServiceUtils.js +40 -0
  96. package/dist/utils/ServiceUtils.js.map +1 -0
  97. package/dist/utils/SortingUtils.d.ts +9 -0
  98. package/dist/utils/SortingUtils.js +24 -0
  99. package/dist/utils/SortingUtils.js.map +1 -0
  100. package/dist/utils/UserAgentUtils/index.d.ts +1 -0
  101. package/dist/utils/UserAgentUtils/index.js +5 -0
  102. package/dist/utils/UserAgentUtils/index.js.map +1 -1
  103. package/package.json +1 -1
  104. package/reports/test-report.xml +148 -84
  105. package/src/dataunit/DataUnit.ts +191 -68
  106. package/src/dataunit/formatting/PrettyFormatter.ts +10 -2
  107. package/src/dataunit/loader/DataUnitInMemoryLoaderConfig.ts +10 -0
  108. package/src/dataunit/loader/dataUnitInMemoryLoader.ts +176 -0
  109. package/src/dataunit/loader/utils/dataUnitLoaderUtils.ts +86 -0
  110. package/src/dataunit/loading/LoadDataRequest.ts +1 -1
  111. package/src/dataunit/loading/PaginationInfo.ts +10 -0
  112. package/src/dataunit/sorting/FieldComparator.ts +18 -32
  113. package/src/dataunit/state/action/DataUnitAction.ts +1 -0
  114. package/src/dataunit/state/slice/LoadingControlSlice.ts +42 -0
  115. package/src/dataunit/state/slice/RecordsSlice.ts +1 -1
  116. package/src/dataunit/state/slice/SelectionSlice.ts +2 -2
  117. package/src/dataunit/state/slice/test/RecordsSlice.spec.ts +45 -0
  118. package/src/dataunit/test/DataUnit.spec.ts +44 -0
  119. package/src/exceptions/SilentException.ts +25 -0
  120. package/src/index.ts +20 -1
  121. package/src/repository/IRepository.ts +7 -0
  122. package/src/repository/indexeddb/IDBRepository.ts +4 -0
  123. package/src/utils/CacheManager/index.ts +103 -0
  124. package/src/utils/CacheManager/interfaces/index.ts +5 -0
  125. package/src/utils/ColumnFilterManager.ts +104 -0
  126. package/src/utils/LockManager.ts +213 -0
  127. package/src/utils/MaskFormatter.ts +93 -2
  128. package/src/utils/ObjectUtils.ts +36 -0
  129. package/src/utils/ServiceUtils.ts +36 -0
  130. package/src/utils/SortingUtils.ts +30 -0
  131. package/src/utils/UserAgentUtils/index.ts +6 -1
  132. package/src/utils/test/objectUtils.spec.ts +109 -0
  133. package/test/dataunit/loader/dataUnitInMemoryLoader.spec.ts +221 -0
  134. package/test/dataunit/loader/utils/dataUnitLoaderUtils.spec.ts +158 -0
  135. package/test/util/ColumnFilterManager.spec.ts +133 -0
@@ -26,7 +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";
29
30
  import ServiceCanceledException from "../exceptions/ServiceCanceledException.js";
31
+ import SilentException from "../exceptions/SilentException.js";
30
32
 
31
33
  /***
32
34
  * `DataUnit`: Atua como uma camada de abstração entre o back-end e a interface do usuário.
@@ -34,11 +36,12 @@ import ServiceCanceledException from "../exceptions/ServiceCanceledException.js"
34
36
  export default class DataUnit {
35
37
 
36
38
  public static CHANGING_PAGE_LOADING_SOURCE = "CHANGING_PAGE_LOADING_SOURCE";
39
+ public static ALL_RECORDS_SELECTION_SOURCE = "ALL_RECORDS_SELECTION_SOURCE";
37
40
  public static DEFAULT_DATAUNIT_NAME = "dataunit";
38
41
 
39
42
  private _uuid: string;
40
43
  private _name: string;
41
- private _observers: Array<(action: DataUnitAction, options?:DataUnitEventOptions) => void>;
44
+ private _observers: Map<string, (action: DataUnitAction, options?: DataUnitEventOptions) => void>;
42
45
  private _sortingProvider?: SortingProvider;
43
46
  private _filterProviders: Map<string, FilterProvider>;
44
47
  private _stateManager: StateManager;
@@ -50,12 +53,15 @@ export default class DataUnit {
50
53
  private _savingLockers: Promise<any>[] = [];
51
54
  private _defaultSorting: Array<Sort>;
52
55
  private _allowReleaseCallbacks: boolean;
56
+ private _waitingToReload: boolean = false;
57
+ private _cancelPagination: boolean = false;
53
58
 
54
59
  public metadataLoader?: (dataUnit: DataUnit) => Promise<UnitMetadata>;
55
60
  public dataLoader?: (dataUnit: DataUnit, request: LoadDataRequest) => Promise<LoadDataResponse>;
56
61
  public saveLoader?: (dataUnit: DataUnit, changes: Array<Change>) => Promise<Array<SavedRecord>>;
57
62
  public removeLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<string>>;
58
63
  public recordLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<Record>>;
64
+ public allRecordsLoader?: (dataUnit: DataUnit) => Array<Record> | undefined;
59
65
 
60
66
  constructor(name: string = DataUnit.DEFAULT_DATAUNIT_NAME, parentDataUnit?: DataUnit) {
61
67
  this._uuid = uuid()
@@ -77,7 +83,7 @@ export default class DataUnit {
77
83
  SnapshotReducer
78
84
  ]
79
85
  );
80
- this._observers = [];
86
+ this._observers = new Map();
81
87
  this._filterProviders = new Map<string, FilterProvider>();
82
88
  this._sortingProvider = undefined;
83
89
  this._defaultSorting = [];
@@ -115,7 +121,7 @@ export default class DataUnit {
115
121
  public releaseCallbacks(){
116
122
  if(!this._allowReleaseCallbacks) return;
117
123
 
118
- this._observers = [];
124
+ this._observers = new Map();
119
125
  this._filterProviders = new Map<string, FilterProvider>();
120
126
  this._sortingProvider = undefined;
121
127
  this._interceptors = new Map();
@@ -147,6 +153,36 @@ export default class DataUnit {
147
153
  return this._uuid;
148
154
  }
149
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
+
150
186
  /**
151
187
  *
152
188
  * Obtém o nome de identificação do DataUnit (geralmente em formato de URI - Uniform Resource Identifier).
@@ -351,6 +387,9 @@ export default class DataUnit {
351
387
  *
352
388
  */
353
389
  public async gotoPage(page: number, executionCtx?: ExecutionContext): Promise<LoadDataResponse | void> {
390
+ if(this._pageSize === 0) {
391
+ return;
392
+ }
354
393
 
355
394
  let request = getCurrentRequest(this._stateManager);
356
395
 
@@ -484,11 +523,14 @@ export default class DataUnit {
484
523
  this.dispatchAction(Action.SAVING_ERROR);
485
524
  this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
486
525
  if(cause instanceof ServiceCanceledException){
487
- console.debug("Service canceled: " + cause.message)
488
- resolve()
489
- } else{
490
- fail(new ErrorException("Erro ao salvar alterações", cause, errorCode))
526
+ console.debug("Service canceled: " + cause.message);
527
+ resolve();
528
+ }
529
+ if(cause instanceof SilentException){
530
+ fail(cause);
531
+ return;
491
532
  }
533
+ fail(new ErrorException("Erro ao salvar alterações", cause, errorCode));
492
534
  });
493
535
  } else {
494
536
  this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
@@ -557,8 +599,8 @@ export default class DataUnit {
557
599
  if(selection.isAllRecords()){
558
600
  throw new Error("Exclusão remota não implementada.");
559
601
  }
560
- const records = selection?.records || [];
561
- const recordIds = selection?.recordIds || [];
602
+ const records = selection?.records as Array<Record> || [];
603
+ const recordIds = selection?.recordIds as Array<string> || [];
562
604
  return this.removeRecords(recordIds, records, buffered, undefined, silent);
563
605
  }
564
606
  return Promise.resolve([]);
@@ -661,13 +703,13 @@ export default class DataUnit {
661
703
  */
662
704
  public getFormattedValue(fieldName: string, value?: any): string {
663
705
  const descriptor = this.getField(fieldName);
664
- if (value === undefined) {
706
+ if (value == undefined) {
665
707
  value = this.getFieldValue(fieldName);
666
708
  } else if (typeof value === "string" && descriptor?.dataType != DataType.TEXT){
667
709
  value = this.valueFromString(fieldName, value);
668
710
  }
669
711
 
670
- if(value === undefined){
712
+ if(value == undefined){
671
713
  return "";
672
714
  }
673
715
 
@@ -738,6 +780,7 @@ export default class DataUnit {
738
780
  return this.dispatchAction(Action.PAGINATION_UPDATED, info, undefined);
739
781
  }
740
782
 
783
+
741
784
  /**
742
785
  *
743
786
  * Define a lógica de ordenação dos registros.
@@ -802,7 +845,8 @@ export default class DataUnit {
802
845
  *
803
846
  */
804
847
  public set records(records: Array<Record>) {
805
- this.dispatchAction(Action.DATA_LOADED, { records }, undefined);
848
+ const paginationInfo = this.getPaginationInfo();
849
+ this.dispatchAction(Action.DATA_LOADED, { records, paginationInfo }, undefined);
806
850
  }
807
851
 
808
852
  /**
@@ -895,8 +939,12 @@ export default class DataUnit {
895
939
  public copySelected(executionCtx?: ExecutionContext): void {
896
940
  const selectionInfo = this.getSelectionInfo();
897
941
  if (selectionInfo) {
898
- 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>;
899
946
  if(selectedRecords){
947
+
900
948
  this.dispatchAction(Action.RECORDS_COPIED, prepareCopiedRecord(this._stateManager, selectedRecords, this.getParentRecordId()), executionCtx);
901
949
  }
902
950
  }
@@ -962,21 +1010,31 @@ export default class DataUnit {
962
1010
  * @param fieldName -Identificador do campo a ser modificado.
963
1011
  * @param newValue - Valor a ser inserido no campo.
964
1012
  * @param records - Indica quais registros foram afetados pela alteração no valor do campo.
1013
+ * @param options - Configurações do evento
965
1014
  * @returns - Promise que será resolvida quando o novo valor for persistido no state.
966
- *
967
- */
1015
+ *
1016
+ */
968
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();
969
1025
 
970
- if(!this.hasNewRecord() && !this.getSelectedRecord()) await this.addRecord();
971
-
972
1026
  const typedValue = this.validateAndTypeValue(fieldName, newValue);
973
1027
  const currentValue = this.getFieldValue(fieldName);
974
-
1028
+
1029
+ if(!(newValue instanceof Promise) && ObjectUtils.hasEquivalentProps(currentValue, typedValue)){
1030
+ return Promise.resolve(false);
1031
+ }
1032
+
975
1033
  if(newValue instanceof Promise){
976
1034
  const promise:Promise<boolean> = new Promise(accept => {
977
1035
  newValue.then(resolvedValue => {
978
1036
  this.dispatchAction(Action.DATA_RESOLVED, { [fieldName]: resolvedValue, records }, undefined);
979
- accept(this.setFieldValue(fieldName, resolvedValue, records));
1037
+ accept(this.setFieldValue(fieldName, resolvedValue, records, options));
980
1038
  });
981
1039
  });
982
1040
  this._savingLockers.push(promise);
@@ -1005,6 +1063,18 @@ export default class DataUnit {
1005
1063
  this.dispatchAction(Action.FIELD_INVALIDATED, { fieldName, message, recordId }, undefined);
1006
1064
  }
1007
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
+
1008
1078
  /**
1009
1079
  *
1010
1080
  * Limpa campos inválidos.
@@ -1112,7 +1182,7 @@ export default class DataUnit {
1112
1182
  public setSelection(selection: Array<string> | SelectionMode.ALL_RECORDS, executionCtx?: ExecutionContext): Promise<SelectionInfo> {
1113
1183
  return new Promise(resolve => {
1114
1184
  this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection }, executionCtx)
1115
- .then(()=>resolve(getSelectionInfo(this._stateManager)));
1185
+ .then(()=>resolve(this.getSelectionInfo()));
1116
1186
  });
1117
1187
  }
1118
1188
 
@@ -1133,35 +1203,53 @@ export default class DataUnit {
1133
1203
  *
1134
1204
  * @param selection - IDs dos registros selecionados no snapshot atual
1135
1205
  * @param executionCtx - Contexto de execução da seleção dos registros do DataUnit.
1136
- *
1137
1206
  * @returns - Informações sobre a seleção.
1138
1207
  */
1139
1208
  public updatePageSelection(selection: Array<string>, executionCtx?: ExecutionContext): Promise<SelectionInfo|undefined>{
1140
-
1141
- if(!selection){
1142
- return Promise.resolve(this.getSelectionInfo());
1143
- }
1209
+ if(!selection) return Promise.resolve(this.getSelectionInfo());
1144
1210
 
1145
1211
  return new Promise(resolve => {
1146
- const newSelection: Set<string> = new Set(getSelection(this._stateManager));
1147
- const currentRecords = getCurrentRecords(this._stateManager) || new Map();
1148
- Array.from(currentRecords.keys()).forEach(
1149
- recordId => {
1150
- if(selection.includes(recordId)){
1151
- newSelection.add(recordId);
1152
- } else {
1153
- newSelection.delete(recordId);
1154
- }
1155
- }
1156
- );
1212
+ const newSelection: Set<string> = new Set(selection);
1157
1213
 
1158
1214
  this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection: Array.from(newSelection) }, executionCtx)
1159
- .then(()=>{
1160
- resolve(this.getSelectionInfo())
1161
- });
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()));
1162
1232
  });
1163
1233
  }
1164
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
+
1165
1253
  /**
1166
1254
  *
1167
1255
  * Obtém informações sobre a seleção atual.
@@ -1169,8 +1257,16 @@ export default class DataUnit {
1169
1257
  * @returns - Objeto com informações como registros selecionados e seleção por critério.
1170
1258
  *
1171
1259
  **/
1172
- public getSelectionInfo(): SelectionInfo | undefined {
1173
- 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;
1174
1270
  }
1175
1271
 
1176
1272
  /**
@@ -1526,10 +1622,7 @@ export default class DataUnit {
1526
1622
  this._stateManager.process(action);
1527
1623
  this?._parentDataUnit?.dispatchAction(Action.CHILD_CHANGED, { srcAction: action, srcDataUnit: this });
1528
1624
  this._observers.forEach(f => {
1529
- /*
1530
- if some observer throws exceptions,
1531
- should be continued
1532
- */
1625
+ //if some observer throws exceptions, should be continued
1533
1626
  try {
1534
1627
  f(action, options);
1535
1628
  } catch (e) {
@@ -1568,10 +1661,17 @@ export default class DataUnit {
1568
1661
  * Ela vai ser chamada sempre que uma ação for despachada (dispatchAction()).
1569
1662
  *
1570
1663
  * @param observer - Função que recebe como parâmetro as ações que serão monitoradas.
1571
- *
1664
+ * @param uuid - Identificador do observer. Quando não informado, será gerado um identificador aleatório.
1572
1665
  */
1573
- public subscribe(observer: (action: DataUnitAction, options?:DataUnitEventOptions) => void | Promise<void>) {
1574
- 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;
1575
1675
  }
1576
1676
 
1577
1677
  /**
@@ -1579,10 +1679,18 @@ export default class DataUnit {
1579
1679
  * Remove um observer existente.
1580
1680
  *
1581
1681
  * @param observer - Observer que se deseja remover.
1582
- *
1682
+ * @param uuid - Identificador do observer. Quando não informado o delete removera com base no equals do observer.
1583
1683
  */
1584
- public unsubscribe(observer: Function) {
1585
- 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
+ }
1586
1694
  }
1587
1695
 
1588
1696
  /**
@@ -1595,18 +1703,21 @@ export default class DataUnit {
1595
1703
  public reloadCurrentRecord(): Promise<Array<Record>>{
1596
1704
  return new Promise(async (resolve, fail) => {
1597
1705
  const selection = getSelection(this._stateManager);
1598
- this.dispatchAction(Action.LOADING_RECORD, selection);
1706
+ await this.dispatchAction(Action.LOADING_RECORD, selection);
1599
1707
 
1600
1708
  if(!this.recordLoader || !this.dataLoader) {
1601
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1709
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1710
+ resolve([]);
1602
1711
  return;
1603
1712
  }
1604
1713
 
1605
- this.recordLoader(this, selection).then(response => {
1606
- this.dispatchAction(Action.RECORD_LOADED, response)
1607
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1608
- }).catch(cause => {
1609
- 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);
1610
1721
  const {errorCode} = cause;
1611
1722
  fail(new ErrorException("Erro ao recarregar registro", cause, errorCode));
1612
1723
  });
@@ -1701,11 +1812,12 @@ export default class DataUnit {
1701
1812
  * @param fieldName - nome do campo para ficar invisível.
1702
1813
  *
1703
1814
  */
1704
- public hideField(fieldName:string) {
1815
+ public hideField(fieldName:string, options:HideFieldOptions) {
1705
1816
  const fieldDescriptor = this.getField(fieldName);
1706
1817
 
1707
1818
  if(fieldDescriptor?.visible === true){
1708
1819
  fieldDescriptor.visible = false;
1820
+ fieldDescriptor.properties = {...fieldDescriptor.properties, visibleOnConfig: options.visibleOnConfig };
1709
1821
  this.metadata = {...this.metadata};
1710
1822
  }
1711
1823
  }
@@ -1745,7 +1857,7 @@ export default class DataUnit {
1745
1857
  }
1746
1858
 
1747
1859
  if (selection) {
1748
- return selection.records;
1860
+ return selection.records as Array<Record>;
1749
1861
  }
1750
1862
  }
1751
1863
 
@@ -1763,12 +1875,15 @@ export default class DataUnit {
1763
1875
  public getSelection(): Array<string> {
1764
1876
  console.warn("DataUnit: O método `getSelection` foi descontinuado. Use o método `getSelectionInfo`.");
1765
1877
  const selection = this.getSelectionInfo();
1878
+ if(selection == undefined){
1879
+ return [];
1880
+ }
1766
1881
 
1767
- if(selection != undefined && selection.isAllRecords()){
1882
+ if(selection.isAllRecords()){
1768
1883
  throw new Error("Erro interno: Impossível retornar os registros selecionados. A seleção atual é virtual. Use o método `getSelectionInfo`.");
1769
1884
  }
1770
1885
 
1771
- return selection?.recordIds || [];
1886
+ return selection?.recordIds as Array<string>;
1772
1887
  }
1773
1888
 
1774
1889
  /**
@@ -1949,12 +2064,13 @@ export enum SelectionMode{
1949
2064
 
1950
2065
  export class SelectionInfo{
1951
2066
 
1952
- private _records: Array<Record>;
1953
2067
  public mode: SelectionMode;
1954
- private _total?: number;
1955
2068
  public filters?: Array<Filter>;
1956
2069
  public sort?: Array<Sort>;
1957
-
2070
+ public getAllRecords?: () => Array<Record> | undefined;
2071
+ private _records: Array<Record>;
2072
+ private _total?: number;
2073
+
1958
2074
  constructor(records: Array<Record>, mode: SelectionMode = SelectionMode.SOME_RECORDS, total?:number, filters?: Array<Filter>, sort?: Array<Sort>){
1959
2075
  this._records = records;
1960
2076
  this._total = total;
@@ -1965,7 +2081,10 @@ export class SelectionInfo{
1965
2081
 
1966
2082
  public get records(): Array<Record> | undefined{
1967
2083
  if(this.isAllRecords()){
1968
- 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.");
1969
2088
  }
1970
2089
  return this._records;
1971
2090
  }
@@ -1984,7 +2103,7 @@ export class SelectionInfo{
1984
2103
  if(this.isAllRecords()){
1985
2104
  return this._total || 0;
1986
2105
  }
1987
- return this.records == undefined ? 0: this.records.length;
2106
+ return this.records == undefined ? 0 : (this.records as Array<Record>).length;
1988
2107
  }
1989
2108
 
1990
2109
  public isAllRecords(): boolean{
@@ -1996,4 +2115,8 @@ export class SelectionInfo{
1996
2115
  }
1997
2116
  }
1998
2117
 
1999
- 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
+ }