mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
Merge branch 'fix/demo-dashboard' into release/v1.43.9
This commit is contained in:
commit
fed16a4c43
4 files changed
+79
-7
No files matched your search
+28
-3
@@ -90,6 +90,7 @@ import {
|
||||
import { ENVIRONMENT_LOCATION_AAD } from "../src/lib/crypto/encrypted-columns";
|
||||
import { sealInsightsCachedText } from "../src/lib/insights/cached-text-cipher";
|
||||
import {
|
||||
DEFAULT_CHART_OVERLAY_PREFS,
|
||||
DEFAULT_DASHBOARD_LAYOUT,
|
||||
serializeDashboardLayout,
|
||||
} from "../src/lib/dashboard-layout";
|
||||
@@ -497,16 +498,40 @@ async function seed() {
|
||||
// One row of six tiles (weight, the two blood-pressure values, resting
|
||||
// heart rate, HRV and mood) and the weight chart right below it, so the
|
||||
// first screen of the public demo shows the summary, the tiles and the
|
||||
// start of a chart together. Every other tile stays one switch away in
|
||||
// the layout settings; its data is seeded either way. Writing the layout
|
||||
// verbatim keeps the demo's home page stable across default tweaks.
|
||||
// start of a chart together. Below it only the measurement charts: the
|
||||
// mood and medication cards, achievements, recent workouts and check-ups
|
||||
// stay one switch away in the layout settings, their data seeded either
|
||||
// way. Weight, BMI and blood pressure open on 90 days, resting heart rate
|
||||
// on 30 with its 7-day trend and trend line, so each chart shows a shape
|
||||
// rather than a flat week. Writing the layout verbatim keeps the demo's
|
||||
// home page stable across default tweaks.
|
||||
const SHOWCASE_TILE_IDS = new Set(["weight", "bp", "pulse", "hrv", "mood"]);
|
||||
const HIDDEN_CARD_IDS = new Set([
|
||||
"mood",
|
||||
"medications",
|
||||
"achievements",
|
||||
"recentWorkouts",
|
||||
"vorsorge",
|
||||
]);
|
||||
const demoDashboardLayout = serializeDashboardLayout({
|
||||
...DEFAULT_DASHBOARD_LAYOUT,
|
||||
widgets: DEFAULT_DASHBOARD_LAYOUT.widgets.map((w) => ({
|
||||
...w,
|
||||
visible: w.visible && !HIDDEN_CARD_IDS.has(w.id),
|
||||
tileVisible: SHOWCASE_TILE_IDS.has(w.id),
|
||||
})),
|
||||
chartOverlayPrefs: {
|
||||
weight: { ...DEFAULT_CHART_OVERLAY_PREFS, rangePoints: 90 },
|
||||
bmi: { ...DEFAULT_CHART_OVERLAY_PREFS, rangePoints: 90 },
|
||||
bp: { ...DEFAULT_CHART_OVERLAY_PREFS, rangePoints: 90 },
|
||||
// The resting heart rate chart is the dashboard's `pulse` chart.
|
||||
pulse: {
|
||||
...DEFAULT_CHART_OVERLAY_PREFS,
|
||||
rangePoints: 30,
|
||||
showTrendIndicator: true,
|
||||
showTrendArrow: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await client.query(
|
||||
`UPDATE users SET dashboard_widgets_json = $1 WHERE id = $2`,
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
/**
|
||||
* The setup checklist on a demo instance.
|
||||
*
|
||||
* The demo is one shared, read-only account carrying onboarding answers, so
|
||||
* `isStillInSetup` keeps the checklist on screen for every visitor although
|
||||
* none of its rows can be done there. The shell already leaves out the tour
|
||||
* under `DEMO_MODE`; the dashboard leaves out the checklist the same way.
|
||||
* Pinned here: every render path of the page threads the flag, and the
|
||||
* client mounts the checklist only without it.
|
||||
*/
|
||||
const PAGE_PATH = join(process.cwd(), "src/app/page.tsx");
|
||||
const CLIENT_PATH = join(process.cwd(), "src/app/page-client.tsx");
|
||||
|
||||
describe("dashboard setup checklist on a demo instance", () => {
|
||||
it("threads DEMO_MODE into every render of the dashboard client", () => {
|
||||
const src = readFileSync(PAGE_PATH, "utf8");
|
||||
expect(src).toContain('process.env.DEMO_MODE === "true"');
|
||||
const renders = src.match(/<DashboardPageClient\b[^>]*>/g) ?? [];
|
||||
expect(renders.length).toBeGreaterThan(0);
|
||||
for (const render of renders) {
|
||||
expect(render).toContain("demoMode={demoMode}");
|
||||
}
|
||||
});
|
||||
|
||||
it("mounts the checklist only outside demo mode", () => {
|
||||
const src = readFileSync(CLIENT_PATH, "utf8");
|
||||
const mounts = src.match(/<GettingStartedChecklist\b[^>]*\/>/g) ?? [];
|
||||
expect(mounts).toHaveLength(1);
|
||||
expect(src).toContain("{demoMode ? null : <GettingStartedChecklist />}");
|
||||
});
|
||||
});
|
||||
@@ -193,6 +193,7 @@ import {
|
||||
|
||||
export default function DashboardPageClient({
|
||||
batchWindow: batchWindowProp,
|
||||
demoMode = false,
|
||||
}: {
|
||||
/**
|
||||
* v1.30.9 — the batched-series ISO window computed server-side from the
|
||||
@@ -204,6 +205,12 @@ export default function DashboardPageClient({
|
||||
* under, so the prefetched slice lands instead of triggering a refetch.
|
||||
*/
|
||||
batchWindow?: BatchWindow;
|
||||
/**
|
||||
* True on a `DEMO_MODE` instance. The demo is one shared, read-only
|
||||
* account a visitor cannot set up, so the setup checklist has nothing to
|
||||
* offer there, as the shell already leaves out the tour.
|
||||
*/
|
||||
demoMode?: boolean;
|
||||
} = {}) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const mounted = useMounted();
|
||||
@@ -2312,7 +2319,7 @@ export default function DashboardPageClient({
|
||||
* content (tiles, charts) keeps a stable position, and the
|
||||
* near-empty dashboards of the new accounts the card targets keep
|
||||
* it visible without scrolling anyway. */}
|
||||
<GettingStartedChecklist />
|
||||
{demoMode ? null : <GettingStartedChecklist />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+8
-3
@@ -76,12 +76,15 @@ const DIGEST_SOFT_BUDGET_MS = 400;
|
||||
* others.
|
||||
*/
|
||||
export default async function DashboardPage() {
|
||||
// `DEMO_MODE` is a server-only env var; resolved here and threaded in, as
|
||||
// the layout does for the shell.
|
||||
const demoMode = process.env.DEMO_MODE === "true";
|
||||
// Operator/test escape hatch: `DASHBOARD_SSR_PREFETCH=false` renders the
|
||||
// pure client-fetch dashboard (pre-prefetch behaviour). The e2e server
|
||||
// sets it so Playwright route mocks — which only see CLIENT fetches —
|
||||
// keep governing what the dashboard paints. It gates EVERY prefetch below.
|
||||
if (process.env.DASHBOARD_SSR_PREFETCH === "false") {
|
||||
return <DashboardPageClient />;
|
||||
return <DashboardPageClient demoMode={demoMode} />;
|
||||
}
|
||||
let dehydratedState = null;
|
||||
let batchWindow: BatchWindow | undefined;
|
||||
@@ -171,11 +174,13 @@ export default async function DashboardPage() {
|
||||
}
|
||||
|
||||
if (dehydratedState === null) {
|
||||
return <DashboardPageClient batchWindow={batchWindow} />;
|
||||
return (
|
||||
<DashboardPageClient batchWindow={batchWindow} demoMode={demoMode} />
|
||||
);
|
||||
}
|
||||
return (
|
||||
<HydrationBoundary state={dehydratedState}>
|
||||
<DashboardPageClient batchWindow={batchWindow} />
|
||||
<DashboardPageClient batchWindow={batchWindow} demoMode={demoMode} />
|
||||
</HydrationBoundary>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user