From dff5a155efbe273e464f40cf8b48be2379cd11d9 Mon Sep 17 00:00:00 2001 From: tianma-if Date: Thu, 23 Jul 2026 00:43:55 +0800 Subject: [PATCH] feat(demo): add on-demand demo data reset endpoint and UI button --- apps/api/src/index.ts | 20 ++++++++++++ apps/web/src/components/NotebookPane.tsx | 22 +++++++++++++ apps/web/src/components/WorkspaceApp.tsx | 41 ++++++++++++++++++++++++ apps/web/src/lib/api.ts | 5 +++ packages/shared/src/i18n/en-US.ts | 10 ++++++ packages/shared/src/i18n/zh-CN.ts | 10 ++++++ 6 files changed, 108 insertions(+) diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 9d767081..c56136de 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -2226,6 +2226,26 @@ app.get("/api/v1/resources/:id/blob", async (c) => { return new Response(object.body, { headers }); }); +app.post("/api/v1/demo/reset", async (c) => { + if (!isDemoMode(c.env) && !isLocalDemoSeedEnabled(c.env)) { + return c.json( + { + error: { + code: "demo_mode_disabled", + message: "Demo reset is only available when demo mode or local demo seed is enabled", + }, + }, + 400 + ); + } + + await resetDemoData(c.env, Date.now()); + return c.json({ + success: true, + message: "Demo seed data successfully restored", + }); +}); + app.patch("/api/v1/memos/:id", zValidator("json", MemoUpdateSchema), async (c) => { const denied = requireScopes(c, "write:memos"); diff --git a/apps/web/src/components/NotebookPane.tsx b/apps/web/src/components/NotebookPane.tsx index 8e74fa06..52ce926f 100644 --- a/apps/web/src/components/NotebookPane.tsx +++ b/apps/web/src/components/NotebookPane.tsx @@ -19,6 +19,7 @@ import { CheckCircle2, CircleUserRound, Download, + RotateCcw, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; @@ -236,6 +237,9 @@ export const NotebookPane = ({ authRequired, onLogout, isLoggingOut, + demoMode = false, + onResetDemo, + isResettingDemo = false, }: { user: AuthUser | null; view: string; @@ -264,6 +268,9 @@ export const NotebookPane = ({ authRequired: boolean; onLogout: () => void; isLoggingOut: boolean; + demoMode?: boolean; + onResetDemo?: () => void; + isResettingDemo?: boolean; }) => { const { t } = useTranslation(); const { isInstallable, install } = usePwaInstall(); @@ -481,6 +488,21 @@ export const NotebookPane = ({