rustio-admin 0.30.0

Django Admin, but for Rust. A small, focused admin framework.
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{{ page_title|default("") }}{% if page_title %} · {% endif %}{{ site_title }}{% endblock %}</title>
{# Flicker-free theme: set data-theme before first paint. #}
<script>
  (function () {
    try {
      var t = localStorage.getItem("rio-theme");
      if (!t) t = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
      document.documentElement.setAttribute("data-theme", t);
    } catch (e) { document.documentElement.setAttribute("data-theme", "light"); }
  })();
</script>
<link rel="stylesheet" href="/static/admin.css">
{# _theme.html MUST come after admin.css — project token overrides
 # win cascade ties on source order without needing !important. #}
{% include "admin/_theme.html" %}
{% block extra_head %}{% endblock %}
</head>
<body class="rio-canvas {% if identity %}rio-console{% if is_demo_session %} rio-console--demo{% endif %}{% if read_only %} rio-console--read-only{% endif %}{% else %}rio-auth{% endif %}">
{% if identity %}
  {% block sidebar %}{% include "admin/_sidebar.html" %}{% endblock %}
  <div class="rio-ws">
    {% block topbar %}{% include "admin/_topbar.html" %}{% endblock %}
    <div class="rio-ws-body">
      <div class="rio-ws-inner">
        {% if is_demo_session %}<div class="rio-alert rio-alert--info" role="status">DEMO USER{% if demo_label %} ({{ demo_label }}){% endif %} — actions are visible to other operators.</div>{% endif %}
        {% if read_only %}<div class="rio-alert rio-alert--warn" role="status">READ-ONLY — project-data mutations are disabled. Auth flows still work.</div>{% endif %}
        {% if flash %}<div class="rio-alert rio-alert--{{ flash.kind }}" role="status">{{ flash.message }}</div>{% endif %}
        <main id="main">
{% else %}
  <header class="rio-auth-top">
    <span class="rio-brand-word">{{ app_name }}</span>
    <span class="rio-devpill rio-devpill--{{ environment_kind }}">{{ environment_label }}</span>
  </header>
  <main id="main" class="rio-auth-main">
    {% if flash %}<div class="rio-alert rio-alert--{{ flash.kind }}" role="status">{{ flash.message }}</div>{% endif %}
{% endif %}

        {% block content %}{% endblock %}

{% if identity %}
        </main>
      </div>{# /rio-ws-inner — content column ends here #}
      <footer class="rio-appfoot" role="contentinfo">
        <div class="rio-appfoot-inner">
          <span class="rio-brand-word">{{ app_name }}</span>
          <span class="rio-appfoot-links">
            <a href="/admin/history">Audit log</a>
            <a href="/admin/apis">API surface</a>
            <a href="/admin/health">Health</a>
            <a href="/admin/docs">Docs</a>
            <a href="/admin/account/sessions">Sessions</a>
          </span>
          <span class="rio-appfoot-meta">{{ identity.email }} · <time datetime="{{ server_now }}">{{ server_now }}</time></span>
        </div>
      </footer>
    </div>
  </div>
  {# Global ⌘K search palette (wired by initSearchPalette in admin.js) #}
  <div class="rio-search-palette" data-rio-search-palette aria-hidden="true">
    <div class="rio-search-palette__dialog" data-rio-search-palette-dialog role="dialog" aria-modal="true" aria-label="Search records">
      <div class="rio-search-palette__field">
        <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
        <input type="search" class="rio-search-palette__input" data-rio-search-palette-input placeholder="Search records…" autocomplete="off" spellcheck="false" aria-label="Search records" role="combobox" aria-expanded="true" aria-controls="rio-search-palette-results" aria-autocomplete="list">
        <span class="rio-kbd">Esc</span>
      </div>
      <ul class="rio-search-palette__results" id="rio-search-palette-results" data-rio-search-palette-results role="listbox" aria-label="Results"></ul>
    </div>
  </div>
{% else %}
  </main>
  <footer class="rio-auth-foot">
    <time datetime="{{ server_now }}">{{ server_now }}</time>
    {% if show_powered_by %}<span aria-hidden="true">·</span><a href="https://docs.rs/rustio-admin/{{ framework_version }}" target="_blank" rel="noopener noreferrer">Powered by RustIO v{{ framework_version }}</a>{% endif %}
  </footer>
{% endif %}
<script src="/static/admin.js" defer></script>
</body>
</html>