@firedesktop/react-base 1.50.0 → 1.52.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.
- package/package.json +1 -1
- package/src/lib/components/AppIcon.tsx +784 -0
- package/src/lib/components/AppInput.tsx +66 -0
- package/src/lib/components/AppPagination.tsx +124 -0
- package/src/lib/components/Spin.tsx +31 -0
- package/src/lib/components/Toaster/Toaster.tsx +50 -0
- package/src/lib/components/Toaster/Types.ts +11 -0
- package/src/lib/components/index.ts +8 -0
- package/src/lib/index.ts +15 -0
- package/src/lib/styles/base.css +392 -0
- package/src/lib/styles/syncfusion_bootstrap4.css +10 -0
- package/src/lib/styles/toaster.css +50 -0
- package/src/lib/utils/CurrencyUtiles.ts +28 -0
- package/src/lib/utils/DateUtils.ts +135 -0
- package/src/lib/utils/FileUtil.ts +27 -0
- package/src/lib/utils/configuration/ConfigurationLoader.tsx +43 -0
- package/src/lib/utils/configuration/ConfigurationManager.ts +29 -0
- package/src/lib/utils/configuration/ConfigurationReturner.tsx +39 -0
- package/src/lib/utils/configuration/index.ts +9 -0
- package/src/lib/utils/fetch/Types.ts +11 -0
- package/src/lib/utils/fetch/fetchWrapper.ts +144 -0
- package/src/lib/utils/fetch/index.ts +4 -0
- package/src/lib/utils/index.ts +8 -0
- package/src/lib/utils/labels/LanguageLoader.tsx +67 -0
- package/src/lib/utils/labels/LanguageManager.ts +53 -0
- package/src/lib/utils/labels/LanguageReturner.tsx +41 -0
- package/src/lib/utils/labels/index.ts +9 -0
- package/.vscode/settings.json +0 -3
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: 'Toast_icons';
|
|
3
|
+
src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype');
|
|
4
|
+
font-weight: normal;
|
|
5
|
+
font-style: normal;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
#toast_types button {
|
|
9
|
+
margin: 5px;
|
|
10
|
+
min-width: 160px;
|
|
11
|
+
max-width: 160px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#toast_types {
|
|
15
|
+
text-align: center;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.toast-icons {
|
|
19
|
+
font-family: 'Toast_icons' !important;
|
|
20
|
+
speak: none;
|
|
21
|
+
font-size: 55px;
|
|
22
|
+
font-style: normal;
|
|
23
|
+
font-weight: normal;
|
|
24
|
+
font-variant: normal;
|
|
25
|
+
text-transform: none;
|
|
26
|
+
line-height: 1;
|
|
27
|
+
-webkit-font-smoothing: antialiased;
|
|
28
|
+
-moz-osx-font-smoothing: grayscale;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#toast_type .e-toast-icon.e-icons {
|
|
32
|
+
height: auto;
|
|
33
|
+
font-size: 30px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.toast-icons.e-success::before {
|
|
37
|
+
content: "\e701";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.toast-icons.e-error::before {
|
|
41
|
+
content: "\e700";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.toast-icons.e-info::before {
|
|
45
|
+
content: "\e704";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.toast-icons.e-warning::before {
|
|
49
|
+
content: "\e703";
|
|
50
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default function CurrencyUtiles() {
|
|
2
|
+
/**
|
|
3
|
+
* Intl
|
|
4
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
|
|
5
|
+
*
|
|
6
|
+
* @param value
|
|
7
|
+
* @param locale 'en-US' or 'en' or 'US'...
|
|
8
|
+
* @param currency https://www.easymarkets.com/eu/learn-centre/discover-trading/currency-acronyms-and-abbreviations/, default EUR
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
const numberToCurrencyString = (value: string | number | undefined, locale: string = 'IT', currency = 'EUR'): String => {
|
|
12
|
+
try {
|
|
13
|
+
const valueNumber = Number(value);
|
|
14
|
+
|
|
15
|
+
if (value === undefined || value === null || isNaN(valueNumber))
|
|
16
|
+
return '';
|
|
17
|
+
|
|
18
|
+
return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(valueNumber);
|
|
19
|
+
} catch (err) { }
|
|
20
|
+
|
|
21
|
+
return '';
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
numberToCurrencyString
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
export default function DateUtils() {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Intl
|
|
5
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
|
|
6
|
+
* format
|
|
7
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format
|
|
8
|
+
* @param inComingDate
|
|
9
|
+
* @param locale 'en-US' or 'en' or 'US'...
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
const dateToString = (inComingDate: string | Date, locale: string = 'IT'): String => {
|
|
13
|
+
try {
|
|
14
|
+
if (inComingDate instanceof Date)
|
|
15
|
+
return new Intl.DateTimeFormat(locale, {
|
|
16
|
+
|
|
17
|
+
}).format(inComingDate);
|
|
18
|
+
else
|
|
19
|
+
return new Intl.DateTimeFormat(locale).format(new Date(inComingDate));
|
|
20
|
+
} catch (err) { }
|
|
21
|
+
|
|
22
|
+
return '';
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const dateToString_Italian = (inComingDate: string | Date | undefined, separator: string,
|
|
26
|
+
time: 'HH:mm' | 'HH:mm:ss' | undefined): string => {
|
|
27
|
+
if (!inComingDate)
|
|
28
|
+
return '';
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
let day = 0;
|
|
32
|
+
let month = 0;
|
|
33
|
+
let year = 0;
|
|
34
|
+
let hour = 0;
|
|
35
|
+
let minutes = 0;
|
|
36
|
+
let seconds = 0;
|
|
37
|
+
|
|
38
|
+
if (inComingDate instanceof Date) {
|
|
39
|
+
day = inComingDate.getDate();
|
|
40
|
+
month = inComingDate.getMonth();
|
|
41
|
+
year = inComingDate.getFullYear();
|
|
42
|
+
|
|
43
|
+
hour = inComingDate.getHours();
|
|
44
|
+
minutes = inComingDate.getMinutes();
|
|
45
|
+
seconds = inComingDate.getSeconds();
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const newD = new Date(inComingDate);
|
|
49
|
+
day = newD.getDate();
|
|
50
|
+
month = newD.getMonth();
|
|
51
|
+
year = newD.getFullYear();
|
|
52
|
+
|
|
53
|
+
hour = newD.getHours();
|
|
54
|
+
minutes = newD.getMinutes();
|
|
55
|
+
seconds = newD.getSeconds();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let value = `${('' + day).padStart(2, '0')}${separator}${('' + (month + 1)).padStart(2, '0')}${separator}${year}`;
|
|
59
|
+
|
|
60
|
+
if (time) {
|
|
61
|
+
value += ` ${('' + hour).padStart(2, '0')}:${('' + minutes).padStart(2, '0')}`;
|
|
62
|
+
if (time === 'HH:mm:ss')
|
|
63
|
+
value += `:${('' + seconds).padStart(2, '0')}`;
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
} catch (err) { }
|
|
67
|
+
|
|
68
|
+
return '';
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const isoStringToDate = (value: string | undefined): Date | undefined => {
|
|
72
|
+
if (!value)
|
|
73
|
+
return undefined;
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
return new Date(value);
|
|
77
|
+
} catch (err) { }
|
|
78
|
+
|
|
79
|
+
return undefined;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const removeTime = (inComingDate?: string | Date): Date | undefined => {
|
|
83
|
+
if (!inComingDate)
|
|
84
|
+
return undefined;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
let date: Date;
|
|
88
|
+
if (inComingDate instanceof Date) {
|
|
89
|
+
date = inComingDate;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
date = new Date(inComingDate);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return new Date(
|
|
96
|
+
date.getFullYear(),
|
|
97
|
+
date.getMonth(),
|
|
98
|
+
date.getDate()
|
|
99
|
+
);
|
|
100
|
+
} catch (err) { }
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* inComingDate: must be in the following format '2022-07-07T14:00:00.000Z'
|
|
105
|
+
*/
|
|
106
|
+
const zuluTimeUTC_to_yourTimeZone = (inComingDate: string): string => {
|
|
107
|
+
if (inComingDate && inComingDate[inComingDate.length - 1] === 'Z') {
|
|
108
|
+
try {
|
|
109
|
+
const date = new Date(inComingDate);
|
|
110
|
+
const day = date.getDate();
|
|
111
|
+
const month = date.getMonth();
|
|
112
|
+
const year = date.getFullYear();
|
|
113
|
+
const hour = date.getHours();
|
|
114
|
+
const minutes = date.getMinutes();
|
|
115
|
+
const seconds = date.getSeconds();
|
|
116
|
+
const separator = '-';
|
|
117
|
+
|
|
118
|
+
return `${year}${separator}${('' + (month + 1)).padStart(2, '0')}${separator}${('' + day).padStart(2, '0')}` +
|
|
119
|
+
`T${('' + hour).padStart(2, '0')}:${('' + minutes).padStart(2, '0')}:${('' + seconds).padStart(2, '0')}`;
|
|
120
|
+
}
|
|
121
|
+
catch (err) { }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return inComingDate;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
dateToString,
|
|
130
|
+
dateToString_Italian,
|
|
131
|
+
isoStringToDate,
|
|
132
|
+
removeTime,
|
|
133
|
+
zuluTimeUTC_to_yourTimeZone
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function FileUtils() {
|
|
2
|
+
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
|
|
3
|
+
const byteCharacters = atob(b64Data);
|
|
4
|
+
const byteArrays = [];
|
|
5
|
+
|
|
6
|
+
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
|
|
7
|
+
const slice = byteCharacters.slice(offset, offset + sliceSize);
|
|
8
|
+
|
|
9
|
+
const byteNumbers = new Array(slice.length);
|
|
10
|
+
for (let i = 0; i < slice.length; i++) {
|
|
11
|
+
byteNumbers[i] = slice.charCodeAt(i);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
15
|
+
byteArrays.push(byteArray);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const blob = new Blob(byteArrays, { type: contentType });
|
|
19
|
+
return blob;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
b64toBlob
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default FileUtils;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
3
|
+
|
|
4
|
+
import ConfigurationManager from './ConfigurationManager';
|
|
5
|
+
|
|
6
|
+
export type configurationLoaderParamsType = {
|
|
7
|
+
updateAppState: (name: string, value: object) => any,
|
|
8
|
+
path?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function ConfigurationLoader({ updateAppState, path }: configurationLoaderParamsType) {
|
|
12
|
+
const dispatch = useDispatch();
|
|
13
|
+
const { configuration }: any = useSelector(state => state);
|
|
14
|
+
const { loadConfiguration } = ConfigurationManager();
|
|
15
|
+
|
|
16
|
+
let fullPath = '/configuration/config.json';
|
|
17
|
+
if (path)
|
|
18
|
+
fullPath = path;
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
async function justAsync() {
|
|
22
|
+
if (!configuration || !configuration.loaded) {
|
|
23
|
+
console.log(`Loading Configuration for this Site in this path: ${fullPath}`);
|
|
24
|
+
await loadConfiguration(fullPath).then((response: any) => {
|
|
25
|
+
console.log(`Loaded Configuration for this Site in this path: ${fullPath}`, response);
|
|
26
|
+
dispatch(updateAppState('configuration', response));
|
|
27
|
+
|
|
28
|
+
}).catch((err: any) => {
|
|
29
|
+
console.error(`Problem loading the Site Configuration in this path: ${fullPath}`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
justAsync();
|
|
34
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<React.Fragment>
|
|
39
|
+
</React.Fragment>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default ConfigurationLoader;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function ConfigurationManager() {
|
|
2
|
+
|
|
3
|
+
async function loadConfiguration(fullPath: string) {
|
|
4
|
+
try {
|
|
5
|
+
const res = await fetch(fullPath, { headers: { 'Content-Type': 'application/json; charset=utf-8' } });
|
|
6
|
+
return await res.json();
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
console.error('Problem loading the Site Labels');
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
async function loadConfigurationWithDispatch(dispatch: any, updateAppState: any, configuration: any) {
|
|
14
|
+
if (!configuration || !configuration.loaded) {
|
|
15
|
+
const fullPath = '/configuration/config.json';
|
|
16
|
+
console.log(`Loading Configuration for this Site from this path: ${fullPath}`);
|
|
17
|
+
loadConfiguration(fullPath).then((response: any) => {
|
|
18
|
+
console.log(`Loaded Configuration for this Site in this path: ${fullPath}`, response);
|
|
19
|
+
dispatch(updateAppState('configuration', response));
|
|
20
|
+
}).catch((err: any) => {
|
|
21
|
+
console.error(`Problem loading the Site Configuration in this path: ${fullPath}`);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return { loadConfiguration, loadConfigurationWithDispatch };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default ConfigurationManager;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import ConfigurationManager from './ConfigurationManager';
|
|
4
|
+
|
|
5
|
+
export type Configuration_Type = {
|
|
6
|
+
loaded: boolean
|
|
7
|
+
}
|
|
8
|
+
export type configurationLoaderParamsType = {
|
|
9
|
+
configuration?: Configuration_Type
|
|
10
|
+
onConfigurationLoad: (condifiguration?: Configuration_Type) => void
|
|
11
|
+
path: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function ConfigurationReturner({ configuration, onConfigurationLoad, path }: configurationLoaderParamsType) {
|
|
15
|
+
const { loadConfiguration } = ConfigurationManager();
|
|
16
|
+
|
|
17
|
+
const fullPath = `${path}/config.json`;
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
async function justAsync() {
|
|
21
|
+
if (!configuration || !configuration.loaded) {
|
|
22
|
+
console.log(`Loading Configuration for this Path: ${path} in this fullpath: ${fullPath}`);
|
|
23
|
+
await loadConfiguration(fullPath).then((response: any) => {
|
|
24
|
+
console.log(`Loaded Configuration for this Path: ${path} in this fullpath: ${fullPath}`, response);
|
|
25
|
+
onConfigurationLoad(response);
|
|
26
|
+
}).catch((err: any) => {
|
|
27
|
+
console.error(`Problem loading the Path: ${path} Configuration in this fullpath: ${fullPath}`);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
justAsync();
|
|
32
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<React.Fragment>
|
|
37
|
+
</React.Fragment>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import ConfigurationManager from './ConfigurationManager';
|
|
2
|
+
import ConfigurationLoader from './ConfigurationLoader';
|
|
3
|
+
import ConfigurationReturner from './ConfigurationReturner';
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
ConfigurationLoader,
|
|
7
|
+
ConfigurationManager,
|
|
8
|
+
ConfigurationReturner
|
|
9
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import * as Types from './Types';
|
|
2
|
+
|
|
3
|
+
class Constants {
|
|
4
|
+
static labels = {
|
|
5
|
+
errorBadRequest: 'Request is not in a valid format',
|
|
6
|
+
errorGeneric: 'Sorry we have errors on the remote server',
|
|
7
|
+
errorServerNotAvailable: 'Server not available',
|
|
8
|
+
errorSessionExpired: 'Your session has expired, please login.',
|
|
9
|
+
} as Types.ILabels;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class FetchWrapper {
|
|
13
|
+
apiVersion?: string;
|
|
14
|
+
labels?: Types.ILabels;
|
|
15
|
+
status_401?: () => void;
|
|
16
|
+
status_403?: () => void;
|
|
17
|
+
|
|
18
|
+
constructor(apiVersion?: string, labels?: Types.ILabels, status_401?: () => void, status_403?: () => void) {
|
|
19
|
+
this.apiVersion = apiVersion;
|
|
20
|
+
this.status_401 = status_401;
|
|
21
|
+
this.status_403 = status_403;
|
|
22
|
+
|
|
23
|
+
if (labels && labels !== null && labels.errorGeneric && labels.errorServerNotAvailable && labels.errorSessionExpired)
|
|
24
|
+
this.labels = labels;
|
|
25
|
+
else
|
|
26
|
+
this.labels = Constants.labels;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get = (url: string, applicationName?: string, token?: string, onGenericServerError?: (status: number, error?: any) => void, params?: Blob | any, isFile = false, isBlobInReturn = false) => {
|
|
30
|
+
return this.generic('GET', url, applicationName, token, onGenericServerError, params, isFile, isBlobInReturn);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
post = (url: string, applicationName?: string, token?: string, onGenericServerError?: (status: number, error?: any) => void, params?: Blob | any, isFile = false, isBlobInReturn = false,
|
|
34
|
+
additionalParams: Types.AdditionalParamsType[] = []) => {
|
|
35
|
+
return this.generic('POST', url, applicationName, token, onGenericServerError, params, isFile, isBlobInReturn, this.apiVersion, additionalParams);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
put = (url: string, applicationName?: string, token?: string, onGenericServerError?: (status: number, error?: any) => void, params?: Blob | any, isFile = false, isBlobInReturn = false) => {
|
|
39
|
+
return this.generic('PUT', url, applicationName, token, onGenericServerError, params, isFile, isBlobInReturn);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
delete = (url: string, applicationName?: string, token?: string, onGenericServerError?: (status: number, error?: any) => void, params?: Blob | any, isFile = false, isBlobInReturn = false) => {
|
|
43
|
+
return this.generic('DELETE', url, applicationName, token, onGenericServerError, params, isFile, isBlobInReturn);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
generic = (method: string, url: string, applicationName?: string, token?: string, onGenericServerError?: (status: number, error?: any) => void, params?: Blob | any, isFile = false,
|
|
47
|
+
isBlobInReturn = false, version = this.apiVersion, additionalParams: Types.AdditionalParamsType[] = []) => {
|
|
48
|
+
// Headers & Body
|
|
49
|
+
let body: BodyInit;
|
|
50
|
+
const headers = new Headers();
|
|
51
|
+
headers.append('pragma', 'no-cache');
|
|
52
|
+
if (version)
|
|
53
|
+
headers.append('api-version', version);
|
|
54
|
+
if (applicationName)
|
|
55
|
+
headers.append('ApplicationName', applicationName);
|
|
56
|
+
if (token)
|
|
57
|
+
headers.append('SessionToken', token);
|
|
58
|
+
// This should be the right way, but here we use SessionToken
|
|
59
|
+
// headers.append('Authorization', 'Bearer ' + token);
|
|
60
|
+
|
|
61
|
+
if (params) {
|
|
62
|
+
if (isFile) {
|
|
63
|
+
var formData = new FormData();
|
|
64
|
+
formData.append('file', params);
|
|
65
|
+
body = formData;
|
|
66
|
+
if (additionalParams) {
|
|
67
|
+
for (let index = 0; index < additionalParams.length; index++) {
|
|
68
|
+
const element = additionalParams[index];
|
|
69
|
+
formData.append(element.name, '' + element.value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
headers.append('Content-Type', 'application/json');
|
|
74
|
+
body = JSON.stringify(params);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const requestInit = {
|
|
79
|
+
body,
|
|
80
|
+
method: method,
|
|
81
|
+
mode: 'cors',
|
|
82
|
+
cache: 'no-cache',
|
|
83
|
+
credentials: 'omit',
|
|
84
|
+
headers
|
|
85
|
+
} as RequestInit;
|
|
86
|
+
|
|
87
|
+
const labels = this.labels;
|
|
88
|
+
const status_401 = this.status_401;
|
|
89
|
+
const status_403 = this.status_403;
|
|
90
|
+
|
|
91
|
+
return fetch(encodeURI(url), requestInit)
|
|
92
|
+
.then(response => {
|
|
93
|
+
// Others Status Code
|
|
94
|
+
if (response.status < 200 || response.status >= 300)
|
|
95
|
+
throw response;
|
|
96
|
+
|
|
97
|
+
return isBlobInReturn ? response.blob() : response.json();
|
|
98
|
+
})
|
|
99
|
+
.then(json => {
|
|
100
|
+
return json;
|
|
101
|
+
})
|
|
102
|
+
.catch(error => {
|
|
103
|
+
console.error(`Error on fetch url: ${url}`);
|
|
104
|
+
|
|
105
|
+
if (!error || error.message === 'Failed to fetch')
|
|
106
|
+
throw new Error(labels.errorServerNotAvailable);
|
|
107
|
+
|
|
108
|
+
// This is an error coming from BE
|
|
109
|
+
if (error.status === 401 && status_401) {
|
|
110
|
+
status_401();
|
|
111
|
+
} else if (error.status === 403 && status_401) {
|
|
112
|
+
status_403();
|
|
113
|
+
} else if (error.status === 400 && onGenericServerError) {
|
|
114
|
+
onGenericServerError(error.status, error);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!error.text) {
|
|
118
|
+
if (error.status === 400) {
|
|
119
|
+
throw new Error(labels.errorBadRequest);
|
|
120
|
+
} else if (error.status === 401 || error.status === 403) {
|
|
121
|
+
throw new Error(labels.errorSessionExpired);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
return error.text();
|
|
126
|
+
|
|
127
|
+
if (error.message && error.message !== '')
|
|
128
|
+
throw error.message;
|
|
129
|
+
|
|
130
|
+
throw new Error(labels.errorGeneric);
|
|
131
|
+
})
|
|
132
|
+
.then(finalMessage => {
|
|
133
|
+
if (typeof (finalMessage) === 'object')
|
|
134
|
+
return finalMessage;
|
|
135
|
+
|
|
136
|
+
if (finalMessage)
|
|
137
|
+
throw new Error(finalMessage);
|
|
138
|
+
|
|
139
|
+
throw new Error(labels.errorGeneric);
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default FetchWrapper;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Fetch from './fetch';
|
|
2
|
+
import * as Configuration from './configuration';
|
|
3
|
+
import CurrencyUtiles from './CurrencyUtiles';
|
|
4
|
+
import DateUtils from './DateUtils';
|
|
5
|
+
import FileUtils from './FileUtil';
|
|
6
|
+
import * as Labels from './labels';
|
|
7
|
+
|
|
8
|
+
export { Configuration, CurrencyUtiles, DateUtils, Fetch, FileUtils, Labels };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
4
|
+
|
|
5
|
+
import LanguageManager from './LanguageManager';
|
|
6
|
+
|
|
7
|
+
export type languageLoaderParamsType = {
|
|
8
|
+
updateAppState: (name: string, value: object) => any,
|
|
9
|
+
language: string,
|
|
10
|
+
path?: string,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function LanguageLoader({ updateAppState, language, path }: languageLoaderParamsType) {
|
|
14
|
+
const dispatch = useDispatch();
|
|
15
|
+
const { labels }: any = useSelector(state => state);
|
|
16
|
+
const { loadLabels } = LanguageManager();
|
|
17
|
+
|
|
18
|
+
const fileName = `${language}.json`;
|
|
19
|
+
|
|
20
|
+
const baseLanguageFullPath = `./labels/${fileName}`;
|
|
21
|
+
|
|
22
|
+
let fullPath = `./labels/${fileName}`;
|
|
23
|
+
if (path)
|
|
24
|
+
fullPath = `./${path}/${fileName}`;
|
|
25
|
+
|
|
26
|
+
// Do it on change language
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
async function justAsync() {
|
|
29
|
+
if (!labels || !labels.language || labels.language !== language) {
|
|
30
|
+
|
|
31
|
+
console.log(`Loading Base Language Labels for this Site in this path: ${baseLanguageFullPath}`);
|
|
32
|
+
let allLabels: any = {};
|
|
33
|
+
try {
|
|
34
|
+
allLabels = await loadLabels(baseLanguageFullPath);
|
|
35
|
+
console.log(`Loaded Base Language Labels for this Site in this path: ${baseLanguageFullPath}`, allLabels);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.error(`Problem loading Base Site Language Labels in this path: ${baseLanguageFullPath}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log(`Loading Custom Language Labels for this Site in this path: ${fullPath}`);
|
|
42
|
+
loadLabels(fullPath).then((response: any) => {
|
|
43
|
+
if (response) {
|
|
44
|
+
console.log(`Loaded Custom Language Labels for this Site in this path: ${fullPath}`, response);
|
|
45
|
+
const merged = _.merge(allLabels, response);
|
|
46
|
+
dispatch(updateAppState('labels', merged));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.warn(`Custom Site Language Labels NOT FOUND in this path: ${fullPath}`);
|
|
50
|
+
dispatch(updateAppState('labels', allLabels));
|
|
51
|
+
}
|
|
52
|
+
}).catch((err: any) => {
|
|
53
|
+
console.warn(`Custom Site Language Labels NOT FOUND in this path: ${fullPath}`);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
justAsync();
|
|
58
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
59
|
+
}, [language]);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<React.Fragment>
|
|
63
|
+
</React.Fragment>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default LanguageLoader;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function LanguageManager() {
|
|
2
|
+
|
|
3
|
+
async function loadLabels(fullPath: string) {
|
|
4
|
+
try {
|
|
5
|
+
const res = await fetch(fullPath, { headers: { 'Content-Type': 'application/json; charset=utf-8' } });
|
|
6
|
+
return await res.json();
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
console.warn(`Problem loading the Site Labels, Path ${fullPath}`);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
async function loadLabelsWithDispatch(dispatch: any, updateAppState: any, labels: any, language: string) {
|
|
14
|
+
if (!labels || !labels.language || labels.language !== language) {
|
|
15
|
+
const fullPath = `./labels/${language}.json`;
|
|
16
|
+
console.log(`Loading Labels for this Language ${language}, from this path: ${fullPath}`);
|
|
17
|
+
loadLabels(fullPath).then((response: any) => {
|
|
18
|
+
console.log(`Loaded Labels for this Language ${language}`, response);
|
|
19
|
+
dispatch(updateAppState('labels', response));
|
|
20
|
+
}).catch((err: any) => {
|
|
21
|
+
console.warn(`Problem loading the Site Labels, language: ${language}, fullPath: ${fullPath}`);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getLabel(labels: any, id: string, defaultValue?: string) {
|
|
27
|
+
if (labels === null || labels === undefined)
|
|
28
|
+
return defaultValue || '';
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const splits = id.split('.');
|
|
32
|
+
let message = labels;
|
|
33
|
+
for (let index = 0; index < splits.length; index++) {
|
|
34
|
+
const element = splits[index];
|
|
35
|
+
message = message[element];
|
|
36
|
+
}
|
|
37
|
+
if (message !== null && message !== undefined)
|
|
38
|
+
return message;
|
|
39
|
+
|
|
40
|
+
return defaultValue ? defaultValue : id;
|
|
41
|
+
} catch (ex) {
|
|
42
|
+
return defaultValue ? defaultValue : id;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
getLabel,
|
|
48
|
+
loadLabels,
|
|
49
|
+
loadLabelsWithDispatch
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default LanguageManager;
|