fix(resources): wire missing created_by and updated_by

This commit is contained in:
Edouard Vanbelle
2026-07-20 19:52:51 +02:00
parent 4873a5e837
commit 931e27d09c
21 changed files with 140 additions and 47 deletions
@@ -1570,6 +1570,7 @@
.rl-ctx-item--disabled {
opacity: 0.5;
}
.rl-ctx-item--disabled:hover {
background: transparent;
}
-1
View File
@@ -74,4 +74,3 @@ export async function probeFolderAccess(id: string): Promise<boolean> {
inflight.set(id, p);
return p;
}
+1 -2
View File
@@ -366,8 +366,7 @@
<Button
icon="star-outline"
data-testid="favorites-batch-remove-btn"
onclick={() => sel.forEach(unfavorite)}
>{t('files.unfavorite', 'Remove favorite')}</Button
onclick={() => sel.forEach(unfavorite)}>{t('files.unfavorite', 'Remove favorite')}</Button
>
{/snippet}
</ResourceList>
@@ -26,7 +26,6 @@ vi.mock('$lib/api/endpoints/folders', () => ({ renameFolder: vi.fn(), deleteFold
vi.mock('$lib/stores/dialogs.svelte', () => ({ confirmDialog, promptDialog }));
import { fetchFavoritesPage, removeFavorite } from '$lib/api/endpoints/favorites';
import { deleteFile } from '$lib/api/endpoints/files';
import FavoritesPage from './+page.svelte';
const m = (fn: unknown) => fn as ReturnType<typeof vi.fn>;
+9 -6
View File
@@ -48,9 +48,12 @@
let reversed = $state(false);
const owners = useOwnerCache(resolveOwnerName);
// Envelope shape: `accessed_at` → `ctx.date`, `updated_by` → `ctx.ownerId`
// (Recent's provenance semantic — "who touched this recently" — differs
// from Favorites'/Files' `created_by`).
// Envelope shape: `accessed_at` → `ctx.date`, `created_by` → `ctx.ownerId`.
// Recent is a per-user view of items the caller accessed; the "who
// touched this last" (`updated_by`) semantic is real but adds noise
// (mostly the current user), so we align with Files / Favorites and
// show the original author instead. Cross-surface consistency wins
// over the finer-grained signal.
//
// Dotfile hiding is delegated to ResourceList via `showDotfileToggle`
// — the component reads `preferences.hideDotfiles` and drops matching
@@ -117,10 +120,10 @@
raw = reset ? page.items : [...raw, ...page.items];
primeContextPage(contextMap, reset, page.items, (it) => [
it.resource.id,
{ date: it.accessed_at, ownerId: it.resource.updated_by ?? null }
{ date: it.accessed_at, ownerId: it.resource.created_by ?? null }
]);
cursor = page.next_cursor;
void owners.resolve(page.items.map((i) => i.resource.updated_by));
void owners.resolve(page.items.map((i) => i.resource.created_by));
} catch (e) {
console.error('recent: load error', e);
error = t('errors_loadFailed', 'Failed to load items');
@@ -184,7 +187,7 @@
raw = [...raw.slice(0, idx), snapshot, ...raw.slice(idx)];
contextMap.set(item.id, {
date: snapshot.accessed_at,
ownerId: snapshot.resource.updated_by ?? null
ownerId: snapshot.resource.created_by ?? null
});
errorToast(e);
}
-1
View File
@@ -25,7 +25,6 @@ vi.mock('$lib/api/endpoints/folders', () => ({ renameFolder: vi.fn(), deleteFold
vi.mock('$lib/stores/dialogs.svelte', () => ({ confirmDialog, promptDialog }));
import { fetchRecentPage, clearRecent, removeFromRecent } from '$lib/api/endpoints/recent';
import { deleteFile } from '$lib/api/endpoints/files';
import RecentPage from './+page.svelte';
const m = (fn: unknown) => fn as ReturnType<typeof vi.fn>;
+16 -6
View File
@@ -300,17 +300,14 @@
standard action-bar sizing and reads consistently with
`/recent` and `/favorites` batch clusters.
-->
<Button
icon="undo"
data-testid="trash-batch-restore-btn"
onclick={() => sel.forEach(restore)}>{t('trash.restore', 'Restore')}</Button
<Button icon="undo" data-testid="trash-batch-restore-btn" onclick={() => sel.forEach(restore)}
>{t('trash.restore', 'Restore')}</Button
>
<Button
variant="danger"
icon="trash"
data-testid="trash-batch-delete-btn"
onclick={() => sel.forEach(purge)}
>{t('trash.delete', 'Delete permanently')}</Button
onclick={() => sel.forEach(purge)}>{t('trash.delete', 'Delete permanently')}</Button
>
{/snippet}
{#snippet rowBadge(_item, ctx)}
@@ -414,4 +411,17 @@
:global(.files-grid-view .file-item .action-cell .btn-action--delete:hover) {
color: var(--color-error-text);
}
/* List view: hide the expiry chip that ResourceList paints inside
`.file-icon__badge`. In list mode the same info is already in
the "Expires at" column (`dateCell` snippet above) — showing
the chip on the tiny row icon crops it and duplicates the
signal. Grid view keeps the chip: no dedicated column exists
there and the badge is the ONLY expiration surface on the
card. Scoped to trash because trash is the only section
emitting a rowBadge today; if another section starts using it,
this rule stays inert for them. */
:global(.files-list-view .file-item .file-icon__badge) {
display: none;
}
</style>