Skip to content

Commit

Permalink
Merge pull request #1424 from ChainSafe/feat/download-buckets-1418
Browse files Browse the repository at this point in the history
Storage: Download functionality on bucket files
  • Loading branch information
FSM1 authored Aug 11, 2021
2 parents a43c72c + 3764d08 commit 31b6739
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ const useStyles = makeStyles(({ breakpoints, constants, palette }: CSSTheme) =>
},
dropdownItem: {
backgroundColor: constants.fileSystemItemRow.itemBackground,
color: constants.fileSystemItemRow.itemColor
color: constants.fileSystemItemRow.itemColor,
"& a": {
textDecoration: "none"
}
}
})
})
Expand Down Expand Up @@ -166,7 +169,8 @@ const FileSystemTableItem = React.forwardRef(
<TableRow
data-cy="file-item-row"
className={clsx(classes.tableRow, {
droppable: isFolder && (isOverMove || isOverUpload)
droppable: isFolder && (isOverMove || isOverUpload),
ipfs: desktop && fileSystemType && fileSystemType === "ipfs"
})}
type="grid"
ref={forwardedRef}
Expand Down
15 changes: 7 additions & 8 deletions packages/storage-ui/src/Components/Pages/BucketPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useLocalStorage } from "@chainsafe/browser-storage-hooks"
import { DISMISSED_SURVEY_KEY } from "../Modules/SurveyBanner"

const BucketPage: React.FC<IFileBrowserModuleProps> = () => {
const { storageBuckets, uploadFiles, uploadsInProgress, getStorageSummary } = useStorage()
const { storageBuckets, uploadFiles, uploadsInProgress, getStorageSummary, downloadFile } = useStorage()
const { storageApiClient } = useStorageApi()
const { addToastMessage } = useToaster()
const [loadingCurrentPath, setLoadingCurrentPath] = useState(false)
Expand Down Expand Up @@ -137,15 +137,14 @@ const BucketPage: React.FC<IFileBrowserModuleProps> = () => {
}, [addToastMessage, pathContents, refreshContents, storageApiClient, bucket, currentPath])

const handleDownload = useCallback(async (
//cid: string
toDownload: ISelectedFile
) => {
throw new Error("Not implemented")
// const itemToDownload = pathContents.find(item => item.cid === cid)
// if (!itemToDownload || !bucket) return
const itemToDownload = pathContents.find(item => item.cid === toDownload.cid)
if (!itemToDownload || !bucket) return

// downloadFile(bucket.id, itemToDownload, currentPath)
downloadFile(bucket.id, itemToDownload, currentPath)
}, [
//pathContents, currentPath, bucket
pathContents, currentPath, bucket, downloadFile
])

// Breadcrumbs/paths
Expand Down Expand Up @@ -198,7 +197,7 @@ const BucketPage: React.FC<IFileBrowserModuleProps> = () => {
[CONTENT_TYPES.Image]: [],
[CONTENT_TYPES.Pdf]: [],
[CONTENT_TYPES.Text]: [],
[CONTENT_TYPES.File]: ["delete", "move"],
[CONTENT_TYPES.File]: ["download", "move", "delete"],
[CONTENT_TYPES.Directory]: ["delete", "move"]
}), [])

Expand Down
89 changes: 88 additions & 1 deletion packages/storage-ui/src/Contexts/StorageContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { useStorageApi } from "./StorageApiContext"
import { v4 as uuidv4 } from "uuid"
import { t } from "@lingui/macro"
import { readFileAsync } from "../Utils/Helpers"
import axios, { CancelToken } from "axios"
import { getPathWithFile } from "../Utils/pathUtils"

type StorageContextProps = {
children: React.ReactNode | React.ReactNode[]
Expand All @@ -42,13 +44,22 @@ export type DownloadProgress = {
complete: boolean
}

interface GetFileContentParams {
cid: string
cancelToken?: CancelToken
onDownloadProgress?: (progressEvent: ProgressEvent<EventTarget>) => void
file: FileSystemItem
path: string
}

type StorageContext = {
pins: PinStatus[]
uploadsInProgress: UploadProgress[]
downloadsInProgress: DownloadProgress[]
storageSummary: BucketSummaryResponse | undefined
getStorageSummary: () => Promise<void>
uploadFiles: (bucketId: string, files: File[], path: string) => Promise<void>
downloadFile: (bucketId: string, itemToDownload: FileSystemItem, path: string) => void
addPin: (cid: string) => Promise<PinStatus>
refreshPins: () => void
unpin: (requestId: string) => void
Expand Down Expand Up @@ -132,7 +143,7 @@ const StorageProvider = ({ children }: StorageContextProps) => {
[]
)

const [downloadsInProgress] = useReducer(
const [downloadsInProgress, dispatchDownloadsInProgress] = useReducer(
downloadsInProgressReducer,
[]
)
Expand Down Expand Up @@ -257,6 +268,81 @@ const StorageProvider = ({ children }: StorageContextProps) => {
}
}, [storageBuckets, storageApiClient, getStorageSummary])

const getFileContent = useCallback(async (
bucketId: string,
{ cancelToken, onDownloadProgress, path }: GetFileContentParams
) => {

try {
const result = await storageApiClient.getBucketObjectContent(
bucketId,
{ path: path },
cancelToken,
onDownloadProgress
)

return result.data

} catch (error) {
if (axios.isCancel(error)) {
return Promise.reject()
} else {
console.error(error)
return Promise.reject(error)
}
}
}, [storageApiClient])

const downloadFile = useCallback(async (bucketId: string, itemToDownload: FileSystemItem, path: string) => {
const toastId = uuidv4()
try {
const downloadProgress: DownloadProgress = {
id: toastId,
fileName: itemToDownload.name,
complete: false,
error: false,
progress: 0
}
dispatchDownloadsInProgress({ type: "add", payload: downloadProgress })
const result = await getFileContent(bucketId, {
cid: itemToDownload.cid,
file: itemToDownload,
path: getPathWithFile(path, itemToDownload.name),
onDownloadProgress: (progressEvent) => {
dispatchDownloadsInProgress({
type: "progress",
payload: {
id: toastId,
progress: Math.ceil(
(progressEvent.loaded / itemToDownload.size) * 100
)
}
})
}
})
if (!result) return
const link = document.createElement("a")
link.href = URL.createObjectURL(result)
link.download = itemToDownload?.name || "file"
link.click()
dispatchDownloadsInProgress({
type: "complete",
payload: { id: toastId }
})
URL.revokeObjectURL(link.href)
setTimeout(() => {
dispatchDownloadsInProgress({
type: "remove",
payload: { id: toastId }
})
}, REMOVE_UPLOAD_PROGRESS_DELAY)
return Promise.resolve()
} catch (error) {
dispatchDownloadsInProgress({ type: "error", payload: { id: toastId } })
return Promise.reject()
}
}, [getFileContent])

return (
<StorageContext.Provider
value={{
Expand All @@ -269,6 +355,7 @@ const StorageProvider = ({ children }: StorageContextProps) => {
refreshPins,
unpin,
storageBuckets,
downloadFile,
createBucket,
removeBucket,
uploadFiles
Expand Down

0 comments on commit 31b6739

Please sign in to comment.