feat: frontend MVP — auth, timeline, upload, albums, admin, image viewer
Backend: - user roles (DB + JWT + first-user-is-admin) - volume-aware file resolver (multi-volume asset serving) - directory scanner uses volume URI directly - date-summary endpoint (capture date from EXIF) - timeline ordered by capture date - list endpoints: volumes, plugins, pipelines, library paths - delete endpoints: volumes, library paths - configurable upload body limit (MAX_UPLOAD_BYTES) Frontend: - auth: login/register, token refresh, role-based admin gate - timeline: date-grouped grid, infinite scroll, date scrubber - image viewer: fullscreen zoom/pan/pinch, metadata sidebar - upload: drag-drop, sequential upload, progress tracking - albums: create, add/remove photos, asset picker dialog - admin: storage (import library), jobs (pagination, error details), plugins (list + toggle), pipelines, sidecars, duplicates - multi-select mode with add-to-album action - TanStack Query for all data fetching
This commit is contained in:
@@ -6,6 +6,7 @@ pub struct UserResponse {
|
||||
pub id: Uuid,
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub role: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
@@ -22,6 +23,7 @@ impl UserResponse {
|
||||
id: *user.id.as_uuid(),
|
||||
username: user.username.clone(),
|
||||
email: user.email.to_string(),
|
||||
role: user.role.clone(),
|
||||
created_at: user.created_at,
|
||||
}
|
||||
}
|
||||
@@ -34,6 +36,7 @@ pub struct AlbumResponse {
|
||||
pub description: String,
|
||||
pub creator_id: Uuid,
|
||||
pub asset_count: usize,
|
||||
pub asset_ids: Vec<Uuid>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
@@ -45,6 +48,7 @@ impl AlbumResponse {
|
||||
description: album.description.clone(),
|
||||
creator_id: *album.creator_user_id.as_uuid(),
|
||||
asset_count: album.asset_count(),
|
||||
asset_ids: album.entries.iter().map(|e| *e.asset_id.as_uuid()).collect(),
|
||||
created_at: *album.created_at.as_datetime(),
|
||||
}
|
||||
}
|
||||
@@ -84,6 +88,17 @@ impl AssetResponse {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct DateSummaryResponse {
|
||||
pub dates: Vec<DateCountEntry>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct DateCountEntry {
|
||||
pub date: String,
|
||||
pub count: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct TimelineResponse {
|
||||
pub assets: Vec<AssetResponse>,
|
||||
@@ -349,6 +364,7 @@ pub struct JobResponse {
|
||||
pub status: String,
|
||||
pub priority: u32,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl JobResponse {
|
||||
@@ -359,6 +375,7 @@ impl JobResponse {
|
||||
status: format!("{:?}", job.status),
|
||||
priority: job.priority,
|
||||
created_at: *job.created_at.as_datetime(),
|
||||
error_message: job.error_message.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user