From 91872623a9b4c3c741d4c5e93dc4fce8b3f2baae Mon Sep 17 00:00:00 2001 From: tristandubbeld Date: Wed, 22 Oct 2025 13:14:31 +0200 Subject: [PATCH 1/3] feat(graphql): add sdkWorkspace field to currentTeamInfoFragment --- packages/app/src/app/graphql/types.ts | 2 ++ .../app/src/app/overmind/effects/gql/dashboard/fragments.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/app/src/app/graphql/types.ts b/packages/app/src/app/graphql/types.ts index 38a263954b1..dd5825047fb 100644 --- a/packages/app/src/app/graphql/types.ts +++ b/packages/app/src/app/graphql/types.ts @@ -3596,6 +3596,7 @@ export type CurrentTeamInfoFragmentFragment = { avatarUrl: string | null; frozen: boolean; insertedAt: string; + sdkWorkspace: boolean; users: Array<{ __typename?: 'User'; id: any; @@ -5075,6 +5076,7 @@ export type GetTeamQuery = { avatarUrl: string | null; frozen: boolean; insertedAt: string; + sdkWorkspace: boolean; users: Array<{ __typename?: 'User'; id: any; diff --git a/packages/app/src/app/overmind/effects/gql/dashboard/fragments.ts b/packages/app/src/app/overmind/effects/gql/dashboard/fragments.ts index d201b56789f..a6022dfab0f 100644 --- a/packages/app/src/app/overmind/effects/gql/dashboard/fragments.ts +++ b/packages/app/src/app/overmind/effects/gql/dashboard/fragments.ts @@ -186,6 +186,7 @@ export const currentTeamInfoFragment = gql` avatarUrl frozen insertedAt + sdkWorkspace users { id avatarUrl From de74b140f080aac42fd435c092cabadedbd2e8e5 Mon Sep 17 00:00:00 2001 From: tristandubbeld Date: Wed, 22 Oct 2025 13:14:48 +0200 Subject: [PATCH 2/3] feat(hooks): add useActiveTeamInfo hook for team info abstraction --- .../app/src/app/hooks/useActiveTeamInfo.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 packages/app/src/app/hooks/useActiveTeamInfo.ts diff --git a/packages/app/src/app/hooks/useActiveTeamInfo.ts b/packages/app/src/app/hooks/useActiveTeamInfo.ts new file mode 100644 index 00000000000..a16ea5b0daa --- /dev/null +++ b/packages/app/src/app/hooks/useActiveTeamInfo.ts @@ -0,0 +1,37 @@ +import { useAppState } from 'app/overmind'; + +export type ActiveTeamInfo = { + id: string | null; + name: string | null; + sdkWorkspace: boolean; + frozen: boolean; +}; + +/** + * Hook to access active team information. + * + * This hook provides an abstraction layer over the Overmind state, + * making it easier to migrate away from Overmind in the future. + * + * @returns Active team information or null values if no team is active + */ +export const useActiveTeamInfo = (): ActiveTeamInfo => { + const { activeTeamInfo } = useAppState(); + + if (!activeTeamInfo) { + return { + id: null, + name: null, + sdkWorkspace: false, + frozen: false, + }; + } + + return { + id: activeTeamInfo.id, + name: activeTeamInfo.name, + sdkWorkspace: activeTeamInfo.sdkWorkspace ?? false, + frozen: activeTeamInfo.frozen, + }; +}; + From 85a160abf62e2d320be3a82cc43d2d4b8648fe6b Mon Sep 17 00:00:00 2001 From: tristandubbeld Date: Wed, 22 Oct 2025 13:15:02 +0200 Subject: [PATCH 3/3] feat(dashboard): customize UI for SDK workspaces --- .../src/app/pages/Dashboard/Header/index.tsx | 54 ++++++++++--------- .../src/app/pages/Dashboard/Sidebar/index.tsx | 43 +++++++++------ 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/packages/app/src/app/pages/Dashboard/Header/index.tsx b/packages/app/src/app/pages/Dashboard/Header/index.tsx index 2b7c9792643..eb3527c2581 100644 --- a/packages/app/src/app/pages/Dashboard/Header/index.tsx +++ b/packages/app/src/app/pages/Dashboard/Header/index.tsx @@ -12,6 +12,7 @@ import { UserMenu } from 'app/pages/common/UserMenu'; import { Notifications } from 'app/components/Notifications'; import { dashboard as dashboardUrls } from '@codesandbox/common/lib/utils/url-generator'; import { useWorkspaceLimits } from 'app/hooks/useWorkspaceLimits'; +import { useActiveTeamInfo } from 'app/hooks/useActiveTeamInfo'; import { TeamAvatar } from 'app/components/TeamAvatar'; import { WorkspaceSelect } from 'app/components/WorkspaceSelect'; import { SkeletonTextBlock } from 'app/components/Skeleton/elements'; @@ -25,6 +26,7 @@ export const Header: React.FC = React.memo( const history = useHistory(); const actions = useActions(); const { isFrozen } = useWorkspaceLimits(); + const { sdkWorkspace } = useActiveTeamInfo(); const { activeWorkspaceAuthorization, hasLogIn, @@ -96,31 +98,35 @@ export const Header: React.FC = React.memo( - + {!sdkWorkspace && ( + <> + - + + + )} {hasLogIn && } diff --git a/packages/app/src/app/pages/Dashboard/Sidebar/index.tsx b/packages/app/src/app/pages/Dashboard/Sidebar/index.tsx index 430228b68f1..2c5f849d6ea 100644 --- a/packages/app/src/app/pages/Dashboard/Sidebar/index.tsx +++ b/packages/app/src/app/pages/Dashboard/Sidebar/index.tsx @@ -7,6 +7,7 @@ import css from '@styled-system/css'; import { useWorkspaceAuthorization } from 'app/hooks/useWorkspaceAuthorization'; import { useWorkspaceSubscription } from 'app/hooks/useWorkspaceSubscription'; import { useWorkspaceFeatureFlags } from 'app/hooks/useWorkspaceFeatureFlags'; +import { useActiveTeamInfo } from 'app/hooks/useActiveTeamInfo'; import { ContextMenu } from './ContextMenu'; import { DashboardBaseFolder } from '../types'; import { Position } from '../Components/Selection'; @@ -76,7 +77,13 @@ export const Sidebar: React.FC = ({ setNewFolderPath, }; - const showRespositories = !state.environment.isOnPrem; + const { sdkWorkspace } = useActiveTeamInfo(); + + const hasRepositories = state.activeTeam && state.sidebar[state.activeTeam] + ? state.sidebar[state.activeTeam].repositories.length > 0 + : false; + + const showRespositories = !state.environment.isOnPrem && (!sdkWorkspace || hasRepositories); const { ubbBeta } = useWorkspaceFeatureFlags(); const { isPrimarySpace, hasAdminAccess, hasEditorAccess } = useWorkspaceAuthorization(); @@ -204,15 +211,17 @@ export const Sidebar: React.FC = ({ size={2} css={css({ color: 'sideBarSectionHeader.foreground' })} > - Devboxes and Sandboxes + {sdkWorkspace ? 'Sandboxes' : 'Devboxes and Sandboxes'} - + {!sdkWorkspace && ( + + )} = ({ path={dashboardUrls.deleted(activeTeam)} icon="trash" /> - - + {!sdkWorkspace && ( + <> + + + + )} {ubbBeta && state.activeTeamInfo && (