@sankhyalabs/core 5.20.0-dev.8 → 5.20.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 (190) hide show
  1. package/.docs/classes/Base64Utils.md +39 -0
  2. package/.docs/classes/Change.md +11 -11
  3. package/.docs/classes/ColumnFilterManager.md +145 -0
  4. package/.docs/classes/DataUnit.md +429 -139
  5. package/.docs/classes/DataUnitInMemoryLoader.md +303 -0
  6. package/.docs/classes/DataUnitLoaderUtils.md +151 -0
  7. package/.docs/classes/DateUtils.md +8 -8
  8. package/.docs/classes/FieldComparator.md +2 -2
  9. package/.docs/classes/IDBRepository.md +22 -0
  10. package/.docs/classes/LockManager.md +249 -0
  11. package/.docs/classes/MaskFormatter.md +66 -14
  12. package/.docs/classes/ObjectUtils.md +141 -0
  13. package/.docs/classes/OverflowWatcher.md +533 -0
  14. package/.docs/classes/SelectionInfo.md +25 -11
  15. package/.docs/classes/ServiceCanceledException.md +193 -0
  16. package/.docs/classes/ServiceUtils.md +67 -0
  17. package/.docs/classes/SilentException.md +193 -0
  18. package/.docs/classes/StringUtils.md +24 -0
  19. package/.docs/classes/UserAgentUtils.md +15 -1
  20. package/.docs/enumerations/Action.md +41 -21
  21. package/.docs/enumerations/ChangeOperation.md +4 -4
  22. package/.docs/enumerations/LockManagerOperation.md +33 -0
  23. package/.docs/enumerations/OverflowDirection.md +29 -0
  24. package/.docs/enumerations/RECORD_DATE_FORMAT.md +27 -0
  25. package/.docs/enumerations/SelectionMode.md +2 -2
  26. package/.docs/enumerations/StorageType.md +37 -0
  27. package/.docs/globals.md +25 -0
  28. package/.docs/interfaces/DUActionInterceptor.md +1 -1
  29. package/.docs/interfaces/DataUnitInMemoryLoaderConfig.md +37 -0
  30. package/.docs/interfaces/IRepository.md +18 -0
  31. package/.docs/interfaces/LoadDataRequest.md +1 -1
  32. package/.docs/interfaces/OverFlowWatcherParams.md +67 -0
  33. package/.docs/interfaces/PageRequest.md +3 -3
  34. package/.docs/interfaces/PaginationInfo.md +25 -0
  35. package/.docs/interfaces/PaginationInfoBuilderParams.md +37 -0
  36. package/.docs/interfaces/QuickFilter.md +3 -3
  37. package/.docs/interfaces/Record.md +4 -4
  38. package/.docs/interfaces/SavedRecord.md +5 -5
  39. package/.docs/interfaces/WaitingChange.md +3 -3
  40. package/.docs/namespaces/MaskFormatter/type-aliases/MaskCharacter.md +1 -1
  41. package/.docs/namespaces/MaskFormatter/variables/MaskCharacter.md +1 -1
  42. package/.docs/type-aliases/DataUnitEventOptions.md +17 -0
  43. package/.docs/type-aliases/OnOverflowCallBack.md +25 -0
  44. package/.docs/variables/OVERFLOWED_CLASS_NAME.md +13 -0
  45. package/.releaserc +1 -0
  46. package/bun.lockb +0 -0
  47. package/dist/dataunit/DataUnit.d.ts +92 -13
  48. package/dist/dataunit/DataUnit.js +219 -71
  49. package/dist/dataunit/DataUnit.js.map +1 -1
  50. package/dist/dataunit/DataUnitHelper.js +6 -5
  51. package/dist/dataunit/DataUnitHelper.js.map +1 -1
  52. package/dist/dataunit/formatting/PrettyFormatter.js +14 -6
  53. package/dist/dataunit/formatting/PrettyFormatter.js.map +1 -1
  54. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.d.ts +9 -0
  55. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js +6 -0
  56. package/dist/dataunit/loader/DataUnitInMemoryLoaderConfig.js.map +1 -0
  57. package/dist/dataunit/loader/dataUnitInMemoryLoader.d.ts +25 -0
  58. package/dist/dataunit/loader/dataUnitInMemoryLoader.js +131 -0
  59. package/dist/dataunit/loader/dataUnitInMemoryLoader.js.map +1 -0
  60. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.d.ts +20 -0
  61. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js +62 -0
  62. package/dist/dataunit/loader/utils/dataUnitLoaderUtils.js.map +1 -0
  63. package/dist/dataunit/loading/LoadDataRequest.d.ts +1 -1
  64. package/dist/dataunit/loading/PaginationInfo.d.ts +8 -0
  65. package/dist/dataunit/metadata/DataType.js +3 -0
  66. package/dist/dataunit/metadata/DataType.js.map +1 -1
  67. package/dist/dataunit/sorting/FieldComparator.d.ts +2 -2
  68. package/dist/dataunit/sorting/FieldComparator.js +4 -9
  69. package/dist/dataunit/sorting/FieldComparator.js.map +1 -1
  70. package/dist/dataunit/state/action/DataUnitAction.d.ts +2 -0
  71. package/dist/dataunit/state/action/DataUnitAction.js +2 -0
  72. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  73. package/dist/dataunit/state/slice/LoadingControlSlice.js +16 -0
  74. package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -1
  75. package/dist/dataunit/state/slice/RecordsSlice.js +1 -1
  76. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  77. package/dist/dataunit/state/slice/SelectionSlice.js +4 -4
  78. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  79. package/dist/exceptions/ServiceCanceledException.d.ts +14 -0
  80. package/dist/exceptions/ServiceCanceledException.js +13 -0
  81. package/dist/exceptions/ServiceCanceledException.js.map +1 -0
  82. package/dist/exceptions/SilentException.d.ts +14 -0
  83. package/dist/exceptions/SilentException.js +13 -0
  84. package/dist/exceptions/SilentException.js.map +1 -0
  85. package/dist/index.d.ts +13 -2
  86. package/dist/index.js +12 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/repository/IRepository.d.ts +6 -0
  89. package/dist/repository/indexeddb/IDBRepository.d.ts +1 -0
  90. package/dist/repository/indexeddb/IDBRepository.js +3 -0
  91. package/dist/repository/indexeddb/IDBRepository.js.map +1 -1
  92. package/dist/utils/Base64Utils.d.ts +7 -0
  93. package/dist/utils/Base64Utils.js +13 -0
  94. package/dist/utils/Base64Utils.js.map +1 -0
  95. package/dist/utils/CacheManager/index.d.ts +52 -0
  96. package/dist/utils/CacheManager/index.js +101 -0
  97. package/dist/utils/CacheManager/index.js.map +1 -0
  98. package/dist/utils/CacheManager/interfaces/index.d.ts +5 -0
  99. package/dist/utils/CacheManager/interfaces/index.js +7 -0
  100. package/dist/utils/CacheManager/interfaces/index.js.map +1 -0
  101. package/dist/utils/ColumnFilterManager.d.ts +19 -0
  102. package/dist/utils/ColumnFilterManager.js +73 -0
  103. package/dist/utils/ColumnFilterManager.js.map +1 -0
  104. package/dist/utils/DateUtils.js +3 -0
  105. package/dist/utils/DateUtils.js.map +1 -1
  106. package/dist/utils/ElementUtils.d.ts +2 -0
  107. package/dist/utils/ElementUtils.js +9 -0
  108. package/dist/utils/ElementUtils.js.map +1 -0
  109. package/dist/utils/LockManager.d.ts +58 -0
  110. package/dist/utils/LockManager.js +191 -0
  111. package/dist/utils/LockManager.js.map +1 -0
  112. package/dist/utils/MaskFormatter.d.ts +16 -1
  113. package/dist/utils/MaskFormatter.js +82 -2
  114. package/dist/utils/MaskFormatter.js.map +1 -1
  115. package/dist/utils/ObjectUtils.d.ts +38 -0
  116. package/dist/utils/ObjectUtils.js +51 -0
  117. package/dist/utils/ObjectUtils.js.map +1 -1
  118. package/dist/utils/OnboardingUtils.js +1 -1
  119. package/dist/utils/OnboardingUtils.js.map +1 -1
  120. package/dist/utils/OverflowWatcher/index.d.ts +59 -0
  121. package/dist/utils/OverflowWatcher/index.js +188 -0
  122. package/dist/utils/OverflowWatcher/index.js.map +1 -0
  123. package/dist/utils/OverflowWatcher/types/overflow-callback.d.ts +6 -0
  124. package/dist/utils/OverflowWatcher/types/overflow-callback.js +2 -0
  125. package/dist/utils/OverflowWatcher/types/overflow-callback.js.map +1 -0
  126. package/dist/utils/OverflowWatcher/types/overflow-direction.d.ts +7 -0
  127. package/dist/utils/OverflowWatcher/types/overflow-direction.js +9 -0
  128. package/dist/utils/OverflowWatcher/types/overflow-direction.js.map +1 -0
  129. package/dist/utils/ServiceUtils.d.ts +24 -0
  130. package/dist/utils/ServiceUtils.js +40 -0
  131. package/dist/utils/ServiceUtils.js.map +1 -0
  132. package/dist/utils/SortingUtils.d.ts +9 -0
  133. package/dist/utils/SortingUtils.js +24 -0
  134. package/dist/utils/SortingUtils.js.map +1 -0
  135. package/dist/utils/StringUtils.d.ts +6 -0
  136. package/dist/utils/StringUtils.js +11 -0
  137. package/dist/utils/StringUtils.js.map +1 -1
  138. package/dist/utils/UserAgentUtils/index.d.ts +1 -0
  139. package/dist/utils/UserAgentUtils/index.js +5 -0
  140. package/dist/utils/UserAgentUtils/index.js.map +1 -1
  141. package/jest.config.ts +2 -0
  142. package/package.json +2 -1
  143. package/reports/test-report.xml +215 -0
  144. package/setupTests.js +7 -0
  145. package/sonar-project.properties +6 -3
  146. package/src/dataunit/DataUnit.ts +268 -86
  147. package/src/dataunit/DataUnitHelper.ts +6 -5
  148. package/src/dataunit/formatting/PrettyFormatter.ts +15 -6
  149. package/src/dataunit/loader/DataUnitInMemoryLoaderConfig.ts +10 -0
  150. package/src/dataunit/loader/dataUnitInMemoryLoader.ts +176 -0
  151. package/src/dataunit/loader/utils/dataUnitLoaderUtils.ts +86 -0
  152. package/src/dataunit/loading/LoadDataRequest.ts +1 -1
  153. package/src/dataunit/loading/PaginationInfo.ts +10 -0
  154. package/src/dataunit/metadata/DataType.ts +3 -0
  155. package/src/dataunit/sorting/FieldComparator.ts +18 -32
  156. package/src/dataunit/state/action/DataUnitAction.ts +2 -0
  157. package/src/dataunit/state/slice/LoadingControlSlice.ts +42 -0
  158. package/src/dataunit/state/slice/RecordsSlice.ts +1 -1
  159. package/src/dataunit/state/slice/SelectionSlice.ts +4 -4
  160. package/src/dataunit/state/slice/test/RecordsSlice.spec.ts +45 -0
  161. package/src/dataunit/test/DataUnit.spec.ts +44 -0
  162. package/src/exceptions/ServiceCanceledException.ts +25 -0
  163. package/src/exceptions/SilentException.ts +25 -0
  164. package/src/index.ts +32 -1
  165. package/src/repository/IRepository.ts +7 -0
  166. package/src/repository/indexeddb/IDBRepository.ts +4 -0
  167. package/src/utils/Base64Utils.ts +13 -0
  168. package/src/utils/CacheManager/index.ts +103 -0
  169. package/src/utils/CacheManager/interfaces/index.ts +5 -0
  170. package/src/utils/ColumnFilterManager.ts +104 -0
  171. package/src/utils/DateUtils.ts +3 -0
  172. package/src/utils/ElementUtils.ts +10 -0
  173. package/src/utils/LockManager.ts +213 -0
  174. package/src/utils/MaskFormatter.ts +93 -2
  175. package/src/utils/ObjectUtils.ts +56 -0
  176. package/src/utils/OnboardingUtils.ts +1 -1
  177. package/src/utils/OverflowWatcher/index.ts +243 -0
  178. package/src/utils/OverflowWatcher/types/overflow-callback.ts +6 -0
  179. package/src/utils/OverflowWatcher/types/overflow-direction.ts +7 -0
  180. package/src/utils/ServiceUtils.ts +36 -0
  181. package/src/utils/SortingUtils.ts +30 -0
  182. package/src/utils/StringUtils.ts +13 -0
  183. package/src/utils/UserAgentUtils/index.ts +6 -1
  184. package/src/utils/test/objectUtils.spec.ts +109 -0
  185. package/test/dataunit/formatting/PrettyFormatter.spec.ts +177 -0
  186. package/test/dataunit/loader/dataUnitInMemoryLoader.spec.ts +221 -0
  187. package/test/dataunit/loader/utils/dataUnitLoaderUtils.spec.ts +158 -0
  188. package/test/util/ColumnFilterManager.spec.ts +133 -0
  189. package/test/util/ElementUtils.spec.ts +34 -0
  190. package/test/util/OverflowWatcher.spec.ts +152 -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,27 +36,32 @@ 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) => 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;
44
- private _interceptors: Array<DUActionInterceptor>;
48
+ private _interceptors: Map<string, DUActionInterceptor>;
45
49
  private _pageSize: number;
46
50
  private _childByName = new Map<string, DataUnit>();
47
51
  private _parentDataUnit: DataUnit | undefined;
48
52
  private _loadingLockers: Promise<void>[];
49
53
  private _savingLockers: Promise<any>[] = [];
50
54
  private _defaultSorting: Array<Sort>;
55
+ private _allowReleaseCallbacks: boolean;
56
+ private _waitingToReload: boolean = false;
57
+ private _cancelPagination: boolean = false;
51
58
 
52
59
  public metadataLoader?: (dataUnit: DataUnit) => Promise<UnitMetadata>;
53
60
  public dataLoader?: (dataUnit: DataUnit, request: LoadDataRequest) => Promise<LoadDataResponse>;
54
61
  public saveLoader?: (dataUnit: DataUnit, changes: Array<Change>) => Promise<Array<SavedRecord>>;
55
62
  public removeLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<string>>;
56
63
  public recordLoader?: (dataUnit: DataUnit, recordIds: Array<string>) => Promise<Array<Record>>;
64
+ public allRecordsLoader?: (dataUnit: DataUnit) => Array<Record> | undefined;
57
65
 
58
66
  constructor(name: string = DataUnit.DEFAULT_DATAUNIT_NAME, parentDataUnit?: DataUnit) {
59
67
  this._uuid = uuid()
@@ -75,11 +83,12 @@ export default class DataUnit {
75
83
  SnapshotReducer
76
84
  ]
77
85
  );
78
- this._observers = [];
86
+ this._observers = new Map();
79
87
  this._filterProviders = new Map<string, FilterProvider>();
80
88
  this._sortingProvider = undefined;
81
89
  this._defaultSorting = [];
82
- this._interceptors = [];
90
+ this._allowReleaseCallbacks = true;
91
+ this._interceptors = new Map();
83
92
  this._parentDataUnit = parentDataUnit;
84
93
  this._parentDataUnit?.subscribe(this.onDataUnitParentEvent);
85
94
  this._loadingLockers = [];
@@ -110,10 +119,12 @@ export default class DataUnit {
110
119
  * - Sorting Providers
111
120
  */
112
121
  public releaseCallbacks(){
113
- this._observers = [];
122
+ if(!this._allowReleaseCallbacks) return;
123
+
124
+ this._observers = new Map();
114
125
  this._filterProviders = new Map<string, FilterProvider>();
115
126
  this._sortingProvider = undefined;
116
- this._interceptors = [];
127
+ this._interceptors = new Map();
117
128
  }
118
129
 
119
130
  /**
@@ -142,6 +153,36 @@ export default class DataUnit {
142
153
  return this._uuid;
143
154
  }
144
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
+
145
186
  /**
146
187
  *
147
188
  * Obtém o nome de identificação do DataUnit (geralmente em formato de URI - Uniform Resource Identifier).
@@ -180,6 +221,8 @@ export default class DataUnit {
180
221
  case Action.NEXT_SELECTED:
181
222
  case Action.PREVIOUS_SELECTED:
182
223
  case Action.DATA_LOADED:
224
+ case Action.RECORDS_ADDED:
225
+ case Action.EDITION_CANCELED:
183
226
  this.clearDataUnit();
184
227
  const selectedRecord = this._parentDataUnit?.getSelectedRecord();
185
228
  if(selectedRecord != undefined && !this.isNewRecord(selectedRecord.__record__id__)){
@@ -241,10 +284,10 @@ export default class DataUnit {
241
284
  async response => {
242
285
  await this.dispatchAction(
243
286
  Action.DATA_LOADED,
244
- {...response, keepSelection: request.keepSelection, filters: request.filters},
287
+ {...response, keepSelection: request.keepSelection, filters: request.filters, selectFirstRecord},
245
288
  executionCtx
246
289
  );
247
-
290
+
248
291
  await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
249
292
 
250
293
  if(selectFirstRecord){
@@ -302,6 +345,10 @@ export default class DataUnit {
302
345
  }
303
346
  }
304
347
 
348
+ public async loadDataWithParams({source, keepSelection, selectFirstRecord, executionCtx, checkLastFilter, quickFilter}: LoadDataParams): Promise<LoadDataResponse> {
349
+ return await this.loadData(quickFilter, executionCtx, checkLastFilter, source, selectFirstRecord, keepSelection);
350
+ }
351
+
305
352
  /**
306
353
  *
307
354
  * Carrega os registros do DataUnit.
@@ -313,20 +360,23 @@ export default class DataUnit {
313
360
  * @returns - Registros requisitados.
314
361
  *
315
362
  */
316
- public async loadData(quickFilter?: QuickFilter, executionCtx?: ExecutionContext, checkLastFilter?: boolean, source?: string, selectFirstRecord?: boolean): Promise<LoadDataResponse> {
363
+ public async loadData(quickFilter?: QuickFilter, executionCtx?: ExecutionContext, checkLastFilter?: boolean, source?: string, selectFirstRecord?: boolean, keepSelection?: boolean): Promise<LoadDataResponse> {
317
364
 
318
365
  await this.processLoadingLockers();
319
366
 
320
- if (this._parentDataUnit && !this._parentDataUnit.getSelectedRecord()) {
367
+ if (this._parentDataUnit) {
368
+ const parentRecord = this._parentDataUnit.getSelectedRecord();
369
+ if(parentRecord == undefined || this._parentDataUnit.isNewRecord(parentRecord.__record__id__)){
321
370
  if(this.records){
322
371
  this.clearDataUnit();
323
372
  }
324
373
  return Promise.resolve({
325
374
  records: []
326
375
  });
376
+ }
327
377
  }
328
378
 
329
- const loadDataRequest = this.getLoadDataRequest(quickFilter, source);
379
+ const loadDataRequest = this.getLoadDataRequest(quickFilter, source, keepSelection);
330
380
  return this.executeLoadData(loadDataRequest, executionCtx, checkLastFilter, selectFirstRecord);
331
381
  }
332
382
 
@@ -336,11 +386,14 @@ export default class DataUnit {
336
386
  *
337
387
  * @param page - Número da página desejada.
338
388
  * @param executionCtx - Contexto de execução do carregamento dos registros do DataUnit.
339
- *
389
+ *
340
390
  * @returns - Registros da página desejada.
341
391
  *
342
392
  */
343
393
  public async gotoPage(page: number, executionCtx?: ExecutionContext): Promise<LoadDataResponse | void> {
394
+ if(this._pageSize === 0) {
395
+ return;
396
+ }
344
397
 
345
398
  let request = getCurrentRequest(this._stateManager);
346
399
 
@@ -388,12 +441,13 @@ export default class DataUnit {
388
441
  return this.gotoPage(getCurrentPage(this._stateManager) - 1, executionCtx);
389
442
  }
390
443
 
391
- private getLoadDataRequest(quickFilter?: QuickFilter, source?: string): LoadDataRequest {
444
+ private getLoadDataRequest(quickFilter?: QuickFilter, source?: string, keepSelection?: boolean): LoadDataRequest {
392
445
  const request: LoadDataRequest = {
393
446
  filters: quickFilter?.filter ? [quickFilter.filter] : this.getFilters(),
394
447
  sort: this.getSort(),
395
448
  parentRecordId: this.getParentRecordId(),
396
- source
449
+ source,
450
+ keepSelection
397
451
  };
398
452
 
399
453
  if (quickFilter) {
@@ -471,7 +525,16 @@ export default class DataUnit {
471
525
  Promise.all(dispatchPromisses).then(() => resolve());
472
526
  }).catch(cause => {
473
527
  const {errorCode} = cause;
528
+ this.dispatchAction(Action.SAVING_ERROR);
474
529
  this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
530
+ if(cause instanceof ServiceCanceledException){
531
+ console.debug("Service canceled: " + cause.message);
532
+ resolve();
533
+ }
534
+ if(cause instanceof SilentException){
535
+ fail(cause);
536
+ return;
537
+ }
475
538
  fail(new ErrorException("Erro ao salvar alterações", cause, errorCode));
476
539
  });
477
540
  } else {
@@ -541,8 +604,8 @@ export default class DataUnit {
541
604
  if(selection.isAllRecords()){
542
605
  throw new Error("Exclusão remota não implementada.");
543
606
  }
544
- const records = selection?.records || [];
545
- const recordIds = selection?.recordIds || [];
607
+ const records = selection?.records as Array<Record> || [];
608
+ const recordIds = selection?.recordIds as Array<string> || [];
546
609
  return this.removeRecords(recordIds, records, buffered, undefined, silent);
547
610
  }
548
611
  return Promise.resolve([]);
@@ -576,10 +639,11 @@ export default class DataUnit {
576
639
  const currentRecordsKeys = Array.from(getCurrentRecords(this._stateManager).keys());
577
640
  const removedIndex: Array<number> = recordIds
578
641
  .map(id => currentRecordsKeys.indexOf(id))
579
- .filter(index => index > -1);
642
+ .filter(index => index > -1)
643
+ .sort((a, b) => a - b);
580
644
 
581
645
  const nextIndex = Math.min(removedIndex.slice(-1)[0] + 1, currentRecordsKeys.length);
582
- const selectionAfterRemove = [currentRecordsKeys[nextIndex]];
646
+ const selectionAfterRemove = currentRecordsKeys[nextIndex] ? [currentRecordsKeys[nextIndex]] : [];
583
647
 
584
648
  this.dispatchAction(Action.RECORDS_REMOVED, { records: removedIds, cachedRecords, removedIndex, buffered: false, selectionAfterRemove }, executionCtx);
585
649
  this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
@@ -643,7 +707,6 @@ export default class DataUnit {
643
707
  *
644
708
  */
645
709
  public getFormattedValue(fieldName: string, value?: any): string {
646
-
647
710
  const descriptor = this.getField(fieldName);
648
711
  if (value == undefined) {
649
712
  value = this.getFieldValue(fieldName);
@@ -666,7 +729,7 @@ export default class DataUnit {
666
729
  *
667
730
  */
668
731
  public addInterceptor(interceptor: DUActionInterceptor): void {
669
- this._interceptors.push(interceptor);
732
+ this._interceptors.set(interceptor.interceptAction.toString(), interceptor);
670
733
  }
671
734
 
672
735
  /**
@@ -677,7 +740,7 @@ export default class DataUnit {
677
740
  *
678
741
  */
679
742
  public removeInterceptor(interceptor: DUActionInterceptor) {
680
- this._interceptors = this._interceptors.filter(i => i !== interceptor);
743
+ this._interceptors.delete(interceptor.interceptAction.toString())
681
744
  }
682
745
 
683
746
  /**
@@ -722,6 +785,7 @@ export default class DataUnit {
722
785
  return this.dispatchAction(Action.PAGINATION_UPDATED, info, undefined);
723
786
  }
724
787
 
788
+
725
789
  /**
726
790
  *
727
791
  * Define a lógica de ordenação dos registros.
@@ -786,7 +850,8 @@ export default class DataUnit {
786
850
  *
787
851
  */
788
852
  public set records(records: Array<Record>) {
789
- this.dispatchAction(Action.DATA_LOADED, { records }, undefined);
853
+ const paginationInfo = this.getPaginationInfo();
854
+ this.dispatchAction(Action.DATA_LOADED, { records, paginationInfo }, undefined);
790
855
  }
791
856
 
792
857
  /**
@@ -879,8 +944,12 @@ export default class DataUnit {
879
944
  public copySelected(executionCtx?: ExecutionContext): void {
880
945
  const selectionInfo = this.getSelectionInfo();
881
946
  if (selectionInfo) {
882
- const selectedRecords = selectionInfo.records;
947
+ if(selectionInfo.isAllRecords()){
948
+ throw new Error("Erro interno: Impossível copiar os registros selecionados pois a seleção atual é virtual.");
949
+ }
950
+ const selectedRecords = selectionInfo.records as Array<Record>;
883
951
  if(selectedRecords){
952
+
884
953
  this.dispatchAction(Action.RECORDS_COPIED, prepareCopiedRecord(this._stateManager, selectedRecords, this.getParentRecordId()), executionCtx);
885
954
  }
886
955
  }
@@ -946,21 +1015,31 @@ export default class DataUnit {
946
1015
  * @param fieldName -Identificador do campo a ser modificado.
947
1016
  * @param newValue - Valor a ser inserido no campo.
948
1017
  * @param records - Indica quais registros foram afetados pela alteração no valor do campo.
1018
+ * @param options - Configurações do evento
949
1019
  * @returns - Promise que será resolvida quando o novo valor for persistido no state.
950
- *
951
- */
952
- public async setFieldValue(fieldName: string, newValue: any, records?: Array<string>): Promise<boolean> {
1020
+ *
1021
+ */
1022
+ public async setFieldValue(fieldName: string, newValue: any, records?: Array<string>, options?:DataUnitEventOptions): Promise<boolean> {
1023
+ const noRecordSelected = !this.hasNewRecord() && !this.getSelectedRecord();
1024
+
1025
+ const suppressCreateNewRecord = options?.suppressCreateNewRecord;
1026
+
1027
+ if(noRecordSelected && suppressCreateNewRecord) return Promise.resolve(false);
1028
+
1029
+ if(noRecordSelected) await this.addRecord();
953
1030
 
954
- if(!this.hasNewRecord() && !this.getSelectedRecord()) await this.addRecord();
955
-
956
1031
  const typedValue = this.validateAndTypeValue(fieldName, newValue);
957
1032
  const currentValue = this.getFieldValue(fieldName);
958
-
1033
+
1034
+ if(!(newValue instanceof Promise) && ObjectUtils.hasEquivalentProps(currentValue, typedValue)){
1035
+ return Promise.resolve(false);
1036
+ }
1037
+
959
1038
  if(newValue instanceof Promise){
960
1039
  const promise:Promise<boolean> = new Promise(accept => {
961
1040
  newValue.then(resolvedValue => {
962
1041
  this.dispatchAction(Action.DATA_RESOLVED, { [fieldName]: resolvedValue, records }, undefined);
963
- accept(this.setFieldValue(fieldName, resolvedValue, records));
1042
+ accept(this.setFieldValue(fieldName, resolvedValue, records, options));
964
1043
  });
965
1044
  });
966
1045
  this._savingLockers.push(promise);
@@ -968,7 +1047,7 @@ export default class DataUnit {
968
1047
  }
969
1048
 
970
1049
  if (currentValue !== typedValue) {
971
- const promise = this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records }, undefined);
1050
+ const promise = this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records }, undefined, options);
972
1051
  this._savingLockers.push(promise);
973
1052
  return promise;
974
1053
  }
@@ -989,6 +1068,18 @@ export default class DataUnit {
989
1068
  this.dispatchAction(Action.FIELD_INVALIDATED, { fieldName, message, recordId }, undefined);
990
1069
  }
991
1070
 
1071
+ /**
1072
+ *
1073
+ * Cancela o saving exibindo os campos invalidos.
1074
+ *
1075
+ * @param filds - Lista dos campos
1076
+ * @param recordId - Indica qual registro está com os campos inválido.
1077
+ *
1078
+ */
1079
+ public savingCanceled(fields: Array<{name: string, message: string}>, recordId: string): void {
1080
+ this.dispatchAction(Action.SAVING_CANCELED, { fields, recordId }, undefined);
1081
+ }
1082
+
992
1083
  /**
993
1084
  *
994
1085
  * Limpa campos inválidos.
@@ -1096,7 +1187,7 @@ export default class DataUnit {
1096
1187
  public setSelection(selection: Array<string> | SelectionMode.ALL_RECORDS, executionCtx?: ExecutionContext): Promise<SelectionInfo> {
1097
1188
  return new Promise(resolve => {
1098
1189
  this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection }, executionCtx)
1099
- .then(()=>resolve(getSelectionInfo(this._stateManager)));
1190
+ .then(()=>resolve(this.getSelectionInfo()));
1100
1191
  });
1101
1192
  }
1102
1193
 
@@ -1117,35 +1208,53 @@ export default class DataUnit {
1117
1208
  *
1118
1209
  * @param selection - IDs dos registros selecionados no snapshot atual
1119
1210
  * @param executionCtx - Contexto de execução da seleção dos registros do DataUnit.
1120
- *
1121
1211
  * @returns - Informações sobre a seleção.
1122
1212
  */
1123
1213
  public updatePageSelection(selection: Array<string>, executionCtx?: ExecutionContext): Promise<SelectionInfo|undefined>{
1124
-
1125
- if(!selection){
1126
- return Promise.resolve(this.getSelectionInfo());
1127
- }
1214
+ if(!selection) return Promise.resolve(this.getSelectionInfo());
1128
1215
 
1129
1216
  return new Promise(resolve => {
1130
- const newSelection: Set<string> = new Set(getSelection(this._stateManager));
1131
- const currentRecords = getCurrentRecords(this._stateManager) || new Map();
1132
- Array.from(currentRecords.keys()).forEach(
1133
- recordId => {
1134
- if(selection.includes(recordId)){
1135
- newSelection.add(recordId);
1136
- } else {
1137
- newSelection.delete(recordId);
1138
- }
1139
- }
1140
- );
1217
+ const newSelection: Set<string> = new Set(selection);
1141
1218
 
1142
1219
  this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection: Array.from(newSelection) }, executionCtx)
1143
- .then(()=>{
1144
- resolve(this.getSelectionInfo())
1145
- });
1220
+ .then(()=> resolve(this.getSelectionInfo()));
1146
1221
  });
1147
1222
  }
1148
1223
 
1224
+
1225
+ private updatePageSelectionAll(addRecords: boolean): Promise<SelectionInfo|undefined>{
1226
+ return new Promise(resolve => {
1227
+ const newSelection: Set<string> = new Set<string>();
1228
+
1229
+ const cachedSelection = getSelection(this._stateManager);
1230
+ cachedSelection.forEach(item => newSelection.add(item));
1231
+
1232
+ const recordsIds = this.records.map(r => r.__record__id__);
1233
+ recordsIds.forEach(id => addRecords ? newSelection.add(id): newSelection.delete(id));
1234
+
1235
+ this.dispatchAction(Action.SELECTION_CHANGED, { type: "id", selection: Array.from(newSelection) })
1236
+ .then(()=> resolve(this.getSelectionInfo()));
1237
+ });
1238
+ }
1239
+
1240
+ /**
1241
+ * Seleciona todos os registros da página.
1242
+ *
1243
+ * @returns - Informações sobre a seleção.
1244
+ */
1245
+ public selectAllRecords(): Promise<SelectionInfo|undefined>{
1246
+ return this.updatePageSelectionAll(true);
1247
+ }
1248
+
1249
+ /**
1250
+ * Desseleciona todos os registros da página.
1251
+ *
1252
+ * @returns - Informações sobre a seleção.
1253
+ */
1254
+ public unSelectAllRecords(): Promise<SelectionInfo|undefined>{
1255
+ return this.updatePageSelectionAll(false);
1256
+ }
1257
+
1149
1258
  /**
1150
1259
  *
1151
1260
  * Obtém informações sobre a seleção atual.
@@ -1153,8 +1262,16 @@ export default class DataUnit {
1153
1262
  * @returns - Objeto com informações como registros selecionados e seleção por critério.
1154
1263
  *
1155
1264
  **/
1156
- public getSelectionInfo(): SelectionInfo | undefined {
1157
- return getSelectionInfo(this._stateManager)
1265
+ public getSelectionInfo(): SelectionInfo{
1266
+ const selectionInfo: SelectionInfo = getSelectionInfo(this._stateManager);
1267
+ selectionInfo.getAllRecords = () => this.allRecordsLoader?.(this);
1268
+
1269
+ if (selectionInfo.sort != undefined && selectionInfo.sort.length > 0) {
1270
+ const sortingFunction = SortingUtils.getSortingFunction(this, selectionInfo.sort)
1271
+ selectionInfo.records?.sort(sortingFunction)
1272
+ }
1273
+
1274
+ return selectionInfo;
1158
1275
  }
1159
1276
 
1160
1277
  /**
@@ -1168,6 +1285,15 @@ export default class DataUnit {
1168
1285
  return getSelectedRecord(this._stateManager);
1169
1286
  }
1170
1287
 
1288
+ /**
1289
+ * Retorna o DataUnit pai
1290
+ *
1291
+ * @returns DataUnit pai ou undefined
1292
+ */
1293
+ public getParentDataUnit(): DataUnit | undefined {
1294
+ return this._parentDataUnit;
1295
+ }
1296
+
1171
1297
  /**
1172
1298
  *
1173
1299
  * Limpa todos os registros do DataUnit
@@ -1255,14 +1381,28 @@ export default class DataUnit {
1255
1381
  /**
1256
1382
  *
1257
1383
  * Retorna se existe algum tipo de alteração pendente.
1258
- *
1384
+ *
1385
+ * @param ignoreChildren: Define se deverá ignorar alterações pendentes no DataUnit filho.
1259
1386
  * @returns Verdadeiro se existir alterações pendentes.
1260
1387
  *
1261
1388
  */
1262
- public isDirty(): boolean {
1389
+ public isDirty(ignoreChildren?: boolean): boolean {
1390
+ if(ignoreChildren) return isDirty(this._stateManager);
1391
+
1263
1392
  return isDirty(this._stateManager) || this.childrenIsDirty();
1264
1393
  }
1265
1394
 
1395
+ /**
1396
+ *
1397
+ * Retorna se existe alterações pendentes no DataUnit pai.
1398
+ *
1399
+ * @returns Verdadeiro se existir alterações pendentes e Falso caso não exista alterações ou não exista DataUnit pai.
1400
+ *
1401
+ */
1402
+ public isParentDirty(): boolean {
1403
+ return this._parentDataUnit ? this._parentDataUnit.isDirty(true) : false;
1404
+ }
1405
+
1266
1406
  /**
1267
1407
  *
1268
1408
  * Retorna se existe algum DataUnit detail com alterações pendentes.
@@ -1435,17 +1575,17 @@ export default class DataUnit {
1435
1575
  * @returns - Verdadeiro se ação iniciada.
1436
1576
  *
1437
1577
  */
1438
- private async dispatchAction(actionType: Action, payload?: any, executionCtx?: ExecutionContext): Promise<boolean> {
1578
+ private async dispatchAction(actionType: Action, payload?: any, executionCtx?: ExecutionContext, options?:DataUnitEventOptions): Promise<boolean> {
1439
1579
  return new Promise(async resolve => {
1440
1580
  let action = new DataUnitAction(actionType, payload);
1441
1581
  if (executionCtx && executionCtx.before) {
1442
1582
  action = executionCtx.before(action);
1443
1583
  }
1444
- if (action && this._interceptors && this._interceptors.length > 0) {
1584
+ if (action && this._interceptors && this._interceptors.size > 0) {
1445
1585
  action = await this.intercept(action, this._interceptors.values());
1446
1586
  }
1447
1587
  if (action) {
1448
- this.doDispatchAction(action);
1588
+ this.doDispatchAction(action, options);
1449
1589
  if (executionCtx && executionCtx.after) {
1450
1590
  executionCtx.after(action)
1451
1591
  }
@@ -1483,16 +1623,13 @@ export default class DataUnit {
1483
1623
  * @param action - Ações em execução no DataUnit.
1484
1624
  *
1485
1625
  */
1486
- private doDispatchAction(action: DataUnitAction): void {
1626
+ private doDispatchAction(action: DataUnitAction, options:DataUnitEventOptions = {}): void {
1487
1627
  this._stateManager.process(action);
1488
1628
  this?._parentDataUnit?.dispatchAction(Action.CHILD_CHANGED, { srcAction: action, srcDataUnit: this });
1489
1629
  this._observers.forEach(f => {
1490
- /*
1491
- if some observer throws exceptions,
1492
- should be continued
1493
- */
1630
+ //if some observer throws exceptions, should be continued
1494
1631
  try {
1495
- f(action);
1632
+ f(action, options);
1496
1633
  } catch (e) {
1497
1634
  console.warn("[DataUnit] error while call observer", e);
1498
1635
  }
@@ -1529,10 +1666,17 @@ export default class DataUnit {
1529
1666
  * Ela vai ser chamada sempre que uma ação for despachada (dispatchAction()).
1530
1667
  *
1531
1668
  * @param observer - Função que recebe como parâmetro as ações que serão monitoradas.
1532
- *
1669
+ * @param uuid - Identificador do observer. Quando não informado, será gerado um identificador aleatório.
1533
1670
  */
1534
- public subscribe(observer: (action: DataUnitAction) => void) {
1535
- this._observers.push(observer);
1671
+ public subscribe(observer: (action: DataUnitAction, options?: DataUnitEventOptions) => void | Promise<void>, uuid?: string): string {
1672
+ if (uuid) {
1673
+ this._observers.set(uuid, observer);
1674
+ } else {
1675
+ uuid = StringUtils.generateUUID();
1676
+ this._observers.set(uuid, observer);
1677
+ }
1678
+
1679
+ return uuid;
1536
1680
  }
1537
1681
 
1538
1682
  /**
@@ -1540,10 +1684,18 @@ export default class DataUnit {
1540
1684
  * Remove um observer existente.
1541
1685
  *
1542
1686
  * @param observer - Observer que se deseja remover.
1543
- *
1687
+ * @param uuid - Identificador do observer. Quando não informado o delete removera com base no equals do observer.
1544
1688
  */
1545
- public unsubscribe(observer: Function) {
1546
- this._observers = this._observers.filter(f => f !== observer);
1689
+ public unsubscribe(observer: Function, uuid?: string) {
1690
+ if (uuid) {
1691
+ this._observers.delete(uuid);
1692
+ } else {
1693
+ this._observers.forEach((valor, chave) => {
1694
+ if (valor == observer) {
1695
+ this._observers.delete(chave);
1696
+ }
1697
+ });
1698
+ }
1547
1699
  }
1548
1700
 
1549
1701
  /**
@@ -1556,18 +1708,21 @@ export default class DataUnit {
1556
1708
  public reloadCurrentRecord(): Promise<Array<Record>>{
1557
1709
  return new Promise(async (resolve, fail) => {
1558
1710
  const selection = getSelection(this._stateManager);
1559
- this.dispatchAction(Action.LOADING_RECORD, selection);
1711
+ await this.dispatchAction(Action.LOADING_RECORD, selection);
1560
1712
 
1561
1713
  if(!this.recordLoader || !this.dataLoader) {
1562
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1714
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1715
+ resolve([]);
1563
1716
  return;
1564
1717
  }
1565
1718
 
1566
- this.recordLoader(this, selection).then(response => {
1567
- this.dispatchAction(Action.RECORD_LOADED, response)
1568
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1569
- }).catch(cause => {
1570
- this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1719
+ this.recordLoader(this, selection).then(async response => {
1720
+ await this.dispatchAction(Action.RECORD_LOADED, response)
1721
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1722
+
1723
+ resolve(response);
1724
+ }).catch(async cause => {
1725
+ await this.dispatchAction(Action.LOADING_PROPERTIES_CLEANED);
1571
1726
  const {errorCode} = cause;
1572
1727
  fail(new ErrorException("Erro ao recarregar registro", cause, errorCode));
1573
1728
  });
@@ -1662,11 +1817,12 @@ export default class DataUnit {
1662
1817
  * @param fieldName - nome do campo para ficar invisível.
1663
1818
  *
1664
1819
  */
1665
- public hideField(fieldName:string) {
1820
+ public hideField(fieldName:string, options:HideFieldOptions) {
1666
1821
  const fieldDescriptor = this.getField(fieldName);
1667
1822
 
1668
1823
  if(fieldDescriptor?.visible === true){
1669
1824
  fieldDescriptor.visible = false;
1825
+ fieldDescriptor.properties = {...fieldDescriptor.properties, visibleOnConfig: options.visibleOnConfig };
1670
1826
  this.metadata = {...this.metadata};
1671
1827
  }
1672
1828
  }
@@ -1706,7 +1862,7 @@ export default class DataUnit {
1706
1862
  }
1707
1863
 
1708
1864
  if (selection) {
1709
- return selection.records;
1865
+ return selection.records as Array<Record>;
1710
1866
  }
1711
1867
  }
1712
1868
 
@@ -1724,12 +1880,15 @@ export default class DataUnit {
1724
1880
  public getSelection(): Array<string> {
1725
1881
  console.warn("DataUnit: O método `getSelection` foi descontinuado. Use o método `getSelectionInfo`.");
1726
1882
  const selection = this.getSelectionInfo();
1883
+ if(selection == undefined){
1884
+ return [];
1885
+ }
1727
1886
 
1728
- if(selection != undefined && selection.isAllRecords()){
1887
+ if(selection.isAllRecords()){
1729
1888
  throw new Error("Erro interno: Impossível retornar os registros selecionados. A seleção atual é virtual. Use o método `getSelectionInfo`.");
1730
1889
  }
1731
1890
 
1732
- return selection?.recordIds || [];
1891
+ return selection?.recordIds as Array<string>;
1733
1892
  }
1734
1893
 
1735
1894
  /**
@@ -1765,6 +1924,10 @@ export default class DataUnit {
1765
1924
  return loadingLockerResolver || Promise.resolve;
1766
1925
  }
1767
1926
 
1927
+ public set allowReleaseCallbacks(allow: boolean){
1928
+ this._allowReleaseCallbacks = allow;
1929
+ }
1930
+
1768
1931
  private async processLoadingLockers(){
1769
1932
  if(this._loadingLockers.length) {
1770
1933
  await Promise.all(this._loadingLockers);
@@ -1774,6 +1937,15 @@ export default class DataUnit {
1774
1937
 
1775
1938
  }
1776
1939
 
1940
+ export interface LoadDataParams {
1941
+ quickFilter?: QuickFilter;
1942
+ executionCtx?: ExecutionContext;
1943
+ checkLastFilter?: boolean;
1944
+ source?: string;
1945
+ selectFirstRecord?: boolean;
1946
+ keepSelection?: boolean
1947
+ }
1948
+
1777
1949
  export interface DUActionInterceptor {
1778
1950
  interceptAction(action: DataUnitAction): DataUnitAction | Promise<DataUnitAction>;
1779
1951
  }
@@ -1906,12 +2078,13 @@ export enum SelectionMode{
1906
2078
 
1907
2079
  export class SelectionInfo{
1908
2080
 
1909
- private _records: Array<Record>;
1910
2081
  public mode: SelectionMode;
1911
- private _total?: number;
1912
2082
  public filters?: Array<Filter>;
1913
2083
  public sort?: Array<Sort>;
1914
-
2084
+ public getAllRecords?: () => Array<Record> | undefined;
2085
+ private _records: Array<Record>;
2086
+ private _total?: number;
2087
+
1915
2088
  constructor(records: Array<Record>, mode: SelectionMode = SelectionMode.SOME_RECORDS, total?:number, filters?: Array<Filter>, sort?: Array<Sort>){
1916
2089
  this._records = records;
1917
2090
  this._total = total;
@@ -1922,7 +2095,10 @@ export class SelectionInfo{
1922
2095
 
1923
2096
  public get records(): Array<Record> | undefined{
1924
2097
  if(this.isAllRecords()){
1925
- throw new Error("Erro interno: [ALL_RECORDS] - Impossível retornar os registros selecionados numa seleção virtual.")
2098
+ if(this.getAllRecords != undefined){
2099
+ return this.getAllRecords();
2100
+ }
2101
+ throw new Error("Erro interno: Impossível retornar os registros selecionados numa seleção virtual.");
1926
2102
  }
1927
2103
  return this._records;
1928
2104
  }
@@ -1941,7 +2117,7 @@ export class SelectionInfo{
1941
2117
  if(this.isAllRecords()){
1942
2118
  return this._total || 0;
1943
2119
  }
1944
- return this.records == undefined ? 0: this.records.length;
2120
+ return this.records == undefined ? 0 : (this.records as Array<Record>).length;
1945
2121
  }
1946
2122
 
1947
2123
  public isAllRecords(): boolean{
@@ -1952,3 +2128,9 @@ export class SelectionInfo{
1952
2128
  return this.length === 0;
1953
2129
  }
1954
2130
  }
2131
+
2132
+ export type DataUnitEventOptions = {[key:string]: any};
2133
+
2134
+ export type HideFieldOptions = {
2135
+ visibleOnConfig: boolean
2136
+ };