cmd/projax/main.go boots a pgxpool against PROJAX_DB_URL (falls back to
SUPABASE_DATABASE_URL), auto-applies embedded migrations on start
(disable with PROJAX_AUTO_MIGRATE=off), and serves on PROJAX_LISTEN_ADDR
(default :8080).
store package wraps the unified view + projax.items writes. Item has
helper methods for templates: IsArea, Editable, SourceRefDeref. The
Promote() flow runs the insert + item_links link inside a single
transaction so the source row drops out of items_unified atomically.
web package: per-page html/template instances parsed against a shared
layout.tmpl, embedded static/style.css, HTMX from CDN. Pages:
GET / tree of items_unified
GET /i/{path} detail (editable for projax, read-only +
promote form for mai.projects)
POST /i/{path} update projax-native item
POST /i/{path}/promote one-page promote (HTMX-aware fragment for
inline classify)
GET /new?parent={path} create form
POST /new create projax-native item
GET /admin/classify orphan list with inline HTMX promote
GET /healthz DB ping
GET /static/* embedded assets
Auth is intentionally out of scope for v1 — service binds to whatever
PROJAX_LISTEN_ADDR points at, deploy guidance pins it to the Tailscale
interface (covered in 1d README).
Tests (skip when DB env is unset):
TestTreeRenders, TestHealthz,
TestDetailProjaxNativeEditable, TestDetailMaiProjectsReadOnly,
TestClassifyListsOrphans, TestPromoteRoundTrip.
53 lines
1.4 KiB
Cheetah
53 lines
1.4 KiB
Cheetah
{{define "content"}}
|
|
<h1>Tree</h1>
|
|
<p class="counts">
|
|
<strong>{{.ProjaxCount}}</strong> projax · <strong>{{.MaiCount}}</strong> mai.projects orphans
|
|
{{if .MaiCount}}<a href="/admin/classify">→ classify</a>{{end}}
|
|
</p>
|
|
|
|
<section class="tree">
|
|
<h2>Areas + projax items</h2>
|
|
<ul class="forest">
|
|
{{range .Areas}}
|
|
<li class="node area">
|
|
<a href="/i/{{.Item.Path}}">{{.Item.Title}}</a>
|
|
<span class="slug">{{.Item.Path}}</span>
|
|
<a class="add" href="/new?parent={{.Item.Path}}">+</a>
|
|
{{template "children" .}}
|
|
</li>
|
|
{{end}}
|
|
</ul>
|
|
</section>
|
|
|
|
{{if .Orphans}}
|
|
<section class="orphans">
|
|
<h2>mai.projects orphans <small>(unclassified)</small></h2>
|
|
<ul class="flat">
|
|
{{range .Orphans}}
|
|
<li class="node orphan">
|
|
<a href="/i/{{.Path}}">{{.Title}}</a>
|
|
<span class="slug">{{.Path}}</span>
|
|
<span class="status status-{{.Status}}">{{.Status}}</span>
|
|
</li>
|
|
{{end}}
|
|
</ul>
|
|
</section>
|
|
{{end}}
|
|
{{end}}
|
|
|
|
{{define "children"}}
|
|
{{if .Children}}
|
|
<ul>
|
|
{{range .Children}}
|
|
<li class="node project">
|
|
<a href="/i/{{.Item.Path}}">{{.Item.Title}}</a>
|
|
<span class="slug">{{.Item.Path}}</span>
|
|
<span class="status status-{{.Item.Status}}">{{.Item.Status}}</span>
|
|
<a class="add" href="/new?parent={{.Item.Path}}">+</a>
|
|
{{template "children" .}}
|
|
</li>
|
|
{{end}}
|
|
</ul>
|
|
{{end}}
|
|
{{end}}
|