From 5bf19d71fe72fabe53332c11ec6b2c1b875c37e2 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Fri, 8 Mar 2024 22:18:34 +0800 Subject: [PATCH] Final replacements of ui setNotification with toast --- .../SidePanelEditor/SidePanelEditor.tsx | 40 ++--- apps/studio/components/ui/ToastLoader.tsx | 27 ++++ ...lorerStore.ts => StorageExplorerStore.tsx} | 148 +++++++++--------- 3 files changed, 125 insertions(+), 90 deletions(-) create mode 100644 apps/studio/components/ui/ToastLoader.tsx rename apps/studio/localStores/storageExplorer/{StorageExplorerStore.ts => StorageExplorerStore.tsx} (95%) diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx index a1fc06afd64..fffee92bf70 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx @@ -3,13 +3,13 @@ import { useQueryClient } from '@tanstack/react-query' import { isEmpty, isUndefined, noop } from 'lodash' import { useState } from 'react' import { toast } from 'react-hot-toast' -import { Modal } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' +import { ToastLoader } from 'components/ui/ToastLoader' import { useDatabasePublicationCreateMutation } from 'data/database-publications/database-publications-create-mutation' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation' +import type { Constraint } from 'data/database/constraints-query' import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { entityTypeKeys } from 'data/entity-types/keys' import { sqlKeys } from 'data/sql/keys' @@ -17,10 +17,12 @@ import { useTableRowCreateMutation } from 'data/table-rows/table-row-create-muta import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-mutation' import { tableKeys } from 'data/tables/keys' import { getTables } from 'data/tables/tables-query' -import { useStore, useUrlState } from 'hooks' +import { useUrlState } from 'hooks' import { useGetImpersonatedRole } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' import type { Dictionary } from 'types' +import { Modal } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { ColumnEditor, RowEditor, SpreadsheetImport, TableEditor } from '.' import type { ForeignKey } from './ForeignKeySelector/ForeignKeySelector.types' import ForeignRowSelector from './RowEditor/ForeignRowSelector/ForeignRowSelector' @@ -38,7 +40,6 @@ import { updateTable, } from './SidePanelEditor.utils' import type { ImportContent } from './TableEditor/TableEditor.types' -import type { Constraint } from 'data/database/constraints-query' export interface SidePanelEditorProps { editable?: boolean @@ -59,7 +60,6 @@ const SidePanelEditor = ({ const snap = useTableEditorStateSnapshot() const [_, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] }) - const { ui } = useStore() const queryClient = useQueryClient() const { project } = useProjectContext() @@ -508,12 +508,13 @@ const SidePanelEditor = ({ selectedTable, selectedHeaders, (progress: number) => { - ui.setNotification({ - id: toastId, - progress, - category: 'loading', - message: `Adding ${rowCount.toLocaleString()} rows to ${selectedTable.name}`, - }) + toast.loading( + , + { id: toastId } + ) } ) if (res.error) { @@ -529,14 +530,15 @@ const SidePanelEditor = ({ importContent.rows, selectedHeaders, (progress: number) => { - ui.setNotification({ - id: toastId, - progress, - category: 'loading', - message: `Adding ${importContent.rows.length.toLocaleString()} rows to ${ - selectedTable.name - }`, - }) + toast.loading( + , + { id: toastId } + ) } ) if (res.error) { diff --git a/apps/studio/components/ui/ToastLoader.tsx b/apps/studio/components/ui/ToastLoader.tsx new file mode 100644 index 00000000000..6e88277acf6 --- /dev/null +++ b/apps/studio/components/ui/ToastLoader.tsx @@ -0,0 +1,27 @@ +// [Joshen] Just FYI eventually we're going to move to use toasts +// from the UI library, but this is a transition to move everything to +// react-hot-toast while we're trying to deprecate mobx entirely + +import SparkBar from './SparkBar' + +interface ToastLoaderProps { + progress: number + message: string + description?: string +} + +export const ToastLoader = ({ progress, message, description }: ToastLoaderProps) => { + return ( +
+ + {description !== undefined &&

{description}

} +
+ ) +} diff --git a/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts b/apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx similarity index 95% rename from apps/studio/localStores/storageExplorer/StorageExplorerStore.ts rename to apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx index 5581824837a..68c469b0083 100644 --- a/apps/studio/localStores/storageExplorer/StorageExplorerStore.ts +++ b/apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx @@ -1,5 +1,4 @@ // @ts-nocheck - import { createClient } from '@supabase/supabase-js' import { BlobReader, BlobWriter, ZipWriter } from '@zip.js/zip.js' import { chunk, compact, find, findIndex, has, isEqual, some, uniq, uniqBy } from 'lodash' @@ -7,6 +6,7 @@ import { makeAutoObservable } from 'mobx' import toast from 'react-hot-toast' import { toast as UiToast } from 'ui' +import { ToastLoader } from 'components/ui/ToastLoader' import { STORAGE_ROW_STATUS, STORAGE_ROW_TYPES, @@ -59,9 +59,6 @@ class StorageExplorerStore { sortBy: { column: this.sortBy, order: this.sortByOrder }, } - /* UI store */ - ui = null - /* Supabase client */ supabaseClient = null /* [Joshen] Move towards using API */ @@ -79,8 +76,6 @@ class StorageExplorerStore { constructor(projectRef) { makeAutoObservable(this, { supabaseClient: false }) this.projectRef = projectRef - // eslint-disable-next-line react-hooks/rules-of-hooks - this.ui = useStore().ui // ignore when in a non-browser environment if (typeof window !== 'undefined') { @@ -509,14 +504,15 @@ class StorageExplorerStore { .map((folder) => folder.name) .join('/') - const toastId = this.ui.setNotification({ - category: 'loading', - message: `Uploading ${formattedFilesToUpload.length} file${ - formattedFilesToUpload.length > 1 ? 's' : '' - }...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: 0, - }) + const toastId = toast.loading( + 1 ? 's' : '' + }...`} + description={STORAGE_PROGRESS_INFO_TEXT} + /> + ) // Upload files in batches const promises = formattedFilesToUpload.map((file) => { @@ -582,15 +578,16 @@ class StorageExplorerStore { await batchedPromises.reduce(async (previousPromise, nextBatch) => { await previousPromise await Promise.allSettled(nextBatch.map((batch) => batch())) - this.ui.setNotification({ - id: toastId, - category: 'loading', - message: `Uploading ${formattedFilesToUpload.length} file${ - formattedFilesToUpload.length > 1 ? 's' : '' - }...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: this.uploadProgress * 100, - }) + toast.loading( + 1 ? 's' : '' + }...`} + description={STORAGE_PROGRESS_INFO_TEXT} + />, + { id: toastId } + ) }, Promise.resolve()) if (numberOfFilesUploadedSuccess > 0) { @@ -738,12 +735,13 @@ class StorageExplorerStore { this.clearSelectedItems() - const toastId = this.ui.setNotification({ - category: 'loading', - message: `Deleting ${prefixes.length} file(s)...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: 0, - }) + const toastId = toast.loading( + + ) // batch BATCH_SIZE prefixes per request const batches = chunk(prefixes, BATCH_SIZE).map((batch) => () => { @@ -757,13 +755,14 @@ class StorageExplorerStore { await chunk(batches, BATCH_SIZE).reduce(async (previousPromise, nextBatch) => { await previousPromise await Promise.all(nextBatch.map((batch) => batch())) - this.ui.setNotification({ - id: toastId, - category: 'loading', - message: `Deleting ${prefixes.length} file(s)...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: progress * 100, - }) + toast.loading( + , + { id: toastId } + ) }, Promise.resolve()) // Clear file preview cache if deleted files exist in cache @@ -798,13 +797,14 @@ class StorageExplorerStore { const files = await this.getAllItemsAlongFolder(folder) - this.ui.setNotification({ - id: toastId, - category: 'loading', - message: `Downloading ${files.length} files...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: 0, - }) + toast.loading( + 1 ? 's' : ''}...`} + desription={STORAGE_PROGRESS_INFO_TEXT} + />, + { id: toastId } + ) const promises = files.map((file) => { const fileMimeType = file.metadata?.mimetype ?? null @@ -835,13 +835,14 @@ class StorageExplorerStore { const downloadedFiles = await batchedPromises.reduce(async (previousPromise, nextBatch) => { const previousResults = await previousPromise const batchResults = await Promise.allSettled(nextBatch.map((batch) => batch())) - this.ui.setNotification({ - id: toastId, - category: 'loading', - message: `Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: progress * 100, - }) + toast.loading( + 1 ? 's' : ''}...`} + desription={STORAGE_PROGRESS_INFO_TEXT} + />, + { id: toastId } + ) return (previousResults ?? []).concat(batchResults.map((x) => x.value).filter(Boolean)) }, Promise.resolve()) @@ -890,7 +891,9 @@ class StorageExplorerStore { let progress = 0 const returnBlob = true const showIndividualToast = false - const toastId = toast.loading(`Downloading ${files.length} files...`) + const toastId = toast.loading( + `Downloading ${files.length} file${files.length > 1 ? 's' : ''}...` + ) const promises = formattedFilesWithPrefix.map((file) => { return () => { @@ -906,13 +909,14 @@ class StorageExplorerStore { const downloadedFiles = await batchedPromises.reduce(async (previousPromise, nextBatch) => { const previousResults = await previousPromise const batchResults = await Promise.allSettled(nextBatch.map((batch) => batch())) - this.ui.setNotification({ - id: toastId, - category: 'loading', - message: `Downloading ${files.length} file${files.length > 1 ? 's' : ''}...`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: progress * 100, - }) + toast.loading( + 1 ? 's' : ''}...`} + description={STORAGE_PROGRESS_INFO_TEXT} + />, + { id: toastId } + ) return (previousResults ?? []).concat(batchResults.map((x) => x.value).filter(Boolean)) }, Promise.resolve()) @@ -1208,12 +1212,13 @@ class StorageExplorerStore { return this.updateRowStatus(originalName, STORAGE_ROW_STATUS.READY, columnIndex) } - const toastId = this.ui.setNotification({ - category: 'loading', - message: `Renaming folder to ${newName}`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: 0, - }) + const toastId = toast.loading( + + ) /** * Catch any folder names that contain slash or backslash @@ -1268,13 +1273,14 @@ class StorageExplorerStore { await batchedPromises.reduce(async (previousPromise, nextBatch) => { await previousPromise await Promise.all(nextBatch.map((batch) => batch())) - this.ui.setNotification({ - id: toastId, - category: 'loading', - message: `Renaming folder to ${newName}`, - description: STORAGE_PROGRESS_INFO_TEXT, - progress: progress * 100, - }) + toast.loader( + , + { id: toastId } + ) }, Promise.resolve()) if (!hasErrors) {