rustio-admin 0.31.0

Django Admin, but for Rust. A small, focused admin framework.
Documentation
{% extends "admin/_base.html" %}
{% block content %}
<div class="rio-form-shell">

<nav class="rio-crumbs">
  <a href="/admin">Home</a><span class="rio-crumb-sep">·</span>
  <a href="/admin/{{ admin_name }}">{{ display_name }}</a><span class="rio-crumb-sep">·</span>
  <span class="rio-crumb-current">{% if mode == "new" %}Add {{ singular_name }}{% else %}#{{ object_id }}{% endif %}</span>
</nav>

<div class="rio-masthead-top">
  <div>
    <h1>{% if mode == "new" %}Add {{ singular_name }}{% else %}Edit {{ singular_name }}{% endif %}</h1>
    <p class="rio-masthead-desc">{% if mode == "edit" %}Editing fields below — saves are atomic and audited.{% else %}Create a new {{ singular_name|lower }}. Required fields are marked.{% endif %}</p>
  </div>
</div>

{% if errors %}
<div class="rio-alert rio-alert--danger" role="alert">
  <strong>Please correct the errors below:</strong>
  <ul>{% for e in errors %}<li>{{ e }}</li>{% endfor %}</ul>
</div>
{% endif %}

<form method="post" action="{% if mode == 'new' %}/admin/{{ admin_name }}/new{% else %}/admin/{{ admin_name }}/{{ object_id }}/edit{% endif %}" class="rio-form"{% if has_file_field %} enctype="multipart/form-data"{% endif %}>
  <input type="hidden" name="_csrf" value="{{ csrf_token }}">
  {% for section in sections %}
  <fieldset class="rio-fieldset rio-board">
    {% if section.title %}<legend class="rio-fieldset-legend">{{ section.title }}</legend>{% endif %}
    <div class="rio-fieldset-grid">
      {% for field in section.fields %}{% include "admin/includes/_form_field.html" %}{% endfor %}
    </div>
  </fieldset>
  {% endfor %}

  <div class="rio-form-actions">
    {% if not read_only %}
    <button type="submit" name="_save" class="rio-btn rio-btn--primary">Save</button>
    <button type="submit" name="_continue" class="rio-btn rio-btn--secondary">Save and continue editing</button>
    <button type="submit" name="_addanother" class="rio-btn rio-btn--secondary">Save and add another</button>
    {% else %}
    <span style="color:var(--rio-text-mute);font-size:var(--rio-text-14)">Read-only mode — saves are disabled.</span>
    {% endif %}
    <span class="rio-action-bar-end">
      {% if mode == "edit" %}
      <a class="rio-action-link rio-action-link--muted" href="/admin/{{ admin_name }}/{{ object_id }}/history">{{ icon("clock") }} History</a>
      {% if not read_only %}<a class="rio-action-link rio-action-link--danger" href="/admin/{{ admin_name }}/{{ object_id }}/delete">{{ icon("trash") }} Delete</a>{% endif %}
      {% endif %}
      <a href="/admin/{{ admin_name }}" class="rio-action-link">Cancel</a>
    </span>
  </div>
</form>

{% for inline in inlines %}
<section class="rio-board rio-inline-section" aria-labelledby="inline-{{ inline.target_admin_name }}">
  <header class="rio-inline-section__header">
    <h2 id="inline-{{ inline.target_admin_name }}">{{ inline.label }}</h2>
    <span style="font-family:var(--rio-font-mono);font-size:var(--rio-text-12);color:var(--rio-text-faint)">
      {% if inline.has_more %}Showing {{ inline.rows|length }} of {{ inline.total }}{% else %}{{ inline.total }} {% if inline.total == 1 %}row{% else %}rows{% endif %}{% endif %}
    </span>
  </header>
  {% if inline.rows %}
  <table class="rio-dtable">
    <tbody>
      {% for r in inline.rows %}
      <tr>
        <td><a class="rio-prod-name" href="{{ r.edit_url }}">#{{ r.id }} — {{ r.label }}</a></td>
        <td class="col-act">
          {% if not read_only %}
          <span class="rio-row-actions">
            <a class="rio-iconbtn rio-iconbtn--sm" href="{{ r.edit_url }}" aria-label="Edit">{{ icon("pencil") }}</a>
            <a class="rio-iconbtn rio-iconbtn--sm" href="{{ r.delete_url }}" aria-label="Delete" style="color:var(--rio-danger)">{{ icon("trash") }}</a>
          </span>
          {% else %}<a class="rio-btn rio-btn--subtle rio-btn--sm" href="{{ r.edit_url }}">View</a>{% endif %}
        </td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
  {% else %}
  <div class="rio-empty">
    {{ icon("table") }}
    <div class="rio-empty-title">No related {{ inline.target_display_name|lower }} yet</div>
    {% if not read_only %}<div>Add the first one — it links back to this row automatically.</div><div style="margin-block-start:12px"><a class="rio-btn rio-btn--primary rio-btn--sm" href="{{ inline.add_url }}">{{ icon("plus") }} Add {{ inline.target_display_name|lower }}</a></div>{% endif %}
  </div>
  {% endif %}
  <div class="rio-board-foot">
    {% if not read_only %}<a class="rio-btn rio-btn--subtle rio-btn--sm" href="{{ inline.add_url }}">{{ icon("plus") }} Add new {{ inline.target_display_name|lower }}</a>{% endif %}
    {% if inline.has_more %}<a class="rio-btn rio-btn--subtle rio-btn--sm" href="{{ inline.list_url }}">View all {{ inline.total }} {{ icon("arrow-right") }}</a>{% endif %}
  </div>
</section>
{% endfor %}

</div>
{% endblock %}