@sankhyalabs/core 0.0.0-bugfix-dev-KB-75210.1 → 0.0.0-bugfix-dev-KB-75940.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.docs/classes/Change.md +11 -11
  2. package/.docs/classes/DataUnit.md +154 -120
  3. package/.docs/classes/KeyboardManager.md +79 -9
  4. package/.docs/classes/LockManager.md +73 -15
  5. package/.docs/classes/SelectionInfo.md +12 -12
  6. package/.docs/classes/UserAgentUtils.md +15 -1
  7. package/.docs/enumerations/ChangeOperation.md +4 -4
  8. package/.docs/enumerations/LockManagerOperation.md +12 -0
  9. package/.docs/enumerations/SelectionMode.md +2 -2
  10. package/.docs/interfaces/DUActionInterceptor.md +1 -1
  11. package/.docs/interfaces/PageRequest.md +3 -3
  12. package/.docs/interfaces/PaginationInfo.md +12 -0
  13. package/.docs/interfaces/QuickFilter.md +3 -3
  14. package/.docs/interfaces/Record.md +4 -4
  15. package/.docs/interfaces/SavedRecord.md +5 -5
  16. package/.docs/interfaces/WaitingChange.md +3 -3
  17. package/.docs/type-aliases/DataUnitEventOptions.md +1 -1
  18. package/dist/dataunit/DataUnit.d.ts +9 -0
  19. package/dist/dataunit/DataUnit.js +25 -9
  20. package/dist/dataunit/DataUnit.js.map +1 -1
  21. package/dist/dataunit/formatting/PrettyFormatter.js +4 -0
  22. package/dist/dataunit/formatting/PrettyFormatter.js.map +1 -1
  23. package/dist/dataunit/loading/PaginationInfo.d.ts +4 -0
  24. package/dist/dataunit/state/slice/LoadingControlSlice.js +16 -0
  25. package/dist/dataunit/state/slice/LoadingControlSlice.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/utils/KeyboardManager/index.d.ts +4 -0
  30. package/dist/utils/KeyboardManager/index.js +37 -1
  31. package/dist/utils/KeyboardManager/index.js.map +1 -1
  32. package/dist/utils/KeyboardManager/interface.d.ts +1 -0
  33. package/dist/utils/LockManager.d.ts +15 -3
  34. package/dist/utils/LockManager.js +52 -2
  35. package/dist/utils/LockManager.js.map +1 -1
  36. package/dist/utils/UserAgentUtils/index.d.ts +1 -0
  37. package/dist/utils/UserAgentUtils/index.js +5 -0
  38. package/dist/utils/UserAgentUtils/index.js.map +1 -1
  39. package/package.json +1 -1
  40. package/reports/test-report.xml +87 -87
  41. package/src/dataunit/DataUnit.ts +30 -9
  42. package/src/dataunit/formatting/PrettyFormatter.ts +5 -0
  43. package/src/dataunit/loading/PaginationInfo.ts +5 -0
  44. package/src/dataunit/state/slice/LoadingControlSlice.ts +42 -0
  45. package/src/index.ts +1 -1
  46. package/src/utils/KeyboardManager/index.ts +47 -0
  47. package/src/utils/KeyboardManager/interface.ts +1 -0
  48. package/src/utils/LockManager.ts +63 -7
  49. package/src/utils/UserAgentUtils/index.ts +6 -1
@@ -1,4 +1,5 @@
1
1
 
2
+ import { ChangeOperation } from "../../DataUnit.js";
2
3
  import { LoadDataRequest } from "../../loading/LoadDataRequest.js";
3
4
  import { PaginationInfo } from "../../loading/PaginationInfo.js";
4
5
  import { Action } from "../action/DataUnitAction.js";
@@ -16,6 +17,9 @@ class LoadingControlReducerImpl implements ActionReducer {
16
17
  return {...currentState, paginationInfo: action.payload?.paginationInfo};
17
18
  case Action.PAGINATION_UPDATED:
18
19
  return {...currentState, paginationInfo: action.payload};
20
+ case Action.DATA_SAVED:
21
+ return {...currentState, paginationInfo: updatePaginationInfo(stateManager, action.payload)};
22
+
19
23
  }
20
24
  return currentState;
21
25
  }
@@ -56,7 +60,45 @@ export const hasPreviousPages = (stateManager: StateManager): boolean => {
56
60
  return paginationInfo ? paginationInfo.currentPage > 0 : false;
57
61
  }
58
62
 
63
+ const updatePaginationInfo = (stateManager: StateManager, payload: Payload): PaginationInfo =>{
64
+ const paginationInfo = getPaginationInfo(stateManager);
65
+ let { records, changes } = payload;
66
+
67
+ if(!records || !changes || !paginationInfo || !validateNewRecordOperation(changes)) return paginationInfo as PaginationInfo;
68
+
69
+ const { count, firstRecord, lastRecord, total } = paginationInfo;
70
+
71
+ return {
72
+ ...paginationInfo,
73
+ count: (count ?? 0) + records.length,
74
+ firstRecord: firstRecord === 0 && records.length > 0 ? 1 : firstRecord,
75
+ lastRecord: lastRecord + records.length,
76
+ total: (total ?? 0) + records.length
77
+ }
78
+
79
+ }
80
+
81
+ const validateNewRecordOperation = (changes: Array<Change>): boolean => {
82
+ return changes.every(change => isNewRecordOperation(change._operation));
83
+ };
84
+
85
+ const isNewRecordOperation = (operation: string): operation is ChangeOperation => {
86
+ return ["INSERT", "COPY"].includes(operation);
87
+ };
88
+
59
89
  interface LoadingControlState{
60
90
  lastRequest: LoadDataRequest;
61
91
  paginationInfo: PaginationInfo;
92
+ }
93
+
94
+ interface Change {
95
+ dataUnit: string;
96
+ record: Record<string, any>;
97
+ updatingFields: Record<string, any>;
98
+ _operation: string;
99
+ }
100
+
101
+ interface Payload {
102
+ changes: Change[];
103
+ records: Record<string, any>[];
62
104
  }
package/src/index.ts CHANGED
@@ -123,5 +123,5 @@ export {
123
123
  OVERFLOWED_CLASS_NAME,
124
124
  DataUnitEventOptions,
125
125
  ServiceCanceledException,
126
- SilentException,
126
+ SilentException
127
127
  };
@@ -9,6 +9,7 @@ import { keyCodeEventValues } from "./keyCodes/index.js";
9
9
  */
10
10
  export class KeyboardManager {
11
11
  private _options: IKeyboardOptions;
12
+ private _shadowRoots: ShadowRoot [] = [];
12
13
  private _mappedElements: IKeyboardMappedKeysElements = {};
13
14
 
14
15
  /**
@@ -22,10 +23,48 @@ export class KeyboardManager {
22
23
  propagate: false,
23
24
  element: document.body,
24
25
  debounceTime: 0,
26
+ enableShadowDom: false,
25
27
  ...options
26
28
  }
29
+
30
+ if(this._options.enableShadowDom) {
31
+ this._shadowRoots = this.findAllNestedShadowRoots(this._options.element);
32
+ }
27
33
  }
28
34
 
35
+ private findAllNestedShadowRoots(element: HTMLElement | Element | ChildNode | Document , results: ShadowRoot [] = []): ShadowRoot [] {
36
+ if (!element) {
37
+ return results;
38
+ }
39
+
40
+ const shadowRoot = (element as HTMLElement)?.shadowRoot;
41
+ if (shadowRoot) {
42
+ results.push(shadowRoot);
43
+
44
+ shadowRoot.querySelectorAll("*").forEach((child) => {
45
+ this.findAllNestedShadowRoots(child, results);
46
+ });
47
+ }
48
+
49
+ element.childNodes.forEach((child) => {
50
+ this.findAllNestedShadowRoots(child, results);
51
+ });
52
+
53
+ return results;
54
+ }
55
+
56
+ private addEventListenerToNestedShadowRoots(event: 'keydown' | 'keyup', callback: VoidFunction) {
57
+ this._shadowRoots.forEach((shadowRoot) => {
58
+ shadowRoot.addEventListener(event, callback);
59
+ });
60
+ }
61
+
62
+ private removeEventListenerToNestedShadowRoots(event: 'keydown' | 'keyup', callback: VoidFunction) {
63
+ this._shadowRoots.forEach((shadowRoot) => {
64
+ shadowRoot.removeEventListener(event, callback);
65
+ });
66
+ }
67
+
29
68
  /**
30
69
  * Associa um evento de teclado com uma função
31
70
  *
@@ -61,6 +100,10 @@ export class KeyboardManager {
61
100
 
62
101
  bindOptions.element.addEventListener(bindOptions.type, debounceFunction);
63
102
 
103
+ if(bindOptions.enableShadowDom) {
104
+ this.addEventListenerToNestedShadowRoots(bindOptions.type, debounceFunction);
105
+ }
106
+
64
107
  return this;
65
108
  }
66
109
 
@@ -86,6 +129,10 @@ export class KeyboardManager {
86
129
 
87
130
  element.removeEventListener(type, callback);
88
131
 
132
+ if(unbindElement.options.enableShadowDom) {
133
+ this.removeEventListenerToNestedShadowRoots(type, callback);
134
+ }
135
+
89
136
  return this;
90
137
  }
91
138
 
@@ -1,6 +1,7 @@
1
1
  export interface IKeyboardOptions {
2
2
  type: 'keydown' | 'keyup',
3
3
  propagate: boolean,
4
+ enableShadowDom: boolean,
4
5
  element: HTMLElement | Document,
5
6
  debounceTime: number,
6
7
  description?: string,
@@ -6,7 +6,11 @@ export enum LockManagerOperation {
6
6
  /**
7
7
  Operação de lock utilizada para controlar cliques nos botoes da taskbar.
8
8
  */
9
- TASKBAR_CLICK = "taskbar_click"
9
+ TASKBAR_CLICK = "taskbar_click",
10
+ /**
11
+ Operação de lock utilizada para controlar carregamento da aplicação.
12
+ */
13
+ APP_LOADING = "app_loading"
10
14
  }
11
15
 
12
16
  type Lock = {
@@ -72,7 +76,7 @@ export class LockManager{
72
76
  }
73
77
  });
74
78
  };
75
-
79
+
76
80
  /**
77
81
  * Cria um contexto de locker, caso nao exista, para todos elementos pais iniciados com ez- ou snk-.
78
82
  *
@@ -103,6 +107,30 @@ export class LockManager{
103
107
  }
104
108
  }
105
109
 
110
+ /**
111
+ * Reseta todos os locks existentes para um determinado contexto e operação de forma assíncrona
112
+ * @param id - ID do contexto ou elemento HTML contendo contexto
113
+ * @param operation - Operação específica para resetar os locks
114
+ * @returns Promise que será resolvida quando todos os locks forem resetados
115
+ */
116
+ public static async resetLocks(id: string | HTMLElement, operation: LockManagerOperation): Promise<void> {
117
+ const lockerId = this.buildLockerID(id, operation);
118
+ if (!lockerId) return;
119
+
120
+ const currentLocks = this._locks.get(lockerId);
121
+
122
+ if (currentLocks?.length) {
123
+ await Promise.all(currentLocks.map(lock => {
124
+ lock.done = true;
125
+ lock.resolve?.();
126
+ return lock.promise;
127
+ }));
128
+
129
+ this._locks.delete(lockerId);
130
+ }
131
+ }
132
+
133
+
106
134
  /**
107
135
  * Inicia um locker baseado em um contexto e uma operação.
108
136
  *
@@ -111,7 +139,7 @@ export class LockManager{
111
139
  *
112
140
  * @returns - Uma função que fara a liberação do lock.
113
141
  */
114
- public static lock(id:string|HTMLElement, operation:LockManagerOperation): any{
142
+ public static lock(id:string|HTMLElement, operation:LockManagerOperation): () => void {
115
143
  const lockerId = LockManager.buildLockerID(id, operation);
116
144
 
117
145
  if(!lockerId) return () => {};
@@ -122,7 +150,6 @@ export class LockManager{
122
150
 
123
151
  const currentLocks = LockManager._locks.get(lockerId) ?? [];
124
152
  currentLocks.push(lock);
125
-
126
153
  LockManager._locks.set(lockerId, currentLocks);
127
154
 
128
155
  return () => {
@@ -139,19 +166,48 @@ export class LockManager{
139
166
  *
140
167
  * @returns - Promise que será resolvida quando todos lockers forem finalizados.
141
168
  */
142
- public static async whenResolve(id:string|HTMLElement, operation:LockManagerOperation): Promise<void> {
169
+ public static async whenResolve(id:string|HTMLElement, operation:LockManagerOperation, debounce?: number, timeOut?: number): Promise<void> {
143
170
  const lockerId = LockManager.buildLockerID(id, operation);
144
171
 
145
172
  if(!lockerId) return;
146
173
 
174
+ if(debounce) await new Promise(resolve => setTimeout(resolve, debounce));
175
+
176
+ const startTime = Date.now();
177
+
147
178
  while (LockManager._locks.get(lockerId)?.length) {
179
+
180
+ if (timeOut && Date.now() - startTime >= timeOut) {
181
+ await this.resetLocks(id, operation);
182
+ return;
183
+ }
184
+
148
185
  const locks:Array<Lock> = LockManager._locks.get(lockerId) ?? [];
149
186
  await Promise.all(locks.map(lock => lock.promise));
150
187
 
151
188
  //Aguarda listeners da tela reagirem as mudancas de estado do dataunit
152
- await new Promise(resolve => setTimeout(resolve, 200));
153
-
189
+ await new Promise(resolve => setTimeout(resolve, debounce || 200));
190
+
154
191
  LockManager._locks.set(lockerId, locks.filter(lock => !lock.done));
192
+ }
193
+
194
+ }
195
+
196
+ public static async whenHasLock(id:string|HTMLElement, operation:LockManagerOperation, timeOut?: number): Promise<void> {
197
+ const lockerId = LockManager.buildLockerID(id, operation);
198
+
199
+ if(!lockerId) return;
200
+
201
+ const startTime = Date.now();
202
+
203
+ while (!LockManager._locks.get(lockerId)?.length) {
204
+
205
+ if (timeOut && Date.now() - startTime >= timeOut) {
206
+ await this.resetLocks(id, operation);
207
+ return;
208
+ }
209
+
210
+ await new Promise(resolve => setTimeout(resolve, 200));
155
211
  }
156
212
  }
157
213
  }
@@ -15,6 +15,11 @@ export class UserAgentUtils {
15
15
  return !!browser.firefox;
16
16
  }
17
17
 
18
+ public static isElectron() {
19
+ const browser = this.getBrowserInfo();
20
+ return !!browser.electron;
21
+ }
22
+
18
23
  /**
19
24
  * Obtém nome e versão do navegador que está sendo utilizado.
20
25
  * @returns Objeto com o nome e versão do navegador.
@@ -40,6 +45,7 @@ export class UserAgentUtils {
40
45
  }
41
46
  } catch (e) {
42
47
  //ignored
48
+ console.warn(e);
43
49
  }
44
50
 
45
51
  browser = {
@@ -49,7 +55,6 @@ export class UserAgentUtils {
49
55
  simpleVersion,
50
56
  ...(Array.isArray(type) ? type.reduce((acc, val) => ({ ...acc, [val]: true}), {}) : { [type]: true })
51
57
  }
52
-
53
58
  return !hasFound;
54
59
  }
55
60
  })