Improve admin mobile layouts
This commit is contained in:
@@ -10,15 +10,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Status Tabs -->
|
<!-- Status Tabs -->
|
||||||
<div class="tabs p-1">
|
<div class="w-full md:w-auto min-w-0 overflow-x-auto">
|
||||||
{% for st in status_options %}
|
<div class="tabs p-1 w-max">
|
||||||
<a class="tab {% if st.value in editorial_statuses %}tab-active{% endif %}" href="/editor?editorial_status={{ st.value }}">
|
{% for st in status_options %}
|
||||||
{{ st.label }}
|
<a class="tab {% if st.value in editorial_statuses %}tab-active{% endif %}" href="/editor?editorial_status={{ st.value }}">
|
||||||
<span class="ml-2 px-1.5 py-0.5 rounded-full text-xs font-semibold {% if st.value in editorial_statuses %}bg-app-primary/20 text-app-primary{% else %}bg-app-surface text-app-textMuted{% endif %}">
|
{{ st.label }}
|
||||||
{{ counts.get(st.value, 0) }}
|
<span class="ml-2 px-1.5 py-0.5 rounded-full text-xs font-semibold {% if st.value in editorial_statuses %}bg-app-primary/20 text-app-primary{% else %}bg-app-surface text-app-textMuted{% endif %}">
|
||||||
</span>
|
{{ counts.get(st.value, 0) }}
|
||||||
</a>
|
</span>
|
||||||
{% endfor %}
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
<div class="flex flex-col xl:flex-row gap-6">
|
<div class="flex flex-col xl:flex-row gap-6" x-data="{ filtersOpen: false }">
|
||||||
<!-- Sidebar Filters -->
|
<!-- Sidebar Filters -->
|
||||||
<aside class="w-full xl:w-72 flex-shrink-0">
|
<aside class="w-full flex-shrink-0 transition-all duration-200" :class="filtersOpen ? 'xl:w-72' : 'xl:w-12'">
|
||||||
<div class="card p-4 sticky top-6">
|
<div class="card p-4 sticky top-6">
|
||||||
|
<button type="button" class="btn btn-ghost btn-icon w-full mb-0" @click="filtersOpen = !filtersOpen" :aria-expanded="filtersOpen.toString()" :title="filtersOpen ? 'Свернуть фильтры' : 'Развернуть фильтры'">
|
||||||
|
<i data-lucide="sliders-horizontal" class="w-5 h-5"></i>
|
||||||
|
</button>
|
||||||
<form id="filter-form" hx-get="/editor" hx-target="#content-area" hx-push-url="true" hx-trigger="submit">
|
<form id="filter-form" hx-get="/editor" hx-target="#content-area" hx-push-url="true" hx-trigger="submit">
|
||||||
<input type="hidden" name="editorial_status" value="{{ status_filter }}">
|
<input type="hidden" name="editorial_status" value="{{ status_filter }}">
|
||||||
|
|
||||||
<div class="flex justify-between items-center mb-6">
|
<div x-show="filtersOpen" x-cloak class="flex justify-between items-center mt-4 mb-6">
|
||||||
<h2 class="text-sm font-bold text-app-textMuted uppercase tracking-wider">Фильтры</h2>
|
<h2 class="text-sm font-bold text-app-textMuted uppercase tracking-wider">Фильтры</h2>
|
||||||
<a href="/editor" class="text-xs text-app-primary hover:text-app-primaryHover transition-colors" hx-boost="true" hx-target="#content-area">Сбросить</a>
|
<a href="/editor" class="text-xs text-app-primary hover:text-app-primaryHover transition-colors" hx-boost="true" hx-target="#content-area">Сбросить</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-6">
|
<div x-show="filtersOpen" x-cloak class="space-y-6">
|
||||||
<!-- Sort -->
|
<!-- Sort -->
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-xs font-semibold text-app-textMain mb-2">Сортировка</label>
|
<label class="block text-xs font-semibold text-app-textMain mb-2">Сортировка</label>
|
||||||
|
|||||||
@@ -95,7 +95,44 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card overflow-hidden">
|
<div class="card overflow-hidden">
|
||||||
<div class="overflow-x-auto">
|
<div class="md:hidden divide-y divide-app-border">
|
||||||
|
{% for p in posts %}
|
||||||
|
<a href="/raw/{{ p.id }}" class="block p-4 hover:bg-app-surfaceHover transition-colors">
|
||||||
|
<div class="flex items-start justify-between gap-3">
|
||||||
|
<div class="min-w-0">
|
||||||
|
<div class="font-mono text-xs text-app-primary">#{{ p.id }}</div>
|
||||||
|
<div class="mt-1 font-semibold text-app-textMain truncate">{{ p.source_name }}</div>
|
||||||
|
<div class="mt-1 flex flex-wrap gap-1">
|
||||||
|
<span class="badge badge-neutral text-[9px] uppercase tracking-wider">{{ p.status }}</span>
|
||||||
|
{% if p.qualification_status %}
|
||||||
|
<span class="badge badge-success text-[9px] uppercase tracking-wider bg-app-success/10 text-app-success border-app-success/20">Квалиф: {{ p.qualification_status }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if p.rewrite_status %}
|
||||||
|
<span class="badge badge-warning text-[9px] uppercase tracking-wider bg-app-warning/10 text-app-warning border-app-warning/20">Рерайт: {{ p.rewrite_status }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-shrink-0 text-right">
|
||||||
|
{% if p.qualification_score is not none %}
|
||||||
|
<div class="font-mono font-bold text-lg {% if p.qualification_score >= 8 %}text-app-success{% elif p.qualification_score >= 5 %}text-app-warning{% else %}text-app-error{% endif %}">{{ p.qualification_score }}</div>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-app-textMuted">—</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-xs text-app-textMain/80 leading-relaxed line-clamp-3">{{ p.raw_text }}</div>
|
||||||
|
<div class="mt-2 text-[10px] text-app-textMuted">{{ p.posted_at_fmt or p.created_at_fmt }}</div>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<div class="px-4 py-12">
|
||||||
|
<div class="flex flex-col items-center justify-center text-app-textMuted">
|
||||||
|
<i data-lucide="inbox" class="w-12 h-12 mb-3 text-app-borderFocus"></i>
|
||||||
|
<p class="text-sm">Нет данных по заданным фильтрам</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="hidden md:block overflow-x-auto">
|
||||||
<table class="w-full text-left text-sm whitespace-nowrap">
|
<table class="w-full text-left text-sm whitespace-nowrap">
|
||||||
<thead class="bg-app-bg border-b border-app-border">
|
<thead class="bg-app-bg border-b border-app-border">
|
||||||
<tr class="text-app-textMuted font-semibold tracking-wide uppercase text-xs">
|
<tr class="text-app-textMuted font-semibold tracking-wide uppercase text-xs">
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
<tr class="hover:bg-app-surfaceHover transition-colors" id="source-row-{{ s.id }}">
|
<tr class="hover:bg-app-surfaceHover transition-colors" id="source-row-{{ s.id }}">
|
||||||
<td class="px-4 py-3 font-mono text-[10px] text-app-textMuted">{{ s.id }}</td>
|
<td class="hidden sm:table-cell px-4 py-3 font-mono text-[10px] text-app-textMuted">{{ s.id }}</td>
|
||||||
<td class="px-4 py-3 uppercase text-[10px] tracking-widest font-bold text-app-textMuted">{{ s.platform }}</td>
|
<td class="hidden md:table-cell px-4 py-3 uppercase text-[10px] tracking-widest font-bold text-app-textMuted">{{ s.platform }}</td>
|
||||||
<td class="px-4 py-3">
|
<td class="px-4 py-3 min-w-0">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2 min-w-0">
|
||||||
<span class="font-bold text-app-textMain">{{ s.name }}</span>
|
<span class="font-bold text-app-textMain truncate">{{ s.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[10px] font-mono text-app-textMuted mt-1" title="External ID">{{ s.external_id or "" }}</div>
|
<div class="sm:hidden text-[10px] font-mono text-app-textMuted mt-1">#{{ s.id }}</div>
|
||||||
|
<div class="text-[10px] font-mono text-app-textMuted mt-1 truncate" title="External ID">{{ s.external_id or "" }}</div>
|
||||||
|
<div class="sm:hidden text-[10px] font-mono text-blue-400 mt-1 truncate">#{{ s.tag or "—" }}</div>
|
||||||
|
<a href="{{ s.url }}" target="_blank" class="lg:hidden text-[10px] text-app-textMuted hover:text-white hover:underline truncate block mt-1" title="{{ s.url }}">{{ s.url }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 font-mono text-[10px] text-blue-400">#{{ s.tag or "—" }}</td>
|
<td class="hidden sm:table-cell px-4 py-3 font-mono text-[10px] text-blue-400 truncate">#{{ s.tag or "—" }}</td>
|
||||||
<td class="px-4 py-3">
|
<td class="hidden lg:table-cell px-4 py-3">
|
||||||
<a href="{{ s.url }}" target="_blank" class="text-app-textMuted hover:text-white hover:underline truncate inline-block max-w-[12rem]" title="{{ s.url }}">{{ s.url }}</a>
|
<a href="{{ s.url }}" target="_blank" class="text-app-textMuted hover:text-white hover:underline truncate inline-block max-w-[12rem]" title="{{ s.url }}">{{ s.url }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3">
|
<td class="px-3 sm:px-4 py-3">
|
||||||
<div class="flex flex-col gap-1 items-start">
|
<div class="flex flex-col gap-1 items-start">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
{% if s.active %}
|
{% if s.active %}
|
||||||
@@ -29,12 +32,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-right">
|
<td class="hidden sm:table-cell px-4 py-3 text-right">
|
||||||
<div class="font-bold text-app-textMain">{{ s.posts_count }}</div>
|
<div class="font-bold text-app-textMain">{{ s.posts_count }}</div>
|
||||||
<div class="text-[10px] text-app-success" title="За последние 24 часа">+{{ s.posts_24h }}</div>
|
<div class="text-[10px] text-app-success" title="За последние 24 часа">+{{ s.posts_24h }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-right text-[10px] text-app-textMuted">{{ s.last_parsed_at_fmt or "Никогда" }}</td>
|
<td class="hidden xl:table-cell px-4 py-3 text-right text-[10px] text-app-textMuted">{{ s.last_parsed_at_fmt or "Никогда" }}</td>
|
||||||
<td class="px-4 py-3 text-center">
|
<td class="px-3 sm:px-4 py-3 text-center">
|
||||||
<div class="flex justify-center items-center gap-1">
|
<div class="flex justify-center items-center gap-1">
|
||||||
<a href="/sources/{{ s.id }}/edit" class="btn btn-ghost btn-icon w-8 h-8 rounded-md hover:bg-app-surface text-app-textMuted hover:text-white" title="Править">
|
<a href="/sources/{{ s.id }}/edit" class="btn btn-ghost btn-icon w-8 h-8 rounded-md hover:bg-app-surface text-app-textMuted hover:text-white" title="Править">
|
||||||
<i data-lucide="edit-2" class="w-4 h-4"></i>
|
<i data-lucide="edit-2" class="w-4 h-4"></i>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<div class="overflow-x-auto">
|
<div class="overflow-hidden">
|
||||||
<table class="w-full text-left text-sm whitespace-nowrap">
|
<table class="w-full table-fixed text-left text-sm">
|
||||||
<thead class="bg-app-bg border-b border-app-border">
|
<thead class="bg-app-bg border-b border-app-border">
|
||||||
<tr class="text-app-textMuted font-semibold tracking-wide uppercase text-xs">
|
<tr class="text-app-textMuted font-semibold tracking-wide uppercase text-xs">
|
||||||
<th class="px-4 py-3 w-16">#</th>
|
<th class="hidden sm:table-cell px-4 py-3 w-16">#</th>
|
||||||
<th class="px-4 py-3 w-24">Платформа</th>
|
<th class="hidden md:table-cell px-4 py-3 w-24">Платформа</th>
|
||||||
<th class="px-4 py-3">Название</th>
|
<th class="px-4 py-3">Название</th>
|
||||||
<th class="px-4 py-3 w-32">Тэг</th>
|
<th class="hidden sm:table-cell px-4 py-3 w-32">Тэг</th>
|
||||||
<th class="px-4 py-3 w-48">Ссылка</th>
|
<th class="hidden lg:table-cell px-4 py-3 w-48">Ссылка</th>
|
||||||
<th class="px-4 py-3 w-32">Статус Парсера</th>
|
<th class="px-3 py-3 w-28 sm:w-32">Статус</th>
|
||||||
<th class="px-4 py-3 w-24 text-right">Посты</th>
|
<th class="hidden sm:table-cell px-4 py-3 w-24 text-right">Посты</th>
|
||||||
<th class="px-4 py-3 w-40 text-right">Последний парсинг</th>
|
<th class="hidden xl:table-cell px-4 py-3 w-40 text-right">Последний парсинг</th>
|
||||||
<th class="px-4 py-3 w-32 text-center">Действия</th>
|
<th class="px-3 py-3 w-24 sm:w-32 text-center">Действия</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-app-border text-xs">
|
<tbody class="divide-y divide-app-border text-xs">
|
||||||
|
|||||||
Reference in New Issue
Block a user