diff --git a/package.json b/package.json index 635371a2..47e59d15 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@types/react-sortable-hoc": "^0.6.5", "@types/react-virtualized": "^9.21.4", "array-move": "^2.1.0", + "attr-accept": "^1.1.3", "date-fns": "^2.0.0-beta.5", "firebase": "^6.6.0", "formik": "^1.5.8", diff --git a/src/components/Fields/Image.tsx b/src/components/Fields/Image.tsx new file mode 100644 index 00000000..cd9cec25 --- /dev/null +++ b/src/components/Fields/Image.tsx @@ -0,0 +1,40 @@ +import React, { useCallback, useState } from "react"; +import { useDropzone } from "react-dropzone"; +import useUploader from "../../hooks/useFiretable/useUploader"; +const Image = (props: any) => { + const { columnData, cellData, cellActions, rowData, rowIndex } = props; + const [uploaderState, upload] = useUploader(); + const [localImage, setLocalImage] = useState(null); + const onDrop = useCallback(acceptedFiles => { + // Do something with the files + const imageFile = acceptedFiles[0]; + if (imageFile) { + upload(rowData.ref, columnData.fieldName, imageFile); + let url = URL.createObjectURL(imageFile); + setLocalImage(url); + } + }, []); + + const { getRootProps, getInputProps, isDragActive } = useDropzone({ + onDrop, + multiple: false, + accept: ["image/png", "image/jpg", "image/jpeg"] + }); + return ( +
+ + {localImage ? ( +
+ +
+ ) : cellData ? ( + + ) : isDragActive ? ( +

Drop the files here ...

+ ) : ( +

Drag 'n' drop some files here, or click to select files

+ )} +
+ ); +}; +export default Image; diff --git a/src/components/Fields/index.tsx b/src/components/Fields/index.tsx index a5ad34d3..c29e8349 100644 --- a/src/components/Fields/index.tsx +++ b/src/components/Fields/index.tsx @@ -4,6 +4,8 @@ import CheckBoxIcon from "@material-ui/icons/CheckBox"; import SimpleTextIcon from "@material-ui/icons/TextFormat"; import LongTextIcon from "@material-ui/icons/Notes"; import PhoneIcon from "@material-ui/icons/Phone"; +import ImageIcon from "@material-ui/icons/Photo"; +import FileIcon from "@material-ui/icons/InsertDriveFileOutlined"; import DateIcon from "@material-ui/icons/CalendarToday"; import TimeIcon from "@material-ui/icons/AccessTime"; import RatingIcon from "@material-ui/icons/StarHalf"; @@ -21,7 +23,9 @@ export enum FieldType { dateTime = "DATE_TIME", number = "NUMBER", url = "URL", - rating = "RATING" + rating = "RATING", + image = "IMAGE", + file = "FILE" } export const FIELDS = [ @@ -34,7 +38,9 @@ export const FIELDS = [ { icon: , name: "Date", type: FieldType.date }, { icon: , name: "Time", type: FieldType.dateTime }, { icon: , name: "URL", type: FieldType.url }, - { icon: , name: "Rating", type: FieldType.rating } + { icon: , name: "Rating", type: FieldType.rating }, + { icon: , name: "Image", type: FieldType.image }, + { icon: , name: "File", type: FieldType.file } ]; export const getFieldIcon = (type: FieldType) => { diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 98831a1c..157a4258 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -75,7 +75,7 @@ class MuiVirtualizedTable extends React.PureComponent< > { static defaultProps = { headerHeight: 48, - rowHeight: 48 + rowHeight: 200 }; getRowClassName = ({ index }: Row) => { diff --git a/src/components/TableCell.tsx b/src/components/TableCell.tsx index fb510c2e..939f7e6f 100644 --- a/src/components/TableCell.tsx +++ b/src/components/TableCell.tsx @@ -13,6 +13,7 @@ import Number from "./Fields/Number"; import Rating from "./Fields/Rating"; import Date from "./Fields/Date"; import DateTime from "./Fields/DateTime"; +import Image from "./Fields/Image"; const TableCell = (props: any) => { const { @@ -96,6 +97,17 @@ const TableCell = (props: any) => { columnData={columnData} /> ); + case FieldType.image: + return ( + + ); case FieldType.date: return ( { .map(doc => { const data = doc.data(); const id = doc.id; - return { ...data, id }; + const ref = doc.ref; + + return { ...data, id, ref }; }) .filter(doc => doc.id !== "_FIRETABLE_"); //removes schema file tableDispatch({ diff --git a/src/hooks/useFiretable/useUploader.ts b/src/hooks/useFiretable/useUploader.ts index 48e0c83b..47e0ce4c 100644 --- a/src/hooks/useFiretable/useUploader.ts +++ b/src/hooks/useFiretable/useUploader.ts @@ -6,19 +6,17 @@ const intialState = {}; const uploadReducer = (prevState: any, newProps: any) => { return { ...prevState, ...newProps }; }; -const useUploader = (collectionPath: string) => { +const useUploader = () => { const [uploaderState, uploaderDispatch] = useReducer(uploadReducer, { - ...intialState, - collectionPath + ...intialState }); - const setCollectionPath = (path: string) => { - var collectionPath = bucket.ref(path); - uploaderDispatch({ collectionPath }); - }; - const upload = (docId: string, fieldName: string, file: File) => { - const storageRef = uploaderState.storagePath.child( - `${docId}/${fieldName}/${file.name}.${file.type}` - ); + + const upload = ( + docRef: firebase.firestore.DocumentReference, + fieldName: string, + file: File + ) => { + const storageRef = bucket.ref(`${docRef.path}/${fieldName}/${file.name}`); var uploadTask = storageRef.put(file); uploadTask.on( firebase.storage.TaskEvent.STATE_CHANGED, // or 'state_changed' @@ -35,7 +33,7 @@ const useUploader = (collectionPath: string) => { break; } }, - function(error: FirebaseError) { + function(error: any) { // A full list of error codes is available at // https://firebase.google.com/docs/storage/web/handle-errors switch (error.code) { @@ -57,12 +55,13 @@ const useUploader = (collectionPath: string) => { .getDownloadURL() .then(function(downloadURL: string) { console.log("File available at", downloadURL); + docRef.update({ [fieldName]: downloadURL }); }); } ); }; - const uploadActions = { upload, setCollectionPath }; - return [uploaderState, uploadActions]; + + return [uploaderState, upload]; }; export default useUploader;