From 03debcab5a8c0dae70a216a385ffa2578c86710e Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Jan 2025 19:49:46 +0530 Subject: [PATCH] feat: completed sidebar changes --- frontend/src/components/v2/Menu/Menu.tsx | 82 +++--- .../OrganizationLayout/OrganizationLayout.tsx | 254 +++++++++++------ .../MenuIconButton/MenuIconButton.tsx | 55 ++++ .../components/MenuIconButton/index.tsx | 1 + .../SidebarFooter/SidebarFooter.tsx | 171 +++++++++-- .../SidebarHeader/SidebarHeader.tsx | 250 +++++++++++------ .../layouts/ProjectLayout/ProjectLayout.tsx | 265 +++++++++--------- .../ProjectSelect/ProjectSelect.tsx | 2 +- frontend/src/pages/cert-manager/layout.tsx | 7 +- frontend/src/pages/kms/layout.tsx | 7 +- .../CertManagerOverviewPage/route.tsx | 16 +- .../organization/KmsOverviewPage/route.tsx | 16 +- .../SecretManagerOverviewPage/route.tsx | 16 +- .../organization/SshOverviewPage/route.tsx | 16 +- frontend/src/pages/secret-manager/layout.tsx | 7 +- frontend/src/pages/ssh/layout.tsx | 7 +- 16 files changed, 794 insertions(+), 378 deletions(-) create mode 100644 frontend/src/layouts/OrganizationLayout/components/MenuIconButton/MenuIconButton.tsx create mode 100644 frontend/src/layouts/OrganizationLayout/components/MenuIconButton/index.tsx diff --git a/frontend/src/components/v2/Menu/Menu.tsx b/frontend/src/components/v2/Menu/Menu.tsx index f33f6c21b..29076af18 100644 --- a/frontend/src/components/v2/Menu/Menu.tsx +++ b/frontend/src/components/v2/Menu/Menu.tsx @@ -38,46 +38,46 @@ export const MenuItem = ({ }: MenuItemProps & ComponentPropsWithRef): JSX.Element => { const iconRef = useRef(null); return ( -
iconRef.current?.play()} onMouseLeave={() => iconRef.current?.stop()}> -
  • - - -
    - {icon && ( -
    - { - iconRef.current = el; - }} - src={`/lotties/${icon}.json`} - loop - className="h-full w-full" - /> -
    - )} - {children} - - {description && {description}} - -
  • -
    +
  • iconRef.current?.play()} + onMouseLeave={() => iconRef.current?.stop()} + className={twMerge( + "duration-50 group mt-0.5 flex cursor-pointer flex-col rounded px-1 py-2 font-inter text-sm text-bunker-100 transition-all hover:bg-mineshaft-700", + isSelected && "bg-mineshaft-600 hover:bg-mineshaft-600", + isDisabled && "cursor-not-allowed hover:bg-transparent", + className + )} + > + + +
    + {icon && ( +
    + { + iconRef.current = el; + }} + src={`/lotties/${icon}.json`} + loop + className="h-full w-full" + /> +
    + )} + {children} + + {description && {description}} + +
  • ); }; @@ -90,7 +90,7 @@ export type MenuGroupProps = { export const MenuGroup = ({ children, title }: MenuGroupProps): JSX.Element => ( <> -
  • {title}
  • +
  • {title}
  • {children} ); diff --git a/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx b/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx index 7a5a48892..af050ef70 100644 --- a/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx +++ b/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx @@ -1,14 +1,16 @@ -import { useState } from "react"; +import { ReactNode, useState } from "react"; import { useTranslation } from "react-i18next"; import { faMobile } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useQueryClient } from "@tanstack/react-query"; import { Link, Outlet, useNavigate, useRouter } from "@tanstack/react-router"; +import { AnimatePresence, motion } from "framer-motion"; +import { twMerge } from "tailwind-merge"; import { Mfa } from "@app/components/auth/Mfa"; import { CreateOrgModal } from "@app/components/organization/CreateOrgModal"; import SecurityClient from "@app/components/utilities/SecurityClient"; -import { Menu, MenuItem } from "@app/components/v2"; +import { Menu, MenuGroup, MenuItem } from "@app/components/v2"; import { useUser } from "@app/context"; import { usePopUp, useToggle } from "@app/hooks"; import { useSelectOrganization, workspaceKeys } from "@app/hooks/api"; @@ -18,10 +20,15 @@ import { ProjectType } from "@app/hooks/api/workspace/types"; import { navigateUserToOrg } from "@app/pages/auth/LoginPage/Login.utils"; import { InsecureConnectionBanner } from "./components/InsecureConnectionBanner"; +import { MenuIconButton } from "./components/MenuIconButton"; import { SidebarFooter } from "./components/SidebarFooter"; import { SidebarHeader } from "./components/SidebarHeader"; -export const OrganizationLayout = () => { +type Props = { + children?: ReactNode; +}; + +export const OrganizationLayout = ({ children }: Props) => { const [shouldShowMfa, toggleShowMfa] = useToggle(false); const [requiredMfaMethod, setRequiredMfaMethod] = useState(MfaMethod.EMAIL); const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {}); @@ -34,6 +41,9 @@ export const OrganizationLayout = () => { const router = useRouter(); const queryClient = useQueryClient(); + const isNestedLayout = Boolean(children); + const [isCollapsed, setIsCollapsed] = useToggle(isNestedLayout); + const { t } = useTranslation(); const handleOrgChange = async (orgId: string) => { queryClient.removeQueries({ queryKey: authKeys.getAuthToken }); @@ -71,93 +81,171 @@ export const OrganizationLayout = () => { return ( <> -
    +
    {!window.isSecureContext && }
    -
    diff --git a/frontend/src/layouts/OrganizationLayout/components/MenuIconButton/MenuIconButton.tsx b/frontend/src/layouts/OrganizationLayout/components/MenuIconButton/MenuIconButton.tsx new file mode 100644 index 000000000..0a07a4ef3 --- /dev/null +++ b/frontend/src/layouts/OrganizationLayout/components/MenuIconButton/MenuIconButton.tsx @@ -0,0 +1,55 @@ +import { ComponentPropsWithRef, ElementType, useRef } from "react"; +import { DotLottie, DotLottieReact } from "@lottiefiles/dotlottie-react"; + +import { MenuItemProps } from "@app/components/v2"; +import { twMerge } from "tailwind-merge"; + +export const MenuIconButton = ({ + children, + icon, + className, + isDisabled, + isSelected, + as: Item = "button", + description, + // wrapping in forward ref with generic component causes the loss of ts definitions on props + inputRef, + ...props +}: MenuItemProps & ComponentPropsWithRef): JSX.Element => { + const iconRef = useRef(null); + return ( + iconRef.current?.play()} + onMouseLeave={() => iconRef.current?.stop()} + ref={inputRef} + {...props} + > +
    + {icon && ( +
    + { + iconRef.current = el; + }} + src={`/lotties/${icon}.json`} + loop + className="h-full w-full" + /> +
    + )} + {children} + + ); +}; diff --git a/frontend/src/layouts/OrganizationLayout/components/MenuIconButton/index.tsx b/frontend/src/layouts/OrganizationLayout/components/MenuIconButton/index.tsx new file mode 100644 index 000000000..6655c7091 --- /dev/null +++ b/frontend/src/layouts/OrganizationLayout/components/MenuIconButton/index.tsx @@ -0,0 +1 @@ +export { MenuIconButton } from "./MenuIconButton"; diff --git a/frontend/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx b/frontend/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx index 6a634a9c4..5d45850c6 100644 --- a/frontend/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/SidebarFooter/SidebarFooter.tsx @@ -1,25 +1,33 @@ import { faGithub, faSlack } from "@fortawesome/free-brands-svg-icons"; import { + faAnglesLeft, + faAnglesRight, + faArrowUpRightFromSquare, faBook, faEnvelope, faInfinity, faInfo, + faInfoCircle, faPlus, - faQuestion + faQuestion, + faUser } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Link } from "@tanstack/react-router"; +import { Link, useNavigate } from "@tanstack/react-router"; import { WishForm } from "@app/components/features/WishForm"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, - DropdownMenuTrigger + DropdownMenuTrigger, + MenuItem } from "@app/components/v2"; import { envConfig } from "@app/config/env"; -import { useOrganization, useSubscription } from "@app/context"; -import { useGetOrgTrialUrl } from "@app/hooks/api"; +import { useOrganization, useSubscription, useUser } from "@app/context"; +import { useGetOrgTrialUrl, useLogoutUser } from "@app/hooks/api"; + +import { MenuIconButton } from "../MenuIconButton"; export const INFISICAL_SUPPORT_OPTIONS = [ [ @@ -44,40 +52,68 @@ export const INFISICAL_SUPPORT_OPTIONS = [ ] ]; -export const SidebarFooter = () => { +type Props = { + isCollapsed?: boolean; + onToggleSidebar: () => void; +}; + +export const SidebarFooter = ({ isCollapsed, onToggleSidebar }: Props) => { const { subscription } = useSubscription(); const { currentOrg } = useOrganization(); const { mutateAsync } = useGetOrgTrialUrl(); + const { user } = useUser(); + const navigate = useNavigate(); + const logout = useLogoutUser(); + const logOutUser = async () => { + try { + console.log("Logging out..."); + await logout.mutateAsync(); + navigate({ to: "/login" }); + } catch (error) { + console.error(error); + } + }; + return (
    {(window.location.origin.includes("https://app.infisical.com") || - window.location.origin.includes("https://gamma.infisical.com")) && } - -
    - - Invite people -
    - - - -
    - - Help & Support + window.location.origin.includes("https://gamma.infisical.com")) && + !isCollapsed && } + {!isCollapsed && ( + +
    + + Invite people
    + + )} + + + {isCollapsed ? ( + + + Support + + ) : ( +
    + + Help & Support +
    + )}
    {INFISICAL_SUPPORT_OPTIONS.map(([icon, text, url]) => ( @@ -125,6 +161,91 @@ export const SidebarFooter = () => {
    )} + {isCollapsed ? ( + + + + ) : ( + + + Collapse + + )} + + + {isCollapsed ? ( +
    + +
    + {user?.firstName?.charAt(0)} +
    +
    +
    + ) : ( +
    +
    + {user?.firstName?.charAt(0)} +
    +
    + {user?.firstName} {user?.lastName} +
    +
    + +
    +
    + )} +
    + +
    {user?.username}
    + + Personal Settings + + + + Documentation + + + + + + Join Slack Community + + + + {user?.superAdmin && ( + + + Server Admin Console + + + )} + + + Organization Admin Console + + +
    + + +
    ); }; diff --git a/frontend/src/layouts/OrganizationLayout/components/SidebarHeader/SidebarHeader.tsx b/frontend/src/layouts/OrganizationLayout/components/SidebarHeader/SidebarHeader.tsx index 98683c2e5..fe68e8bd4 100644 --- a/frontend/src/layouts/OrganizationLayout/components/SidebarHeader/SidebarHeader.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/SidebarHeader/SidebarHeader.tsx @@ -1,6 +1,6 @@ -import { faAngleDown, faArrowUpRightFromSquare, faCheck } from "@fortawesome/free-solid-svg-icons"; +import { faCheck, faSort } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Link, useNavigate } from "@tanstack/react-router"; +import { useNavigate } from "@tanstack/react-router"; import { Button, @@ -9,17 +9,18 @@ import { DropdownMenuItem, DropdownMenuTrigger } from "@app/components/v2"; -import { useOrganization, useUser } from "@app/context"; +import { useOrganization } from "@app/context"; import { useGetOrganizations, useLogoutUser } from "@app/hooks/api"; import { AuthMethod } from "@app/hooks/api/users/types"; +import { twMerge } from "tailwind-merge"; type Prop = { onChangeOrg: (orgId: string) => void; + isCollapsed?: boolean; }; -export const SidebarHeader = ({ onChangeOrg }: Prop) => { +export const SidebarHeader = ({ onChangeOrg, isCollapsed }: Prop) => { const { currentOrg } = useOrganization(); - const { user } = useUser(); const navigate = useNavigate(); const { data: orgs } = useGetOrganizations(); @@ -35,24 +36,42 @@ export const SidebarHeader = ({ onChangeOrg }: Prop) => { }; return ( -
    +
    - -
    -
    - {currentOrg?.name.charAt(0)} -
    -
    - {currentOrg?.name} -
    - + +
    + {isCollapsed ? ( +
    + {currentOrg?.name.charAt(0)} +
    + ) : ( + <> +
    + {currentOrg?.name.charAt(0)} +
    +
    +
    + {currentOrg?.name} +
    +
    Free Plan
    +
    + + + )}
    -
    {user?.username}
    +
    organizations
    {orgs?.map((org) => { return ( @@ -93,71 +112,6 @@ export const SidebarHeader = ({ onChangeOrg }: Prop) => { ); })} - -
    - - - - - -
    - {user?.firstName?.charAt(0)} - {user?.lastName && user?.lastName?.charAt(0)} -
    -
    - -
    {user?.username}
    - - Personal Settings - - - - Documentation - - - - - - Join Slack Community - - - - {user?.superAdmin && ( - - - Server Admin Console - - - )} - - - Organization Admin Console - -
    ); }; + +// +// +//
    +//
    +// {currentOrg?.name.charAt(0)} +//
    +//
    +// {currentOrg?.name} +//
    +// +//
    +//
    +// +//
    {user?.username}
    +// {orgs?.map((org) => { +// return ( +// +// +// +// ); +// })} +//
    +// +// +// +// +// +//
    +// {user?.firstName?.charAt(0)} +// {user?.lastName && user?.lastName?.charAt(0)} +//
    +//
    +// +//
    {user?.username}
    +// +// Personal Settings +// +// +// +// Documentation +// +// +// +// +// +// Join Slack Community +// +// +// +// {user?.superAdmin && ( +// +// +// Server Admin Console +// +// +// )} +// +// +// Organization Admin Console +// +// +//
    +// +// +// diff --git a/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx b/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx index 1f73202bd..6f21aa788 100644 --- a/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx +++ b/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx @@ -7,7 +7,7 @@ import { Link, Outlet, useNavigate, useRouter } from "@tanstack/react-router"; import { Mfa } from "@app/components/auth/Mfa"; import SecurityClient from "@app/components/utilities/SecurityClient"; -import { Menu, MenuItem } from "@app/components/v2"; +import { Menu, MenuGroup, MenuItem } from "@app/components/v2"; import { useUser, useWorkspace } from "@app/context"; import { useToggle } from "@app/hooks"; import { @@ -22,7 +22,6 @@ import { ProjectType } from "@app/hooks/api/workspace/types"; import { navigateUserToOrg } from "@app/pages/auth/LoginPage/Login.utils"; import { InsecureConnectionBanner } from "../OrganizationLayout/components/InsecureConnectionBanner"; -import { SidebarFooter } from "../OrganizationLayout/components/SidebarFooter"; import { ProjectSelect } from "./components/ProjectSelect"; import { SidebarHeader } from "./components/SidebarHeader"; @@ -105,144 +104,146 @@ export const ProjectLayout = () => {
    diff --git a/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx b/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx index 0ba943b7b..10d6889a5 100644 --- a/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx +++ b/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx @@ -167,7 +167,7 @@ export const ProjectSelect = () => { }, [workspaces, projectFavorites, currentWorkspace]); return ( -
    +

    {currentWorkspace?.type ? getProjectTitle(currentWorkspace?.type) : "Project"}

    diff --git a/frontend/src/pages/cert-manager/layout.tsx b/frontend/src/pages/cert-manager/layout.tsx index 9bd48a65c..a9a68de25 100644 --- a/frontend/src/pages/cert-manager/layout.tsx +++ b/frontend/src/pages/cert-manager/layout.tsx @@ -4,11 +4,16 @@ import { workspaceKeys } from "@app/hooks/api"; import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries"; import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries"; import { ProjectLayout } from "@app/layouts/ProjectLayout"; +import { OrganizationLayout } from "@app/layouts/OrganizationLayout"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/cert-manager/$projectId/_cert-manager-layout" )({ - component: ProjectLayout, + component: () => ( + + + + ), beforeLoad: async ({ params, context }) => { await context.queryClient.ensureQueryData({ queryKey: workspaceKeys.getWorkspaceById(params.projectId), diff --git a/frontend/src/pages/kms/layout.tsx b/frontend/src/pages/kms/layout.tsx index 7a8cfe7e3..5a78be252 100644 --- a/frontend/src/pages/kms/layout.tsx +++ b/frontend/src/pages/kms/layout.tsx @@ -3,12 +3,17 @@ import { createFileRoute } from "@tanstack/react-router"; import { workspaceKeys } from "@app/hooks/api"; import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries"; import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries"; +import { OrganizationLayout } from "@app/layouts/OrganizationLayout"; import { ProjectLayout } from "@app/layouts/ProjectLayout"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/kms/$projectId/_kms-layout" )({ - component: ProjectLayout, + component: () => ( + + + + ), beforeLoad: async ({ params, context }) => { await context.queryClient.ensureQueryData({ queryKey: workspaceKeys.getWorkspaceById(params.projectId), diff --git a/frontend/src/pages/organization/CertManagerOverviewPage/route.tsx b/frontend/src/pages/organization/CertManagerOverviewPage/route.tsx index a4e8bb63c..e939b3c3c 100644 --- a/frontend/src/pages/organization/CertManagerOverviewPage/route.tsx +++ b/frontend/src/pages/organization/CertManagerOverviewPage/route.tsx @@ -1,9 +1,21 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute, linkOptions } from "@tanstack/react-router"; import { CertManagerOverviewPage } from "./CertManagerOverviewPage"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/organization/_layout/cert-manager/overview" )({ - component: CertManagerOverviewPage + component: CertManagerOverviewPage, + context: () => ({ + breadcrumbs: [ + { + label: "products", + link: linkOptions({ disabled: true, to: "/" }) + }, + { + label: "Cert Managers", + link: linkOptions({ to: "/organization/cert-manager/overview" }) + } + ] + }) }); diff --git a/frontend/src/pages/organization/KmsOverviewPage/route.tsx b/frontend/src/pages/organization/KmsOverviewPage/route.tsx index 3c9f96924..42ab611bd 100644 --- a/frontend/src/pages/organization/KmsOverviewPage/route.tsx +++ b/frontend/src/pages/organization/KmsOverviewPage/route.tsx @@ -1,9 +1,21 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute, linkOptions } from "@tanstack/react-router"; import { KmsOverviewPage } from "./KmsOverviewPage"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/organization/_layout/kms/overview" )({ - component: KmsOverviewPage + component: KmsOverviewPage, + context: () => ({ + breadcrumbs: [ + { + label: "products", + link: linkOptions({ disabled: true, to: "/" }) + }, + { + label: "KMS", + link: linkOptions({ to: "/organization/kms/overview" }) + } + ] + }) }); diff --git a/frontend/src/pages/organization/SecretManagerOverviewPage/route.tsx b/frontend/src/pages/organization/SecretManagerOverviewPage/route.tsx index 30320f2b3..55f01e018 100644 --- a/frontend/src/pages/organization/SecretManagerOverviewPage/route.tsx +++ b/frontend/src/pages/organization/SecretManagerOverviewPage/route.tsx @@ -1,9 +1,21 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute, linkOptions } from "@tanstack/react-router"; import { SecretManagerOverviewPage } from "./SecretManagerOverviewPage"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/organization/_layout/secret-manager/overview" )({ - component: SecretManagerOverviewPage + component: SecretManagerOverviewPage, + context: () => ({ + breadcrumbs: [ + { + label: "products", + link: linkOptions({ disabled: true, to: "/" }) + }, + { + label: "Secret Managers", + link: linkOptions({ to: "/organization/secret-manager/overview" }) + } + ] + }) }); diff --git a/frontend/src/pages/organization/SshOverviewPage/route.tsx b/frontend/src/pages/organization/SshOverviewPage/route.tsx index 4fd99a812..e23f9bab3 100644 --- a/frontend/src/pages/organization/SshOverviewPage/route.tsx +++ b/frontend/src/pages/organization/SshOverviewPage/route.tsx @@ -1,9 +1,21 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute, linkOptions } from "@tanstack/react-router"; import { SshOverviewPage } from "./SshOverviewPage"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/organization/_layout/ssh/overview" )({ - component: SshOverviewPage + component: SshOverviewPage, + context: () => ({ + breadcrumbs: [ + { + label: "products", + link: linkOptions({ disabled: true, to: "/" }) + }, + { + label: "SSH", + link: linkOptions({ to: "/organization/ssh/overview" }) + } + ] + }) }); diff --git a/frontend/src/pages/secret-manager/layout.tsx b/frontend/src/pages/secret-manager/layout.tsx index 1ead7191d..824c341b6 100644 --- a/frontend/src/pages/secret-manager/layout.tsx +++ b/frontend/src/pages/secret-manager/layout.tsx @@ -4,11 +4,16 @@ import { workspaceKeys } from "@app/hooks/api"; import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries"; import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries"; import { ProjectLayout } from "@app/layouts/ProjectLayout"; +import { OrganizationLayout } from "@app/layouts/OrganizationLayout"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout" )({ - component: ProjectLayout, + component: () => ( + + + + ), beforeLoad: async ({ params, context }) => { await context.queryClient.ensureQueryData({ queryKey: workspaceKeys.getWorkspaceById(params.projectId), diff --git a/frontend/src/pages/ssh/layout.tsx b/frontend/src/pages/ssh/layout.tsx index 4ab53124c..d305bf3d2 100644 --- a/frontend/src/pages/ssh/layout.tsx +++ b/frontend/src/pages/ssh/layout.tsx @@ -4,11 +4,16 @@ import { workspaceKeys } from "@app/hooks/api"; import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries"; import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries"; import { ProjectLayout } from "@app/layouts/ProjectLayout"; +import { OrganizationLayout } from "@app/layouts/OrganizationLayout"; export const Route = createFileRoute( "/_authenticate/_inject-org-details/ssh/$projectId/_ssh-layout" )({ - component: ProjectLayout, + component: () => ( + + + + ), beforeLoad: async ({ params, context }) => { await context.queryClient.ensureQueryData({ queryKey: workspaceKeys.getWorkspaceById(params.projectId),