Admin walkthrough — secondary flows
Less-common tasks each as a focused mini-walkthrough.
A. Editing an existing tutorial
Open /admin/help-tutorials. Find the row by:
- Page Key column — paginated default-sorted by page_key.
- Language filter — narrow to one language if you keep translations.
- Status filter — flip to Draft to find tutorials you've deactivated.
Click the pencil icon at the row's right edge. The frontend calls helpApi.getForPage(token, page_key, language) because the list endpoint returns lightweight summaries (no steps / settings_help payload). The fetch unwraps either { tutorial, is_read } or a flat row, then populates the editor.
Make your edits. Click Save. The same PUT /admin/help-tutorials/{id} route handles the upsert. The unique (page_key, language) constraint is enforced server-side — you cannot change a tutorial's page_key to one that already has a row in the same language.
B. Re-seeding defaults after a platform upgrade
When the platform ships new default tutorials in defaultTutorialsEN(), existing tenants stay on the old set until you re-seed.
Open /admin/help-tutorials, click the Seed Defaults button (sparkles icon). The toast confirms seedSuccess: count={N}.
What happens behind the scenes:
POST /admin/help-tutorials/seed
→ service.SeedDefaults(ctx, language) // language of the request, default en
→ iterate defaultTutorialsEN() entries, tagged with that language
→ INSERT INTO help_tutorials (...)
ON CONFLICT (page_key, language) DO NOTHING
→ return { created: <int> }
Key behaviour:
- Gaps only. Rows that already exist (
page_key, languagecollision) are left alone. Your edits are NEVER overwritten. - One language per run. Each run seeds the English default set under the request's language. To seed another language, call the endpoint with
{ "language": "<code>" }. - Idempotent. Re-running on a tenant that has every row already returns
created: 0.
If you need to FORCE refresh a single row to match the latest default, edit it manually in the admin UI — there is no "force overwrite from defaults" endpoint.
C. Deleting a tutorial
From the list at /admin/help-tutorials, click the trash icon at the row's right edge.
A confirm dialog appears with destructive styling (variant: "destructive"). Click Confirm.
The frontend calls DELETE /admin/help-tutorials/{id}. On success:
- The toast shows Tutorial deleted.
- The row is removed from the local list (no full refetch).
- The row is gone from the DB.
- Any
help_tutorial_readsrows pointing to thatpage_keySTAY in place — the table is keyed onpage_key, not on the tutorial UUID, so they don't cascade. They're harmless (just dead pointers).
If you want to bring the tutorial back, re-create it — there is no undo and no recycle bin for tutorials specifically. The deletion is final.
D. Previewing without saving
You're drafting a tutorial and want to see how it renders before committing. From the editor modal:
- Fill any fields you want to preview.
- Click Preview (bottom-left of the modal footer).
- The same
<HelpPanel>component slides in from the right. Title, description, steps, settings tab (if Settings Help entries were added), video tab (if a URL was provided), and footer Got it button — all live. - Click the X in the panel header or press Escape to close. The editor modal stays open with your in-progress edits intact.
The preview reads from your editor state — not from the DB — so it works for both create mode (no row yet exists) and edit mode (your changes are visible without a save).
E. Forcing a re-prompt platform-wide
After a major page redesign, you want every operator's "unread" dot to come back on. Two paths:
Per-user (the operator does it):
// In the operator's browser console
localStorage.removeItem("help-tutorials-read");
// Optional: also re-enable auto-open
localStorage.removeItem("help-tutorials-auto-open");
The next admin page they load shows the unread pulse again, and if isAutoOpenEnabled() returns true the panel auto-opens.
Platform-wide (you do it once):
-- Per tenant
DELETE FROM help_tutorial_reads;
The server-side reads are wiped, but the clients' localStorage help-tutorials-read lists still mark pages as read locally. The frontend uses localStorage as the primary source for the unread dot — the server-side state is for cross-device parity. So DELETE FROM help_tutorial_reads alone won't bring back the pulse for users with stale localStorage. In practice you'll want to combine: announce the redesign with a "clear your help cache" instruction, OR ship a frontend version that bumps the storage key.
