From c56d51707ac29485be34d282fe300ec6c0291548 Mon Sep 17 00:00:00 2001 From: Jackz Date: Sun, 20 Apr 2025 08:22:29 -0500 Subject: [PATCH 1/3] Fix login again --- src/routes/ui/auth/login.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/ui/auth/login.rs b/src/routes/ui/auth/login.rs index 5260a00..a57e525 100644 --- a/src/routes/ui/auth/login.rs +++ b/src/routes/ui/auth/login.rs @@ -90,7 +90,7 @@ pub async fn handler( let ctx = context! { route: route.uri.path(), csrf_token: csrf_token, - form: &Context::default(), + form: &form.context, return_to, meta: meta.inner() }; From 6eb900b814e61a8498bd063870e7724f25a994eb Mon Sep 17 00:00:00 2001 From: Jackz Date: Sun, 20 Apr 2025 08:22:44 -0500 Subject: [PATCH 2/3] Move options up --- src/routes/ui/user.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/routes/ui/user.rs b/src/routes/ui/user.rs index 98303d9..9608462 100644 --- a/src/routes/ui/user.rs +++ b/src/routes/ui/user.rs @@ -46,6 +46,13 @@ pub async fn list_library_files( sort_dir: Option, display: Option, ) -> Result { + let options = FileDisplayOptions { + // TODO: prevent bad values + // TODO: fix login errror msg -------_____------ + sort_key: validate_option(sort_key, FILE_CONSTANTS.sort_keys, "name"), + sort_dir: validate_option(sort_dir, &["asc", "desc"], "asc"), + display: validate_option(display, FILE_CONSTANTS.display_options, "list"), + }; let libs = libraries.lock().await; let library = libs.get(library_id).await?; let files = library.list_files(&PathBuf::from(&path)).await @@ -82,13 +89,7 @@ pub async fn list_library_files( parent, path_segments: segments, // TODO: have struct? - options: FileDisplayOptions { - // TODO: prevent bad values - // TODO: fix login errror msg -------_____------ - sort_key: validate_option(sort_key, FILE_CONSTANTS.sort_keys, "name"), - sort_dir: validate_option(sort_dir, &["asc", "desc"], "asc"), - display: validate_option(display, FILE_CONSTANTS.display_options, "list"), - }, + options, DATA: FILE_CONSTANTS })) } From d1cf5d30384f7f7463cb78a8f46bbf05b5cb678c Mon Sep 17 00:00:00 2001 From: Jackz Date: Sun, 20 Apr 2025 08:48:33 -0500 Subject: [PATCH 3/3] Implement folder sorting --- src/objs/library.rs | 42 ++++++++++++++++++++++++++++++++--- src/routes/api/library.rs | 3 ++- src/routes/ui/user.rs | 7 +++++- src/storage.rs | 2 +- templates/auth/login.html.hbs | 2 +- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/objs/library.rs b/src/objs/library.rs index 6d8d68e..a4a3747 100644 --- a/src/objs/library.rs +++ b/src/objs/library.rs @@ -1,7 +1,9 @@ +use std::cmp::Ordering; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; -use anyhow::Error; +use anyhow::{anyhow, Error}; +use log::trace; use rocket::response::stream::ReaderStream; use rocket::serde::Serialize; use tokio::io::BufStream; @@ -17,6 +19,21 @@ pub struct Library { repo: RepoContainer, } +/// The direction of sort and the field to sort by +#[derive(PartialEq, Debug)] +pub struct ListOptions { + pub sort_field: Option, + pub sort_descending: Option +} +impl Default for ListOptions { + fn default() -> Self { + ListOptions { + sort_field: Some("name".to_string()), + sort_descending: Some(false), + } + } +} + impl Library { pub fn new(library_model: LibraryModel, repo: RepoContainer) -> Library { Library { @@ -49,9 +66,28 @@ impl Library { repo.backend.read_file(&self.model.id.to_string(), rel_path) } - pub async fn list_files(&self, rel_path: &PathBuf) -> Result, anyhow::Error> { + pub async fn list_files(&self, rel_path: &PathBuf, options: ListOptions) -> Result, anyhow::Error> { let repo = self.repo.read().await; - repo.backend.list_files(&self.model.id.to_string(), rel_path) + let mut list = repo.backend.list_files(&self.model.id.to_string(), rel_path)?; + let field = options.sort_field.unwrap_or("name".to_string()); + let descending = options.sort_descending.unwrap_or(false); + match field.as_str() { + "name" => list.sort_by(|a, b| { + if a._type == FileType::File && b._type != FileType::File { Ordering::Greater } + else if a._type != FileType::File && b._type == FileType::File { Ordering::Less } + else { a.path.cmp(&b.path) } + }), + "size" => list.sort_by(|a, b| { + if a._type == FileType::File && b._type != FileType::File { Ordering::Greater } + else if a._type != FileType::File && b._type == FileType::File { Ordering::Less } + else { a.size.cmp(&b.size) } + }), + _ => return Err(anyhow!("Unsupported field")) + } + if descending { + list.reverse(); + } + Ok(list) } pub async fn delete_file(&self, rel_path: &PathBuf) -> Result<(), anyhow::Error> { diff --git a/src/routes/api/library.rs b/src/routes/api/library.rs index 77ec866..861b91d 100644 --- a/src/routes/api/library.rs +++ b/src/routes/api/library.rs @@ -17,6 +17,7 @@ use crate::managers::libraries::LibraryManager; use crate::managers::repos::RepoManager; use crate::models::library::{LibraryModel, LibraryWithRepoModel}; use crate::models::user; +use crate::objs::library::ListOptions; use crate::storage::{FileEntry, FileType}; use crate::util::{JsonErrorResponse, ResponseError}; #[get("/")] @@ -30,7 +31,7 @@ pub(crate) async fn get_file(pool: &State, library_id: &str) -> Result>>, library_id: &str, path: &str) -> Result>, ResponseError> { let libs = libraries.lock().await; let library = libs.get(library_id).await?; - library.list_files(&PathBuf::from(path)).await + library.list_files(&PathBuf::from(path), ListOptions::default()).await .map(|files| Json(files)) .map_err(|e| ResponseError::InternalServerError(JsonErrorResponse { code: "STORAGE_ERROR".to_string(), diff --git a/src/routes/ui/user.rs b/src/routes/ui/user.rs index 9608462..33bb906 100644 --- a/src/routes/ui/user.rs +++ b/src/routes/ui/user.rs @@ -17,6 +17,7 @@ use tokio::sync::Mutex; use crate::consts::FILE_CONSTANTS; use crate::guards::{AuthUser}; use crate::managers::libraries::LibraryManager; +use crate::objs::library::ListOptions; use crate::routes::ui::auth; use crate::util::{JsonErrorResponse, ResponseError}; @@ -55,7 +56,11 @@ pub async fn list_library_files( }; let libs = libraries.lock().await; let library = libs.get(library_id).await?; - let files = library.list_files(&PathBuf::from(&path)).await + let list_options = ListOptions { + sort_field: Some(options.sort_key.clone()), + sort_descending: Some(options.sort_dir == "desc"), + }; + let files = library.list_files(&PathBuf::from(&path), list_options).await .map_err(|e| ResponseError::InternalServerError(JsonErrorResponse { code: "STORAGE_ERROR".to_string(), message: e.to_string(), diff --git a/src/storage.rs b/src/storage.rs index 6e8f16c..91cc881 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -19,7 +19,7 @@ pub enum StorageBackendMap { S3(S3Storage) } -#[derive(Debug, Serialize, Deserialize, FromFormField)] +#[derive(Debug, Serialize, Deserialize, FromFormField, PartialEq)] #[serde(rename_all = "lowercase")] pub enum FileType { File, diff --git a/templates/auth/login.html.hbs b/templates/auth/login.html.hbs index a585cb0..0ad8b67 100644 --- a/templates/auth/login.html.hbs +++ b/templates/auth/login.html.hbs @@ -24,7 +24,7 @@
- +