Merge pull request #629 from EdouardVanbelle/refactor/front-resource-list
Refactor(front) restore legacy frontend features
This commit is contained in:
@@ -127,6 +127,11 @@ pub struct FavoriteResourceRow {
|
||||
/// folder rows. Routes into `FileDto::content_hash` and feeds
|
||||
/// `File::compute_etag` to populate `FileDto::etag`.
|
||||
pub blob_hash: Option<String>,
|
||||
/// §14 provenance — who created the row. `None` when the creator
|
||||
/// was deleted (FK `ON DELETE SET NULL`).
|
||||
pub created_by: Option<Uuid>,
|
||||
/// §14 provenance — who last touched the row.
|
||||
pub updated_by: Option<Uuid>,
|
||||
/// `true` when `owner_id == requesting user_id`.
|
||||
pub is_owner: bool,
|
||||
pub favorited_at: DateTime<Utc>,
|
||||
|
||||
@@ -219,6 +219,13 @@ pub struct FolderResourceRow {
|
||||
/// on the REST `/api/folders/{id}/resources` listing so API
|
||||
/// consumers can issue conditional requests against listed files.
|
||||
pub blob_hash: Option<String>,
|
||||
/// §14 provenance — who created the row. `None` when the creator was
|
||||
/// deleted (FK `ON DELETE SET NULL`). Populates
|
||||
/// `FileDto::created_by` / `FolderDto::created_by` on the listing so
|
||||
/// the UI can render the owner column without a follow-up query.
|
||||
pub created_by: Option<Uuid>,
|
||||
/// §14 provenance — who last touched the row.
|
||||
pub updated_by: Option<Uuid>,
|
||||
// Pre-computed sort fields — returned by the SQL for cursor construction.
|
||||
/// `LOWER(name)` used by `name`/`type` sorts.
|
||||
pub sort_str: String,
|
||||
|
||||
@@ -112,6 +112,16 @@ pub struct RecentResourceRow {
|
||||
/// folder rows. Feeds `File::compute_etag` so this listing's
|
||||
/// `etag` matches GET/HEAD/PROPFIND for the same file.
|
||||
pub blob_hash: Option<String>,
|
||||
/// §14 provenance — who created the row. `None` when the creator
|
||||
/// was deleted (FK `ON DELETE SET NULL`). Powers the owner column
|
||||
/// on the `/recent` UI (aligned with `/files` and `/favorites`
|
||||
/// for cross-surface consistency, rather than the finer-grained
|
||||
/// but noisier "who touched this last" signal).
|
||||
pub created_by: Option<Uuid>,
|
||||
/// §14 provenance — who last touched the row. Not currently
|
||||
/// consumed by the UI but surfaced for API parity with the other
|
||||
/// listing endpoints.
|
||||
pub updated_by: Option<Uuid>,
|
||||
/// `true` when `owner_id == requesting user_id`.
|
||||
pub is_owner: bool,
|
||||
pub accessed_at: DateTime<Utc>,
|
||||
|
||||
@@ -71,6 +71,12 @@ pub struct TrashResourceRow {
|
||||
/// same file (restorable trash items are conditional-request
|
||||
/// targets too).
|
||||
pub blob_hash: Option<String>,
|
||||
/// §14 provenance — who created the row. `None` when the creator
|
||||
/// was deleted (FK `ON DELETE SET NULL`).
|
||||
pub created_by: Option<Uuid>,
|
||||
/// §14 provenance — who last touched the row (includes the trash
|
||||
/// action itself, which stamps `updated_by = caller_id`).
|
||||
pub updated_by: Option<Uuid>,
|
||||
pub trashed_at: DateTime<Utc>,
|
||||
pub deletion_date: DateTime<Utc>,
|
||||
/// Original location path (for folders: `path`; for files: `parent.path || '/' || name`).
|
||||
|
||||
@@ -888,9 +888,8 @@ fn row_to_item_dto(row: TrashResourceRow) -> TrashResourceItemDto {
|
||||
icon_class: intern_display("fas fa-folder"),
|
||||
icon_special_class: intern_display("folder-icon"),
|
||||
category: intern_display("Folder"),
|
||||
// §14 provenance not selected by the trash listing query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
TrashResourceItemDto {
|
||||
resource_type: ResourceTypeDto::Folder,
|
||||
@@ -932,9 +931,8 @@ fn row_to_item_dto(row: TrashResourceRow) -> TrashResourceItemDto {
|
||||
sort_date: None,
|
||||
content_hash,
|
||||
etag,
|
||||
// §14 provenance not selected by the trash listing query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
TrashResourceItemDto {
|
||||
resource_type: ResourceTypeDto::File,
|
||||
|
||||
@@ -318,6 +318,7 @@ impl FavoritesRepositoryPort for FavoritesPgRepository {
|
||||
fld.drive_id AS drive_id,
|
||||
NULL::text AS blob_hash,
|
||||
fld.created_by AS created_by,
|
||||
fld.updated_by AS updated_by,
|
||||
EXISTS (
|
||||
SELECT 1 FROM storage.role_grants g
|
||||
WHERE g.resource_type = 'drive'
|
||||
@@ -350,6 +351,7 @@ impl FavoritesRepositoryPort for FavoritesPgRepository {
|
||||
f.drive_id AS drive_id,
|
||||
f.blob_hash,
|
||||
f.created_by AS created_by,
|
||||
f.updated_by AS updated_by,
|
||||
EXISTS (
|
||||
SELECT 1 FROM storage.role_grants g
|
||||
WHERE g.resource_type = 'drive'
|
||||
@@ -529,7 +531,8 @@ impl FavoritesRepositoryPort for FavoritesPgRepository {
|
||||
SELECT
|
||||
r.resource_type, r.resource_id, r.name, r.parent_id,
|
||||
r.mime_type, r.size, r.resource_created_at, r.modified_at,
|
||||
r.drive_id, r.is_owner, r.favorited_at, r.resource_path,
|
||||
r.drive_id, r.blob_hash, r.created_by, r.updated_by,
|
||||
r.is_owner, r.favorited_at, r.resource_path,
|
||||
r.sort_str, r.type_order, r.folder_first{username_col}
|
||||
FROM resources r
|
||||
{user_join}
|
||||
@@ -602,6 +605,8 @@ LIMIT $6"
|
||||
modified_at: row.get("modified_at"),
|
||||
drive_id: row.get("drive_id"),
|
||||
blob_hash: row.try_get("blob_hash").ok(),
|
||||
created_by: row.try_get("created_by").ok(),
|
||||
updated_by: row.try_get("updated_by").ok(),
|
||||
is_owner: row.try_get("is_owner").unwrap_or(false),
|
||||
favorited_at: row.get("favorited_at"),
|
||||
path: row.try_get("resource_path").ok(),
|
||||
|
||||
@@ -1446,6 +1446,8 @@ impl FolderDbRepository {
|
||||
f.updated_at AS modified_at,
|
||||
f.drive_id,
|
||||
NULL::text AS blob_hash,
|
||||
f.created_by,
|
||||
f.updated_by,
|
||||
LOWER(f.name) AS sort_str,
|
||||
0::bigint AS type_order,
|
||||
0::int AS folder_first
|
||||
@@ -1465,6 +1467,8 @@ impl FolderDbRepository {
|
||||
fm.updated_at AS modified_at,
|
||||
fm.drive_id,
|
||||
fm.blob_hash,
|
||||
fm.created_by,
|
||||
fm.updated_by,
|
||||
LOWER(fm.name) AS sort_str,
|
||||
fm.category_order::bigint AS type_order,
|
||||
1::int AS folder_first
|
||||
@@ -1655,6 +1659,7 @@ impl FolderDbRepository {
|
||||
let sql = format!(
|
||||
"SELECT resource_type, id, name, folder_id, mime_type, size, \
|
||||
created_at, modified_at, drive_id, blob_hash, \
|
||||
created_by, updated_by, \
|
||||
sort_str, type_order, folder_first \
|
||||
FROM ({inner}) r \
|
||||
{outer_order} \
|
||||
@@ -1663,6 +1668,7 @@ impl FolderDbRepository {
|
||||
|
||||
// Row: (resource_type, id, name, folder_id, mime_type, size,
|
||||
// created_at, modified_at, drive_id, blob_hash,
|
||||
// created_by, updated_by,
|
||||
// sort_str, type_order, folder_first)
|
||||
type Row = (
|
||||
String,
|
||||
@@ -1675,6 +1681,8 @@ impl FolderDbRepository {
|
||||
chrono::DateTime<chrono::Utc>,
|
||||
Uuid, // drive_id
|
||||
Option<String>,
|
||||
Option<Uuid>, // created_by
|
||||
Option<Uuid>, // updated_by
|
||||
String,
|
||||
i64,
|
||||
i32,
|
||||
@@ -1706,9 +1714,11 @@ impl FolderDbRepository {
|
||||
modified_at: r.7,
|
||||
drive_id: r.8,
|
||||
blob_hash: r.9,
|
||||
sort_str: r.10,
|
||||
type_order: r.11,
|
||||
folder_first: r.12,
|
||||
created_by: r.10,
|
||||
updated_by: r.11,
|
||||
sort_str: r.12,
|
||||
type_order: r.13,
|
||||
folder_first: r.14,
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
@@ -244,6 +244,7 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
|
||||
fld.drive_id AS drive_id,
|
||||
NULL::text AS blob_hash,
|
||||
fld.created_by AS created_by,
|
||||
fld.updated_by AS updated_by,
|
||||
EXISTS (
|
||||
SELECT 1 FROM storage.role_grants g
|
||||
WHERE g.resource_type = 'drive'
|
||||
@@ -276,6 +277,7 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
|
||||
f.drive_id AS drive_id,
|
||||
f.blob_hash,
|
||||
f.created_by AS created_by,
|
||||
f.updated_by AS updated_by,
|
||||
EXISTS (
|
||||
SELECT 1 FROM storage.role_grants g
|
||||
WHERE g.resource_type = 'drive'
|
||||
@@ -454,7 +456,8 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
|
||||
SELECT
|
||||
r.resource_type, r.resource_id, r.name, r.parent_id,
|
||||
r.mime_type, r.size, r.resource_created_at, r.modified_at,
|
||||
r.drive_id, r.is_owner, r.accessed_at, r.resource_path,
|
||||
r.drive_id, r.blob_hash, r.created_by, r.updated_by,
|
||||
r.is_owner, r.accessed_at, r.resource_path,
|
||||
r.sort_str, r.type_order, r.folder_first{username_col}
|
||||
FROM resources r
|
||||
{user_join}
|
||||
@@ -531,6 +534,8 @@ LIMIT $6"
|
||||
modified_at: row.get("modified_at"),
|
||||
drive_id: row.get("drive_id"),
|
||||
blob_hash: row.try_get("blob_hash").ok(),
|
||||
created_by: row.try_get("created_by").ok(),
|
||||
updated_by: row.try_get("updated_by").ok(),
|
||||
is_owner: row.try_get("is_owner").unwrap_or(false),
|
||||
accessed_at: row.get("accessed_at"),
|
||||
path: row.try_get("resource_path").ok(),
|
||||
|
||||
@@ -367,6 +367,8 @@ impl TrashDbRepository {
|
||||
fld.updated_at AS modified_at,
|
||||
fld.drive_id AS drive_id,
|
||||
NULL::text AS blob_hash,
|
||||
fld.created_by AS created_by,
|
||||
fld.updated_by AS updated_by,
|
||||
fld.trashed_at AS trashed_at,
|
||||
(fld.trashed_at + ($7::int * INTERVAL '1 day')) AS deletion_date,
|
||||
fld.path::text AS resource_path,
|
||||
@@ -393,6 +395,8 @@ impl TrashDbRepository {
|
||||
f.updated_at AS modified_at,
|
||||
f.drive_id AS drive_id,
|
||||
f.blob_hash,
|
||||
f.created_by AS created_by,
|
||||
f.updated_by AS updated_by,
|
||||
f.trashed_at AS trashed_at,
|
||||
(f.trashed_at + ($7::int * INTERVAL '1 day')) AS deletion_date,
|
||||
COALESCE(pfld.path::text || '/' || f.name, f.name) AS resource_path,
|
||||
@@ -522,7 +526,8 @@ impl TrashDbRepository {
|
||||
SELECT
|
||||
r.resource_type, r.resource_id, r.name, r.parent_id,
|
||||
r.mime_type, r.size, r.resource_created_at, r.modified_at,
|
||||
r.drive_id, r.trashed_at, r.deletion_date, r.resource_path,
|
||||
r.drive_id, r.blob_hash, r.created_by, r.updated_by,
|
||||
r.trashed_at, r.deletion_date, r.resource_path,
|
||||
r.sort_str, r.type_order, r.folder_first
|
||||
FROM resources r
|
||||
{keyset}
|
||||
@@ -581,6 +586,8 @@ LIMIT $6"
|
||||
modified_at: row.get("modified_at"),
|
||||
drive_id: row.get("drive_id"),
|
||||
blob_hash: row.try_get("blob_hash").ok(),
|
||||
created_by: row.try_get("created_by").ok(),
|
||||
updated_by: row.try_get("updated_by").ok(),
|
||||
trashed_at,
|
||||
deletion_date,
|
||||
path: row.try_get("resource_path").ok(),
|
||||
|
||||
@@ -217,9 +217,8 @@ pub async fn list_favorites_resources(
|
||||
icon_class: intern_display("fas fa-folder"),
|
||||
icon_special_class: intern_display("folder-icon"),
|
||||
category: intern_display("Folder"),
|
||||
// §14 provenance not selected by the favorites query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
FavoritesResourceItemDto {
|
||||
resource_type: ResourceTypeDto::Folder,
|
||||
@@ -266,9 +265,8 @@ pub async fn list_favorites_resources(
|
||||
sort_date: None,
|
||||
content_hash,
|
||||
etag,
|
||||
// §14 provenance not selected by the favorites query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
FavoritesResourceItemDto {
|
||||
resource_type: ResourceTypeDto::File,
|
||||
|
||||
@@ -487,9 +487,8 @@ pub async fn list_folder_resources(
|
||||
icon_class: intern_display("fas fa-folder"),
|
||||
icon_special_class: intern_display("folder-icon"),
|
||||
category: intern_display("Folder"),
|
||||
// §14 provenance not selected by the resources query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
FolderResourceItemDto {
|
||||
resource_type: ResourceTypeDto::Folder,
|
||||
@@ -539,9 +538,8 @@ pub async fn list_folder_resources(
|
||||
sort_date: None,
|
||||
content_hash,
|
||||
etag,
|
||||
// §14 provenance not selected by the resources query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
FolderResourceItemDto {
|
||||
resource_type: ResourceTypeDto::File,
|
||||
|
||||
@@ -237,9 +237,8 @@ pub async fn list_recent_resources(
|
||||
icon_class: intern_display("fas fa-folder"),
|
||||
icon_special_class: intern_display("folder-icon"),
|
||||
category: intern_display("Folder"),
|
||||
// §14 provenance not selected by the recents query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
RecentResourceItemDto {
|
||||
resource_type: ResourceTypeDto::Folder,
|
||||
@@ -284,9 +283,8 @@ pub async fn list_recent_resources(
|
||||
sort_date: None,
|
||||
content_hash,
|
||||
etag,
|
||||
// §14 provenance not selected by the recents query.
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
created_by: row.created_by,
|
||||
updated_by: row.updated_by,
|
||||
};
|
||||
RecentResourceItemDto {
|
||||
resource_type: ResourceTypeDto::File,
|
||||
|
||||
Reference in New Issue
Block a user