feat: session sharing frontend (#76)

* feat: add session sharing types, API client, and utilities

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add SessionTimeline and ActionMenu reusable components

SessionTimeline extracts timeline/checklist rendering from SessionDetailPage
into a reusable component for both authenticated and public session views.
ActionMenu provides a dropdown action menu with keyboard/click-outside dismiss.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add ShareSessionModal and integrate into SessionDetailPage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add Share Progress popover to TreeNavigationPage

Replace the single "Copy for Ticket" button with a "Share Progress"
popover that offers three actions: Copy Progress Summary (existing PSA
export flow), Copy Share Link (auto-creates account-only share if
needed), and Manage Share Links (opens ShareSessionModal).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add public SharedSessionPage with tree preview

Add the public-facing shared session page at /share/:shareToken that
renders shared sessions without authentication. Includes error handling
for 401 (redirect to login), 403 (access denied), 404 (not found),
and 410 (expired). The page features a minimal header, session metadata,
SessionTimeline component, and a new SharedSessionTreePreview component
that renders the decision tree structure with the path taken highlighted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add My Shares management page with nav link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address code review issues in session sharing

- Add useCallback for loadShares in ShareSessionModal (React hook deps)
- Use TreeStructure type instead of Record<string, unknown> for type safety
- Fix login redirect format to match LoginPage's expected state shape

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add focused tests for session sharing utilities and API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve tree_structure type compatibility for shared session views

- Use TreeStructure & Record<string, unknown> intersection for JSONB flexibility
- Add explicit cast in SharedSessionTreePreview for recursive node rendering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add session sharing learnings to CLAUDE.md

Add gotchas #12 (TreeStructure vs Tree types) and #13 (login redirect
state format), note about npm run build strictness, and public route
pattern to Common Tasks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: procedural editor UX improvements

Add URL intake field type, fix variable name editing collapsing fields
(index-based keys/updates), auto-generate variable names by field type,
add section header as first-class step type, and simplify step editor
with "More Options" collapsible for advanced fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: allow section_header step type in validation, improve tag input

- Add 'section_header' to VALID_STEP_TYPES in backend validation so
  procedural flows with section headers can be published
- Replace procedural editor's inline tag input with TagInput component
  (supports autocomplete, Tab, comma, semicolon, and paste splitting)
- Add semicolon delimiter support to TagInput component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add type-aware routing for procedural flows

Centralizes tree navigation routing via getTreeNavigatePath helper.
Fixes all pages to route procedural sessions to /flows/:id/navigate
instead of /trees/:id/navigate. Adds safety redirect in troubleshooting
navigator and resume support in procedural navigator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove unused index prop from IntakeFieldEditor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #76.
This commit is contained in:
chihlasm
2026-02-14 23:08:17 -05:00
committed by GitHub
parent 6b4304ab92
commit 57f429f33b
32 changed files with 2199 additions and 426 deletions

View File

@@ -39,6 +39,7 @@ export interface TreeSnapshot extends TreeStructure {
description?: string
category?: string
version?: number
tree_type?: string
}
export interface Session {
@@ -58,6 +59,7 @@ export interface Session {
exported: boolean
scratchpad: string
next_steps: string
session_variables: Record<string, string>
}
export interface SessionCreate {
@@ -125,3 +127,45 @@ export interface SaveAsTreeResponse {
tree_name: string
message: string
}
// Session Sharing
export type SessionShareVisibility = 'public' | 'account'
export interface SessionShareCreate {
visibility: SessionShareVisibility
share_name?: string
expires_at?: string // ISO datetime string
}
export interface SessionShare {
id: string
session_id: string
account_id: string
share_token: string
share_name: string | null
visibility: SessionShareVisibility
created_by: string
created_at: string
updated_at: string
expires_at: string | null
view_count: number
last_viewed_at: string | null
is_active: boolean
share_url: string | null
}
export interface SharedSessionView {
session_id: string
tree_name: string
tree_description: string | null
tree_structure: TreeStructure & Record<string, unknown>
path_taken: string[]
decisions: DecisionRecord[]
custom_steps: CustomStep[]
started_at: string
completed_at: string | null
ticket_number: string | null
client_name: string | null
share_name: string | null
visibility: SessionShareVisibility
}

View File

@@ -61,7 +61,7 @@ export interface TreeStructure {
export type TreeType = 'troubleshooting' | 'procedural'
export type IntakeFieldType =
| 'text' | 'textarea' | 'number' | 'ip_address' | 'email'
| 'text' | 'textarea' | 'number' | 'ip_address' | 'email' | 'url'
| 'select' | 'multi_select' | 'checkbox' | 'password'
export type StepContentType = 'action' | 'informational' | 'verification' | 'warning'
@@ -105,7 +105,7 @@ export interface StepVerification {
export interface ProceduralStep {
id: string
type: 'procedure_step' | 'procedure_end'
type: 'procedure_step' | 'procedure_end' | 'section_header'
title: string
description?: string
content_type?: StepContentType