diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.test.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.test.tsx index 70dac621b..6ebb38125 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.test.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.test.tsx @@ -234,6 +234,7 @@ describe("ProjectOnboardingWizard", () => { throw new Error("Stripe account info should not load on the app selection step."); }); const listEmailThemes = vi.fn(async () => []); + const getEmailPreview = vi.fn(async () => ""); const getStripeAccountInfo = vi.fn(async () => null); render( @@ -265,6 +266,7 @@ describe("ProjectOnboardingWizard", () => { app: { setupPayments: vi.fn(async () => ({ url: "https://example.com" })), listEmailThemes, + getEmailPreview, getStripeAccountInfo, useEmailThemes, useStripeAccountInfo, @@ -280,6 +282,7 @@ describe("ProjectOnboardingWizard", () => { ); expect(listEmailThemes).toHaveBeenCalledOnce(); + expect(getEmailPreview).not.toHaveBeenCalled(); expect(getStripeAccountInfo).not.toHaveBeenCalled(); expect(useEmailThemes).not.toHaveBeenCalled(); expect(useStripeAccountInfo).not.toHaveBeenCalled(); diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.tsx index 929adf18c..e50b27414 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client-parts/project-onboarding-wizard.tsx @@ -33,6 +33,7 @@ import { import { AuthPage, type AdminOwnedProject } from "@hexclave/next"; import { type AppId } from "@hexclave/shared/dist/apps/apps-config"; import { type EnvironmentConfigOverrideOverride } from "@hexclave/shared/dist/config/schema"; +import { previewTemplateSource } from "@hexclave/shared/dist/helpers/emails"; import { runAsynchronously, runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises"; import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -187,7 +188,10 @@ export function ProjectOnboardingWizard(props: { } runAsynchronously(async () => { - await project.app.listEmailThemes(); + const themes = await project.app.listEmailThemes(); + await Promise.allSettled(themes.map((theme) => + project.app.getEmailPreview({ themeId: theme.id, templateTsxSource: previewTemplateSource }) + )); }, { noErrorLogging: true }); }, [isLinkExistingMode, project.app, status]); diff --git a/packages/template/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts b/packages/template/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts index e8fe88bc9..6234d69bd 100644 --- a/packages/template/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +++ b/packages/template/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts @@ -828,7 +828,8 @@ export class _HexclaveAdminAppImplIncomplete { - return (await this._interface.renderEmailPreview(options)).html; + const result = Result.orThrow(await this._emailPreviewCache.getOrWait([options.themeId, options.themeTsxSource, options.templateId, options.templateTsxSource], "write-only")); + return result.html; } // IF_PLATFORM react-like useEmailPreview(options: { themeId?: string | null | false, themeTsxSource?: string, templateId?: string, templateTsxSource?: string }): string {