From 86c04f85f61d7bba8ae32cf0b4b2be78fca74298 Mon Sep 17 00:00:00 2001 From: kqjy Date: Mon, 22 Dec 2025 13:17:27 +0800 Subject: [PATCH] Fix bucket object browser nested object action button; Improve UX --- app/version.py | 2 +- static/css/main.css | 16 ++++++++ templates/bucket_detail.html | 80 +++++++++++++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/app/version.py b/app/version.py index bd1e371..ea75040 100644 --- a/app/version.py +++ b/app/version.py @@ -1,7 +1,7 @@ """Central location for the application version string.""" from __future__ import annotations -APP_VERSION = "0.1.7" +APP_VERSION = "0.1.8" def get_version() -> str: diff --git a/static/css/main.css b/static/css/main.css index a75838a..77b74b3 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -517,6 +517,22 @@ code { overflow-y: auto; } +.objects-table-container thead { + position: sticky; + top: 0; + z-index: 10; +} + +.objects-table-container thead th { + background-color: #f8f9fa; + border-bottom: 1px solid var(--myfsio-card-border); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +[data-theme='dark'] .objects-table-container thead th { + background-color: #1e293b; +} + .btn-group form { display: inline; } .font-monospace { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; } diff --git a/templates/bucket_detail.html b/templates/bucket_detail.html index 41d22ba..d04b181 100644 --- a/templates/bucket_detail.html +++ b/templates/bucket_detail.html @@ -86,7 +86,9 @@ Upload - +
+ +
+
+
@@ -2189,7 +2200,8 @@ }; const countObjectsInFolder = (folderPrefix) => { - return allObjects.filter(obj => obj.key.startsWith(folderPrefix)).length; + const count = allObjects.filter(obj => obj.key.startsWith(folderPrefix)).length; + return { count, mayHaveMore: hasMoreObjects }; }; const renderBreadcrumb = (prefix) => { @@ -2265,7 +2277,8 @@ const createFolderRow = (folderPath) => { const folderName = folderPath.slice(currentPrefix.length).replace(/\/$/, ''); - const objectCount = countObjectsInFolder(folderPath); + const { count: objectCount, mayHaveMore } = countObjectsInFolder(folderPath); + const countDisplay = mayHaveMore ? `${objectCount}+` : objectCount; const tr = document.createElement('tr'); tr.className = 'folder-row'; @@ -2283,7 +2296,7 @@ ${escapeHtml(folderName)}/
-
${objectCount} object${objectCount !== 1 ? 's' : ''}
+
${countDisplay} object${objectCount !== 1 ? 's' : ''}
@@ -2309,6 +2322,12 @@ toggleRowSelection(obj.element, checkbox.checked); }); }); + + const folderBtn = tr.querySelector('button'); + folderBtn?.addEventListener('click', (e) => { + e.stopPropagation(); + navigateToFolder(folderPath); + }); tr.addEventListener('click', (e) => { if (e.target.closest('[data-folder-select]') || e.target.closest('button')) return; @@ -2329,6 +2348,14 @@ updateBulkDeleteState(); } + if (typeof updateFolderViewStatus === 'function') { + updateFolderViewStatus(); + } + + if (typeof updateFilterWarning === 'function') { + updateFilterWarning(); + } + if (previewPanel) previewPanel.classList.add('d-none'); if (previewEmpty) previewEmpty.classList.remove('d-none'); activeRow = null; @@ -3138,16 +3165,59 @@ function initFolderNavigation() { if (hasFolders()) { - renderBreadcrumb(''); + renderBreadcrumb(currentPrefix); renderObjectsView(); } + if (typeof updateFolderViewStatus === 'function') { + updateFolderViewStatus(); + } + if (typeof updateFilterWarning === 'function') { + updateFilterWarning(); + } } bulkDeleteButton?.addEventListener('click', () => openBulkDeleteModal()); bulkDeleteConfirm?.addEventListener('click', () => performBulkDelete()); + const filterWarning = document.getElementById('filter-warning'); + const filterWarningText = document.getElementById('filter-warning-text'); + const folderViewStatus = document.getElementById('folder-view-status'); + + const updateFilterWarning = () => { + if (!filterWarning) return; + const isFiltering = currentFilterTerm.length > 0; + if (isFiltering && hasMoreObjects) { + filterWarning.classList.remove('d-none'); + } else { + filterWarning.classList.add('d-none'); + } + }; + + const updateFolderViewStatus = () => { + if (!folderViewStatus || !loadMoreStatus) return; + if (currentPrefix) { + const { folders, files } = getFoldersAtPrefix(currentPrefix); + const visibleCount = folders.length + files.length; + const folderObjectCount = allObjects.filter(obj => obj.key.startsWith(currentPrefix)).length; + const folderMayHaveMore = hasMoreObjects && folderObjectCount > 0; + if (folderMayHaveMore) { + folderViewStatus.textContent = `Showing ${visibleCount} items in folder • more may be available`; + folderViewStatus.classList.remove('d-none'); + loadMoreStatus.classList.add('d-none'); + } else { + folderViewStatus.textContent = `${visibleCount} items in folder`; + folderViewStatus.classList.remove('d-none'); + loadMoreStatus.classList.add('d-none'); + } + } else { + folderViewStatus.classList.add('d-none'); + loadMoreStatus.classList.remove('d-none'); + } + }; + document.getElementById('object-search')?.addEventListener('input', (event) => { currentFilterTerm = event.target.value.toLowerCase(); + updateFilterWarning(); if (hasFolders()) { const { folders, files } = getFoldersAtPrefix(currentPrefix);