From 026aa7db8d94eb870ba1b0eb1854ee048605e289 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Fri, 10 Sep 2021 17:43:16 +0300 Subject: [PATCH 01/16] add basic folder upload --- packages/files-ui/package.json | 1 + .../Modules/FileBrowsers/CSFFileBrowser.tsx | 22 ++--- .../files-ui/src/Contexts/FilesContext.tsx | 3 +- .../Utils/getFilesFromDataTransferItems.ts | 85 +++++++++++++++++++ packages/files-ui/src/types.d.ts | 1 + yarn.lock | 5 ++ 6 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts create mode 100644 packages/files-ui/src/types.d.ts diff --git a/packages/files-ui/package.json b/packages/files-ui/package.json index 5cbd9a2373..cac910f1ad 100644 --- a/packages/files-ui/package.json +++ b/packages/files-ui/package.json @@ -24,6 +24,7 @@ "babel-preset-react": "^6.24.1", "bnc-onboard": "1.32.0", "clsx": "^1.1.1", + "datatransfer-files-promise": "^1.3.1", "dayjs": "^1.9.7", "eth-crypto": "^1.8.0", "ethers": "^5.4.3", diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx index 5dd24d422e..a6482c3421 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx @@ -21,6 +21,7 @@ import { useLocalStorage } from "@chainsafe/browser-storage-hooks" import { DISMISSED_SURVEY_KEY } from "../../SurveyBanner" import { FileBrowserContext } from "../../../Contexts/FileBrowserContext" import { parseFileContentResponse } from "../../../Utils/Helpers" +import getFilesFromDataTransferItems from "../../../Utils/getFilesFromDataTransferItems" const CSFFileBrowser: React.FC = () => { const { @@ -178,22 +179,13 @@ const CSFFileBrowser: React.FC = () => { const handleUploadOnDrop = useCallback(async (files: File[], fileItems: DataTransferItemList, path: string) => { if (!bucket) return - let hasFolder = false - for (let i = 0; i < files.length; i++) { - if (fileItems[i].webkitGetAsEntry()?.isDirectory) { - hasFolder = true - } - } - if (hasFolder) { - addToastMessage({ - message: "Folder uploads are not supported currently", - appearance: "error" + + const flattenedFiles = await getFilesFromDataTransferItems(fileItems) + const paths = [...new Set(flattenedFiles.map(f=> f.filepath))] + console.log(paths) + paths.forEach(p => { + uploadFiles(bucket, flattenedFiles.filter(f => f.filepath === p), path + p) }) - } else { - uploadFiles(bucket, files, path) - .then(() => refreshContents()) - .catch(console.error) - } }, [addToastMessage, uploadFiles, bucket, refreshContents]) const viewFolder = useCallback((cid: string) => { diff --git a/packages/files-ui/src/Contexts/FilesContext.tsx b/packages/files-ui/src/Contexts/FilesContext.tsx index 770304f94f..c69dbce73b 100644 --- a/packages/files-ui/src/Contexts/FilesContext.tsx +++ b/packages/files-ui/src/Contexts/FilesContext.tsx @@ -364,11 +364,10 @@ const FilesProvider = ({ children }: FilesContextProps) => { const encryptedData = await encryptFile(fileData, key) return { data: new Blob([encryptedData], { type: f.type }), - fileName: f.name + fileName: f.name, } }) ) - await filesApiClient.uploadBucketObjects( bucket.id, filesParam, diff --git a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts new file mode 100644 index 0000000000..01b463ff68 --- /dev/null +++ b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts @@ -0,0 +1,85 @@ +type FileWithPath = File & {filepath: string} + +const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItemList): Promise> => { + //@ts-ignore + const readFile = (entry: FileSystemFileEntry, path = ''): Promise => { + return new Promise((resolve, reject) => { + entry.file((file: File) => { + //@ts-ignore + file.filepath = path + //@ts-ignore + resolve(file) + }, (err: Error) => { + reject(err) + }) + }) + } + + //@ts-ignore + const dirReadEntries = (dirReader: FileSystemDirectoryReader, path: string): Promise => { + return new Promise((resolve, reject) => { + //@ts-ignore + dirReader.readEntries(async (entries: FileSystemEntry[]) => { + let files = [] as Array + for (let entry of entries) { + const itemFiles = await getFilesFromEntry(entry, path) as Array + files = files.concat(itemFiles) + } + resolve(files) + }, (err: Error) => { + reject(err) + }) + }) + } + + //@ts-ignore + const readDir = async (entry: FileSystemDirectoryEntry, path: string) => { + const dirReader = entry.createReader() + const newPath = path + entry.name + '/' + let files = [] as Array + let newFiles + do { + newFiles = await dirReadEntries(dirReader, newPath) + files = files.concat(newFiles) + } while (newFiles.length > 0) + return files + } + + //@ts-ignore + const getFilesFromEntry = async (entry: FileSystemEntry, path = '') => { + if (entry.isFile) { + //@ts-ignore + const file = await readFile(entry as FileSystemFileEntry, path) + return [file] + } + if (entry.isDirectory) { + //@ts-ignore + const files = await readDir(entry as FileSystemDirectoryEntry, path) + return files + } + // throw new Error('Entry not isFile and not isDirectory - unable to get files') + } + + let files = [] as Array + let entries = [] + + // Pull out all entries before reading them + for (let i = 0, ii = dataTransferItems.length; i < ii; i++) { + //@ts-ignore + entries.push(dataTransferItems[i].webkitGetAsEntry()) + } + + // Recursively read through all entries + for (let entry of entries) { + if (entry) { + const newFiles = await getFilesFromEntry(entry) + if (newFiles) { + files = files.concat(newFiles) + } + } + } + + return files +} + +export default getFilesFromDataTransferItems \ No newline at end of file diff --git a/packages/files-ui/src/types.d.ts b/packages/files-ui/src/types.d.ts new file mode 100644 index 0000000000..e2284a571b --- /dev/null +++ b/packages/files-ui/src/types.d.ts @@ -0,0 +1 @@ +declare module 'datatransfer-files-promise'; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9f4f27606b..9aa65de042 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10484,6 +10484,11 @@ data-urls@^1.0.0, data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" +datatransfer-files-promise@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/datatransfer-files-promise/-/datatransfer-files-promise-1.3.1.tgz#8996214c76925b57fe4c03b25a214ceaca76f063" + integrity sha512-xwh/RYaCTzUVyZr+rDKO28ew3Nbe4aP1HmEa1rNta9Uq1VNI2+ME0s1JKwsnUKXEpCWL+puGXkpJ6j+3vm/T8g== + date-fns@^2.16.1: version "2.16.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b" From 934d4648d37f597367263d9a59db1fc81d5d1519 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Mon, 13 Sep 2021 17:04:15 +0200 Subject: [PATCH 02/16] wire up folder uploads for modal --- .../common-components/src/FileInput/FileInput.tsx | 15 ++++++++------- .../Modules/FileBrowsers/CSFFileBrowser.tsx | 3 +-- .../src/Components/Modules/UploadFileModule.tsx | 10 +++++++--- .../Modules/UploadFileModal/UploadFileModal.tsx | 6 ++++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/common-components/src/FileInput/FileInput.tsx b/packages/common-components/src/FileInput/FileInput.tsx index ef4066cab0..8dbe68c82f 100644 --- a/packages/common-components/src/FileInput/FileInput.tsx +++ b/packages/common-components/src/FileInput/FileInput.tsx @@ -137,21 +137,22 @@ const FileInput = ({ const classes = useStyles() const [previews, setPreviews] = useState([]) const [errors, setErrors] = useState([]) - const [{ value }, meta, helpers] = useField(name) + const [{ value }, meta, helpers] = useField>(name) useEffect(() => { onFileNumberChange && onFileNumberChange(value.length) }, [onFileNumberChange, value.length]) const onDrop = useCallback( - async (acceptedFiles: File[], fileRejections: FileRejection[]) => { + async (acceptedFiles: any[], fileRejections: FileRejection[]) => { const filtered = acceptedFiles.filter((file) => maxFileSize ? file.size <= maxFileSize : true ) + setErrors([]) if (showPreviews) { setPreviews( - filtered.map((file: any) => + filtered.map((file) => Object.assign(file, { preview: URL.createObjectURL(file) }) @@ -220,12 +221,12 @@ const FileInput = ({ >
    - {value.map((file: any, i: any) => ( + {value.map((file: any, i: number) => (
  • - {file.name} + {file.path} - - - - - - ) -} - -export default UploadFileModule From 1f0d90c1199205c8d756cfc66e151e77ae5741a5 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Mon, 13 Sep 2021 17:26:48 +0200 Subject: [PATCH 04/16] fix types --- packages/files-ui/package.json | 1 + .../Utils/getFilesFromDataTransferItems.ts | 27 +++++++------------ yarn.lock | 12 +++++++++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/files-ui/package.json b/packages/files-ui/package.json index cac910f1ad..c2acdda100 100644 --- a/packages/files-ui/package.json +++ b/packages/files-ui/package.json @@ -16,6 +16,7 @@ "@tkey/security-questions": "3.12.0", "@tkey/web-storage": "3.12.0", "@toruslabs/torus-direct-web-sdk": "4.10.0", + "@types/filesystem": "^0.0.32", "@types/uuid": "^8.3.0", "axios": "0.21.4", "babel-loader": "8.1.0", diff --git a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts index 01b463ff68..51471240b9 100644 --- a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts +++ b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts @@ -1,24 +1,21 @@ type FileWithPath = File & {filepath: string} const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItemList): Promise> => { - //@ts-ignore - const readFile = (entry: FileSystemFileEntry, path = ''): Promise => { + const readFile = (entry: FileEntry, path = ''): Promise => { return new Promise((resolve, reject) => { entry.file((file: File) => { - //@ts-ignore - file.filepath = path - //@ts-ignore - resolve(file) + Object.defineProperty(file, 'filepath', { + value: path + }) + resolve(file as FileWithPath) }, (err: Error) => { reject(err) }) }) } - //@ts-ignore - const dirReadEntries = (dirReader: FileSystemDirectoryReader, path: string): Promise => { + const dirReadEntries = (dirReader: DirectoryReader, path: string): Promise => { return new Promise((resolve, reject) => { - //@ts-ignore dirReader.readEntries(async (entries: FileSystemEntry[]) => { let files = [] as Array for (let entry of entries) { @@ -32,8 +29,7 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem }) } - //@ts-ignore - const readDir = async (entry: FileSystemDirectoryEntry, path: string) => { + const readDir = async (entry: DirectoryEntry, path: string) => { const dirReader = entry.createReader() const newPath = path + entry.name + '/' let files = [] as Array @@ -45,19 +41,15 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem return files } - //@ts-ignore const getFilesFromEntry = async (entry: FileSystemEntry, path = '') => { if (entry.isFile) { - //@ts-ignore - const file = await readFile(entry as FileSystemFileEntry, path) + const file = await readFile(entry as FileEntry, path) return [file] } if (entry.isDirectory) { - //@ts-ignore - const files = await readDir(entry as FileSystemDirectoryEntry, path) + const files = await readDir(entry as DirectoryEntry, path) return files } - // throw new Error('Entry not isFile and not isDirectory - unable to get files') } let files = [] as Array @@ -65,7 +57,6 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem // Pull out all entries before reading them for (let i = 0, ii = dataTransferItems.length; i < ii; i++) { - //@ts-ignore entries.push(dataTransferItems[i].webkitGetAsEntry()) } diff --git a/yarn.lock b/yarn.lock index 9aa65de042..8503463839 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5672,6 +5672,18 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/filesystem@^0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.32.tgz#307df7cc084a2293c3c1a31151b178063e0a8edf" + integrity sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee" + integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ== + "@types/fs-extra@^8.0.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.1.tgz#1e49f22d09aa46e19b51c0b013cb63d0d923a068" From 1fd093ad14c1a1a667a6a4e611d7d956f27cce8b Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Mon, 13 Sep 2021 17:28:50 +0200 Subject: [PATCH 05/16] remove types --- packages/files-ui/src/types.d.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 packages/files-ui/src/types.d.ts diff --git a/packages/files-ui/src/types.d.ts b/packages/files-ui/src/types.d.ts deleted file mode 100644 index e2284a571b..0000000000 --- a/packages/files-ui/src/types.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'datatransfer-files-promise'; \ No newline at end of file From 22ee35c6f65b8801edc61f677c9cefe50af8f54b Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 13 Sep 2021 15:35:27 +0000 Subject: [PATCH 06/16] lingui extract --- packages/storage-ui/src/locales/en/messages.po | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/storage-ui/src/locales/en/messages.po b/packages/storage-ui/src/locales/en/messages.po index 3f2656b39a..0c168816e4 100644 --- a/packages/storage-ui/src/locales/en/messages.po +++ b/packages/storage-ui/src/locales/en/messages.po @@ -28,9 +28,6 @@ msgstr "Add API Key" msgid "Add S3 Key" msgstr "Add S3 Key" -msgid "Add more files" -msgstr "Add more files" - msgid "Api Keys" msgstr "Api Keys" @@ -73,9 +70,6 @@ msgstr "Cid" msgid "Cids" msgstr "Cids" -msgid "Click or drag to upload files" -msgstr "Click or drag to upload files" - msgid "Confirm" msgstr "Confirm" @@ -178,9 +172,6 @@ msgstr "" msgid "File" msgstr "File" -msgid "File/Folder already exists" -msgstr "File/Folder already exists" - msgid "Folder" msgstr "Folder" @@ -274,9 +265,6 @@ msgstr "Please enter a folder name" msgid "Please enter a name" msgstr "Please enter a name" -msgid "Please select a file to upload" -msgstr "Please select a file to upload" - msgid "Preview" msgstr "Preview" @@ -334,9 +322,6 @@ msgstr "Something went wrong!" msgid "Something went wrong. We couldn't upload your file" msgstr "Something went wrong. We couldn't upload your file" -msgid "Start Upload" -msgstr "Start Upload" - msgid "Status" msgstr "Status" From d54d81131dd316b0b8ca507e2fb8874a3d2e9d15 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Mon, 13 Sep 2021 17:51:53 +0200 Subject: [PATCH 07/16] fix lint --- .../Modules/FileBrowsers/CSFFileBrowser.tsx | 10 +++++----- .../Modules/FileBrowsers/UploadFileModal.tsx | 4 ++-- packages/files-ui/src/Contexts/FilesContext.tsx | 2 +- .../src/Utils/getFilesFromDataTransferItems.ts | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx index daad452c26..1d9aaef883 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx @@ -179,11 +179,11 @@ const CSFFileBrowser: React.FC = () => { const handleUploadOnDrop = useCallback(async (files: File[], fileItems: DataTransferItemList, path: string) => { if (!bucket) return - const flattenedFiles = await getFilesFromDataTransferItems(fileItems) - const paths = [...new Set(flattenedFiles.map(f=> f.filepath))] - paths.forEach(p => { - uploadFiles(bucket, flattenedFiles.filter(f => f.filepath === p), path + p) - }) + const flattenedFiles = await getFilesFromDataTransferItems(fileItems) + const paths = [...new Set(flattenedFiles.map(f => f.filepath))] + paths.forEach(p => { + uploadFiles(bucket, flattenedFiles.filter(f => f.filepath === p), path + p) + }) }, [uploadFiles, bucket]) const viewFolder = useCallback((cid: string) => { diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx index 35ad07f7d8..268ed18871 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx @@ -94,9 +94,9 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => { helpers.setSubmitting(true) try { close() - const paths = [...new Set(values.files.map(f => f.path.substring(0, f.path.lastIndexOf('/'))))] + const paths = [...new Set(values.files.map(f => f.path.substring(0, f.path.lastIndexOf("/"))))] paths.forEach(async p => { - const filesToUpload = values.files.filter((f => f.path.substring(0, f.path.lastIndexOf('/')) === p)) + const filesToUpload = values.files.filter((f => f.path.substring(0, f.path.lastIndexOf("/")) === p)) await uploadFiles(bucket, filesToUpload, currentPath + p) }) refreshContents && refreshContents() diff --git a/packages/files-ui/src/Contexts/FilesContext.tsx b/packages/files-ui/src/Contexts/FilesContext.tsx index afe0683906..bb9adc2b2c 100644 --- a/packages/files-ui/src/Contexts/FilesContext.tsx +++ b/packages/files-ui/src/Contexts/FilesContext.tsx @@ -323,7 +323,7 @@ const FilesProvider = ({ children }: FilesContextProps) => { const encryptedData = await encryptFile(fileData, key) return { data: new Blob([encryptedData], { type: f.type }), - fileName: f.name, + fileName: f.name } }) ) diff --git a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts index 51471240b9..2f08cab87d 100644 --- a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts +++ b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts @@ -1,10 +1,10 @@ type FileWithPath = File & {filepath: string} const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItemList): Promise> => { - const readFile = (entry: FileEntry, path = ''): Promise => { + const readFile = (entry: FileEntry, path = ""): Promise => { return new Promise((resolve, reject) => { entry.file((file: File) => { - Object.defineProperty(file, 'filepath', { + Object.defineProperty(file, "filepath", { value: path }) resolve(file as FileWithPath) @@ -18,7 +18,7 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem return new Promise((resolve, reject) => { dirReader.readEntries(async (entries: FileSystemEntry[]) => { let files = [] as Array - for (let entry of entries) { + for (const entry of entries) { const itemFiles = await getFilesFromEntry(entry, path) as Array files = files.concat(itemFiles) } @@ -31,7 +31,7 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem const readDir = async (entry: DirectoryEntry, path: string) => { const dirReader = entry.createReader() - const newPath = path + entry.name + '/' + const newPath = path + entry.name + "/" let files = [] as Array let newFiles do { @@ -41,7 +41,7 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem return files } - const getFilesFromEntry = async (entry: FileSystemEntry, path = '') => { + const getFilesFromEntry = async (entry: FileSystemEntry, path = "") => { if (entry.isFile) { const file = await readFile(entry as FileEntry, path) return [file] @@ -53,7 +53,7 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem } let files = [] as Array - let entries = [] + const entries = [] // Pull out all entries before reading them for (let i = 0, ii = dataTransferItems.length; i < ii; i++) { @@ -61,7 +61,7 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem } // Recursively read through all entries - for (let entry of entries) { + for (const entry of entries) { if (entry) { const newFiles = await getFilesFromEntry(entry) if (newFiles) { @@ -73,4 +73,4 @@ const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItem return files } -export default getFilesFromDataTransferItems \ No newline at end of file +export default getFilesFromDataTransferItems \ No newline at end of file From 9d07cb6eb029a633fe6621db70b8f5a4895525a0 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Mon, 13 Sep 2021 17:52:53 +0200 Subject: [PATCH 08/16] add source attribution --- packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts index 2f08cab87d..6b21bb1d21 100644 --- a/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts +++ b/packages/files-ui/src/Utils/getFilesFromDataTransferItems.ts @@ -1,3 +1,5 @@ +//Shamelessly borrowed from https://github.com/anatol-grabowski/datatransfer-files-promise with added Types + type FileWithPath = File & {filepath: string} const getFilesFromDataTransferItems = async (dataTransferItems: DataTransferItemList): Promise> => { From a41c434d879782c9b59cf47581ea138cbb4d1387 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 14 Sep 2021 10:26:57 +0000 Subject: [PATCH 09/16] lingui extract --- packages/files-ui/src/locales/de/messages.po | 11 +++-------- packages/files-ui/src/locales/fr/messages.po | 11 +++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/files-ui/src/locales/de/messages.po b/packages/files-ui/src/locales/de/messages.po index 103f7cb1c2..19b5f0d558 100644 --- a/packages/files-ui/src/locales/de/messages.po +++ b/packages/files-ui/src/locales/de/messages.po @@ -5,8 +5,7 @@ msgstr "" "POT-Creation-Date: 2021-04-20 00:28+0200\n" "PO-Revision-Date: 2021-09-14 09:14+0000\n" "Last-Translator: J. Lavoie \n" -"Language-Team: German \n" +"Language-Team: German \n" "Language: de\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -825,14 +824,10 @@ msgid "unknown" msgstr "unbekannt" msgid "{0, plural, one {Downloading {1} file} other {Downloading {2} files}}" -msgstr "" -"{0, plural, one {{1} Datei wird heruntergeladen} other {{2} Dateien werden " -"heruntergeladen}}" +msgstr "{0, plural, one {{1} Datei wird heruntergeladen} other {{2} Dateien werden heruntergeladen}}" msgid "{0, plural, one {Encrypting and uploading {1} file} other {Encrypting and uploading {2} files}}" -msgstr "" -"{0, plural, one {{1} Datei wird verschlüsselt und hochgeladen} other {{2} " -"Dateien werden verschlüsselt und hochgeladen}}" +msgstr "{0, plural, one {{1} Datei wird verschlüsselt und hochgeladen} other {{2} Dateien werden verschlüsselt und hochgeladen}}" msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "{0, plural, one {Sie sind dabei, {1} Artikel zu löschen.} other {Sie sind dabei, {2} Artikel zu löschen.}}" diff --git a/packages/files-ui/src/locales/fr/messages.po b/packages/files-ui/src/locales/fr/messages.po index a6ef823c23..e80c60a873 100644 --- a/packages/files-ui/src/locales/fr/messages.po +++ b/packages/files-ui/src/locales/fr/messages.po @@ -5,8 +5,7 @@ msgstr "" "POT-Creation-Date: 2021-04-23 11:05+0200\n" "PO-Revision-Date: 2021-09-14 09:14+0000\n" "Last-Translator: J. Lavoie \n" -"Language-Team: French \n" +"Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -829,14 +828,10 @@ msgid "unknown" msgstr "inconnu" msgid "{0, plural, one {Downloading {1} file} other {Downloading {2} files}}" -msgstr "" -"{0, plural, one {Téléchargement de {1} fichier} other {Téléchargement de {2} " -"fichiers}}" +msgstr "{0, plural, one {Téléchargement de {1} fichier} other {Téléchargement de {2} fichiers}}" msgid "{0, plural, one {Encrypting and uploading {1} file} other {Encrypting and uploading {2} files}}" -msgstr "" -"{0, plural, one {Chiffrement et téléversement de {1} fichier} other {" -"Chiffrement et téléversements {2} fichiers}}" +msgstr "{0, plural, one {Chiffrement et téléversement de {1} fichier} other {Chiffrement et téléversements {2} fichiers}}" msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" msgstr "{0, plural, one {Vous êtes sur le point de supprimer {1} élément.} other {Vous êtes sur le point de supprimer {2} éléments.}}" From ca614abad46b1bbe97573715100fe6a035e3ede6 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Wed, 15 Sep 2021 13:45:59 +0200 Subject: [PATCH 10/16] incorporate feedback --- .../Modules/FileBrowsers/CSFFileBrowser.tsx | 2 +- .../Modules/FileBrowsers/UploadFileModal.tsx | 3 +- .../Modules/FilesList/FilesList.tsx | 2 +- .../UploadFileModal/UploadfileModal.tsx | 169 ++++++++++++++++++ 4 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 packages/storage-ui/src/Components/Modules/UploadFileModal/UploadfileModal.tsx diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx index 1d9aaef883..96666371bd 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx @@ -182,7 +182,7 @@ const CSFFileBrowser: React.FC = () => { const flattenedFiles = await getFilesFromDataTransferItems(fileItems) const paths = [...new Set(flattenedFiles.map(f => f.filepath))] paths.forEach(p => { - uploadFiles(bucket, flattenedFiles.filter(f => f.filepath === p), path + p) + uploadFiles(bucket, flattenedFiles.filter(f => f.filepath === p), getPathWithFile(path, p)) }) }, [uploadFiles, bucket]) diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx index 268ed18871..8a13046f90 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx @@ -9,6 +9,7 @@ import { Trans, t } from "@lingui/macro" import clsx from "clsx" import { CSFTheme } from "../../../Themes/types" import { useFileBrowser } from "../../../Contexts/FileBrowserContext" +import {getPathWithFile} from "../../../Utils/pathUtils" const useStyles = makeStyles(({ constants, breakpoints }: CSFTheme) => createStyles({ @@ -97,7 +98,7 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => { const paths = [...new Set(values.files.map(f => f.path.substring(0, f.path.lastIndexOf("/"))))] paths.forEach(async p => { const filesToUpload = values.files.filter((f => f.path.substring(0, f.path.lastIndexOf("/")) === p)) - await uploadFiles(bucket, filesToUpload, currentPath + p) + await uploadFiles(bucket, filesToUpload, getPathWithFile(currentPath, p)) }) refreshContents && refreshContents() helpers.resetForm() diff --git a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx index bb0f1d9e30..19f5624de0 100644 --- a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx +++ b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx @@ -36,7 +36,7 @@ import FileSystemItem from "../FileSystemItem/FileSystemItem" import UploadProgressModals from "../UploadProgressModals" import DownloadProgressModals from "../DownloadProgressModals" import CreateFolderModal from "../CreateFolderModal/CreateFolderModal" -import UploadFileModule from "../UploadFileModal/UploadFileModal" +import UploadFileModule from "../UploadFileModal/UploadfileModal" import MoveFileModal from "../MoveFileModal/MoveFileModal" import { CONTENT_TYPES } from "../../../Utils/Constants" import { CSSTheme } from "../../../Themes/types" diff --git a/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadfileModal.tsx b/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadfileModal.tsx new file mode 100644 index 0000000000..3631b53622 --- /dev/null +++ b/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadfileModal.tsx @@ -0,0 +1,169 @@ +import { Button, FileInput } from "@chainsafe/common-components" +import { useStorage } from "../../../Contexts/StorageContext" +import { createStyles, makeStyles } from "@chainsafe/common-theme" +import React, { useCallback, useState } from "react" +import { Formik, Form } from "formik" +import { array, object } from "yup" +import CustomModal from "../../Elements/CustomModal" +import { Trans, t } from "@lingui/macro" +import clsx from "clsx" +import { CSSTheme } from "../../../Themes/types" +import { useFileBrowser } from "../../../Contexts/FileBrowserContext" + +const useStyles = makeStyles(({ constants, breakpoints }: CSSTheme) => + createStyles({ + root: { + }, + modalInner: { + backgroundColor: constants.uploadModal.background, + color: constants.uploadModal.color, + [breakpoints.down("md")]: { + maxWidth: `${breakpoints.width("md")}px !important` + } + }, + input: { + marginBottom: constants.generalUnit * 2 + }, + fileList: { + color: constants.uploadModal.color + }, + item: { + color: constants.uploadModal.color + }, + cta: {}, + okButton: { + marginLeft: constants.generalUnit, + "&.wide": { + paddingLeft: constants.generalUnit * 4, + paddingRight: constants.generalUnit * 4 + } + }, + cancelButton: {}, + label: { + fontSize: 14, + lineHeight: "22px" + }, + addFiles: { + backgroundColor: constants.uploadModal.addMoreBackground, + color: constants.uploadModal.addMore, + "& svg": { + fill: constants.uploadModal.addMore + } + }, + closeIcon: { + "& svg": { + fill: constants.uploadModal.icon + }, + "&:hover svg": { + fill: constants.uploadModal.iconHover + } + }, + footer: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-end", + alignItems: "center", + padding: constants.generalUnit * 2, + backgroundColor: constants.uploadModal.footerBackground + } + }) +) + +interface IUploadFileModuleProps { + modalOpen: boolean + close: () => void +} + +const UploadFileModal = ({ modalOpen, close }: IUploadFileModuleProps) => { + const classes = useStyles() + const [isDoneDisabled, setIsDoneDisabled] = useState(true) + const { uploadFiles } = useStorage() + const { currentPath, refreshContents, bucket } = useFileBrowser() + + const UploadSchema = object().shape({ files: array().required(t`Please select a file to upload`) }) + + const onFileNumberChange = useCallback((filesNumber: number) => { + setIsDoneDisabled(filesNumber === 0) + }, []) + + const onSubmit = useCallback(async (values, helpers) => { + if (!bucket) return + helpers.setSubmitting(true) + try { + close() + await uploadFiles(bucket.id, values.files, currentPath) + refreshContents && refreshContents() + helpers.resetForm() + } catch (errors) { + if (errors[0].message.includes("conflict with existing")) { + helpers.setFieldError("files", t`File/Folder already exists`) + } else { + helpers.setFieldError("files", errors[0].message) + } + } + helpers.setSubmitting(false) + }, [close, currentPath, uploadFiles, refreshContents, bucket]) + + return ( + + +
    + +
    + + +
    + +
    +
    + ) +} + +export default UploadFileModal \ No newline at end of file From 9a7d55b010ed74c2c3aee1157899c82d6cadb3fe Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 15 Sep 2021 11:50:11 +0000 Subject: [PATCH 11/16] lingui extract --- packages/storage-ui/src/locales/en/messages.po | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/storage-ui/src/locales/en/messages.po b/packages/storage-ui/src/locales/en/messages.po index 0c168816e4..3f2656b39a 100644 --- a/packages/storage-ui/src/locales/en/messages.po +++ b/packages/storage-ui/src/locales/en/messages.po @@ -28,6 +28,9 @@ msgstr "Add API Key" msgid "Add S3 Key" msgstr "Add S3 Key" +msgid "Add more files" +msgstr "Add more files" + msgid "Api Keys" msgstr "Api Keys" @@ -70,6 +73,9 @@ msgstr "Cid" msgid "Cids" msgstr "Cids" +msgid "Click or drag to upload files" +msgstr "Click or drag to upload files" + msgid "Confirm" msgstr "Confirm" @@ -172,6 +178,9 @@ msgstr "" msgid "File" msgstr "File" +msgid "File/Folder already exists" +msgstr "File/Folder already exists" + msgid "Folder" msgstr "Folder" @@ -265,6 +274,9 @@ msgstr "Please enter a folder name" msgid "Please enter a name" msgstr "Please enter a name" +msgid "Please select a file to upload" +msgstr "Please select a file to upload" + msgid "Preview" msgstr "Preview" @@ -322,6 +334,9 @@ msgstr "Something went wrong!" msgid "Something went wrong. We couldn't upload your file" msgstr "Something went wrong. We couldn't upload your file" +msgid "Start Upload" +msgstr "Start Upload" + msgid "Status" msgstr "Status" From 350bb64a08128b5ded50000b7d0b030853631278 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Wed, 15 Sep 2021 14:06:02 +0200 Subject: [PATCH 12/16] fix lint --- .../src/Components/Modules/FileBrowsers/UploadFileModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx index 8a13046f90..d2a0615753 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/UploadFileModal.tsx @@ -9,7 +9,7 @@ import { Trans, t } from "@lingui/macro" import clsx from "clsx" import { CSFTheme } from "../../../Themes/types" import { useFileBrowser } from "../../../Contexts/FileBrowserContext" -import {getPathWithFile} from "../../../Utils/pathUtils" +import { getPathWithFile } from "../../../Utils/pathUtils" const useStyles = makeStyles(({ constants, breakpoints }: CSFTheme) => createStyles({ From bbd53bed5ccb29a331dbf07df777181fc20350dd Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Wed, 15 Sep 2021 14:08:09 +0200 Subject: [PATCH 13/16] Fix casing --- .../storage-ui/src/Components/Modules/FilesList/FilesList.tsx | 2 +- .../{UploadfileModal.tsx => UploadFileModal.tsx} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/storage-ui/src/Components/Modules/UploadFileModal/{UploadfileModal.tsx => UploadFileModal.tsx} (100%) diff --git a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx index 19f5624de0..bb0f1d9e30 100644 --- a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx +++ b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx @@ -36,7 +36,7 @@ import FileSystemItem from "../FileSystemItem/FileSystemItem" import UploadProgressModals from "../UploadProgressModals" import DownloadProgressModals from "../DownloadProgressModals" import CreateFolderModal from "../CreateFolderModal/CreateFolderModal" -import UploadFileModule from "../UploadFileModal/UploadfileModal" +import UploadFileModule from "../UploadFileModal/UploadFileModal" import MoveFileModal from "../MoveFileModal/MoveFileModal" import { CONTENT_TYPES } from "../../../Utils/Constants" import { CSSTheme } from "../../../Themes/types" diff --git a/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadfileModal.tsx b/packages/storage-ui/src/Components/Modules/UploadFileModal/UploadFileModal.tsx similarity index 100% rename from packages/storage-ui/src/Components/Modules/UploadFileModal/UploadfileModal.tsx rename to packages/storage-ui/src/Components/Modules/UploadFileModal/UploadFileModal.tsx From 30195bb513c047371ae3e1dcead8bb40a48de52d Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Wed, 15 Sep 2021 14:08:59 +0200 Subject: [PATCH 14/16] Rename component for consistency --- .../storage-ui/src/Components/Modules/FilesList/FilesList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx index bb0f1d9e30..eb3c4b4e04 100644 --- a/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx +++ b/packages/storage-ui/src/Components/Modules/FilesList/FilesList.tsx @@ -36,7 +36,7 @@ import FileSystemItem from "../FileSystemItem/FileSystemItem" import UploadProgressModals from "../UploadProgressModals" import DownloadProgressModals from "../DownloadProgressModals" import CreateFolderModal from "../CreateFolderModal/CreateFolderModal" -import UploadFileModule from "../UploadFileModal/UploadFileModal" +import UploadFileModal from "../UploadFileModal/UploadFileModal" import MoveFileModal from "../MoveFileModal/MoveFileModal" import { CONTENT_TYPES } from "../../../Utils/Constants" import { CSSTheme } from "../../../Themes/types" @@ -990,7 +990,7 @@ const FilesList = () => { modalOpen={createFolderModalOpen} close={() => setCreateFolderModalOpen(false)} /> - setIsUploadModalOpen(false)} /> From 26fbb6a626f0f0810914b7d7c424745102e1f2bc Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 16 Sep 2021 11:34:54 +0000 Subject: [PATCH 15/16] lingui extract --- packages/files-ui/src/locales/fr/messages.po | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/files-ui/src/locales/fr/messages.po b/packages/files-ui/src/locales/fr/messages.po index c5fc74be70..698558251b 100644 --- a/packages/files-ui/src/locales/fr/messages.po +++ b/packages/files-ui/src/locales/fr/messages.po @@ -5,8 +5,7 @@ msgstr "" "POT-Creation-Date: 2021-04-23 11:05+0200\n" "PO-Revision-Date: 2021-09-15 21:36+0000\n" "Last-Translator: J. Lavoie \n" -"Language-Team: French \n" +"Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" From 88d0b53362c606acafd8ef2b1d748dcbdda40700 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Thu, 16 Sep 2021 13:59:36 +0200 Subject: [PATCH 16/16] clean up types --- packages/common-components/src/FileInput/FileInput.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/common-components/src/FileInput/FileInput.tsx b/packages/common-components/src/FileInput/FileInput.tsx index 8dbe68c82f..256ba82b17 100644 --- a/packages/common-components/src/FileInput/FileInput.tsx +++ b/packages/common-components/src/FileInput/FileInput.tsx @@ -99,6 +99,10 @@ const useStyles = makeStyles(({ constants, palette, overrides }: ITheme) => }) ) +interface FileWithPath extends File { + path?: string +} + interface IFileInputProps extends DropzoneOptions { className?: string variant?: "dropzone" | "filepicker" @@ -137,14 +141,14 @@ const FileInput = ({ const classes = useStyles() const [previews, setPreviews] = useState([]) const [errors, setErrors] = useState([]) - const [{ value }, meta, helpers] = useField>(name) + const [{ value }, meta, helpers] = useField>(name) useEffect(() => { onFileNumberChange && onFileNumberChange(value.length) }, [onFileNumberChange, value.length]) const onDrop = useCallback( - async (acceptedFiles: any[], fileRejections: FileRejection[]) => { + async (acceptedFiles: Array, fileRejections: FileRejection[]) => { const filtered = acceptedFiles.filter((file) => maxFileSize ? file.size <= maxFileSize : true ) @@ -189,7 +193,7 @@ const FileInput = ({ }) const removeItem = (i: number) => { - const items = value as any[] + const items = value items.splice(i, 1) helpers.setValue(items) }