{# One labelled control, in the four shapes the configuration forms need, plus
one button that belongs to a box rather than to a form.
Macros rather than includes so a caller cannot forget to set the variable one
reads, and so the distinction that matters here is structural: ``field`` and
``choice`` take a value and put it back, ``secret`` and ``secret_lines`` have
no value parameter at all. A credential cannot be echoed into a page by
somebody passing the wrong argument, because there is no argument to pass.
{% from "partials/field.html" import field, secret, choice, generate %}
{{ field("name", "Display name", value=fields.name, hint="Defaults to the spec's title.") }}
{{ secret("token", "Token", error=errors.get("token")) }}
{{ choice("auth_type", "Authentication", auth_options, fields.auth_type) }}
**Every conditional attribute below starts with a space, and has to.** The
environment renders with ``trim_blocks`` and ``lstrip_blocks`` (web/shell.py),
which take the newline after a block tag and the indentation before one — so
two conditional attributes on consecutive lines are emitted with nothing
between them. ``checked`` beside ``data-reveal`` came out as one attribute
called ``checkeddata-reveal``, which a browser accepts and silently leaves the
box unticked; ``placeholder`` beside ``aria-invalid`` did the same to a
rejected number field. The space inside the block is what separates them, and
an extra one where the attribute is absent costs nothing (task 125).
#}
{% macro _messages(name, hint, error) -%}
{% if hint %}{{ hint }}{% endif %}
{% if error %}{{ error }}{% endif %}
{%- endmacro %}
{% macro field(name, label, value="", hint=none, error=none, type="text", required=false,
placeholder=none) -%}
{%- endmacro %}
{# A credential field. Never carries a value, in any circumstance: what the
operator typed last time is either already stored or was wrong. #}
{% macro secret(name, label, hint=none, error=none) -%}
{%- endmacro %}
{# The same promise, for a credential that is more than one line. #}
{% macro secret_lines(name, label, hint=none, error=none, rows=4) -%}
{%- endmacro %}
{# A checkbox, which is the one control whose value is its presence: unticked,
it is simply not in the submitted form. ``reveal`` works on it exactly as it
does on a select — see static/js/forms.js — which is how "Replace the
credential" opens the panel holding the credential. #}
{% macro switch(name, label, checked=false, hint=none, error=none, reveal=none) -%}
{%- endmacro %}
{# ``options`` is a list of (value, label) pairs. ``reveal`` names the group of
panels this control shows and hides; see static/js/forms.js. #}
{% macro choice(name, label, options, value="", hint=none, error=none, reveal=none) -%}
{%- endmacro %}
{# A button that fills the box named by ``field`` with a freshly generated
secret, for a value the operator has to invent rather than be given: the MCP
bearer token, so far (task 126).
Hidden here and unhidden by static/js/forms.js. Everything else in this file
works without a script and this cannot — a button that fills a box needs
something to fill it with — and a control that does nothing when clicked is
worse than one that was never offered. The hint beside the box says how to
make a token at a shell instead.
The value is generated in the browser, never on the server. It would
otherwise have to come back through the flash cookie, which is signed,
written to the browser's disk and sent again on the next request, or the
route would have to stop redirecting after a POST. Generated here it only
ever travels the direction it has to travel anyway. #}
{% macro generate(field, label="Generate one") -%}
{%- endmacro %}