95 lines
4.3 KiB
HTML
95 lines
4.3 KiB
HTML
<!doctype html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>{% block title %}Админка{% endblock %} — DispelEvilBot</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script src="https://unpkg.com/htmx.org@2.0.4" defer></script>
|
|
</head>
|
|
<body class="min-h-screen bg-slate-100 text-slate-900">
|
|
<header class="border-b border-slate-200 bg-white">
|
|
<div class="mx-auto flex max-w-5xl items-center justify-between px-4 py-4">
|
|
<a href="/" class="text-lg font-semibold">DispelEvilBot</a>
|
|
<nav class="flex items-center gap-4 text-sm">
|
|
<a href="/" class="text-slate-600 hover:text-slate-900">Главная</a>
|
|
<a href="/messages" class="text-slate-600 hover:text-slate-900">Сообщения</a>
|
|
<a href="/sequences" class="text-slate-600 hover:text-slate-900">Последовательности</a>
|
|
<a href="/schedules" class="text-slate-600 hover:text-slate-900">Расписания</a>
|
|
<a href="/users" class="text-slate-600 hover:text-slate-900">Пользователи</a>
|
|
<a href="/admins" class="text-slate-600 hover:text-slate-900">Админы</a>
|
|
<a href="/logs" class="text-slate-600 hover:text-slate-900">Логи</a>
|
|
{% if request.session.get('admin_id') %}
|
|
<span class="text-slate-500">{{ request.session.get('admin_username') or 'админ' }}</span>
|
|
<form method="post" action="/logout">
|
|
<input type="hidden" name="csrf_token" value="{{ request.session.get('csrf', '') }}" />
|
|
<button type="submit" class="text-slate-600 hover:text-slate-900">Выйти</button>
|
|
</form>
|
|
{% endif %}
|
|
<span class="text-slate-500">админка · v{{ version }}</span>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="mx-auto max-w-5xl px-4 py-8">
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
<footer class="mx-auto max-w-5xl px-4 pb-8 text-xs text-slate-400">DispelEvilBot v{{ version }}</footer>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
var tags = {
|
|
b: ["<b>", "</b>"],
|
|
i: ["<i>", "</i>"],
|
|
u: ["<u>", "</u>"],
|
|
s: ["<s>", "</s>"],
|
|
code: ["<code>", "</code>"],
|
|
pre: ["<pre>", "</pre>"],
|
|
quote: ["<blockquote>", "</blockquote>"],
|
|
spoiler: ["<tg-spoiler>", "</tg-spoiler>"],
|
|
a: ['<a href="">', "</a>"],
|
|
};
|
|
|
|
document.querySelectorAll("[data-editor]").forEach(function (root) {
|
|
var textarea = root.querySelector("textarea");
|
|
var counter = root.querySelector("[data-counter]");
|
|
var max = parseInt(root.dataset.max || "0", 10);
|
|
|
|
function updateCounter() {
|
|
if (counter) counter.textContent = textarea.value.length + (max ? " / " + max : "");
|
|
}
|
|
textarea.addEventListener("input", updateCounter);
|
|
updateCounter();
|
|
|
|
root.querySelectorAll("button[data-tag]").forEach(function (button) {
|
|
button.addEventListener("click", function () {
|
|
var pair = tags[button.dataset.tag];
|
|
if (!pair) return;
|
|
var start = textarea.selectionStart;
|
|
var end = textarea.selectionEnd;
|
|
var selected = textarea.value.slice(start, end);
|
|
var inserted = pair[0] + selected + pair[1];
|
|
textarea.value = textarea.value.slice(0, start) + inserted + textarea.value.slice(end);
|
|
textarea.focus();
|
|
textarea.selectionStart = start + pair[0].length;
|
|
textarea.selectionEnd = start + pair[0].length + selected.length;
|
|
updateCounter();
|
|
});
|
|
});
|
|
|
|
textarea.addEventListener("keydown", function (event) {
|
|
if (!(event.ctrlKey || event.metaKey)) return;
|
|
var key = event.key.toLowerCase();
|
|
var tag = key === "b" ? "b" : key === "i" ? "i" : key === "u" ? "u" : null;
|
|
if (!tag) return;
|
|
event.preventDefault();
|
|
var button = root.querySelector('button[data-tag="' + tag + '"]');
|
|
if (button) button.click();
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|