Pilots: separate admin tab, collapsible dashboard section

Admin: moved pilot management out of the RDP tab into its own
"Pilots" tab - dedicated list, create/edit form and slot table with
a per-slot user-assign dropdown (always on, no more is_pilot
checkbox toggling the RDP tab's slot table between two modes). The
RDP tab goes back to exactly its pre-pilots shape.

Dashboard: a granted pilot no longer sits inside the "Ваши сервисы"
grid - it gets its own <details> section above it, open by default
whenever the user has at least one pilot (and simply absent when
they have none, rather than showing empty and collapsed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 06:51:18 +00:00
parent 46e5b5a41e
commit ae630f9115
3 changed files with 282 additions and 44 deletions
+36 -2
View File
@@ -101,6 +101,17 @@
.dv-section-head h2{font:700 13.5px/1 "Ubuntu Mono",monospace;letter-spacing:.1em;text-transform:uppercase;margin:0}
.dv-section-head::after{content:"";flex:1;height:1px;background:var(--dv-line)}
.dv-section-count{font:600 12px/1 "Ubuntu Mono",monospace;color:var(--dv-fg-faint)}
.dv-pilots-section{padding:28px 0 6px}
.dv-pilots-summary{cursor:pointer;list-style:none;user-select:none}
.dv-pilots-summary::-webkit-details-marker{display:none}
.dv-pilots-summary::before{
content:"▸";display:inline-block;color:var(--dv-accent);font-size:11px;margin-right:2px;
transition:transform .15s;
}
.dv-pilots-section[open] .dv-pilots-summary::before{transform:rotate(90deg)}
.dv-pilots-toggle-hint{font:400 11px/1 "Ubuntu",sans-serif;color:var(--dv-fg-faint)}
.dv-pilots-section .dv-tile-grid{margin-top:16px}
.dv-empty{padding:18px 0;color:var(--dv-fg-faint);font:400 13px/1.5 "Ubuntu",sans-serif}
.dv-tile-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:14px}
@@ -246,11 +257,34 @@
<p class="dv-filter-note">Показана категория «<b>{{ current_cat.name if current_cat else selected_category_slug }}</b>»<a href="/">сбросить</a></p>
{% endif %}
<div class="dv-readouts">
<div class="dv-readout"><div class="dv-readout-val">{{ '%02d'|format(services|length) }}</div><div class="dv-readout-label">Доступно</div></div>
<div class="dv-readout"><div class="dv-readout-val">{{ '%02d'|format((services|length) + (pilot_services|length)) }}</div><div class="dv-readout-label">Доступно</div></div>
<div class="dv-readout"><div class="dv-readout-val">{{ '%02d'|format(categories|length) }}</div><div class="dv-readout-label">Категорий</div></div>
</div>
</div>
{% if pilot_services %}
<details class="dv-pilots-section" open>
<summary class="dv-section-head dv-pilots-summary">
<h2>Пилоты</h2><span class="dv-section-count">{{ '%02d'|format(pilot_services|length) }}</span>
<span class="dv-pilots-toggle-hint">свернуть/развернуть</span>
</summary>
<div class="dv-tile-grid">
{% for service in pilot_services %}
<div class="dv-tile">
<a class="dv-tile-hit go-link" href="/go/{{ service.slug }}" aria-label="Открыть {{ service.name }}"></a>
<div class="dv-tile-top">
<div class="dv-tile-plate"><img src="{{ service.icon_path or '/static/service-placeholder.svg' }}" alt="" /></div>
<div class="dv-tile-name">{{ service.name }} <span class="dv-pilot-badge">ПИЛОТ</span></div>
</div>
<div class="dv-tile-desc">{{ service_comment_html.get(service.id, '') }}</div>
<a class="dv-tile-enter go-link" href="/go/{{ service.slug }}">Войти →</a>
<span class="dv-tile-led"></span>
</div>
{% endfor %}
</div>
</details>
{% endif %}
<section class="dv-section">
<div class="dv-section-head"><h2>Ваши сервисы</h2><span class="dv-section-count">{{ '%02d'|format(services|length) }}</span></div>
{% if services %}
@@ -260,7 +294,7 @@
<a class="dv-tile-hit go-link" href="/go/{{ service.slug }}" aria-label="Открыть {{ service.name }}"></a>
<div class="dv-tile-top">
<div class="dv-tile-plate"><img src="{{ service.icon_path or '/static/service-placeholder.svg' }}" alt="" /></div>
<div class="dv-tile-name">{{ service.name }}{% if service.id in pilot_ids %} <span class="dv-pilot-badge">ПИЛОТ</span>{% endif %}</div>
<div class="dv-tile-name">{{ service.name }}</div>
</div>
<div class="dv-tile-desc">{{ service_comment_html.get(service.id, '') }}</div>
<a class="dv-tile-enter go-link" href="/go/{{ service.slug }}">Войти →</a>