/
FileArray.js
121 lines (115 loc) 路 4.07 KB
/
FileArray.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import React, { useMemo, useCallback, useRef } from "react";
import { useField } from "formik";
import * as MuiFileDropzone from "mui-file-dropzone";
import Fieldset from "./Fieldset.js";
import HelperText from "../inputs/HelperText.js";
import PropTypes from "prop-types";
const { DropzoneArea } = MuiFileDropzone;
export default function FileArray({ name, label, subform, hint, maxRows }) {
const [, { initialValue = [] }, { setValue }] = useField(name),
fileField = subform.find(
(field) => field.type === "file" || field.type === "image"
) || {
name: "file",
type: "file",
},
accept = fileField.type === "image" ? "image/*" : null,
loadedRef = useRef(null);
const initialFiles = useMemo(() => {
if (!initialValue || initialValue.length === 0) {
return [];
}
return initialValue
.filter((row) => {
if (
!row[fileField.name] ||
row[fileField.name] === "__clear__"
) {
return false;
}
return true;
})
.map((row) => {
const value = row[fileField.name];
if (value.type && value.body) {
return value.body;
} else if (typeof value === "string") {
return value;
}
});
}, [initialValue]),
acceptedFiles = useMemo(
() => (accept ? accept.split(",") : null),
[accept]
),
setFiles = useCallback(
(files) => {
if (!loadedRef.current) {
// initialFiles loaded
let fileIndex = 0;
loadedRef.current = initialValue.map((row) => {
let file;
if (
row[fileField.name] &&
row[fileField.name] !== "__clear__"
) {
file = files[fileIndex];
fileIndex++;
}
return { row, file };
});
return;
}
const nextValue = files.map((file, i) => {
const { row, file: initialFile } = loadedRef.current[i] || {
row: {},
file: null,
};
if (initialFile === file) {
return row;
} else {
return {
...row,
[fileField.name]: {
name: file.name,
type: file.type,
body: file,
},
};
}
});
if (initialValue && nextValue.length < initialValue.length) {
initialValue.slice(nextValue.length).forEach((row) => {
nextValue.push({
...row,
[fileField.name]: "__clear__",
});
});
}
setValue(nextValue);
},
[initialValue]
);
return (
<Fieldset label={label}>
<DropzoneArea
initialFiles={initialFiles}
acceptedFiles={acceptedFiles}
onChange={setFiles}
filesLimit={maxRows}
/>
<HelperText name={name} hint={hint} />
</Fieldset>
);
}
FileArray.Fieldset = function EmptyFieldset() {
return null;
};
FileArray.propTypes = {
name: PropTypes.string,
accept: PropTypes.string,
label: PropTypes.string,
subform: PropTypes.arrayOf(PropTypes.object),
hint: PropTypes.string,
maxRows: PropTypes.number,
};