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:
Dionisio
2026-02-14 11:06:29 +01:00
parent 1672889044
commit 9290aea591
7 changed files with 57 additions and 17 deletions
+4
View File
@@ -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;
+4
View File
@@ -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;
+6 -2
View File
@@ -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
View File
@@ -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');
+3 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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',