feat(drive): move UI to {created,updated}_by

This commit is contained in:
Edouard Vanbelle
2026-07-03 00:31:36 +02:00
parent 206a780494
commit 29bcf48eb7
13 changed files with 59 additions and 6 deletions
+21
View File
@@ -29,7 +29,22 @@ export interface FolderItem {
// hierarchy fields (including owner_id) for non-owner callers.
// Backend serialises `Option<String>` (folder_dto.rs:53); this
// type just tells the truth about the wire.
//
// Deprecated post-D7 (frontend cutover): callers should prefer
// `created_by` / `updated_by` instead — they carry §14 provenance
// and survive the drop of `storage.folders.user_id`. The
// `owner_id` field will be removed from the wire once every
// callsite has moved.
owner_id: string | null;
// §14 provenance — who originally created the folder. `null` when
// the creating user has since been deleted (backend FK is
// `ON DELETE SET NULL`). Preferred over `owner_id` on the Files
// browser owner column and the Favorites / Shared surfaces.
created_by: string | null;
// §14 provenance — who last touched the folder (rename / move /
// metadata change). Preferred over `owner_id` on the Recent
// surface, where "who touched this recently" is the intent.
updated_by: string | null;
parent_id: string | null;
path: string;
etag: string;
@@ -46,7 +61,13 @@ export interface FileItem {
name: string;
// `null` on share-recipient responses (same as FolderItem above).
// Backend serialises `Option<String>` at file_dto.rs:59.
//
// Deprecated post-D7 (frontend cutover): prefer `created_by` /
// `updated_by` as documented on `FolderItem`.
owner_id: string | null;
// §14 provenance — see FolderItem for semantics.
created_by: string | null;
updated_by: string | null;
folder_id: string;
path: string;
size: number;
@@ -29,6 +29,8 @@ function file(over: Record<string, unknown> = {}) {
category: 'Image',
folder_id: '',
owner_id: '',
created_by: null,
updated_by: null,
path: '',
size: 1,
modified_at: 0,
@@ -58,6 +58,8 @@ function folder(id: string, name: string) {
modified_at: 0,
name,
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
parent_id: 'home',
path: '/' + name,
etag: 'e'
@@ -21,6 +21,8 @@ function item(id: string) {
category: 'Image',
folder_id: '',
owner_id: '',
created_by: null,
updated_by: null,
path: '',
size: 1,
modified_at: 0,
+2
View File
@@ -31,6 +31,8 @@ export function minimalPhotoItem(id: string): FileItem {
modified_at: 0,
name: '',
owner_id: '',
created_by: null,
updated_by: null,
folder_id: '',
path: '',
size: 0,
+6 -2
View File
@@ -40,7 +40,11 @@
const entries = $derived(
raw.map((it): ResourceEntry => {
const isFile = it.resource_type === 'file';
const ownerId = it.resource.owner_id ?? null;
// §14 provenance — prefer `created_by` (who put the item
// into the system) over the deprecated `owner_id`. Fall
// back to `owner_id` for pre-D7 rows whose `created_by`
// column wasn't backfilled.
const ownerId = it.resource.created_by ?? it.resource.owner_id ?? null;
return {
id: it.resource.id,
name: it.resource.name,
@@ -106,7 +110,7 @@
});
raw = reset ? page.items : [...raw, ...page.items];
cursor = page.next_cursor;
void owners.resolve(page.items.map((i) => i.resource.owner_id));
void owners.resolve(page.items.map((i) => i.resource.created_by ?? i.resource.owner_id));
} catch (e) {
console.error('favorites: load error', e);
error = t('errors_loadFailed', 'Failed to load items');
@@ -42,6 +42,8 @@ function withOneFile() {
modified_at: 0,
name: 'photo.png',
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
folder_id: 'root',
path: '/photo.png',
size: 10,
@@ -1797,7 +1797,9 @@
<div class="grid-meta">
<span class="grid-meta__date">{relativeTimeAgo(folder.modified_at)}</span>
</div>
<div class="owner-cell">{ownerLabel(folder.owner_id, session.user?.id ?? null)}</div>
<div class="owner-cell">
{ownerLabel(folder.created_by ?? folder.owner_id, session.user?.id ?? null)}
</div>
<div class="type-cell">{t('files.file_types.folder', 'Folder')}</div>
<div class="size-cell">—</div>
<div class="date-cell">{formatDate(folder.modified_at)}</div>
@@ -1927,7 +1929,9 @@
<span class="grid-meta__date">{relativeTimeAgo(file.modified_at)}</span>
{#if file.size != null}<span class="grid-meta__size">{formatBytes(file.size)}</span>{/if}
</div>
<div class="owner-cell">{ownerLabel(file.owner_id, session.user?.id ?? null)}</div>
<div class="owner-cell">
{ownerLabel(file.created_by ?? file.owner_id, session.user?.id ?? null)}
</div>
<div class="type-cell">{typeLabel(file.category)}</div>
<div class="size-cell">{file.size != null ? formatBytes(file.size) : ''}</div>
<div class="date-cell">{formatDate(file.modified_at)}</div>
+4
View File
@@ -91,6 +91,8 @@ function fileItem(id: string, name: string) {
modified_at: 0,
name,
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
folder_id: 'home',
path: '/' + name,
size: 4,
@@ -111,6 +113,8 @@ function folderItem(id: string, name: string) {
modified_at: 0,
name,
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
parent_id: 'home',
path: '/' + name,
etag: 'e'
+2
View File
@@ -35,6 +35,8 @@ function photo(id: string) {
modified_at: 0,
name: id + '.jpg',
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
folder_id: 'home',
path: '/' + id + '.jpg',
size: 100,
+6 -2
View File
@@ -42,7 +42,11 @@
const entries = $derived(
raw.map((it): ResourceEntry => {
const isFile = it.resource_type === 'file';
const ownerId = it.resource.owner_id ?? null;
// §14 provenance — Recent's mental model is "who touched
// this recently", so `updated_by` (the last mutator) is
// preferred over `created_by` (who put it in). Fall back
// to `owner_id` for pre-D7 rows with no provenance.
const ownerId = it.resource.updated_by ?? it.resource.owner_id ?? null;
return {
id: it.resource.id,
name: it.resource.name,
@@ -118,7 +122,7 @@
});
raw = reset ? page.items : [...raw, ...page.items];
cursor = page.next_cursor;
void owners.resolve(page.items.map((i) => i.resource.owner_id));
void owners.resolve(page.items.map((i) => i.resource.updated_by ?? i.resource.owner_id));
} catch (e) {
console.error('recent: load error', e);
error = t('errors_loadFailed', 'Failed to load items');
+2
View File
@@ -46,6 +46,8 @@ function withOneFile() {
modified_at: 0,
name: 'notes.txt',
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
folder_id: 'root',
path: '/notes.txt',
size: 4,
+2
View File
@@ -47,6 +47,8 @@ function grantItem() {
modified_at: 0,
name: 'Docs',
owner_id: 'me',
created_by: 'me',
updated_by: 'me',
parent_id: null,
path: '/Docs',
etag: 'e'