From 96c97ed0819a23ad2005e99105e6f47b7c9afd34 Mon Sep 17 00:00:00 2001 From: Siddhant Khare Date: Tue, 22 Apr 2025 09:03:03 +0000 Subject: [PATCH 1/2] feat(dashboard): Refactor header layout and update start page UI --- components/dashboard/src/menu/Menu.tsx | 104 +++++++++++-------- components/dashboard/src/start/StartPage.tsx | 4 + 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/components/dashboard/src/menu/Menu.tsx b/components/dashboard/src/menu/Menu.tsx index 773adef745f16e..3c25c3c4c12602 100644 --- a/components/dashboard/src/menu/Menu.tsx +++ b/components/dashboard/src/menu/Menu.tsx @@ -22,6 +22,8 @@ import { User, RoleOrPermission } from "@gitpod/public-api/lib/gitpod/v1/user_pb import { getPrimaryEmail } from "@gitpod/public-api-common/lib/user-utils"; import { ConfigurationsMigrationCoachmark } from "../repositories/coachmarks/MigrationCoachmark"; import { useInstallationConfiguration } from "../data/installation/installation-config-query"; +import { useIsDataOps } from "../data/featureflag-query"; +import { ProductLogo } from "../components/ProductLogo"; interface Entry { title: string; @@ -34,9 +36,7 @@ export default function Menu() { const location = useLocation(); const { setCurrency } = useContext(PaymentContext); const [isFeedbackFormVisible, setFeedbackFormVisible] = useState(false); - - const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration(); - const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation; + const isDataOps = useIsDataOps(); useEffect(() => { const { server } = getGitpodService(); @@ -79,16 +79,24 @@ export default function Menu() { - {/* hidden on smaller screens (in its own menu below on smaller screens) */} -
- + {/* Mobile Only Divider and User Menu */} +
+
+ +
+ {/* Desktop Only Divider, User Menu, and Workspaces Nav */} +
+
+ +
+ +
{isFeedbackFormVisible && }
- {/* only shown on small screens */} + {/* Mobile-only OrgPagesNav and Separator */} - {/* only shown on small screens */} ); @@ -162,10 +177,9 @@ type UserMenuProps = { user?: User; className?: string; withAdminLink?: boolean; - withFeedbackLink?: boolean; onFeedback?: () => void; }; -const UserMenu: FC = ({ user, className, withAdminLink, withFeedbackLink, onFeedback }) => { +const UserMenu: FC = ({ user, className, withAdminLink, onFeedback }) => { const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration(); const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation; @@ -178,12 +192,6 @@ const UserMenu: FC = ({ user, className, withAdminLink, withFeedb link: "/admin", }); } - if (withFeedbackLink && isGitpodIo) { - items.push({ - title: "Feedback", - onClick: onFeedback, - }); - } // Add a separator to the last item if (items.length > 0) { @@ -191,10 +199,10 @@ const UserMenu: FC = ({ user, className, withAdminLink, withFeedb } return items; - }, [isGitpodIo, onFeedback, user?.rolesOrPermissions, withAdminLink, withFeedbackLink]); + }, [user?.rolesOrPermissions, withAdminLink]); const menuEntries = useMemo(() => { - return [ + const baseEntries: ContextMenuEntry[] = [ { title: (user && (getPrimaryEmail(user) || user?.name)) || "User", customFontStyle: "text-gray-400", @@ -215,15 +223,27 @@ const UserMenu: FC = ({ user, className, withAdminLink, withFeedb href: "https://www.gitpod.io/support/", target: "_blank", rel: "noreferrer", - separator: true, - }, - ...extraSection, - { - title: "Log out", - href: gitpodHostUrl.asApiLogout().toString(), + separator: !isGitpodIo, }, ]; - }, [extraSection, user]); + + if (isGitpodIo) { + baseEntries.push({ + title: "Feedback", + onClick: onFeedback, + separator: true, + }); + } + + baseEntries.push(...extraSection); + + baseEntries.push({ + title: "Log out", + href: gitpodHostUrl.asApiLogout().toString(), + }); + + return baseEntries; + }, [extraSection, user, isGitpodIo, onFeedback]); return (
= ({ user, className, withAdminLink, withFeedb function isSelected(entry: Entry, location: Location) { const all = [entry.link, ...(entry.alternatives || [])].map((l) => l.toLowerCase()); const path = location.pathname.toLowerCase(); - return all.some((n) => n === path || n + "/" === path); + return all.some((n) => n === path || n + "/" === path || path.startsWith(n + "/")); } diff --git a/components/dashboard/src/start/StartPage.tsx b/components/dashboard/src/start/StartPage.tsx index e17b6df243c61a..521cf7adfedb6a 100644 --- a/components/dashboard/src/start/StartPage.tsx +++ b/components/dashboard/src/start/StartPage.tsx @@ -14,6 +14,7 @@ import { VerifyModal } from "./VerifyModal"; import { useWorkspaceDefaultImageQuery } from "../data/workspaces/default-workspace-image-query"; import { GetWorkspaceDefaultImageResponse_Source } from "@gitpod/public-api/lib/gitpod/v1/workspace_pb"; import { ProductLogo } from "../components/ProductLogo"; +import { useIsDataOps } from "../data/featureflag-query"; export enum StartPhase { Checking = 0, @@ -96,6 +97,8 @@ export function StartPage(props: StartPageProps) { const { phase, error, workspaceId } = props; let title = props.title || getPhaseTitle(phase, error); useDocumentTitle("Starting"); + const isDataOps = useIsDataOps(); + return (
@@ -105,6 +108,7 @@ export function StartPage(props: StartPageProps) { error || phase === StartPhase.Stopped || phase === StartPhase.IdeReady ? "" : "animate-bounce" }`} /> + {!isDataOps && Gitpod Classic} {title} {typeof phase === "number" && phase < StartPhase.IdeReady && ( From 657d73f26baf8f96fbb3430dc19c667a4c372a5c Mon Sep 17 00:00:00 2001 From: Siddhant Khare Date: Tue, 22 Apr 2025 10:54:51 +0000 Subject: [PATCH 2/2] addressing nit fixes --- components/dashboard/src/menu/Menu.tsx | 30 ++++++++------------ components/dashboard/src/start/StartPage.tsx | 2 +- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/components/dashboard/src/menu/Menu.tsx b/components/dashboard/src/menu/Menu.tsx index 3c25c3c4c12602..2a4406ddcd298a 100644 --- a/components/dashboard/src/menu/Menu.tsx +++ b/components/dashboard/src/menu/Menu.tsx @@ -88,7 +88,7 @@ export default function Menu() {
-
+
@@ -108,13 +108,10 @@ export default function Menu() { )} {!isDataOps && (
  • - +
  • )} @@ -122,13 +119,10 @@ export default function Menu() { {/* Right side items - Mobile Only */}
    {!isDataOps && ( - + )}
    @@ -183,7 +177,7 @@ const UserMenu: FC = ({ user, className, withAdminLink, onFeedbac const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration(); const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation; - const extraSection = useMemo(() => { + const adminSection = useMemo(() => { const items: ContextMenuEntry[] = []; if (withAdminLink && user?.rolesOrPermissions?.includes(RoleOrPermission.ADMIN)) { @@ -202,7 +196,7 @@ const UserMenu: FC = ({ user, className, withAdminLink, onFeedbac }, [user?.rolesOrPermissions, withAdminLink]); const menuEntries = useMemo(() => { - const baseEntries: ContextMenuEntry[] = [ + const entries: ContextMenuEntry[] = [ { title: (user && (getPrimaryEmail(user) || user?.name)) || "User", customFontStyle: "text-gray-400", @@ -228,22 +222,22 @@ const UserMenu: FC = ({ user, className, withAdminLink, onFeedbac ]; if (isGitpodIo) { - baseEntries.push({ + entries.push({ title: "Feedback", onClick: onFeedback, separator: true, }); } - baseEntries.push(...extraSection); + entries.push(...adminSection); - baseEntries.push({ + entries.push({ title: "Log out", href: gitpodHostUrl.asApiLogout().toString(), }); - return baseEntries; - }, [extraSection, user, isGitpodIo, onFeedback]); + return entries; + }, [adminSection, user, isGitpodIo, onFeedback]); return (
    - {!isDataOps && Gitpod Classic} + {!isDataOps && Gitpod Classic} {title} {typeof phase === "number" && phase < StartPhase.IdeReady && (