822f4266f6
Reorganizes the /docs surface from a single DOCS.md route into a hub with a left-side flyout nav and three new sub-routes for the on-site sessions browser (roadmap item #30): /docs → redirect to /docs/user-guide /docs/user-guide → existing DOCS.md content /docs/sessions → redirect to /docs/sessions/about /docs/sessions/about → README.md of ohm-session-history /docs/sessions/<NNNN> → per-session transcript index /docs/sessions/<NNNN>/<f> → per-transcript view The flyout is a persistent left sidebar on desktop and a slide-out drawer on mobile (toggled by a ☰ button in the docs header). Its session list is driven by the /api/docs/sessions/manifest fetch — loading shows a skeleton; 502 shows an inline retry; empty manifest shows only the "About" row. Each sub-route owns its own empty-state / error handling: - 404 transcripts render "This transcript isn't published yet" with a link back to the parent session index, no JS crash. - 502 (gitea unreachable) renders a retry button. - Manifest 404 is mapped to {} server-side so the flyout renders cleanly with no error banner when no sessions are published yet. Analytics (per SPEC §21): - new EVENTS.DOC_VIEWED ("Doc Viewed") fires on each sub-route mount with `section`: 'user-guide' | 'sessions/about' | 'sessions/<NNNN>' | 'sessions/<NNNN>/<filename>'. - every interactive nav element carries aria-label + data-amp-track-name so autocapture rows are readable. The existing v0.14.0 Docs.jsx component is dropped — its content moved verbatim into DocsUserGuide.jsx; the new layout subsumes the back-button + signed-out home affordances it used to carry. All four new sub-routes reuse the existing MarkdownPreview renderer (marked + mermaid lazy-load) so no second markdown library lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
2.9 KiB
React
97 lines
2.9 KiB
React
// DocsSessionTranscript.jsx — v0.19.0 / roadmap item #30.
|
|
//
|
|
// Per-transcript view at `/docs/sessions/:nnnn/:filename`. Fetches the
|
|
// transcript body via the backend mediator and renders it through the
|
|
// shared MarkdownPreview.
|
|
//
|
|
// Empty-state contract:
|
|
// 404 → "This transcript isn't published yet" with a link back to
|
|
// the parent session index
|
|
// 502 → "Couldn't reach the session-history repo" + retry button
|
|
|
|
import { useEffect, useState, useCallback } from 'react'
|
|
import { Link, useParams } from 'react-router-dom'
|
|
import MarkdownPreview from './MarkdownPreview.jsx'
|
|
import { getSessionTranscript } from '../api.js'
|
|
import { EVENTS, track } from '../lib/analytics'
|
|
|
|
export default function DocsSessionTranscript() {
|
|
const { nnnn, filename } = useParams()
|
|
const [body, setBody] = useState('')
|
|
const [status, setStatus] = useState('loading') // loading | ok | notfound | error
|
|
const [reloadTick, setReloadTick] = useState(0)
|
|
|
|
useEffect(() => {
|
|
track(EVENTS.DOC_VIEWED, { section: `sessions/${nnnn}/${filename}` })
|
|
}, [nnnn, filename])
|
|
|
|
useEffect(() => {
|
|
let active = true
|
|
setStatus('loading')
|
|
getSessionTranscript(nnnn, filename)
|
|
.then(text => {
|
|
if (!active) return
|
|
setBody(text || '')
|
|
setStatus('ok')
|
|
})
|
|
.catch(e => {
|
|
if (!active) return
|
|
if (e.status === 404) {
|
|
setStatus('notfound')
|
|
} else {
|
|
setStatus('error')
|
|
}
|
|
})
|
|
return () => { active = false }
|
|
}, [nnnn, filename, reloadTick])
|
|
|
|
const retry = useCallback(() => setReloadTick(t => t + 1), [])
|
|
|
|
return (
|
|
<article className="docs-article">
|
|
<div className="docs-breadcrumbs">
|
|
<Link
|
|
to={`/docs/sessions/${nnnn}`}
|
|
aria-label={`Back to session ${nnnn} index`}
|
|
data-amp-track-name="Docs Transcript Back To Index"
|
|
>
|
|
← Session {nnnn}
|
|
</Link>
|
|
</div>
|
|
{status === 'loading' && <p className="muted">Loading…</p>}
|
|
{status === 'notfound' && (
|
|
<div className="docs-empty">
|
|
<p>This transcript isn't published yet.</p>
|
|
<p>
|
|
<Link
|
|
to={`/docs/sessions/${nnnn}`}
|
|
aria-label={`Back to session ${nnnn}`}
|
|
data-amp-track-name="Docs Transcript Back To Session"
|
|
>
|
|
← Back to session {nnnn}
|
|
</Link>
|
|
</p>
|
|
</div>
|
|
)}
|
|
{status === 'error' && (
|
|
<div className="docs-error" role="alert">
|
|
<p>Couldn't reach the session-history repo.</p>
|
|
<button
|
|
type="button"
|
|
onClick={retry}
|
|
aria-label="Retry"
|
|
data-amp-track-name="Docs Transcript Retry"
|
|
>
|
|
Try again
|
|
</button>
|
|
</div>
|
|
)}
|
|
{status === 'ok' && (
|
|
<div className="philosophy-body">
|
|
<MarkdownPreview content={body} />
|
|
</div>
|
|
)}
|
|
</article>
|
|
)
|
|
}
|