FrontPage
is an async component
The front page: what the project is and how to get it, what you can use (its packages, apps and docs), a map of its namespaces with where their code runs, and its README.
import { docSummary } from "#codebase/tcmts/cli/pages"; import { shortHash } from "#codebase/tcmts/core/hash"; import { at, childrenOf, codeHref, DefRow, entriesIn, Frame, GetIt, getItCommand, Html, inSlices, leafOf, markdownHtml, namesNow, namespaceSummary, pageOf, parentOf, Place, PlaceBar, placeMix, projectNow, roleNow, shareNow, } from "#codebase/tcmts/share"; export async function FrontPage() { const s = shareNow(); if (!s.signedIn) return <Frame tab="code" title="Sign in" children={null} />; const rows = namesNow(s); const project = projectNow(s); const head = s.cb.store.head(); const releases = s.cb.store.releases(); // (where each runs: the map's bars, and which are apps) await inSlices(rows.map((r) => () => roleNow(s, r))); const apps = rows.filter((r) => r.kind === "term" && roleNow(s, r) === "app").slice(0, 4); const docsNs = [...new Set(rows.filter((r) => r.kind === "file").map((r) => parentOf(r.path)))].find((n) => leafOf(n) === "docs"); const { namespaces, defs } = childrenOf(rows, project.root); const loose = defs.filter((r) => leafOf(r.path) !== "README" && leafOf(r.path) !== "CONTRIBUTING"); const readme = project.readme && pageOf(s, project.readme.hash); return ( <Frame tab="code" title={project.name}> <div className="narrow"> <h1 className="sr-only">{project.name}</h1> {project.description && <p className="lede">{project.description}</p>} <div className="facts"> {!s.shown && <GetIt command={getItCommand(s)} isPublic={s.isPublic} />} <span> ⎇ {s.cb.store.branch().name} · <a className="hash" href={at(`/history/${head}`)}>{shortHash(head)}</a> </span> <span>{rows.length.toLocaleString("en")} definitions</span> <a href={at("/history")}>{entriesIn(s, head).toLocaleString("en")} history entries</a> {!s.shown && <a href={at("/people")}>maintainer{s.users.length ? ` + ${s.users.length} contributor${s.users.length > 1 ? "s" : ""}` : ""}</a>} </div> {(project.packages.length > 0 || apps.length > 0 || docsNs || project.readme) && ( <div className="entry"> {project.packages.map((p) => { const latest = releases.filter((r) => r.package === p.name).sort((a, b) => b.ts - a.ts)[0]; return ( <div className="ecard" key={p.name}> <div className="kind">Package</div> <h3 className="mono"> <a href={codeHref(p.manifestPath)}>{p.name}</a> </h3> <p>{p.description ?? (p.bins.length ? `the ${p.bins.join(", ")} command${p.bins.length > 1 ? "s" : ""}` : `the ${p.namespace || "whole"} namespace`)}</p> {latest ? <a href={at(`/releases#${p.name}@${latest.version}`)}>{latest.version}</a> : <span className="muted">not released</span>} {p.bins.length > 0 && ( <> {" "} <span className="muted">· runs</span> {p.bins.map((b) => <code key={b}>{b} </code>)} </> )} </div> ); })} {apps.map((a) => ( <div className="ecard" key={a.path}> <div className="kind">App</div> <h3 className="mono"> <a href={codeHref(a.path)}>{a.path.slice(project.root ? project.root.length + 1 : 0)}</a> </h3> <p>{docSummary(s.cb.store.getDef(a.hash)!) ?? "a web app"}</p> <code>tcm dev {a.path}</code> </div> ))} {(docsNs || project.readme) && ( <div className="ecard"> <div className="kind">Docs</div> <h3>{docsNs ? <a href={codeHref(docsNs)}>{rows.filter((r) => parentOf(r.path) === docsNs).length} pages</a> : "README"}</h3> <p>Pages kept in the codebase, their links following renames.</p> {[project.readme, project.contributing].filter((r) => r !== undefined).map((r, i) => ( <span key={r.path}> {i > 0 && " · "} <a href={codeHref(r.path)}>{leafOf(r.path)}</a> </span> ))} </div> )} </div> )} <div className="sechead"> <b>Map</b> <span className="muted">what's in it, by namespace</span> <span className="right legend"> <Place place="server" /> server <Place place="anywhere" /> anywhere <Place place="browser" /> browser </span> </div> <div className="map"> {namespaces.length ? ( namespaces.map((n) => ( <div key={n.name}> <a href={codeHref(n.name)}> <b>{leafOf(n.name)}</b> </a> <span className="muted">{namespaceSummary(s, rows, n.name) || `${n.rows.length} definitions`}</span> <PlaceBar mix={placeMix(s, n.rows, n.name)} /> </div> )) ) : ( <div className="muted">No namespaces yet.</div> )} </div> {loose.length > 0 && ( <div className="box"> <div className="boxhead"> <b>{project.root || "Top level"}</b> <span className="muted">{loose.length} definitions</span> </div> {loose.slice(0, 40).map((r) => ( <DefRow key={r.path} row={r} /> ))} </div> )} {readme?.docMarkdown && ( <div className="box"> <div className="boxhead"> <b>README</b> <a className="muted" href={codeHref(project.readme!.path)}> {project.readme!.path} </a> </div> <Html className="boxbody md" html={markdownHtml(s.cb, readme.docMarkdown)} /> </div> )} </div> </Frame> ); }
uses
- tcmts.cli.pages.docSummary
- tcmts.core.hash.shortHash
- tcmts.share.DefRow
- tcmts.share.Frame
- tcmts.share.GetIt
- tcmts.share.Html
- tcmts.share.Place
- tcmts.share.PlaceBar
- tcmts.share.at
- tcmts.share.childrenOf
- tcmts.share.codeHref
- tcmts.share.entriesIn
- tcmts.share.getItCommand
- tcmts.share.inSlices
- tcmts.share.leafOf
- tcmts.share.markdownHtml
- tcmts.share.namesNow
- tcmts.share.namespaceSummary
- tcmts.share.pageOf
- tcmts.share.parentOf
- tcmts.share.placeMix
- tcmts.share.projectNow
- tcmts.share.roleNow
- tcmts.share.shareNow