Skip to content

Commit

Permalink
DEVPROD-10207: Add waterfall modal [minor] (#608)
Browse files Browse the repository at this point in the history
  • Loading branch information
sophstad authored Feb 4, 2025
1 parent 0cf158f commit 46edf09
Show file tree
Hide file tree
Showing 32 changed files with 592 additions and 661 deletions.
22 changes: 5 additions & 17 deletions apps/spruce/cypress/integration/announcements.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
import {
CY_DISABLE_NEW_USER_WELCOME_MODAL,
CY_DISABLE_COMMITS_WELCOME_MODAL,
} from "constants/cookies";
import { CY_DISABLE_COMMITS_WELCOME_MODAL } from "constants/cookies";

describe("Announcement overlays", () => {
it("Displays a welcome modal only when you first visit spruce", () => {
cy.clearCookie(CY_DISABLE_NEW_USER_WELCOME_MODAL);
cy.visit("/");
cy.dataCy("welcome-modal").should("exist");
cy.dataCy("close-welcome-modal").click();
cy.visit("/");
cy.dataCy("welcome-modal").should("not.exist");
});

it("Should not show a Sitewide banner after it has been dismissed", () => {
cy.clearCookie("This is an important notification");
cy.visit("/");
Expand All @@ -36,12 +24,12 @@ describe("Announcement overlays", () => {
});
});

it("visiting the commits page for the first time should show a welcome modal", () => {
it("visiting the commits page for the first time should show the waterfall beta modal", () => {
cy.clearCookie(CY_DISABLE_COMMITS_WELCOME_MODAL);
cy.visit("/commits/spruce");
cy.dataCy("welcome-modal").should("be.visible");
cy.dataCy("close-welcome-modal").click();
cy.dataCy("waterfall-modal").should("be.visible");
cy.contains("Maybe later, continue to Project Health").click();
cy.reload();
cy.dataCy("welcome-modal").should("not.exist");
cy.dataCy("waterfall-modal").should("not.exist");
});
});
2 changes: 0 additions & 2 deletions apps/spruce/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import "./commands";
import {
CY_DISABLE_COMMITS_WELCOME_MODAL,
CY_DISABLE_NEW_USER_WELCOME_MODAL,
SLACK_NOTIFICATION_BANNER,
SEEN_IMAGE_VISIBILITY_GUIDE_CUE,
SEEN_TEST_ANALYSIS_TAB_GUIDE_CUE,
Expand Down Expand Up @@ -175,7 +174,6 @@ before(() => {
cy.login();
cy.setCookie(bannerCookie, "true");
cy.setCookie(CY_DISABLE_COMMITS_WELCOME_MODAL, "true");
cy.setCookie(CY_DISABLE_NEW_USER_WELCOME_MODAL, "true");
cy.setCookie(SLACK_NOTIFICATION_BANNER, "true");
cy.setCookie(SEEN_IMAGE_VISIBILITY_GUIDE_CUE, "true");
cy.setCookie(SEEN_TEST_ANALYSIS_TAB_GUIDE_CUE, "true");
Expand Down
1 change: 1 addition & 0 deletions apps/spruce/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@leafygreen-ui/interaction-ring": "^7.0.2",
"@leafygreen-ui/leafygreen-provider": "^3.2.0",
"@leafygreen-ui/loading-indicator": "^2.0.12",
"@leafygreen-ui/marketing-modal": "^5.0.2",
"@leafygreen-ui/menu": "^20.0.1",
"@leafygreen-ui/modal": "^16.0.3",
"@leafygreen-ui/number-input": "^2.1.0",
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { AnalyticsIdentifier } from "analytics/types";
type Action =
| { name: "Changed tab"; tab: string }
| { name: "Saved profile info" }
| { name: "Saved beta feature settings" }
| {
name: "Saved beta feature settings";
"beta_features.spruce_waterfall_enabled": boolean;
}
| { name: "Saved notification preferences" }
| { name: "Deleted subscriptions" }
| { name: "Clicked CLI download link"; "download.name": string }
Expand Down
6 changes: 5 additions & 1 deletion apps/spruce/src/analytics/waterfall/useWaterfallAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ type Action =
| { name: "Changed page"; direction: "next" | "previous" }
| { name: "Deleted one filter chip" }
| { name: "Deleted all filter chips" }
| { name: "Toggled task icon legend"; open: boolean };
| { name: "Toggled task icon legend"; open: boolean }
| {
name: "Viewed waterfall beta modal";
"beta_features.spruce_waterfall_enabled": boolean;
};

export const useWaterfallAnalytics = () => {
const { [slugs.projectIdentifier]: projectIdentifier } = useParams();
Expand Down
19 changes: 0 additions & 19 deletions apps/spruce/src/components/Content/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useQuery } from "@apollo/client";
import styled from "@emotion/styled";
import { palette } from "@leafygreen-ui/palette";
import Cookies from "js-cookie";
import { Outlet } from "react-router-dom";
import { FullPageLoad } from "@evg-ui/lib/components/FullPageLoad";
import { size, transitionDuration } from "@evg-ui/lib/constants/tokens";
Expand All @@ -10,22 +9,14 @@ import { Feedback } from "components/Feedback";
import { Header } from "components/Header";
import { SiteLayout } from "components/styles/Layout";
import { TaskStatusIconLegend } from "components/TaskStatusIconLegend";
import WelcomeModal from "components/WelcomeModal";
import { CY_DISABLE_NEW_USER_WELCOME_MODAL } from "constants/cookies";
import { newSpruceUser } from "constants/welcomeModalProps";
import { useAuthStateContext } from "context/Auth";
import { UserQuery, UserQueryVariables } from "gql/generated/types";
import { USER } from "gql/queries";
import { useUserSettings } from "hooks";
import { useAnnouncementToast } from "hooks/useAnnouncementToast";
import { WaterfallScrollToTop } from "pages/waterfall/ScrollToTop";
import { isProduction } from "utils/environmentVariables";

const { gray, white } = palette;

const shouldDisableForTest =
!isProduction() && Cookies.get(CY_DISABLE_NEW_USER_WELCOME_MODAL) === "true";

export const Layout: React.FC = () => {
const { isAuthenticated } = useAuthStateContext();
useAnnouncementToast();
Expand All @@ -36,9 +27,6 @@ export const Layout: React.FC = () => {
const { data } = useQuery<UserQuery, UserQueryVariables>(USER);
useAnalyticsAttributes(data?.user?.userId ?? "");
localStorage.setItem("userId", data?.user?.userId ?? "");
const { userSettings } = useUserSettings();
const { useSpruceOptions } = userSettings ?? {};
const { hasUsedSpruceBefore = true } = useSpruceOptions ?? {};

if (!isAuthenticated) {
return <FullPageLoad />;
Expand All @@ -48,13 +36,6 @@ export const Layout: React.FC = () => {
<SiteLayout>
<Header />
<Outlet />
{!shouldDisableForTest && !hasUsedSpruceBefore && (
<WelcomeModal
carouselCards={newSpruceUser}
param="hasUsedSpruceBefore"
title="Welcome to the New Evergreen UI!"
/>
)}
<FloatingContent>
<WaterfallScrollToTop />
<TaskStatusIconLegend />
Expand Down
140 changes: 72 additions & 68 deletions apps/spruce/src/components/Content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "components/Redirects";
import { showWaterfallPage } from "constants/featureFlags";
import { redirectRoutes, routes, slugs } from "constants/routes";
import { useAdminBetaFeatures } from "hooks";
import { Commits } from "pages/Commits";
import { ConfigurePatch } from "pages/ConfigurePatch";
import { Container } from "pages/Container";
Expand All @@ -31,75 +32,78 @@ import { VersionPage } from "pages/Version";
import { Waterfall } from "pages/Waterfall";
import { Layout } from "./Layout";

export const Content: React.FC = () => (
<Routes>
<Route element={<Layout />}>
<Route element={<Navigate to={routes.myPatches} />} path="/" />
<Route element={<Commits />} path={routes.commits} />
<Route element={<Container />} path={routes.container} />
<Route
element={<WaterfallCommitsRedirect />}
path={redirectRoutes.waterfall}
/>
<Route element={<ConfigurePatch />} path={routes.configurePatch}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<Distro />} path={routes.distroSettings}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route
element={<DistroSettingsRedirect />}
path={redirectRoutes.distroSettings}
/>
<Route element={<Host />} path={routes.host} />
<Route element={<Hosts />} path={routes.hosts} />
<Route element={<Image />} path={`${routes.image}/*`}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={null} path={routes.jobLogs}>
<Route element={<JobLogs isLogkeeper />} path={`:${slugs.buildId}`}>
<Route element={null} path={`:${slugs.groupId}`} />
export const Content: React.FC = () => {
const { adminBetaSettings } = useAdminBetaFeatures();
return (
<Routes>
<Route element={<Layout />}>
<Route element={<Navigate to={routes.myPatches} />} path="/" />
<Route element={<Commits />} path={routes.commits} />
<Route element={<Container />} path={routes.container} />
<Route
element={<WaterfallCommitsRedirect />}
path={redirectRoutes.waterfall}
/>
<Route element={<ConfigurePatch />} path={routes.configurePatch}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<Distro />} path={routes.distroSettings}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route
element={<JobLogs isLogkeeper={false} />}
path={`:${slugs.taskId}/:${slugs.execution}/:${slugs.groupId}`}
element={<DistroSettingsRedirect />}
path={redirectRoutes.distroSettings}
/>
<Route element={<Host />} path={routes.host} />
<Route element={<Hosts />} path={routes.hosts} />
<Route element={<Image />} path={`${routes.image}/*`}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={null} path={routes.jobLogs}>
<Route element={<JobLogs isLogkeeper />} path={`:${slugs.buildId}`}>
<Route element={null} path={`:${slugs.groupId}`} />
</Route>
<Route
element={<JobLogs isLogkeeper={false} />}
path={`:${slugs.taskId}/:${slugs.execution}/:${slugs.groupId}`}
/>
</Route>
<Route element={<MyPatches />} path={routes.myPatches} />
<Route element={<PatchRedirect />} path={redirectRoutes.patch}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<Preferences />} path={routes.preferences}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<ProjectPatches />} path={routes.projectPatches} />
<Route element={<ProjectSettings />} path={routes.projectSettings}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route
element={<ProjectSettingsRedirect />}
path={redirectRoutes.projectSettings}
/>
<Route element={<Spawn />} path={routes.spawn}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<Task />} path={routes.task} />
<Route element={<TaskHistory />} path={routes.taskHistory} />
<Route
element={<TaskQueue />}
path={`${routes.taskQueue}/:${slugs.distroId}?`}
/>
<Route element={<UserPatches />} path={routes.userPatches} />
<Route
element={<UserPatchesRedirect />}
path={redirectRoutes.userPatches}
/>
<Route element={<VariantHistory />} path={routes.variantHistory} />
<Route element={<VersionPage />} path={routes.version} />
{(showWaterfallPage || adminBetaSettings?.spruceWaterfallEnabled) && (
<Route element={<Waterfall />} path={routes.waterfall} />
)}
<Route element={<PageDoesNotExist />} path="*" />
</Route>
<Route element={<MyPatches />} path={routes.myPatches} />
<Route element={<PatchRedirect />} path={redirectRoutes.patch}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<Preferences />} path={routes.preferences}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<ProjectPatches />} path={routes.projectPatches} />
<Route element={<ProjectSettings />} path={routes.projectSettings}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route
element={<ProjectSettingsRedirect />}
path={redirectRoutes.projectSettings}
/>
<Route element={<Spawn />} path={routes.spawn}>
<Route element={null} path={`:${slugs.tab}`} />
</Route>
<Route element={<Task />} path={routes.task} />
<Route element={<TaskHistory />} path={routes.taskHistory} />
<Route
element={<TaskQueue />}
path={`${routes.taskQueue}/:${slugs.distroId}?`}
/>
<Route element={<UserPatches />} path={routes.userPatches} />
<Route
element={<UserPatchesRedirect />}
path={redirectRoutes.userPatches}
/>
<Route element={<VariantHistory />} path={routes.variantHistory} />
<Route element={<VersionPage />} path={routes.version} />
{showWaterfallPage && (
<Route element={<Waterfall />} path={routes.waterfall} />
)}
<Route element={<PageDoesNotExist />} path="*" />
</Route>
</Routes>
);
</Routes>
);
};
Loading

0 comments on commit 46edf09

Please sign in to comment.