mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
File upload error handling (#52006)
This commit is contained in:
parent
7e9194e6e2
commit
5ad2767954
@ -1,11 +1,12 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { uniqueId, isString } from 'lodash';
|
import { isString, uniqueId } from 'lodash';
|
||||||
import React, { ReactNode, useCallback, useState } from 'react';
|
import React, { ReactNode, useCallback, useState } from 'react';
|
||||||
import { DropEvent, DropzoneOptions, FileRejection, useDropzone, Accept } from 'react-dropzone';
|
import { Accept, DropEvent, DropzoneOptions, FileRejection, useDropzone } from 'react-dropzone';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { useTheme2 } from '../../themes';
|
import { useTheme2 } from '../../themes';
|
||||||
|
import { Alert } from '../Alert/Alert';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
|
|
||||||
import { FileListItem } from './FileListItem';
|
import { FileListItem } from './FileListItem';
|
||||||
@ -58,6 +59,7 @@ export interface DropzoneFile {
|
|||||||
|
|
||||||
export function FileDropzone({ options, children, readAs, onLoad, fileListRenderer, onFileRemove }: FileDropzoneProps) {
|
export function FileDropzone({ options, children, readAs, onLoad, fileListRenderer, onFileRemove }: FileDropzoneProps) {
|
||||||
const [files, setFiles] = useState<DropzoneFile[]>([]);
|
const [files, setFiles] = useState<DropzoneFile[]>([]);
|
||||||
|
const [errorMessages, setErrorMessages] = useState<string[]>([]);
|
||||||
|
|
||||||
const setFileProperty = useCallback(
|
const setFileProperty = useCallback(
|
||||||
(customFile: DropzoneFile, action: (customFileToModify: DropzoneFile) => void) => {
|
(customFile: DropzoneFile, action: (customFileToModify: DropzoneFile) => void) => {
|
||||||
@ -83,6 +85,8 @@ export function FileDropzone({ options, children, readAs, onLoad, fileListRender
|
|||||||
setFiles((oldFiles) => [...oldFiles, ...customFiles]);
|
setFiles((oldFiles) => [...oldFiles, ...customFiles]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setErrors(rejectedFiles);
|
||||||
|
|
||||||
if (options?.onDrop) {
|
if (options?.onDrop) {
|
||||||
options.onDrop(acceptedFiles, rejectedFiles, event);
|
options.onDrop(acceptedFiles, rejectedFiles, event);
|
||||||
} else {
|
} else {
|
||||||
@ -161,12 +165,40 @@ export function FileDropzone({ options, children, readAs, onLoad, fileListRender
|
|||||||
return <FileListItem key={file.id} file={file} removeFile={removeFile} />;
|
return <FileListItem key={file.id} file={file} removeFile={removeFile} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const setErrors = (rejectedFiles: FileRejection[]) => {
|
||||||
|
let errors: string[] = [];
|
||||||
|
rejectedFiles.map((rejectedFile) => {
|
||||||
|
rejectedFile.errors.map((error) => {
|
||||||
|
errors.push(error.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setErrorMessages(errors);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getErrorMessages = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.errorAlert}>
|
||||||
|
<Alert title="Upload failed" severity="error" onRemove={clearAlert}>
|
||||||
|
{errorMessages.map((error) => {
|
||||||
|
return <div key={error}>{error}</div>;
|
||||||
|
})}
|
||||||
|
</Alert>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearAlert = () => {
|
||||||
|
setErrorMessages([]);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div data-testid="dropzone" {...getRootProps({ className: styles.dropzone })}>
|
<div data-testid="dropzone" {...getRootProps({ className: styles.dropzone })}>
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
{children ?? <FileDropzoneDefaultChildren primaryText={getPrimaryText(files, options)} />}
|
{children ?? <FileDropzoneDefaultChildren primaryText={getPrimaryText(files, options)} />}
|
||||||
</div>
|
</div>
|
||||||
|
{errorMessages.length > 0 && getErrorMessages()}
|
||||||
{options?.accept && (
|
{options?.accept && (
|
||||||
<small className={cx(styles.small, styles.acceptMargin)}>{getAcceptedFileTypeText(options.accept)}</small>
|
<small className={cx(styles.small, styles.acceptMargin)}>{getAcceptedFileTypeText(options.accept)}</small>
|
||||||
)}
|
)}
|
||||||
@ -276,5 +308,8 @@ function getStyles(theme: GrafanaTheme2, isDragActive?: boolean) {
|
|||||||
small: css`
|
small: css`
|
||||||
color: ${theme.colors.text.secondary};
|
color: ${theme.colors.text.secondary};
|
||||||
`,
|
`,
|
||||||
|
errorAlert: css`
|
||||||
|
padding-top: 10px;
|
||||||
|
`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user