{% extends "base.html" %} {% block content %}

{{ heading }}

{% if subheading %}

{{ subheading }}

{% endif %}
{{ ff_icon("arrow-left", size=15) }} {{ _("Back to {name}", name=model_title|lower) }} {% if delete_url %} {# Red, because it is the one action on this page that cannot be undone. Ghost rather than solid: it is not what the page is for, and a slab of red beside "Save changes" competes with it. #} {{ ff_icon("trash", size=15) }} {{ _("Delete") }} {% endif %}
{% if form.non_field_errors %} {% elif form.error_count %} {% endif %}
{% if version_token %} {# Carries the row's state at load time, so a save that would silently overwrite someone else's edit can be detected instead. #} {% endif %}
{% for field in form.fields %} {# Long controls span both columns: a textarea squeezed into half a page is worse than a taller form. A map earns the width only when there is one -- without a tile URL the field is a short text box and a full-width row of nothing beside it. #} {% set wide = field.widget in ('textarea', 'json', 'relations') or (field.widget == 'point' and settings.ui.map_tile_url) %}
{% if field.widget == "readonly" %}
{{ field.value|ff_display }}
{% elif field.widget == "textarea" or field.widget == "json" %} {% elif field.widget == "point" %} {# The pair of coordinates stays the control that holds and submits the value; the map only writes into it. Typing "41.2995, 69.2401" still works, pasting from anywhere still works, and with script off or no tile URL configured this is exactly the text box it has always been. #} {% elif field.widget in ("file", "image") %} {# A native file input cannot be prefilled -- browsers refuse, for good reason -- so a stored value is shown as a link (or a thumbnail, for an image) beside the input rather than inside it. Choosing a new file replaces it on save; the "Clear" checkbox removes it without replacing it, and only appears when there is something to remove. This is also the whole control with script off. With it, the uploader reads this block for the stored value and the clear checkbox, adopts both, and replaces the pair with a drop target that previews what is there and what is about to replace it. #} {% if field.value %}
{% if field.widget == "image" %} {% endif %} {{ field.value.rsplit("/", 1)[-1] }}
{% endif %} {% elif field.widget == "color" %} {# A swatch and the hex beside it, kept in step. The native picker alone cannot be typed into and cannot be read aloud; the text box alone cannot be pointed at. Both, bound together, is the only version that serves everyone. #}
{% elif field.widget == "richtext" %} {# The editor is the project's to choose. FastFort renders the textarea and marks it; `UISettings.richtext_url` names a script that upgrades it -- CKEditor, TinyMCE, whatever the project already licences. Without one this is a textarea, which is a working control rather than a broken editor. #} {% elif field.widget == "nullboolean" %} {# Three states, because the column has three. A checkbox would turn "not answered yet" into "answered no" the first time anyone pressed Save. #} {% elif field.widget == "checkbox" %} {% elif field.widget == "password" %} {# Two boxes, both empty. The stored hash is never sent to the browser, so there is nothing to prefill and nothing to leak. #} {% elif field.widget == "select" or field.widget == "relation" %} {% elif field.widget == "relations" %} {{ _("Hold Ctrl (or Cmd) to select more than one.") }} {% else %} {% endif %} {% if field.help_text and field.widget != "checkbox" %} {{ field.help_text }} {% endif %} {% for message in field.errors %} {{ message }} {% endfor %}
{% endfor %}
{{ _("Cancel") }}
{% endblock %}