fix: address user feedback (delete user, editor return, UI tweaks)

This commit is contained in:
Your Name
2026-07-19 00:47:49 +05:00
parent a2dcdf4aea
commit fbb42b1f0e
5 changed files with 69 additions and 49 deletions
@@ -85,7 +85,7 @@
</div> </div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="text-sm text-app-textMuted">На странице:</span> <span class="text-sm text-app-textMuted">На странице:</span>
<select name="per_page" class="select select-sm w-auto py-1" form="filter-form"> <select name="per_page" class="select select-sm w-auto py-1 pr-8" form="filter-form">
{% for n in [10,25,50,100] %} {% for n in [10,25,50,100] %}
<option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option> <option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option>
{% endfor %} {% endfor %}
+48 -36
View File
@@ -74,7 +74,11 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<div class="mb-4" x-data="{ galleryOpen: false, activeIdx: 0, images: {{ photo_urls | tojson | forceescape }} }" @keydown.escape.window="galleryOpen = false"> <div class="mb-4" x-data="{ galleryOpen: false, activeIdx: 0, images: {{ photo_urls | tojson | forceescape }} }"
@keydown.escape.window="galleryOpen = false"
@keydown.left.window="if(galleryOpen && images.length > 1) activeIdx = (activeIdx === 0) ? images.length - 1 : activeIdx - 1"
@keydown.right.window="if(galleryOpen && images.length > 1) activeIdx = (activeIdx === images.length - 1) ? 0 : activeIdx + 1">
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
{% for m in p.media_items %} {% for m in p.media_items %}
{% if m.type == "photo" and m.url %} {% if m.type == "photo" and m.url %}
@@ -91,32 +95,30 @@
</div> </div>
<!-- Alpine Modal Gallery --> <!-- Alpine Modal Gallery -->
<template x-if="galleryOpen"> <div x-show="galleryOpen" style="display: none;" x-transition.opacity class="fixed inset-0 z-[100] flex items-center justify-center bg-black/90 backdrop-blur-sm p-4">
<div class="fixed inset-0 z-[100] flex items-center justify-center bg-black/90 backdrop-blur-sm p-4"> <!-- Close button -->
<!-- Close button --> <button @click.prevent="galleryOpen = false" type="button" class="absolute top-4 right-4 text-white hover:text-app-primary transition-colors p-2">
<button @click.prevent="galleryOpen = false" type="button" class="absolute top-4 right-4 text-white hover:text-app-primary transition-colors p-2"> <svg xmlns="http://www.w3.org/2000/svg" class="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /></svg>
<i data-lucide="x" class="w-8 h-8"></i> </button>
</button>
<!-- Previous --> <!-- Previous -->
<button x-show="images.length > 1" @click.prevent="activeIdx = (activeIdx === 0) ? images.length - 1 : activeIdx - 1" type="button" class="absolute left-4 top-1/2 -translate-y-1/2 text-white hover:text-app-primary p-2"> <button x-show="images.length > 1" @click.prevent="activeIdx = (activeIdx === 0) ? images.length - 1 : activeIdx - 1" type="button" class="absolute left-4 top-1/2 -translate-y-1/2 text-white hover:text-app-primary p-2">
<i data-lucide="chevron-left" class="w-10 h-10"></i> <svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7" /></svg>
</button> </button>
<!-- Image --> <!-- Image -->
<img :src="images[activeIdx]" class="max-w-full max-h-[90vh] object-contain rounded-lg shadow-2xl"> <img :src="images[activeIdx]" class="max-w-full max-h-[90vh] object-contain rounded-lg shadow-2xl">
<!-- Next --> <!-- Next -->
<button x-show="images.length > 1" @click.prevent="activeIdx = (activeIdx === images.length - 1) ? 0 : activeIdx + 1" type="button" class="absolute right-4 top-1/2 -translate-y-1/2 text-white hover:text-app-primary p-2"> <button x-show="images.length > 1" @click.prevent="activeIdx = (activeIdx === images.length - 1) ? 0 : activeIdx + 1" type="button" class="absolute right-4 top-1/2 -translate-y-1/2 text-white hover:text-app-primary p-2">
<i data-lucide="chevron-right" class="w-10 h-10"></i> <svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" /></svg>
</button> </button>
<!-- Counter --> <!-- Counter -->
<div x-show="images.length > 1" class="absolute bottom-4 left-1/2 -translate-x-1/2 text-white font-mono text-sm bg-black/50 px-3 py-1 rounded-full"> <div x-show="images.length > 1" class="absolute bottom-4 left-1/2 -translate-x-1/2 text-white font-mono text-sm bg-black/50 px-3 py-1 rounded-full">
<span x-text="activeIdx + 1"></span> / <span x-text="images.length"></span> <span x-text="activeIdx + 1"></span> / <span x-text="images.length"></span>
</div>
</div> </div>
</template> </div>
</div> </div>
{% endif %} {% endif %}
@@ -182,28 +184,38 @@
</div> </div>
<!-- Actions --> <!-- Actions -->
{% if p.editorial_status != 'published' %}
<div class="mt-5 pt-4 border-t border-app-border flex flex-wrap items-center justify-between gap-3"> <div class="mt-5 pt-4 border-t border-app-border flex flex-wrap items-center justify-between gap-3">
<!-- Delete Button --> {% if p.editorial_status == 'rejected' %}
<div> <div>
{% if p.editorial_status != 'rejected' %} <button class="btn btn-ghost btn-sm text-app-warning hover:bg-app-warning/10 hover:text-app-warning" type="button"
hx-post="/editor/{{ p.id }}/return" hx-target="#post-container-{{ p.id }}" hx-swap="outerHTML"
hx-vals='{"csrf_token": "{{ user.csrf_token }}"}'>
<i data-lucide="corner-up-left" class="w-4 h-4"></i> Вернуть на проверку
</button>
</div>
{% else %}
<!-- Delete Button -->
<div>
<button class="btn btn-ghost btn-sm text-app-error hover:bg-app-errorBg hover:text-app-error" type="button" <button class="btn btn-ghost btn-sm text-app-error hover:bg-app-errorBg hover:text-app-error" type="button"
hx-post="/editor/{{ p.id }}/reject" hx-target="#post-container-{{ p.id }}" hx-swap="outerHTML" hx-post="/editor/{{ p.id }}/reject" hx-target="#post-container-{{ p.id }}" hx-swap="outerHTML"
hx-vals='{"csrf_token": "{{ user.csrf_token }}"}' hx-vals='{"csrf_token": "{{ user.csrf_token }}"}'
onclick="return confirm('Отклонить пост?')"> onclick="return confirm('Отклонить пост?')">
<i data-lucide="x" class="w-4 h-4"></i> В мусор <i data-lucide="x" class="w-4 h-4"></i> Отклонить
</button> </button>
{% endif %} </div>
</div>
<div class="flex gap-2"> <div class="flex gap-2">
<button type="submit" name="action" value="save" class="btn btn-surface btn-sm"> <button type="submit" name="action" value="save" class="btn btn-surface btn-sm">
<i data-lucide="save" class="w-4 h-4"></i> Сохранить как черновик <i data-lucide="save" class="w-4 h-4"></i> Сохранить как черновик
</button> </button>
<button type="submit" name="action" value="accept" class="btn btn-primary btn-sm"> <button type="submit" name="action" value="accept" class="btn btn-primary btn-sm">
<i data-lucide="send" class="w-4 h-4"></i> Сохранить и Опубликовать <i data-lucide="send" class="w-4 h-4"></i> Сохранить и Опубликовать
</button> </button>
</div> </div>
{% endif %}
</div> </div>
{% endif %}
</div> </div>
</div> </div>
</form> </form>
+1 -1
View File
@@ -77,7 +77,7 @@
<input type="hidden" name="{{ item.key }}" value="{{ item.value }}"> <input type="hidden" name="{{ item.key }}" value="{{ item.value }}">
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<select name="per_page" class="select select-sm w-20 py-1" onchange="this.form.submit()"> <select name="per_page" class="select select-sm w-20 py-1 pr-8" onchange="this.form.submit()">
{% for n in [25,50,100,200] %} {% for n in [25,50,100,200] %}
<option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option> <option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option>
{% endfor %} {% endfor %}
@@ -86,7 +86,7 @@
</div> </div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="text-sm text-app-textMuted">На странице:</span> <span class="text-sm text-app-textMuted">На странице:</span>
<select name="per_page" class="select select-sm w-auto py-1" form="filter-form" onchange="document.getElementById('filter-form').dispatchEvent(new Event('submit', {cancelable: true}))"> <select name="per_page" class="select select-sm w-auto py-1 pr-8" form="filter-form" onchange="document.getElementById('filter-form').dispatchEvent(new Event('submit', {cancelable: true}))">
{% for n in [25,50,100,200] %} {% for n in [25,50,100,200] %}
<option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option> <option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option>
{% endfor %} {% endfor %}
+14 -6
View File
@@ -43,12 +43,20 @@
</td> </td>
<td class="px-4 py-3 text-right"> <td class="px-4 py-3 text-right">
{% if user.role == "admin" and user.id != u.id %} {% if user.role == "admin" and user.id != u.id %}
<form method="post" action="/users/{{ u.id }}/toggle" class="m-0 inline-block"> <div class="flex items-center justify-end gap-2">
<input type="hidden" name="csrf_token" value="{{ user.csrf_token }}"> <form method="post" action="/users/{{ u.id }}/toggle" class="m-0 inline-block">
<button class="btn btn-xs {% if u.is_active %}btn-danger-outline{% else %}btn-primary-outline{% endif %}" type="submit"> <input type="hidden" name="csrf_token" value="{{ user.csrf_token }}">
{% if u.is_active %}Блокировать{% else %}Разблокировать{% endif %} <button class="btn btn-xs {% if u.is_active %}btn-surface{% else %}btn-primary-outline{% endif %}" type="submit">
</button> {% if u.is_active %}Блокировать{% else %}Разблокировать{% endif %}
</form> </button>
</form>
<form method="post" action="/users/{{ u.id }}/delete" class="m-0 inline-block" onsubmit="return confirm('Точно удалить пользователя?')">
<input type="hidden" name="csrf_token" value="{{ user.csrf_token }}">
<button class="btn btn-xs text-app-error hover:bg-app-errorBg hover:text-app-error" type="submit">
Удалить
</button>
</form>
</div>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>