{{/* The component kit: one {{define}} per partial of docs/plans/panel-redesign.md § Three layers. This is the only file besides layout.html in which an sp- component class is written; a page calls a partial and passes the struct that components.go declares for it (a page never builds the input with dict), and it never rebuilds the markup. The reference for every partial in every state is the mockup components page, docs/assets/panel-redesign/panel/src/components.html — the markup here is that markup, element for element and class for class, and the kit page (GET /server/components, kit.html) renders it all from fixtures. Go templates have no slots, so a component that wraps the page's own content is an open/close pair: box_open … box_close, body_open … body_close, record_open … record_close. Between the two the page writes Bulma markup (a table in its table-container, a form) or calls another partial. */}} {{/* ---- inline content: the text a struct field carries */}} {{/* inline renders a Text (components.go): plain text, links, code, mono values, strong, emphasis, tags and line breaks, all escaped. It is how a lead, a box's end slot or a fact's value can hold a link or a code span without any field being trusted HTML. */}} {{define "inline"}}{{range .}}{{if .Break}}
{{else if .Tag}}{{template "tag" .Tag}}{{else if .Href}}{{template "inline_leaf" .}}{{else}}{{template "inline_leaf" .}}{{end}}{{end}}{{end}} {{define "inline_leaf"}}{{if .Code}}{{.Text}}{{else if .Mono}}{{.Text}}{{else if .Strong}}{{.Text}}{{else if .Em}}{{.Text}}{{else}}{{.Text}}{{end}}{{end}} {{/* tag is a status tag (input: Tag). The colour comes from status_tag, the one mapping of status to Bulma classes; the label defaults to the status. */}} {{define "tag"}}{{if .Label}}{{.Label}}{{else}}{{.Status}}{{end}}{{end}} {{/* kicker is the upper-case mono micro-label on its own (input: string). page_head writes its own kicker as the line above the title. */}} {{define "kicker"}}{{.}}{{end}} {{/* action is a button in a page head or a box foot (input: Action): a link, or a POST form with one submit button when Post is set — a state change is never a link. */}} {{define "action"}}{{if .Post}}
{{else}}{{if .Icon}}{{end}}{{.Label}}{{end}}{{end}} {{/* row_action: a POST in the last cell of a table row (td.sp-actions), a form with one button that is drawn like the links beside it. It sits against the previous link with no whitespace between, as the cell's spacing is margins. */}} {{define "row_action"}}
{{end}} {{/* ---- page head and postmark */}} {{/* page_head opens every page (input: Head): the path or section as the kicker, the h1, a lead or a route line, the postmark when the page has a verdict, a note on the right, and the buttons. */}} {{define "page_head"}}
{{if .Postmark}}{{template "postmark" .Postmark}} {{end}}
{{if .Crumbs}}

{{range $i, $c := .Crumbs}}{{if $i}} {{end}}{{if $c.Href}}{{$c.Label}}{{else}}{{$c.Label}}{{end}} /{{end}}

{{else if .Kicker}}

{{.Kicker}}

{{end}}

{{.Title}}{{if .Code}} {{.Code}}{{end}}

{{if .Route}}{{template "route" .Route}} {{else if .Lead}}

{{template "inline" .Lead}}

{{end}}
{{if .Note}}
{{range $i, $l := .Note}}{{if $i}}
{{end}}{{$l}}{{end}}
{{end}}{{if .Actions}}
{{range .Actions}}{{template "action" .}}{{end}}
{{end}}
{{end}} {{/* postmark is the round verdict stamp (input: Postmark). Inside page_head only, at most one per page. */}} {{define "postmark"}}
{{.Top}}{{.Word}}{{.Bottom}}
{{end}} {{/* route is the from → to line of a message (input: Route). */}} {{define "route"}}

{{range .}}{{if .Arrow}}{{else if .Tag}}{{template "tag" .Tag}}{{else}}{{.Text}}{{end}}{{end}}

{{end}} {{/* flash is the result of the last action, between page_head and the first box (input: Flash). A field's own error stays in help is-danger. */}} {{define "flash"}}
{{template "inline" .Text}}
{{end}} {{/* ---- box */}} {{/* box_open starts a box and writes its head (input: Box); box_close ends it. The variants are sp-danger-zone (a destructive confirmation) and sp-credential (a secret shown once). A box foot, a table in its table-container, a run of records, a log or an empty state sit directly inside; anything else goes in body_open … body_close. */}} {{define "box_open"}}
{{template "box_head" .}} {{end}} {{define "box_close"}}
{{end}} {{/* body_open pads the content of a box (box_body); body_close ends it. */}} {{define "body_open"}}
{{end}} {{define "body_close"}}
{{end}} {{/* box_head is the numbered mono head of a box (input: Box): the number — or an icon when the box is not part of a sequence — the title, an end slot (a note, a tag, a link, or a filter form) and an optional link to the section's Help topic. */}} {{define "box_head"}}
{{if .Icon}}{{else}}{{.No}}{{end}}

{{.Title}}

{{if .Filter}}{{template "filter_form" .Filter}}{{else if .End}}
{{template "inline" .End}}
{{end}}{{if .Help}}{{end}}
{{end}} {{/* filter_form is the filter of a list in the end slot of its box head (input: Filter): selects, date inputs and one button, sent with GET. */}} {{define "filter_form"}}
{{range .Selects}}
{{end}}{{range .Dates}} {{end}}
{{end}} {{/* box_foot is the line under a box's content (input: Foot): a legend, paging with an end slot, or the one button that finishes the page. */}} {{define "box_foot"}}
{{if .Button}}{{template "action" .Button}}{{else}}{{if .Bare}}{{template "inline" .Text}}{{else}}{{template "inline" .Text}}{{end}}{{if .Link}}{{.Link.Label}}{{end}}{{if .End}}{{template "inline" .End}}{{end}}{{end}}
{{end}} {{/* ---- health, records, copy */}} {{/* health_cards is the Overview grid (input: []HealthCard); each card is health_card (input: HealthCard) and links to its detail. */}} {{define "health_cards"}}
{{range .}} {{template "health_card" .}}{{end}}
{{end}} {{define "health_card"}}{{.Name}}{{.Value}}{{.Sub}}{{end}} {{/* dns_record is one DNS record (input: Record): its status, what to publish with a Copy button, and "In DNS now" only when it differs. */}} {{define "dns_record"}}

{{.Name}}

{{if .Status.Status}}{{template "tag" .Status}}{{end}}{{if .Note}}{{template "inline" .Note}}{{end}}
{{if .Host}}
{{template "copy_field" .HostField}}
{{end}}{{if .Value}}{{template "copy_field" .ValueField}} {{end}}{{if .InDNS}}
{{if .Problem}}

{{template "inline" .Problem}}

{{end}}
{{end}}
{{end}} {{/* record_open starts the padded block a record sits in and record_close ends it, for what is not a DNS record but is laid out like one: the fields of a secret shown once, a form inside a box. */}} {{define "record_open"}}
{{end}} {{define "record_close"}}
{{end}} {{/* copy_field is a read-only value joined to its Copy button (input: CopyField): one line, or a textarea when Rows is set — a DKIM key. The button is wired by panel.js through data-copy. */}} {{define "copy_field"}}
{{if .Rows}}{{else}}{{end}}
{{if .Help}}

{{template "inline" .Help}}

{{end}}
{{end}} {{/* ---- facts, menu, timeline, log, states */}} {{/* facts is a label / value grid (input: []Fact); Big is for a headline number, with its supporting line under it. */}} {{define "facts"}}
{{range .}}
{{.Label}}
{{template "inline" .Value}}{{if .Note}}
{{template "inline" .Note}}
{{end}}
{{end}}
{{end}} {{/* side_menu is the Bulma menu of a detail page (input: SideMenu): icons, count tags, and the rarely used entries in a group of their own. It stays in view while the page scrolls. */}} {{define "side_menu"}}{{end}} {{/* timeline is what happened to a message, in order (input: []Step). */}} {{define "timeline"}}
    {{range .}} {{if .Strong}}{{.Strong}}{{end}}{{template "inline" .Text}}{{end}}
{{end}} {{/* log_pane is a dark block of log lines (input: []LogLine). The time is dimmed, a warning amber, an error red. The newline between lines is part of the text: the pane is a pre. */}} {{define "log_pane"}}
{{range $i, $l := .}}{{if $i}}
{{end}}{{if $l.Time}}{{$l.Time}} {{end}}{{if eq $l.Level "warn"}}{{$l.Text}}{{else if eq $l.Level "error"}}{{$l.Text}}{{else}}{{$l.Text}}{{end}}{{end}}
{{end}} {{/* empty_state says what is absent and why that is fine (input: EmptyState). */}} {{define "empty_state"}}
{{template "inline" .Text}}
{{end}} {{/* confirm_list lists what a destructive action will take with it (input: []Text), inside an sp-danger-zone box above the danger button. */}} {{define "confirm_list"}}{{end}} {{/* help_topic is one topic of the Help page (input: HelpTopic): a heading and paragraphs; topics stack inside one box. */}} {{define "help_topic"}}

{{.Title}}

{{range .Body}}

{{template "inline" .}}

{{end}}
{{end}}