saleor-dashboard/src/components/FileUploadField/FileUploadField.tsx
Dawid Tarasiuk 1e140853ec
File attributes (#884)
* Update changelog with file attributes

* Add file type attribute

* Update attribute properties form

* Update translation messages with file upload

* Create generic attributes component (#832)

* Create generic Attributes component

* Add story for Attributes component

* Remove deprecated attribute value type field from queries

* Update test snapshots of attributes component

* Add file upload field to atributes (#888)

* Add story for Attributes component

* Update test snapshots of attributes component

* Create file upload field in attributes

* Update upload file input data-test

* Update storybook test snapshots of attributes

* Add dedicated input props to file field

* Run Cypress using custom API

* Add missing error handling in file upload field

Co-authored-by: Krzysztof Wolski <krzysztof.k.wolski@gmail.com>

* Add file attribute upload to page attributes (#894)

* Support upload file attribute for pages

* Update after review

* Add file attribute upload to variant attributes (#892)

* Support upload file attribute for variants

* Update after review

* Refactor attribute values errors merging

* Update after review

* Add file attribute upload to product attributes (#826)

* Support upload file attribute for products

* Update after review

* Refactor attribute values errors merging

* Refactor product attribute value delete handling

* Fix deleting file in file upload field

* Fix delete attribute values errors handling

* Add link to file upload field (#898)

* Update file attributes updates (#899)

* Update file attributes updates

* Refactor file uploads handling

* Move attributes utils to attributes directory

* Fix product channel listing updates

* Clear file field value if file is not passed as prop

* Delete attribute values before update (#908)

* Delete file attributes after file update

* Triggr CI

* Show skeleton in file upload field during loading

Co-authored-by: Krzysztof Wolski <krzysztof.k.wolski@gmail.com>
2020-12-16 11:53:28 +01:00

147 lines
3.6 KiB
TypeScript

import { makeStyles } from "@material-ui/core";
import Button from "@material-ui/core/Button";
import IconButton from "@material-ui/core/IconButton";
import Typography from "@material-ui/core/Typography";
import DeleteIcon from "@material-ui/icons/Delete";
import { FileFragment } from "@saleor/fragments/types/FileFragment";
import { commonMessages } from "@saleor/intl";
import React from "react";
import { useIntl } from "react-intl";
import Skeleton from "../Skeleton";
export interface FileChoiceType {
label: string;
value: string;
file?: FileFragment;
}
export interface FileUploadFieldProps {
inputProps?: React.DetailedHTMLProps<
React.InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
>;
className?: string;
disabled: boolean;
loading: boolean;
file: FileChoiceType;
error?: boolean;
helperText?: string;
onFileUpload: (file: File) => void;
onFileDelete: () => void;
}
const useStyles = makeStyles(
theme => ({
errorText: {
color: theme.palette.error.light
},
fileField: {
display: "none"
},
fileUrl: {
color: theme.palette.primary.main,
textDecoration: "none"
},
uploadFileContent: {
alignItems: "center",
color: theme.palette.primary.main,
display: "flex",
fontSize: "1rem"
},
uploadFileName: {
minWidth: "6rem"
}
}),
{ name: "FileUploadField" }
);
const FileUploadField: React.FC<FileUploadFieldProps> = props => {
const {
loading,
disabled,
file,
className,
error,
helperText,
onFileUpload,
onFileDelete,
inputProps
} = props;
const classes = useStyles({});
const intl = useIntl();
const fileInputAnchor = React.createRef<HTMLInputElement>();
const clickFileInput = () => fileInputAnchor.current.click();
const handleFileDelete = () => {
fileInputAnchor.current.value = "";
onFileDelete();
};
React.useEffect(() => {
if (!file.value) {
fileInputAnchor.current.value = "";
}
}, [file]);
return (
<>
<div className={className}>
{file.label ? (
<div className={classes.uploadFileContent}>
<div className={classes.uploadFileName}>
{loading ? (
<Skeleton />
) : (
<a
href={file.file?.url}
target="blank"
className={classes.fileUrl}
>
{file.label}
</a>
)}
</div>
<IconButton
color="primary"
onClick={handleFileDelete}
disabled={disabled || loading}
data-test="button-delete-file"
>
<DeleteIcon />
</IconButton>
</div>
) : (
<div>
<Button
onClick={clickFileInput}
disabled={disabled || loading}
variant="outlined"
color="primary"
data-test="button-upload-file"
>
{intl.formatMessage(commonMessages.chooseFile)}
</Button>
</div>
)}
{error && (
<Typography variant="caption" className={classes.errorText}>
{helperText}
</Typography>
)}
</div>
<input
className={classes.fileField}
id="fileUpload"
onChange={event => onFileUpload(event.target.files[0])}
type="file"
data-test="upload-file-input"
ref={fileInputAnchor}
{...inputProps}
/>
</>
);
};
FileUploadField.displayName = "FileUploadField";
export default FileUploadField;