mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
candidates UI: full width, action and bulk buttons
- base.html: container -> container-fluid (nav and content full width) - Right pane: large buttons Publish / Process with local model / Rewrite / Reject (for new candidates) - Left pane bottom: bulk operations panel with 4 visible buttons (Publish / Process / Reject / Stale) instead of hidden select - bulk: action 'process' reclassifies selected with local model (impl_reclassify extracted); ids optional (empty selection -> no_selection redirect instead of 422); redirect preserves filters - Tests: full width, buttons present, bulk empty/process, published/metrics — green
This commit is contained in:
@@ -6,14 +6,14 @@
|
||||
<title>VESTI — {% block title %}Управление{% endblock %}</title>
|
||||
<link href="/static/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body { padding-top: 2rem; background: #f5f6fa; }
|
||||
body { padding-top: 1.5rem; background: #f5f6fa; }
|
||||
.card { box-shadow: 0 1px 4px rgba(0,0,0,.08); }
|
||||
.post-text { white-space: pre-wrap; max-height: 140px; overflow-y: auto; font-size: .9rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
|
||||
<div class="container">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/candidates">📰 VESTI</a>
|
||||
<div class="navbar-nav">
|
||||
<a class="nav-link" href="/candidates">Кандидаты</a>
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container mt-4">
|
||||
<div class="container-fluid mt-2 px-3">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -48,15 +48,16 @@
|
||||
{% set selected_qs = '&selected=' ~ selected.id if selected else '' %}
|
||||
|
||||
<div class="row g-0">
|
||||
<div class="col-md-5">
|
||||
<div class="border rounded p-2 d-flex flex-column" style="max-height: 78vh; background:#fff;">
|
||||
<div class="d-flex align-items-center mb-1">
|
||||
<span class="me-2 text-muted small">Группировка:</span>
|
||||
{% for val, label in [('source', 'по источнику'), ('date', 'по дате'), ('status', 'по статусу')] %}
|
||||
<!-- ЛЕВАЯ ПАНЕЛЬ: список + группировка + массовые операции -->
|
||||
<div class="col-md-4">
|
||||
<div class="border rounded p-2 d-flex flex-column" style="max-height: 82vh; background:#fff;">
|
||||
<div class="d-flex flex-wrap align-items-center mb-1 gap-1">
|
||||
<span class="me-1 text-muted small">Группировка:</span>
|
||||
{% for val, label in [('source', 'источник'), ('date', 'дата'), ('status', 'статус')] %}
|
||||
{% if group_by == val %}
|
||||
<span class="badge bg-primary text-white me-1">{{ label }}</span>
|
||||
<span class="badge bg-primary text-white">{{ label }}</span>
|
||||
{% else %}
|
||||
<a class="badge bg-light text-dark border me-1 text-decoration-none"
|
||||
<a class="badge bg-light text-dark border text-decoration-none"
|
||||
href="/candidates?group_by={{ val }}{% if filters_qs %}&{{ filters_qs }}{% endif %}{{ selected_qs }}">{{ label }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -102,21 +103,23 @@
|
||||
<input type="hidden" name="own" value="{{ own }}">
|
||||
<input type="hidden" name="q" value="{{ q }}">
|
||||
<input type="hidden" name="group_by" value="{{ group_by }}">
|
||||
<div class="d-flex align-items-center gap-2 mt-2">
|
||||
<select name="action" class="form-select form-select-sm" style="width:auto;">
|
||||
<option value=""></option>
|
||||
<option value="reject">🚫 Отклонить</option>
|
||||
<option value="reject-old">🗑 Отклонить старьё</option>
|
||||
<option value="approve">✅ Опубликовать</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Выполнить</button>
|
||||
<div class="border-top pt-2 mt-1">
|
||||
<div class="small text-muted mb-1">⚡ Массовые операции <span class="badge bg-secondary" id="sel-count">0</span></div>
|
||||
<div class="btn-group btn-group-sm w-100 d-flex flex-wrap gap-1">
|
||||
<button class="btn btn-sm btn-success flex-fill" name="action" value="approve">✅ Опубликовать</button>
|
||||
<button class="btn btn-sm btn-info flex-fill text-dark" name="action" value="process">🤖 Обработать моделью</button>
|
||||
<button class="btn btn-sm btn-outline-danger flex-fill" name="action" value="reject">🚫 Отклонить</button>
|
||||
<button class="btn btn-sm btn-outline-secondary flex-fill" name="action" value="reject-old">🗑 Старьё</button>
|
||||
</div>
|
||||
<div class="form-text mt-1">Отметьте галочками слева и нажмите действие. «Обработать» — переклассификация локальной моделью (qwen).</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-7">
|
||||
<div class="border rounded p-3 bg-white" style="max-height: 78vh; overflow-y:auto;">
|
||||
<!-- ПРАВАЯ ПАНЕЛЬ: детали выбранного -->
|
||||
<div class="col-md-8">
|
||||
<div class="border rounded p-3 bg-white" style="max-height: 82vh; overflow-y:auto;">
|
||||
{% if selected %}
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<h5 class="mb-0">#{{ selected.id }} {{ selected.source_name or '?' }}</h5>
|
||||
@@ -132,23 +135,25 @@
|
||||
{% if selected.url %}<a class="btn btn-sm btn-outline-secondary ms-2" href="{{ selected.url }}" target="_blank">Исходник</a>{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3 d-flex gap-2">
|
||||
<div class="mb-3 d-flex flex-wrap gap-2">
|
||||
{% if selected.status != 'published' %}
|
||||
<form method="post" action="/posts/{{ selected.id }}/approve">
|
||||
<button class="btn btn-sm btn-success" type="submit">✅ Опубликовать</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if selected.status != 'rejected' %}
|
||||
<form method="post" action="/posts/{{ selected.id }}/reject">
|
||||
<button class="btn btn-sm btn-outline-danger" type="submit">🚫 Отклонить</button>
|
||||
<button class="btn btn-success" type="submit">✅ Опубликовать</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if selected.status != 'published' %}
|
||||
<form method="post" action="/posts/{{ selected.id }}/reclassify">
|
||||
<button class="btn btn-sm btn-outline-info" type="submit">🔄 Переклассифицировать</button>
|
||||
<button class="btn btn-info" type="submit">🤖 Обработать моделью</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if selected.status != 'published' %}
|
||||
<form method="post" action="/posts/{{ selected.id }}/rewrite">
|
||||
<button class="btn btn-sm btn-outline-primary" type="submit">✍️ Переписать</button>
|
||||
<button class="btn btn-outline-primary" type="submit">✍️ Переписать</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if selected.status != 'rejected' and selected.status != 'published' %}
|
||||
<form method="post" action="/posts/{{ selected.id }}/reject">
|
||||
<button class="btn btn-outline-danger" type="submit">🚫 Отклонить</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user