From a76cfa6ae9299dda1cea1866183e3538793a3419 Mon Sep 17 00:00:00 2001 From: Sven Efftinge Date: Wed, 5 Oct 2022 05:47:10 +0000 Subject: [PATCH] [dashboard] deprecate individual account --- components/dashboard/src/Menu.tsx | 279 +++++++++--------- .../dashboard/src/components/PillMenuItem.tsx | 6 +- .../dashboard/src/projects/Projects.tsx | 13 + .../dashboard/src/teams/teams-context.tsx | 2 +- 4 files changed, 165 insertions(+), 135 deletions(-) diff --git a/components/dashboard/src/Menu.tsx b/components/dashboard/src/Menu.tsx index 0cbdc00dadec21..98f2a58c8107e6 100644 --- a/components/dashboard/src/Menu.tsx +++ b/components/dashboard/src/Menu.tsx @@ -14,9 +14,8 @@ import gitpodIcon from "./icons/gitpod.svg"; import { getGitpodService, gitpodHostUrl } from "./service/service"; import { UserContext } from "./user-context"; import { TeamsContext, getCurrentTeam, getSelectedTeamSlug } from "./teams/teams-context"; -import getSettingsMenu from "./settings/settings-menu"; import { getAdminMenu } from "./admin/admin-menu"; -import ContextMenu from "./components/ContextMenu"; +import ContextMenu, { ContextMenuEntry } from "./components/ContextMenu"; import Separator from "./components/Separator"; import PillMenuItem from "./components/PillMenuItem"; import TabMenuItem from "./components/TabMenuItem"; @@ -36,7 +35,7 @@ interface Entry { } export default function Menu() { - const { user, userBillingMode, refreshUserBillingMode } = useContext(UserContext); + const { user } = useContext(UserContext); const { showUsageView } = useContext(FeatureFlagContext); const { teams } = useContext(TeamsContext); const location = useLocation(); @@ -46,6 +45,11 @@ export default function Menu() { const { project, setProject } = useContext(ProjectContext); const [isFeedbackFormVisible, setFeedbackFormVisible] = useState(false); + const [hasIndividualProjects, setHasIndividualProjects] = useState(false); + getGitpodService() + .server.getUserProjects() + .then((projects) => setHasIndividualProjects(projects.length > 0)); + const match = useRouteMatch<{ segment1?: string; segment2?: string; segment3?: string }>( "/(t/)?:segment1/:segment2?/:segment3?", ); @@ -90,14 +94,21 @@ export default function Menu() { return all.some((n) => n === path || n + "/" === path); } - const userFullName = user?.fullName || user?.name || "..."; - // Hide most of the top menu when in a full-page form. const isMinimalUI = inResource(location.pathname, ["new", "teams/new", "open"]); const isWorkspacesUI = inResource(location.pathname, ["workspaces"]); + const isAccountUI = inResource(location.pathname, [ + "account", + "notifications", + "variables", + "keys", + "integrations", + "preferences", + ]); const isAdminUI = inResource(window.location.pathname, ["admin"]); const [teamMembers, setTeamMembers] = useState>({}); + useEffect(() => { if (!teams) { return; @@ -154,13 +165,8 @@ export default function Menu() { } }, [team]); - useEffect(() => { - // Refresh billing mode - refreshUserBillingMode(); - }, [teams]); - const teamOrUserSlug = !!team ? "/t/" + team.slug : "/projects"; - const leftMenu: Entry[] = (() => { + const secondLevelMenu: Entry[] = (() => { // Project menu if (projectSlug) { return [ @@ -180,55 +186,45 @@ export default function Menu() { ]; } // Team menu - if (team) { - const currentUserInTeam = (teamMembers[team.id] || []).find((m) => m.userId === user?.id); - - const teamSettingsList = [ - { - title: "Projects", - link: `/t/${team.slug}/projects`, - alternatives: [] as string[], - }, - { - title: "Members", - link: `/t/${team.slug}/members`, - }, - ]; - if (showUsageView || (teamBillingMode && teamBillingMode.mode === "usage-based")) { - teamSettingsList.push({ - title: "Usage", - link: `/t/${team.slug}/usage`, - }); - } - if (currentUserInTeam?.role === "owner") { - teamSettingsList.push({ - title: "Settings", - link: `/t/${team.slug}/settings`, - alternatives: getTeamSettingsMenu({ team, billingMode: teamBillingMode }).flatMap((e) => e.link), - }); - } - - return teamSettingsList; + if (!team) { + return []; } - // User menu - const userMenu = []; - userMenu.push({ - title: "Projects", - link: "/projects", - }); - if (showUsageView) { - userMenu.push({ + const currentUserInTeam = (teamMembers[team.id] || []).find((m) => m.userId === user?.id); + + const teamSettingsList = [ + { + title: "Projects", + link: `/t/${team.slug}/projects`, + alternatives: [] as string[], + }, + { + title: "Members", + link: `/t/${team.slug}/members`, + }, + ]; + if (showUsageView || (teamBillingMode && teamBillingMode.mode === "usage-based")) { + teamSettingsList.push({ title: "Usage", - link: "/usage", + link: `/t/${team.slug}/usage`, }); } - userMenu.push({ - title: "Settings", - link: "/settings", - alternatives: getSettingsMenu({ userBillingMode }).flatMap((e) => e.link), - }); - return userMenu; + if (currentUserInTeam?.role === "owner") { + teamSettingsList.push({ + title: "Settings", + link: `/t/${team.slug}/settings`, + alternatives: getTeamSettingsMenu({ team, billingMode: teamBillingMode }).flatMap((e) => e.link), + }); + } + + return teamSettingsList; })(); + const leftMenu: Entry[] = [ + { + title: "Workspaces", + link: "/workspaces", + alternatives: ["/"], + }, + ]; const rightMenu: Entry[] = [ ...(user?.rolesOrPermissions?.includes("admin") ? [ @@ -239,11 +235,6 @@ export default function Menu() { }, ] : []), - { - title: "Workspaces", - link: "/workspaces", - alternatives: ["/"], - }, ]; const handleFeedbackFormClick = () => { @@ -253,86 +244,93 @@ export default function Menu() { const onFeedbackFormClose = () => { setFeedbackFormVisible(false); }; - const isTeamLevelActive = !projectSlug && !isWorkspacesUI && !isAdminUI && teamOrUserSlug; + const isTeamLevelActive = !projectSlug && !isWorkspacesUI && !isAccountUI && !isAdminUI && teamOrUserSlug; const renderTeamMenu = () => { + if (!teams || teams.length === 0) { + return ( +
+ +
+ ); + } + const userFullName = user?.fullName || user?.name || "..."; + const entries: (ContextMenuEntry & { slug: string })[] = [ + ...(hasIndividualProjects + ? [ + { + title: userFullName, + customContent: ( +
+ + {userFullName} + + Personal Account +
+ ), + active: getSelectedTeamSlug() === "", + separator: true, + slug: "", + link: "/projects", + }, + ] + : []), + ...(teams || []) + .map((t) => ({ + slug: t.slug, + title: t.name, + customContent: ( +
+ {t.name} + + {!!teamMembers[t.id] + ? `${teamMembers[t.id].length} member${teamMembers[t.id].length === 1 ? "" : "s"}` + : "..."} + +
+ ), + active: getSelectedTeamSlug() === t.slug, + separator: true, + link: `/t/${t.slug}`, + })) + .sort((a, b) => (a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1)), + { + slug: "new", + title: "Create a new team", + customContent: ( +
+ New Team + + + +
+ ), + link: "/teams/new", + }, + ]; const classes = "flex h-full text-base py-0 " + (isTeamLevelActive ? "text-gray-50 bg-gray-800 dark:bg-gray-50 dark:text-gray-900 border-gray-700 dark:border-gray-200" : "text-gray-500 bg-gray-50 dark:bg-gray-800 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 dark:border-gray-700"); + const selectedEntry = entries.find((e) => e.slug === getSelectedTeamSlug()) || entries[0]; return ( -
- - - {teams?.find((t) => t.slug === getSelectedTeamSlug())?.name || userFullName} +
+ + + {selectedEntry.title!}
- - - {userFullName} - - Personal Account -
- ), - active: getSelectedTeamSlug() === "", - separator: true, - link: "/projects", - }, - ...(teams || []) - .map((t) => ({ - title: t.name, - customContent: ( -
- - {t.name} - - - {!!teamMembers[t.id] - ? `${teamMembers[t.id].length} member${ - teamMembers[t.id].length === 1 ? "" : "s" - }` - : "..."} - -
- ), - active: getSelectedTeamSlug() === t.slug, - separator: true, - link: `/t/${t.slug}`, - })) - .sort((a, b) => (a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1)), - { - title: "Create a new team", - customContent: ( -
- New Team - - - -
- ), - link: "/teams/new", - }, - ]} - > +
Gitpod's logo - {!isMinimalUI &&
{renderTeamMenu()}
} + {!isMinimalUI && ( + <> +
+ {leftMenu.map((entry) => ( +
+ +
+ ))} +
+ {renderTeamMenu()} + + )}
{isFeedbackFormVisible && }
- {!isMinimalUI && !prebuildId && !isWorkspacesUI && !isAdminUI && ( + {!isMinimalUI && !prebuildId && !isWorkspacesUI && !isAccountUI && !isAdminUI && (