Admin walkthrough — secondary flows

Help Tutorials

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, language collision) 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_reads rows pointing to that page_key STAY in place — the table is keyed on page_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:

  1. Fill any fields you want to preview.
  2. Click Preview (bottom-left of the modal footer).
  3. 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.
  4. 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.