@sankhyalabs/core 1.0.38 → 1.0.42

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 (156) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +34 -0
  3. package/README.md +54 -54
  4. package/dist/application/Application.d.ts +8 -0
  5. package/dist/application/Application.js +19 -0
  6. package/dist/application/Application.js.map +1 -0
  7. package/dist/dataunit/DataUnit.d.ts +82 -80
  8. package/dist/dataunit/DataUnit.js +278 -254
  9. package/dist/dataunit/DataUnit.js.map +1 -1
  10. package/dist/dataunit/metadata/DataType.d.ts +9 -9
  11. package/dist/dataunit/metadata/DataType.js +36 -36
  12. package/dist/dataunit/metadata/DataType.js.map +1 -1
  13. package/dist/dataunit/metadata/UnitMetadata.d.ts +71 -71
  14. package/dist/dataunit/metadata/UnitMetadata.js +31 -31
  15. package/dist/dataunit/state/HistReducer.d.ts +10 -10
  16. package/dist/dataunit/state/HistReducer.js +27 -27
  17. package/dist/dataunit/state/HistReducer.js.map +1 -1
  18. package/dist/dataunit/state/StateManager.d.ts +57 -57
  19. package/dist/dataunit/state/StateManager.js +96 -96
  20. package/dist/dataunit/state/action/DataUnitAction.d.ts +28 -27
  21. package/dist/dataunit/state/action/DataUnitAction.js +33 -32
  22. package/dist/dataunit/state/action/DataUnitAction.js.map +1 -1
  23. package/dist/dataunit/state/slice/AddedRecordsSlice.d.ts +11 -11
  24. package/dist/dataunit/state/slice/AddedRecordsSlice.js +25 -25
  25. package/dist/dataunit/state/slice/AddedRecordsSlice.js.map +1 -1
  26. package/dist/dataunit/state/slice/ChangesSlice.d.ts +12 -12
  27. package/dist/dataunit/state/slice/ChangesSlice.js +72 -72
  28. package/dist/dataunit/state/slice/ChangesSlice.js.map +1 -1
  29. package/dist/dataunit/state/slice/CurrentRecordsSlice.d.ts +11 -11
  30. package/dist/dataunit/state/slice/CurrentRecordsSlice.js +45 -45
  31. package/dist/dataunit/state/slice/CurrentRecordsSlice.js.map +1 -1
  32. package/dist/dataunit/state/slice/RecordsSlice.d.ts +10 -10
  33. package/dist/dataunit/state/slice/RecordsSlice.js +43 -37
  34. package/dist/dataunit/state/slice/RecordsSlice.js.map +1 -1
  35. package/dist/dataunit/state/slice/RemovedRecordsSlice.d.ts +9 -9
  36. package/dist/dataunit/state/slice/RemovedRecordsSlice.js +24 -20
  37. package/dist/dataunit/state/slice/RemovedRecordsSlice.js.map +1 -1
  38. package/dist/dataunit/state/slice/SelectionSlice.d.ts +11 -11
  39. package/dist/dataunit/state/slice/SelectionSlice.js +111 -111
  40. package/dist/dataunit/state/slice/SelectionSlice.js.map +1 -1
  41. package/dist/dataunit/state/slice/UnitMetadataSlice.d.ts +11 -11
  42. package/dist/dataunit/state/slice/UnitMetadataSlice.js +20 -20
  43. package/dist/dataunit/state/slice/UnitMetadataSlice.js.map +1 -1
  44. package/dist/http/AuthorizedServiceCaller.d.ts +11 -11
  45. package/dist/http/AuthorizedServiceCaller.js +53 -53
  46. package/dist/http/AuthorizedServiceCaller.js.map +1 -1
  47. package/dist/http/HttpProvider.d.ts +25 -25
  48. package/dist/http/HttpProvider.js +73 -73
  49. package/dist/http/HttpProvider.js.map +1 -1
  50. package/dist/http/RequestMetadata.d.ts +30 -30
  51. package/dist/http/RequestMetadata.js +24 -24
  52. package/dist/http/SkwHttpProvider.d.ts +9 -9
  53. package/dist/http/SkwHttpProvider.js +66 -67
  54. package/dist/http/SkwHttpProvider.js.map +1 -1
  55. package/dist/http/data-fetcher/HttpFetcher.d.ts +14 -0
  56. package/dist/http/data-fetcher/HttpFetcher.js +164 -0
  57. package/dist/http/data-fetcher/HttpFetcher.js.map +1 -0
  58. package/dist/http/data-fetcher/default/DefaultGraphQL.d.ts +3 -0
  59. package/dist/http/data-fetcher/default/DefaultGraphQL.js +18 -0
  60. package/dist/http/data-fetcher/default/DefaultGraphQL.js.map +1 -0
  61. package/dist/http/data-fetcher/default/application-config-fetcher.d.ts +6 -0
  62. package/dist/http/data-fetcher/default/application-config-fetcher.js +21 -0
  63. package/dist/http/data-fetcher/default/application-config-fetcher.js.map +1 -0
  64. package/dist/http/data-fetcher/default/data-unit-graphql.d.ts +3 -0
  65. package/dist/http/data-fetcher/default/data-unit-graphql.js +18 -0
  66. package/dist/http/data-fetcher/default/data-unit-graphql.js.map +1 -0
  67. package/dist/http/data-fetcher/default/dataunit-executor.d.ts +10 -0
  68. package/dist/http/data-fetcher/default/dataunit-executor.js +56 -0
  69. package/dist/http/data-fetcher/default/dataunit-executor.js.map +1 -0
  70. package/dist/http/data-fetcher/default/dataunit-fetcher.d.ts +9 -0
  71. package/dist/http/data-fetcher/default/dataunit-fetcher.js +69 -0
  72. package/dist/http/data-fetcher/default/dataunit-fetcher.js.map +1 -0
  73. package/dist/http/data-fetcher/default/form-config-fetcher.d.ts +2 -0
  74. package/dist/http/data-fetcher/default/form-config-fetcher.js +3 -0
  75. package/dist/http/data-fetcher/default/form-config-fetcher.js.map +1 -0
  76. package/dist/http/data-fetcher/default/grid-config-fetcher.d.ts +2 -0
  77. package/dist/http/data-fetcher/default/grid-config-fetcher.js +3 -0
  78. package/dist/http/data-fetcher/default/grid-config-fetcher.js.map +1 -0
  79. package/dist/http/data-fetcher/default/index.d.ts +0 -0
  80. package/dist/http/data-fetcher/default/index.js +2 -0
  81. package/dist/http/data-fetcher/default/index.js.map +1 -0
  82. package/dist/http/data-fetcher/default/sankhya-graphql.d.ts +3 -0
  83. package/dist/http/data-fetcher/default/sankhya-graphql.js +8 -0
  84. package/dist/http/data-fetcher/default/sankhya-graphql.js.map +1 -0
  85. package/dist/http/data-fetcher/graphql/DefaultGraphQl.d.ts +3 -0
  86. package/dist/http/data-fetcher/graphql/DefaultGraphQl.js +18 -0
  87. package/dist/http/data-fetcher/graphql/DefaultGraphQl.js.map +1 -0
  88. package/dist/http/data-fetcher/state/LoadStateManager.d.ts +23 -0
  89. package/dist/http/data-fetcher/state/LoadStateManager.js +78 -0
  90. package/dist/http/data-fetcher/state/LoadStateManager.js.map +1 -0
  91. package/dist/index.d.ts +16 -16
  92. package/dist/index.js +17 -17
  93. package/dist/index.js.map +1 -1
  94. package/dist/ui/FloatingManager.d.ts +24 -24
  95. package/dist/ui/FloatingManager.js +122 -123
  96. package/dist/ui/FloatingManager.js.map +1 -1
  97. package/dist/utils/ApplicationContext.d.ts +5 -5
  98. package/dist/utils/ApplicationContext.js +16 -16
  99. package/dist/utils/ApplicationContext.js.map +1 -1
  100. package/dist/utils/CriteriaModel.d.ts +109 -109
  101. package/dist/utils/CriteriaModel.js +173 -173
  102. package/dist/utils/CriteriaParameter.d.ts +69 -69
  103. package/dist/utils/CriteriaParameter.js +82 -84
  104. package/dist/utils/CriteriaParameter.js.map +1 -1
  105. package/dist/utils/DateUtils.d.ts +5 -5
  106. package/dist/utils/DateUtils.js +42 -42
  107. package/dist/utils/DateUtils.js.map +1 -1
  108. package/dist/utils/MaskFormatter.d.ts +126 -126
  109. package/dist/utils/MaskFormatter.js +275 -275
  110. package/dist/utils/NumberUtils.d.ts +53 -53
  111. package/dist/utils/NumberUtils.js +141 -146
  112. package/dist/utils/NumberUtils.js.map +1 -1
  113. package/dist/utils/StringUtils.d.ts +18 -18
  114. package/dist/utils/StringUtils.js +53 -53
  115. package/dist/utils/TimeFormatter.d.ts +33 -33
  116. package/dist/utils/TimeFormatter.js +97 -97
  117. package/dist/utils/TimeFormatter.js.map +1 -1
  118. package/jest.config.ts +16 -13
  119. package/mock/http/XMLHttpRequest-mock.js +25 -25
  120. package/package.json +37 -31
  121. package/src/dataunit/DataUnit.ts +356 -333
  122. package/src/dataunit/metadata/DataType.ts +37 -37
  123. package/src/dataunit/metadata/UnitMetadata.ts +82 -82
  124. package/src/dataunit/state/HistReducer.ts +33 -33
  125. package/src/dataunit/state/StateManager.ts +141 -141
  126. package/src/dataunit/state/action/DataUnitAction.ts +50 -48
  127. package/src/dataunit/state/slice/AddedRecordsSlice.ts +32 -32
  128. package/src/dataunit/state/slice/ChangesSlice.ts +90 -90
  129. package/src/dataunit/state/slice/CurrentRecordsSlice.ts +53 -53
  130. package/src/dataunit/state/slice/RecordsSlice.ts +56 -49
  131. package/src/dataunit/state/slice/RemovedRecordsSlice.ts +29 -25
  132. package/src/dataunit/state/slice/SelectionSlice.ts +130 -130
  133. package/src/dataunit/state/slice/UnitMetadataSlice.ts +29 -29
  134. package/src/http/AuthorizedServiceCaller.ts +58 -57
  135. package/src/http/HttpProvider.ts +93 -93
  136. package/src/http/RequestMetadata.ts +41 -41
  137. package/src/http/SkwHttpProvider.ts +77 -77
  138. package/src/index.ts +44 -44
  139. package/src/ui/FloatingManager.ts +165 -165
  140. package/src/utils/ApplicationContext.ts +18 -18
  141. package/src/utils/CriteriaModel.ts +207 -207
  142. package/src/utils/CriteriaParameter.ts +107 -107
  143. package/src/utils/DateUtils.ts +52 -52
  144. package/src/utils/MaskFormatter.ts +322 -322
  145. package/src/utils/NumberUtils.ts +175 -175
  146. package/src/utils/StringUtils.ts +60 -60
  147. package/src/utils/TimeFormatter.ts +97 -97
  148. package/test/http/HttpProvider.spec.ts +34 -34
  149. package/test/http/SkwHttpProvider.ts.spec.ts +33 -33
  150. package/test/util/CriteriaModel.spec.ts +231 -231
  151. package/test/util/CriteriaParameter.spec.ts +51 -51
  152. package/test/util/MaskFormatter.spec.ts +138 -138
  153. package/test/util/NumberUtils.spec.ts +156 -156
  154. package/test/util/StringUtils.spec.ts +43 -43
  155. package/test/util/TimeFormatter.spec.ts +25 -25
  156. package/tsconfig.json +15 -15
@@ -1,38 +1,38 @@
1
- export enum DataType{
2
- NUMBER = "NUMBER",
3
- DATE = "DATE",
4
- TEXT = "TEXT",
5
- BOOLEAN = "BOOLEAN",
6
- OBJECT = "OBJECT"
7
- }
8
-
9
- export const convertType = (dataType:DataType, value: any): any => {
10
- if(value === undefined || value === null){
11
- return value;
12
- }
13
- switch (dataType){
14
- case DataType.NUMBER:
15
- return value === "" || isNaN(value) ? null : Number(value);
16
- case DataType.OBJECT:
17
- return typeof value === "string" ? JSON.parse(value) : value;
18
- case DataType.BOOLEAN:
19
- return Boolean(value);
20
- case DataType.DATE:
21
- return new Date(value.toString())
22
- default:
23
- return value;
24
- }
25
- }
26
-
27
- export const toString = (dataType:DataType, value: any): string => {
28
-
29
- if(value === undefined || value === null){
30
- return value;
31
- }
32
-
33
- if(dataType === DataType.OBJECT){
34
- return JSON.stringify(value);
35
- } else {
36
- return value.toString();
37
- }
1
+ export enum DataType{
2
+ NUMBER = "NUMBER",
3
+ DATE = "DATE",
4
+ TEXT = "TEXT",
5
+ BOOLEAN = "BOOLEAN",
6
+ OBJECT = "OBJECT"
7
+ }
8
+
9
+ export const convertType = (dataType:DataType, value: any): any => {
10
+ if(value === undefined || value === null){
11
+ return value;
12
+ }
13
+ switch (dataType){
14
+ case DataType.NUMBER:
15
+ return value === "" || isNaN(value) ? null : Number(value);
16
+ case DataType.OBJECT:
17
+ return typeof value === "string" ? JSON.parse(value) : value;
18
+ case DataType.BOOLEAN:
19
+ return Boolean(value);
20
+ case DataType.DATE:
21
+ return new Date(value.toString());
22
+ default:
23
+ return value;
24
+ }
25
+ }
26
+
27
+ export const toString = (dataType:DataType, value: any): string => {
28
+
29
+ if(value === undefined || value === null){
30
+ return value;
31
+ }
32
+
33
+ if(dataType === DataType.OBJECT){
34
+ return JSON.stringify(value);
35
+ } else {
36
+ return value.toString();
37
+ }
38
38
  }
@@ -1,82 +1,82 @@
1
- import { DataType } from "./DataType";
2
-
3
- export interface UnitMetadata{
4
- name: string;
5
- label: string;
6
- fields: Array<FieldDescriptor>;
7
- }
8
-
9
- export interface FieldDescriptor {
10
- name: string;
11
- label: string;
12
- dataType: DataType;
13
- userInterface?: UserInterface;
14
- defaultValue?: any;
15
- visible?: boolean;
16
- readOnly?: boolean;
17
- required?: boolean;
18
- properties?: any;
19
- dependencies?: Array<FieldDependency>;
20
- }
21
-
22
- export interface FieldDependency {
23
- masterFields: Array<string>;
24
- type: DependencyType;
25
- expression: string;
26
- }
27
-
28
- export interface Filter{
29
- name: string;
30
- expression: string;
31
- params?: Array<FilterParam>
32
- }
33
-
34
- export interface FilterParam{
35
- name: string
36
- value: any
37
- }
38
-
39
- export interface Sort{
40
- field: string
41
- mode: SortMode
42
- dataType: DataType
43
- }
44
-
45
- export interface FilterProvider{
46
- getFilter(dataUnit: string): Array<Filter> | undefined;
47
- }
48
-
49
- export interface SortingProvider{
50
- getSort(dataUnit: string): Array<Sort> | undefined;
51
- }
52
-
53
- export enum SortMode{
54
- ASC = "ASC",
55
- DESC = "DESC"
56
- }
57
-
58
- export enum DependencyType {
59
- SEARCHING = "SEARCHING",
60
- REQUIREMENT = "REQUIREMENT",
61
- VISIBILITY = "REQUIREMENT"
62
- }
63
-
64
- export enum UserInterface {
65
- FILE = "FILE",
66
- IMAGE = "IMAGE",
67
- DATE = "DATE",
68
- DATETIME = "DATETIME",
69
- TIME = "TIME",
70
- ELAPSEDTIME = "ELAPSEDTIME",
71
- CHECKBOX = "CHECKBOX",
72
- SWITCH = "SWITCH",
73
- OPTIONSELECTOR = "OPTIONSELECTOR",
74
- DECIMALNUMBER = "DECIMALNUMBER",
75
- INTEGERNUMBER = "INTEGERNUMBER",
76
- SEARCH = "SEARCH",
77
- SHORTTEXT = "SHORTTEXT",
78
- PASSWORD = "PASSWORD",
79
- MASKEDTEXT = "MASKEDTEXT",
80
- LONGTEXT = "LONGTEXT",
81
- HTML = "HTML"
82
- }
1
+ import { DataType } from "./DataType.js";
2
+
3
+ export interface UnitMetadata{
4
+ name: string;
5
+ label: string;
6
+ fields: Array<FieldDescriptor>;
7
+ }
8
+
9
+ export interface FieldDescriptor {
10
+ name: string;
11
+ label: string;
12
+ dataType: DataType;
13
+ userInterface?: UserInterface;
14
+ defaultValue?: any;
15
+ visible?: boolean;
16
+ readOnly?: boolean;
17
+ required?: boolean;
18
+ properties?: any;
19
+ dependencies?: Array<FieldDependency>;
20
+ }
21
+
22
+ export interface FieldDependency {
23
+ masterFields: Array<string>;
24
+ type: DependencyType;
25
+ expression: string;
26
+ }
27
+
28
+ export interface Filter{
29
+ name: string;
30
+ expression: string;
31
+ params?: Array<FilterParam>
32
+ }
33
+
34
+ export interface FilterParam{
35
+ name: string
36
+ value: any
37
+ }
38
+
39
+ export interface Sort{
40
+ field: string
41
+ mode: SortMode
42
+ dataType: DataType
43
+ }
44
+
45
+ export interface FilterProvider{
46
+ getFilter(dataUnit: string): Array<Filter> | undefined;
47
+ }
48
+
49
+ export interface SortingProvider{
50
+ getSort(dataUnit: string): Array<Sort> | undefined;
51
+ }
52
+
53
+ export enum SortMode{
54
+ ASC = "ASC",
55
+ DESC = "DESC"
56
+ }
57
+
58
+ export enum DependencyType {
59
+ SEARCHING = "SEARCHING",
60
+ REQUIREMENT = "REQUIREMENT",
61
+ VISIBILITY = "REQUIREMENT"
62
+ }
63
+
64
+ export enum UserInterface {
65
+ FILE = "FILE",
66
+ IMAGE = "IMAGE",
67
+ DATE = "DATE",
68
+ DATETIME = "DATETIME",
69
+ TIME = "TIME",
70
+ ELAPSEDTIME = "ELAPSEDTIME",
71
+ CHECKBOX = "CHECKBOX",
72
+ SWITCH = "SWITCH",
73
+ OPTIONSELECTOR = "OPTIONSELECTOR",
74
+ DECIMALNUMBER = "DECIMALNUMBER",
75
+ INTEGERNUMBER = "INTEGERNUMBER",
76
+ SEARCH = "SEARCH",
77
+ SHORTTEXT = "SHORTTEXT",
78
+ PASSWORD = "PASSWORD",
79
+ MASKEDTEXT = "MASKEDTEXT",
80
+ LONGTEXT = "LONGTEXT",
81
+ HTML = "HTML"
82
+ }
@@ -1,34 +1,34 @@
1
- import { ActionReducer } from "./StateManager";
2
- import { Action } from "./action/DataUnitAction";
3
- import StateManager, {StateAction} from "./StateManager";
4
-
5
- class HistReducerImpl implements ActionReducer {
6
-
7
- public sliceName: string = "";
8
-
9
- public reduce(stateManager: StateManager, _currentState: void, action: StateAction): void {
10
-
11
- switch (action.type) {
12
- case Action.DATA_SAVED:
13
- case Action.EDITION_CANCELED:
14
- stateManager.clearUndo();
15
- break;
16
- case Action.CHANGE_UNDONE:
17
- stateManager.undo();
18
- break;
19
- case Action.CHANGE_REDONE:
20
- stateManager.redo();
21
- break;
22
- }
23
- }
24
- }
25
-
26
- export const HistReducer = new HistReducerImpl();
27
-
28
- export const canUndo = (stateManager: StateManager): boolean => {
29
- return stateManager.canUndo();
30
- }
31
-
32
- export const canRedo = (stateManager: StateManager): boolean =>{
33
- return stateManager.canRedo();
1
+ import { ActionReducer } from "./StateManager.js";
2
+ import { Action } from "./action/DataUnitAction.js";
3
+ import StateManager, {StateAction} from "./StateManager.js";
4
+
5
+ class HistReducerImpl implements ActionReducer {
6
+
7
+ public sliceName: string = "";
8
+
9
+ public reduce(stateManager: StateManager, _currentState: void, action: StateAction): void {
10
+
11
+ switch (action.type) {
12
+ case Action.DATA_SAVED:
13
+ case Action.EDITION_CANCELED:
14
+ stateManager.clearUndo();
15
+ break;
16
+ case Action.CHANGE_UNDONE:
17
+ stateManager.undo();
18
+ break;
19
+ case Action.CHANGE_REDONE:
20
+ stateManager.redo();
21
+ break;
22
+ }
23
+ }
24
+ }
25
+
26
+ export const HistReducer = new HistReducerImpl();
27
+
28
+ export const canUndo = (stateManager: StateManager): boolean => {
29
+ return stateManager.canUndo();
30
+ }
31
+
32
+ export const canRedo = (stateManager: StateManager): boolean =>{
33
+ return stateManager.canRedo();
34
34
  }
@@ -1,142 +1,142 @@
1
- /**
2
- * Essa classe representa uma interpretação do padrão de projetos Flux.
3
- * No padrão Flux os dados da aplicação são chamados de "estado" e existem
4
- * algumas regras para gerenciamento/manipulação desse estado:
5
- *
6
- * 1 - O estado é imutável.
7
- * 2 - Toda modificação de estado é representada por uma "ação".
8
- * 3 - Quando "ações" acontecem a "store" cria um novo estado e notifica a todos interessados.
9
- *
10
- * Nessa interpretação desse design pattern, o StateManager faz o papel da store,
11
- * notificando os manipuladores de estado (handlers), que são responsáveis por pedaços
12
- * do estado (slices).
13
- *
14
- * O StateManager mantém dois tipos de estados: "Histórico" e "Não Histórico". No estado
15
- * "Histórico", sempre que uma alteração de estado acontece, o estado anterior é guardado em
16
- * uma pilha, o que permite que possamos voltar no tempo, desfazendo algumas ações
17
- */
18
- export default class StateManager {
19
-
20
- private _reducers: Array<ActionReducer>;
21
-
22
- private _past: Array<any> = [];
23
- private _future: Array<any> = [];
24
- private _present: any = {};
25
-
26
- private _nonHist: any = {};
27
- private _histClean: boolean = false;
28
-
29
- constructor(reducers: Array<ActionReducer>) {
30
- this._reducers = reducers;
31
- }
32
-
33
- public process(action: StateAction) {
34
-
35
- const oldPresent: any = this._present;
36
- let hasHistChange: boolean = false;
37
- this._histClean = false;
38
-
39
- this._reducers.forEach(
40
- reducer => {
41
- const sliceName = reducer.sliceName;
42
- const isHistoric = this.isHistoric(sliceName);
43
- const oldSlice = this.getSlice(sliceName, isHistoric);
44
- const newSlice = reducer.reduce(this, oldSlice, action);
45
- if (newSlice !== oldSlice) {
46
- this.updateSlice(sliceName, newSlice, isHistoric);
47
- hasHistChange ||= isHistoric;
48
- }
49
- }
50
- );
51
-
52
- if (hasHistChange && !this._histClean) {
53
- this._past.push(oldPresent);
54
- this._future = [];
55
- document.dispatchEvent(new CustomEvent("undoableAction", { detail: this }))
56
- }
57
-
58
- }
59
-
60
- public select(sliceName: string, selector: (state: any) => any): any {
61
- const isHistoric = this.isHistoric(sliceName);
62
- return selector(this.getSlice(sliceName, isHistoric));
63
- }
64
-
65
- private isHistoric(slice: string) {
66
- return slice.startsWith("hist::");
67
- }
68
-
69
- private updateSlice(name: string, slice: any, isHistoric: boolean): void {
70
- if (isHistoric) {
71
- this._present = { ...this._present, [name]: slice };
72
- if (slice === undefined) {
73
- delete this._present[name];
74
- }
75
- } else {
76
- this._nonHist = { ...this._nonHist, [name]: slice };
77
- if (slice === undefined) {
78
- delete this._nonHist[name];
79
- }
80
- }
81
- }
82
-
83
- private getSlice(name: string, isHistoric: boolean): any {
84
- return isHistoric ? this._present[name] : this._nonHist[name];
85
- }
86
-
87
- public canUndo(): boolean {
88
- return this._past.length > 0;
89
- }
90
-
91
- public canRedo(): boolean {
92
- return this._future.length > 0;
93
- }
94
-
95
- public undo() {
96
- if (this.canUndo()) {
97
- this._future.push(this._present);
98
- this._present = this._past.pop();
99
- }
100
- }
101
-
102
- public redo() {
103
- if (this.canRedo()) {
104
- this._past.push(this._present);
105
- this._present = this._future.pop();
106
- }
107
- }
108
-
109
- public clearUndo() {
110
- this._histClean = true;
111
- this._past = [];
112
- this._future = [];
113
- }
114
-
115
- public persist() {
116
-
117
- }
118
-
119
- }
120
-
121
- /**
122
- * Baseado no padrão Flux, qualquer alteração de estado parte de uma ação.
123
- * Essa ação pode conter um payload ou não.
124
- */
125
- export interface StateAction {
126
- /**
127
- * O tipo da ação representa o que aconteceu. Com base nesse tipo
128
- * os manipuladores de estado agem criando um novo estado.
129
- */
130
- type: string,
131
-
132
- /**
133
- * Muitas ações contém informações importantes para compor o novo estado.
134
- * Isso é chamado de payload.
135
- */
136
- payload?: any
137
- }
138
-
139
- export interface ActionReducer {
140
- sliceName: string;
141
- reduce(stateManager: StateManager, state: any, action: StateAction): any;
1
+ /**
2
+ * Essa classe representa uma interpretação do padrão de projetos Flux.
3
+ * No padrão Flux os dados da aplicação são chamados de "estado" e existem
4
+ * algumas regras para gerenciamento/manipulação desse estado:
5
+ *
6
+ * 1 - O estado é imutável.
7
+ * 2 - Toda modificação de estado é representada por uma "ação".
8
+ * 3 - Quando "ações" acontecem a "store" cria um novo estado e notifica a todos interessados.
9
+ *
10
+ * Nessa interpretação desse design pattern, o StateManager faz o papel da store,
11
+ * notificando os manipuladores de estado (handlers), que são responsáveis por pedaços
12
+ * do estado (slices).
13
+ *
14
+ * O StateManager mantém dois tipos de estados: "Histórico" e "Não Histórico". No estado
15
+ * "Histórico", sempre que uma alteração de estado acontece, o estado anterior é guardado em
16
+ * uma pilha, o que permite que possamos voltar no tempo, desfazendo algumas ações
17
+ */
18
+ export default class StateManager {
19
+
20
+ private _reducers: Array<ActionReducer>;
21
+
22
+ private _past: Array<any> = [];
23
+ private _future: Array<any> = [];
24
+ private _present: any = {};
25
+
26
+ private _nonHist: any = {};
27
+ private _histClean: boolean = false;
28
+
29
+ constructor(reducers: Array<ActionReducer>) {
30
+ this._reducers = reducers;
31
+ }
32
+
33
+ public process(action: StateAction) {
34
+
35
+ const oldPresent: any = this._present;
36
+ let hasHistChange: boolean = false;
37
+ this._histClean = false;
38
+
39
+ this._reducers.forEach(
40
+ reducer => {
41
+ const sliceName = reducer.sliceName;
42
+ const isHistoric = this.isHistoric(sliceName);
43
+ const oldSlice = this.getSlice(sliceName, isHistoric);
44
+ const newSlice = reducer.reduce(this, oldSlice, action);
45
+ if (newSlice !== oldSlice) {
46
+ this.updateSlice(sliceName, newSlice, isHistoric);
47
+ hasHistChange ||= isHistoric;
48
+ }
49
+ }
50
+ );
51
+
52
+ if (hasHistChange && !this._histClean) {
53
+ this._past.push(oldPresent);
54
+ this._future = [];
55
+ document.dispatchEvent(new CustomEvent("undoableAction", { detail: this }))
56
+ }
57
+
58
+ }
59
+
60
+ public select(sliceName: string, selector: (state: any) => any): any {
61
+ const isHistoric = this.isHistoric(sliceName);
62
+ return selector(this.getSlice(sliceName, isHistoric));
63
+ }
64
+
65
+ private isHistoric(slice: string) {
66
+ return slice.startsWith("hist::");
67
+ }
68
+
69
+ private updateSlice(name: string, slice: any, isHistoric: boolean): void {
70
+ if (isHistoric) {
71
+ this._present = { ...this._present, [name]: slice };
72
+ if (slice === undefined) {
73
+ delete this._present[name];
74
+ }
75
+ } else {
76
+ this._nonHist = { ...this._nonHist, [name]: slice };
77
+ if (slice === undefined) {
78
+ delete this._nonHist[name];
79
+ }
80
+ }
81
+ }
82
+
83
+ private getSlice(name: string, isHistoric: boolean): any {
84
+ return isHistoric ? this._present[name] : this._nonHist[name];
85
+ }
86
+
87
+ public canUndo(): boolean {
88
+ return this._past.length > 0;
89
+ }
90
+
91
+ public canRedo(): boolean {
92
+ return this._future.length > 0;
93
+ }
94
+
95
+ public undo() {
96
+ if (this.canUndo()) {
97
+ this._future.push(this._present);
98
+ this._present = this._past.pop();
99
+ }
100
+ }
101
+
102
+ public redo() {
103
+ if (this.canRedo()) {
104
+ this._past.push(this._present);
105
+ this._present = this._future.pop();
106
+ }
107
+ }
108
+
109
+ public clearUndo() {
110
+ this._histClean = true;
111
+ this._past = [];
112
+ this._future = [];
113
+ }
114
+
115
+ public persist() {
116
+
117
+ }
118
+
119
+ }
120
+
121
+ /**
122
+ * Baseado no padrão Flux, qualquer alteração de estado parte de uma ação.
123
+ * Essa ação pode conter um payload ou não.
124
+ */
125
+ export interface StateAction {
126
+ /**
127
+ * O tipo da ação representa o que aconteceu. Com base nesse tipo
128
+ * os manipuladores de estado agem criando um novo estado.
129
+ */
130
+ type: string,
131
+
132
+ /**
133
+ * Muitas ações contém informações importantes para compor o novo estado.
134
+ * Isso é chamado de payload.
135
+ */
136
+ payload?: any
137
+ }
138
+
139
+ export interface ActionReducer {
140
+ sliceName: string;
141
+ reduce(stateManager: StateManager, state: any, action: StateAction): any;
142
142
  }