Skip to content

Commit

Permalink
DEVPROD-10203: Redirect links to waterfall if beta feature is enabled (
Browse files Browse the repository at this point in the history
  • Loading branch information
minnakt authored Feb 4, 2025
1 parent 9f636cc commit 390dbc1
Show file tree
Hide file tree
Showing 21 changed files with 196 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const baseRoute = "/preferences";
const tabNames = {
profile: "/profile",
cli: "/cli",
newUI: "/newUI",
uiSettings: "/ui-settings",
};
describe("user preferences pages", () => {
it("visiting /preferences should redirect to the profile tab", () => {
Expand All @@ -26,7 +26,7 @@ describe("user preferences pages", () => {

describe("beta features", () => {
it("should be able to edit beta features", () => {
cy.visit(`${baseRoute}${tabNames.newUI}`);
cy.visit(`${baseRoute}${tabNames.uiSettings}`);
cy.dataCy("save-beta-features-button").should(
"have.attr",
"aria-disabled",
Expand Down
30 changes: 30 additions & 0 deletions apps/spruce/cypress/integration/waterfall/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,34 @@ describe("navigation", () => {
cy.location("pathname").should("equal", "/project/spruce/waterfall");
cy.dataCy("waterfall-page").should("be.visible");
});

it("nav bar items change if opted into beta test", () => {
cy.visit("/preferences/ui-settings");

// The beta test is enabled but the user is not opted in.
cy.dataCy("project-health-link").should("be.visible");
cy.dataCy("waterfall-link").should("not.exist");
cy.dataCy("auxiliary-dropdown-link").click();
cy.dataCy("auxiliary-dropdown-waterfall").should("be.visible");
cy.dataCy("auxiliary-dropdown-project-health").should("not.exist");

// Opt the user in to the beta test.
cy.dataCy("spruce-waterfall-enabled").within(() => {
cy.get('[data-label="Enabled"]').click({ force: true });
});
cy.dataCy("save-beta-features-button").should(
"have.attr",
"aria-disabled",
"false",
);
cy.dataCy("save-beta-features-button").click();
cy.validateToast("success", "Your changes have been saved.");

// Nav bar items should have changed.
cy.dataCy("project-health-link").should("not.exist");
cy.dataCy("waterfall-link").should("be.visible");
cy.dataCy("auxiliary-dropdown-link").click();
cy.dataCy("auxiliary-dropdown-waterfall").should("not.exist");
cy.dataCy("auxiliary-dropdown-project-health").should("be.visible");
});
});
3 changes: 3 additions & 0 deletions apps/spruce/cypress/integration/waterfall/waterfall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ describe("waterfall page", () => {
describe("task stats tooltip", () => {
it("shows task stats when clicked", () => {
cy.dataCy("task-stats-tooltip").should("not.exist");
cy.dataCy("task-stats-tooltip-button")
.eq(3)
.should("have.attr", "aria-disabled", "false");
cy.dataCy("task-stats-tooltip-button").eq(3).click();
cy.dataCy("task-stats-tooltip").should("be.visible");
cy.dataCy("task-stats-tooltip").should("contain.text", "Failed");
Expand Down
3 changes: 2 additions & 1 deletion apps/spruce/src/analytics/navbar/useNavbarAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ type Action =
| { name: "Clicked project settings link" }
| { name: "Clicked project patches link" }
| { name: "Clicked EVG wiki link" }
| { name: "Clicked preferences link" }
| { name: "Clicked profile link" }
| { name: "Clicked notifications link" }
| { name: "Clicked UI settings link" }
| { name: "Clicked task queue link" };

export const useNavbarAnalytics = () =>
Expand Down
38 changes: 36 additions & 2 deletions apps/spruce/src/components/Header/AuxiliaryDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import Badge, { Variant as BadgeVariant } from "@leafygreen-ui/badge";
import { useNavbarAnalytics } from "analytics";
import {
routes,
getDistroSettingsRoute,
getProjectPatchesRoute,
getProjectSettingsRoute,
getTaskQueueRoute,
getCommitsRoute,
getWaterfallRoute,
} from "constants/routes";
import { useFirstDistro } from "hooks";
import {
useAdminBetaFeatures,
useFirstDistro,
useMergedBetaFeatures,
} from "hooks";
import { NavDropdown } from "./NavDropdown";

interface AuxiliaryDropdownProps {
Expand All @@ -19,6 +26,32 @@ export const AuxiliaryDropdown: React.FC<AuxiliaryDropdownProps> = ({
const { sendEvent } = useNavbarAnalytics();
const { distro } = useFirstDistro();

const { adminBetaSettings } = useAdminBetaFeatures();

const { betaFeatures } = useMergedBetaFeatures();
const { spruceWaterfallEnabled } = betaFeatures ?? {};

const inverseLink = spruceWaterfallEnabled
? {
"data-cy": "auxiliary-dropdown-project-health",
text: "Project Health",
to: getCommitsRoute(projectIdentifier),
onClick: () => sendEvent({ name: "Clicked project health link" }),
}
: {
"data-cy": "auxiliary-dropdown-waterfall",
text: (
<span>
Waterfall{" "}
<Badge darkMode variant={BadgeVariant.Blue}>
Beta
</Badge>
</span>
),
to: getWaterfallRoute(projectIdentifier),
onClick: () => sendEvent({ name: "Clicked waterfall link" }),
};

const menuItems = [
{
text: "All Hosts",
Expand All @@ -36,7 +69,6 @@ export const AuxiliaryDropdown: React.FC<AuxiliaryDropdownProps> = ({
text: "Distro Settings",
onClick: () => sendEvent({ name: "Clicked distro settings link" }),
},

{
"data-cy": "auxiliary-dropdown-project-patches",
to: getProjectPatchesRoute(projectIdentifier),
Expand All @@ -49,6 +81,8 @@ export const AuxiliaryDropdown: React.FC<AuxiliaryDropdownProps> = ({
to: getProjectSettingsRoute(projectIdentifier),
onClick: () => sendEvent({ name: "Clicked project settings link" }),
},
// Don't show inverse link if waterfall beta test is not active.
...(adminBetaSettings?.spruceWaterfallEnabled ? [inverseLink] : []),
];

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/spruce/src/components/Header/NavDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const NavDropdownMenuIcon: React.FC<{ open: boolean }> = ({ open }) => (

export interface MenuItemType {
"data-cy"?: string;
text: string;
text: string | React.ReactNode;
href?: string;
to?: string;
onClick?: () => void;
Expand Down
31 changes: 23 additions & 8 deletions apps/spruce/src/components/Header/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ import { wikiUrl } from "constants/externalResources";
import {
getCommitsRoute,
getUserPatchesRoute,
getWaterfallRoute,
routes,
slugs,
} from "constants/routes";
import { useAuthStateContext } from "context/Auth";
import { UserQuery, SpruceConfigQuery } from "gql/generated/types";
import { USER, SPRUCE_CONFIG } from "gql/queries";
import { useLegacyUIURL } from "hooks";
import { useLegacyUIURL, useMergedBetaFeatures } from "hooks";
import { validators } from "utils";
import { AuxiliaryDropdown } from "./AuxiliaryDropdown";
import { UserDropdown } from "./UserDropdown";
Expand Down Expand Up @@ -63,6 +64,9 @@ export const Navbar: React.FC = () => {
const projectIdentifier =
currProject || configData?.spruceConfig?.ui?.defaultProject;

const { betaFeatures } = useMergedBetaFeatures();
const { spruceWaterfallEnabled } = betaFeatures ?? {};

if (!isAuthenticated) {
return null;
}
Expand All @@ -75,13 +79,24 @@ export const Navbar: React.FC = () => {
>
<StyledAnimatedIcon icon={HolidayTree} />
</LogoLink>
<PrimaryLink
data-cy="project-health-link"
onClick={() => sendEvent({ name: "Clicked project health link" })}
to={getCommitsRoute(projectIdentifier)}
>
Project Health
</PrimaryLink>
{spruceWaterfallEnabled ? (
<PrimaryLink
data-cy="waterfall-link"
onClick={() => sendEvent({ name: "Clicked waterfall link" })}
to={getWaterfallRoute(projectIdentifier)}
>
Waterfall
</PrimaryLink>
) : (
<PrimaryLink
data-cy="project-health-link"
onClick={() => sendEvent({ name: "Clicked project health link" })}
to={getCommitsRoute(projectIdentifier)}
>
Project Health
</PrimaryLink>
)}

<PrimaryLink
onClick={() => sendEvent({ name: "Clicked my patches link" })}
// @ts-expect-error: FIXME. This comment was added by an automated script.
Expand Down
11 changes: 8 additions & 3 deletions apps/spruce/src/components/Header/UserDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,28 @@ export const UserDropdown = () => {

const menuItems: MenuItemType[] = [
{
text: "Preferences",
text: "Profile",
to: getPreferencesRoute(PreferencesTabRoutes.Profile),
onClick: () => sendEvent({ name: "Clicked preferences link" }),
onClick: () => sendEvent({ name: "Clicked profile link" }),
},
{
text: "Notifications",
to: getPreferencesRoute(PreferencesTabRoutes.Notifications),
onClick: () => sendEvent({ name: "Clicked notifications link" }),
},
{
text: "UI Settings",
to: getPreferencesRoute(PreferencesTabRoutes.UISettings),
onClick: () => sendEvent({ name: "Clicked UI settings link" }),
},
{
"data-cy": "log-out",
text: "Log out",
onClick: () => logoutAndRedirect(),
},
];
if (permissions?.canEditAdminSettings) {
menuItems.splice(2, 0, {
menuItems.splice(-1, 0, {
"data-cy": "admin-link",
text: "Admin",
href: adminSettingsURL,
Expand Down
17 changes: 15 additions & 2 deletions apps/spruce/src/components/Redirects/WaterfallCommitsRedirect.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { useParams, Navigate } from "react-router-dom";
import { getCommitsRoute, slugs } from "constants/routes";
import { getCommitsRoute, getWaterfallRoute, slugs } from "constants/routes";
import { useMergedBetaFeatures } from "hooks";

export const WaterfallCommitsRedirect: React.FC = () => {
const { [slugs.projectIdentifier]: projectIdentifier } = useParams();
return <Navigate to={getCommitsRoute(projectIdentifier)} />;

const { betaFeatures } = useMergedBetaFeatures();
const { spruceWaterfallEnabled } = betaFeatures ?? {};

return (
<Navigate
to={
spruceWaterfallEnabled
? getWaterfallRoute(projectIdentifier)
: getCommitsRoute(projectIdentifier)
}
/>
);
};
2 changes: 1 addition & 1 deletion apps/spruce/src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export enum PreferencesTabRoutes {
Profile = "profile",
Notifications = "notifications",
CLI = "cli",
NewUI = "newUI",
UISettings = "ui-settings",
PublicKeys = "publickeys",
}

Expand Down
14 changes: 11 additions & 3 deletions apps/spruce/src/hooks/useBreadcrumbRoot/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useBreadcrumbAnalytics } from "analytics";
import { getCommitsRoute } from "constants/routes";
import { useGetUserPatchesPageTitleAndLink } from "hooks";
import { getCommitsRoute, getWaterfallRoute } from "constants/routes";
import {
useGetUserPatchesPageTitleAndLink,
useMergedBetaFeatures,
} from "hooks";

export const useBreadcrumbRoot = (
isPatch: boolean,
Expand All @@ -9,6 +12,9 @@ export const useBreadcrumbRoot = (
) => {
const breadcrumbAnalytics = useBreadcrumbAnalytics();

const { betaFeatures } = useMergedBetaFeatures();
const { spruceWaterfallEnabled } = betaFeatures ?? {};

const { link: userPatchesPageLink, title: userPatchesPageTitle } =
useGetUserPatchesPageTitleAndLink(author, !isPatch) ?? {};

Expand All @@ -25,7 +31,9 @@ export const useBreadcrumbRoot = (
"data-cy": "bc-my-patches",
}
: {
to: getCommitsRoute(projectIdentifier),
to: spruceWaterfallEnabled
? getWaterfallRoute(projectIdentifier)
: getCommitsRoute(projectIdentifier),
text: projectIdentifier,
onClick: () => {
breadcrumbAnalytics.sendEvent({
Expand Down
20 changes: 15 additions & 5 deletions apps/spruce/src/pages/preferences/PreferencesTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import {
slugs,
} from "constants/routes";
import { CliTab } from "./preferencesTabs/CliTab";
import { NewUITab } from "./preferencesTabs/NewUITab";
import { NotificationsTab } from "./preferencesTabs/NotificationsTab";
import { ProfileTab } from "./preferencesTabs/ProfileTab";
import { PublicKeysTab } from "./preferencesTabs/PublicKeysTab";
import { UISettingsTab } from "./preferencesTabs/UISettingsTab";

export const PreferencesTabs: React.FC = () => {
// @ts-expect-error: FIXME. This comment was added by an automated script.
Expand Down Expand Up @@ -52,13 +52,23 @@ export const PreferencesTabs: React.FC = () => {
}
path={PreferencesTabRoutes.CLI}
/>
{/* Delete this redirect in DEVPROD-14564. */}
<Route
element={
<Navigate
replace
to={getPreferencesRoute(PreferencesTabRoutes.UISettings)}
/>
}
path="/newUI"
/>
<Route
element={
<Container>
<NewUITab />
<UISettingsTab />
</Container>
}
path={PreferencesTabRoutes.NewUI}
path={PreferencesTabRoutes.UISettings}
/>
<Route
element={
Expand Down Expand Up @@ -97,8 +107,8 @@ const getTitle = (
[PreferencesTabRoutes.CLI]: {
title: "CLI & API",
},
[PreferencesTabRoutes.NewUI]: {
title: "New UI Settings",
[PreferencesTabRoutes.UISettings]: {
title: "UI Settings",
},
[PreferencesTabRoutes.PublicKeys]: {
title: "Manage Public Keys",
Expand Down
10 changes: 5 additions & 5 deletions apps/spruce/src/pages/preferences/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,18 @@ const Preferences: React.FC = () => {
Public Keys
</SideNavItem>
<SideNavItem
active={tab === PreferencesTabRoutes.NewUI}
active={tab === PreferencesTabRoutes.UISettings}
as={Link}
data-cy="newui-nav-tab"
data-cy="ui-settings-nav-tab"
onClick={() =>
sendEvent({
name: "Changed tab",
tab: PreferencesTabRoutes.NewUI,
tab: PreferencesTabRoutes.UISettings,
})
}
to={getPreferencesRoute(PreferencesTabRoutes.NewUI)}
to={getPreferencesRoute(PreferencesTabRoutes.UISettings)}
>
New UI
UI Settings
</SideNavItem>
</SideNavGroup>
</SideNav>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ParagraphSkeleton } from "@leafygreen-ui/skeleton-loader";
import { SettingsCard } from "components/SettingsCard";
import { useAdminBetaFeatures, useUserBetaFeatures } from "hooks";
import { BetaFeatureSettings } from "./newUITab/BetaFeatures";
import { PreferenceToggles } from "./newUITab/PreferenceToggles";
import { BetaFeatureSettings } from "./uiSettingsTab/BetaFeatures";
import { PreferenceToggles } from "./uiSettingsTab/PreferenceToggles";

export const NewUITab: React.FC = () => {
export const UISettingsTab: React.FC = () => {
const { userBetaSettings } = useUserBetaFeatures();
const { adminBetaSettings } = useAdminBetaFeatures();

Expand Down
Loading

0 comments on commit 390dbc1

Please sign in to comment.