fix(#107): trash/recent/favorites list view rendering bugs
Trash view:
- Fix 'Invalid Date': use item.trashed_at (ISO 8601) instead of item.deleted_at * 1000
- Fix literal i18n key 'files.file_types.file': determine type from file extension
(pdf, image, video, audio, text, document) since trash DTO has no mime_type
- Fix column alignment: remove checkbox from trash header (not applicable),
add .trash-header CSS class matching the 5-column grid layout
Recent view:
- Fix header/row column misalignment: add empty placeholder div for indicator
column and .recent-header CSS class matching the 5-column grid
- Fix missing i18n key: use 'recent.accessed' instead of 'files.last_accessed'
- Fix default typeLabel not internationalized: use i18n.t('files.file_types.document')
Favorites view:
- Fix header/row column misalignment: add empty placeholder div for indicator
column and .favorites-header CSS class matching the 5-column grid
- Fix default typeLabel not internationalized: use i18n.t('files.file_types.document')
Bump SW cache to v11.
This commit is contained in:
@@ -47,6 +47,10 @@
|
||||
}
|
||||
|
||||
/* Adjustments for list view */
|
||||
.list-header.favorites-header {
|
||||
grid-template-columns: 30px minmax(200px, 2fr) 1fr 1fr 120px;
|
||||
}
|
||||
|
||||
.file-item.favorite-item {
|
||||
position: relative;
|
||||
grid-template-columns: 30px minmax(200px, 2fr) 1fr 1fr 120px;
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
}
|
||||
|
||||
/* Adjustments for list view */
|
||||
.list-header.recent-header {
|
||||
grid-template-columns: 30px minmax(200px, 2fr) 1fr 1fr 120px;
|
||||
}
|
||||
|
||||
.file-item.recent-item {
|
||||
position: relative;
|
||||
grid-template-columns: 30px minmax(200px, 2fr) 1fr 1fr 120px;
|
||||
|
||||
@@ -1811,9 +1811,13 @@ select:focus {
|
||||
background-color: #fff0ec;
|
||||
}
|
||||
|
||||
/* For trash mode, adjust columns */
|
||||
/* For trash mode, adjust columns (5 cols: name, type, path, date, actions) */
|
||||
.list-header.trash-header {
|
||||
grid-template-columns: minmax(180px, 1.5fr) 0.5fr 1fr 140px 100px;
|
||||
}
|
||||
|
||||
.trash-item.file-item {
|
||||
grid-template-columns: minmax(180px, 1.5fr) 0.5fr 1fr 120px 100px;
|
||||
grid-template-columns: minmax(180px, 1.5fr) 0.5fr 1fr 140px 100px;
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
|
||||
+35
-9
@@ -874,8 +874,7 @@ async function loadTrashItems() {
|
||||
if (window.multiSelect) window.multiSelect.clear();
|
||||
elements.filesGrid.innerHTML = '';
|
||||
elements.filesListView.innerHTML = `
|
||||
<div class="list-header">
|
||||
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
|
||||
<div class="list-header trash-header">
|
||||
<div data-i18n="files.name">Name</div>
|
||||
<div data-i18n="files.type">Type</div>
|
||||
<div data-i18n="trash.original_location">Original location</div>
|
||||
@@ -924,17 +923,44 @@ async function loadTrashItems() {
|
||||
*/
|
||||
function addTrashItemToView(item) {
|
||||
const isFile = item.item_type === 'file';
|
||||
const iconClass = isFile ? 'fas fa-file' : 'fas fa-folder';
|
||||
|
||||
// Format date
|
||||
const deletedDate = new Date(item.deleted_at * 1000);
|
||||
// Format date - backend sends trashed_at as ISO 8601 string
|
||||
const deletedDate = new Date(item.trashed_at);
|
||||
const formattedDate = deletedDate.toLocaleDateString() + ' ' +
|
||||
deletedDate.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
|
||||
// Item type label
|
||||
const typeLabel = isFile ?
|
||||
(window.i18n ? window.i18n.t('files.file_types.file') : 'File') :
|
||||
(window.i18n ? window.i18n.t('files.file_types.folder') : 'Folder');
|
||||
// Determine type label and icon from extension (trash DTO has no mime_type)
|
||||
let typeLabel;
|
||||
let iconClass;
|
||||
if (!isFile) {
|
||||
iconClass = 'fas fa-folder';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.folder') : 'Folder';
|
||||
} else {
|
||||
const ext = (item.name.split('.').pop() || '').toLowerCase();
|
||||
const imageExts = ['jpg','jpeg','png','gif','bmp','svg','webp','ico','tiff'];
|
||||
const videoExts = ['mp4','avi','mkv','mov','wmv','flv','webm'];
|
||||
const audioExts = ['mp3','wav','ogg','flac','aac','wma','m4a'];
|
||||
const textExts = ['txt','md','csv','log','ini','cfg','conf'];
|
||||
if (ext === 'pdf') {
|
||||
iconClass = 'fas fa-file-pdf';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.pdf') : 'PDF';
|
||||
} else if (imageExts.includes(ext)) {
|
||||
iconClass = 'fas fa-file-image';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.image') : 'Image';
|
||||
} else if (videoExts.includes(ext)) {
|
||||
iconClass = 'fas fa-file-video';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.video') : 'Video';
|
||||
} else if (audioExts.includes(ext)) {
|
||||
iconClass = 'fas fa-file-audio';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.audio') : 'Audio';
|
||||
} else if (textExts.includes(ext)) {
|
||||
iconClass = 'fas fa-file-alt';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.text') : 'Text';
|
||||
} else {
|
||||
iconClass = 'fas fa-file';
|
||||
typeLabel = window.i18n ? window.i18n.t('files.file_types.document') : 'Document';
|
||||
}
|
||||
}
|
||||
|
||||
// Grid view element
|
||||
const gridElement = document.createElement('div');
|
||||
|
||||
@@ -320,7 +320,8 @@ const favorites = {
|
||||
|
||||
filesGrid.innerHTML = '';
|
||||
filesListView.innerHTML = `
|
||||
<div class="list-header">
|
||||
<div class="list-header favorites-header">
|
||||
<div></div>
|
||||
<div data-i18n="files.name">Name</div>
|
||||
<div data-i18n="files.type">Type</div>
|
||||
<div data-i18n="files.size">Size</div>
|
||||
@@ -556,7 +557,7 @@ const favorites = {
|
||||
// Determine icon and type
|
||||
let iconClass = 'fas fa-file';
|
||||
let iconSpecialClass = '';
|
||||
let typeLabel = 'Document';
|
||||
let typeLabel = window.i18n ? window.i18n.t('files.file_types.document') : 'Document';
|
||||
|
||||
if (file.mime_type) {
|
||||
if (file.mime_type.startsWith('image/')) {
|
||||
|
||||
+4
-3
@@ -109,11 +109,12 @@ const recent = {
|
||||
|
||||
filesGrid.innerHTML = '';
|
||||
filesListView.innerHTML = `
|
||||
<div class="list-header">
|
||||
<div class="list-header recent-header">
|
||||
<div></div>
|
||||
<div data-i18n="files.name">Name</div>
|
||||
<div data-i18n="files.type">Type</div>
|
||||
<div data-i18n="files.size">Size</div>
|
||||
<div data-i18n="files.last_accessed">Last accessed</div>
|
||||
<div data-i18n="recent.accessed">Accessed</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -157,7 +158,7 @@ const recent = {
|
||||
// Determine icon and type
|
||||
let iconClass = 'fas fa-file';
|
||||
let iconSpecialClass = '';
|
||||
let typeLabel = 'Document';
|
||||
let typeLabel = window.i18n ? window.i18n.t('files.file_types.document') : 'Document';
|
||||
|
||||
if (file.mime_type) {
|
||||
if (file.mime_type.startsWith('image/')) {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// OxiCloud Service Worker
|
||||
const CACHE_NAME = 'oxicloud-cache-v10';
|
||||
const CACHE_NAME = 'oxicloud-cache-v11';
|
||||
const ASSETS_TO_CACHE = [
|
||||
'/',
|
||||
'/index.html',
|
||||
|
||||
Reference in New Issue
Block a user