diff --git a/app/gui/src/dashboard/App.tsx b/app/gui/src/dashboard/App.tsx
index 9a6deee3dcd9..db72c7ce26fd 100644
--- a/app/gui/src/dashboard/App.tsx
+++ b/app/gui/src/dashboard/App.tsx
@@ -50,7 +50,6 @@ import * as inputBindingsModule from '#/configurations/inputBindings'
import AuthProvider, * as authProvider from '#/providers/AuthProvider'
import BackendProvider, { useLocalBackend } from '#/providers/BackendProvider'
-import DriveProvider from '#/providers/DriveProvider'
import { useHttpClientStrict } from '#/providers/HttpClientProvider'
import InputBindingsProvider from '#/providers/InputBindingsProvider'
import LocalStorageProvider, * as localStorageProvider from '#/providers/LocalStorageProvider'
@@ -98,7 +97,6 @@ import { STATIC_QUERY_OPTIONS } from '#/utilities/reactQuery'
import { useInitAuthService } from '#/authentication/service'
import { InvitedToOrganizationModal } from '#/modals/InvitedToOrganizationModal'
-import { CategoriesProvider } from './layouts/Drive/Categories/categoriesHooks'
// ============================
// === Global configuration ===
@@ -536,20 +534,14 @@ function AppRouter(props: AppRouterProps) {
onAuthenticated={onAuthenticated}
>
-
- {/* Ideally this would be in `Drive.tsx`, but it currently must be all the way out here
- * due to modals being in `TheModal`. */}
-
-
-
- {routes}
-
-
-
-
-
-
-
+
+
+ {routes}
+
+
+
+
+
diff --git a/app/gui/src/dashboard/layouts/CategorySwitcher.tsx b/app/gui/src/dashboard/layouts/CategorySwitcher.tsx
index f6b08477ba1b..278e517eece5 100644
--- a/app/gui/src/dashboard/layouts/CategorySwitcher.tsx
+++ b/app/gui/src/dashboard/layouts/CategorySwitcher.tsx
@@ -55,7 +55,7 @@ interface CategoryMetadata {
/** Props for a {@link CategorySwitcherItem}. */
interface InternalCategorySwitcherItemProps extends CategoryMetadata {
readonly currentCategory: Category
- readonly setCategory: (category: Category) => void
+ readonly setCategoryId: (categoryId: Category['id']) => void
readonly badgeContent?: React.ReactNode
readonly isDisabled: boolean
}
@@ -71,7 +71,7 @@ const CATEGORY_SWITCHER_VARIANTS = tv({
/** An entry in a {@link CategorySwitcher}. */
function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) {
- const { currentCategory, setCategory, badgeContent, isDisabled: isDisabledRaw } = props
+ const { currentCategory, setCategoryId, badgeContent, isDisabled: isDisabledRaw } = props
const { isNested = false, category, icon, label, buttonLabel, dropZoneLabel } = props
const [isTransitioning, startTransition] = React.useTransition()
@@ -126,7 +126,7 @@ function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) {
// and to not invoke the Suspense boundary.
// This makes the transition feel more responsive and natural.
startTransition(() => {
- setCategory(category)
+ setCategoryId(category.id)
})
}
})
@@ -221,12 +221,12 @@ function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) {
/** Props for a {@link CategorySwitcher}. */
export interface CategorySwitcherProps {
readonly category: Category
- readonly setCategory: (category: Category) => void
+ readonly setCategoryId: (categoryId: Category['id']) => void
}
/** A switcher to choose the currently visible assets table categoryModule.categoryType. */
function CategorySwitcher(props: CategorySwitcherProps) {
- const { category, setCategory } = props
+ const { category, setCategoryId } = props
const { getText } = textProvider.useText()
const [, setSearchParams] = useSearchParams()
@@ -237,7 +237,7 @@ function CategorySwitcher(props: CategorySwitcherProps) {
const cloudCategories = useCloudCategoryList()
const localCategories = useLocalCategoryList()
- const itemProps = { currentCategory: category, setCategory, dispatchAssetEvent }
+ const itemProps = { currentCategory: category, setCategoryId, dispatchAssetEvent }
const {
cloudCategory,
diff --git a/app/gui/src/dashboard/layouts/Drive.tsx b/app/gui/src/dashboard/layouts/Drive.tsx
index 6100f8d316ae..b07fc5778ff1 100644
--- a/app/gui/src/dashboard/layouts/Drive.tsx
+++ b/app/gui/src/dashboard/layouts/Drive.tsx
@@ -39,6 +39,7 @@ import { useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
import { useDeferredValue, useEffect } from 'react'
import { toast } from 'react-toastify'
import { Suspense } from '../components/Suspense'
+import { useCategoriesAPI } from './Drive/Categories/categoriesHooks'
import { useDirectoryIds } from './Drive/directoryIdsHooks'
// =============
@@ -47,10 +48,6 @@ import { useDirectoryIds } from './Drive/directoryIdsHooks'
/** Props for a {@link Drive}. */
export interface DriveProps {
- readonly category: Category
- readonly setCategory: (category: Category) => void
- readonly setCategoryId: (categoryId: Category['id']) => void
- readonly resetCategory: () => void
readonly hidden: boolean
readonly initialProjectName: string | null
readonly assetsManagementApiRef: React.Ref
@@ -60,13 +57,13 @@ const CATEGORIES_TO_DISPLAY_START_MODAL = ['cloud', 'local', 'local-directory']
/** Contains directory path and directory contents (projects, folders, secrets and files). */
function Drive(props: DriveProps) {
- const { category, resetCategory } = props
-
const { isOffline } = offlineHooks.useOffline()
const toastAndLog = toastAndLogHooks.useToastAndLog()
const { user } = authProvider.useFullUserSession()
const localBackend = backendProvider.useLocalBackend()
const { getText } = textProvider.useText()
+ const categoriesAPI = useCategoriesAPI()
+ const { category, resetCategory, setCategory } = categoriesAPI
const isCloud = categoryModule.isCloudCategory(category)
@@ -128,7 +125,7 @@ function Drive(props: DriveProps) {
}}
>
-
+
)
@@ -136,14 +133,21 @@ function Drive(props: DriveProps) {
}
}
+/**
+ * Props for a {@link DriveAssetsView}.
+ */
+interface DriveAssetsViewProps extends DriveProps {
+ readonly category: Category
+ readonly setCategory: (categoryId: Category['id']) => void
+}
+
/**
* The assets view of the Drive.
*/
-function DriveAssetsView(props: DriveProps) {
+function DriveAssetsView(props: DriveAssetsViewProps) {
const {
category,
setCategory,
- setCategoryId,
hidden = false,
initialProjectName,
assetsManagementApiRef,
@@ -254,7 +258,7 @@ function DriveAssetsView(props: DriveProps) {
-
+
{isCloud && (
{
- setCategoryId('local')
+ setCategory('local')
}}
>
{getText('switchToLocal')}
diff --git a/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx b/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx
index 92ad8203e076..f56c63b29c98 100644
--- a/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx
+++ b/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx
@@ -10,6 +10,8 @@ import { DashboardTabBar } from './DashboardTabBar'
import * as eventCallbacks from '#/hooks/eventCallbackHooks'
import * as projectHooks from '#/hooks/projectHooks'
+import { CategoriesProvider } from '#/layouts/Drive/Categories/categoriesHooks'
+import DriveProvider from '#/providers/DriveProvider'
import * as authProvider from '#/providers/AuthProvider'
import * as backendProvider from '#/providers/BackendProvider'
@@ -43,7 +45,6 @@ import * as backendModule from '#/services/Backend'
import * as localBackendModule from '#/services/LocalBackend'
import * as projectManager from '#/services/ProjectManager'
-import type { Category } from '#/layouts/CategorySwitcher/Category'
import { useCategoriesAPI } from '#/layouts/Drive/Categories/categoriesHooks'
import { baseName } from '#/utilities/fileInfo'
import { tryFindSelfPermission } from '#/utilities/permissions'
@@ -68,11 +69,17 @@ export interface DashboardProps {
/** The component that contains the entire UI. */
export default function Dashboard(props: DashboardProps) {
return (
-
-
-
-
-
+
+ {/* Ideally this would be in `Drive.tsx`, but it currently must be all the way out here
+ * due to modals being in `TheModal`. */}
+
+
+
+
+
+
+
+
)
}
@@ -114,10 +121,6 @@ function DashboardInner(props: DashboardProps) {
const categoriesAPI = useCategoriesAPI()
- const setCategory = eventCallbacks.useEventCallback((newCategory: Category) => {
- categoriesAPI.setCategory(newCategory.id)
- })
-
const projectsStore = useProjectsStore()
const page = usePage()
const launchedProjects = useLaunchedProjects()
@@ -281,10 +284,6 @@ function DashboardInner(props: DashboardProps) {
initialProjectName={initialProjectName}
ydocUrl={ydocUrl}
assetManagementApiRef={assetManagementApiRef}
- category={categoriesAPI.category}
- setCategory={setCategory}
- setCategoryId={categoriesAPI.setCategory}
- resetCategory={categoriesAPI.resetCategory}
/>
diff --git a/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx b/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx
index f39d1279c667..1bfc4641b2f8 100644
--- a/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx
+++ b/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx
@@ -7,7 +7,6 @@ import { Suspense } from '#/components/Suspense'
import { useEventCallback } from '#/hooks/eventCallbackHooks'
import { useOpenProjectMutation, useRenameProjectMutation } from '#/hooks/projectHooks'
import type { AssetManagementApi } from '#/layouts/AssetsTable'
-import type { Category } from '#/layouts/CategorySwitcher/Category'
import Drive from '#/layouts/Drive'
import type { GraphEditorRunner } from '#/layouts/Editor'
import Editor from '#/layouts/Editor'
@@ -22,24 +21,11 @@ export interface DashboardTabPanelsProps {
readonly initialProjectName: string | null
readonly ydocUrl: string | null
readonly assetManagementApiRef: React.RefObject | null
- readonly category: Category
- readonly setCategory: (category: Category) => void
- readonly resetCategory: () => void
- readonly setCategoryId: (categoryId: Category['id']) => void
}
/** The tab panels for the dashboard page. */
export function DashboardTabPanels(props: DashboardTabPanelsProps) {
- const {
- appRunner,
- initialProjectName,
- ydocUrl,
- assetManagementApiRef,
- category,
- setCategory,
- resetCategory,
- setCategoryId,
- } = props
+ const { appRunner, initialProjectName, ydocUrl, assetManagementApiRef } = props
const page = usePage()
@@ -64,10 +50,6 @@ export function DashboardTabPanels(props: DashboardTabPanelsProps) {
children: (