115 lines
5.4 KiB
HTML
115 lines
5.4 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Управление пользователями — Morozovka Portal{% endblock %}
|
|
{% block main_class %}container{% endblock %}
|
|
|
|
{% block head %}
|
|
<style>
|
|
.search-row { display: flex; gap: 10px; align-items: center; margin: 20px 0; flex-wrap: wrap; }
|
|
.search-row input { padding: 8px 12px; background: #0d1117; color: white; border: 1px solid #30363d; border-radius: 5px; min-width: 240px; font-family: inherit; }
|
|
.search-row input:focus { outline: none; border-color: #58a6ff; }
|
|
.search-row a { color: #8b949e; font-size: 0.9rem; text-decoration: none; }
|
|
.search-row a:hover { color: #f85149; }
|
|
.search-row button.secondary { padding: 8px 16px; background: #21262d; color: #e6edf3; border: 1px solid #30363d; border-radius: 5px; cursor: pointer; font-weight: 600; }
|
|
.search-row button.secondary:hover { background: #30363d; }
|
|
|
|
table { width: 100%; border-collapse: collapse; margin-top: 20px; background: #161b22; border-radius: 8px; overflow: hidden; }
|
|
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #30363d; }
|
|
th { background: #21262d; color: #8b949e; font-size: 0.85rem; text-transform: uppercase; }
|
|
tr:hover { background: #21262d; }
|
|
|
|
.badge { padding: 4px 8px; border-radius: 4px; font-size: 0.8rem; font-weight: bold; }
|
|
.role-admin { background: #da3633; color: white; }
|
|
.role-professor { background: #f0883e; color: white; }
|
|
.role-lead { background: #d29922; color: white; }
|
|
.role-member { background: #238636; color: white; }
|
|
.role-student { background: #1f6feb; color: white; }
|
|
.role-guest { background: #30363d; color: white; }
|
|
|
|
.status-pill { padding: 2px 8px; border-radius: 10px; font-size: 0.75rem; }
|
|
.status-active { background: rgba(63,185,80,0.2); color: #3fb950; }
|
|
.status-inactive { background: rgba(248,81,73,0.2); color: #f85149; }
|
|
|
|
select { padding: 6px; border-radius: 4px; background: #0d1117; color: white; border: 1px solid #30363d; font-family: inherit; }
|
|
button { padding: 6px 12px; background: #238636; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; }
|
|
button:hover { background: #2ea043; }
|
|
button.danger { background: #da3633; }
|
|
button.danger:hover { background: #f85149; }
|
|
button.secondary { background: #21262d; border: 1px solid #30363d; }
|
|
button.secondary:hover { background: #30363d; }
|
|
a { color: #58a6ff; text-decoration: none; }
|
|
a:hover { text-decoration: underline; }
|
|
|
|
.actions-cell { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
|
.inactive { opacity: 0.55; }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1 class="page-title">Управление пользователями</h1>
|
|
|
|
<form class="search-row" method="GET">
|
|
<input type="text" name="q" placeholder="Поиск по логину / ФИО / email" value="{{ q or '' }}">
|
|
<button type="submit" class="secondary">Найти</button>
|
|
{% if q %}<a href="/admin/users">✕ Сбросить</a>{% endif %}
|
|
</form>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Логин</th>
|
|
<th>ФИО</th>
|
|
<th>Email</th>
|
|
<th>Роль</th>
|
|
<th>Статус</th>
|
|
<th>Действия</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for u in users %}
|
|
<tr class="{% if not u.is_active %}inactive{% endif %}">
|
|
<td>{{ u.id }}</td>
|
|
<td><strong>{{ u.username }}</strong></td>
|
|
<td>{{ u.full_name or '—' }}</td>
|
|
<td>{{ u.email or '—' }}</td>
|
|
<td>
|
|
<span class="badge role-{{ u.role }}">{{ u.role }}</span>
|
|
</td>
|
|
<td>
|
|
{% if u.is_active %}<span class="status-pill status-active">активен</span>
|
|
{% else %}<span class="status-pill status-inactive">заблокирован</span>{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="actions-cell">
|
|
<form action="/admin/users/{{ u.id }}/role" method="POST" style="display:flex; gap:5px;">
|
|
<select name="role">
|
|
{% for r in ['admin','professor','lead','member','student','guest'] %}
|
|
<option value="{{ r }}" {% if u.role == r %}selected{% endif %}>{{ r }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<button type="submit">Сменить</button>
|
|
</form>
|
|
|
|
{% if u.id != session.get('user_id') %}
|
|
<form action="/admin/users/{{ u.id }}/toggle_active" method="POST" style="display:inline;">
|
|
<button type="submit" class="secondary">
|
|
{% if u.is_active %}Заблокировать{% else %}Разблокировать{% endif %}
|
|
</button>
|
|
</form>
|
|
<form action="/admin/users/{{ u.id }}/delete" method="POST" style="display:inline;"
|
|
onsubmit="return confirm('Удалить {{ u.username }} НАВСЕГДА? Блокировка безопаснее.');">
|
|
<button type="submit" class="danger">Удалить</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="7" style="text-align: center; color: #8b949e; padding: 24px;">Пользователи не найдены</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endblock %}
|