fix: address user feedback (delete user, editor return, UI tweaks)
This commit is contained in:
@@ -85,7 +85,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<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] %}
|
||||
<option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option>
|
||||
{% endfor %}
|
||||
|
||||
@@ -74,7 +74,11 @@
|
||||
{% endif %}
|
||||
{% 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">
|
||||
{% for m in p.media_items %}
|
||||
{% if m.type == "photo" and m.url %}
|
||||
@@ -91,16 +95,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Alpine Modal Gallery -->
|
||||
<template x-if="galleryOpen">
|
||||
<div class="fixed inset-0 z-[100] flex items-center justify-center bg-black/90 backdrop-blur-sm p-4">
|
||||
<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">
|
||||
<!-- 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">
|
||||
<i data-lucide="x" class="w-8 h-8"></i>
|
||||
<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>
|
||||
</button>
|
||||
|
||||
<!-- 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">
|
||||
<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>
|
||||
|
||||
<!-- Image -->
|
||||
@@ -108,7 +111,7 @@
|
||||
|
||||
<!-- 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">
|
||||
<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>
|
||||
|
||||
<!-- Counter -->
|
||||
@@ -116,7 +119,6 @@
|
||||
<span x-text="activeIdx + 1"></span> / <span x-text="images.length"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -182,17 +184,25 @@
|
||||
</div>
|
||||
|
||||
<!-- 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">
|
||||
{% if p.editorial_status == 'rejected' %}
|
||||
<div>
|
||||
<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>
|
||||
{% if p.editorial_status != 'rejected' %}
|
||||
<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-vals='{"csrf_token": "{{ user.csrf_token }}"}'
|
||||
onclick="return confirm('Отклонить пост?')">
|
||||
<i data-lucide="x" class="w-4 h-4"></i> В мусор
|
||||
<i data-lucide="x" class="w-4 h-4"></i> Отклонить
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
@@ -203,7 +213,9 @@
|
||||
<i data-lucide="send" class="w-4 h-4"></i> Сохранить и Опубликовать
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<input type="hidden" name="{{ item.key }}" value="{{ item.value }}">
|
||||
{% endif %}
|
||||
{% 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] %}
|
||||
<option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option>
|
||||
{% endfor %}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<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] %}
|
||||
<option value="{{ n }}" {% if pagination.per_page == n %}selected{% endif %}>{{ n }}</option>
|
||||
{% endfor %}
|
||||
|
||||
@@ -43,12 +43,20 @@
|
||||
</td>
|
||||
<td class="px-4 py-3 text-right">
|
||||
{% if user.role == "admin" and user.id != u.id %}
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<form method="post" action="/users/{{ u.id }}/toggle" class="m-0 inline-block">
|
||||
<input type="hidden" name="csrf_token" value="{{ user.csrf_token }}">
|
||||
<button class="btn btn-xs {% if u.is_active %}btn-danger-outline{% else %}btn-primary-outline{% endif %}" type="submit">
|
||||
<button class="btn btn-xs {% if u.is_active %}btn-surface{% else %}btn-primary-outline{% endif %}" type="submit">
|
||||
{% if u.is_active %}Блокировать{% else %}Разблокировать{% endif %}
|
||||
</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 %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user