Меню в шапке собрано в группы
Вместо длинного ряда ссылок теперь «Сообщения» (шаблоны, расписания, отправка) и «Пользователи» (список, админы, звания); на десктопе группы раскрываются при наведении и по клику, на телефоне — по нажатию. Служебный текст «админ» и версия из шапки убраны, версия осталась в подвале.
This commit is contained in:
parent
d85bc5b0f4
commit
73e83e2413
|
|
@ -171,7 +171,7 @@ make backup E=test # на домашнем сервере: ./scripts/clickho
|
|||
|
||||
## Версионирование
|
||||
|
||||
- Единый источник версии — `common/version.py` (`__version__`), текущая — `0.6.3`.
|
||||
- Единый источник версии — `common/version.py` (`__version__`), текущая — `0.6.4`.
|
||||
- Схема — SemVer-подобная (`MAJOR.MINOR.PATCH`); git-тег = `v` + версия (`v0.1`).
|
||||
- Docker-образы тегируются версией (Блок 2), события ClickHouse получают `bot_version` (Блок 3).
|
||||
- Выпуск: изменить `common/version.py` → коммит → аннотированный тег `vX.Y` → `git push --tags`.
|
||||
|
|
|
|||
|
|
@ -22,24 +22,58 @@
|
|||
</button>
|
||||
<nav
|
||||
id="nav-menu"
|
||||
class="hidden w-full flex-col gap-2 border-t border-slate-100 pt-2 text-sm sm:flex sm:w-auto sm:flex-row sm:items-center sm:gap-4 sm:border-0 sm:pt-0"
|
||||
class="hidden w-full flex-col gap-2 border-t border-slate-100 pt-2 text-sm sm:flex sm:w-auto sm:flex-row sm:items-center sm:gap-1 sm:border-0 sm:pt-0"
|
||||
>
|
||||
<a href="/" class="py-1 text-slate-600 hover:text-slate-900">Главная</a>
|
||||
<a href="/sequences" class="py-1 text-slate-600 hover:text-slate-900">Шаблоны</a>
|
||||
<a href="/schedules" class="py-1 text-slate-600 hover:text-slate-900">Расписания</a>
|
||||
<a href="/users" class="py-1 text-slate-600 hover:text-slate-900">Пользователи</a>
|
||||
<a href="/titles" class="py-1 text-slate-600 hover:text-slate-900">Звания</a>
|
||||
<a href="/admins" class="py-1 text-slate-600 hover:text-slate-900">Админы</a>
|
||||
<a href="/logs" class="py-1 text-slate-600 hover:text-slate-900">Логи</a>
|
||||
<a href="/send" class="py-1 text-slate-600 hover:text-slate-900">Отправить</a>
|
||||
<a href="/" class="rounded px-2 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Главная</a>
|
||||
|
||||
<div class="relative" data-group>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center justify-between gap-1 rounded px-2 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900 sm:w-auto"
|
||||
data-group-toggle
|
||||
aria-expanded="false"
|
||||
>
|
||||
Сообщения <span class="text-xs">▾</span>
|
||||
</button>
|
||||
<div
|
||||
class="mt-1 hidden flex-col gap-1 rounded-lg border border-slate-200 bg-white p-2 sm:absolute sm:left-0 sm:top-full sm:z-20 sm:mt-1 sm:min-w-48 sm:shadow-lg"
|
||||
data-group-dropdown
|
||||
>
|
||||
<a href="/sequences" class="rounded px-3 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Шаблоны</a>
|
||||
<a href="/schedules" class="rounded px-3 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Расписания</a>
|
||||
<a href="/send" class="rounded px-3 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Отправить</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative" data-group>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center justify-between gap-1 rounded px-2 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900 sm:w-auto"
|
||||
data-group-toggle
|
||||
aria-expanded="false"
|
||||
>
|
||||
Пользователи <span class="text-xs">▾</span>
|
||||
</button>
|
||||
<div
|
||||
class="mt-1 hidden flex-col gap-1 rounded-lg border border-slate-200 bg-white p-2 sm:absolute sm:left-0 sm:top-full sm:z-20 sm:mt-1 sm:min-w-48 sm:shadow-lg"
|
||||
data-group-dropdown
|
||||
>
|
||||
<a href="/users" class="rounded px-3 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Список</a>
|
||||
<a href="/admins" class="rounded px-3 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Админы</a>
|
||||
<a href="/titles" class="rounded px-3 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Звания</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/logs" class="rounded px-2 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">Логи</a>
|
||||
|
||||
{% if request.session.get('admin_id') %}
|
||||
<span class="py-1 text-slate-500">{{ request.session.get('admin_username') or 'админ' }}</span>
|
||||
<form method="post" action="/logout" class="py-1">
|
||||
<form method="post" action="/logout" class="py-1 sm:ml-1">
|
||||
<input type="hidden" name="csrf_token" value="{{ request.session.get('csrf', '') }}" />
|
||||
<button type="submit" class="text-slate-600 hover:text-slate-900">Выйти</button>
|
||||
<button type="submit" class="rounded px-2 py-1.5 text-slate-600 hover:bg-slate-100 hover:text-slate-900">
|
||||
Выйти
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<span class="py-1 text-slate-500">админка · v{{ version }}</span>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -63,6 +97,35 @@
|
|||
});
|
||||
}
|
||||
|
||||
var groups = document.querySelectorAll("[data-group]");
|
||||
groups.forEach(function (group) {
|
||||
var toggle = group.querySelector("[data-group-toggle]");
|
||||
var dropdown = group.querySelector("[data-group-dropdown]");
|
||||
if (!toggle || !dropdown) return;
|
||||
|
||||
function setOpen(open) {
|
||||
dropdown.classList.toggle("hidden", !open);
|
||||
toggle.setAttribute("aria-expanded", String(open));
|
||||
}
|
||||
|
||||
toggle.addEventListener("click", function (event) {
|
||||
event.stopPropagation();
|
||||
setOpen(dropdown.classList.contains("hidden"));
|
||||
});
|
||||
|
||||
if (window.matchMedia("(min-width: 640px)").matches) {
|
||||
group.addEventListener("mouseenter", function () { setOpen(true); });
|
||||
group.addEventListener("mouseleave", function () { setOpen(false); });
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("click", function () {
|
||||
groups.forEach(function (group) {
|
||||
var dropdown = group.querySelector("[data-group-dropdown]");
|
||||
if (dropdown) dropdown.classList.add("hidden");
|
||||
});
|
||||
});
|
||||
|
||||
var tags = {
|
||||
b: ["<b>", "</b>"],
|
||||
i: ["<i>", "</i>"],
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
__version__ = "0.6.3"
|
||||
__version__ = "0.6.4"
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ from common import __version__
|
|||
|
||||
def test_version_is_set():
|
||||
assert __version__
|
||||
assert __version__ == "0.6.3"
|
||||
assert __version__ == "0.6.4"
|
||||
|
|
|
|||
Loading…
Reference in New Issue