Skip to content

Commit 62b3495

Browse files
author
Jovert Lota Palonpon
committed
wip - Dropzone Component #23
1 parent 32fb16d commit 62b3495

File tree

2 files changed

+115
-34
lines changed

2 files changed

+115
-34
lines changed

resources/js/ui/Dropzone.js

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ function Dropzone(props) {
107107
maxFiles,
108108
maxFileSize,
109109
handleUpload,
110+
handleFileRemoved,
110111
} = props;
111112

112113
const [files, setFiles] = useState([]);
@@ -134,6 +135,100 @@ function Dropzone(props) {
134135
return errors[0];
135136
};
136137

138+
const removeFile = removedFile => {
139+
if (removedFile.status === 'uploading') {
140+
const confirmed = confirm('The file is being uploaded, stop it?');
141+
142+
if (!confirmed) {
143+
return;
144+
}
145+
}
146+
147+
if (removedFile.status === 'uploaded') {
148+
handleFileRemoved(() => {
149+
setFiles(files.filter(file => file.url !== removedFile.url));
150+
});
151+
152+
return;
153+
}
154+
155+
setFiles(files.filter(file => file.url !== removedFile.url));
156+
};
157+
158+
useEffect(
159+
() => () =>
160+
files.forEach(file => {
161+
// Make sure to revoke the data uris to avoid memory leaks.
162+
URL.revokeObjectURL(file.preview);
163+
}),
164+
[files],
165+
);
166+
167+
/**
168+
* Handle the queueing of files here.
169+
*/
170+
useEffect(() => {
171+
// If nothing is in the queue, stop.
172+
if (files.findIndex(file => file.status === 'queued') < 0) {
173+
return;
174+
}
175+
176+
// Stop if there is a file being uploaded.
177+
if (files.findIndex(file => file.status === 'uploading') > -1) {
178+
return;
179+
}
180+
181+
// Queue out a file if the one being uploaded is removed / has finished.
182+
setFiles(
183+
files
184+
// Set aside the uploaded files
185+
.filter(file => file.status === 'uploaded')
186+
.concat(
187+
files
188+
// Only the queued files should be a candidate for uploading.
189+
.filter(file => file.status === 'queued')
190+
.map((file, key) => {
191+
// Upload the first in the queue
192+
if (key === 0) {
193+
return Object.assign(file, {
194+
status: 'uploading',
195+
message: '',
196+
});
197+
}
198+
199+
return file;
200+
}),
201+
)
202+
// Append the rejected files at the end.
203+
.concat(files.filter(file => file.status === 'rejected')),
204+
);
205+
}, [files]);
206+
207+
/**
208+
* Handle the file being uploaded here.
209+
*/
210+
useEffect(() => {
211+
// Stop if there are nothing to be uploaded.
212+
if (files.findIndex(file => file.status === 'uploading') < 0) {
213+
return;
214+
}
215+
216+
handleUpload(files.find(file => file.status === 'uploading'), () => {
217+
setFiles(
218+
files.map(file => {
219+
if (file.status === 'uploading') {
220+
return Object.assign(file, {
221+
status: 'uploaded',
222+
message: '',
223+
});
224+
}
225+
226+
return file;
227+
}),
228+
);
229+
});
230+
}, [files]);
231+
137232
const { getRootProps, getInputProps, open, isDragActive } = useDropzone({
138233
accept: acceptedFileTypes.join(','),
139234
maxSize: maxFileSize * 1000 * 1000,
@@ -158,10 +253,12 @@ function Dropzone(props) {
158253

159254
setFiles(
160255
files.concat(acceptedFiles, rejectedFiles).map((file, key) => {
256+
// Set the first one as uploading.
161257
if (key === 0 && file.status === 'queued') {
162-
file.status = 'uploading';
163-
164-
return file;
258+
return Object.assign(file, {
259+
status: 'uploading',
260+
message: '',
261+
});
165262
}
166263

167264
return file;
@@ -174,18 +271,6 @@ function Dropzone(props) {
174271

175272
const { ref, ...rootProps } = getRootProps();
176273

177-
useEffect(
178-
() => () => {
179-
files.forEach(file => {
180-
// Make sure to revoke the data uris to avoid memory leaks.
181-
URL.revokeObjectURL(file.preview);
182-
});
183-
184-
// If there aren't any one being uploaded, pick one from the queue.
185-
},
186-
[files],
187-
);
188-
189274
return (
190275
<RootRef rootRef={ref}>
191276
<Grid
@@ -278,25 +363,11 @@ function Dropzone(props) {
278363
<Typography
279364
color="primary"
280365
className={classes.removeLink}
281-
onClick={() => {
282-
if (file.status === 'uploading') {
283-
const confirmed = confirm(
284-
'The file is being uploaded, stop it?',
285-
);
286-
287-
if (!confirmed) {
288-
return;
289-
}
290-
}
291-
292-
setFiles(
293-
files.filter(
294-
(file, i) => i !== key,
295-
),
296-
);
297-
}}
366+
onClick={() => removeFile(file)}
298367
>
299-
Remove File
368+
{file.status === 'uploading'
369+
? 'Cancel'
370+
: 'Remove File'}
300371
</Typography>
301372
</Grid>
302373
))
@@ -360,6 +431,7 @@ Dropzone.propTypes = {
360431
maxFiles: PropTypes.number,
361432
maxFileSize: PropTypes.number,
362433
handleUpload: PropTypes.func.isRequired,
434+
handleFileRemoved: PropTypes.func.isRequired,
363435
};
364436

365437
Dropzone.defaultProps = {

resources/js/views/__backoffice/users/Forms/Avatar.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,16 @@ const Avatar = props => {
1717
<Dropzone
1818
maxFiles={2}
1919
maxFileSize={2}
20-
handleUpload={file => console.log(file)}
20+
handleUpload={(file, done) => {
21+
setTimeout(() => {
22+
done();
23+
}, Math.floor(Math.random() * Math.floor(15)) * 1000);
24+
}}
25+
handleFileRemoved={removed => {
26+
setTimeout(() => {
27+
removed();
28+
}, Math.floor(Math.random() * Math.floor(10)) * 1000);
29+
}}
2130
/>
2231

2332
<div className={classes.sectionSpacer} />

0 commit comments

Comments
 (0)