diff --git a/packages/files-ui/src/Components/Elements/RestrictedModeBanner.tsx b/packages/files-ui/src/Components/Elements/RestrictedModeBanner.tsx
new file mode 100644
index 0000000000..c1b6bbc39f
--- /dev/null
+++ b/packages/files-ui/src/Components/Elements/RestrictedModeBanner.tsx
@@ -0,0 +1,49 @@
+import { Typography, Button, useHistory } from "@chainsafe/common-components"
+import { createStyles, makeStyles, useThemeSwitcher } from "@chainsafe/common-theme"
+import { Trans } from "@lingui/macro"
+import React from "react"
+import { CSFTheme } from "../../Themes/types"
+import { ROUTE_LINKS } from "../FilesRoutes"
+
+const useStyles = makeStyles(
+ ({ breakpoints, constants, palette }: CSFTheme) => {
+ return createStyles({
+ accountRestrictedNotification: {
+ position: "fixed",
+ bottom: 0,
+ backgroundColor: palette.additional["gray"][10],
+ color: palette.additional["gray"][1],
+ padding: `${constants.generalUnit * 2}px ${constants.generalUnit * 3}px`,
+ left: 0,
+ width: "100vw",
+ [breakpoints.up("md")]: {
+ left: `${constants.navWidth}px`,
+ width:`calc(100vw - ${constants.navWidth}px)`,
+ display: "flex",
+ justifyContent: "space-between",
+ alignItems: "center"
+ }
+ }
+ })
+ }
+)
+
+const RestrictedModeBanner = () => {
+ const classes = useStyles()
+ const { desktop } = useThemeSwitcher()
+ const { redirect } = useHistory()
+
+ return (
+
+
+ You've got a payment due. Until you've settled up, we've placed your account in restricted mode
+
+
+
)
+}
+
+export default RestrictedModeBanner
\ No newline at end of file
diff --git a/packages/files-ui/src/Components/Layouts/AppWrapper.tsx b/packages/files-ui/src/Components/Layouts/AppWrapper.tsx
index e9da33b95c..90d6e5891a 100644
--- a/packages/files-ui/src/Components/Layouts/AppWrapper.tsx
+++ b/packages/files-ui/src/Components/Layouts/AppWrapper.tsx
@@ -24,7 +24,6 @@ const useStyles = makeStyles(
padding: "0",
"&.active": {
// This moves the content areas based on the size of the nav bar
-
padding: `${0}px ${constants.contentPadding}px ${0}px ${
Number(constants.navWidth) +
Number(constants.contentPadding)
@@ -34,20 +33,18 @@ const useStyles = makeStyles(
[breakpoints.down("md")]: {}
},
content: {
+ height: "initial",
[breakpoints.up("md")]: {
height: "100%",
minHeight: "100vh",
transitionDuration: `${animation.translate}ms`,
- padding: 0,
"&.active": {
- height: "initial",
padding: `${constants.contentTopPadding}px 0 0`
}
},
[breakpoints.down("md")]: {
minHeight: "100vh",
"&.active": {
- height: "initial",
padding: `${constants.mobileHeaderHeight}px 0 0`
}
}
@@ -84,14 +81,16 @@ const AppWrapper: React.FC = ({ children }: IAppWrapper) => {
setNavOpen={setNavOpen}
/>
diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx
index 1727cbb873..56f6d88d0f 100644
--- a/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx
+++ b/packages/files-ui/src/Components/Modules/FileBrowsers/CSFFileBrowser.tsx
@@ -25,6 +25,7 @@ import getFilesFromDataTransferItems from "../../../Utils/getFilesFromDataTransf
const CSFFileBrowser: React.FC = () => {
const { downloadFile, uploadFiles, buckets } = useFiles()
+ const { accountRestricted } = useFilesApi()
const { filesApiClient } = useFilesApi()
const { addToast } = useToasts()
const [loadingCurrentPath, setLoadingCurrentPath] = useState(false)
@@ -92,12 +93,11 @@ const CSFFileBrowser: React.FC = () => {
const message = `${
itemToDelete.isFolder ? t`Folder` : t`File`
} ${t`deleted successfully`}`
- const id = addToast({
+ addToast({
title: message,
type: "success",
testId: "deletion-success"
})
- console.log(id)
}
return Promise.resolve()
} catch (error) {
@@ -176,12 +176,20 @@ const CSFFileBrowser: React.FC = () => {
const handleUploadOnDrop = useCallback(async (files: File[], fileItems: DataTransferItemList, path: string) => {
if (!bucket) return
+ if (accountRestricted) {
+ addToast({
+ type:"error",
+ title: t`Uploads disabled`,
+ subtitle: t`Oops! You need to pay for this month to upload more content.`
+ })
+ 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), getPathWithFile(path, p))
})
- }, [uploadFiles, bucket])
+ }, [uploadFiles, bucket, accountRestricted, addToast])
const viewFolder = useCallback((cid: string) => {
const fileSystemItem = pathContents.find(f => f.cid === cid)
diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx
index 7b7bc01bc5..090032121f 100644
--- a/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx
+++ b/packages/files-ui/src/Components/Modules/FileBrowsers/ShareModal.tsx
@@ -14,6 +14,7 @@ import { useFileBrowser } from "../../../Contexts/FileBrowserContext"
import clsx from "clsx"
import { useEffect } from "react"
import { nameValidator } from "../../../Utils/validationSchema"
+import { useFilesApi } from "../../../Contexts/FilesApiContext"
const useStyles = makeStyles(
({ breakpoints, constants, palette, typography, zIndex }: CSFTheme) => {
@@ -188,6 +189,7 @@ interface IShareFileProps {
const ShareModal = ({ close, file, filePath }: IShareFileProps) => {
const classes = useStyles()
const { handleCreateSharedFolder } = useCreateOrEditSharedFolder()
+ const { accountRestricted } = useFilesApi()
const [sharedFolderName, setSharedFolderName] = useState("")
const { sharedFolderReaders, sharedFolderWriters, handleLookupUser, onNewUsers, usersError, resetUsers } = useLookupSharedFolderUser()
const [isUsingCurrentBucket, setIsUsingCurrentBucket] = useState(true)
@@ -213,14 +215,16 @@ const ShareModal = ({ close, file, filePath }: IShareFileProps) => {
.filter(buck => buck.type === "share" || buck.type === "csf")
// filter out the current bucket
.filter(buck => buck.id !== bucket?.id)
- // all buckets where the user is reader or writer
+ // all buckets where the user is owner or writer
.filter(buck => !!buck.writers.find((w) => w.uuid === profile.userId) || !!buck.owners.find((o) => o.uuid === profile.userId))
+ // filter out CSF and share buckets where user is an owner if their account is restricted
+ .filter(buck => !(!!accountRestricted && (buck.type === "csf" || !!buck.owners.find(o => o.uuid === profile.userId))))
.map(buck => ({
label: buck.name || t`Home`,
value: buck.id
}))
}
- , [bucket, buckets, profile])
+ , [bucket, buckets, profile, accountRestricted])
const hasNoSharedBucket = useMemo(() => bucketsOptions.length === 0, [bucketsOptions.length])
@@ -232,10 +236,10 @@ const ShareModal = ({ close, file, filePath }: IShareFileProps) => {
// if the user has no shared bucket, we default to new folder creation
useEffect(() => {
- if (hasNoSharedBucket) {
+ if (hasNoSharedBucket && !accountRestricted) {
setIsUsingCurrentBucket(false)
}
- }, [hasNoSharedBucket])
+ }, [hasNoSharedBucket, accountRestricted])
const onNameChange = useCallback((value?: string | number) => {
if (value === undefined) return
diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx
index 2697dd1b98..54523d8fc6 100644
--- a/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx
+++ b/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFileBrowser.tsx
@@ -18,10 +18,11 @@ import { useFilesApi } from "../../../Contexts/FilesApiContext"
import { useUser } from "../../../Contexts/UserContext"
import DragAndDrop from "../../../Contexts/DnDContext"
import FilesList from "./views/FilesList"
+import getFilesFromDataTransferItems from "../../../Utils/getFilesFromDataTransferItems"
const SharedFileBrowser = () => {
const { downloadFile, uploadFiles, buckets, refreshBuckets, getStorageSummary } = useFiles()
- const { filesApiClient } = useFilesApi()
+ const { filesApiClient, accountRestricted } = useFilesApi()
const { addToast } = useToasts()
const [loadingCurrentPath, setLoadingCurrentPath] = useState(false)
const [pathContents, setPathContents] = useState([])
@@ -179,23 +180,20 @@ const SharedFileBrowser = () => {
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) {
+ if (accountRestricted) {
addToast({
- title: t`Folder uploads are not supported currently`,
- type: "error"
+ type:"error",
+ title: t`Unable to upload`,
+ subtitle: t`Oops! You need to pay for this month to upload more content.`
})
- } else {
- uploadFiles(bucket, files, path)
- .then(() => refreshContents())
- .catch(console.error)
+ return
}
- }, [addToast, uploadFiles, bucket, refreshContents])
+ 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), getPathWithFile(path, p))
+ })
+ }, [uploadFiles, bucket, accountRestricted, addToast])
const bulkOperations: IBulkOperations = useMemo(() => ({
[CONTENT_TYPES.Directory]: ["download", "move", "delete"],
diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFoldersOverview.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFoldersOverview.tsx
index 3e6f46d8b9..033606c183 100644
--- a/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFoldersOverview.tsx
+++ b/packages/files-ui/src/Components/Modules/FileBrowsers/SharedFoldersOverview.tsx
@@ -26,6 +26,7 @@ import { SharedFolderModalMode } from "./types"
import SharingExplainerModal from "../../SharingExplainerModal"
import { useSharingExplainerModalFlag } from "./hooks/useSharingExplainerModalFlag"
import { usePageTrack } from "../../../Contexts/PosthogContext"
+import RestrictedModeBanner from "../../Elements/RestrictedModeBanner"
export const desktopSharedGridSettings = "69px 3fr 120px 190px 150px 45px !important"
export const mobileSharedGridSettings = "3fr 80px 45px !important"
@@ -38,7 +39,10 @@ const useStyles = makeStyles(
position: "relative",
[breakpoints.down("md")]: {
marginLeft: constants.generalUnit * 2,
- marginRight: constants.generalUnit * 2
+ marginRight: constants.generalUnit * 2,
+ "&.bottomBanner": {
+ paddingBottom: constants.bottomBannerMobileHeight
+ }
},
[breakpoints.up("md")]: {
border: "1px solid transparent",
@@ -47,6 +51,10 @@ const useStyles = makeStyles(
minHeight: `calc(100vh - ${Number(constants.contentTopPadding)}px)`,
"&.droppable": {
borderColor: palette.additional["geekblue"][4]
+ },
+ "&.bottomBanner": {
+ minHeight: `calc(100vh - ${Number(constants.contentTopPadding) + Number(constants.bottomBannerHeight)}px)`,
+ paddingBottom: constants.bottomBannerHeight
}
}
},
@@ -108,7 +116,7 @@ type SortingType = "name" | "size" | "date_uploaded"
const SharedFolderOverview = () => {
const classes = useStyles()
- const { filesApiClient } = useFilesApi()
+ const { filesApiClient, accountRestricted } = useFilesApi()
const { buckets, isLoadingBuckets, refreshBuckets } = useFiles()
const [createOrEditSharedFolderMode, setCreateOrEditSharedFolderMode] = useState(undefined)
const [bucketToEdit, setBucketToEdit] = useState(undefined)
@@ -160,10 +168,13 @@ const SharedFolderOverview = () => {
const openSharedFolder = useCallback((bucketId: string) => {
redirect(ROUTE_LINKS.SharedFolderExplorer(bucketId, "/"))
}, [redirect])
+
return (
<>
{
setBucketToEdit(undefined)
setCreateOrEditSharedFolderMode("create")
}}
+ disabled={accountRestricted}
>
Create a Shared Folder
@@ -294,6 +306,9 @@ const SharedFolderOverview = () => {
injectedClass={{ inner: classes.confirmDeletionDialog }}
testId="shared-folder-deletion"
/>
+ {accountRestricted &&
+
+ }
>
)
}
diff --git a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx
index e46746314f..b2e7da0af3 100644
--- a/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx
+++ b/packages/files-ui/src/Components/Modules/FileBrowsers/views/FilesList.tsx
@@ -53,6 +53,8 @@ import SharedUsers from "../../../Elements/SharedUsers"
import Menu from "../../../../UI-components/Menu"
import SharingExplainerModal from "../../../SharingExplainerModal"
import { useSharingExplainerModalFlag } from "../hooks/useSharingExplainerModalFlag"
+import { useFilesApi } from "../../../../Contexts/FilesApiContext"
+import RestrictedModeBanner from "../../../Elements/RestrictedModeBanner"
const baseOperations: FileOperation[] = ["download", "info", "preview", "share"]
const readerOperations: FileOperation[] = [...baseOperations, "report"]
@@ -73,7 +75,10 @@ const useStyles = makeStyles(
position: "relative",
[breakpoints.down("md")]: {
marginLeft: constants.generalUnit * 2,
- marginRight: constants.generalUnit * 2
+ marginRight: constants.generalUnit * 2,
+ "&.bottomBanner": {
+ paddingBottom: constants.bottomBannerMobileHeight
+ }
},
[breakpoints.up("md")]: {
border: "1px solid transparent",
@@ -82,6 +87,10 @@ const useStyles = makeStyles(
minHeight: `calc(100vh - ${Number(constants.contentTopPadding)}px)`,
"&.droppable": {
borderColor: palette.primary.main
+ },
+ "&.bottomBanner": {
+ minHeight: `calc(100vh - ${Number(constants.contentTopPadding) + Number(constants.bottomBannerHeight)}px)`,
+ paddingBottom: constants.bottomBannerHeight
}
}
},
@@ -312,6 +321,7 @@ const FilesList = ({ isShared = false }: Props) => {
const [isReportFileModalOpen, setIsReportFileModalOpen] = useState(false)
const [isFileInfoModalOpen, setIsFileInfoModalOpen] = useState(false)
const [isShareModalOpen, setIsShareModalOpen] = useState(false)
+ const { accountRestricted } = useFilesApi()
const {
heading,
@@ -626,7 +636,8 @@ const FilesList = ({ isShared = false }: Props) => {
>
),
- onClick: () => setCreateFolderModalOpen(true)
+ onClick: () => setCreateFolderModalOpen(true),
+ disabled: accountRestricted
},
{
contents: (
@@ -637,10 +648,11 @@ const FilesList = ({ isShared = false }: Props) => {
>
),
- onClick: () => setIsUploadModalOpen(true)
+ onClick: () => setIsUploadModalOpen(true),
+ disabled: accountRestricted
}
],
- [classes.menuIcon])
+ [classes.menuIcon, accountRestricted])
const onShare = useCallback((fileInfoPath: string, fileIndex: number) => {
if(hasSeenSharingExplainerModal) {
@@ -653,95 +665,58 @@ const FilesList = ({ isShared = false }: Props) => {
}, [hasSeenSharingExplainerModal])
return (
-
-
+
-
- Drop to upload files
-
-
-
-
- {crumbs && moduleRootPath && (
- redirect(moduleRootPath)}
- showDropDown={!desktop}
- />
- )}
-
-