{{define "note"}}{{$n := .N}}{{$p := .P}}{{$away := and $n.Change $p.ChangeID (ne $n.Change $p.ChangeID)}}
{{if $n.File}}{{base $n.File}}{{lines $n}}{{end}} {{if $n.Kind}}{{$n.Kind}}{{end}} {{$n.Agent.Short}}
{{md $n.Text $p}}
{{end}} {{define "notelist"}}{{range .Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}{{if not .Notes}}

no notes match these filters

{{end}}{{end}} {{/* htmx responses: the list plus an out-of-band count update */}} {{define "notelist-oob"}}{{len .Notes}}{{template "notelist" .}}{{end}} {{define "note-added"}}{{if .File}}{{len .File.Notes}}{{end}}{{range .Notes}}{{template "note" (dict "N" . "P" $)}}{{end}}{{end}} {{/* A child-note form appears below every full card in a focused thread. It deliberately uses a normal POST: one append and one redirect rebuild the entire DAG from the log, including shared mention paths. */}} {{define "replyform"}}{{$n := .N}}{{$p := .P}}
reply to #{{$n.ID}}
as {{$p.User}} at {{short $p.ChangeID}} → the log
{{end}} {{/* Recursive at arbitrary depth. A DAG join/cycle is a reference rather than a second card, which keeps ids unique and recursion finite. */}} {{define "threadnode"}}{{$x := .Node}}{{$p := .P}}
{{if eq $x.Via "reply"}}↳{{else}}↶{{end}}
{{if $x.Reference}}

{{$x.Via}} also reaches note #{{$x.Note.ID}}

{{else}} {{template "note" (dict "N" $x.Note "P" $p)}} {{if $p.Live}}{{template "replyform" (dict "N" $x.Note "P" $p)}}{{end}} {{if $x.Children}}
{{range $x.Children}}{{template "threadnode" (dict "Node" . "P" $p)}}{{end}}
{{end}} {{end}}
{{end}} {{/* the add-a-comment form; live pages only, since it writes to the log */}} {{define "noteform"}}
{{if .File}} on {{base .File.Path}} {{else}} {{end}}
as {{.User}} at {{short .ChangeID}} → the log
{{range .Facets.Kinds}} {{end}}