@sankhyalabs/core 1.0.23 → 1.0.26
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.
- package/dist/application/Application.d.ts +8 -0
- package/dist/application/Application.js +19 -0
- package/dist/application/Application.js.map +1 -0
- package/dist/dataunit/DataUnit.d.ts +17 -7
- package/dist/dataunit/DataUnit.js +60 -24
- package/dist/dataunit/DataUnit.js.map +1 -1
- package/dist/dataunit/metadata/DataType.d.ts +1 -1
- package/dist/dataunit/metadata/DataType.js +4 -4
- package/dist/dataunit/metadata/DataType.js.map +1 -1
- package/dist/dataunit/metadata/UnitMetadata.d.ts +29 -8
- package/dist/dataunit/metadata/UnitMetadata.js +5 -0
- package/dist/dataunit/metadata/UnitMetadata.js.map +1 -1
- package/dist/dataunit/state/slice/ChangesSlice.d.ts +1 -1
- package/dist/dataunit/state/slice/ChangesSlice.js +5 -5
- package/dist/dataunit/state/slice/ChangesSlice.js.map +1 -1
- package/dist/dataunit/state/slice/UnitMetadataSlice.d.ts +2 -2
- package/dist/dataunit/state/slice/UnitMetadataSlice.js +1 -1
- package/dist/dataunit/state/slice/UnitMetadataSlice.js.map +1 -1
- package/dist/http/data-fetcher/HttpFetcher.d.ts +13 -0
- package/dist/http/data-fetcher/HttpFetcher.js +174 -0
- package/dist/http/data-fetcher/HttpFetcher.js.map +1 -0
- package/dist/http/data-fetcher/default/application-config-fetcher.d.ts +6 -0
- package/dist/http/data-fetcher/default/application-config-fetcher.js +21 -0
- package/dist/http/data-fetcher/default/application-config-fetcher.js.map +1 -0
- package/dist/http/data-fetcher/default/dataunit-fetcher.d.ts +9 -0
- package/dist/http/data-fetcher/default/dataunit-fetcher.js +45 -0
- package/dist/http/data-fetcher/default/dataunit-fetcher.js.map +1 -0
- package/dist/http/data-fetcher/default/form-config-fetcher.d.ts +2 -0
- package/dist/http/data-fetcher/default/form-config-fetcher.js +3 -0
- package/dist/http/data-fetcher/default/form-config-fetcher.js.map +1 -0
- package/dist/http/data-fetcher/default/grid-config-fetcher.d.ts +2 -0
- package/dist/http/data-fetcher/default/grid-config-fetcher.js +3 -0
- package/dist/http/data-fetcher/default/grid-config-fetcher.js.map +1 -0
- package/dist/http/data-fetcher/state/LoadStateManager.d.ts +23 -0
- package/dist/http/data-fetcher/state/LoadStateManager.js +74 -0
- package/dist/http/data-fetcher/state/LoadStateManager.js.map +1 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/StringUtils.d.ts +6 -0
- package/dist/utils/StringUtils.js +31 -0
- package/dist/utils/StringUtils.js.map +1 -1
- package/package.json +4 -2
- package/src/application/Application.ts +22 -0
- package/src/dataunit/DataUnit.ts +83 -38
- package/src/dataunit/metadata/DataType.ts +4 -4
- package/src/dataunit/metadata/UnitMetadata.ts +35 -9
- package/src/dataunit/state/slice/ChangesSlice.ts +5 -5
- package/src/dataunit/state/slice/UnitMetadataSlice.ts +2 -2
- package/src/http/data-fetcher/HttpFetcher.ts +174 -0
- package/src/http/data-fetcher/default/application-config-fetcher.ts +26 -0
- package/src/http/data-fetcher/default/dataunit-fetcher.ts +52 -0
- package/src/http/data-fetcher/default/form-config-fetcher.ts +3 -0
- package/src/http/data-fetcher/default/grid-config-fetcher.ts +3 -0
- package/src/http/data-fetcher/state/LoadStateManager.ts +74 -0
- package/src/index.ts +23 -2
- package/src/utils/StringUtils.ts +36 -3
- package/test/util/StringUtils.spec.ts +42 -33
package/src/dataunit/DataUnit.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { UnitMetadata,
|
|
1
|
+
import { UnitMetadata, FieldDescriptor, SortingProvider, FilterProvider, Sort, Filter } from "./metadata/UnitMetadata";
|
|
2
2
|
import { convertType } from "./metadata/DataType";
|
|
3
3
|
|
|
4
4
|
import { DataUnitAction, Action } from "./state/action/DataUnitAction";
|
|
5
5
|
import StateManager from "./state/StateManager";
|
|
6
6
|
|
|
7
7
|
import { HistReducer, canRedo, canUndo } from "./state/HistReducer";
|
|
8
|
-
import { UnitMetadataReducer,
|
|
8
|
+
import { UnitMetadataReducer, getField, getMetadata } from "./state/slice/UnitMetadataSlice";
|
|
9
9
|
import { RecordsReducer } from "./state/slice/RecordsSlice";
|
|
10
10
|
import { SelectionReducer, getSelection, hasNext, hasPrevious } from "./state/slice/SelectionSlice";
|
|
11
11
|
import { ChangesReducer, isDirty, getChangesToSave } from "./state/slice/ChangesSlice";
|
|
@@ -13,14 +13,17 @@ import { RemovedRecordsReducer } from "./state/slice/RemovedRecordsSlice";
|
|
|
13
13
|
import { AddedRecordsReducer } from "./state/slice/AddedRecordsSlice";
|
|
14
14
|
import { CurrentRecordsReducer, getCurrentRecords, getFieldValue } from "./state/slice/CurrentRecordsSlice";
|
|
15
15
|
|
|
16
|
+
|
|
16
17
|
export default class DataUnit {
|
|
17
18
|
|
|
18
19
|
private _name: string;
|
|
19
20
|
private _observers: Array<(action: DataUnitAction) => void>;
|
|
21
|
+
private _sortingProvider?: SortingProvider;
|
|
22
|
+
private _filterProviders: Array<FilterProvider>;
|
|
20
23
|
private _stateManager: StateManager;
|
|
21
24
|
|
|
22
25
|
public metadataLoader?: (dataUnit: string) => Promise<UnitMetadata>;
|
|
23
|
-
public dataLoader?: (dataUnit: string) => Promise<Array<Record>>;
|
|
26
|
+
public dataLoader?: (dataUnit: string, sort?: Array<Sort>, filters?: Array<Filter>) => Promise<Array<Record>>;
|
|
24
27
|
public saveLoader?: (dataUnit: string, changes: Array<Change>) => Promise<Array<SavedRecord>>;
|
|
25
28
|
|
|
26
29
|
constructor(name: string) {
|
|
@@ -38,6 +41,8 @@ export default class DataUnit {
|
|
|
38
41
|
]
|
|
39
42
|
);
|
|
40
43
|
this._observers = [];
|
|
44
|
+
this._filterProviders = [];
|
|
45
|
+
this._sortingProvider = undefined;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
public get name(): string {
|
|
@@ -46,12 +51,24 @@ export default class DataUnit {
|
|
|
46
51
|
|
|
47
52
|
// Métodos privados
|
|
48
53
|
private validateAndTypeValue(fieldName: string, newValue: any): any {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
//FIXME: Validações devem ser feitas aqui
|
|
55
|
+
const descriptor: FieldDescriptor | undefined = this.getField(fieldName);
|
|
56
|
+
return descriptor ? convertType(descriptor.dataType, newValue) : newValue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private getFilters(): Array<Filter> | undefined{
|
|
60
|
+
let filters: Array<Filter> | undefined = undefined;
|
|
61
|
+
this._filterProviders.forEach(p => {
|
|
62
|
+
const f = p.getFilter(this.name);
|
|
63
|
+
if(f){
|
|
64
|
+
filters = (filters||[]).concat(f);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return filters;
|
|
68
|
+
}
|
|
53
69
|
|
|
54
|
-
|
|
70
|
+
private getSort(): Array<Sort> | undefined{
|
|
71
|
+
return this._sortingProvider ? this._sortingProvider.getSort(this._name) : undefined;
|
|
55
72
|
}
|
|
56
73
|
|
|
57
74
|
// Loaders
|
|
@@ -59,39 +76,71 @@ export default class DataUnit {
|
|
|
59
76
|
this.dispatchAction(Action.LOADING_METADATA);
|
|
60
77
|
if (this.metadataLoader) {
|
|
61
78
|
this.metadataLoader(this._name).then(
|
|
62
|
-
metadata => this.
|
|
79
|
+
metadata => this.metadata = metadata
|
|
63
80
|
);
|
|
64
81
|
}
|
|
65
82
|
}
|
|
66
83
|
|
|
67
|
-
public loadData():
|
|
84
|
+
public loadData(): Promise<Array<Record>> {
|
|
68
85
|
this.dispatchAction(Action.LOADING_DATA);
|
|
69
|
-
|
|
70
|
-
this.dataLoader
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
86
|
+
return new Promise((resolve, fail)=>{
|
|
87
|
+
if (this.dataLoader) {
|
|
88
|
+
const sort = this.getSort();
|
|
89
|
+
const filters = this.getFilters();
|
|
90
|
+
this.dataLoader(this._name, sort, filters).then(
|
|
91
|
+
records => {
|
|
92
|
+
this.records = records;
|
|
93
|
+
resolve(this.records);
|
|
94
|
+
}
|
|
95
|
+
).catch(()=>fail());
|
|
96
|
+
}
|
|
97
|
+
});
|
|
74
98
|
}
|
|
75
99
|
|
|
76
100
|
public saveData(): void {
|
|
77
101
|
|
|
78
|
-
const changes: Array<Change> = getChangesToSave(this._stateManager);
|
|
102
|
+
const changes: Array<Change> = getChangesToSave(this._name, this._stateManager);
|
|
79
103
|
|
|
80
|
-
if(changes.length > 0){
|
|
104
|
+
if (changes.length > 0) {
|
|
81
105
|
this.dispatchAction(Action.SAVING_DATA);
|
|
82
|
-
if(this.saveLoader){
|
|
106
|
+
if (this.saveLoader) {
|
|
83
107
|
this.saveLoader(this._name, changes).then(
|
|
84
|
-
records => this.dispatchAction(Action.DATA_SAVED, {changes, records})
|
|
108
|
+
records => this.dispatchAction(Action.DATA_SAVED, { changes, records })
|
|
85
109
|
);
|
|
86
110
|
}
|
|
87
111
|
}
|
|
88
112
|
}
|
|
89
113
|
|
|
90
114
|
// API
|
|
91
|
-
public
|
|
115
|
+
public addFilterProvider(provider: FilterProvider): void{
|
|
116
|
+
this._filterProviders.push(provider);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public set sortingProvider(provider: SortingProvider){
|
|
120
|
+
this._sortingProvider = provider;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public set metadata(md: UnitMetadata) {
|
|
124
|
+
this.dispatchAction(Action.METADATA_LOADED, md);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public get metadata(): UnitMetadata {
|
|
92
128
|
return getMetadata(this._stateManager);
|
|
93
129
|
}
|
|
94
130
|
|
|
131
|
+
public set records(r: Array<Record>){
|
|
132
|
+
this.dispatchAction(Action.DATA_LOADED, r);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public get records(): Array<Record>{
|
|
136
|
+
const records = getCurrentRecords(this._stateManager);
|
|
137
|
+
return records ? Array.from(records.values()) : [];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public getField(fieldName: string): FieldDescriptor | undefined{
|
|
141
|
+
return getField(this._stateManager, fieldName);
|
|
142
|
+
}
|
|
143
|
+
|
|
95
144
|
public addRecord(): void {
|
|
96
145
|
this.dispatchAction(Action.RECORDS_ADDED, [{}]);
|
|
97
146
|
}
|
|
@@ -103,15 +152,20 @@ export default class DataUnit {
|
|
|
103
152
|
}
|
|
104
153
|
}
|
|
105
154
|
|
|
106
|
-
public getRecords(): Array<Record>|undefined {
|
|
107
|
-
const records = getCurrentRecords(this._stateManager);
|
|
108
|
-
return records ? Array.from(records.values()) : undefined;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
155
|
public getFieldValue(fieldName: string): any {
|
|
112
156
|
return getFieldValue(this._stateManager, fieldName);
|
|
113
157
|
}
|
|
114
158
|
|
|
159
|
+
public setFieldValue(fieldName: string, newValue: any, records?: Array<string>): void {
|
|
160
|
+
|
|
161
|
+
const typedValue = this.validateAndTypeValue(fieldName, newValue);
|
|
162
|
+
const currentValue = this.getFieldValue(fieldName);
|
|
163
|
+
|
|
164
|
+
if (currentValue !== typedValue) {
|
|
165
|
+
this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue, records });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
115
169
|
public getSelection(): Array<string> {
|
|
116
170
|
return getSelection(this._stateManager);
|
|
117
171
|
}
|
|
@@ -132,16 +186,6 @@ export default class DataUnit {
|
|
|
132
186
|
this.dispatchAction(Action.PREVIOUS_SELECTED);
|
|
133
187
|
}
|
|
134
188
|
|
|
135
|
-
public setFieldValue(fieldName: string, newValue: any): void {
|
|
136
|
-
|
|
137
|
-
const typedValue = this.validateAndTypeValue(fieldName, newValue);
|
|
138
|
-
const currentValue = this.getFieldValue(fieldName);
|
|
139
|
-
|
|
140
|
-
if (currentValue !== typedValue) {
|
|
141
|
-
this.dispatchAction(Action.DATA_CHANGED, { [fieldName]: typedValue });
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
189
|
public cancelEdition(): void {
|
|
146
190
|
this.dispatchAction(Action.EDITION_CANCELED);
|
|
147
191
|
}
|
|
@@ -190,7 +234,6 @@ export default class DataUnit {
|
|
|
190
234
|
public unsubscribe(observer: Function) {
|
|
191
235
|
this._observers = this._observers.filter(f => f !== observer);
|
|
192
236
|
}
|
|
193
|
-
|
|
194
237
|
}
|
|
195
238
|
|
|
196
239
|
export interface Record {
|
|
@@ -199,7 +242,7 @@ export interface Record {
|
|
|
199
242
|
[key: string]: any;
|
|
200
243
|
}
|
|
201
244
|
|
|
202
|
-
export interface SavedRecord extends Record{
|
|
245
|
+
export interface SavedRecord extends Record {
|
|
203
246
|
__old__id__?: string;
|
|
204
247
|
}
|
|
205
248
|
|
|
@@ -211,12 +254,14 @@ export enum ChangeOperation {
|
|
|
211
254
|
|
|
212
255
|
export class Change {
|
|
213
256
|
|
|
257
|
+
public dataUnit: string;
|
|
214
258
|
public record: Record;
|
|
215
259
|
public updatingFields: any;
|
|
216
260
|
|
|
217
261
|
private _operation: ChangeOperation;
|
|
218
262
|
|
|
219
|
-
constructor(record: Record, updates: any, operation: ChangeOperation) {
|
|
263
|
+
constructor(dataUnit: string, record: Record, updates: any, operation: ChangeOperation) {
|
|
264
|
+
this.dataUnit = dataUnit;
|
|
220
265
|
this.record = record;
|
|
221
266
|
this.updatingFields = updates;
|
|
222
267
|
this._operation = operation;
|
|
@@ -3,7 +3,7 @@ export enum DataType{
|
|
|
3
3
|
DATE = "DATE",
|
|
4
4
|
TEXT = "TEXT",
|
|
5
5
|
BOOLEAN = "BOOLEAN",
|
|
6
|
-
|
|
6
|
+
OBJECT = "OBJECT"
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export const convertType = (dataType:DataType, value: any): any => {
|
|
@@ -13,8 +13,8 @@ export const convertType = (dataType:DataType, value: any): any => {
|
|
|
13
13
|
switch (dataType){
|
|
14
14
|
case DataType.NUMBER:
|
|
15
15
|
return value === "" || isNaN(value) ? null : Number(value);
|
|
16
|
-
case DataType.
|
|
17
|
-
return JSON.parse(value);
|
|
16
|
+
case DataType.OBJECT:
|
|
17
|
+
return typeof value === "string" ? JSON.parse(value) : value;
|
|
18
18
|
case DataType.BOOLEAN:
|
|
19
19
|
return Boolean(value);
|
|
20
20
|
case DataType.DATE:
|
|
@@ -30,7 +30,7 @@ export const toString = (dataType:DataType, value: any): string => {
|
|
|
30
30
|
return value;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
if(dataType === DataType.
|
|
33
|
+
if(dataType === DataType.OBJECT){
|
|
34
34
|
return JSON.stringify(value);
|
|
35
35
|
} else {
|
|
36
36
|
return value.toString();
|
|
@@ -3,32 +3,58 @@ import { DataType } from "./DataType";
|
|
|
3
3
|
export interface UnitMetadata{
|
|
4
4
|
name: string;
|
|
5
5
|
label: string;
|
|
6
|
-
fields: Array<
|
|
6
|
+
fields: Array<FieldDescriptor>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface FieldDescriptor {
|
|
10
10
|
name: string;
|
|
11
11
|
label: string;
|
|
12
12
|
dataType: DataType;
|
|
13
13
|
userInterface?: UserInterface;
|
|
14
|
-
defaultValue?:
|
|
14
|
+
defaultValue?: any;
|
|
15
|
+
visible?: boolean;
|
|
15
16
|
readOnly?: boolean;
|
|
16
17
|
required?: boolean;
|
|
17
|
-
properties?:
|
|
18
|
+
properties?: any;
|
|
18
19
|
dependencies?: Array<FieldDependency>;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export interface UIProperty {
|
|
22
|
-
name: string;
|
|
23
|
-
value: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
22
|
export interface FieldDependency {
|
|
27
23
|
masterFields: Array<string>;
|
|
28
24
|
type: DependencyType;
|
|
29
25
|
expression: string;
|
|
30
26
|
}
|
|
31
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
|
+
|
|
32
58
|
export enum DependencyType {
|
|
33
59
|
SEARCHING = "SEARCHING",
|
|
34
60
|
REQUIREMENT = "REQUIREMENT",
|
|
@@ -16,7 +16,7 @@ class ChangesReducerImpl implements ActionReducer{
|
|
|
16
16
|
switch(action.type){
|
|
17
17
|
|
|
18
18
|
case Action.DATA_CHANGED:
|
|
19
|
-
const selection = getSelection(stateManager);
|
|
19
|
+
const selection: Array<string> = action.payload.records || getSelection(stateManager);
|
|
20
20
|
if(selection){
|
|
21
21
|
const newState = new Map(currentState);
|
|
22
22
|
selection.forEach(recordId => {
|
|
@@ -54,7 +54,7 @@ export const isDirty = (stateManager: StateManager): boolean => {
|
|
|
54
54
|
return getChanges(stateManager) !== undefined;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export const getChangesToSave = (stateManager: StateManager): Array<Change> => {
|
|
57
|
+
export const getChangesToSave = (dataUnit: string, stateManager: StateManager): Array<Change> => {
|
|
58
58
|
const result: Array<Change> = [];
|
|
59
59
|
|
|
60
60
|
const changes = getChanges(stateManager);
|
|
@@ -65,7 +65,7 @@ export const getChangesToSave = (stateManager: StateManager): Array<Change> => {
|
|
|
65
65
|
if(changes){
|
|
66
66
|
const c = changes.get(r.__record__id__);
|
|
67
67
|
if (c) {
|
|
68
|
-
result.push(new Change(r, c, ChangeOperation.UPDATE));
|
|
68
|
+
result.push(new Change(dataUnit, r, c, ChangeOperation.UPDATE));
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
});
|
|
@@ -74,7 +74,7 @@ export const getChangesToSave = (stateManager: StateManager): Array<Change> => {
|
|
|
74
74
|
const addedRecords = getAddedRecords(stateManager);
|
|
75
75
|
if (addedRecords) {
|
|
76
76
|
addedRecords.forEach(r => {
|
|
77
|
-
result.push(new Change(r, changes?.get(r.__record__id__), ChangeOperation.INSERT));
|
|
77
|
+
result.push(new Change(dataUnit, r, changes?.get(r.__record__id__), ChangeOperation.INSERT));
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -83,7 +83,7 @@ export const getChangesToSave = (stateManager: StateManager): Array<Change> => {
|
|
|
83
83
|
records.forEach(r=>recordsById[r.__record__id__] = r);
|
|
84
84
|
if (removedRecords) {
|
|
85
85
|
removedRecords.forEach(id => {
|
|
86
|
-
result.push(new Change(recordsById[id], undefined, ChangeOperation.DELETE));
|
|
86
|
+
result.push(new Change(dataUnit, recordsById[id], undefined, ChangeOperation.DELETE));
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { ActionReducer, StateAction } from "../StateManager";
|
|
3
|
-
import { UnitMetadata,
|
|
3
|
+
import { UnitMetadata, FieldDescriptor } from "../../metadata/UnitMetadata";
|
|
4
4
|
import { Action } from "../action/DataUnitAction";
|
|
5
5
|
import StateManager from "../StateManager";
|
|
6
6
|
|
|
@@ -24,7 +24,7 @@ export const getMetadata = (stateManager: StateManager): UnitMetadata => {
|
|
|
24
24
|
return stateManager.select(UnitMetadataReducer.sliceName, (state: UnitMetadata) => state);
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export const
|
|
27
|
+
export const getField = (stateManager: StateManager, fieldName: string): FieldDescriptor|undefined => {
|
|
28
28
|
const md: UnitMetadata = getMetadata(stateManager);
|
|
29
29
|
return md ? md.fields.find(fmd => fmd.name === fieldName) : undefined;
|
|
30
30
|
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { LoadStateManager, LoadType } from "./state/LoadStateManager";
|
|
2
|
+
import { DataType } from "./../../dataunit/metadata/DataType";
|
|
3
|
+
import { UserInterface } from "./../../dataunit/metadata/UnitMetadata";
|
|
4
|
+
import { batchRequests, BatchRequestDocument } from 'graphql-request';
|
|
5
|
+
|
|
6
|
+
export class HttpFetcher{
|
|
7
|
+
private static instance: HttpFetcher;
|
|
8
|
+
private static loadStateManager: LoadStateManager;
|
|
9
|
+
private static watingRequestsById: Map<string, WaitingRequest >= new Map<string, WaitingRequest>();
|
|
10
|
+
|
|
11
|
+
private constructor() {
|
|
12
|
+
HttpFetcher.loadStateManager = LoadStateManager.get(LoadType.APP_LOAD);
|
|
13
|
+
HttpFetcher.loadStateManager.onLoaded(this.onApplicationLoaded);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public static get(): HttpFetcher {
|
|
17
|
+
if (!HttpFetcher.instance) {
|
|
18
|
+
HttpFetcher.instance = new HttpFetcher();
|
|
19
|
+
}
|
|
20
|
+
return HttpFetcher.instance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async callGraphQL(req:any):Promise<any>{
|
|
24
|
+
if(HttpFetcher.loadStateManager.isPreInitialize()){
|
|
25
|
+
const reqKey = this.getReqKey(req);
|
|
26
|
+
req.queryID = reqKey;
|
|
27
|
+
req.values.queryID = reqKey;
|
|
28
|
+
|
|
29
|
+
if(!HttpFetcher.watingRequestsById.has(reqKey)){
|
|
30
|
+
HttpFetcher.watingRequestsById.set(reqKey, new WaitingRequest(req));
|
|
31
|
+
}
|
|
32
|
+
return HttpFetcher.getWatingRequest(reqKey)?.promise;
|
|
33
|
+
}else{
|
|
34
|
+
//TODO: fazer chamada direta para graphQL
|
|
35
|
+
return new Promise(function(resolve){
|
|
36
|
+
const md = {
|
|
37
|
+
name: "dd://br.com.sankhya.cad.parceiro/Parceiro",
|
|
38
|
+
label: "Parceiro",
|
|
39
|
+
fields: [
|
|
40
|
+
{
|
|
41
|
+
name: "CODPARC",
|
|
42
|
+
label: "Cód. Parceiro",
|
|
43
|
+
dataType: DataType.NUMBER
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "NOMEPARC",
|
|
47
|
+
label: "Nome",
|
|
48
|
+
dataType: DataType.TEXT,
|
|
49
|
+
userInterface: UserInterface.LONGTEXT,
|
|
50
|
+
required: true
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "P",
|
|
54
|
+
label: "pera",
|
|
55
|
+
dataType: DataType.TEXT,
|
|
56
|
+
userInterface: UserInterface.OPTIONSELECTOR,
|
|
57
|
+
properties: {options: `{"M": "Madura", "V": "Verde", "P": "Passada"}`}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "ME",
|
|
61
|
+
label: "ME",
|
|
62
|
+
dataType: DataType.NUMBER,
|
|
63
|
+
userInterface: UserInterface.DECIMALNUMBER,
|
|
64
|
+
properties: {precision: 4, prettyPrecision: 1}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
setTimeout(() => resolve(md));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private getReqKey(req:any):string{
|
|
74
|
+
return window.btoa(this.hashCode(`${req.query}${JSON.stringify(req.values || "")}`)).replaceAll("=", "");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private static getQueryTemplate(re:any):string{
|
|
78
|
+
return (re.query || "").replaceAll("$queryAlias$", re.queryID);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private static getWatingRequest(reqID:string):WaitingRequest|undefined{
|
|
82
|
+
return HttpFetcher.watingRequestsById.get(reqID);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private async onApplicationLoaded():Promise<any>{
|
|
86
|
+
const requestsBatch:Array<BatchRequestDocument> = [];
|
|
87
|
+
|
|
88
|
+
HttpFetcher.watingRequestsById.forEach(async (waitingReq:WaitingRequest) => {
|
|
89
|
+
let query = HttpFetcher.getQueryTemplate(waitingReq.request);
|
|
90
|
+
requestsBatch.push({ document: query, variables: {...waitingReq.request.values } });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
let res:any = undefined;
|
|
94
|
+
let dataResponse:Array<any> = [];
|
|
95
|
+
let errorsResponse:Array<any> = [];
|
|
96
|
+
|
|
97
|
+
try{
|
|
98
|
+
res = await batchRequests('http://localhost:8082/', requestsBatch);
|
|
99
|
+
res.forEach((resItem:any) => {
|
|
100
|
+
dataResponse.push(resItem.data);
|
|
101
|
+
});
|
|
102
|
+
}catch(err:any){
|
|
103
|
+
res = err.response;
|
|
104
|
+
const req:any = err.request;
|
|
105
|
+
Object.entries(res).forEach(([key, val]:Array<any>) => {
|
|
106
|
+
if(val.errors){
|
|
107
|
+
errorsResponse.push(val.errors.map((item:any) => {
|
|
108
|
+
item.request = req;
|
|
109
|
+
item.index = Number(key);
|
|
110
|
+
return item;
|
|
111
|
+
}));
|
|
112
|
+
}else if(val.data){
|
|
113
|
+
dataResponse.push(val.data);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//Reject primises with errors from query
|
|
118
|
+
errorsResponse.forEach((errorResponse:any) => {
|
|
119
|
+
Object.entries(errorResponse).forEach(([key, val]:Array<any>) => {
|
|
120
|
+
(HttpFetcher.getWatingRequest(val.request.variables[val.index].queryID)?.reject || Promise.reject)(val);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
//Resolve primises with data from query
|
|
124
|
+
dataResponse.forEach((data:any) => {
|
|
125
|
+
Object.entries(data).forEach(([key, val]:Array<any>) => {
|
|
126
|
+
(HttpFetcher.getWatingRequest(key)?.resolve || Promise.resolve)(val);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
HttpFetcher.watingRequestsById.clear();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
//TODO: Mover este metodo para o @sankhyalabs/core classe string utils.
|
|
133
|
+
private hashCode (txt:string):string {
|
|
134
|
+
var hash = 0, i, chr;
|
|
135
|
+
if (txt.length === 0) return hash.toString();
|
|
136
|
+
for (i = 0; i < txt.length; i++) {
|
|
137
|
+
chr = txt.charCodeAt(i);
|
|
138
|
+
hash = ((hash << 5) - hash) + chr;
|
|
139
|
+
hash |= 0; // Convert to 32bit integer
|
|
140
|
+
}
|
|
141
|
+
return hash.toString();
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
class WaitingRequest {
|
|
146
|
+
private _resolve: Function = () => {};
|
|
147
|
+
private _reject: Function = () => {};
|
|
148
|
+
private _promisse: Promise<any>;
|
|
149
|
+
private _request: any = undefined;
|
|
150
|
+
|
|
151
|
+
constructor(req:any){
|
|
152
|
+
this._request = req;
|
|
153
|
+
this._promisse = new Promise((resolve, reject) => {
|
|
154
|
+
this._resolve = resolve;
|
|
155
|
+
this._reject = reject;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public get resolve():Function{
|
|
160
|
+
return this._resolve;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public get reject():Function{
|
|
164
|
+
return this._reject;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public get promise():Promise<any>{
|
|
168
|
+
return this._promisse;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public get request():any{
|
|
172
|
+
return this._request;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { gql } from 'graphql-request';
|
|
2
|
+
import { HttpFetcher } from '../HttpFetcher';
|
|
3
|
+
|
|
4
|
+
export class ApplicationConfigFetcher {
|
|
5
|
+
|
|
6
|
+
private templateByQuery:Map<string, string >= new Map<string, string>();
|
|
7
|
+
|
|
8
|
+
constructor(){
|
|
9
|
+
this.buldTemplates();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
private buldTemplates():void{
|
|
13
|
+
this.templateByQuery.set('getResource', gql `query($name: String!) {
|
|
14
|
+
$queryAlias$: getResource(name: $name){
|
|
15
|
+
name
|
|
16
|
+
resource
|
|
17
|
+
}
|
|
18
|
+
}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public getResource(name:string, resourceID:string):Promise<any>{
|
|
22
|
+
const completPath = `cfg://app/${resourceID}/${name}`;
|
|
23
|
+
return HttpFetcher.get().callGraphQL({ values : { "name": completPath }, query: this.templateByQuery.get("getResource")});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UnitMetadata } from "../../../dataunit/metadata/UnitMetadata";
|
|
2
|
+
import { HttpFetcher } from "../HttpFetcher";
|
|
3
|
+
import { gql } from 'graphql-request';
|
|
4
|
+
import DataUnit from "../../../dataunit/DataUnit";
|
|
5
|
+
|
|
6
|
+
export class DataUnitFetcher{
|
|
7
|
+
|
|
8
|
+
private templateByQuery:Map<string, string >= new Map<string, string>();
|
|
9
|
+
|
|
10
|
+
constructor(){
|
|
11
|
+
this.buldTemplates();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private buldTemplates():void{
|
|
15
|
+
this.templateByQuery.set('getDataUnit', gql `query($name: String!) {
|
|
16
|
+
$queryAlias$: getDataUnit(name: $name){
|
|
17
|
+
name,
|
|
18
|
+
cardinality,
|
|
19
|
+
fields{
|
|
20
|
+
name,
|
|
21
|
+
defaultValue,
|
|
22
|
+
label,
|
|
23
|
+
readOnly,
|
|
24
|
+
required,
|
|
25
|
+
dataType,
|
|
26
|
+
userInterface,
|
|
27
|
+
properties{
|
|
28
|
+
name,
|
|
29
|
+
value
|
|
30
|
+
},
|
|
31
|
+
dependencies{
|
|
32
|
+
masterFields,
|
|
33
|
+
type,
|
|
34
|
+
expression
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public getDataUnit(name:string, resourceID:string):Promise<UnitMetadata>{
|
|
42
|
+
const completPath = `dd://${resourceID}/${name}`;
|
|
43
|
+
return HttpFetcher.get().callGraphQL({ values : { "name": completPath }, query: this.templateByQuery.get("getDataUnit")});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public static bindTo(dataUnit:DataUnit, resourceID:string):DataUnitFetcher{
|
|
47
|
+
const du = new DataUnitFetcher();
|
|
48
|
+
dataUnit.metadataLoader = (name:string) => du.getDataUnit(name, resourceID);
|
|
49
|
+
//TODO: Implementar bind dos demais métodos.
|
|
50
|
+
return du;
|
|
51
|
+
}
|
|
52
|
+
}
|