Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions console/src/components/ShowCreateBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ export const ShowCreateBlockInner = ({

return <ExpandableCodeBlock text={tryPrettyStr(showCreate.sql, 100)} />;
};

export default ShowCreateBlock;
10 changes: 9 additions & 1 deletion console/src/config/AppConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,15 @@ export class CloudAppConfig implements IBaseAppConfig {
stackSwitcherEnabled =
!this.isImpersonating && this.#consoleEnvironment !== "production";

stripePromise = getStripePromise(this.#consoleEnvironment);
// Lazy so the Stripe.js script only loads when the billing route reads
// this property; never fetched on cold load for other routes.
#stripePromise?: ReturnType<typeof getStripePromise>;
get stripePromise() {
if (!this.#stripePromise) {
this.#stripePromise = getStripePromise(this.#consoleEnvironment);
}
return this.#stripePromise;
}

// Whether query retries are enabled. False for test environments.
// TODO (password-auth): Remove the possibility of defaultStack being "test". Should be able to figure
Expand Down
22 changes: 13 additions & 9 deletions console/src/config/apiKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

import { loadStripe } from "@stripe/stripe-js";
import type { Stripe } from "@stripe/stripe-js";

export const getLaunchDarklyKey = (consoleEnv: string) => {
if (consoleEnv === "production") {
Expand Down Expand Up @@ -43,12 +43,16 @@ export const getSegmentApiKey = ({
return "dGeQYRjmGVsqDI0KIARrAhTvk1BdJJhk";
};

export const getStripePromise = (consoleEnv: string) => {
if (consoleEnv === "production") {
// Production key
return loadStripe("pk_live_eILilEpJ7DCwmw9I4JHuBLEB001qSrxuw0");
}

// Stripe development key
return loadStripe("pk_test_XUB2NGLtbtzx9HQbTKlP1ZCw00FZqUgrXf");
export const getStripePromise = async (
consoleEnv: string,
): Promise<Stripe | null> => {
// Dynamic import keeps @stripe/stripe-js out of the main bundle; combined
// with the lazy getter on AppConfig.stripePromise, the Stripe.js script
// only loads when the billing route is visited.
const { loadStripe } = await import("@stripe/stripe-js");
const key =
consoleEnv === "production"
? "pk_live_eILilEpJ7DCwmw9I4JHuBLEB001qSrxuw0"
: "pk_test_XUB2NGLtbtzx9HQbTKlP1ZCw00FZqUgrXf";
return loadStripe(key);
};
28 changes: 22 additions & 6 deletions console/src/hooks/useIntercom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,34 @@
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

import Intercom from "@intercom/messenger-js-sdk";
import { useEffect } from "react";

import { useIntercomJwt } from "~/api/auth";
const APP_ID = "r8661p0d";

/**
* Loads the Intercom SDK and boots it off the critical path. The SDK module is
* dynamically imported (own chunk) and the boot call is scheduled in idle time
* so it does not compete with first-paint bandwidth/CPU.
*/
function bootIntercomDeferred(config: {
app_id: string;
intercom_user_jwt?: string;
}) {
const schedule =
typeof window.requestIdleCallback === "function"
? (cb: () => void) =>
window.requestIdleCallback(cb, { timeout: 3000 })
: (cb: () => void) => window.setTimeout(cb, 1000);
schedule(async () => {
const { default: Intercom } = await import("@intercom/messenger-js-sdk");
Intercom(config);
});
}

export function useIntercomAnonymous() {
useEffect(() => {
const anonymousConfig = {
app_id: APP_ID,
};
Intercom(anonymousConfig);
bootIntercomDeferred({ app_id: APP_ID });
}, []);
}

Expand All @@ -28,7 +44,7 @@ export function useIntercom() {

useEffect(() => {
if (jwt) {
Intercom({ app_id: APP_ID, intercom_user_jwt: jwt });
bootIntercomDeferred({ app_id: APP_ID, intercom_user_jwt: jwt });
}
}, [jwt]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import React from "react";

import { ShowCreateObjectType } from "~/api/materialize/showCreate";
import { LoadingContainer } from "~/components/LoadingContainer";
import { ShowCreateBlock } from "~/components/ShowCreateBlock";
import { ObjectColumnsList } from "~/platform/object-explorer/ObjectColumns";

import { MaintainedObjectListItem } from "./queries";
import { SourceDiagnostics } from "./SourceDiagnostics";

const ShowCreateBlock = React.lazy(
() => import("~/components/ShowCreateBlock"),
);

export interface ObjectMetadataProps {
item: MaintainedObjectListItem;
}
Expand Down
15 changes: 10 additions & 5 deletions console/src/platform/object-explorer/ConnectionDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { ConnectionDependency } from "~/api/materialize/object-explorer/connecti
import { ShowCreateObjectType } from "~/api/materialize/showCreate";
import { AppErrorBoundary } from "~/components/AppErrorBoundary";
import { LoadingContainer } from "~/components/LoadingContainer";
import { ShowCreateBlock } from "~/components/ShowCreateBlock";
import TextLink from "~/components/TextLink";
import { MainContentContainer } from "~/layouts/BaseLayout";
import { MaterializeTheme } from "~/theme";
Expand All @@ -37,6 +36,10 @@ import { useConnectionDependencies, useObjectDetails } from "./queries";
import { relativeObjectPath } from "./routerHelpers";
import { ObjectDetailsParams } from "./useSchemaObjectParams";

const ShowCreateBlock = React.lazy(
() => import("~/components/ShowCreateBlock"),
);

const ConnectionDependencyTable = ({
connectionDependencies,
}: {
Expand Down Expand Up @@ -126,10 +129,12 @@ export const ConnectionDetailsContent = ({
<MainContentContainer>
<ObjectDetailsContainer>
<ObjectDetailsStrip {...object} />
<ShowCreateBlock
{...object}
objectType={object.type as ShowCreateObjectType}
/>
<React.Suspense fallback={<LoadingContainer />}>
<ShowCreateBlock
{...object}
objectType={object.type as ShowCreateObjectType}
/>
</React.Suspense>
{connectionDependencies.length > 0 && (
<ConnectionDependencyTable
connectionDependencies={connectionDependencies}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import {
import { ALLOWED_OBJECT_TYPES } from "~/api/materialize/workflowGraph";
import { AppErrorBoundary } from "~/components/AppErrorBoundary";
import { LoadingContainer } from "~/components/LoadingContainer";
import { ShowCreateBlock } from "~/components/ShowCreateBlock";
import WorkflowGraph from "~/components/WorkflowGraph/WorkflowGraph";
import { useFlags } from "~/hooks/useFlags";
import { MainContentContainer, Tab } from "~/layouts/BaseLayout";
import { SentryRoutes } from "~/sentry";
Expand All @@ -38,6 +36,14 @@ const DataflowVisualizer = React.lazy(
() => import("~/platform/clusters/DataflowVisualizer"),
);

const ShowCreateBlock = React.lazy(
() => import("~/components/ShowCreateBlock"),
);

const WorkflowGraph = React.lazy(
() => import("~/components/WorkflowGraph/WorkflowGraph"),
);

const SIMPLE_OBJECTS_WITH_INDEXES = ["materialized-view", "view", "table"];
const DATAFLOW_VISUALIZER_OBJECTS = ["materialized-view", "index"];

Expand Down Expand Up @@ -86,10 +92,12 @@ export const SimpleObjectDetailsContent = ({
sourceType={object?.sourceType}
/>
{canShowCreate && (
<ShowCreateBlock
{...databaseObject}
objectType={databaseObject.type as ShowCreateObjectType}
/>
<React.Suspense fallback={<LoadingContainer />}>
<ShowCreateBlock
{...databaseObject}
objectType={databaseObject.type as ShowCreateObjectType}
/>
</React.Suspense>
)}
</ObjectDetailsContainer>
</MainContentContainer>
Expand Down Expand Up @@ -194,7 +202,11 @@ export const SimpleObjectDetailRoutes = () => {
{shouldShowWorkflowGraph && (
<Route
path="workflow"
element={<WorkflowGraph focusedObjectId={id} />}
element={
<React.Suspense fallback={<LoadingContainer />}>
<WorkflowGraph focusedObjectId={id} />
</React.Suspense>
}
/>
)}
{shouldShowIndexes && (
Expand Down
11 changes: 9 additions & 2 deletions console/src/platform/object-explorer/SinkDetailRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { Navigate, Outlet, Route, useNavigate } from "react-router-dom";

import { AppErrorBoundary } from "~/components/AppErrorBoundary";
import { LoadingContainer } from "~/components/LoadingContainer";
import WorkflowGraph from "~/components/WorkflowGraph/WorkflowGraph";
import { Tab } from "~/layouts/BaseLayout";
import { useSinkList } from "~/platform/sinks/queries";
import SinkErrors from "~/platform/sinks/SinkErrors";
Expand All @@ -24,6 +23,10 @@ import { SimpleObjectDetailsContainer } from "./SimpleObjectDetailRoutes";
import { useSchemaObjectParams } from "./useSchemaObjectParams";
import { useToastIfObjectNotExtant } from "./useToastIfObjectNotExtant";

const WorkflowGraph = React.lazy(
() => import("~/components/WorkflowGraph/WorkflowGraph"),
);

const WORKFLOW_TAB = {
label: "Workflow",
href: `../workflow`,
Expand Down Expand Up @@ -120,7 +123,11 @@ export const SinkDetailRoutes = () => {
<Route path="errors" element={<SinkErrorsContainer />} />
<Route
path="workflow"
element={<WorkflowGraph focusedObjectId={id} />}
element={
<React.Suspense fallback={<LoadingContainer />}>
<WorkflowGraph focusedObjectId={id} />
</React.Suspense>
}
/>
<Route path="*" element={<Navigate to="../.." replace />} />
</Route>
Expand Down
17 changes: 14 additions & 3 deletions console/src/platform/object-explorer/SourceDetailRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { Navigate, Outlet, Route, useNavigate } from "react-router-dom";
import { Source } from "~/api/materialize/source/sourceList";
import { AppErrorBoundary } from "~/components/AppErrorBoundary";
import { LoadingContainer } from "~/components/LoadingContainer";
import WorkflowGraph from "~/components/WorkflowGraph/WorkflowGraph";
import { Tab } from "~/layouts/BaseLayout";
import { useSourcesList } from "~/platform/sources/queries";
import SourceErrors from "~/platform/sources/SourceErrors";
Expand All @@ -29,6 +28,10 @@ import { SimpleObjectDetailsContainer } from "./SimpleObjectDetailRoutes";
import { useSchemaObjectParams } from "./useSchemaObjectParams";
import { useToastIfObjectNotExtant } from "./useToastIfObjectNotExtant";

const WorkflowGraph = React.lazy(
() => import("~/components/WorkflowGraph/WorkflowGraph"),
);

export const SourceOverviewContainer = () => {
return (
<AppErrorBoundary message="An error occurred loading object details.">
Expand Down Expand Up @@ -173,7 +176,11 @@ export const SourceDetailRoutes = () => {
<Route path="columns" element={<ObjectColumns />} />
<Route
path="workflow"
element={<WorkflowGraph focusedObjectId={id} />}
element={
<React.Suspense fallback={<LoadingContainer />}>
<WorkflowGraph focusedObjectId={id} />
</React.Suspense>
}
/>
</>
) : (
Expand All @@ -183,7 +190,11 @@ export const SourceDetailRoutes = () => {
<Route path="columns" element={<ObjectColumns />} />
<Route
path="workflow"
element={<WorkflowGraph focusedObjectId={id} />}
element={
<React.Suspense fallback={<LoadingContainer />}>
<WorkflowGraph focusedObjectId={id} />
</React.Suspense>
}
/>
<Route path="errors" element={<SourceErrorsContainer />} />
<Route path="tables" element={<SourceTablesContainer />} />
Expand Down
Loading