diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx index 451c70485b8..d1b725d7477 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx @@ -6,9 +6,13 @@ import { Button, DropdownMenu, DropdownMenuContent, - DropdownMenuSeparator, DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, DropdownMenuTrigger, + IconCheck, IconChevronLeft, IconChevronRight, IconColumns, @@ -21,18 +25,14 @@ import { IconUpload, IconX, Input, - IconCheck, - DropdownMenuSub, - DropdownMenuSubTrigger, - DropdownMenuSubContent, } from 'ui' +import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import APIDocsButton from 'components/ui/APIDocsButton' import { useCheckPermissions } from 'hooks' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { useStorageExplorerStateSnapshot } from 'state/storage-explorer' import { STORAGE_SORT_BY, STORAGE_SORT_BY_ORDER, STORAGE_VIEWS } from '../Storage.constants' -import APIDocsButton from 'components/ui/APIDocsButton' -import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' const VIEW_OPTIONS = [ { key: STORAGE_VIEWS.COLUMNS, name: 'As columns' }, diff --git a/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts b/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts index 632ce1df1b2..1f400d094fc 100644 --- a/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts +++ b/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts @@ -5,6 +5,7 @@ import { BlobReader, BlobWriter, ZipWriter } from '@zip.js/zip.js' import { chunk, compact, find, findIndex, has, isEqual, some, uniq, uniqBy } from 'lodash' import { makeAutoObservable } from 'mobx' import toast from 'react-hot-toast' +import { toast as UiToast } from 'ui' import { STORAGE_ROW_STATUS, @@ -283,22 +284,13 @@ class StorageExplorerStore { if (formattedName === null) return if (!/^[a-zA-Z0-9_-\s]*$/.test(formattedName)) { - return this.ui.setNotification({ - message: 'Folder name contains invalid special characters', - category: 'error', - duration: 8000, - }) - } - /** - * todo: move this to a util file, as renameFolder() uses same logic - */ - if (formattedName.includes('/') || formattedName.includes('\\')) { - return this.ui.setNotification({ - message: 'Folder names should not have forward or back slashes.', - category: 'error', - duration: 8000, + return UiToast({ + variant: 'destructive', + description: 'Folder name contains invalid special characters', + duration: 6000, }) } + if (formattedName.length === 0) { return this.removeTempRows(columnIndex) } @@ -425,10 +417,7 @@ class StorageExplorerStore { // https://stackoverflow.com/a/53058574 getFilesDataTransferItems = async (items) => { - const toastId = this.ui.setNotification({ - category: 'loading', - message: 'Retrieving items to upload...', - }) + const { dismiss } = UiToast({ description: 'Retrieving items to upload...' }) const files = [] const queue = [] for (const item of items) { @@ -446,7 +435,7 @@ class StorageExplorerStore { queue.push(...(await this.readAllDirectoryEntries(entry.createReader()))) } } - toast.dismiss(toastId) + dismiss() return files } @@ -663,7 +652,8 @@ class StorageExplorerStore { let numberOfFilesMovedFail = 0 this.clearSelectedItems() - const infoToastId = toast('Please do not close the browser until the move is completed', { + const { dismiss } = UiToast({ + description: 'Please do not close the browser until the move is completed', duration: Infinity, }) @@ -690,20 +680,16 @@ class StorageExplorerStore { ) if (numberOfFilesMovedFail === this.selectedItemsToMove.length) { - this.ui.setNotification({ - message: 'Failed to move files', - category: 'error', - }) + UiToast({ variant: 'destructive', description: 'Failed to move files' }) } else { - this.ui.setNotification({ - message: `Successfully moved ${ + UiToast({ + description: `Successfully moved ${ this.selectedItemsToMove.length - numberOfFilesMovedFail - } to ${formattedNewPathToFile}`, - category: 'success', + } files to ${formattedNewPathToFile.length > 0 ? formattedNewPathToFile : 'the root of your bucket'}`, }) } - toast.dismiss(infoToastId) + dismiss() // Clear file preview cache if moved files exist in cache const idsOfItemsToMove = this.selectedItemsToMove.map((item) => item.id) diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx index 9e54f4ff3c8..9e96606394c 100644 --- a/apps/studio/pages/_app.tsx +++ b/apps/studio/pages/_app.tsx @@ -59,6 +59,7 @@ import { useAppStateSnapshot } from 'state/app-state' import { RootStore } from 'stores' import HCaptchaLoadedStore from 'stores/hcaptcha-loaded-store' import { AppPropsWithLayout } from 'types' +import { Toaster } from 'ui' dayjs.extend(customParseFormat) dayjs.extend(utc) @@ -182,6 +183,7 @@ function CustomApp({ Component, pageProps }: AppPropsWithLayout) { + {!isTestEnv && } diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index e4a92577b6b..77b83b88a65 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -81,6 +81,9 @@ export * from './src/components/ThemeProvider/prefixedThemes' // shadcn export * from './src/components/shadcn/ui/dropdown-menu' +export * from './src/components/shadcn/ui/use-toast' +export * from './src/components/shadcn/ui/toast' +export * from './src/components/shadcn/ui/toaster' export { Command as Command_Shadcn_, diff --git a/packages/ui/src/components/shadcn/ui/toast.tsx b/packages/ui/src/components/shadcn/ui/toast.tsx index bba0efd8c58..9f865254157 100644 --- a/packages/ui/src/components/shadcn/ui/toast.tsx +++ b/packages/ui/src/components/shadcn/ui/toast.tsx @@ -14,7 +14,7 @@ const ToastViewport = React.forwardRef<