From 4a1e18ac656393f221ef3e32a2acc60cd707fbdd Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Tue, 20 Jun 2023 11:03:51 +0800 Subject: [PATCH] Shift fetching + reading of buckets to RQ --- .../layouts/StorageLayout/StorageLayout.tsx | 13 +++-- .../layouts/StorageLayout/StorageMenu.tsx | 6 ++- .../StoragePolicies/StoragePolicies.js | 9 +++- studio/data/storage/buckets-query.ts | 51 +++++++++++++++++++ studio/data/storage/keys.ts | 3 ++ .../[ref]/storage/buckets/[bucketId].tsx | 28 ++++------ .../project/[ref]/storage/buckets/index.tsx | 15 ++---- 7 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 studio/data/storage/buckets-query.ts create mode 100644 studio/data/storage/keys.ts diff --git a/studio/components/layouts/StorageLayout/StorageLayout.tsx b/studio/components/layouts/StorageLayout/StorageLayout.tsx index cc753c05347..59d257f7d9f 100644 --- a/studio/components/layouts/StorageLayout/StorageLayout.tsx +++ b/studio/components/layouts/StorageLayout/StorageLayout.tsx @@ -11,6 +11,7 @@ import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStor import { formatPoliciesForStorage } from 'components/to-be-cleaned/Storage/Storage.utils' import DeleteBucketModal from 'components/to-be-cleaned/Storage/DeleteBucketModal' import { PROJECT_STATUS } from 'lib/constants' +import { useBucketsQuery } from 'data/storage/buckets-query' interface Props { title: string @@ -21,13 +22,11 @@ const StorageLayout: FC = ({ title, children }) => { const { ui, meta } = useStore() const { ref: projectRef } = useParams() const storageExplorerStore = useStorageStore() - const { - selectedBucketToEdit, - closeDeleteBucketModal, - showDeleteBucketModal, - deleteBucket, - buckets, - } = storageExplorerStore || {} + const { selectedBucketToEdit, closeDeleteBucketModal, showDeleteBucketModal, deleteBucket } = + storageExplorerStore || {} + + const { data } = useBucketsQuery({ projectRef }) + const buckets = data ?? [] const { data: settings, isLoading } = useProjectApiQuery({ projectRef }) const apiService = settings?.autoApiService diff --git a/studio/components/layouts/StorageLayout/StorageMenu.tsx b/studio/components/layouts/StorageLayout/StorageMenu.tsx index bfbca13590a..218b9a947b6 100644 --- a/studio/components/layouts/StorageLayout/StorageMenu.tsx +++ b/studio/components/layouts/StorageLayout/StorageMenu.tsx @@ -14,6 +14,7 @@ import { StorageBucket } from 'components/interfaces/Storage/Storage.types' import EditBucketModal from 'components/interfaces/Storage/EditBucketModal' import CreateBucketModal from 'components/interfaces/Storage/CreateBucketModal' import ShimmeringLoader from 'components/ui/ShimmeringLoader' +import { useBucketsQuery } from 'data/storage/buckets-query' interface Props {} @@ -32,7 +33,10 @@ const StorageMenu: FC = () => { | 'logs' const storageExplorerStore = useStorageStore() - const { loaded, buckets, openDeleteBucketModal } = storageExplorerStore || {} + const { data } = useBucketsQuery({ projectRef: ref }) + const { loaded, openDeleteBucketModal } = storageExplorerStore || {} + + const buckets = data ?? [] return ( <> diff --git a/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePolicies.js b/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePolicies.js index b2f1b57d8af..f47e0ed45ad 100644 --- a/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePolicies.js +++ b/studio/components/to-be-cleaned/Storage/StoragePolicies/StoragePolicies.js @@ -12,11 +12,18 @@ import ConfirmModal from 'components/ui/Dialogs/ConfirmDialog' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { PolicyEditorModal } from 'components/interfaces/Auth/Policies' +import { useBucketsQuery } from 'data/storage/buckets-query' +import { useParams } from 'common' const StoragePolicies = () => { const { ui, meta } = useStore() + const { ref: projectRef } = useParams() + const storageStore = useStorageStore() - const { loaded, buckets } = storageStore + const { loaded } = storageStore + + const { data } = useBucketsQuery({ projectRef }) + const buckets = data ?? [] const roles = meta.roles.list((role) => !meta.roles.systemRoles.includes(role.name)) diff --git a/studio/data/storage/buckets-query.ts b/studio/data/storage/buckets-query.ts new file mode 100644 index 00000000000..012f2149969 --- /dev/null +++ b/studio/data/storage/buckets-query.ts @@ -0,0 +1,51 @@ +import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' +import { get } from 'lib/common/fetch' +import { API_URL, IS_PLATFORM } from 'lib/constants' +import { useCallback } from 'react' +import { storageKeys } from './keys' + +export type BucketsVariables = { projectRef?: string } + +export type BucketsResponse = { + id: string + name: string + owner: string + public: boolean + created_at: string + updated_at: string + file_size_limit: null | number + allowed_mime_types: null | string[] +} + +export async function getBuckets({ projectRef }: BucketsVariables, signal?: AbortSignal) { + if (!projectRef) throw new Error('projectRef is required') + + const response = await get(`${API_URL}/storage/${projectRef}/buckets`, { signal }) + if (response.error) throw response.error + return response as BucketsResponse[] +} + +export type BucketsData = Awaited> +export type BucketsError = unknown + +export const useBucketsQuery = ( + { projectRef }: BucketsVariables, + { enabled = true, ...options }: UseQueryOptions = {} +) => + useQuery( + storageKeys.buckets(projectRef), + ({ signal }) => getBuckets({ projectRef }, signal), + { enabled: IS_PLATFORM && enabled && typeof projectRef !== 'undefined', ...options } + ) + +export const useBucketsPrefetch = ({ projectRef }: BucketsVariables) => { + const client = useQueryClient() + + return useCallback(() => { + if (projectRef) { + client.prefetchQuery(storageKeys.buckets(projectRef), ({ signal }) => + getBuckets({ projectRef }, signal) + ) + } + }, [projectRef]) +} diff --git a/studio/data/storage/keys.ts b/studio/data/storage/keys.ts new file mode 100644 index 00000000000..112eff0e10b --- /dev/null +++ b/studio/data/storage/keys.ts @@ -0,0 +1,3 @@ +export const storageKeys = { + buckets: (projectRef: string | undefined) => ['projects', projectRef, 'buckets'] as const, +} diff --git a/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx b/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx index 1486d50d11a..2d3d0c06987 100644 --- a/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx +++ b/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx @@ -1,30 +1,24 @@ -import React, { useEffect } from 'react' -import { useRouter } from 'next/router' -import { observer } from 'mobx-react-lite' import { find } from 'lodash' +import { observer } from 'mobx-react-lite' +import { useEffect } from 'react' -import { API_URL } from 'lib/constants' +import { useParams } from 'common' +import { StorageLayout } from 'components/layouts' +import { StorageExplorer } from 'components/to-be-cleaned/Storage' +import { useBucketsQuery } from 'data/storage/buckets-query' import { useFlag, useStore } from 'hooks' import { post } from 'lib/common/fetch' -import { PROJECT_STATUS } from 'lib/constants' -import { StorageLayout } from 'components/layouts' -import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' -import { StorageExplorer } from 'components/to-be-cleaned/Storage' -import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' +import { API_URL, PROJECT_STATUS } from 'lib/constants' import { NextPageWithLayout } from 'types' -/** - * PageLayout is used to setup layout - as usual it will requires inject global store - */ const PageLayout: NextPageWithLayout = () => { - const router = useRouter() - const { ref, bucketId } = router.query + const { ref, bucketId } = useParams() const { ui } = useStore() const project = ui.selectedProject - const storageStore = useStorageStore() - const { buckets, loaded } = storageStore + const { data, isSuccess } = useBucketsQuery({ projectRef: ref }) + const buckets = data ?? [] const kpsEnabled = useFlag('initWithKps') @@ -40,7 +34,7 @@ const PageLayout: NextPageWithLayout = () => { return (
- {loaded ? ( + {isSuccess ? ( !bucket ? (

Bucket {bucketId} cannot be found

diff --git a/studio/pages/project/[ref]/storage/buckets/index.tsx b/studio/pages/project/[ref]/storage/buckets/index.tsx index 9b9cdef63f9..dc5752c423a 100644 --- a/studio/pages/project/[ref]/storage/buckets/index.tsx +++ b/studio/pages/project/[ref]/storage/buckets/index.tsx @@ -1,18 +1,13 @@ -import React, { useEffect } from 'react' -import { observer } from 'mobx-react-lite' - -import { API_URL } from 'lib/constants' -import { useFlag, useStore } from 'hooks' import { useParams } from 'common/hooks' -import { post } from 'lib/common/fetch' -import { PROJECT_STATUS } from 'lib/constants' import { StorageLayout } from 'components/layouts' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' +import { useFlag, useStore } from 'hooks' +import { post } from 'lib/common/fetch' +import { API_URL, PROJECT_STATUS } from 'lib/constants' +import { observer } from 'mobx-react-lite' +import { useEffect } from 'react' import { NextPageWithLayout } from 'types' -/** - * PageLayout is used to setup layout - as usual it will requires inject global store - */ const PageLayout: NextPageWithLayout = ({}) => { const { ref } = useParams() const { ui } = useStore()