@onewelcome/react-lib-components 1.8.3 → 1.9.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/dist/Button/BaseButton.d.ts +2 -1
- package/dist/Button/Button.d.ts +1 -1
- package/dist/Button/IconButton.d.ts +1 -1
- package/dist/Button/Spinner.d.ts +2 -0
- package/dist/_BaseStyling_/BaseStyling.d.ts +1 -1
- package/dist/react-lib-components.cjs.development.js +39 -14
- package/dist/react-lib-components.cjs.development.js.map +1 -1
- package/dist/react-lib-components.cjs.production.min.js +1 -1
- package/dist/react-lib-components.cjs.production.min.js.map +1 -1
- package/dist/react-lib-components.esm.js +40 -15
- package/dist/react-lib-components.esm.js.map +1 -1
- package/dist/util/helper.d.ts +1 -0
- package/package.json +14 -14
- package/src/Button/BaseButton.module.scss +24 -0
- package/src/Button/BaseButton.test.tsx +12 -0
- package/src/Button/BaseButton.tsx +17 -5
- package/src/Button/Spinner.tsx +33 -0
- package/src/DataGrid/DataGridBody/__snapshots__/DataGridBody.test.tsx.snap +4 -4
- package/src/Form/FileUpload/FileUpload.module.scss +9 -2
- package/src/Form/FileUpload/FileUpload.tsx +35 -33
- package/src/Form/Wrapper/InputWrapper/InputWrapper.module.scss +1 -0
- package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.module.scss +1 -1
- package/src/_BaseStyling_/BaseStyling.tsx +14 -6
- package/src/hooks/useUploadFile.test.ts +2 -2
- package/src/hooks/useUploadFile.tsx +8 -5
- package/src/util/helper.test.tsx +16 -1
- package/src/util/helper.tsx +9 -0
package/dist/util/helper.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export declare const getValueByPath: (obj: {
|
|
|
12
12
|
}, path: string) => any;
|
|
13
13
|
/** Source: https://stackoverflow.com/a/42769683/5084110 */
|
|
14
14
|
export declare const remToPx: (rem: number) => number;
|
|
15
|
+
export declare const isJsonString: (str: any) => boolean;
|
|
15
16
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"homepage": "http://onewelcome.github.io/react-lib-components",
|
|
3
3
|
"name": "@onewelcome/react-lib-components",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.9.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "OneWelcome B.V.",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
}
|
|
54
54
|
],
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@babel/core": "^7.21.
|
|
56
|
+
"@babel/core": "^7.21.3",
|
|
57
57
|
"@mdx-js/react": "^1.6.22",
|
|
58
58
|
"@onewelcome/eslint-config-shared-codestyle": "^9.0.3",
|
|
59
59
|
"@size-limit/preset-small-lib": "^8.2.4",
|
|
@@ -80,13 +80,13 @@
|
|
|
80
80
|
"@types/react-dom": "^17.0.18",
|
|
81
81
|
"@types/react-router": "^5.1.20",
|
|
82
82
|
"@types/react-router-dom": "^5.3.3",
|
|
83
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
84
|
-
"@typescript-eslint/parser": "^5.
|
|
83
|
+
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
|
84
|
+
"@typescript-eslint/parser": "^5.56.0",
|
|
85
85
|
"babel-loader": "^9.1.2",
|
|
86
|
-
"chromatic": "^6.17.
|
|
86
|
+
"chromatic": "^6.17.2",
|
|
87
87
|
"dts-cli": "^1.6.3",
|
|
88
|
-
"eslint": "^8.
|
|
89
|
-
"eslint-config-prettier": "^8.
|
|
88
|
+
"eslint": "^8.36.0",
|
|
89
|
+
"eslint-config-prettier": "^8.8.0",
|
|
90
90
|
"eslint-plugin-cypress": "^2.12.1",
|
|
91
91
|
"eslint-plugin-jest": "^27.2.1",
|
|
92
92
|
"eslint-plugin-license-header": "^0.6.0",
|
|
@@ -95,19 +95,19 @@
|
|
|
95
95
|
"husky": "^8.0.3",
|
|
96
96
|
"identity-obj-proxy": "^3.0.0",
|
|
97
97
|
"jest-junit": "^15.0.0",
|
|
98
|
-
"lint-staged": "^13.
|
|
98
|
+
"lint-staged": "^13.2.0",
|
|
99
99
|
"npm-run-all": "^4.1.5",
|
|
100
|
-
"prettier": "^2.8.
|
|
100
|
+
"prettier": "^2.8.6",
|
|
101
101
|
"react": "^17.0.2",
|
|
102
102
|
"react-dom": "^17.0.2",
|
|
103
103
|
"react-is": "^18.2.0",
|
|
104
|
-
"react-router": "^6.
|
|
105
|
-
"react-router-dom": "^6.
|
|
104
|
+
"react-router": "^6.9.0",
|
|
105
|
+
"react-router-dom": "^6.9.0",
|
|
106
106
|
"rollup-plugin-cleanup": "^3.2.1",
|
|
107
107
|
"rollup-plugin-styles": "^4.0.0",
|
|
108
|
-
"sass": "^1.
|
|
109
|
-
"size-limit": "^8.
|
|
110
|
-
"style-loader": "^3.3.
|
|
108
|
+
"sass": "^1.60.0",
|
|
109
|
+
"size-limit": "^8.2.4",
|
|
110
|
+
"style-loader": "^3.3.2",
|
|
111
111
|
"tslib": "^2.5.0",
|
|
112
112
|
"typescript": "^4.9.5"
|
|
113
113
|
}
|
|
@@ -18,4 +18,28 @@
|
|
|
18
18
|
|
|
19
19
|
.button {
|
|
20
20
|
@include mixins.buttonBase();
|
|
21
|
+
position: relative;
|
|
22
|
+
|
|
23
|
+
.content-hidden {
|
|
24
|
+
visibility: hidden;
|
|
25
|
+
display: flex;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.spinner {
|
|
30
|
+
position: absolute;
|
|
31
|
+
top: calc(50% - 0.75rem);
|
|
32
|
+
left: calc(50% - 0.75rem);
|
|
33
|
+
transform: translate(-50%, -50%);
|
|
34
|
+
animation: spin 1s infinite linear;
|
|
35
|
+
|
|
36
|
+
@keyframes spin {
|
|
37
|
+
0% {
|
|
38
|
+
transform: rotate(0deg);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
100% {
|
|
42
|
+
transform: rotate(360deg);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
21
45
|
}
|
|
@@ -75,6 +75,18 @@ describe("Properties of the button", () => {
|
|
|
75
75
|
expect(onClickHandler).toHaveBeenCalledTimes(0);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
it("when loading onClick function should not have been called", async () => {
|
|
79
|
+
const onClickHandler = jest.fn();
|
|
80
|
+
const { baseButton } = createBaseButton(defaultParams => ({
|
|
81
|
+
...defaultParams,
|
|
82
|
+
loading: true,
|
|
83
|
+
onClick: onClickHandler
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
await userEvent.click(baseButton);
|
|
87
|
+
expect(onClickHandler).toHaveBeenCalledTimes(0);
|
|
88
|
+
});
|
|
89
|
+
|
|
78
90
|
it('should have the class "TESTING"', () => {
|
|
79
91
|
const { baseButton } = createBaseButton(defaultParams => ({
|
|
80
92
|
...defaultParams,
|
|
@@ -14,21 +14,23 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import React, { ForwardRefRenderFunction, ComponentPropsWithRef } from "react";
|
|
17
|
+
import React, { ForwardRefRenderFunction, ComponentPropsWithRef, Fragment } from "react";
|
|
18
18
|
import classes from "./BaseButton.module.scss";
|
|
19
|
+
import { Spinner } from "./Spinner";
|
|
19
20
|
|
|
20
21
|
export interface Props extends ComponentPropsWithRef<"button"> {
|
|
21
22
|
type?: "submit" | "button" | "reset";
|
|
22
23
|
disabled?: boolean;
|
|
24
|
+
loading?: boolean;
|
|
23
25
|
color?: "primary" | "secondary" | "tertiary" | "default";
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
const BaseButtonComponent: ForwardRefRenderFunction<HTMLButtonElement, Props> = (
|
|
27
|
-
{ children, type = "button", className, ...rest },
|
|
29
|
+
{ children, type = "button", className, loading, disabled, ...rest },
|
|
28
30
|
ref
|
|
29
31
|
) => {
|
|
30
32
|
const validTypes = ["submit", "button", "reset"];
|
|
31
|
-
|
|
33
|
+
const isDisabled = disabled || loading;
|
|
32
34
|
if (!validTypes.includes(type))
|
|
33
35
|
throw new Error(
|
|
34
36
|
`You have entered an invalid button type. Expected 'submit', 'button' or 'reset' got ${type}`
|
|
@@ -37,11 +39,21 @@ const BaseButtonComponent: ForwardRefRenderFunction<HTMLButtonElement, Props> =
|
|
|
37
39
|
return (
|
|
38
40
|
<button
|
|
39
41
|
{...rest}
|
|
42
|
+
disabled={isDisabled}
|
|
40
43
|
ref={ref}
|
|
41
44
|
type={type}
|
|
42
|
-
className={`${classes.button} ${
|
|
45
|
+
className={`${classes.button} ${loading ? classes.loading : ""} ${
|
|
46
|
+
className ? className : ""
|
|
47
|
+
}`}
|
|
43
48
|
>
|
|
44
|
-
{
|
|
49
|
+
{loading ? (
|
|
50
|
+
<Fragment>
|
|
51
|
+
<div className={classes["content-hidden"]}>{children}</div>
|
|
52
|
+
<Spinner className={classes["spinner"]} />
|
|
53
|
+
</Fragment>
|
|
54
|
+
) : (
|
|
55
|
+
children
|
|
56
|
+
)}
|
|
45
57
|
</button>
|
|
46
58
|
);
|
|
47
59
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 OneWelcome B.V.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React from "react";
|
|
18
|
+
|
|
19
|
+
export const Spinner: React.FC<React.SVGProps<SVGSVGElement>> = props => (
|
|
20
|
+
<svg
|
|
21
|
+
{...props}
|
|
22
|
+
width="24"
|
|
23
|
+
height="24"
|
|
24
|
+
viewBox="0 0 24 24"
|
|
25
|
+
fill="none"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
+
>
|
|
28
|
+
<path
|
|
29
|
+
d="M24 12C24 13.8937 23.5518 15.7606 22.6921 17.4479C21.8323 19.1352 20.5855 20.5951 19.0534 21.7082C17.5214 22.8213 15.7476 23.556 13.8772 23.8523C12.0068 24.1485 10.0928 23.9979 8.2918 23.4127C6.49076 22.8275 4.85378 21.8243 3.51472 20.4853C2.17565 19.1462 1.17251 17.5092 0.587322 15.7082C0.00212849 13.9072 -0.148504 11.9932 0.14774 10.1228C0.443984 8.25238 1.17869 6.47863 2.2918 4.94658L3.91307 6.1245C2.98585 7.4007 2.37384 8.87823 2.12707 10.4363C1.8803 11.9943 2.00577 13.5887 2.49324 15.0889C2.9807 16.5892 3.81632 17.9528 4.93176 19.0682C6.0472 20.1837 7.4108 21.0193 8.91107 21.5068C10.4113 21.9942 12.0057 22.1197 13.5637 21.8729C15.1218 21.6262 16.5993 21.0141 17.8755 20.0869C19.1517 19.1597 20.1903 17.9436 20.9065 16.5381C21.6227 15.1326 21.996 13.5775 21.996 12H24Z"
|
|
30
|
+
fill="#5D607E"
|
|
31
|
+
/>
|
|
32
|
+
</svg>
|
|
33
|
+
);
|
|
@@ -45,7 +45,7 @@ Array [
|
|
|
45
45
|
aria-controls="consent_menu_Paweł-menu"
|
|
46
46
|
aria-expanded="false"
|
|
47
47
|
aria-haspopup="true"
|
|
48
|
-
class="button
|
|
48
|
+
class="button icon-button text default button-m"
|
|
49
49
|
id="consent_menu_Paweł"
|
|
50
50
|
tabindex="0"
|
|
51
51
|
type="button"
|
|
@@ -108,7 +108,7 @@ Array [
|
|
|
108
108
|
aria-controls="consent_menu_Michał-menu"
|
|
109
109
|
aria-expanded="false"
|
|
110
110
|
aria-haspopup="true"
|
|
111
|
-
class="button
|
|
111
|
+
class="button icon-button text default button-m"
|
|
112
112
|
id="consent_menu_Michał"
|
|
113
113
|
tabindex="0"
|
|
114
114
|
type="button"
|
|
@@ -171,7 +171,7 @@ Array [
|
|
|
171
171
|
aria-controls="consent_menu_Daniel-menu"
|
|
172
172
|
aria-expanded="false"
|
|
173
173
|
aria-haspopup="true"
|
|
174
|
-
class="button
|
|
174
|
+
class="button icon-button text default button-m"
|
|
175
175
|
id="consent_menu_Daniel"
|
|
176
176
|
tabindex="0"
|
|
177
177
|
type="button"
|
|
@@ -234,7 +234,7 @@ Array [
|
|
|
234
234
|
aria-controls="consent_menu_Jasha-menu"
|
|
235
235
|
aria-expanded="false"
|
|
236
236
|
aria-haspopup="true"
|
|
237
|
-
class="button
|
|
237
|
+
class="button icon-button text default button-m"
|
|
238
238
|
id="consent_menu_Jasha"
|
|
239
239
|
tabindex="0"
|
|
240
240
|
type="button"
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
}
|
|
40
40
|
&.error {
|
|
41
41
|
span[data-icon-status],
|
|
42
|
-
.file-upload-title
|
|
43
|
-
.file-selector-sub-text {
|
|
42
|
+
.file-upload-title {
|
|
44
43
|
color: var(--error);
|
|
45
44
|
}
|
|
46
45
|
}
|
|
@@ -63,6 +62,14 @@
|
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
64
|
|
|
65
|
+
.file-selector-sub-text {
|
|
66
|
+
color: var(--greyed-out);
|
|
67
|
+
padding: 0 1.25rem;
|
|
68
|
+
&.error {
|
|
69
|
+
color: var(--error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
66
73
|
.file-select {
|
|
67
74
|
display: flex;
|
|
68
75
|
align-items: center;
|
|
@@ -136,7 +136,7 @@ const FileUploadComponent: ForwardRefRenderFunction<HTMLInputElement, Props> = (
|
|
|
136
136
|
|
|
137
137
|
let err = false;
|
|
138
138
|
if (maxFileSize && file.size && file.size >= maxFileSize) {
|
|
139
|
-
const mb = (
|
|
139
|
+
const mb = (maxFileSize / (1024 * 1024)).toFixed(2);
|
|
140
140
|
result.error =
|
|
141
141
|
exceedingMaxSizeErrorText ||
|
|
142
142
|
`The maximum allowed file size is ${mb}MB. Upload a smaller file.`;
|
|
@@ -188,40 +188,42 @@ const FileUploadComponent: ForwardRefRenderFunction<HTMLInputElement, Props> = (
|
|
|
188
188
|
|
|
189
189
|
return (
|
|
190
190
|
<div className={classes["file-upload-wrapper"]} {...wrapperProps}>
|
|
191
|
-
<div
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
{title}
|
|
199
|
-
|
|
200
|
-
<div className={classes["file-select"]}>
|
|
201
|
-
<Icon className={"drop-file-icon"} icon={Icons.FileUpload} />
|
|
202
|
-
<Typography variant="body" className={"drag-and-drop-text"}>
|
|
203
|
-
{dragAndDropText}
|
|
191
|
+
<div className={classes["dropzone-wrapper"]}>
|
|
192
|
+
<div
|
|
193
|
+
className={dropzoneClassNames.join(" ")}
|
|
194
|
+
onDragOver={e => !disabled && handleOnDragOver(e)}
|
|
195
|
+
onDragLeave={e => !disabled && handleOnDragLeave(e)}
|
|
196
|
+
onDrop={e => !disabled && handleOnDrop(e)}
|
|
197
|
+
>
|
|
198
|
+
<Typography variant="body-bold" className={classes["file-upload-title"]} ref={labelRef}>
|
|
199
|
+
{title}
|
|
204
200
|
</Typography>
|
|
205
|
-
<div className={classes["file-
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
201
|
+
<div className={classes["file-select"]}>
|
|
202
|
+
<Icon className={"drop-file-icon"} icon={Icons.FileUpload} />
|
|
203
|
+
<Typography variant="body" className={"drag-and-drop-text"}>
|
|
204
|
+
{dragAndDropText}
|
|
205
|
+
</Typography>
|
|
206
|
+
<div className={classes["file-upload-btn"]}>
|
|
207
|
+
<Button variant="outline" disabled={disabled}>
|
|
208
|
+
{selectButtonText}
|
|
209
|
+
<input
|
|
210
|
+
className={classes["upload-input"]}
|
|
211
|
+
{...rest}
|
|
212
|
+
ref={ref}
|
|
213
|
+
aria-labelledby={labeledBy}
|
|
214
|
+
type="file"
|
|
215
|
+
name={name}
|
|
216
|
+
{...(multiple && { multiple: true })}
|
|
217
|
+
disabled={disabled}
|
|
218
|
+
accept={accept}
|
|
219
|
+
onChange={onInputChange}
|
|
220
|
+
spellCheck={rest.spellCheck || false}
|
|
221
|
+
/>
|
|
222
|
+
</Button>
|
|
223
|
+
</div>
|
|
224
|
+
{!disabled && icon}
|
|
225
|
+
<span className={classes["outline"]}></span>
|
|
222
226
|
</div>
|
|
223
|
-
{!disabled && icon}
|
|
224
|
-
<span className={classes["outline"]}></span>
|
|
225
227
|
</div>
|
|
226
228
|
{subText && (
|
|
227
229
|
<Typography variant={"sub-text"} className={subTextClass.join(" ")}>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* and make sure to add it to the shouldBeColorPicker array!
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import React, {
|
|
22
|
+
import React, { HTMLAttributes, ReactChild, useEffect, useRef, useState } from "react";
|
|
23
23
|
|
|
24
24
|
interface CSSProperties {
|
|
25
25
|
colorFocus?: string;
|
|
@@ -193,23 +193,31 @@ export const BaseStyling = ({ children, properties = {} }: Props) => {
|
|
|
193
193
|
|
|
194
194
|
/** We need a loading state, because otherwise you see the colors flash from the default to the possible overridden ones. */
|
|
195
195
|
const [isLoading, setIsLoading] = useState(true);
|
|
196
|
+
const baseStylingWrapper = useRef(null);
|
|
196
197
|
|
|
197
198
|
const setCSSProperties = (CSSPropertiesObject: CSSProperties) => {
|
|
198
199
|
for (const [key, value] of Object.entries(CSSPropertiesObject)) {
|
|
199
200
|
const formattedPropertyName = key.replace(/([A-Z])/g, val => `-${val.toLowerCase()}`);
|
|
200
|
-
|
|
201
|
+
(baseStylingWrapper.current! as HTMLElement).style.setProperty(
|
|
202
|
+
`--${formattedPropertyName}`,
|
|
203
|
+
value
|
|
204
|
+
);
|
|
201
205
|
}
|
|
202
206
|
};
|
|
203
207
|
|
|
204
208
|
useEffect(() => {
|
|
205
|
-
if (Object.keys(properties).length !== 0) {
|
|
209
|
+
if (Object.keys(properties).length !== 0 && baseStylingWrapper.current) {
|
|
206
210
|
const mergedState = { ...defaultProperties, ...properties };
|
|
207
211
|
setCSSProperties(mergedState);
|
|
208
|
-
} else {
|
|
212
|
+
} else if (baseStylingWrapper.current) {
|
|
209
213
|
setCSSProperties(defaultProperties);
|
|
210
214
|
}
|
|
211
215
|
setIsLoading(false);
|
|
212
|
-
}, [properties]);
|
|
216
|
+
}, [properties, baseStylingWrapper.current]);
|
|
213
217
|
|
|
214
|
-
return
|
|
218
|
+
return (
|
|
219
|
+
<div className="basestyling-wrapper" ref={baseStylingWrapper}>
|
|
220
|
+
{!isLoading ? children : null}
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
215
223
|
};
|
|
@@ -101,7 +101,7 @@ describe("it should perform upload", () => {
|
|
|
101
101
|
|
|
102
102
|
it("should contain a file with status of error", async () => {
|
|
103
103
|
const response = { code: 404, body: { message: "Error test" } };
|
|
104
|
-
const mock = setupXhrEnvironment([404, DONE, response]);
|
|
104
|
+
const mock = setupXhrEnvironment([404, DONE, JSON.stringify(response)]);
|
|
105
105
|
const files3 = [
|
|
106
106
|
{
|
|
107
107
|
name: "test3.txt",
|
|
@@ -115,7 +115,7 @@ describe("it should perform upload", () => {
|
|
|
115
115
|
|
|
116
116
|
it("should contain a file with status of server error", async () => {
|
|
117
117
|
const response = { code: 500, body: { message: "Error test" } };
|
|
118
|
-
const mock = setupXhrEnvironment([500, DONE, response]);
|
|
118
|
+
const mock = setupXhrEnvironment([500, DONE, JSON.stringify(response)]);
|
|
119
119
|
const files6 = [
|
|
120
120
|
{
|
|
121
121
|
name: "test6.txt",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { FileType } from "../Form/FileUpload/FileUpload";
|
|
18
18
|
import { useEffect, useState } from "react";
|
|
19
|
-
import { getValueByPath } from "../util/helper";
|
|
19
|
+
import { getValueByPath, isJsonString } from "../util/helper";
|
|
20
20
|
|
|
21
21
|
export interface UploadResponseType {
|
|
22
22
|
fileList: FileType[];
|
|
@@ -76,6 +76,7 @@ export const useUploadFile = (
|
|
|
76
76
|
) => {
|
|
77
77
|
let fileStatus: FileType["status"] = undefined;
|
|
78
78
|
let error = "";
|
|
79
|
+
const response = responseText && isJsonString(responseText) && JSON.parse(responseText);
|
|
79
80
|
if (requestStatus >= 200 && requestStatus < 400) {
|
|
80
81
|
fileStatus = "completed";
|
|
81
82
|
} else if (requestStatus === 0) {
|
|
@@ -83,13 +84,15 @@ export const useUploadFile = (
|
|
|
83
84
|
error =
|
|
84
85
|
networkErrorText || "Network error. Check internet connection and retry uploading the file";
|
|
85
86
|
} else if (requestStatus >= 400 && requestStatus < 500) {
|
|
86
|
-
const response = responseText && JSON.parse(JSON.stringify(responseText));
|
|
87
87
|
fileStatus = "error";
|
|
88
|
-
error =
|
|
88
|
+
error =
|
|
89
|
+
responseErrorPath && response ? getValueByPath(response, responseErrorPath) : "Bad request";
|
|
89
90
|
} else if (requestStatus >= 500) {
|
|
90
|
-
const response = responseText && JSON.parse(JSON.stringify(responseText));
|
|
91
91
|
fileStatus = "error";
|
|
92
|
-
error =
|
|
92
|
+
error =
|
|
93
|
+
responseErrorPath && response
|
|
94
|
+
? getValueByPath(response, responseErrorPath)
|
|
95
|
+
: "Server Error";
|
|
93
96
|
}
|
|
94
97
|
return { fileStatus, error };
|
|
95
98
|
};
|
package/src/util/helper.test.tsx
CHANGED
|
@@ -24,7 +24,8 @@ import {
|
|
|
24
24
|
throttle,
|
|
25
25
|
areArraysDifferent,
|
|
26
26
|
getValueByPath,
|
|
27
|
-
isEqual
|
|
27
|
+
isEqual,
|
|
28
|
+
isJsonString
|
|
28
29
|
} from "./helper";
|
|
29
30
|
import { render } from "@testing-library/react";
|
|
30
31
|
|
|
@@ -337,3 +338,17 @@ describe("pixel to rem function works", () => {
|
|
|
337
338
|
expect(result).toBe(px);
|
|
338
339
|
});
|
|
339
340
|
});
|
|
341
|
+
|
|
342
|
+
describe("isJsonString should work", () => {
|
|
343
|
+
it("should return true when parameter is a valid JSON string", () => {
|
|
344
|
+
const param = JSON.stringify({ test: 1 });
|
|
345
|
+
|
|
346
|
+
expect(isJsonString(param)).toEqual(true);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it("should return false when parameter is a valid JSON string", () => {
|
|
350
|
+
const param = { test: 2 };
|
|
351
|
+
|
|
352
|
+
expect(isJsonString(param)).toEqual(false);
|
|
353
|
+
});
|
|
354
|
+
});
|
package/src/util/helper.tsx
CHANGED
|
@@ -181,3 +181,12 @@ export const getValueByPath = (obj: { [key: string]: any }, path: string): any =
|
|
|
181
181
|
export const remToPx = (rem: number): number => {
|
|
182
182
|
return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
183
183
|
};
|
|
184
|
+
|
|
185
|
+
export const isJsonString = (str: any) => {
|
|
186
|
+
try {
|
|
187
|
+
JSON.parse(str);
|
|
188
|
+
} catch (e) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
return true;
|
|
192
|
+
};
|