diff --git a/apps/studio/components/interfaces/Account/AccessTokens/AccessTokenList.tsx b/apps/studio/components/interfaces/Account/AccessTokens/AccessTokenList.tsx index 73db62030ffb7..cb0ad93a87cff 100644 --- a/apps/studio/components/interfaces/Account/AccessTokens/AccessTokenList.tsx +++ b/apps/studio/components/interfaces/Account/AccessTokens/AccessTokenList.tsx @@ -50,6 +50,7 @@ const RowLoading = () => ( ) const tableHeaderClass = 'text-left font-mono uppercase text-xs text-foreground-lighter h-auto py-2' + const TableContainer = ({ children }: { children: React.ReactNode }) => ( @@ -151,13 +152,15 @@ export const AccessTokenList = ({ searchString = '', onDeleteSuccess }: AccessTo {filteredTokens?.map((x) => { return ( - -

{x.name}

+ +

+ {x.name} +

- - {x.token_alias} + +

{x.token_alias}

- +

{x.last_used_at ? ( @@ -171,7 +174,7 @@ export const AccessTokenList = ({ searchString = '', onDeleteSuccess }: AccessTo )}

- + {x.expires_at ? ( dayjs(x.expires_at).isBefore(dayjs()) ? ( diff --git a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx index cc6105011284e..cf7095261417a 100644 --- a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx +++ b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx @@ -1,6 +1,4 @@ -import { ArrowLeft } from 'lucide-react' import Head from 'next/head' -import Link from 'next/link' import { useRouter } from 'next/router' import { PropsWithChildren, useEffect } from 'react' @@ -9,13 +7,8 @@ import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' import { withAuth } from 'hooks/misc/withAuth' import { IS_PLATFORM } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' -import { cn, NavMenu, NavMenuItem } from 'ui' -import { - MAX_WIDTH_CLASSES, - PADDING_CLASSES, - ScaffoldContainerLegacy, - ScaffoldTitle, -} from '../Scaffold' +import { cn } from 'ui' +import { WithSidebar } from './WithSidebar' export interface AccountLayoutProps { title: string @@ -37,19 +30,6 @@ const AccountLayout = ({ children, title }: PropsWithChildren { @@ -64,33 +44,52 @@ const AccountLayout = ({ children, title }: PropsWithChildren{title ? `${title} | Supabase` : 'Supabase'} -
- - - - Back to dashboard - - Account settings - -
- - {accountLinks.map((item, i) => ( - - {item.label} - - ))} - -
- {children} +
+ + {children} +
) diff --git a/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx b/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx index 2ea219a9d509c..b70d439f9f5e2 100644 --- a/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx +++ b/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx @@ -1,11 +1,9 @@ -import { isUndefined } from 'lodash' -import { ArrowUpRight, LogOut } from 'lucide-react' +import { ArrowLeft } from 'lucide-react' import Link from 'next/link' -import { PropsWithChildren, ReactNode, useState } from 'react' -import { Badge, cn, Menu } from 'ui' +import { PropsWithChildren, ReactNode } from 'react' +import { cn, Menu } from 'ui' import MobileSheetNav from 'ui-patterns/MobileSheetNav/MobileSheetNav' -import { LayoutHeader } from '../ProjectLayout/LayoutHeader' -import type { SidebarLink, SidebarSection } from './AccountLayout.types' +import type { SidebarSection } from './AccountLayout.types' import { useAppStateSnapshot } from 'state/app-state' interface WithSidebarProps { @@ -17,9 +15,10 @@ interface WithSidebarProps { subitemsParentKey?: number hideSidebar?: boolean customSidebarContent?: ReactNode + backToDashboardURL?: string } -const WithSidebar = ({ +export const WithSidebar = ({ title, header, breadcrumbs = [], @@ -29,6 +28,7 @@ const WithSidebar = ({ subitemsParentKey, hideSidebar = false, customSidebarContent, + backToDashboardURL, }: PropsWithChildren) => { const noContent = !sections && !customSidebarContent const { mobileMenuOpen, setMobileMenuOpen } = useAppStateSnapshot() @@ -43,11 +43,16 @@ const WithSidebar = ({ subitems={subitems} subitemsParentKey={subitemsParentKey} customSidebarContent={customSidebarContent} - className="hidden md:block" + backToDashboardURL={backToDashboardURL} + className="hidden md:flex" /> )}
-
{children}
+
+
+ {children} +
+
) } -export default WithSidebar export const SidebarContent = ({ title, @@ -71,6 +76,7 @@ export const SidebarContent = ({ subitems, subitemsParentKey, customSidebarContent, + backToDashboardURL, className, }: PropsWithChildren> & { className?: string }) => { return ( @@ -78,43 +84,72 @@ export const SidebarContent = ({
- {title && ( -
-
-

- {title} -

+
+ {backToDashboardURL && ( +
+
+ + + Back to dashboard + +
+
+ )} + {header && header} +
+
+ + {customSidebarContent} + {sections.map((section, idx) => ( +
+ {Boolean(section.heading) ? ( + + ) : ( +
+
+ {section.links.map((link, i: number) => { + const isActive = link.isActive && !subitems + return ( + + +
+
+ {link.label} +
+
+ +
+ ) + })} +
+
+ )} + {idx !== sections.length - 1 && ( +
+ )} +
+ ))} +
- )} - {header && header} -
- - {customSidebarContent} - {sections.map((section) => { - return Boolean(section.heading) ? ( - - ) : ( -
- -
- ) - })} -
@@ -128,131 +163,33 @@ interface SectionWithHeadersProps { } const SectionWithHeaders = ({ section, subitems, subitemsParentKey }: SectionWithHeadersProps) => ( -
- {section.heading && } - {section.versionLabel && ( -
- {section.versionLabel} +
+
+ {section.heading && ( + + {section.heading} +
+ } + /> + )} +
+ {section.links.map((link, i: number) => { + const isActive = link.isActive && !subitems + return ( + + +
+
+ {link.label} +
+
+ +
+ ) + })}
- )} - { - - } +
) -interface SidebarItemProps { - links: SidebarLink[] - subitems?: any[] - subitemsParentKey?: number -} - -const SidebarItem = ({ links, subitems, subitemsParentKey }: SidebarItemProps) => { - return ( -
    - {links.map((link, i: number) => { - // disable active state for link with subitems - const isActive = link.isActive && !subitems - - let render: any = ( - - ) - - if (subitems && link.subitemsKey === subitemsParentKey) { - const subItemsRender = subitems.map((y: any, i: number) => ( - - )) - render = [render, ...subItemsRender] - } - - return render - })} -
- ) -} - -interface SidebarLinkProps extends SidebarLink { - id: string - isSubitem?: boolean -} - -const SidebarLinkItem = ({ - id, - label, - href, - isActive, - isSubitem, - isExternal, - onClick, - icon, -}: SidebarLinkProps) => { - if (isUndefined(href)) { - let icon - if (isExternal) { - icon = - } - - if (label === 'Log out') { - icon = - } - - return ( - {})} - icon={icon} - > - {isSubitem ?

{label}

: label} -
- ) - } - - return ( - - - {isExternal && ( - - - - )} -
- - {isSubitem ?

{label}

: label} -
- {icon} -
-
- - ) -} diff --git a/apps/studio/components/layouts/DefaultLayout.tsx b/apps/studio/components/layouts/DefaultLayout.tsx index c9b8a70542865..9361bd4dce92f 100644 --- a/apps/studio/components/layouts/DefaultLayout.tsx +++ b/apps/studio/components/layouts/DefaultLayout.tsx @@ -1,11 +1,14 @@ import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' +import { LOCAL_STORAGE_KEYS } from 'common' import { useParams } from 'common' import { AppBannerWrapper } from 'components/interfaces/App' import { AppBannerContextProvider } from 'components/interfaces/App/AppBannerWrapperContext' import { Sidebar } from 'components/interfaces/Sidebar' import { useCheckLatestDeploy } from 'hooks/use-check-latest-deploy' +import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' +import { useAppStateSnapshot } from 'state/app-state' import { SidebarProvider } from 'ui' import { LayoutHeader } from './ProjectLayout/LayoutHeader' import MobileNavigationBar from './ProjectLayout/NavigationBar/MobileNavigationBar' @@ -28,8 +31,21 @@ export interface DefaultLayoutProps { const DefaultLayout = ({ children, headerTitle }: PropsWithChildren) => { const { ref } = useParams() const router = useRouter() + const appSnap = useAppStateSnapshot() const showProductMenu = !!ref && router.pathname !== '/project/[ref]' + const [lastVisitedOrganization] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.LAST_VISITED_ORGANIZATION, + '' + ) + + const backToDashboardURL = + appSnap.lastRouteBeforeVisitingAccountPage.length > 0 + ? appSnap.lastRouteBeforeVisitingAccountPage + : !!lastVisitedOrganization + ? `/org/${lastVisitedOrganization}` + : '/organizations' + useCheckLatestDeploy() return ( @@ -41,12 +57,18 @@ const DefaultLayout = ({ children, headerTitle }: PropsWithChildren
- +
{/* Main Content Area */}
- {/* Sidebar */} - + {/* Sidebar - Only show for project pages, not account pages */} + {!router.pathname.startsWith('/account') && } {/* Main Content */}
{children}
diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackDropdown.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackDropdown.tsx index 5f02871ce143c..3602fb585b9f4 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackDropdown.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackDropdown.tsx @@ -44,18 +44,20 @@ const FeedbackDropdown = ({ className }: { className?: string }) => {
What would you like to share?
- -
diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index b0d99ecc117df..fe558c231face 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -1,4 +1,5 @@ import { AnimatePresence, motion } from 'framer-motion' +import { ChevronLeft } from 'lucide-react' import Link from 'next/link' import { ReactNode, useMemo, useState } from 'react' @@ -21,6 +22,7 @@ import { useHotKey } from 'hooks/ui/useHotKey' import { IS_PLATFORM } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import { Badge, cn } from 'ui' +import { useRouter } from 'next/router' import { BreadcrumbsView } from './BreadcrumbsView' import { FeedbackDropdown } from './FeedbackDropdown' import { HelpPopover } from './HelpPopover' @@ -52,6 +54,7 @@ interface LayoutHeaderProps { breadcrumbs?: any[] headerTitle?: string showProductMenu?: boolean + backToDashboardURL?: string } const LayoutHeader = ({ @@ -59,13 +62,17 @@ const LayoutHeader = ({ breadcrumbs = [], headerTitle, showProductMenu, + backToDashboardURL, }: LayoutHeaderProps) => { const { ref: projectRef, slug } = useParams() + const router = useRouter() const { data: selectedProject } = useSelectedProjectQuery() const { data: selectedOrganization } = useSelectedOrganizationQuery() const { setMobileMenuOpen } = useAppStateSnapshot() const gitlessBranching = useIsBranching2Enabled() + const isAccountPage = router.pathname.startsWith('/account') + const [showEditorPanel, setShowEditorPanel] = useState(false) useHotKey( () => { @@ -95,7 +102,17 @@ const LayoutHeader = ({ return ( <>
- {showProductMenu && ( + {backToDashboardURL && isAccountPage && ( +
+ + + +
+ )} + {(showProductMenu || isAccountPage) && (