Skip to content

Commit d3348ed

Browse files
feat(dashboard): Update header layout and start page branding (#20762)
* feat(dashboard): Refactor header layout and update start page UI * addressing nit fixes
1 parent 217ba2d commit d3348ed

File tree

2 files changed

+61
-43
lines changed

2 files changed

+61
-43
lines changed

components/dashboard/src/menu/Menu.tsx

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import { User, RoleOrPermission } from "@gitpod/public-api/lib/gitpod/v1/user_pb
2222
import { getPrimaryEmail } from "@gitpod/public-api-common/lib/user-utils";
2323
import { ConfigurationsMigrationCoachmark } from "../repositories/coachmarks/MigrationCoachmark";
2424
import { useInstallationConfiguration } from "../data/installation/installation-config-query";
25+
import { useIsDataOps } from "../data/featureflag-query";
26+
import { ProductLogo } from "../components/ProductLogo";
2527

2628
interface Entry {
2729
title: string;
@@ -34,9 +36,7 @@ export default function Menu() {
3436
const location = useLocation();
3537
const { setCurrency } = useContext(PaymentContext);
3638
const [isFeedbackFormVisible, setFeedbackFormVisible] = useState<boolean>(false);
37-
38-
const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration();
39-
const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation;
39+
const isDataOps = useIsDataOps();
4040

4141
useEffect(() => {
4242
const { server } = getGitpodService();
@@ -79,16 +79,24 @@ export default function Menu() {
7979
<ConfigurationsMigrationCoachmark>
8080
<OrganizationSelector />
8181
</ConfigurationsMigrationCoachmark>
82-
{/* hidden on smaller screens (in its own menu below on smaller screens) */}
83-
<div className="hidden md:block pl-2">
84-
<OrgPagesNav />
82+
{/* Mobile Only Divider and User Menu */}
83+
<div className="flex items-center md:hidden">
84+
<div className="h-6 w-px bg-gray-300 dark:bg-gray-600 mx-2" />
85+
<UserMenu user={user} className="" onFeedback={handleFeedbackFormClick} withAdminLink />
86+
</div>
87+
{/* Desktop Only Divider, User Menu, and Workspaces Nav */}
88+
<div className="hidden md:flex items-center">
89+
<div className="h-6 w-px bg-gray-300 dark:bg-gray-600 mx-2" />
90+
<UserMenu user={user} className="" onFeedback={handleFeedbackFormClick} />
91+
<div className="pl-4">
92+
<OrgPagesNav />
93+
</div>
8594
</div>
8695
</div>
8796
<div className="flex items-center w-auto" id="menu">
88-
{/* hidden on smaller screens - TODO: move to user menu on smaller screen */}
97+
{/* Right side nav - Desktop Only */}
8998
<nav className="hidden md:block flex-1">
90-
<ul className="flex flex-1 items-center justify-between text-base text-gray-500 dark:text-gray-400 space-x-2">
91-
<li className="flex-1"></li>
99+
<ul className="flex flex-1 items-center justify-end text-base text-gray-500 dark:text-gray-400 space-x-4">
92100
{user?.rolesOrPermissions?.includes(RoleOrPermission.ADMIN) && (
93101
<li className="cursor-pointer">
94102
<PillMenuItem
@@ -98,31 +106,32 @@ export default function Menu() {
98106
/>
99107
</li>
100108
)}
101-
{isGitpodIo && (
102-
<li className="cursor-pointer">
103-
<PillMenuItem name="Feedback" onClick={handleFeedbackFormClick} />
109+
{!isDataOps && (
110+
<li>
111+
<div className="flex items-center gap-x-1 text-sm text-pk-content-secondary">
112+
<ProductLogo className="h-4 w-auto" />
113+
<span>Gitpod Classic</span>
114+
</div>
104115
</li>
105116
)}
106117
</ul>
107118
</nav>
108-
{/* Hide normal user menu on small screens */}
109-
<UserMenu user={user} className="hidden md:block" />
110-
{/* Show a user menu w/ admin & feedback links on small screens */}
111-
<UserMenu
112-
user={user}
113-
className="md:hidden"
114-
withAdminLink
115-
withFeedbackLink
116-
onFeedback={handleFeedbackFormClick}
117-
/>
119+
{/* Right side items - Mobile Only */}
120+
<div className="flex items-center space-x-3 md:hidden">
121+
{!isDataOps && (
122+
<div className="flex items-center gap-x-1 text-sm text-pk-content-secondary">
123+
<ProductLogo className="h-4 w-auto" />
124+
<span>Gitpod Classic</span>
125+
</div>
126+
)}
127+
</div>
118128
</div>
119129
{isFeedbackFormVisible && <FeedbackFormModal onClose={onFeedbackFormClose} />}
120130
</div>
121131
</header>
122132
<Separator />
123-
{/* only shown on small screens */}
133+
{/* Mobile-only OrgPagesNav and Separator */}
124134
<OrgPagesNav className="md:hidden app-container flex justify-start py-2" />
125-
{/* only shown on small screens */}
126135
<Separator className="md:hidden" />
127136
</>
128137
);
@@ -162,14 +171,13 @@ type UserMenuProps = {
162171
user?: User;
163172
className?: string;
164173
withAdminLink?: boolean;
165-
withFeedbackLink?: boolean;
166174
onFeedback?: () => void;
167175
};
168-
const UserMenu: FC<UserMenuProps> = ({ user, className, withAdminLink, withFeedbackLink, onFeedback }) => {
176+
const UserMenu: FC<UserMenuProps> = ({ user, className, withAdminLink, onFeedback }) => {
169177
const { data: installationConfig, isLoading: isInstallationConfigLoading } = useInstallationConfiguration();
170178
const isGitpodIo = isInstallationConfigLoading ? false : !installationConfig?.isDedicatedInstallation;
171179

172-
const extraSection = useMemo(() => {
180+
const adminSection = useMemo(() => {
173181
const items: ContextMenuEntry[] = [];
174182

175183
if (withAdminLink && user?.rolesOrPermissions?.includes(RoleOrPermission.ADMIN)) {
@@ -178,23 +186,17 @@ const UserMenu: FC<UserMenuProps> = ({ user, className, withAdminLink, withFeedb
178186
link: "/admin",
179187
});
180188
}
181-
if (withFeedbackLink && isGitpodIo) {
182-
items.push({
183-
title: "Feedback",
184-
onClick: onFeedback,
185-
});
186-
}
187189

188190
// Add a separator to the last item
189191
if (items.length > 0) {
190192
items[items.length - 1].separator = true;
191193
}
192194

193195
return items;
194-
}, [isGitpodIo, onFeedback, user?.rolesOrPermissions, withAdminLink, withFeedbackLink]);
196+
}, [user?.rolesOrPermissions, withAdminLink]);
195197

196198
const menuEntries = useMemo(() => {
197-
return [
199+
const entries: ContextMenuEntry[] = [
198200
{
199201
title: (user && (getPrimaryEmail(user) || user?.name)) || "User",
200202
customFontStyle: "text-gray-400",
@@ -215,15 +217,27 @@ const UserMenu: FC<UserMenuProps> = ({ user, className, withAdminLink, withFeedb
215217
href: "https://www.gitpod.io/support/",
216218
target: "_blank",
217219
rel: "noreferrer",
218-
separator: true,
219-
},
220-
...extraSection,
221-
{
222-
title: "Log out",
223-
href: gitpodHostUrl.asApiLogout().toString(),
220+
separator: !isGitpodIo,
224221
},
225222
];
226-
}, [extraSection, user]);
223+
224+
if (isGitpodIo) {
225+
entries.push({
226+
title: "Feedback",
227+
onClick: onFeedback,
228+
separator: true,
229+
});
230+
}
231+
232+
entries.push(...adminSection);
233+
234+
entries.push({
235+
title: "Log out",
236+
href: gitpodHostUrl.asApiLogout().toString(),
237+
});
238+
239+
return entries;
240+
}, [adminSection, user, isGitpodIo, onFeedback]);
227241

228242
return (
229243
<div
@@ -243,5 +257,5 @@ const UserMenu: FC<UserMenuProps> = ({ user, className, withAdminLink, withFeedb
243257
function isSelected(entry: Entry, location: Location<any>) {
244258
const all = [entry.link, ...(entry.alternatives || [])].map((l) => l.toLowerCase());
245259
const path = location.pathname.toLowerCase();
246-
return all.some((n) => n === path || n + "/" === path);
260+
return all.some((n) => n === path || n + "/" === path || path.startsWith(n + "/"));
247261
}

components/dashboard/src/start/StartPage.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { VerifyModal } from "./VerifyModal";
1414
import { useWorkspaceDefaultImageQuery } from "../data/workspaces/default-workspace-image-query";
1515
import { GetWorkspaceDefaultImageResponse_Source } from "@gitpod/public-api/lib/gitpod/v1/workspace_pb";
1616
import { ProductLogo } from "../components/ProductLogo";
17+
import { useIsDataOps } from "../data/featureflag-query";
1718

1819
export enum StartPhase {
1920
Checking = 0,
@@ -96,6 +97,8 @@ export function StartPage(props: StartPageProps) {
9697
const { phase, error, workspaceId } = props;
9798
let title = props.title || getPhaseTitle(phase, error);
9899
useDocumentTitle("Starting");
100+
const isDataOps = useIsDataOps();
101+
99102
return (
100103
<div className="w-screen h-screen align-middle">
101104
<div className="flex flex-col mx-auto items-center text-center h-screen">
@@ -105,6 +108,7 @@ export function StartPage(props: StartPageProps) {
105108
error || phase === StartPhase.Stopped || phase === StartPhase.IdeReady ? "" : "animate-bounce"
106109
}`}
107110
/>
111+
{!isDataOps && <span className="block mt-2 text-pk-content-secondary">Gitpod Classic</span>}
108112
<Heading2 className="mt-8">{title}</Heading2>
109113
{typeof phase === "number" && phase < StartPhase.IdeReady && (
110114
<ProgressBar phase={phase} error={!!error} />

0 commit comments

Comments
 (0)