Files
rowy/src/components/fields/File/EditorCell.tsx

174 lines
4.9 KiB
TypeScript
Raw Normal View History

2022-05-24 16:17:09 +10:00
import { useCallback } from "react";
2022-11-11 15:49:47 +11:00
import { IEditorCellProps } from "@src/components/fields/types";
2022-05-24 16:17:09 +10:00
import { useSetAtom } from "jotai";
import { findIndex } from "lodash-es";
import { useDropzone } from "react-dropzone";
import { format } from "date-fns";
import { alpha, Stack, Grid, Tooltip, Chip, IconButton } from "@mui/material";
import { Upload as UploadIcon } from "@src/assets/icons";
2022-05-24 16:17:09 +10:00
import ChipList from "@src/components/Table/formatters/ChipList";
import CircularProgressOptical from "@src/components/CircularProgressOptical";
2022-07-18 14:40:46 +10:00
import { projectScope, confirmDialogAtom } from "@src/atoms/projectScope";
2022-05-24 16:17:09 +10:00
import { tableScope, updateFieldAtom } from "@src/atoms/tableScope";
2022-05-31 16:12:16 +10:00
import useUploader from "@src/hooks/useFirebaseStorageUploader";
2022-05-24 16:17:09 +10:00
import { FileIcon } from ".";
import { DATE_TIME_FORMAT } from "@src/constants/dates";
2022-05-31 16:12:16 +10:00
import { FileValue } from "@src/types/table";
2022-05-24 16:17:09 +10:00
export default function File_({
column,
value,
2022-11-11 15:49:47 +11:00
onChange,
2022-05-24 16:17:09 +10:00
onSubmit,
disabled,
2022-11-11 15:49:47 +11:00
_rowy_ref,
tabIndex,
}: IEditorCellProps) {
2022-07-18 14:40:46 +10:00
const confirm = useSetAtom(confirmDialogAtom, projectScope);
2022-05-24 16:17:09 +10:00
const updateField = useSetAtom(updateFieldAtom, tableScope);
const { uploaderState, upload, deleteUpload } = useUploader();
const { progress, isLoading } = uploaderState;
const onDrop = useCallback(
(acceptedFiles: File[]) => {
const file = acceptedFiles[0];
if (file) {
upload({
2022-11-11 15:49:47 +11:00
docRef: _rowy_ref,
2022-05-24 16:17:09 +10:00
fieldName: column.key,
files: [file],
previousValue: value,
onComplete: (newValue) => {
updateField({
2022-11-11 15:49:47 +11:00
path: _rowy_ref.path,
2022-05-24 16:17:09 +10:00
fieldName: column.key,
value: newValue,
});
},
});
}
},
[value]
);
const handleDelete = (ref: string) => {
const newValue = [...value];
const index = findIndex(newValue, ["ref", ref]);
const toBeDeleted = newValue.splice(index, 1);
toBeDeleted.length && deleteUpload(toBeDeleted[0]);
2022-11-11 15:49:47 +11:00
onChange(newValue);
onSubmit();
2022-05-24 16:17:09 +10:00
};
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
multiple: false,
});
const dropzoneProps = getRootProps();
return (
<Stack
direction="row"
alignItems="center"
sx={{
2022-11-11 15:49:47 +11:00
width: "100%",
2022-05-24 16:17:09 +10:00
height: "100%",
...(isDragActive
? {
backgroundColor: (theme) =>
alpha(
theme.palette.primary.main,
theme.palette.action.hoverOpacity * 2
),
"& .row-hover-iconButton": { color: "primary.main" },
}
: {}),
}}
{...dropzoneProps}
2022-11-11 15:49:47 +11:00
tabIndex={tabIndex}
2022-05-24 16:17:09 +10:00
onClick={undefined}
>
<ChipList>
{Array.isArray(value) &&
value.map((file: FileValue) => (
<Grid
item
key={file.downloadURL}
style={
// Truncate so multiple files still visible
value.length > 1 ? { maxWidth: `calc(100% - 12px)` } : {}
}
>
<Tooltip
title={`File last modified ${format(
file.lastModifiedTS,
DATE_TIME_FORMAT
)}`}
>
<Chip
icon={<FileIcon />}
label={file.name}
onClick={(e) => {
window.open(file.downloadURL);
e.stopPropagation();
}}
onDelete={
disabled
? undefined
: () =>
confirm({
handleConfirm: () => handleDelete(file.ref),
title: "Delete file?",
body: "This file cannot be recovered after",
confirm: "Delete",
confirmColor: "error",
})
}
2022-11-11 15:49:47 +11:00
tabIndex={tabIndex}
2022-05-24 16:17:09 +10:00
style={{ width: "100%" }}
/>
</Tooltip>
</Grid>
))}
</ChipList>
{!isLoading ? (
!disabled && (
<IconButton
size="small"
onClick={(e) => {
dropzoneProps.onClick!(e);
e.stopPropagation();
}}
style={{ display: "flex" }}
2022-11-11 15:49:47 +11:00
className={_rowy_ref && "row-hover-iconButton end"}
disabled={!_rowy_ref}
tabIndex={tabIndex}
2022-05-24 16:17:09 +10:00
>
<UploadIcon />
</IconButton>
)
) : (
<div style={{ padding: 4 }}>
<CircularProgressOptical
size={24}
variant={progress === 0 ? "indeterminate" : "determinate"}
value={progress}
style={{ display: "block" }}
/>
</div>
)}
2022-11-11 15:49:47 +11:00
<input {...getInputProps()} tabIndex={tabIndex} />
2022-05-24 16:17:09 +10:00
</Stack>
);
}