diff --git a/.eslintrc.json b/.eslintrc.json index e010c51c26..2992179aaa 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,13 +7,14 @@ "jsx": true // Allows for the parsing of JSX } }, - "plugins": ["@typescript-eslint"], + "plugins": ["@typescript-eslint", "cypress"], "extends": [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:react/recommended", - "plugin:react-hooks/recommended" + "plugin:react-hooks/recommended", + "plugin:cypress/recommended" ], "settings": { "react": { diff --git a/.github/release_drafter.yml b/.github/release-drafter.yml similarity index 83% rename from .github/release_drafter.yml rename to .github/release-drafter.yml index 1170fa755b..850e66e72e 100644 --- a/.github/release_drafter.yml +++ b/.github/release-drafter.yml @@ -1,18 +1,19 @@ name-template: "v$RESOLVED_VERSION 🌈" tag-template: "v$RESOLVED_VERSION" -references: - - dev +# references: +# - dev categories: - title: "🚀 Features" labels: - - "Type: Feature" - - "Type: Enhancement" + - "Feature" + - "Enhancement" - title: "🐛 Bug Fixes" labels: - - "Type: Bug" + - "Bug" + - "Bugfix" + - "fix" - title: "🧰 Maintenance" - label: - - "Type: Maintenance" + label: "Maintenance" change-template: "- $TITLE @$AUTHOR (#$NUMBER)" change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. version-resolver: @@ -30,9 +31,6 @@ exclude-labels: - "skip-changelog" template: | ## Changelog - $CHANGES - 🙏 A big thank you to all the contributors to this release: - $CONTRIBUTORS diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000000..4eb0cd7e6a --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,16 @@ +name: Release Drafter +on: + push: + branches: + - "dev" + +jobs: + build: + name: Release Drafter + runs-on: ubuntu-20.04 + steps: + + - name: Release Drafter + uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release_drafter.yml b/.github/workflows/release_drafter.yml deleted file mode 100644 index e8d766d38d..0000000000 --- a/.github/workflows/release_drafter.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Release Drafter - -on: - push: - # branches to consider in the event; optional, defaults to all - branches: - - dev - pull_request: - # Only following types are handled by the action, but one can default to all as well - types: [opened, reopened, synchronize] -jobs: - update_release_draft: - runs-on: ubuntu-latest - steps: - # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000..7b2f89658c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,54 @@ +name: Cypress tests +on: pull_request +jobs: + cypress-run: + runs-on: ubuntu-latest + container: cypress/browsers:node12.18.3-chrome87-ff82 + steps: + - name: Checkout + uses: actions/checkout@v2 + + - uses: actions/cache@v2 + id: yarn-build-cache + with: + path: | + **/node_modules + ~/.cache/Cypress + **/build + key: ${{ runner.os }}-node_modules-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node_modules-build- + + # Install NPM dependencies, cache them correctly + # and run all Cypress tests + - name: Cypress run + uses: cypress-io/github-action@v2 + env: + GITHUB_PACKAGES_AUTH_TOKEN: ${{ secrets.GH_PKG_AUTH_TOKEN }} + REACT_APP_API_URL: ${{ secrets.GH_REACT_APP_API_URL }} + REACT_APP_BLOCKNATIVE_ID: ${{ secrets.GH_REACT_APP_BLOCKNATIVE_ID }} + REACT_APP_FILES_VERIFIER_NAME: ${{ secrets.GH_REACT_APP_FILES_VERIFIER_NAME }} + REACT_APP_FILES_UUID_VERIFIER_NAME: 'chainsafe-uuid-testnet' + REACT_APP_TEST: 'true' + with: + start: yarn start:files-ui + # quote the url to be safe against YML parsing surprises + wait-on: 'http://localhost:3000' + # wait for max 2 minutes for the files-ui to respond + wait-on-timeout: 120 + # custom test command to run + command: yarn test:ci:files-ui + # store the screenshots if the tests fail + - name: Store screenshots + uses: actions/upload-artifact@v1 + if: failure() + with: + name: cypress-screenshots + path: packages/files-ui/cypress/screenshots + # store the videos if the tests fail + # - name: Store videos + # uses: actions/upload-artifact@v1 + # if: failure() + # with: + # name: cypress-videos + # path: packages/files-ui/cypress/videos diff --git a/.gitignore b/.gitignore index 6fc93ba48f..482d6db688 100644 --- a/.gitignore +++ b/.gitignore @@ -53,4 +53,9 @@ storybook-static .vscode .idea .env -.DS_Store \ No newline at end of file +.DS_Store + +# test artifacts +packages/files-ui/cypress/screenshots/* +packages/files-ui/cypress/videos/* +packages/files-ui/cypress/fixtures/storage \ No newline at end of file diff --git a/package.json b/package.json index c5341d30c1..c02314dbba 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@sentry/cli": "1.60.1", "chalk": "^4.1.0", "eslint-plugin-react-hooks": "^4.2.0", + "npm-run-all": "^4.1.5", "typescript": "^4.0.5", "wsrun": "^5.2.4" }, @@ -37,7 +38,10 @@ "clean:dist": "rm -rf ./*/**/dist && rm -rf ./*/**/build && rm -rf ./*/**/storybook-static", "clean": "yarn clean:dependencies && yarn clean:dist", "start:tunnel": "./ngrok http https://localhost:3000", - "lint": "eslint 'packages/**/src/**/*.{js,jsx,ts,tsx}'" + "lint": "eslint 'packages/**/{src, cypress}/**/*.{js,jsx,ts,tsx}'", + "serve:files-ui": "npx serve packages/files-ui/build -p 3000", + "test:files-ui": "yarn wsrun -p files-ui -c test", + "test:ci:files-ui": "yarn wsrun -p files-ui -c test:ci" }, "workspaces": { "packages": [ diff --git a/packages/common-components/src/FileInput/FileInput.tsx b/packages/common-components/src/FileInput/FileInput.tsx index d83a672131..969fb0d48c 100644 --- a/packages/common-components/src/FileInput/FileInput.tsx +++ b/packages/common-components/src/FileInput/FileInput.tsx @@ -117,9 +117,10 @@ interface IFileInputProps extends DropzoneOptions { } onFileNumberChange: (filesNumber: number) => void moreFilesLabel: string + testId?: string } -const FileInput: React.FC = ({ +const FileInput = ({ className, variant = "dropzone", showPreviews = false, @@ -130,6 +131,7 @@ const FileInput: React.FC = ({ classNames, onFileNumberChange, moreFilesLabel, + testId, ...props }: IFileInputProps) => { const classes = useStyles() @@ -194,6 +196,7 @@ const FileInput: React.FC = ({ return (
@@ -213,7 +216,10 @@ const FileInput: React.FC = ({ )}
) : ( -
+
    {value.map((file: any, i: any) => ( @@ -223,6 +229,7 @@ const FileInput: React.FC = ({ > {file.name} - - - ) : ( - {name} + { + if (event.key === "Escape") { + setEditing(undefined) + } + }} + placeholder = {isFolder + ? t`Please enter a folder name` + : t`Please enter a file name` + } + autoFocus={editing === cid} + /> + + + + ) : ( + {name} + )} + + {desktop && ( + <> + + { + !isFolder && !!created_at && dayjs.unix(created_at).format("DD MMM YYYY h:mm a") + } + + + {!isFolder && formatBytes(size)} + + )} - - {desktop && ( - <> - - { - created_at && dayjs.unix(created_at).format("DD MMM YYYY h:mm a") - } - - - {!isFolder && formatBytes(size)} - - - )} - - - - - ) -} + + + + + ) + } +) + +FileSystemTableItem.displayName = "FileSystemTableItem" -export default FileSystemTableItem \ No newline at end of file +export default FileSystemTableItem diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesTable.view.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx similarity index 82% rename from packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesTable.view.tsx rename to packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx index e1cd8f2a36..185cc775b7 100644 --- a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesTable.view.tsx +++ b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx @@ -20,6 +20,7 @@ import { Dialog, Loading, CheckboxInput, + useHistory, GridIcon, TableIcon } from "@chainsafe/common-components" @@ -31,13 +32,13 @@ import clsx from "clsx" import { plural, t, Trans } from "@lingui/macro" import { NativeTypes } from "react-dnd-html5-backend" import { useDrop } from "react-dnd" -import { BrowserView, FileOperation, IFilesTableBrowserProps } from "../types" -import { FileSystemItem } from "../../../../Contexts/DriveContext" -import FileSystemItemRow from "./FileSystemItem/FileSystemItem" +import { BrowserView, FileOperation } from "../types" +import { FileSystemItem as FileSystemItemType } from "../../../../Contexts/FilesContext" +import FileSystemItem from "./FileSystemItem/FileSystemItem" import FilePreviewModal from "../../FilePreviewModal" import UploadProgressModals from "../../UploadProgressModals" import DownloadProgressModals from "../../DownloadProgressModals" -import CreateFolderModule from "../../CreateFolderModule" +import CreateFolderModal from "../CreateFolderModal" import UploadFileModule from "../../UploadFileModule" import MoveFileModule from "../MoveFileModal" import FileInfoModal from "../FileInfoModal" @@ -45,7 +46,10 @@ import { CONTENT_TYPES } from "../../../../Utils/Constants" import { CSFTheme } from "../../../../Themes/types" import MimeMatcher from "../../../../Utils/MimeMatcher" import { useLanguageContext } from "../../../../Contexts/LanguageContext" +import { getPathWithFile } from "../../../../Utils/pathUtils" import SurveyBanner from "../../../SurveyBanner" +import { DragPreviewLayer } from "./DragPreviewLayer" +import { useFileBrowser } from "../../../../Contexts/FileBrowserContext" interface IStyleProps { themeKey: string @@ -68,7 +72,7 @@ const useStyles = makeStyles( borderRadius: constants.generalUnit / 4, minHeight: `calc(100vh - ${Number(constants.contentTopPadding)}px)`, "&.droppable": { - borderColor: palette.additional["geekblue"][4] + borderColor: palette.primary.main } } // transitionDuration: `${animation.transform}ms`, @@ -231,6 +235,7 @@ const useStyles = makeStyles( display: "flex", flexDirection: "row", marginTop: constants.generalUnit * 3, + minHeight: constants.generalUnit * 4.2, // reserve space for buttons for the interface not to jump when they get visible "& > *": { marginRight: constants.generalUnit } @@ -269,34 +274,36 @@ const useStyles = makeStyles( ) // Sorting -const sortFoldersFirst = (a: FileSystemItem, b: FileSystemItem) => +const sortFoldersFirst = (a: FileSystemItemType, b: FileSystemItemType) => a.isFolder && a.content_type !== b.content_type ? -1 : 1 -const FilesTableView = ({ - heading, - controls = true, - sourceFiles, - handleUploadOnDrop, - bulkOperations, - updateCurrentPath, - crumbs, - handleRename, - handleMove, - downloadFile, - deleteFiles, - recoverFile, - viewFolder, - currentPath, - loadingCurrentPath, - uploadsInProgress, - showUploadsInTable, - allowDropUpload, - itemOperations, - getPath, - isSearch, - withSurvey -}: IFilesTableBrowserProps) => { +const FilesList = () => { const { themeKey, desktop } = useThemeSwitcher() + + const { + heading, + controls = true, + sourceFiles, + handleUploadOnDrop, + bulkOperations, + crumbs, + renameItem: handleRename, + deleteItems: deleteFiles, + recoverItems, + viewFolder, + currentPath, + refreshContents, + loadingCurrentPath, + uploadsInProgress, + showUploadsInTable, + allowDropUpload, + itemOperations, + getPath, + moduleRootPath, + isSearch, + withSurvey, + bucket + } = useFileBrowser() const classes = useStyles({ themeKey }) const [editing, setEditing] = useState() const [direction, setDirection] = useState("ascend") @@ -305,7 +312,9 @@ const FilesTableView = ({ const [selectedCids, setSelectedCids] = useState([]) const [previewFileIndex, setPreviewFileIndex] = useState() const { selectedLocale } = useLanguageContext() - const items: FileSystemItem[] = useMemo(() => { + const { redirect } = useHistory() + + const items: FileSystemItemType[] = useMemo(() => { let temp = [] switch (column) { @@ -338,9 +347,9 @@ const FilesTableView = ({ const files = useMemo(() => items.filter((i) => !i.isFolder), [items]) - const selectedFiles = useMemo( - () => files.filter((file) => selectedCids.includes(file.cid)), - [files, selectedCids] + const selectedItems = useMemo( + () => items.filter((file) => selectedCids.includes(file.cid)), + [selectedCids, items] ) const handleSortToggle = ( @@ -380,7 +389,18 @@ const FilesTableView = ({ } // Selection logic - const handleSelect = useCallback( + const handleSelectCid = useCallback( + (cid: string) => { + if (selectedCids.includes(cid)) { + setSelectedCids([]) + } else { + setSelectedCids([cid]) + } + }, + [selectedCids] + ) + + const handleAddToSelectedCids = useCallback( (cid: string) => { if (selectedCids.includes(cid)) { setSelectedCids( @@ -393,26 +413,26 @@ const FilesTableView = ({ [selectedCids] ) - const toggleAll = () => { + const toggleAll = useCallback(() => { if (selectedCids.length === items.length) { setSelectedCids([]) } else { - setSelectedCids([...items.map((file: FileSystemItem) => file.cid)]) + setSelectedCids([...items.map((file: FileSystemItemType) => file.cid)]) } - } + }, [setSelectedCids, items, selectedCids]) const invalidFilenameRegex = new RegExp("/") const renameSchema = object().shape({ fileName: string() - .min(1, "Please enter a file name") - .max(65, "File name length exceeded") + .min(1, t`Please enter a name`) + .max(65, t`Name too long`) .test( - "Invalid name", - "File name cannot contain '/' character", + t`Invalid name`, + t`Name cannot contain '/' character`, (val: string | null | undefined) => !invalidFilenameRegex.test(val || "") ) - .required("File name is required") + .required(t`A name is required`) }) const [{ isOverUploadable, isOverBrowser }, dropBrowserRef] = useDrop({ @@ -422,6 +442,7 @@ const FilesTableView = ({ handleUploadOnDrop && currentPath && handleUploadOnDrop(item.files, item.items, currentPath) + refreshContents && refreshContents() } }, collect: (monitor) => ({ @@ -437,6 +458,7 @@ const FilesTableView = ({ const [isMoveFileModalOpen, setIsMoveFileModalOpen] = useState(false) const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) const [isDeletingFiles, setIsDeletingFiles] = useState(false) + const [isRecoveringFiles, setIsRecoveringFiles] = useState(false) const [fileInfoPath, setFileInfoPath] = useState( undefined ) @@ -445,6 +467,7 @@ const FilesTableView = ({ // Bulk operations const [validBulkOps, setValidBulkOps] = useState([]) + useEffect(() => { if (bulkOperations) { let filteredList: FileOperation[] = [ @@ -454,7 +477,8 @@ const FilesTableView = ({ "move", "preview", "rename", - "share" + "share", + "recover" ] for (let i = 0; i < selectedCids.length; i++) { const contentType = items.find((item) => item.cid === selectedCids[i]) @@ -513,6 +537,20 @@ const FilesTableView = ({ }) }, [deleteFiles, selectedCids]) + const handleRecoverFiles = useCallback((e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + if (!recoverItems) return + + setIsRecoveringFiles(true) + recoverItems(selectedCids) + .catch(console.error) + .finally(() => { + setIsRecoveringFiles(false) + setSelectedCids([]) + }) + }, [recoverItems, selectedCids]) + const getItemOperations = useCallback( (contentType: string) => { const result = Object.keys(itemOperations).reduce( @@ -541,14 +579,29 @@ const FilesTableView = ({ setSelectedCids([]) }, []) + useEffect(() => { + setSelectedCids([]) + }, [currentPath]) + const onHideSurveyBanner = useCallback(() => { setIsSurveyBannerVisible(false) }, [setIsSurveyBannerVisible]) const handleViewFolder = useCallback((cid: string) => { - resetSelectedCids() viewFolder && viewFolder(cid) - }, [viewFolder, resetSelectedCids]) + }, [viewFolder]) + + const handleOpenMoveFileDialog = useCallback((e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + setIsMoveFileModalOpen(true) + }, []) + + const handleOpenDeleteDialog = useCallback((e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + setIsDeleteModalOpen(true) + }, []) return (
    Drop to upload files
+
- {crumbs ? ( + {crumbs && moduleRootPath ? ( updateCurrentPath("/", undefined, true)} + homeOnClick={() => redirect(moduleRootPath)} showDropDown={!desktop} /> ) : null}
- + {heading}
@@ -603,6 +663,7 @@ const FilesTableView = ({ - )} - {validBulkOps.indexOf("delete") >= 0 && ( - - )} - - )} + +
+ {selectedCids.length > 0 && ( + <> + {validBulkOps.indexOf("move") >= 0 && ( + + )} + {validBulkOps.indexOf("recover") >= 0 && ( + + )} + {validBulkOps.indexOf("delete") >= 0 && ( + + )} + + )} +
))} {items.map((file, index) => ( - { - handleRename && (await handleRename(path, newPath)) + handleRename={async (cid: string, newName: string) => { + handleRename && (await handleRename(cid, newName)) setEditing(undefined) }} - handleMove={handleMove} deleteFile={() => { setSelectedCids([file.cid]) setIsDeleteModalOpen(true) }} - recoverFile={recoverFile} - downloadFile={downloadFile} viewFolder={handleViewFolder} - handleUploadOnDrop={handleUploadOnDrop} setPreviewFileIndex={setPreviewFileIndex} moveFile={() => { setSelectedCids([file.cid]) @@ -848,6 +914,7 @@ const FilesTableView = ({ itemOperations={getItemOperations(file.content_type)} resetSelectedFiles={resetSelectedCids} browserView="table" + recoverFile={() => recoverItems && recoverItems([file.cid])} /> ))} @@ -860,15 +927,15 @@ const FilesTableView = ({ )} > {items.map((file, index) => ( - { setSelectedCids([file.cid]) setIsDeleteModalOpen(true) }} - recoverFile={recoverFile} - downloadFile={downloadFile} - viewFolder={viewFolder} - handleUploadOnDrop={handleUploadOnDrop} setPreviewFileIndex={setPreviewFileIndex} moveFile={() => { setSelectedCids([file.cid]) @@ -898,7 +960,7 @@ const FilesTableView = ({ ))} )} - {files && previewFileIndex !== undefined && ( + {files && previewFileIndex !== undefined && bucket && ( 0 ? setPreviousPreview : undefined} - path={ - isSearch && getPath - ? getPath(files[previewFileIndex].cid) - : undefined - } + path={isSearch && getPath ? getPath(files[previewFileIndex].cid) : getPathWithFile(currentPath, files[previewFileIndex].name)} /> )} { + e.preventDefault() + e.stopPropagation() + }} /> - setCreateFolderModalOpen(false)} - /> - setIsUploadModalOpen(false)} - /> - { - setIsMoveFileModalOpen(false) - setSelectedCids([]) - }} - onCancel={() => setIsMoveFileModalOpen(false)} - /> + { + refreshContents && ( + <> + setCreateFolderModalOpen(false)} + /> + setIsUploadModalOpen(false)} + /> + { + setIsMoveFileModalOpen(false) + setSelectedCids([]) + }} + onCancel={() => setIsMoveFileModalOpen(false)} + /> + + ) + } + setFileInfoPath(undefined)} @@ -957,4 +1025,4 @@ const FilesTableView = ({ ) } -export default FilesTableView +export default FilesList diff --git a/packages/files-ui/src/Components/Modules/FilePreviewModal.tsx b/packages/files-ui/src/Components/Modules/FilePreviewModal.tsx index fe11dfa372..b0412d36ce 100644 --- a/packages/files-ui/src/Components/Modules/FilePreviewModal.tsx +++ b/packages/files-ui/src/Components/Modules/FilePreviewModal.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef } from "react" import { useState } from "react" import { createStyles, makeStyles, useThemeSwitcher } from "@chainsafe/common-theme" -import { FileSystemItem, useDrive } from "../../Contexts/DriveContext" +import { FileSystemItem, useFiles } from "../../Contexts/FilesContext" import MimeMatcher from "./../../Utils/MimeMatcher" import axios, { CancelTokenSource } from "axios" import { @@ -30,6 +30,7 @@ import MarkdownPreview from "./PreviewRenderers/MarkdownPreview" import { useHotkeys } from "react-hotkeys-hook" import { t, Trans } from "@lingui/macro" import { CSFTheme } from "../../Themes/types" +import { useFileBrowser } from "../../Contexts/FileBrowserContext" export interface IPreviewRendererProps { contents: Blob @@ -152,16 +153,17 @@ const useStyles = makeStyles( ) interface Props { - file?: FileSystemItem + file: FileSystemItem nextFile?: () => void previousFile?: () => void closePreview: () => void - path?: string + path: string } const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: Props) => { const classes = useStyles() - const { getFileContent, downloadFile } = useDrive() + const { getFileContent, downloadFile } = useFiles() + const { bucket } = useFileBrowser() const { desktop } = useThemeSwitcher() const [isLoading, setIsLoading] = useState(false) const [loadingProgress, setLoadingProgress] = useState(0) @@ -185,7 +187,7 @@ const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: useEffect(() => { const getContents = async () => { - if (!cid || !size) return + if (!cid || !size || !bucket) return if (source.current) { source.current.cancel("Cancelling previous request") @@ -197,7 +199,7 @@ const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: setError(undefined) try { - const content = await getFileContent({ + const content = await getFileContent(bucket.id, { cid, cancelToken: token, onDownloadProgress: (evt) => { @@ -227,7 +229,7 @@ const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: if (content_type && compatibleFilesMatcher.match(content_type)) { getContents() } - }, [cid, size, content_type, getFileContent, file, path]) + }, [cid, size, content_type, getFileContent, file, path, bucket]) const validRendererMimeType = content_type && @@ -262,7 +264,7 @@ const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: }) const handleDownload = () => { - if (!name || !cid) return + if (!name || !cid || !bucket) return if (fileContent) { const link = document.createElement("a") link.href = URL.createObjectURL(fileContent) @@ -270,7 +272,7 @@ const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: link.click() URL.revokeObjectURL(link.href) } else { - downloadFile(cid) + downloadFile(bucket.id, file, path) } } @@ -426,7 +428,7 @@ const FilePreviewModal = ({ file, nextFile, previousFile, closePreview, path }: diff --git a/packages/files-ui/src/Components/Modules/LoginModule/AuthenticationFactors.tsx b/packages/files-ui/src/Components/Modules/LoginModule/AuthenticationFactors.tsx index 75d26bfc2d..a79feddf2b 100644 --- a/packages/files-ui/src/Components/Modules/LoginModule/AuthenticationFactors.tsx +++ b/packages/files-ui/src/Components/Modules/LoginModule/AuthenticationFactors.tsx @@ -16,7 +16,6 @@ const useStyles = makeStyles(({ breakpoints, constants, typography, palette, zIn width: "100vw", [breakpoints.up("md")]: { maxWidth: 580, - minHeight: "64vh", padding: `${constants.generalUnit * 6.5}px ${constants.generalUnit * 5}px` }, [breakpoints.down("md")]: { diff --git a/packages/files-ui/src/Components/Modules/LoginModule/InitialScreen.tsx b/packages/files-ui/src/Components/Modules/LoginModule/InitialScreen.tsx index ca4bf9a65c..ab454167e2 100644 --- a/packages/files-ui/src/Components/Modules/LoginModule/InitialScreen.tsx +++ b/packages/files-ui/src/Components/Modules/LoginModule/InitialScreen.tsx @@ -3,7 +3,7 @@ import { Button, FacebookLogoIcon, GithubLogoIcon, GoogleLogoIcon, Loading, Typo import { createStyles, makeStyles, useThemeSwitcher } from "@chainsafe/common-theme" import { CSFTheme } from "../../../Themes/types" import { t, Trans } from "@lingui/macro" -import { useImployApi } from "@chainsafe/common-contexts" +import { useFilesApi } from "@chainsafe/common-contexts" import { useWeb3 } from "@chainsafe/web3-context" import { useThresholdKey } from "../../../Contexts/ThresholdKeyContext" import { LOGIN_TYPE } from "@toruslabs/torus-direct-web-sdk" @@ -98,7 +98,6 @@ const useStyles = makeStyles( marginRight: constants.generalUnit * 3.5 }, [breakpoints.down("md")]: { - // TODO: confirm how to move this around display: "none" } }, @@ -112,7 +111,6 @@ const useStyles = makeStyles( fontWeight: 400 }, [breakpoints.down("md")]: { - // TODO: confirm how to move this around display: "none" } }, @@ -138,7 +136,7 @@ interface IInitialScreen { } const InitialScreen = ({ className }: IInitialScreen) => { - const { selectWallet, resetAndSelectWallet } = useImployApi() + const { selectWallet, resetAndSelectWallet } = useFilesApi() const { desktop } = useThemeSwitcher() const { wallet } = useWeb3() const { login, status, resetStatus } = useThresholdKey() @@ -254,6 +252,7 @@ const InitialScreen = ({ className }: IInitialScreen) => { )} - - - - ) -} - -export default SetMasterKeySlide diff --git a/packages/files-ui/src/Components/Modules/PreviewRenderers/PDFPreview.tsx b/packages/files-ui/src/Components/Modules/PreviewRenderers/PDFPreview.tsx index 6743f4a39f..e0e45f883f 100644 --- a/packages/files-ui/src/Components/Modules/PreviewRenderers/PDFPreview.tsx +++ b/packages/files-ui/src/Components/Modules/PreviewRenderers/PDFPreview.tsx @@ -1,11 +1,12 @@ import React, { useEffect, useState } from "react" import { IPreviewRendererProps } from "../FilePreviewModal" import { makeStyles, ITheme, createStyles } from "@chainsafe/common-theme" -import { Document, Page } from "react-pdf" - +import { Document, Page, pdfjs } from "react-pdf" import { Button, Typography } from "@chainsafe/common-components" import { Trans } from "@lingui/macro" +pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.js" + const useStyles = makeStyles(({ constants, palette, zIndex }: ITheme) => createStyles({ controlsContainer: { diff --git a/packages/files-ui/src/Components/Modules/SearchModule.tsx b/packages/files-ui/src/Components/Modules/SearchModule.tsx index bcd73b090d..7c50e4a463 100644 --- a/packages/files-ui/src/Components/Modules/SearchModule.tsx +++ b/packages/files-ui/src/Components/Modules/SearchModule.tsx @@ -5,22 +5,29 @@ import { useOnClickOutside, useThemeSwitcher } from "@chainsafe/common-theme" -import React, { ChangeEvent, useCallback, useRef } from "react" +import React, { ChangeEvent, useCallback, useMemo, useRef } from "react" import { ArrowLeftIcon, Button, SearchBar, Typography, - useHistory + useHistory, + useToaster } from "@chainsafe/common-components" import { useState } from "react" import clsx from "clsx" import { ROUTE_LINKS } from "../FilesRoutes" -import { useDrive, SearchEntry } from "../../Contexts/DriveContext" +import { useFiles, BucketType, SearchEntry } from "../../Contexts/FilesContext" import { CONTENT_TYPES } from "../../Utils/Constants" -import { getParentPathFromFilePath } from "../../Utils/pathUtils" +import { getArrayOfPaths, getParentPathFromFilePath, getURISafePathFromArray } from "../../Utils/pathUtils" import { t, Trans } from "@lingui/macro" import { CSFTheme } from "../../Themes/types" +import { useFilesApi } from "@chainsafe/common-contexts" + +export interface SearchParams { + bucketType: BucketType + bucketId: string +} const useStyles = makeStyles( ({ breakpoints, palette, constants, animation, zIndex, shadows }: CSFTheme) => @@ -151,7 +158,26 @@ const SearchModule: React.FC = ({ const [searchQuery, setSearchQuery] = useState("") const [searchResults, setSearchResults] = useState<{results: SearchEntry[]; query: string} | undefined>(undefined) const ref = useRef(null) - const { getSearchResults, currentSearchBucket } = useDrive() + const { buckets } = useFiles() + const { addToastMessage } = useToaster() + const { filesApiClient } = useFilesApi() + const bucket = useMemo(() => buckets.find(b => b.type === "csf"), [buckets]) + + const getSearchResults = useCallback(async (searchString: string) => { + try { + if (!searchString || !bucket) return [] + + const results = await filesApiClient.searchFiles({ bucket_id: bucket.id, query: searchString }) + return results + } catch (err) { + addToastMessage({ + message: t`There was an error getting search results`, + appearance: "error" + }) + return Promise.reject(err) + } + }, [addToastMessage, bucket, filesApiClient]) + const { redirect } = useHistory() @@ -166,9 +192,7 @@ const SearchModule: React.FC = ({ // TODO useCallback is maybe not needed here // eslint-disable-next-line react-hooks/exhaustive-deps - const debouncedSearch = useCallback(debounce(onSearch, 400), [ - currentSearchBucket?.bucketId - ]) + const debouncedSearch = useCallback(debounce(onSearch, 400), [getSearchResults]) const onSearchChange = (searchString: string) => { setSearchQuery(searchString) @@ -184,7 +208,7 @@ const SearchModule: React.FC = ({ const onSearchSubmit = (e: React.FormEvent) => { e.preventDefault() setSearchActive(false) - redirect(ROUTE_LINKS.Search(searchQuery)) + redirect(ROUTE_LINKS.Search(encodeURIComponent(searchQuery))) } const searchResultsFiles = searchResults?.results.filter( @@ -198,13 +222,13 @@ const SearchModule: React.FC = ({ ) const onSearchEntryClickFolder = (searchEntry: SearchEntry) => { - redirect(ROUTE_LINKS.Home(searchEntry.path)) + redirect(ROUTE_LINKS.Drive(getURISafePathFromArray(getArrayOfPaths(searchEntry.path)))) setSearchQuery("") setSearchActive(false) } const onSearchEntryClickFile = (searchEntry: SearchEntry) => { - redirect(ROUTE_LINKS.Home(getParentPathFromFilePath(searchEntry.path))) + redirect(ROUTE_LINKS.Drive(getURISafePathFromArray(getArrayOfPaths(getParentPathFromFilePath(searchEntry.path))))) setSearchQuery("") setSearchActive(false) } @@ -319,3 +343,4 @@ const SearchModule: React.FC = ({ } export default SearchModule + diff --git a/packages/files-ui/src/Components/Modules/Settings/Plan.tsx b/packages/files-ui/src/Components/Modules/Settings/Plan.tsx index f863d05244..91600b04d1 100644 --- a/packages/files-ui/src/Components/Modules/Settings/Plan.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/Plan.tsx @@ -10,7 +10,7 @@ import { import { makeStyles, ITheme, createStyles } from "@chainsafe/common-theme" import clsx from "clsx" import { FREE_PLAN_LIMIT } from "../../../Utils/Constants" -import { useDrive } from "../../../Contexts/DriveContext" +import { useFiles } from "../../../Contexts/FilesContext" import { Trans } from "@lingui/macro" import { ROUTE_LINKS } from "../../FilesRoutes" @@ -74,7 +74,7 @@ const useStyles = makeStyles((theme: ITheme) => const PlanView: React.FC = () => { const classes = useStyles() - const { spaceUsed } = useDrive() + const { spaceUsed } = useFiles() return ( diff --git a/packages/files-ui/src/Components/Modules/Settings/Profile.tsx b/packages/files-ui/src/Components/Modules/Settings/Profile.tsx index 24860ba8b0..d8a48e6b28 100644 --- a/packages/files-ui/src/Components/Modules/Settings/Profile.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/Profile.tsx @@ -185,8 +185,6 @@ const ProfileView = () => {
{ >
{profile?.publicAddress ? ( -
+
{
*/} -
- +
+ Display Settings { + lg={6} + > + lg={6} + >