mirror of
https://github.com/wahyd4/links.git
synced 2026-08-09 05:06:16 +10:00
fix(home): restore tbody binding, sticky mobile delete bar, 20-row recent-first list
- Fix Uncaught ReferenceError: tbody is not defined — the client-side filter rewrite dropped the const tbody declaration still used by load-more - Mobile: Delete Selected becomes a sticky frosted bottom bar (safe-area aware); disabled (grayed) until a row is selected, then red - Mobile: library search input full-width 48px (primary interaction) - Default list: 20 rows (was 50) sorted by updated_at desc (recent first) instead of click_count; load-more keeps paging +20
This commit is contained in:
@@ -208,6 +208,10 @@
|
|||||||
.apple-btn-primary:hover { background: var(--apple-blue-hover); color: #fff; }
|
.apple-btn-primary:hover { background: var(--apple-blue-hover); color: #fff; }
|
||||||
.apple-btn-danger { background: transparent; color: var(--apple-red); border: 1px solid rgba(255, 59, 48, 0.4); }
|
.apple-btn-danger { background: transparent; color: var(--apple-red); border: 1px solid rgba(255, 59, 48, 0.4); }
|
||||||
.apple-btn-danger:hover { background: rgba(255, 59, 48, 0.08); }
|
.apple-btn-danger:hover { background: rgba(255, 59, 48, 0.08); }
|
||||||
|
.apple-btn-danger:disabled {
|
||||||
|
opacity: 0.45; color: var(--apple-gray); border-color: rgba(0, 0, 0, 0.12);
|
||||||
|
cursor: default; pointer-events: none; background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------- Link library (table) ---------- */
|
/* ---------- Link library (table) ---------- */
|
||||||
.library-header {
|
.library-header {
|
||||||
@@ -579,7 +583,19 @@
|
|||||||
/* ---------- Small screens ---------- */
|
/* ---------- Small screens ---------- */
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.library-header { padding: 1.35rem 1.1rem 1rem; }
|
.library-header { padding: 1.35rem 1.1rem 1rem; }
|
||||||
.library-footer { padding: 1rem 1.1rem 1.25rem; }
|
.library-footer {
|
||||||
|
position: sticky; bottom: 0; z-index: 5;
|
||||||
|
background: rgba(245, 245, 247, 0.88);
|
||||||
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 0 0 var(--apple-radius-lg) var(--apple-radius-lg);
|
||||||
|
margin: 0 -1.1rem -1.25rem;
|
||||||
|
padding: 0.7rem 1.1rem calc(0.7rem + env(safe-area-inset-bottom, 0px));
|
||||||
|
}
|
||||||
|
/* Search takes the full row on mobile (it is the primary interaction) */
|
||||||
|
.library-filter { flex: 1 1 100%; }
|
||||||
|
.library-filter input { width: 100%; height: 48px; font-size: 1rem; }
|
||||||
.apple-table thead th, .apple-table tbody td { padding-left: 0.8rem; padding-right: 0.8rem; }
|
.apple-table thead th, .apple-table tbody td { padding-left: 0.8rem; padding-right: 0.8rem; }
|
||||||
.hero-stats { gap: 1.25rem; }
|
.hero-stats { gap: 1.25rem; }
|
||||||
.posts-panel-header { padding: 1.15rem 1.1rem 0.6rem; }
|
.posts-panel-header { padding: 1.15rem 1.1rem 0.6rem; }
|
||||||
@@ -965,7 +981,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="library-footer">
|
<div class="library-footer">
|
||||||
<p class="selection-hint" id="selection-hint" aria-live="polite"></p>
|
<p class="selection-hint" id="selection-hint" aria-live="polite"></p>
|
||||||
<button type="submit" class="apple-btn apple-btn-danger">{% trans "Delete Selected" %}</button>
|
<button type="submit" id="delete-selected-btn" class="apple-btn apple-btn-danger" disabled>{% trans "Delete Selected" %}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
@@ -1406,6 +1422,7 @@
|
|||||||
|
|
||||||
/* ---------- Load more links ---------- */
|
/* ---------- Load more links ---------- */
|
||||||
const loadMoreBtn = document.getElementById('load-more-links');
|
const loadMoreBtn = document.getElementById('load-more-links');
|
||||||
|
const tbody = document.getElementById('links-table-body');
|
||||||
if (loadMoreBtn && tbody) {
|
if (loadMoreBtn && tbody) {
|
||||||
loadMoreBtn.addEventListener('click', function () {
|
loadMoreBtn.addEventListener('click', function () {
|
||||||
const offset = loadMoreBtn.dataset.offset;
|
const offset = loadMoreBtn.dataset.offset;
|
||||||
@@ -1444,6 +1461,8 @@
|
|||||||
if (!selectionHint) return;
|
if (!selectionHint) return;
|
||||||
const count = document.querySelectorAll('input[name="selected_links"]:checked').length;
|
const count = document.querySelectorAll('input[name="selected_links"]:checked').length;
|
||||||
selectionHint.textContent = count > 0 ? count + ' {% trans "selected" %}' : '';
|
selectionHint.textContent = count > 0 ? count + ' {% trans "selected" %}' : '';
|
||||||
|
const delBtn = document.getElementById('delete-selected-btn');
|
||||||
|
if (delBtn) delBtn.disabled = count === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectAll) {
|
if (selectAll) {
|
||||||
|
|||||||
+7
-7
@@ -47,7 +47,7 @@ from .search_views import search_aliases, search
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Number of link rows rendered on the initial home page load / per "Load more" click.
|
# Number of link rows rendered on the initial home page load / per "Load more" click.
|
||||||
LINKS_PAGE_SIZE = 50
|
LINKS_PAGE_SIZE = 20
|
||||||
|
|
||||||
|
|
||||||
def _ordering_for(sort_by, order):
|
def _ordering_for(sort_by, order):
|
||||||
@@ -74,14 +74,14 @@ class LinkListView(ListView):
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
sort_by = self.request.GET.get('sort', 'click_count')
|
sort_by = self.request.GET.get('sort', 'updated_at')
|
||||||
order = self.request.GET.get('order', 'asc')
|
order = self.request.GET.get('order', 'desc')
|
||||||
return queryset.order_by(_ordering_for(sort_by, order))
|
return queryset.order_by(_ordering_for(sort_by, order))
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['current_sort'] = self.request.GET.get('sort', 'click_count')
|
context['current_sort'] = self.request.GET.get('sort', 'updated_at')
|
||||||
context['current_order'] = self.request.GET.get('order', 'asc')
|
context['current_order'] = self.request.GET.get('order', 'desc')
|
||||||
|
|
||||||
# Modern color palette
|
# Modern color palette
|
||||||
colors = [
|
colors = [
|
||||||
@@ -128,8 +128,8 @@ def load_more_links(request):
|
|||||||
"""Return the next page of link rows (rendered as <tr> HTML) for the
|
"""Return the next page of link rows (rendered as <tr> HTML) for the
|
||||||
home page's "Load more" button, so the initial page load doesn't have
|
home page's "Load more" button, so the initial page load doesn't have
|
||||||
to render the entire link table at once."""
|
to render the entire link table at once."""
|
||||||
sort_by = request.GET.get('sort', 'click_count')
|
sort_by = request.GET.get('sort', 'updated_at')
|
||||||
order = request.GET.get('order', 'asc')
|
order = request.GET.get('order', 'desc')
|
||||||
try:
|
try:
|
||||||
offset = max(int(request.GET.get('offset', 0)), 0)
|
offset = max(int(request.GET.get('offset', 0)), 0)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
|
|||||||
Reference in New Issue
Block a user