From 8f16f5788da6afc9a240e57f1c28a5b0c07cbd24 Mon Sep 17 00:00:00 2001 From: kylemarch513 Date: Thu, 21 Dec 2023 16:35:34 +0100 Subject: [PATCH] file upload from desktop --- cms/Files/Explorer.tsx | 114 ++++++++++++++++++++++++------------- cms/Files/FileCss.css | 49 ++++++++++++++++ cms/Files/index.tsx | 8 ++- cms/Hooks/useUploadFile.ts | 41 +++++++++++++ 4 files changed, 172 insertions(+), 40 deletions(-) create mode 100644 cms/Files/FileCss.css create mode 100644 cms/Hooks/useUploadFile.ts diff --git a/cms/Files/Explorer.tsx b/cms/Files/Explorer.tsx index b98c351..b7b7af5 100644 --- a/cms/Files/Explorer.tsx +++ b/cms/Files/Explorer.tsx @@ -13,6 +13,9 @@ import { import { useClient, useQuery } from '@based/react' import { useRoute } from 'kabouter' import { Search } from './Search' +import { FileDrop } from 'react-file-drop' +import './FileCss.css' +import { useUploadFile } from '../Hooks/useUploadFile' const FILTER_FIELDS = ['type', 'ancestors', 'descendants', 'aliases'] @@ -44,7 +47,7 @@ const filterFolder = (data, rootId) => { return [...indexed, ...unindexed] } -export const Explorer = ({}) => { +export const Explorer = ({ onChange }) => { const route = useRoute('[folder]') const path = route.query.folder as string @@ -56,6 +59,12 @@ export const Explorer = ({}) => { const dragOverItem = useRef() const containerRef = useRef() + const fileInputRef = useRef(null) + + const onFileInputChange = (event) => { + const { files } = event.target + console.log(files) + } const { data, loading: dataLoading } = useQuery('db', { $id: section, @@ -237,7 +246,7 @@ export const Explorer = ({}) => { }) return ( - + [i, i]))} @@ -257,48 +266,75 @@ export const Explorer = ({}) => { }} /> - - + console.log('onFrameDragEnter', event)} + // onFrameDragLeave={(event) => console.log('onFrameDragLeave', event)} + // onFrameDrop={(event) => { + // console.log('onFrameDrop!', event) + // // setDragging(false) + // }} + // onDragOver={(event) => console.log('onDragOver', event)} + // onDragLeave={(event) => { + // console.log('onDragLeave', event) + // setDragging(false) + // }} + onDrop={(files, event) => { + console.log('dropped') + for (const i in files) { + onChange(files[i]) + } }} > - {data?.files?.length > 0 && - //@ts-ignore - filterFolder(data?.files, section).map((item, i) => { - return ( -
dragStart(e, i)} - style={{ maxHeight: 130 }} - > + setDragging(false)} + ref={containerRef} + style={{ + display: 'flex', + flexWrap: 'wrap', + height: '100%', + gap: 30, + // gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 100px))', + }} + > + {data?.files?.length > 0 && + //@ts-ignore + filterFolder(data?.files, section).map((item, i) => { + return (
dragStart(e, i)} + style={{ maxHeight: 130 }} > - +
+ +
-
- ) - })} -
- + ) + })} +
+ + + setOpenSidebar(false)}> diff --git a/cms/Files/FileCss.css b/cms/Files/FileCss.css new file mode 100644 index 0000000..644d717 --- /dev/null +++ b/cms/Files/FileCss.css @@ -0,0 +1,49 @@ +/* Demo.css */ + +.file-drop { + /* relatively position the container bc the contents are absolute */ + position: relative; + height: 100%; + width: 100%; + display: flex; + flex-wrap: wrap; + gap: 30; +} + +.file-drop > .file-drop-target { + /* basic styles */ + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + border-radius: 2px; + + /* horizontally and vertically center all content */ + display: flex; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + + flex-direction: column; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + + align-items: center; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + + justify-content: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + + align-content: center; + -webkit-align-content: center; + -ms-flex-line-pack: center; + + text-align: center; +} diff --git a/cms/Files/index.tsx b/cms/Files/index.tsx index 14cf119..94b1fc6 100644 --- a/cms/Files/index.tsx +++ b/cms/Files/index.tsx @@ -16,6 +16,7 @@ import { Tile } from './Tile' import { Explorer } from './Explorer' import { CmsTable } from '../Components/CmsTable' import { useRoute } from 'kabouter' +import { useUploadFile } from '../Hooks/useUploadFile' export const FileLibrary = () => { const client = useClient() @@ -29,6 +30,7 @@ export const FileLibrary = () => { const { width, height } = useWindowResize() const [tableWidth, setTableWidth] = useState(600) const [tableHeight, setTableHeight] = useState(600) + const { handleFileInputChange, status, progress } = useUploadFile() useEffect(() => { setTableWidth(width - 324) @@ -126,7 +128,11 @@ export const FileLibrary = () => { // columnNamesInRightOrder={arr} /> ) : ( - + { + console.log('uploaded file', file) + })} + /> )} diff --git a/cms/Hooks/useUploadFile.ts b/cms/Hooks/useUploadFile.ts new file mode 100644 index 0000000..b9260df --- /dev/null +++ b/cms/Hooks/useUploadFile.ts @@ -0,0 +1,41 @@ +import * as React from 'react' +import { useClient } from '@based/react' + +export function useUploadFile() { + const client = useClient() + const [status, setStatus] = React.useState< + 'initial' | 'uploading' | 'success' | 'error' + >('initial') + const [progress, setProgress] = React.useState(0) + + function handleFileInputChange( + successHandler: (uploadedFile: { id: string; src: string } | null) => void + ) { + return async function (file?: File) { + try { + if (!file) { + successHandler(null) + return + } + setStatus('uploading') + + const { id, src } = await client.stream( + 'db:file-upload', + { + contents: file, + }, + (value) => { + setProgress(value * 100) + } + ) + + setStatus('success') + successHandler({ id, src }) + } catch { + setStatus('error') + } + } + } + + return { status, progress, handleFileInputChange } +}