diff --git a/console/e2e-tests/platform.spec.ts b/console/e2e-tests/platform.spec.ts
index 46a704ef9ff22..2563abf9c1ec2 100644
--- a/console/e2e-tests/platform.spec.ts
+++ b/console/e2e-tests/platform.spec.ts
@@ -130,9 +130,8 @@ for (const region of REGIONS) {
// await testAccountBlocking(page, context, region);
// }
- // Wait for the onboarding survey to load then skip it
- await page.getByTestId("onboarding-survey").waitFor();
- await context.goto(`${CONSOLE_ADDR}/environment-not-ready/enable-region`);
+ // Wait for the enable region page to load
+ await page.getByTestId("enable-region").waitFor();
await retry(
async () => {
diff --git a/console/e2e-tests/util.ts b/console/e2e-tests/util.ts
index c22bb042ba58e..d51131f43fbd5 100644
--- a/console/e2e-tests/util.ts
+++ b/console/e2e-tests/util.ts
@@ -168,8 +168,8 @@ export class TestContext {
// Navigate to the home page && wait for that to load.
await context.goto(CONSOLE_ADDR);
- // We assume the first page is the onboarding survey
- await page.waitForSelector("[data-testid=onboarding-survey]");
+ // We assume the first page is the enable region page
+ await page.waitForSelector("[data-testid=enable-region]");
return context;
}
diff --git a/console/src/analytics/hubspot.test.ts b/console/src/analytics/hubspot.test.ts
index ab5367bad1eed..79e3d35e6c4c9 100644
--- a/console/src/analytics/hubspot.test.ts
+++ b/console/src/analytics/hubspot.test.ts
@@ -17,8 +17,6 @@ import {
import { getStore } from "~/jotai";
import {
- ONBOARDING_SURVEY_API_ENDPOINT,
- submitOnboardingSurvey,
TRACK_SIGNUP_API_ENDPOINT,
trackSignupInHubspot,
trackSignUpInHubspotActions,
@@ -35,22 +33,6 @@ const trackSignupErrorHandler = http.post(TRACK_SIGNUP_API_ENDPOINT, () => {
return HttpResponse.error();
});
-const onboardingSurveySuccessHandlerSpy = vi.fn();
-
-const onboardingSurveySuccessHandler = http.post(
- ONBOARDING_SURVEY_API_ENDPOINT,
- () => {
- onboardingSurveySuccessHandlerSpy();
- return HttpResponse.json({ ok: true });
- },
-);
-const onboardingSurveyErrorHandler = http.post(
- ONBOARDING_SURVEY_API_ENDPOINT,
- () => {
- return HttpResponse.error();
- },
-);
-
describe("trackSignupInHubspot", () => {
beforeEach(() => {
vi.resetAllMocks();
@@ -117,71 +99,6 @@ describe("trackSignupInHubspot", () => {
});
});
-describe("submitOnboardingSurvey", () => {
- beforeEach(() => {
- vi.resetAllMocks();
- });
-
- it("successfully calls the hubspot api", async () => {
- server.use(onboardingSurveySuccessHandler);
- await submitOnboardingSurvey({
- email: "someuser@example.com",
- organizationId: "9e8b1bc8-fa08-4870-a21f-22ac01cc3808",
- userId: "some-user-id",
- roleDescription: "Other",
- materializeUseCase: "Other",
- projectDescription: "Other",
- primaryDataSource: "Other",
- });
- expect(onboardingSurveySuccessHandlerSpy).toHaveBeenCalledOnce();
- });
-
- it("retries if the the call fails initially", async () => {
- server.use(
- http.post(
- TRACK_SIGNUP_API_ENDPOINT,
- () => {
- return HttpResponse.error();
- },
- { once: true },
- ),
- onboardingSurveySuccessHandler,
- );
- await submitOnboardingSurvey(
- {
- email: "someuser@example.com",
- organizationId: "9e8b1bc8-fa08-4870-a21f-22ac01cc3808",
- userId: "some-user-id",
- roleDescription: "Other",
- materializeUseCase: "Other",
- projectDescription: "Other",
- primaryDataSource: "Other",
- },
- { retryDelay: 10 },
- );
- expect(onboardingSurveySuccessHandlerSpy).toHaveBeenCalledOnce();
- });
-
- it("fails after 3 tries", async () => {
- server.use(onboardingSurveyErrorHandler);
- await expect(() =>
- submitOnboardingSurvey(
- {
- email: "someuser@example.com",
- organizationId: "9e8b1bc8-fa08-4870-a21f-22ac01cc3808",
- userId: "some-user-id",
- roleDescription: "Other",
- materializeUseCase: "Other",
- projectDescription: "Other",
- primaryDataSource: "Other",
- },
- { retryDelay: 10 },
- ),
- ).rejects.toThrowError();
- expect(onboardingSurveySuccessHandlerSpy).not.toHaveBeenCalled();
- });
-});
-
describe("trackSignUpInHubspotActions", () => {
it("should reset state on userVerified when in signedUp state", async () => {
const store = getStore();
diff --git a/console/src/analytics/hubspot.ts b/console/src/analytics/hubspot.ts
index 597677e4e970c..99f1e0350df31 100644
--- a/console/src/analytics/hubspot.ts
+++ b/console/src/analytics/hubspot.ts
@@ -17,14 +17,7 @@ import {
} from "~/external-library-wrappers/frontegg";
import { getStore } from "~/jotai";
import { getQueryClient } from "~/queryClient";
-import { notNullOrUndefined } from "~/util";
-import {
- MaterializeUseCase,
- PrimaryDataSource,
- ProjectDescription,
- RoleDescription,
-} from "./onboardingSurveyOptions";
import { segment } from "./segment";
async function getAnonymousId() {
@@ -60,11 +53,6 @@ export const TRACK_SIGNUP_API_ENDPOINT = buildFormSubmissionUrl({
formGuid: "e1f0065e-c5ec-4004-afb7-d4aeab96c6b2",
});
-export const ONBOARDING_SURVEY_API_ENDPOINT = buildFormSubmissionUrl({
- portalId: "23399445",
- formGuid: "7038d05b-0ad2-4c85-8ef7-36a163c6ddaf",
-});
-
type HubspotPayload = {
fields: { name: string; value: string }[];
context: { pageUri: string; hutk?: string };
@@ -76,10 +64,6 @@ export const hubspotQueryKeys = {
...hubspotQueryKeys.all(),
buildGlobalQueryKey("track-signup"),
],
- onboardingSurvey: () => [
- ...hubspotQueryKeys.all(),
- buildGlobalQueryKey("onboarding-survey"),
- ],
};
export async function trackSignupInHubspot(
@@ -204,112 +188,3 @@ export const trackSignUpInHubspotActions = {
}
},
};
-
-type OnboardingSurveyPayload = {
- email: string;
- organizationId: string;
- userId: string;
- roleDescription: RoleDescription;
- roleDescriptionDetails?: string;
- materializeUseCase: MaterializeUseCase;
- materializeUseCaseDetails?: string;
- projectDescription: ProjectDescription;
- projectDescriptionDetails?: string;
- primaryDataSource: PrimaryDataSource;
- primaryDataSourceDetails?: string;
-};
-
-export async function submitOnboardingSurvey(
- payload: OnboardingSurveyPayload,
- options?: { retryDelay?: number },
-) {
- const data: HubspotPayload = {
- fields: [
- { name: "email", value: payload.email },
- { name: "organization_id", value: payload.organizationId },
- { name: "mz_user_id", value: payload.userId },
-
- {
- name: "how_would_you_describe_your_role_",
- value: payload.roleDescription,
- },
-
- {
- name: "why_are_you_trying_materialize_",
- value: payload.materializeUseCase,
- },
-
- {
- name: "what_are_you_trying_to_solve_with_materialize_",
- value: payload.projectDescription,
- },
-
- {
- name: "what_is_the_primary_or_origin_data_source_",
- value: payload.primaryDataSource,
- },
- ],
- context: {
- pageUri: window.location.href,
- },
- };
-
- [
- {
- name: "how_would_you_describe_your_role__details",
- value: payload.roleDescriptionDetails,
- },
- {
- name: "why_are_you_trying_materialize__details",
- value: payload.materializeUseCaseDetails,
- },
- {
- name: "what_are_you_trying_to_solve_with_materialize__details",
- value: payload.projectDescriptionDetails,
- },
- {
- name: "what_is_the_primary_or_origin_data_source__details",
- value: payload.primaryDataSourceDetails,
- },
- ].forEach(({ name, value }) => {
- if (notNullOrUndefined(value)) {
- data.fields.push({
- name: name,
- value: value,
- });
- }
- });
-
- const hutk = getHubspotUtk();
- if (hutk) {
- data.context = {
- ...data.context,
- hutk,
- };
- }
-
- return getQueryClient()
- .getMutationCache()
- .build(getQueryClient(), {
- mutationKey: hubspotQueryKeys.onboardingSurvey(),
- mutationFn: (params: HubspotPayload) => {
- return fetch(ONBOARDING_SURVEY_API_ENDPOINT, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(params),
- });
- },
- retry: 3,
- retryDelay: options?.retryDelay,
- onError: (error) => {
- Sentry.captureException(
- new Error("Hubspot onboarding survey submit failed", {
- cause: error,
- }),
- );
- },
- })
- .execute(data);
-}
diff --git a/console/src/analytics/onboardingSurveyOptions.ts b/console/src/analytics/onboardingSurveyOptions.ts
deleted file mode 100644
index d22778cbc6239..0000000000000
--- a/console/src/analytics/onboardingSurveyOptions.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright Materialize, Inc. and contributors. All rights reserved.
-//
-// Use of this software is governed by the Business Source License
-// included in the LICENSE file.
-//
-// As of the Change Date specified in that file, in accordance with
-// the Business Source License, use of this software will be governed
-// by the Apache License, Version 2.0.
-
-// Form values for the onboarding survey that's submitted via Hubspot
-
-export const OTHER_OPTION = { label: "Other", value: "Other" } as const;
-
-export const ROLE_DESCRIPTION_OPTIONS = [
- { label: "Data Engineer", value: "Data Engineer" },
- { label: "Data Analyst", value: "Data Analyst" },
- { label: "ML Engineer", value: "ML Engineer" },
- { label: "Software Engineer", value: "Software Engineer" },
- { label: "Data Architect", value: "Data Architect" },
- { label: "Database Administrator", value: "Database Administrator" },
- { label: "Technical Executive", value: "Technical Executive" },
- { label: "Student", value: "Student" },
- OTHER_OPTION,
-] as const;
-
-export type RoleDescription =
- (typeof ROLE_DESCRIPTION_OPTIONS)[number]["value"];
-
-export const MATERIALIZE_USE_CASE_OPTIONS = [
- {
- label: "My company is evaluating Materialize",
- value: "My company is evaluating Materialize",
- },
- {
- label: "I’m evaluating Materialize for a client",
- value: "I’m evaluating Materialize for a client",
- },
- {
- label: "I’m exploring new technologies",
- value: "I’m exploring new technologies",
- },
- OTHER_OPTION,
-] as const;
-
-export type MaterializeUseCase =
- (typeof MATERIALIZE_USE_CASE_OPTIONS)[number]["value"];
-
-export const PROJECT_DESCRIPTION_OPTIONS = [
- {
- label: "Improve the performance of complex reads",
- value: "Improve the performance of complex reads",
- },
- {
- label: "Join and act on data from multiple sources",
- value: "Join and act on data from multiple sources",
- },
- {
- label: "Share operational data across teams and services",
- value: "Share operational data across teams and services",
- },
- OTHER_OPTION,
-] as const;
-
-export type ProjectDescription =
- (typeof PROJECT_DESCRIPTION_OPTIONS)[number]["value"];
-
-export const PRIMARY_DATA_SOURCE_OPTIONS = [
- {
- label:
- "PostgreSQL (Amazon RDS, Amazon Aurora, Azure DB, Google Cloud SQL, AlloyDB, Self-hosted PostgresSQL)",
- value: "PostgreSQL",
- },
- {
- label:
- "MySQL (Amazon RDS, Amazon Aurora, Azure DB, Google Cloud SQL, Self-hosted MySQL)",
- value: "MySQL",
- },
- {
- label:
- "Kafka (Apache Kafka, Confluent Cloud, Amazon MSK, WarpStream, Redpanda (Cloud))",
- value: "Kafka",
- },
- {
- label:
- "Cloud Data Warehouse (Amazon Redshift, Google BigQuery, Microsoft Azure, Snowflake)",
- value: "Cloud Data Warehouse",
- },
- {
- label: "Object storage (AWS S3, GCP Cloud Storage, Azure Blob Storage)",
- value: "Object storage / S3",
- },
- { label: "Webhooks", value: "Webhooks" },
- OTHER_OPTION,
-] as const;
-
-export type PrimaryDataSource =
- (typeof PRIMARY_DATA_SOURCE_OPTIONS)[number]["value"];
diff --git a/console/src/platform/environment-not-ready/EnableRegion.tsx b/console/src/platform/environment-not-ready/EnableRegion.tsx
index 67637d147c06c..77c47e7c4bf89 100644
--- a/console/src/platform/environment-not-ready/EnableRegion.tsx
+++ b/console/src/platform/environment-not-ready/EnableRegion.tsx
@@ -14,7 +14,9 @@ import { Navigate } from "react-router-dom";
import ErrorBox from "~/components/ErrorBox";
import { RegionSelectorForm } from "~/components/RegionSelectorForm";
+import TextLink from "~/components/TextLink";
import { User } from "~/external-library-wrappers/frontegg";
+import docUrls from "~/mz-doc-urls.json";
import CreateEnvironmentButton from "~/platform/environment-not-ready/CreateEnvironmentButton";
import useCreateEnvironment from "~/platform/environment-not-ready/useCreateEnvironment";
import { homePagePath } from "~/platform/routeHelpers";
@@ -60,6 +62,30 @@ const EnableRegionContent = ({ user }: { user: User }) => {
Welcome to Materialize
+
+ To get started, enable a region. A region is a dedicated Materialize
+ environment that runs in the cloud provider region you choose.
+
+
+ Every new region starts with a default 25cc quickstart
+ cluster for trying out Materialize. This cluster accrues a{" "}
+
+ baseline cost
+ {" "}
+ from the moment the region is enabled, until you drop it.
+
{
w="full"
alignItems="center"
justifyContent="center"
+ data-testid="enable-region"
>
diff --git a/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.test.tsx b/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.test.tsx
new file mode 100644
index 0000000000000..02ca23bdfeea7
--- /dev/null
+++ b/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.test.tsx
@@ -0,0 +1,94 @@
+// Copyright Materialize, Inc. and contributors. All rights reserved.
+//
+// Use of this software is governed by the Business Source License
+// included in the LICENSE file.
+//
+// As of the Change Date specified in that file, in accordance with
+// the Business Source License, use of this software will be governed
+// by the Apache License, Version 2.0.
+
+import { screen, waitFor } from "@testing-library/react";
+import React from "react";
+
+import server from "~/api/mocks/server";
+import { dummyValidUser } from "~/external-library-wrappers/__mocks__/frontegg";
+import {
+ disabledEnvironment,
+ InitializeStateFn,
+ renderComponent,
+ RenderWithPathname,
+ setFakeEnvironment,
+} from "~/test/utils";
+
+import { EnvironmentNotReadyRoutes } from "./EnvironmentNotReadyRoutes";
+
+const renderRoutes = (
+ initialRouterEntries: string[],
+ initializeState: InitializeStateFn = ({ set }) =>
+ setFakeEnvironment(set, "aws/us-east-1", disabledEnvironment),
+) => {
+ return renderComponent(
+
+
+ ,
+ { initializeState, initialRouterEntries },
+ );
+};
+
+describe("EnvironmentNotReadyRoutes", () => {
+ afterEach(() => {
+ server.resetHandlers();
+ vi.clearAllMocks();
+ });
+
+ it("shows the region selector on the enable-region route", async () => {
+ await renderRoutes(["/enable-region"]);
+ expect(
+ await screen.findByText(
+ "Where would you like to run your Materialize environment?",
+ ),
+ ).toBeVisible();
+ });
+
+ it("explains what a region is and its baseline cost", async () => {
+ await renderRoutes(["/enable-region"]);
+ expect(
+ await screen.findByText(
+ "A region is a dedicated Materialize environment",
+ { exact: false },
+ ),
+ ).toBeVisible();
+ expect(
+ screen.getByText("Every new region starts with a default", {
+ exact: false,
+ }),
+ ).toBeVisible();
+ expect(screen.getByRole("link", { name: "baseline cost" })).toHaveAttribute(
+ "href",
+ expect.stringContaining("billing"),
+ );
+ });
+
+ it("redirects the root path directly to enable-region", async () => {
+ await renderRoutes(["/"]);
+ await waitFor(() => {
+ expect(screen.getByTestId("pathname")).toHaveTextContent(
+ "/enable-region",
+ );
+ });
+ expect(
+ await screen.findByText(
+ "Where would you like to run your Materialize environment?",
+ ),
+ ).toBeVisible();
+ });
+
+ it("redirects the removed onboarding-survey route to enable-region", async () => {
+ await renderRoutes(["/onboarding-survey"]);
+ await waitFor(() => {
+ expect(screen.getByTestId("pathname")).toHaveTextContent(
+ "/enable-region",
+ );
+ });
+ });
+});
diff --git a/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.tsx b/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.tsx
index 770b7a2f8516b..34c8214aec1c5 100644
--- a/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.tsx
+++ b/console/src/platform/environment-not-ready/EnvironmentNotReadyRoutes.tsx
@@ -16,22 +16,14 @@ import { SentryRoutes } from "~/sentry";
import EnableRegion from "./EnableRegion";
import { EnvironmentNotReadyLayout } from "./Layout";
import { OnboardingSteps } from "./OnboardingSteps";
-import OnboardingSurvey from "./OnboardingSurvey";
export const EnvironmentNotReadyRoutes = ({ user }: { user: User }) => {
return (
- }
- />
} />
} />
- }
- />
+ } />
);
diff --git a/console/src/platform/environment-not-ready/OnboardingSurvey.tsx b/console/src/platform/environment-not-ready/OnboardingSurvey.tsx
deleted file mode 100644
index d2809b54f4960..0000000000000
--- a/console/src/platform/environment-not-ready/OnboardingSurvey.tsx
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright Materialize, Inc. and contributors. All rights reserved.
-//
-// Use of this software is governed by the Business Source License
-// included in the LICENSE file.
-//
-// As of the Change Date specified in that file, in accordance with
-// the Business Source License, use of this software will be governed
-// by the Apache License, Version 2.0.
-
-import {
- Button,
- chakra,
- FormControl,
- FormErrorMessage,
- FormLabel,
- HStack,
- Text,
- Textarea,
- Tooltip,
- VStack,
-} from "@chakra-ui/react";
-import React from "react";
-import { useForm } from "react-hook-form";
-import { Navigate, useNavigate } from "react-router-dom";
-
-import { submitOnboardingSurvey } from "~/analytics/hubspot";
-import {
- MATERIALIZE_USE_CASE_OPTIONS,
- MaterializeUseCase,
- OTHER_OPTION,
- PRIMARY_DATA_SOURCE_OPTIONS,
- PrimaryDataSource,
- PROJECT_DESCRIPTION_OPTIONS,
- ProjectDescription,
- ROLE_DESCRIPTION_OPTIONS,
- RoleDescription,
-} from "~/analytics/onboardingSurveyOptions";
-import SimpleSelect from "~/components/SimpleSelect";
-import { AppConfigSwitch } from "~/config/AppConfigSwitch";
-import { User } from "~/external-library-wrappers/frontegg";
-import { useEnvironmentsWithHealth } from "~/store/environments";
-
-import ContactSalesCta from "./ContactSalesCta";
-import { NAVBAR_HEIGHT } from "./Layout";
-
-const PLACEHOLDER_TEXT = "Select...";
-
-type FormState = {
- roleDescription: RoleDescription;
- roleDescriptionDetails?: string;
- materializeUseCase: MaterializeUseCase;
- materializeUseCaseDetails?: string;
- projectDescription: ProjectDescription;
- projectDescriptionDetails?: string;
- primaryDataSource: PrimaryDataSource;
- primaryDataSourceDetails?: string;
-};
-
-const SkipSurveyButton = ({
- onClick,
-}: {
- onClick: (e: React.MouseEvent) => void;
-}) => (
-
-);
-
-const OnboardingSurvey = ({ user }: { user: User }) => {
- const environments = useEnvironmentsWithHealth();
- const navigate = useNavigate();
-
- const { register, handleSubmit, formState, watch } = useForm({
- mode: "onTouched",
- });
-
- const [
- roleDescription,
- materializeUseCase,
- projectDescription,
- primaryDataSource,
- ] = watch([
- "roleDescription",
- "materializeUseCase",
- "projectDescription",
- "primaryDataSource",
- ]);
-
- const { errors } = formState;
-
- const someEnvironmentNotDisabled = Array.from(environments.values()).some(
- (env) => env.state !== "disabled",
- );
-
- if (someEnvironmentNotDisabled) {
- return ;
- }
-
- const onSubmit = handleSubmit(async (data) => {
- try {
- await submitOnboardingSurvey({
- ...data,
- email: user.email,
- organizationId: user.tenantId,
- userId: user.id,
- });
- } catch {
- // Even if this survey fails to submit, we don't want to block
- // onboarding
- console.error("Failed to submit onboarding survey");
- }
- navigate("../enable-region");
- });
-
- return (
-
-
-
-
-
- Your information
-
-
- We'd love to help you get started on the right foot with
- Materialize!
-
-
-
- What is your role?
-
- {ROLE_DESCRIPTION_OPTIONS.map((role) => (
-
- ))}
-
- {errors.roleDescription && (
-
- {errors.roleDescription.message}
-
- )}
-
- {roleDescription === OTHER_OPTION.value && (
-
- Please describe your role
-
-
- )}
-
-
- What brings you to Materialize?
-
- {MATERIALIZE_USE_CASE_OPTIONS.map((useCase) => (
-
- ))}
-
- {errors.materializeUseCase && (
-
- {errors.materializeUseCase.message}
-
- )}
-
- {materializeUseCase === OTHER_OPTION.value && (
-
- Please provide more details
-
-
- )}
-
-
-
- What problem are you trying to solve with Materialize?
-
-
- {PROJECT_DESCRIPTION_OPTIONS.map((project) => (
-
- ))}
-
- {errors.projectDescription && (
-
- {errors.projectDescription.message}
-
- )}
-
- {projectDescription === OTHER_OPTION.value && (
-
- Please describe your problem
-
-
- )}
-
-
- What is your primary data source?
-
- {PRIMARY_DATA_SOURCE_OPTIONS.map((source) => (
-
- ))}
-
- {errors.primaryDataSource && (
-
- {errors.primaryDataSource.message}
-
- )}
-
- {primaryDataSource === OTHER_OPTION.value && (
-
-
- Please describe your primary data source
-
-
-
- )}
-
-
-
-
-
-
-
- // We only show the skip survey button for internal / non-production environments.
- currentStack !== "production" && (
- navigate("../enable-region")}
- />
- )
- }
- />
-
-
-
-
-
-
-
-
- );
-};
-
-export default OnboardingSurvey;