Skip to content

Commit

Permalink
Dataset and Document Upload UI changes (#774)
Browse files Browse the repository at this point in the history
* updated UI
- added file sizes
- changed warning `btn` to primary
- updated message

* Added size exceeded error for datasets
This PR adds a consistent error handling for documents and dataset
  • Loading branch information
DavidQuartz authored Feb 1, 2022
1 parent b5e2161 commit d1b2496
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 16 deletions.
22 changes: 21 additions & 1 deletion geonode_mapstore_client/client/js/routes/UploadDataset.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
getProcessedUploadsByImportId,
uploadDataset
} from '@js/api/geonode/v2';
import uuidv1 from 'uuid/v1';
import axios from '@mapstore/framework/libs/ajax';
import UploadListContainer from '@js/routes/upload/UploadListContainer';
import UploadContainer from '@js/routes/upload/UploadContainer';
Expand Down Expand Up @@ -195,6 +196,18 @@ function UploadList({
}))
.then((responses) => {
const successfulUploads = responses.filter(({ status }) => status === 'success');
const failedUploads = responses.filter(({ status }) => status === 'error');
if (failedUploads.length > 0) {
const failed = failedUploads.map(({ baseName: name, error }) => ({
id: uuidv1(),
name,
progress: 100,
state: 'INVALID',
create_date: Date.now(),
error
}));
onSuccess(failed);
}
if (successfulUploads.length > 0) {
const successfulUploadsIds = successfulUploads.map(({ data }) => data?.id);
const successfulUploadsNames = successfulUploads.map(({ baseName }) => baseName);
Expand Down Expand Up @@ -242,6 +255,8 @@ function ProcessingUploadList({

const [loading, setLoading] = useState(false);
const [filterText, setFilterText] = useState('');
const [deletedIds, setDeletedIds] = useState([]);

const isMounted = useRef(true);
const updatePending = useRef();
updatePending.current = () => {
Expand All @@ -250,15 +265,17 @@ function ProcessingUploadList({
getPendingUploads()
.then((newPendingUploads) => {
if (isMounted.current) {
const failedPendingUploads = pendingUploads.filter(({ state }) => state === 'INVALID');
const newIds = newPendingUploads.map(({ id }) => id);
const missingIds = pendingUploads
.filter(upload => upload.state !== 'PROCESSED' && !newIds.includes(upload.id))
.filter(upload => (upload.state !== 'PROCESSED' && upload.state !== 'INVALID') && !newIds.includes(upload.id) && !deletedIds.includes(upload.id))
.map(({ id }) => id);
const currentProcessed = pendingUploads.filter((upload) => upload.state === 'PROCESSED');
if (missingIds.length > 0) {
getProcessedUploadsById(missingIds)
.then((processed) => {
onChange([
...failedPendingUploads,
...processed,
...currentProcessed,
...newPendingUploads
Expand All @@ -267,13 +284,15 @@ function ProcessingUploadList({
})
.catch(() => {
onChange([
...failedPendingUploads,
...currentProcessed,
...newPendingUploads
]);
setLoading(false);
});
} else {
onChange([
...failedPendingUploads,
...currentProcessed,
...newPendingUploads
]);
Expand All @@ -293,6 +312,7 @@ function ProcessingUploadList({
axios.get(deleteUrl)
.then(() => {
if (isMounted.current) {
setDeletedIds((ids) => [...ids, id]);
onChange(pendingUploads.filter(upload => upload.id !== id));
}
});
Expand Down
9 changes: 7 additions & 2 deletions geonode_mapstore_client/client/js/routes/UploadDocument.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function UploadList({
const [loading, setLoading] = useState(false);
const [uploadContainerProgress, setUploadContainerProgress] = useState({});


function updateWaitingUploads(uploadFiles) {
setWaitingUploads(uploadFiles);
}
Expand Down Expand Up @@ -80,6 +79,11 @@ function UploadList({
setUploadContainerProgress((prevFiles) => ({ ...prevFiles, [fileName]: percentCompleted }));
};

const removeFile = (waiting, name) => {
const uploadFiles = omit(waiting, name);
updateWaitingUploads(uploadFiles);
};

function handleUploadProcess() {
if (!loading) {
setLoading(true);
Expand Down Expand Up @@ -127,7 +131,7 @@ function UploadList({
waitingUploads={waitingUploads}
onDrop={handleDrop}
supportedLabels={getAllowedDocumentTypes().map((ext) => `.${ext}`).join(', ')}
onRemove={(baseName) => updateWaitingUploads(omit(waitingUploads, baseName))}
onRemove={(baseName) => removeFile(waitingUploads, baseName)}
unsupported={unsupported}
disabledUpload={Object.keys(waitingUploads).length === 0}
onUpload={handleUploadProcess}
Expand All @@ -154,6 +158,7 @@ function ProcessingUploadList({
noFilterMatchMsgId="gnviewer.filterNoMatchUploadDocument"
titleMsgId="gnviewer.uploadDocument"
descriptionMsgId="gnviewer.dragAndDropFile"
resourceType="document"
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ function PendingUploadCard({
onRemove,
filesExt,
loading,
progress
progress,
size
}) {
return (
<div className="gn-upload-card">
Expand Down Expand Up @@ -49,7 +50,13 @@ function PendingUploadCard({
);
})}
</ul>
{loading && progress && <div className="gn-upload-card-progress-read">{progress?.[baseName] ? `${progress?.[baseName]}%` : <Spinner />}</div>}
{
(loading && progress) ?
<div className="gn-upload-card-progress-read">
{progress?.[baseName] ? `${progress?.[baseName]}%` : <Spinner />}
</div> :
<div>{size}{' '}MB</div>
}
</div>
{loading && progress && <div style={{position: 'relative'}}>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ function UploadCard({
onRemove,
error
}) {

const exceedingSizeError = (err) => {
let message = err?.message?.match('File size') || '';
let message = err?.message?.match('File size') || err?.errors?.[0]?.match('smaller files') || '';
let fileExceeds = false;
if (message) {
fileExceeds = true;
Expand Down Expand Up @@ -73,7 +74,7 @@ function UploadCard({
<div className="gn-upload-card-tools">
{resumeUrl
? <Button
variant="warning"
variant="primary"
href={resumeUrl}
>
<Message msgId="gnviewer.completeUpload" />
Expand All @@ -90,7 +91,7 @@ function UploadCard({
</Button>
: null}
{state === 'INVALID'
? exceedingSizeError(error) ? <ErrorMessageWithTooltip tooltipId="gnviewer.fileExceeds" /> : <ErrorMessageWithTooltip tooltipId="gnviewer.invalidUploadMessageErrorTooltip" />
? exceedingSizeError(error) ? <ErrorMessageWithTooltip tooltip={error?.message || error?.errors?.[0]} /> : <ErrorMessageWithTooltip tooltipId="gnviewer.invalidUploadMessageErrorTooltip" />
: null}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ function UploadContainer({

const inputFile = useRef();
const waitingUploadNames = Object.keys(waitingUploads);

const handleFileDrop = (event) => {
const files = [...event?.target?.files];
return onDrop(files);
};

const getSize = (filesObj, extensions) => {
let bytes = 0;
extensions.forEach(ext => {
bytes += filesObj[ext].size;
});

return Math.ceil(bytes / (1024 * 1024));
};

return (
<Dropzone
multiple
Expand All @@ -43,17 +58,18 @@ function UploadContainer({
leftColumn={
<div className="gn-upload-list">
<div className="gn-upload-list-header">
<input ref={inputFile} value="" type="file" multiple onChange={(event) => onDrop([...event?.target?.files])} style={{ display: 'none' }}/>
<input ref={inputFile} value="" type="file" multiple onChange={handleFileDrop} style={{ display: 'none' }}/>
<Button onClick={() => inputFile?.current?.click()}>
<FaIcon name="plus"/>{' '}<Message msgId="gnviewer.selectFiles"/>
</Button>
</div>
{waitingUploadNames.length > 0 ? (
<ul style={{overflowX: 'hidden'}}>
<ul>
{waitingUploadNames.map((baseName) => {
const { files, missingExt = [] } = waitingUploads[baseName];
const filesExt = Object.keys(files);
return (
const size = getSize(files, filesExt);
; return (
<li
key={baseName}
>
Expand All @@ -64,6 +80,7 @@ function UploadContainer({
filesExt={filesExt}
loading={loading}
progress={progress}
size={size}
/>
</li>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ function UploadListContainer({
placeholderMsgId,
noFilterMatchMsgId,
titleMsgId,
descriptionMsgId
descriptionMsgId,
resourceType
}) {

const filteredPendingUploads = pendingUploads.filter(({ name }) => !filterText || name.includes(filterText));
Expand All @@ -39,7 +40,7 @@ function UploadListContainer({
<div className="gn-main-event-content">
<div className="gn-main-event-text">
<div className="gn-main-icon">
<FaIcon name="database"/>
{resourceType !== 'dataset' ? <FaIcon name="file"/> : <FaIcon name="database"/>}
</div>
<h1><Message msgId={titleMsgId}/></h1>
<div><Message msgId={descriptionMsgId}/></div>
Expand Down Expand Up @@ -108,4 +109,8 @@ function UploadListContainer({
);
}

UploadListContainer.defaultProps = {
resourceType: 'dataset'
};

export default UploadListContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
"missingFiles": "Fehlende Dateien",
"invalidUploadMessageError": "Fehler",
"invalidUploadMessageErrorTooltip": "Der Upload-Vorgang ist fehlgeschlagen. Bitte überprüfen Sie die Gültigkeit der Datei und versuchen Sie erneut, sie hochzuladen",
"completeUpload": "Hochladen abschließen",
"completeUpload": "Schließen Sie den Upload ab",
"selectFiles": "Dateien auswählen...",
"supportedFiles": "Unterstützte Dateierweiterungen",
"unsupportedFiles": "Für den Upload nicht unterstützte Dateien",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
"missingFiles": "Missing files",
"invalidUploadMessageError": "Error",
"invalidUploadMessageErrorTooltip": "The upload process failed. Please check the validity of the file and try to upload it again",
"completeUpload": "Complete upload",
"completeUpload": "Complete the upload",
"selectFiles": "Select files...",
"supportedFiles": "Supported file extensions",
"unsupportedFiles": "Files not supported for the upload",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@
"missingFiles": "Archivos perdidos",
"invalidUploadMessageError": "Error",
"invalidUploadMessageErrorTooltip": "El proceso de carga falló. Verifique la validez del archivo e intente cargarlo nuevamente",
"completeUpload": "Carga completa",
"completeUpload": "Completa la carga",
"selectFiles": "Seleccionar archivos...",
"supportedFiles": "Extensiones de archivo admitidas",
"unsupportedFiles": "Archivos no admitidos para la carga",
Expand Down

0 comments on commit d1b2496

Please sign in to comment.