Первая версия, написанная гопотой. Не работает нормально лента и поиск, сломана авторизация

This commit is contained in:
2025-10-23 11:03:01 +03:00
parent d6ba7c0f50
commit ee255f651c
12 changed files with 632 additions and 0 deletions

43
app/templates/add.html Normal file
View File

@@ -0,0 +1,43 @@
{% extends "base.html" %}
{% block title %}Добавить пост{% endblock %}
{% block content %}
<h2>Добавить пост</h2>
<form method="post" id="addform">
<div><input name="title" placeholder="Заголовок (необязательно)" style="width:100%"></div>
<div><textarea name="body" rows="10" style="width:100%" placeholder="Текст"></textarea></div>
<div>
<input id="tagsinput" name="tags" placeholder="Теги через запятую" style="width:100%" />
<div id="suggestions" class="suggestions"></div>
</div>
<div><button type="submit">Опубликовать</button></div>
</form>
<script>
(async function(){
const input = document.getElementById("tagsinput");
const sugg = document.getElementById("suggestions");
let last = "";
input.addEventListener("input", async (e) => {
const val = input.value.split(",").pop().trim();
if (!val || val === last) { sugg.innerHTML=""; return; }
last = val;
try {
const res = await fetch('/_tags?q=' + encodeURIComponent(val));
const arr = await res.json();
sugg.innerHTML = arr.slice(0,10).map(t => `<button class="tag-sugg" type="button" data-tag="${t}">#${t}</button>`).join(" ");
document.querySelectorAll(".tag-sugg").forEach(b => {
b.addEventListener("click",(ev)=>{
const tag = ev.currentTarget.dataset.tag;
const parts = input.value.split(",");
parts[parts.length-1] = " " + tag;
input.value = parts.map(p=>p.trim()).filter(Boolean).join(", ") + ", ";
input.focus();
sugg.innerHTML = "";
});
});
} catch(e) { console.warn(e); }
});
})();
</script>
{% endblock %}

60
app/templates/base.html Normal file
View File

@@ -0,0 +1,60 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}Text-Booru{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<header class="header">
<div class="container">
<h1 class="logo"><a href="{{ url_for('index') }}">text.booru</a></h1>
<nav class="nav">
<a href="{{ url_for('index') }}">Лента</a>
<a href="{{ url_for('add_route') }}">Добавить</a>
<a href="{{ url_for('mod_index') }}">Модерация</a>
<a href="{{ url_for('api_export_zip') }}">Экспорт</a>
</nav>
<form class="search" action="{{ url_for('search') }}" method="get">
<input name="q" placeholder="Поиск..." value="{{ request.args.get('q','') }}">
<button>🔎</button>
</form>
</div>
</header>
<main class="container">
<div class="content">
{% block content %}{% endblock %}
</div>
<aside class="sidebar">
<section>
<h3>Теги</h3>
<ul class="taglist">
{% for t in all_tags %}
<li><a href="{{ url_for('tag_page', name=t.name) }}">#{{ t.name }}</a> <span class="count">({{ t.cnt }})</span></li>
{% endfor %}
</ul>
</section>
<section>
<h3>Страницы</h3>
<ul>
{% if page and pages %}
<li>Страница {{ page }} / {{ pages }}</li>
{% for p in range(1, pages+1) %}
<li><a href="{{ url_for('index') }}?page={{ p }}">{{ p }}</a></li>
{% endfor %}
{% endif %}
</ul>
</section>
</aside>
</main>
<footer class="footer">
<div class="container">
<small>Прототип — хранение коротких текстов, tags, search, moderation</small>
</div>
</footer>
</body>
</html>

32
app/templates/index.html Normal file
View File

@@ -0,0 +1,32 @@
{% extends "base.html" %}
{% block title %}Лента — Text-Booru{% endblock %}
{% block content %}
{% if current_tag %}
<h2>Тег: #{{ current_tag }}</h2>
{% else %}
<h2>Последние посты</h2>
{% endif %}
{% for p in posts %}
<article class="card">
<h3><a href="{{ url_for('view_post', pid=p.id) }}">{{ p.title or ("#" ~ p.id) }}</a></h3>
<div class="excerpt">{{ markdown(p.body[:400])|safe }}</div>
<div class="meta">#{{ p.id }} • {{ p.created_at }} •
{% for t in get_tags(p.id) %}<a href="{{ url_for('tag_page', name=t) }}">#{{ t }}</a> {% endfor %}
</div>
</article>
{% endfor %}
<div class="pagination">
{% if page and pages %}
{% if page > 1 %}
<a href="{{ url_for('index') }}?page={{ page-1 }}">« Prev</a>
{% endif %}
<span>Page {{ page }} / {{ pages }}</span>
{% if page < pages %}
<a href="{{ url_for('index') }}?page={{ page+1 }}">Next »</a>
{% endif %}
{% endif %}
</div>
{% endblock %}

31
app/templates/mod.html Normal file
View File

@@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block title %}Модерация{% endblock %}
{% block content %}
<h2>Модерация — флаги</h2>
{% if flags %}
<table class="flags">
<thead><tr><th>ID</th><th>Post</th><th>Reason</th><th>Created</th><th>Resolved</th><th>Action</th></tr></thead>
<tbody>
{% for f in flags %}
<tr>
<td>{{ f.id }}</td>
<td><a href="{{ url_for('view_post', pid=f.post_id) }}">{{ f.title or ('#'+f.post_id|string) }}</a></td>
<td>{{ f.reason }}</td>
<td>{{ f.created_at }}</td>
<td>{{ 'yes' if f.resolved else 'no' }}</td>
<td>
{% if not f.resolved %}
<form action="{{ url_for('mod_resolve', fid=f.id) }}" method="post">
<button type="submit">Resolve</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>Нет флагов.</p>
{% endif %}
{% endblock %}

29
app/templates/post.html Normal file
View File

@@ -0,0 +1,29 @@
{% extends "base.html" %}
{% block title %}{{ post.title or ("Пост #" ~ post.id) }}{% endblock %}
{% block content %}
<article class="post-full">
<h2>{{ post.title or ("Пост #" ~ post.id) }}</h2>
<div class="meta">{{ post.created_at }} • #{{ post.id }}</div>
<div class="body">{{ markdown(post.body)|safe }}</div>
<div class="post-actions">
<form action="{{ url_for('vote', pid=post.id) }}" method="post" style="display:inline;">
<input type="hidden" name="vote" value="up">
<button type="submit">▲ {{ votes.ups }}</button>
</form>
<form action="{{ url_for('vote', pid=post.id) }}" method="post" style="display:inline;">
<input type="hidden" name="vote" value="down">
<button type="submit">▼ {{ votes.downs }}</button>
</form>
<span class="score">Score: {{ votes.score }}</span>
<form action="{{ url_for('flag_post', pid=post.id) }}" method="post" class="flag-form" style="display:inline;">
<input type="text" name="reason" placeholder="Пожаловаться..." />
<button type="submit">Flag ({{ flags }})</button>
</form>
</div>
<p><a href="{{ url_for('index') }}">← Назад в ленту</a></p>
</article>
{% endblock %}

23
app/templates/search.html Normal file
View File

@@ -0,0 +1,23 @@
{% extends "base.html" %}
{% block title %}Поиск — Text-Booru{% endblock %}
{% block content %}
<h2>Поиск</h2>
<form action="{{ url_for('search') }}" method="get">
<input name="q" placeholder="Поиск..." value="{{ q }}">
<button>Искать</button>
</form>
{% if q %}
<h3>Результаты для «{{ q }}»</h3>
{% if posts %}
<ul>
{% for p in posts %}
<li><a href="{{ url_for('view_post', pid=p.id) }}">{{ p.title or p.body[:80] }}</a> — {{ p.created_at }}</li>
{% endfor %}
</ul>
{% else %}
<p>Ничего не найдено.</p>
{% endif %}
{% endif %}
{% endblock %}