From 307a6285e62e45cad7dfb32ad59b92d9b66723a4 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Fri, 1 May 2026 21:16:51 -0400 Subject: [PATCH] =?UTF-8?q?feat(guides):=20rewrite=20in-product=20User=20G?= =?UTF-8?q?uides=20as=20Di=C3=A1taxis=20how-tos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace 15 feature-dump guides with 43 problem-oriented how-tos grouped under 10 categories. Drop Maintenance Flows / AI Assistant / Flow Assist Sparkles — those surfaces no longer exist post-FlowPilot pivot. Rename Step Library → Solutions Library throughout. Correct every "click X in the sidebar" reference to match live labels (Home, History, Tickets, Flows, Scripts, Data, Acct). Schema: add `category: CategoryId` and optional `relatedSlugs` to Guide; new Category type and `categories` const drive hub ordering. GuidesHubPage renders category sections (auto-hides empty); GuideDetailPage renders a related-guides footer when set; GuideCard drops the misleading "N sections" subtitle. Fix step.tip markdown rendering — `**bold**` rendered literally because tip used plain text instead of the same regex replacement used on instruction. 14 net-new how-tos for FlowPilot-era surfaces with no prior coverage: tasklane keyboard flow, view-what-we-know, ask-AI mid-session, pause-and-leave, resolve, record-fix-outcome, escalate (Escalation Mode), post-docs-to-ticket, send-client-update, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate. Browser-verified against engineer + owner test users (sidebar labels, account sub-pages, pilot-screen header buttons, Tasks panel, integration form). tsc clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .ai/CURRENT_TASK.md | 10 + .ai/HANDOFF.md | 39 +- .ai/SESSION_LOG.md | 25 + CHANGELOG.md | 8 + frontend/src/components/guides/GuideCard.tsx | 3 - .../src/components/guides/GuideSection.tsx | 7 +- frontend/src/data/guides.ts | 1243 +++++++++++------ frontend/src/pages/GuideDetailPage.tsx | 25 +- frontend/src/pages/GuidesHubPage.tsx | 28 +- 9 files changed, 914 insertions(+), 474 deletions(-) diff --git a/.ai/CURRENT_TASK.md b/.ai/CURRENT_TASK.md index 06fa6af0..6c60447e 100644 --- a/.ai/CURRENT_TASK.md +++ b/.ai/CURRENT_TASK.md @@ -4,6 +4,14 @@ ## Recently shipped +- **2026-05-01 — In-product User Guides rewrite (uncommitted, on `main`).** Replaced 15 feature-dump guides with 43 problem-oriented Diátaxis how-tos grouped under 10 categories. Dropped Maintenance Flows / AI Assistant / Flow Assist Sparkles (UI no longer exists). Renamed Step Library → Solutions Library. Authored 14 net-new how-tos for FlowPilot-era surfaces (tasklane keyboard flow, what-we-know, resolve, escalate, record-fix-outcome, post-docs-to-ticket, share-update, pause-and-leave, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate, etc.). Schema additions: `category`, optional `relatedSlugs`; hub renders category sections; detail page renders related-guides footer. Fixed rendering bug where `**bold**` in `step.tip` rendered literally. Killed misleading "N sections" subtitle on guide cards. Browser-verified against engineer + owner login (sidebar labels, account sub-pages, pilot-screen header buttons, Tasks panel, integration form). Two unverified items intentionally deferred: change-teammate-role (requires non-owner test member to inspect role-change control) and detailed Resolve / Escalate modal contents (Resolve gated by 6 pending tasks in test data). tsc and Vite build clean. +- **2026-05-01 — PR #158** Session-screen UX impeccable pass + tasklane keyboard flow. Merged into `main` as `5e10005`. + - **Impeccable pass** (5 sub-passes — distill / quieter / layout / typeset / polish): score 24/40 → 33/40. Removed the duplicate "Suggested checks" chip strip; added an inline `Next steps · N pending in Tasks` cue above the latest action-bearing AI bubble; consolidated the desktop session header to Resolve + Escalate + ⋯ kebab (Context / New Ticket / Update Ticket / Pause now under the kebab, mobile kebab gained Context + New Ticket parity); centered the messages column to `max-w-3xl` to match the composer; bubbles dropped to `rounded-xl`. Decoration sweep: dropped 3px side stripes (TaskLane done states, all 6 ProposalBanner modes, WhatWeKnowItem rows), gradient backgrounds (WhatWeKnow + every banner), accent borderTop on TaskLane header, backdrop-blur on handoff overlay, animate-pulse-amber ring in VerifyingBanner, bordered avatar boxes in banners. Type sweep: 14 distinct sizes → 5-step scale (10/11/12/13/14px). Icon disambiguation: `MessageCircleQuestion` split into `Pencil` (Answer CTA) + `HelpCircle` (per-check explainer). Dead `font-sans` audit (12 sites) and double `text-xs` cleanups. + - **TaskLane keyboard-first flow** (real feature): Enter submits + auto-advances to next pending task, Shift+Enter newline, Esc cancels, focus jumps to Send Responses after the last submission. Mouse path also auto-advances. Subtle hint row teaches the shortcut. + - **Banner ↔ script panel linked**: collapsing or dismissing the ProposalBanner now also hides the InlineNoTemplateDialog / TemplateMatchPanel; recording any outcome closes both surfaces. + - **WhatWeKnow collapsible**: per-session preference in `sessionStorage` (`rf-whatweknow-collapsed:{sessionId}`); auto-collapses on first render at ≥5 facts. + - **Side fix**: `ParameterizationPreview.tokenize()` word-boundary guard prevents over-eager highlighting of short values like `"D"` (no longer lights up every capital D in `Get-ADUser`). + - Validation: tsc clean, ESLint clean, Vite build clean. Type-check + lint passed at every commit boundary. - **2026-05-01 — PR #156** Suggested-fix `applied_pending` non-terminal outcome. Merged into `main` as `3ba4532`. Adds: - Schema/API: `FixStatus="applied_pending"`, `pending_reason` Text column, migration `c0f3a4b7e91d`. `PATCH /suggested-fixes/{id}/outcome` accepts pending, requires notes, stamps `applied_at` only. - UI: `PendingBanner` (info-tone, worked / didn't / update reason / dismiss). "Waiting to verify…" overflow option in `VerifyingBanner`. Nudge "Still checking" records pending with a reason. Page-level Resolve auto-patches pending → success before resolution flow; page-level Escalate intercepts pending the same way verifying/partial does. @@ -24,3 +32,5 @@ Week 8: if 0 of 3 pilots produce a verifiable hours-saved-per-week number above - Drive checks 1 (VerifyingBanner overflow → "Waiting to verify…") and 5 (nudge "Still checking" with 3+ post-apply messages) in real pilot usage to close the QA gap left by `/qa` (the tested handlers cover the same mutations, but the entry-path UI rendering wasn't exercised end-to-end). - Consider monitoring how often pending fixes get parked vs resolved — if engineers report losing track across sessions, revisit the cross-session "Follow-ups" dashboard rollup that was scoped out. +- After PR #158 lands in real ticket flow, eyeball the keyboard-hint contrast and the WhatWeKnow auto-collapse-at-5 threshold — both were judgment calls (5 was a guess; the contrast bump from `/70` to full muted-foreground was based on my read, not real screen testing). Adjust if the 5-fact threshold feels too aggressive or too lenient mid-session. +- Two follow-ups logged in `.ai/TODO.md` from the impeccable pass: `ConcludeSessionModal` paused/escalated step should allow multi-select (Ticket Notes + Client Update + Email Draft simultaneously) — real feature work; `bg-card-hover` Tailwind class doesn't resolve in `CommandPalette` — two-line fix. diff --git a/.ai/HANDOFF.md b/.ai/HANDOFF.md index bfca176f..190768c7 100644 --- a/.ai/HANDOFF.md +++ b/.ai/HANDOFF.md @@ -2,28 +2,41 @@ # HANDOFF.md -**Last updated:** 2026-05-01 (session 9 — started issue cleanup plan sections 1 and 2) +**Last updated:** 2026-05-02 (post-guides-rewrite, uncommitted) -**Active task:** None. Pick next from `.ai/TODO.md` or roadmap. - -**Just-updated:** issue cleanup plan sections 1 and 2 were started and documented. +**Active task:** None. The guide rewrite is complete; working tree dirty pending review/commit. ## Where this session ended -Issue cleanup plan follow-up completed: +In-product User Guides at `/guides` rewritten from 15 feature-dump guides → 43 problem-oriented Diátaxis how-tos under 10 categories. Schema extended (`category`, `relatedSlugs`), hub re-rendered with category headings, detail page gained a Related guides footer, tip-markdown rendering bug fixed. All changes browser-verified (engineer + owner) against live UI, every detail page renders without 404, tsc clean. -- Section 1: frontend lint is clean. Stale lint disables from the warning set were removed or replaced with justified comments, hook dependency warnings were resolved, e2e selectors were added for session history and the FlowPilot command-palette entry, and `AssistantChatPage` now logs unexpected `currentChatRef` stale async discards. -- Section 2: `TaskLane` action cards now have diagnostic help affordances for common commands (connectivity, DNS, IP config, event logs, services, and generic checks). #128 was documented as "keep existing responsive side-panel/bottom-drawer behavior unless pilot feedback proves a preference is needed." -- Updated `docs/plans/2026-05-01-issue-cleanup-plan.md` with section 1/2 status and validation. -- Validation passed: `docker exec -w /app resolutionflow_frontend npm run lint`, `docker exec -w /app resolutionflow_frontend npx tsc -b`, and `docker exec -w /app resolutionflow_frontend npm run build` (existing Vite large-chunk warning only). +**Working tree dirty.** Files touched: +- `frontend/src/data/guides.ts` (full rewrite of `guides` array + new `categories` array + extended types) +- `frontend/src/pages/GuidesHubPage.tsx` (renders category sections, hides empty ones) +- `frontend/src/pages/GuideDetailPage.tsx` (related-guides footer, dropped section-count) +- `frontend/src/components/guides/GuideCard.tsx` (dropped section-count subtitle) +- `frontend/src/components/guides/GuideSection.tsx` (markdown bold now works in tips) +- `CHANGELOG.md` ([Unreleased] entry added) +- `.ai/CURRENT_TASK.md` ("Recently shipped" entry added) +- `.ai/SESSION_LOG.md` (session entry added) +- `.ai/HANDOFF.md` (this file) + +The user has not yet been asked to commit. When picking this up next session, check with the user before staging — they may want to ship as a single commit, branch + PR, or fold into another change in flight. ## Resume point — DO THIS NEXT -If tracker auth is available, close #127 and close/archive stale PR #124; rewrite #66 to template packs / one-click install only. Then continue the plan at section 3: #58 structured "step is wrong" quality signals. After that, section 4 is #60 recurring issue detection and section 5 is #129 hierarchical guide navigation. +1. **Decide commit shape.** Likely a single commit on a `feat/guides-diataxis-rewrite` branch with PR. Pre-existing TODOs from the prior session (cleanup of #127, rewrite of #66, sections 3-5 of the issue cleanup plan) are **unblocked again** — pick up `2026-05-01-issue-cleanup-plan.md` section 3 (#58 structured "step is wrong" quality signals) once the guides land. + +2. **Two follow-ups intentionally deferred from this session** (worth picking up if a related touch happens): + - **`change-teammate-role` how-to was dropped** because the test owner account has no non-owner members to inspect the role-change control. Once a teammate is invited via `invite-teammate`, verify whether the Membership list exposes a Role dropdown (or some other control) for non-owners and add the guide back. + - **Resolve / Escalate modal contents are unverified.** Browser couldn't drive Resolve to completion (test session has 6 pending Tasks gating it; clicking Resolve fired a toast). The how-tos point at the right buttons in the right place, but the exact modal copy and the Escalation Mode wedge specifics are based on project context, not live observation. Worth a quick spot-check the next time a clean test session is available. + +3. **`/etc/hosts` entry added on this code-server LXC.** `100.64.78.44 docker-01` — should now persist; HANDOFF.md previously claimed it was already there but wasn't. If `/browse` against `docker-01:5173` ever fails to resolve again, re-add it via `sudo tee` from a real terminal (the `!` shell prefix can't drive interactive sudo on this LXC). ## Environment notes (carry-forward) -- This code-server LXC has bun + docker but no native `python`/`node`/`npm`. Use `docker exec resolutionflow_{backend,frontend} …` for all build/test commands. Documented in `.ai/PROJECT_CONTEXT.md`. -- Headless Chromium (used by `/qa` `/browse`) needs `CONTAINER=1` in the env that launches the browse server, otherwise it aborts at `sandbox/linux/services/credentials.cc` due to the LXC namespace constraint. The browse server is currently running with that env set; restarting it manually requires `CONTAINER=1 $B status` again. -- Code-server's `/etc/hosts` has `100.64.78.44 docker-01` so the headless browser can resolve the bake-in `VITE_API_URL`. Persistent — no need to re-add unless the container is rebuilt. +- Code-server LXC has bun + docker but no native `python`/`node`/`npm`. Use `docker exec resolutionflow_{backend,frontend} …` for build/test commands. +- No `gh` CLI on this LXC — use the Gitea API (`$GITEA_TOKEN`) for PR/issue work, or run `gh` from a host that has it. +- Headless Chromium (`/qa`, `/browse`) needs `CONTAINER=1` in the env launching the browse server (LXC namespace constraint). +- `/etc/hosts` has `100.64.78.44 docker-01` so the headless browser resolves the bake-in `VITE_API_URL`. Confirmed persistent as of this session. - Multi-head alembic state on `main` (heads `070`, `c0f3a4b7e91d`, `024`) is pre-existing. Use `alembic upgrade heads` (plural) if `head` complains. diff --git a/.ai/SESSION_LOG.md b/.ai/SESSION_LOG.md index 57a41ebd..3fe5eee1 100644 --- a/.ai/SESSION_LOG.md +++ b/.ai/SESSION_LOG.md @@ -12,6 +12,31 @@ --- +## 2026-05-02 ~01:00 UTC — Claude — In-product User Guides Diátaxis rewrite (uncommitted) + +- Audited the in-product `/guides` collection against live UI via `/browse` (engineer + owner test users). Existing 15 guides predated the FlowPilot pivot — every "click X in the sidebar" reference was wrong (Dashboard → Home, All Flows → Flows, Sessions → History, Exports gone, etc.). Three guides described surfaces that no longer exist: Maintenance Flows, AI Assistant page, Flow Assist Sparkles button. Findings written to `/tmp/guides-audit.md`. +- Rebuilt `frontend/src/data/guides.ts` from scratch as 43 problem-oriented Diátaxis how-tos under 10 categories. Single-outcome each, terse imperative steps, real UI labels (Create New, Sign in, Manage, Build New Script, Send Invite, Save Settings, Create Category, etc.). Added `category: CategoryId` and optional `relatedSlugs?: string[]` to the `Guide` interface; new `Category` type and `categories` const drive the hub layout. `GuidesHubPage` now renders category sections (auto-hides empty); `GuideDetailPage` renders a Related guides footer; `GuideCard` lost its misleading "N sections" subtitle. +- Fixed `GuideSection.tsx`: `step.tip` was rendered as plain text so `**bold**` markdown in tips rendered literally. Applied the same regex replacement used on `step.instruction`. Verified against `/guides/start-a-session` tip block. +- Authored 14 net-new how-tos for FlowPilot-era surfaces with no prior coverage: tasklane-keyboard-flow, view-what-we-know, ask-ai-mid-session, pause-and-leave-session, resolve-a-session, record-suggested-fix-outcome, escalate-a-session, post-docs-to-ticket, send-client-update, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate. Dropped change-teammate-role from scope — couldn't verify the role-change UI control without a non-owner test member. +- Verified owner-only surfaces with `pro@resolutionflow.example.com`: Membership inline form on `/account` (not a separate `/team-members` route), `/account/categories` real button is **Create Category** (not Add), `/account/chat-retention` real fields are **Retention Period (days)** + **Max Conversations** + **Save Settings**, `/account/integrations` form fields confirmed. Three guides corrected post-audit. +- Smoke-tested all 43 detail pages — every slug renders, no "Guide Not Found" fallthroughs. +- Added `100.64.78.44 docker-01` entry to `/etc/hosts` (user ran `sudo tee` from a normal terminal because the LXC `!` shell prefix can't drive interactive sudo). Should now persist across `/browse` sessions on this LXC. +- `docker exec -w /app resolutionflow_frontend npx tsc -b` clean. +- Files touched: `frontend/src/data/guides.ts`, `frontend/src/pages/GuidesHubPage.tsx`, `frontend/src/pages/GuideDetailPage.tsx`, `frontend/src/components/guides/GuideCard.tsx`, `frontend/src/components/guides/GuideSection.tsx`, `CHANGELOG.md`, `.ai/CURRENT_TASK.md`, `.ai/HANDOFF.md`, `.ai/SESSION_LOG.md`. Working tree dirty — user not yet asked to commit. + +--- + +## 2026-05-01 21:55 UTC — Claude — Session-screen impeccable pass + tasklane keyboard flow shipped (PR #158) + +- Ran the `/impeccable` skill against the assistant chat session screen (chat history / chat bar / TaskLane). Initial design-health score: 24/40 with explicit DESIGN-SYSTEM violations (gradient surfaces in WhatWeKnow + ProposalBanner, side stripes in TaskLane done states + every banner mode, accent borderTop on lane header, backdrop blur on handoff overlay). +- Walked through all 5 impeccable sub-passes (distill, quieter, layout, typeset, polish). Score after pass: 33/40 (+9). Biggest gains in Aesthetic & Minimalist (1→3), Consistency & Standards (1→3), Recognition Rather Than Recall (2→4). +- Inline iterations on top of the impeccable steps: linked banner ↔ script-panel lifecycle (collapse hides both, dismiss closes both, any outcome closes both); collapsible WhatWeKnow with `sessionStorage` memory + auto-collapse-at-5-facts; full keyboard flow on TaskLane (Enter submits + auto-advances, Shift+Enter newline, Esc cancels, focus jumps to Send Responses after the last task). +- Side fix: `ParameterizationPreview` was over-highlighting short parameter values (a `"D"` lit up every capital D in `Get-ADUser`/`Add-Type`/etc.). Added a word-boundary guard, conditional on whether the value itself starts/ends with a word character so values with leading punctuation (`"D:\\Folder"`) still match cleanly. +- Followups logged in `.ai/TODO.md`: `ConcludeSessionModal` multi-select for paused/escalated outcomes (real feature work — engineers often need ≥2 of Ticket Notes / Client Update / Email Draft), and `bg-card-hover` Tailwind drift in `CommandPalette` (silently broken classes — two-line fix). +- Branched as `feat/session-distill-quieter`, 4 commits (impeccable pass, parameterize fix, TODO followups, hint contrast + font-sans audit). PR #158 created via Gitea API (`$GITEA_TOKEN` env, no `gh` on this LXC). Merged into `main` as `5e10005`. Local branch deleted. +- Validation at every commit boundary: `docker exec -w /app resolutionflow_frontend npx tsc -b`, `npm run lint`, and `npm run build` all clean. +- Files touched: 14 frontend files (TaskLane, AssistantChatPage, ChatMessage, ProposalBanner, WhatWeKnow, WhatWeKnowItem, SuggestedFlowCard, ChatSidebar, ConcludeSessionModal, ChatTabStrip, ActionCardGroup, AddNoteButton, ParameterizationPreview), `.ai/TODO.md`, `.ai/CURRENT_TASK.md`, `.ai/HANDOFF.md`, `.ai/SESSION_LOG.md`, `CHANGELOG.md`, `CURRENT-STATE.md`. + ## 2026-05-01 07:20 UTC — Codex — Start issue cleanup plan sections 1 and 2 - Started `docs/plans/2026-05-01-issue-cleanup-plan.md` sections 1 and 2. diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e806b5..d9b8d950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,12 @@ All notable changes to ResolutionFlow are documented here. ## [Unreleased] +### Changed +- **In-product User Guides rewrite** — replaced 15 feature-dump guides with 43 problem-oriented Diátaxis how-tos grouped under 10 categories (Getting started, Working a pilot session, Closing out a session, Documentation & sharing, Authoring flows, Reusable assets, AI assistance, PSA integrations, Account & team admin, Analytics). Dropped three deprecated guides (Maintenance Flows, AI Assistant page, Flow Assist sparkle button — UI no longer exists). Renamed Step Library → Solutions Library to match canonical product terminology. Corrected sidebar entry-path references throughout (Dashboard → Home, All Flows → Flows, Sessions → History, Analytics → Data, etc.). Added `category` and optional `relatedSlugs` to the Guide schema; `GuidesHubPage` now renders category sections; `GuideDetailPage` shows a "Related guides" footer when set. Authored 14 net-new how-tos covering FlowPilot-era surfaces with no prior coverage: tasklane keyboard flow, what-we-know panel, ask-the-AI mid-session, pause-and-leave, resolve a session, record a suggested-fix outcome, escalate (Escalation Mode), post docs to a ConnectWise ticket, share a client update mid-session, build a script with Script Builder, open an AI-suggested flow, pin a flow, and invite a teammate. Fixed a long-standing rendering bug where `**bold**` markdown in `step.tip` rendered literally instead of bolded — the same regex replacement now runs on tips as on instructions. Killed the misleading "N sections" subtitle on guide cards (single-section how-tos make the count noise). + ### Added +- **TaskLane keyboard-first answer flow** (#158) — Enter submits and auto-advances to the next pending task; Shift+Enter inserts a newline; Esc cancels; after the last task, focus jumps to the Send Responses button so the engineer can fire the whole batch with one more keystroke. Mouse path also auto-advances. Subtle hint row (`⏎ submit · ⇧⏎ newline`) under each open input teaches the shortcut. +- **Collapsible "What we know" section** (#158) — TaskLane's facts list is now a collapsible section with per-session memory in `sessionStorage`. Auto-collapses on first render at ≥5 facts so Questions and Diagnostic Checks stay above the fold; engineer's explicit toggle always wins. - **Escalation Mode wedge** (#155) — when an engineer escalates, the senior tech who claims the session lands on a magic-moment handoff-context screen with the structured briefing visible in seconds (no scrolling, no chat re-read). Live SSE pushes new arrivals to anyone watching the queue, atomic claim resolves race conditions, the queue auto-excludes the claimed session, the claiming user retains chat ownership for AI briefings, and a new analytics endpoint tracks post-claim time-to-first-action so you can see real minutes recovered (paired with a manual baseline — see CURRENT_TASK.md two-metric framing). - **Suggested-fix "Awaiting verification" outcome** (#156) — when a fix needs external confirmation (client power-cycle, AD replication, license sync) you can park it in `applied_pending` instead of forcing a worked / didn't / partial verdict. The new PendingBanner shows the parked status with worked / didn't / update reason / dismiss actions. The "Still checking" nudge records pending with a reason instead of just silencing. Page-level Resolve auto-patches pending → success before the resolution flow opens; page-level Escalate intercepts pending the same way it intercepts verifying/partial. Resolution notes and escalation packages frame the pending state honestly (provisional fix; leading hypothesis with what's being waited on). - Tree Templates + Import/Export marketplace (#66) @@ -44,6 +49,8 @@ All notable changes to ResolutionFlow are documented here. - **Image support in Assistant Chat** — paste/attach images in chat input, uploaded to S3, resized for vision model, displayed in conversation history ### Changed +- **Assistant Chat session screen — UX overhaul** (#158, "impeccable" pass) — removed the duplicate "Suggested checks" chip strip in favor of the TaskLane as the single source of truth; added an inline `Next steps · N pending` cue above the latest action-bearing AI bubble; consolidated the session header to two visible primary actions (Resolve + Escalate) plus a kebab for Context / New Ticket / Update Ticket / Pause; centered the messages column to `max-w-3xl` to match the composer; unified chat-bubble radii to `rounded-xl`; dropped every banned decoration (3px side stripes, gradient surfaces, accent borderTop, backdrop blur, pulse rings, bordered avatar boxes) for a single decoration channel per surface; unified 14 distinct text sizes into a 5-step scale (10/11/12/13/14px); split the ambiguous `MessageCircleQuestion` icon into `Pencil` (write affordance for question Answer CTA) and `HelpCircle` (universal help icon for the per-check explainer); audited and dropped redundant `font-sans` classes across the screen. +- **Suggested-fix banner ↔ script panel are now linked** (#158) — collapsing the ProposalBanner now also hides the InlineNoTemplateDialog / TemplateMatchPanel; dismissing the banner closes both surfaces. Recording any outcome on a fix (Dismiss, It worked, Didn't work, Mark partial, Waiting to verify) closes the script panel alongside the banner state transition. - **Edit Procedure page** — layout overhaul and color system refinements for better visual hierarchy - **Flows sidebar navigation** — collapsed to reduce visual noise; session recovery removed from library view - **Account settings page** — audit fixes for improved consistency and usability @@ -54,6 +61,7 @@ All notable changes to ResolutionFlow are documented here. - **Tenant data boundaries** — all session and tree endpoints now return 404 (not 403) for cross-tenant access attempts to avoid confirming resource existence ### Fixed +- **`ParameterizationPreview` over-highlight on short parameter values** (#158) — the tokenizer matched highlight values via raw substring with no word-boundary check, so a single-char value like `"D"` (a drive letter) lit up every capital D in identifiers like `Get-ADUser`, `Add-Type`, `Disable-`. Added a word-boundary guard that's conditional on whether the value itself starts/ends with a word character, so values with leading/trailing punctuation (e.g. `"D:\\Folder"`) still match cleanly when adjacent to whitespace. - **CRITICAL: Copilot tree query isolation** (#131) — user could access any tree UUID if known, exposing full tree structure to AI. Now scoped to current account with 404 for inaccessible trees. - **AI session search isolation** — search endpoint leaked other users' sessions via OR(user_id, account_id). Now restricted to current user only. - **Analytics endpoint isolation** — GET `/analytics/flows/{tree_id}` exposed session counts for any tree UUID. Now returns 404 if tree doesn't belong to requesting account. diff --git a/frontend/src/components/guides/GuideCard.tsx b/frontend/src/components/guides/GuideCard.tsx index e062f2d2..b1ae535c 100644 --- a/frontend/src/components/guides/GuideCard.tsx +++ b/frontend/src/components/guides/GuideCard.tsx @@ -24,9 +24,6 @@ export function GuideCard({ guide }: GuideCardProps) {

{guide.summary}

- - {guide.sections.length} {guide.sections.length === 1 ? 'section' : 'sections'} - diff --git a/frontend/src/components/guides/GuideSection.tsx b/frontend/src/components/guides/GuideSection.tsx index 13933fa5..9090c069 100644 --- a/frontend/src/components/guides/GuideSection.tsx +++ b/frontend/src/components/guides/GuideSection.tsx @@ -37,7 +37,12 @@ export function GuideSection({ section, index }: GuideSectionProps) {

- Tip: {step.tip} + Tip:{' '} + $1'), + }} + />

)} diff --git a/frontend/src/data/guides.ts b/frontend/src/data/guides.ts index 413c8192..70676f49 100644 --- a/frontend/src/data/guides.ts +++ b/frontend/src/data/guides.ts @@ -1,22 +1,79 @@ import type { LucideIcon } from 'lucide-react' import { - Rocket, - Box, - GitBranch, - ListChecks, - Play, - Clock, - Share2, - Sparkles, - BotMessageSquare, - Bookmark, - Wrench, - Settings, BarChart3, - Terminal, + Bookmark, + BookmarkPlus, + Box, + CheckCircle2, + CircleCheck, + ClipboardList, + Clock, + Compass, + Download, + Eye, + Flag, + FolderOpen, + FormInput, + GitBranch, + KeyRound, + Lightbulb, + Link2Off, + ListChecks, + LogIn, + MessageSquare, + Pause, + Pin, + Play, Plug, + PlugZap, + RotateCcw, + Send, + Settings, + Share2, + Shield, + Sparkles, + Tag, + TerminalSquare, + Terminal, + TicketCheck, + TrendingUp, + User, + UserPlus, + Users, + Workflow, } from 'lucide-react' +export type CategoryId = + | 'getting-started' + | 'pilot-sessions' + | 'closing-out' + | 'documentation' + | 'authoring' + | 'reusable-assets' + | 'ai-assistance' + | 'psa' + | 'account-admin' + | 'analytics' + +export interface Category { + id: CategoryId + label: string + description: string +} + +export const categories: Category[] = [ + { id: 'getting-started', label: 'Getting started', description: 'First login, navigation, and orientation.' }, + { id: 'pilot-sessions', label: 'Working a pilot session', description: 'Drive a session from the home screen through a resolution.' }, + { id: 'closing-out', label: 'Closing out a session', description: 'Resolve, escalate, and record outcomes.' }, + { id: 'documentation', label: 'Documentation & sharing', description: 'Share, export, and redact session output.' }, + { id: 'authoring', label: 'Authoring flows', description: 'Build troubleshooting trees and step-by-step procedures.' }, + { id: 'reusable-assets', label: 'Reusable assets', description: 'Solutions library entries, script templates, and the Script Builder.' }, + { id: 'ai-assistance', label: 'AI assistance', description: 'Chat with the AI inside and outside of pilot sessions.' }, + { id: 'psa', label: 'PSA integrations', description: 'Connect ConnectWise and other PSA tools.' }, + { id: 'account-admin', label: 'Account & team admin', description: 'Profile settings, team configuration, and retention.' }, + { id: 'analytics', label: 'Analytics', description: 'Team and personal usage metrics.' }, +] + export interface GuideStep { instruction: string detail?: string @@ -33,543 +90,833 @@ export interface Guide { title: string icon: LucideIcon summary: string + category: CategoryId sections: GuideSection[] + relatedSlugs?: string[] } export const guides: Guide[] = [ + // ───────────────────────────────────────────────────────────────────── + // Getting started + // ───────────────────────────────────────────────────────────────────── { - slug: 'getting-started', - title: 'Getting Started', - icon: Rocket, - summary: 'Account setup, first login, and navigating the app.', + slug: 'sign-in', + title: 'Sign in for the first time', + icon: LogIn, + summary: 'Get from the login page to your dashboard.', + category: 'getting-started', sections: [ { - title: 'Logging In', + title: 'Sign in', steps: [ - { instruction: 'Go to the ResolutionFlow login page and enter your email and password.' }, - { instruction: 'Click **Sign In** to access your dashboard.' }, - { instruction: 'If you forgot your password, click **Forgot password?** on the login page and follow the email instructions.', tip: 'Check your spam folder if you don\'t receive the reset email within a few minutes.' }, + { instruction: 'Open the **ResolutionFlow** login page.' }, + { instruction: 'Enter your email and password.' }, + { instruction: 'Click **Sign in**. You land on **Home**, the dashboard.' }, ], }, + ], + relatedSlugs: ['reset-password', 'find-your-way-around'], + }, + { + slug: 'reset-password', + title: 'Reset a forgotten password', + icon: KeyRound, + summary: 'Recover access when you can\'t sign in.', + category: 'getting-started', + sections: [ { - title: 'Navigating the App', + title: 'Reset', steps: [ - { instruction: 'The **sidebar** on the left contains all main navigation links: Dashboard, All Flows, Flow Editor, Sessions, Exports, and more.' }, - { instruction: 'The **top bar** has a search bar (Ctrl+K / Cmd+K) to quickly find flows, sessions, and tags.' }, - { instruction: 'Click the **Quick Launch** (lightning bolt icon) in the top bar to start a flow without navigating to it first.' }, - { instruction: 'Your **user avatar** in the top-right opens a menu for Account settings, Admin Panel (if applicable), and Logout.' }, + { instruction: 'On the login page, click **Forgot password?**.' }, + { instruction: 'Enter the email on your account and submit.' }, + { instruction: 'Open the password reset email and click the link.', tip: 'Check your spam folder if it doesn\'t arrive within a few minutes.' }, + { instruction: 'Choose a new password and confirm it. You\'re signed in immediately.' }, ], }, + ], + relatedSlugs: ['sign-in'], + }, + { + slug: 'find-your-way-around', + title: 'Find your way around the app', + icon: Compass, + summary: 'Map out the sidebar, top bar, and main destinations.', + category: 'getting-started', + sections: [ { - title: 'Understanding the Dashboard', + title: 'Layout', steps: [ - { instruction: 'The Dashboard shows your active sessions, recent flows, and quick stats at a glance.' }, - { instruction: 'Click any active session card to resume where you left off.' }, - { instruction: 'Use the **Pinned Flows** section at the top of the sidebar for quick access to your most-used flows.' }, + { instruction: 'The **left sidebar** holds the main destinations: **Home** (start a session), **History** (your past sessions), **Tickets**, **Flows**, **Scripts**, **Data** (analytics), and **Acct**.' }, + { instruction: 'The **top bar** has a global search (**Ctrl+K** / **Cmd+K**), a link to **User Guides**, a notifications bell, and your avatar.' }, + { instruction: 'Click **Home** anytime to return to the start screen where new sessions begin.' }, ], }, ], }, { - slug: 'creating-flows', - title: 'Creating Flows', - icon: Box, - summary: 'Create troubleshooting, procedural, and maintenance flows.', + slug: 'pin-a-flow', + title: 'Pin a flow for fast access', + icon: Pin, + summary: 'Keep your most-used flows one click away.', + category: 'getting-started', sections: [ { - title: 'Creating a Troubleshooting Flow', + title: 'Pin', steps: [ - { instruction: 'Click **Flow Editor** in the sidebar, then click the **+ New Flow** button.' }, - { instruction: 'Select **Troubleshooting** as the flow type.' }, - { instruction: 'Enter a name and optional description for your flow.' }, - { instruction: 'Click **Create** to open the canvas editor where you can build your decision tree.', tip: 'Choose a descriptive name like "DNS Resolution Failure" so your team can find it easily.' }, - ], - }, - { - title: 'Creating a Procedural Flow (Project)', - steps: [ - { instruction: 'Click **Flow Editor** in the sidebar, then click the **+ New Flow** button.' }, - { instruction: 'Select **Procedural** as the flow type.' }, - { instruction: 'Enter a name and description.' }, - { instruction: 'Click **Create** to open the procedural editor where you can add steps, intake forms, and checklists.' }, - ], - }, - { - title: 'Creating a Maintenance Flow', - steps: [ - { instruction: 'Click **Flow Editor** in the sidebar, then click the **+ New Flow** button.' }, - { instruction: 'Select **Maintenance** as the flow type.' }, - { instruction: 'Enter a name and description.' }, - { instruction: 'Click **Create**. Maintenance flows use the same step-based editor as procedural flows but support batch launches across multiple targets.' }, - ], - }, - { - title: 'Managing Flow Properties', - steps: [ - { instruction: 'From the flow editor, click the flow name or settings area to update the name, description, category, and tags.' }, - { instruction: 'Assign a **category** to organize flows by topic (e.g., "Networking", "Active Directory").' }, - { instruction: 'Add **tags** for searchability (e.g., "DNS", "VPN", "Firewall").', tip: 'Tags are shared across your team. Use consistent naming so everyone can find relevant flows.' }, + { instruction: 'Click **Flows** in the sidebar and find the flow you want quick access to.' }, + { instruction: 'Click the **Pin** icon on the flow card.' }, + { instruction: 'Open the **Pin** shortcut at the bottom of the sidebar to launch any pinned flow in one click.' }, ], }, ], + relatedSlugs: ['organize-with-categories-tags'], }, + + // ───────────────────────────────────────────────────────────────────── + // Working a pilot session + // ───────────────────────────────────────────────────────────────────── { - slug: 'tree-editor', - title: 'Tree Editor (Canvas)', - icon: GitBranch, - summary: 'Build decision trees with nodes, options, actions, and solutions.', - sections: [ - { - title: 'Understanding the Canvas', - steps: [ - { instruction: 'The canvas editor displays your troubleshooting flow as a visual decision tree.' }, - { instruction: 'Each **node** represents a question, action, or solution in your troubleshooting path.' }, - { instruction: 'Nodes are connected by **options** — the answers or choices that lead to the next step.' }, - { instruction: 'Use the toolbar at the top to zoom, fit to screen, and access additional options.' }, - ], - }, - { - title: 'Adding Nodes', - steps: [ - { instruction: 'Click the **+** button on any existing node to add a child node.' }, - { instruction: 'Choose the node type: **Question** (asks the engineer something), **Action** (instructs them to do something), or **Solution** (the resolution).' }, - { instruction: 'Type the node content — this is what the engineer will see during navigation.' }, - { instruction: 'For Question nodes, add **options** (answers) that branch to different paths.', tip: 'Keep questions specific and actionable. "Is the DNS server responding to nslookup?" is better than "Check DNS".' }, - ], - }, - { - title: 'Editing Nodes', - steps: [ - { instruction: 'Click any node on the canvas to select it and open the edit panel.' }, - { instruction: 'Update the node content, type, or options in the side panel.' }, - { instruction: 'To delete a node, select it and click the **Delete** button or press the Delete key.' }, - { instruction: 'Use **Undo** (Ctrl+Z) and **Redo** (Ctrl+Shift+Z) to revert changes.' }, - ], - }, - { - title: 'Solution Nodes', - steps: [ - { instruction: 'Solution nodes are endpoints — they represent the resolution to the troubleshooting path.' }, - { instruction: 'Write clear, actionable solutions with specific commands or steps the engineer should follow.' }, - { instruction: 'You can have multiple solution nodes for different resolution paths.' }, - ], - }, - ], - }, - { - slug: 'procedural-editor', - title: 'Procedural Flow Editor', - icon: ListChecks, - summary: 'Build step-by-step procedures with intake forms and checklists.', - sections: [ - { - title: 'Adding Steps', - steps: [ - { instruction: 'In the procedural editor, click **Add Step** to add a new step to your flow.' }, - { instruction: 'Enter the step title and detailed instructions.' }, - { instruction: 'Steps execute in order from top to bottom. Drag steps to reorder them.' }, - { instruction: 'Use **Section Headers** to group related steps under labeled sections.', tip: 'Break long procedures into sections like "Preparation", "Execution", and "Verification".' }, - ], - }, - { - title: 'Intake Forms', - steps: [ - { instruction: 'Intake forms collect information before the procedure begins (e.g., client name, server IP).' }, - { instruction: 'Click **Add Field** in the intake form section to add a form field.' }, - { instruction: 'Choose the field type: **Text**, **Textarea**, **Select** (dropdown), **Number**, **URL**, or **Checkbox**.' }, - { instruction: 'Mark fields as **Required** if they must be filled before proceeding.' }, - { instruction: 'Field values become **variables** you can reference in step instructions using the variable name.', tip: 'Use descriptive variable names like "client_name" or "server_ip" so they\'re easy to reference in steps.' }, - ], - }, - { - title: 'Step Options', - steps: [ - { instruction: 'Expand **More Options** on any step to access additional settings.' }, - { instruction: 'Add a **URL** field to link to relevant documentation or tools.' }, - { instruction: 'Steps can include notes fields where engineers enter observations during execution.' }, - ], - }, - ], - }, - { - slug: 'running-flows', - title: 'Running Flows', + slug: 'start-a-session', + title: 'Start a session from the dashboard', icon: Play, - summary: 'Navigate troubleshooting flows and execute procedural procedures.', + summary: 'Describe the issue and get the AI to drive.', + category: 'pilot-sessions', sections: [ { - title: 'Running a Troubleshooting Flow', + title: 'Start', steps: [ - { instruction: 'Go to **All Flows** in the sidebar and find the flow you want to run.' }, - { instruction: 'Click the flow card, then click **Start** to begin a new session.' }, - { instruction: 'Read each question and select the answer that matches your situation.' }, - { instruction: 'Follow the path until you reach a **Solution** node with the resolution steps.' }, - { instruction: 'Use the **Scratchpad** (notepad icon) to take notes during navigation.', tip: 'You can pin frequently-used flows in the sidebar for quick access.' }, - ], - }, - { - title: 'Running a Procedural Flow', - steps: [ - { instruction: 'Navigate to the procedural flow and click **Start**.' }, - { instruction: 'Fill out the **Intake Form** with required information, then click **Begin**.' }, - { instruction: 'Work through each step in order. Mark steps as complete using the checkbox.' }, - { instruction: 'Add notes to individual steps as you work through them.' }, - { instruction: 'The progress bar at the top shows your completion percentage.' }, - ], - }, - { - title: 'Using Flow Assist (AI Copilot)', - steps: [ - { instruction: 'While navigating any flow, click the **Flow Assist** button (sparkles icon) in the bottom-right corner.' }, - { instruction: 'Ask questions about the current step, like "What else could cause this?" or "How do I check this?"' }, - { instruction: 'The AI understands your current position in the flow and provides contextual answers.' }, - { instruction: 'If the AI finds related flows in your team\'s library, they appear as **Suggested Flows** cards you can click to open.' }, + { instruction: 'Go to **Home**.' }, + { instruction: 'In the **"Describe the issue, paste an error message, or drop a screenshot…"** box, type the symptom or paste the error.' }, + { instruction: '(Optional) Click **Attach** to add a screenshot or file, or **Paste Logs** for raw output.' }, + { instruction: 'Click **Start session**. The pilot screen opens with the AI\'s first response and a Tasks panel on the right.', tip: 'For common issues use the quick-start chips below the box (**VPN not connecting**, **Outlook not syncing**, **User locked out**, etc.).' }, ], }, ], + relatedSlugs: ['resume-a-session', 'navigate-troubleshooting-flow'], }, { - slug: 'sessions', - title: 'Sessions', - icon: Clock, - summary: 'Session history, resuming, notes, and scratchpad.', + slug: 'resume-a-session', + title: 'Resume a paused session', + icon: RotateCcw, + summary: 'Pick back up where you left off.', + category: 'pilot-sessions', sections: [ { - title: 'Viewing Session History', + title: 'Resume', steps: [ - { instruction: 'Click **Sessions** in the sidebar to see all your past and active sessions.' }, - { instruction: 'Sessions are listed newest first. Use the filters to show only active or completed sessions.' }, - { instruction: 'Click any session to view its full details including the path taken and notes.' }, - ], - }, - { - title: 'Resuming a Session', - steps: [ - { instruction: 'Find the session in your session history or on the Dashboard.' }, - { instruction: 'Click the session, then click **Resume** to continue where you left off.' }, - { instruction: 'All previous decisions and notes are preserved.', tip: 'Active sessions also appear in the sidebar badge count for quick reference.' }, - ], - }, - { - title: 'Session Notes & Scratchpad', - steps: [ - { instruction: 'During flow navigation, click the **Scratchpad** icon to open the note-taking panel.' }, - { instruction: 'Type free-form notes about your troubleshooting process.' }, - { instruction: 'Notes are saved automatically and included in session exports.' }, + { instruction: 'Click **History** in the sidebar to see all past and active sessions, newest first.' }, + { instruction: 'Click the session you want to continue. The pilot screen reopens with full context restored.' }, + { instruction: 'Or, on the **Home** screen, click any card under **Active Sessions** to jump straight back in.' }, ], }, ], + relatedSlugs: ['start-a-session'], }, { - slug: 'sharing-exports', - title: 'Sharing & Exports', - icon: Share2, - summary: 'Share sessions and export documentation.', + slug: 'navigate-troubleshooting-flow', + title: 'Navigate a troubleshooting flow', + icon: GitBranch, + summary: 'Run an authored decision tree and reach a solution.', + category: 'pilot-sessions', sections: [ { - title: 'Sharing a Session', + title: 'Navigate', steps: [ - { instruction: 'Open a completed session from the session detail page.' }, - { instruction: 'Click the **Share** button to open the sharing modal.' }, - { instruction: 'A unique share link is generated. Click **Copy Link** to copy it to your clipboard.' }, - { instruction: 'Share the link with team members or clients — they can view the session path and notes.' }, - { instruction: 'Manage active share links from the **Exports** page in the sidebar.', tip: 'Share links respect your account\'s public sharing settings. Account owners can enable or disable public shares.' }, - ], - }, - { - title: 'Exporting Sessions', - steps: [ - { instruction: 'From a session detail page, click the **Export** button.' }, - { instruction: 'Choose the detail level: **Summary** (high-level overview), **Standard** (key decisions), or **Detailed** (full path with all notes).' }, - { instruction: 'Preview the export and edit it if needed before downloading.' }, - { instruction: 'Enable **Sensitive Data Redaction** to automatically mask passwords, IPs, and credentials in the export.', tip: 'Use the summary export for client-facing documentation and the detailed export for internal records.' }, - ], - }, - { - title: 'Managing Shares', - steps: [ - { instruction: 'Click **Exports** in the sidebar to see all your shared sessions.' }, - { instruction: 'View how many times each share link has been accessed.' }, - { instruction: 'Revoke share links by clicking the delete icon next to any active share.' }, + { instruction: 'Click **Flows** in the sidebar and find the troubleshooting flow you need.' }, + { instruction: 'Click the flow card and then **Start Session**. The pilot screen opens.' }, + { instruction: 'Read each question in the **Tasks** panel on the right. Click **Answer** to record your response.' }, + { instruction: 'Continue answering until the flow reaches a **Solution**.' }, ], }, ], + relatedSlugs: ['run-procedural-flow', 'start-a-session'], }, { - slug: 'ai-assistant', - title: 'AI Assistant', - icon: BotMessageSquare, - summary: 'Standalone AI chat for IT questions and flow recommendations.', + slug: 'run-procedural-flow', + title: 'Run a procedural flow with an intake form', + icon: ListChecks, + summary: 'Execute a step-by-step procedure on a target.', + category: 'pilot-sessions', sections: [ { - title: 'Starting a Conversation', + title: 'Run', steps: [ - { instruction: 'Click **AI Assistant** in the sidebar to open the chat page.' }, - { instruction: 'Click **Start a Conversation** or the **+ New Chat** button in the left panel.' }, - { instruction: 'Type your question in the message box and press Enter or click the send button.' }, - { instruction: 'The AI responds as a Senior Systems & Network Engineer with MSP expertise.' }, - ], - }, - { - title: 'Managing Conversations', - steps: [ - { instruction: 'All conversations are listed in the left sidebar panel, newest first.' }, - { instruction: 'Click any conversation to switch to it and see the full message history.' }, - { instruction: '**Pin** important conversations by right-clicking or using the pin icon — pinned chats stay at the top.' }, - { instruction: 'Delete conversations you no longer need by clicking the trash icon.' }, - ], - }, - { - title: 'Suggested Flows', - steps: [ - { instruction: 'When you ask a question, the AI searches your team\'s flow library for relevant matches.' }, - { instruction: 'If related flows are found, they appear as **Suggested Flow** cards below the AI response.' }, - { instruction: 'Click a suggested flow card to navigate directly to that flow.' }, + { instruction: 'Open **Flows**, switch to the **Projects** filter, and click the procedural flow you need.' }, + { instruction: 'Click **Start Session**. The intake form appears.' }, + { instruction: 'Fill in the required fields and submit. The first step opens.' }, + { instruction: 'Work through each step in order, marking it complete as you go. Add notes inline where useful.' }, ], }, ], + relatedSlugs: ['navigate-troubleshooting-flow', 'build-intake-form'], }, { - slug: 'ai-copilot', - title: 'Flow Assist (AI Copilot)', + slug: 'tasklane-keyboard-flow', + title: 'Use the tasklane keyboard flow', + icon: Lightbulb, + summary: 'Answer pending tasks without lifting your hands off the keyboard.', + category: 'pilot-sessions', + sections: [ + { + title: 'Keys', + steps: [ + { instruction: 'Click into the answer field on any pending **Question** in the **Tasks** panel.' }, + { instruction: 'Type your answer. Press **Enter** to submit and auto-advance to the next pending task.' }, + { instruction: 'Press **Shift+Enter** to add a newline when an answer needs multiple lines.' }, + { instruction: 'Press **Esc** to cancel the current input and step away.' }, + { instruction: 'After your last submission, focus jumps to **Send Responses** so you can fire all answers in one batch.' }, + ], + }, + ], + relatedSlugs: ['navigate-troubleshooting-flow', 'view-what-we-know'], + }, + { + slug: 'view-what-we-know', + title: 'View What we know during a session', + icon: Eye, + summary: 'See the running list of established facts the AI is reasoning over.', + category: 'pilot-sessions', + sections: [ + { + title: 'View', + steps: [ + { instruction: 'In the **Tasks** panel, find the **What we know · N** header at the top.' }, + { instruction: 'Click to expand and read the facts established so far. Facts are added automatically as you answer questions and paste check output.' }, + { instruction: 'The panel auto-collapses once there are 5 or more facts. Click again any time to re-expand. Your preference is remembered for the rest of the session.' }, + ], + }, + ], + relatedSlugs: ['tasklane-keyboard-flow'], + }, + { + slug: 'ask-ai-mid-session', + title: 'Ask the AI a question mid-session', + icon: MessageSquare, + summary: 'Get contextual help without leaving the session.', + category: 'pilot-sessions', + sections: [ + { + title: 'Ask', + steps: [ + { instruction: 'Find the composer at the bottom of the pilot screen: **"Type a message, paste a screenshot, or drag a file…"**.' }, + { instruction: 'Type your question. Examples: "What else could cause this?", "How do I run this command on Server 2019?", "Explain this step in more detail."' }, + { instruction: 'Press **Enter** or click **Send**. The AI knows what flow and step you\'re on and replies in context.', tip: 'Drop a screenshot or paste log output directly into the composer — the AI can read both.' }, + ], + }, + ], + relatedSlugs: ['open-suggested-flow'], + }, + { + slug: 'pause-and-leave-session', + title: 'Pause and leave a session', + icon: Pause, + summary: 'Save state and walk away without losing context.', + category: 'pilot-sessions', + sections: [ + { + title: 'Pause', + steps: [ + { instruction: 'In the session header, click **Pause**.' }, + { instruction: 'The session is saved automatically with everything you\'ve done so far.' }, + { instruction: 'Pick it up later from **History** or the **Active Sessions** card on **Home**.' }, + ], + }, + ], + relatedSlugs: ['resume-a-session'], + }, + + // ───────────────────────────────────────────────────────────────────── + // Closing out a session + // ───────────────────────────────────────────────────────────────────── + { + slug: 'resolve-a-session', + title: 'Resolve a session', + icon: CircleCheck, + summary: 'Mark the issue fixed and post the resolution note.', + category: 'closing-out', + sections: [ + { + title: 'Resolve', + steps: [ + { instruction: 'In the **Tasks** panel, click **Preview Resolve note** to see the AI-generated resolution summary.' }, + { instruction: 'Edit the note if you want to adjust the wording before posting.' }, + { instruction: 'Click **Resolve** in the session header to mark the session resolved and post the note.', tip: 'If suggested fixes are still parked as **Waiting to verify**, ResolutionFlow auto-marks them as success before resolving.' }, + ], + }, + ], + relatedSlugs: ['record-suggested-fix-outcome', 'escalate-a-session', 'post-docs-to-ticket'], + }, + { + slug: 'record-suggested-fix-outcome', + title: 'Record a suggested-fix outcome', + icon: CheckCircle2, + summary: 'Tell the session whether a fix worked, didn\'t, or needs time.', + category: 'closing-out', + sections: [ + { + title: 'Record', + steps: [ + { instruction: 'After applying a suggested fix, find its banner in the session view.' }, + { instruction: 'Choose the outcome: **It worked**, **Didn\'t work**, or **Waiting to verify…**.' }, + { instruction: 'For **Waiting to verify**, enter a reason (e.g., "Waiting on user to confirm tomorrow morning"). The fix stays open with a **Pending** banner until you finalize it.' }, + { instruction: 'Recording the outcome closes any inline template or follow-on prompts for that fix.' }, + ], + }, + ], + relatedSlugs: ['resolve-a-session'], + }, + { + slug: 'escalate-a-session', + title: 'Escalate a session', + icon: Send, + summary: 'Hand off to a senior tech with full context.', + category: 'closing-out', + sections: [ + { + title: 'Escalate', + steps: [ + { instruction: 'Click **Escalate** in the session header.' }, + { instruction: 'Review the AI-generated **Escalation Mode** package — what was tried, what failed, and the suspected root cause.' }, + { instruction: 'Edit the package as needed and choose a destination: PSA ticket note, email draft, or ticket update.' }, + { instruction: 'Confirm. The senior tech receives the full context, not a "please help" ping.' }, + ], + }, + ], + relatedSlugs: ['resolve-a-session', 'post-docs-to-ticket'], + }, + { + slug: 'post-docs-to-ticket', + title: 'Post session docs to a ConnectWise ticket', + icon: TicketCheck, + summary: 'Write the session\'s output back to your PSA.', + category: 'closing-out', + sections: [ + { + title: 'Post', + steps: [ + { instruction: 'Open the session on a ticket you\'re working. Ticket-linked sessions show ticket actions in the header overflow.' }, + { instruction: 'Click **More session actions** → **Update Ticket**.' }, + { instruction: 'Choose what to post — internal note, public note, or time entry. Edit the markdown if needed.' }, + { instruction: 'Click **Post to ticket**. The note is attributed to your mapped ConnectWise member.', tip: 'Need a one-off update without finishing the session? Use **Share Update** in the header for a partial status post.' }, + ], + }, + ], + relatedSlugs: ['connect-connectwise', 'send-client-update'], + }, + { + slug: 'send-client-update', + title: 'Send a client update from a session', icon: Sparkles, - summary: 'In-session AI help while navigating flows.', + summary: 'Touch base mid-troubleshoot without finishing the session.', + category: 'closing-out', sections: [ { - title: 'Opening Flow Assist', + title: 'Send', steps: [ - { instruction: 'While navigating any flow, look for the **Flow Assist** button (sparkles icon) in the bottom-right corner of the screen.' }, - { instruction: 'Click it to open the AI assistant panel on the right side.' }, - { instruction: 'The AI automatically knows which flow you\'re in and what step you\'re on.' }, - ], - }, - { - title: 'Asking Questions', - steps: [ - { instruction: 'Type your question in the message box at the bottom of the panel.' }, - { instruction: 'Ask things like "What else could cause this?", "How do I run this command?", or "Explain this step in more detail."' }, - { instruction: 'The AI provides contextual answers based on your current position in the flow.' }, - { instruction: 'Your conversation persists throughout the session — you can refer back to earlier answers.', tip: 'Flow Assist is especially useful when you encounter an unfamiliar step or need additional troubleshooting guidance.' }, - ], - }, - { - title: 'Suggested Flows', - steps: [ - { instruction: 'If your question relates to other flows in your team\'s library, the AI shows **Related Flows** cards.' }, - { instruction: 'Click a card to open that flow in a new tab.' }, + { instruction: 'In the session header, click **Share Update**.' }, + { instruction: 'The AI drafts a client-friendly status message based on what\'s been done so far.' }, + { instruction: 'Edit the wording. Toggle redaction to mask sensitive details before sending.' }, + { instruction: 'Send (or copy) the update. Use this when the issue isn\'t resolved yet but the client needs a status touch-point.' }, ], }, ], + relatedSlugs: ['post-docs-to-ticket'], + }, + + // ───────────────────────────────────────────────────────────────────── + // Documentation & sharing + // ───────────────────────────────────────────────────────────────────── + { + slug: 'share-session-link', + title: 'Share a completed session via link', + icon: Share2, + summary: 'Hand a teammate or client a read-only view.', + category: 'documentation', + sections: [ + { + title: 'Share', + steps: [ + { instruction: 'Open the session you want to share.' }, + { instruction: 'Click the **More session actions** kebab in the header and choose **Share**.' }, + { instruction: 'In the share modal, click **Copy Link** to put the URL on your clipboard.' }, + { instruction: 'Send the link. The recipient can view the session path and notes — no login required.', tip: 'Public sharing must be enabled by an account owner. If the option is missing, ask whoever owns the account to turn it on.' }, + ], + }, + ], + relatedSlugs: ['export-session', 'revoke-share-link'], }, { - slug: 'step-library', - title: 'Step Library', + slug: 'export-session', + title: 'Export a session', + icon: Download, + summary: 'Download a session at the right level of detail.', + category: 'documentation', + sections: [ + { + title: 'Export', + steps: [ + { instruction: 'Open the session and click **More session actions** → **Export**.' }, + { instruction: 'Choose a detail level: **Summary** (high-level), **Standard** (key decisions), or **Detailed** (full path with all notes).' }, + { instruction: 'Preview the export and edit the text if needed.' }, + { instruction: 'Click **Download** to save it locally.', tip: 'Set the default format (Markdown / Plain Text / HTML) on the **Acct** page.' }, + ], + }, + ], + relatedSlugs: ['redact-sensitive-data', 'share-session-link'], + }, + { + slug: 'redact-sensitive-data', + title: 'Redact sensitive data from an exported session', + icon: Shield, + summary: 'Mask passwords, IPs, and credentials before sharing.', + category: 'documentation', + sections: [ + { + title: 'Redact', + steps: [ + { instruction: 'Open the session and start an export (**More session actions** → **Export**).' }, + { instruction: 'Toggle **Sensitive Data Redaction** on in the export options.' }, + { instruction: 'Preview to confirm passwords, IPs, and credentials are masked.' }, + { instruction: 'Download the redacted export.' }, + ], + }, + ], + relatedSlugs: ['export-session'], + }, + { + slug: 'revoke-share-link', + title: 'Revoke a session share link', + icon: Link2Off, + summary: 'Cut off access to a previously shared session.', + category: 'documentation', + sections: [ + { + title: 'Revoke', + steps: [ + { instruction: 'Open the session whose share you want to revoke.' }, + { instruction: 'Click **More session actions** → **Share** to see the active link.' }, + { instruction: 'Click **Revoke** next to the link. Anyone holding the URL loses access immediately.' }, + ], + }, + ], + relatedSlugs: ['share-session-link'], + }, + + // ───────────────────────────────────────────────────────────────────── + // Authoring flows + // ───────────────────────────────────────────────────────────────────── + { + slug: 'create-troubleshooting-flow', + title: 'Create a troubleshooting flow', + icon: Box, + summary: 'Spin up a branching decision tree from scratch.', + category: 'authoring', + sections: [ + { + title: 'Create', + steps: [ + { instruction: 'Click **Flows** in the sidebar.' }, + { instruction: 'Click **Create New** and choose **Troubleshooting Flow**.' }, + { instruction: 'Enter a name and an optional description.', tip: 'Name it after the problem it solves, e.g. "DNS Resolution Failure" — teammates search by symptom.' }, + { instruction: 'Click **Create**. The canvas editor opens with an empty root node.' }, + ], + }, + ], + relatedSlugs: ['add-nodes-and-branches', 'write-solution-node'], + }, + { + slug: 'add-nodes-and-branches', + title: 'Add nodes and branches on the canvas', + icon: Workflow, + summary: 'Build out the decision tree.', + category: 'authoring', + sections: [ + { + title: 'Build', + steps: [ + { instruction: 'In the canvas editor, click the **+** on any node to add a child.' }, + { instruction: 'Choose the type: **Question** (asks the engineer something), **Action** (instructs them to do something), or **Solution** (the resolution).' }, + { instruction: 'Type the node content. For **Question** nodes, add the answer **options** that branch to different paths.', tip: 'Keep questions specific. "Is the DNS server responding to nslookup?" beats "Check DNS".' }, + { instruction: 'Use **Undo** (Ctrl+Z) and **Redo** (Ctrl+Shift+Z) to revert mistakes.' }, + ], + }, + ], + relatedSlugs: ['write-solution-node', 'create-troubleshooting-flow'], + }, + { + slug: 'write-solution-node', + title: 'Write a solution node', + icon: Flag, + summary: 'End a path with an actionable resolution.', + category: 'authoring', + sections: [ + { + title: 'Write', + steps: [ + { instruction: 'Add a **Solution** node at the end of a path.' }, + { instruction: 'Write the resolution in plain language, with specific commands or steps the engineer should follow.' }, + { instruction: 'Save. A flow can have multiple solution nodes for different resolution paths.' }, + ], + }, + ], + relatedSlugs: ['add-nodes-and-branches'], + }, + { + slug: 'create-procedural-flow', + title: 'Create a procedural flow', + icon: ClipboardList, + summary: 'Author a step-by-step procedure (project).', + category: 'authoring', + sections: [ + { + title: 'Create', + steps: [ + { instruction: 'Click **Flows** → **Create New** → **Procedural Flow**.' }, + { instruction: 'Enter a name and description.' }, + { instruction: 'Click **Create**. The procedural editor opens.' }, + { instruction: 'Click **Add Step** for each task in the procedure. Drag steps to reorder.', tip: 'Group long procedures with **Section Headers** like "Preparation", "Execution", "Verification".' }, + ], + }, + ], + relatedSlugs: ['build-intake-form', 'run-procedural-flow'], + }, + { + slug: 'build-intake-form', + title: 'Build an intake form for a procedural flow', + icon: FormInput, + summary: 'Collect inputs once, reuse across every step.', + category: 'authoring', + sections: [ + { + title: 'Build', + steps: [ + { instruction: 'In the procedural editor, click **Add Field** in the intake form section.' }, + { instruction: 'Choose the field type: **Text**, **Textarea**, **Select**, **Number**, **URL**, or **Checkbox**.' }, + { instruction: 'Set the **variable name** (e.g. `client_name`, `server_ip`). Steps reference values by this name.' }, + { instruction: 'Mark fields as **Required** if they must be filled before the procedure starts.', tip: 'Reference variables in step instructions to auto-fill commands and notes.' }, + ], + }, + ], + relatedSlugs: ['create-procedural-flow'], + }, + { + slug: 'organize-with-categories-tags', + title: 'Organize flows with categories and tags', + icon: Tag, + summary: 'Make flows findable for the rest of the team.', + category: 'authoring', + sections: [ + { + title: 'Organize', + steps: [ + { instruction: 'Open a flow and click into its name or settings area to edit metadata.' }, + { instruction: 'Assign a **category** (e.g. "Networking", "Active Directory") to group it on the **Flows** page.' }, + { instruction: 'Add **tags** for searchability — "DNS", "VPN", "Firewall". Tags are shared across your team.', tip: 'Use consistent tag spelling so the search picks up everyone\'s flows.' }, + ], + }, + ], + relatedSlugs: ['manage-team-categories'], + }, + + // ───────────────────────────────────────────────────────────────────── + // Reusable assets + // ───────────────────────────────────────────────────────────────────── + { + slug: 'save-to-solutions-library', + title: 'Save a step to the Solutions Library', + icon: BookmarkPlus, + summary: 'Promote a one-off step into a reusable building block.', + category: 'reusable-assets', + sections: [ + { + title: 'Save', + steps: [ + { instruction: 'In the procedural flow editor, click **Save to Library** on a step you want to reuse.' }, + { instruction: 'Give it a name and an optional category.' }, + { instruction: 'The step is now available to import into any procedural flow.' }, + ], + }, + ], + relatedSlugs: ['import-from-solutions-library'], + }, + { + slug: 'import-from-solutions-library', + title: 'Import a Solutions Library entry into a flow', icon: Bookmark, - summary: 'Reusable steps you can import into any procedural flow.', + summary: 'Drop a saved step into the procedure you\'re building.', + category: 'reusable-assets', sections: [ { - title: 'Browsing the Step Library', + title: 'Import', steps: [ - { instruction: 'Click **Step Library** in the sidebar to view all saved reusable steps.' }, - { instruction: 'Steps are organized by category and can be searched by name or tags.' }, - { instruction: 'Click any step to view its full details and instructions.' }, - ], - }, - { - title: 'Saving Steps to the Library', - steps: [ - { instruction: 'In the procedural flow editor, click the **Save to Library** option on any step.' }, - { instruction: 'Give the library step a name and optional category.' }, - { instruction: 'The step is now available for reuse across all your procedural and maintenance flows.' }, - ], - }, - { - title: 'Importing Library Steps', - steps: [ - { instruction: 'In the procedural flow editor, click **Import from Library** when adding a new step.' }, - { instruction: 'Browse or search the step library for the step you want.' }, - { instruction: 'Click **Import** to add it to your flow. The imported step is a copy — editing it won\'t affect the library version.', tip: 'Use the step library for common procedures like "Verify backup status" or "Check DNS resolution" that appear across multiple flows.' }, + { instruction: 'Open **Flows** and switch to the **Solutions Library** tab to browse what\'s available.' }, + { instruction: 'From the procedural editor, click **Import from Library** when adding a step.' }, + { instruction: 'Search or browse, then click **Import**. The imported step is a copy — editing it won\'t affect the library version.' }, ], }, ], + relatedSlugs: ['save-to-solutions-library'], }, { - slug: 'maintenance', - title: 'Maintenance Flows', - icon: Wrench, - summary: 'Batch launches, target lists, and scheduled maintenance.', - sections: [ - { - title: 'Setting Up a Maintenance Flow', - steps: [ - { instruction: 'Create a new flow and select **Maintenance** as the type.' }, - { instruction: 'Build your steps in the procedural editor — these are the maintenance tasks to perform on each target.' }, - { instruction: 'The flow detail page shows maintenance-specific options including batch launches and scheduling.' }, - ], - }, - { - title: 'Target Lists', - steps: [ - { instruction: 'Go to **Account** > **Target Lists** to manage your saved target lists.' }, - { instruction: 'Create a target list with the servers, workstations, or devices you maintain.' }, - { instruction: 'Target lists can be reused across multiple maintenance flows and batch launches.', tip: 'Organize target lists by client or site for easy batch launches (e.g., "Acme Corp - Domain Controllers").' }, - ], - }, - { - title: 'Batch Launching', - steps: [ - { instruction: 'Open a maintenance flow and click **Launch Batch**.' }, - { instruction: 'Select a saved **Target List** or manually enter targets.' }, - { instruction: 'Click **Launch** to create a session for each target in the list.' }, - { instruction: 'All sessions are created immediately. Click into any target to begin executing the maintenance steps.' }, - { instruction: 'Track progress on the **Batch Status** page showing completion status across all targets.' }, - ], - }, - { - title: 'Scheduling', - steps: [ - { instruction: 'On the maintenance flow detail page, click **Schedule** to set up recurring execution.' }, - { instruction: 'Choose a schedule (e.g., weekly, monthly) using the cron expression builder.' }, - { instruction: 'Select the target list to use for each scheduled run.' }, - { instruction: 'Scheduled batches are launched automatically at the configured time.' }, - ], - }, - ], - }, - { - slug: 'account-settings', - title: 'Account Settings', - icon: Settings, - summary: 'Team management, categories, tags, and profile settings.', - sections: [ - { - title: 'Profile Settings', - steps: [ - { instruction: 'Click your **avatar** in the top-right corner and select **Account**.' }, - { instruction: 'Click **Profile Settings** to update your display name, email, and password.' }, - { instruction: 'Changes take effect immediately after saving.' }, - ], - }, - { - title: 'Team Categories', - steps: [ - { instruction: 'Go to **Account** and click **Team Categories** (account owner only).' }, - { instruction: 'Add categories to organize your team\'s flows (e.g., "Networking", "Security", "Cloud").' }, - { instruction: 'Assign colors to categories for visual distinction in the flow library.' }, - { instruction: 'Delete or rename categories as your team\'s needs evolve.' }, - ], - }, - { - title: 'Chat Retention', - steps: [ - { instruction: 'Go to **Account** and click **Chat Retention** (account owner only).' }, - { instruction: 'Set the **retention period** (default: 90 days) — chats older than this are automatically deleted.' }, - { instruction: 'Set the **maximum conversation count** (default: 100) — oldest chats are deleted when the limit is exceeded.' }, - { instruction: 'Pinned chats are never automatically deleted.', tip: 'Pin important AI conversations to preserve them regardless of retention settings.' }, - ], - }, - ], - }, - { - slug: 'analytics', - title: 'Analytics', - icon: BarChart3, - summary: 'Dashboard metrics, team usage, and personal stats.', - sections: [ - { - title: 'Team Analytics', - steps: [ - { instruction: 'Click **Analytics** in the sidebar to view team-wide metrics.' }, - { instruction: 'See total flows, active sessions, completion rates, and usage trends.' }, - { instruction: 'Filter by date range to analyze specific periods.' }, - ], - }, - { - title: 'Personal Analytics', - steps: [ - { instruction: 'From the Analytics page, click **My Stats** to see your individual metrics.' }, - { instruction: 'Track your session count, most-used flows, and average completion time.' }, - { instruction: 'Use personal analytics to identify areas where you spend the most troubleshooting time.' }, - ], - }, - ], - }, - { - slug: 'script-templates', - title: 'Script Templates', + slug: 'generate-script-from-template', + title: 'Generate a script from a template', icon: Terminal, - summary: 'Browse, configure, and generate scripts from reusable templates.', + summary: 'Fill in parameters and get a ready-to-run script.', + category: 'reusable-assets', sections: [ { - title: 'Browsing Templates', + title: 'Generate', steps: [ - { instruction: 'Click **Scripts** in the sidebar to open the Script Library.' }, - { instruction: 'The left pane lists all available templates organized by category.' }, - { instruction: 'Use the search bar to filter templates by name or keyword.' }, - { instruction: 'Click any template to preview its script content in the right pane.' }, + { instruction: 'Click **Scripts** in the sidebar.' }, + { instruction: 'Browse or search the **Script Library**. Click a template to preview the script.' }, + { instruction: 'Click **Configure** and fill in the parameter values (server name, IP, credentials, etc.).' }, + { instruction: 'Click **Generate**. Copy the result to your clipboard or download it.', tip: 'Run generated scripts in a test environment before production.' }, + ], + }, + ], + relatedSlugs: ['manage-script-templates'], + }, + { + slug: 'manage-script-templates', + title: 'Manage script templates', + icon: Settings, + summary: 'Create, edit, and delete templates for the team.', + category: 'reusable-assets', + sections: [ + { + title: 'Manage', + steps: [ + { instruction: 'On the **Scripts** page, click **Manage** at the top.' }, + { instruction: 'Click **New Template** and enter a name, category, script body, and configurable parameters.' }, + { instruction: 'Edit or delete existing templates from the same page. PowerShell, Bash, Python, and other languages are supported.' }, + ], + }, + ], + relatedSlugs: ['generate-script-from-template'], + }, + { + slug: 'build-script-from-scratch', + title: 'Build a script from scratch with Script Builder', + icon: TerminalSquare, + summary: 'Describe what you need, iterate via chat, save it for the team.', + category: 'reusable-assets', + sections: [ + { + title: 'Build', + steps: [ + { instruction: 'Click **Scripts** in the sidebar.' }, + { instruction: 'Click **Build New Script** at the top.' }, + { instruction: 'Describe what the script needs to do in plain language. Script Builder generates an initial draft.' }, + { instruction: 'Iterate via chat — ask Script Builder to add error handling, change languages, or refactor.' }, + { instruction: 'Test the result, then click **Save** to add it to your team\'s Script Library.', tip: 'You can hand off to Script Builder from inside a pilot session via "Open in Script Builder" — context carries over.' }, + ], + }, + ], + relatedSlugs: ['generate-script-from-template', 'manage-script-templates'], + }, + + // ───────────────────────────────────────────────────────────────────── + // AI assistance + // ───────────────────────────────────────────────────────────────────── + { + slug: 'open-suggested-flow', + title: 'Open a flow suggested by the AI', + icon: Sparkles, + summary: 'Jump into a relevant team flow without breaking your session.', + category: 'ai-assistance', + sections: [ + { + title: 'Open', + steps: [ + { instruction: 'While chatting with the AI in a pilot session, watch for **Suggested Flow** cards beneath the AI\'s responses.' }, + { instruction: 'The cards appear when the AI matches a pattern in your team\'s flow library.' }, + { instruction: 'Click a card to open that flow. It loads in context so you can run it without losing the current session.' }, + ], + }, + ], + relatedSlugs: ['ask-ai-mid-session', 'navigate-troubleshooting-flow'], + }, + + // ───────────────────────────────────────────────────────────────────── + // PSA integrations + // ───────────────────────────────────────────────────────────────────── + { + slug: 'connect-connectwise', + title: 'Connect ConnectWise to ResolutionFlow', + icon: Plug, + summary: 'Wire up your PSA so sessions can post back to tickets.', + category: 'psa', + sections: [ + { + title: 'In ConnectWise', + steps: [ + { instruction: 'Sign in to ConnectWise PSA as an admin.' }, + { instruction: 'Go to **System → Members → API Members** and create a new API member.', tip: 'Create a dedicated API member with minimal permissions for security.' }, + { instruction: 'Generate an **API key pair** (public + private key) for the member.' }, + { instruction: 'Note your **Company ID** and **Site URL** (e.g. `na.myconnectwise.net`).' }, ], }, { - title: 'Configuring and Generating Scripts', + title: 'In ResolutionFlow', steps: [ - { instruction: 'Click **Configure** on a template to enter parameter values.' }, - { instruction: 'Fill in the required fields (e.g., server name, IP address, credentials).' }, - { instruction: 'Click **Generate** to produce a ready-to-run script with your values substituted.' }, - { instruction: 'Copy the generated script to your clipboard or download it directly.', tip: 'Double-check generated scripts in a test environment before running them in production.' }, + { instruction: 'Open **Acct → Integrations**.' }, + { instruction: 'Enter a display name, the Site URL, Company ID, public key, and private key.' }, + { instruction: 'Click **Connect**. Run a quick **Test Connection** afterward to confirm.' }, ], }, + ], + relatedSlugs: ['map-connectwise-members', 'test-connectwise-connection'], + }, + { + slug: 'map-connectwise-members', + title: 'Map ConnectWise members to ResolutionFlow teammates', + icon: Users, + summary: 'Make sure ticket notes are credited to the right person.', + category: 'psa', + sections: [ { - title: 'Managing Templates', + title: 'Map', steps: [ - { instruction: 'Click **Manage Templates** at the top of the Script Library page.' }, - { instruction: 'Create new templates with a name, category, script body, and configurable parameters.' }, - { instruction: 'Edit or delete existing templates from the management page.' }, - { instruction: 'Templates support PowerShell, Bash, Python, and other scripting languages.' }, + { instruction: 'Open **Acct → Integrations** and switch to the **Member Mapping** tab.' }, + { instruction: 'Click **Auto-Match by Email** to pair users automatically.' }, + { instruction: 'Manually adjust any unmatched or incorrectly matched members using the dropdowns.' }, + { instruction: 'Click **Save Mappings**. Mapped members are credited when ResolutionFlow posts notes back to tickets.' }, + ], + }, + ], + relatedSlugs: ['connect-connectwise'], + }, + { + slug: 'test-connectwise-connection', + title: 'Test a ConnectWise connection', + icon: PlugZap, + summary: 'Confirm credentials are valid before going live.', + category: 'psa', + sections: [ + { + title: 'Test', + steps: [ + { instruction: 'Open **Acct → Integrations** and find the connection you want to test.' }, + { instruction: 'Click **Test Connection**.' }, + { instruction: 'A success indicator confirms credentials are valid. If it fails, re-check the keys, Company ID, and Site URL.' }, + ], + }, + ], + relatedSlugs: ['connect-connectwise'], + }, + + // ───────────────────────────────────────────────────────────────────── + // Account & team admin + // ───────────────────────────────────────────────────────────────────── + { + slug: 'update-profile', + title: 'Update your profile', + icon: User, + summary: 'Change your display name, email, or password.', + category: 'account-admin', + sections: [ + { + title: 'Edit', + steps: [ + { instruction: 'Click **Acct** in the sidebar (or your **avatar** in the top-right).' }, + { instruction: 'Click **Profile Settings**.' }, + { instruction: 'Update your display name, email, or password and save. Changes take effect immediately.' }, ], }, ], }, { - slug: 'psa-setup', - title: 'PSA Integration Setup', - icon: Plug, - summary: 'Connect ConnectWise or other PSA tools to ResolutionFlow.', + slug: 'manage-team-categories', + title: 'Manage team categories', + icon: FolderOpen, + summary: 'Create the category list everyone tags flows with. Account owner only.', + category: 'account-admin', sections: [ { - title: 'Getting Your API Credentials', + title: 'Manage', steps: [ - { instruction: 'Log in to your ConnectWise PSA instance as an admin.' }, - { instruction: 'Navigate to **System > Members > API Members** and create a new API member.' }, - { instruction: 'Generate an **API key pair** (public key and private key) for the member.' }, - { instruction: 'Note your **Company ID** (the company identifier used to log in) and **Site URL** (e.g., na.myconnectwise.net).', tip: 'Create a dedicated API member for ResolutionFlow with minimal permissions for security.' }, - ], - }, - { - title: 'Connecting in ResolutionFlow', - steps: [ - { instruction: 'Go to **Account > Integrations** in ResolutionFlow.' }, - { instruction: 'Enter a display name, your Site URL, Company ID, Public Key, and Private Key.' }, - { instruction: 'Click **Connect** to save the connection.' }, - { instruction: 'Click **Test Connection** to verify everything is working correctly.' }, - ], - }, - { - title: 'Member Mapping', - steps: [ - { instruction: 'After connecting, switch to the **Member Mapping** tab.' }, - { instruction: 'Click **Auto-Match by Email** to automatically pair ResolutionFlow users with ConnectWise members by email address.' }, - { instruction: 'Manually adjust any unmatched or incorrectly matched members using the dropdowns.' }, - { instruction: 'Click **Save Mappings** to apply changes. Mapped members are used when posting session notes to tickets.' }, - ], - }, - { - title: 'What the Integration Enables', - steps: [ - { instruction: 'Session documentation can be posted directly to ConnectWise tickets as internal notes.' }, - { instruction: 'Ticket context (client info, issue details) can be pulled into sessions for AI-assisted troubleshooting.' }, - { instruction: 'Posts are attributed to the correct ConnectWise member based on your member mappings.' }, + { instruction: 'Open **Acct → Team Categories**.' }, + { instruction: 'Click **Create Category**. Give it a name (e.g. "Networking", "Cloud") and a description.' }, + { instruction: 'Rename or delete categories as your team\'s needs evolve. Existing flows keep their assignment until reassigned.' }, ], }, ], + relatedSlugs: ['organize-with-categories-tags'], + }, + { + slug: 'set-chat-retention', + title: 'Set chat retention', + icon: Clock, + summary: 'Control how long AI conversations stick around. Account owner only.', + category: 'account-admin', + sections: [ + { + title: 'Configure', + steps: [ + { instruction: 'Open **Acct → Chat Retention**.' }, + { instruction: 'Set **Retention Period (days)**. Chats older than this are deleted automatically. Range: 1-365 days.' }, + { instruction: 'Set **Max Conversations**. When this limit is exceeded, oldest unpinned chats are deleted.' }, + { instruction: 'Click **Save Settings**.', tip: 'Pinned conversations are never auto-deleted regardless of retention. Pin the ones you want to keep.' }, + ], + }, + ], + }, + { + slug: 'invite-teammate', + title: 'Invite a teammate', + icon: UserPlus, + summary: 'Send an invite so a coworker can join your team. Account owner only.', + category: 'account-admin', + sections: [ + { + title: 'Invite', + steps: [ + { instruction: 'Click **Acct** in the sidebar and scroll to the **Membership** section.' }, + { instruction: 'In the **Invites** form, enter the teammate\'s email.' }, + { instruction: 'Choose the role: **Engineer** or **Viewer**.' }, + { instruction: 'Click **Send Invite**. They get an email with a sign-up link. Pending invites appear under the form until accepted.', tip: 'Teammates can also self-join with the **Display Code** shown at the top of the Acct page if you share it with them.' }, + ], + }, + ], + }, + + // ───────────────────────────────────────────────────────────────────── + // Analytics + // ───────────────────────────────────────────────────────────────────── + { + slug: 'view-team-analytics', + title: 'View team analytics', + icon: BarChart3, + summary: 'See team-wide usage and resolution metrics.', + category: 'analytics', + sections: [ + { + title: 'View', + steps: [ + { instruction: 'Click **Data** in the sidebar.' }, + { instruction: 'The default view shows team-wide metrics: total flows, active sessions, completion rates, and trends.' }, + { instruction: 'Use the date-range filter to focus on a specific period.' }, + ], + }, + ], + relatedSlugs: ['view-personal-stats'], + }, + { + slug: 'view-personal-stats', + title: 'View your personal stats', + icon: TrendingUp, + summary: 'Track your own session count and completion times.', + category: 'analytics', + sections: [ + { + title: 'View', + steps: [ + { instruction: 'Click **Data** in the sidebar.' }, + { instruction: 'Switch to the **My Stats** tab.' }, + { instruction: 'Track your session count, most-used flows, and average completion time.' }, + ], + }, + ], + relatedSlugs: ['view-team-analytics'], }, ] diff --git a/frontend/src/pages/GuideDetailPage.tsx b/frontend/src/pages/GuideDetailPage.tsx index b597354b..074d6d87 100644 --- a/frontend/src/pages/GuideDetailPage.tsx +++ b/frontend/src/pages/GuideDetailPage.tsx @@ -47,9 +47,6 @@ export default function GuideDetailPage() {
- - {guide.sections.length} {guide.sections.length === 1 ? 'section' : 'sections'} - {guide.sections.reduce((acc, s) => acc + s.steps.length, 0)} steps @@ -63,6 +60,28 @@ export default function GuideDetailPage() { ))}
+ {/* Related guides */} + {guide.relatedSlugs && guide.relatedSlugs.length > 0 && ( +
+

Related guides

+
    + {guide.relatedSlugs + .map(slug => guides.find(g => g.slug === slug)) + .filter((g): g is NonNullable => Boolean(g)) + .map(related => ( +
  • + + {related.title} + +
  • + ))} +
+
+ )} + {/* Back link */}
- {/* Guide cards grid */} -
- {guides.map(guide => ( - - ))} + {/* Category sections */} +
+ {categories.map(category => { + const categoryGuides = guides.filter(g => g.category === category.id) + if (categoryGuides.length === 0) return null + return ( +
+
+

+ {category.label} +

+

{category.description}

+
+
+ {categoryGuides.map(guide => ( + + ))} +
+
+ ) + })}