diff --git a/src/consts.rs b/src/consts.rs index 8569b80..5332850 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,5 +1,7 @@ +use std::cell::OnceCell; use std::time::Duration; use rocket::data::ByteUnit; +use rocket::serde::Serialize; /// The maximum amount of bytes that can be uploaded at once pub const MAX_UPLOAD_SIZE: ByteUnit = ByteUnit::Mebibyte(100_000); @@ -9,4 +11,17 @@ pub const ENCRYPTION_ROUNDS: u32 = 12; pub const SESSION_LIFETIME_SECONDS: u64 = 3600 * 24 * 14; // 14 days -pub const SESSION_COOKIE_NAME: &'static str = "storage-session"; \ No newline at end of file +pub const SESSION_COOKIE_NAME: &'static str = "storage-session"; + + + +#[derive(Serialize)] +pub struct FileConstants<'a> { + pub display_options: &'a[&'a str], + pub sort_keys: &'a[&'a str], +} +pub const FILE_CONSTANTS: FileConstants = FileConstants { + display_options: &["list", "grid"], + sort_keys: &["name", "last_modified", "size"], +}; + diff --git a/src/main.rs b/src/main.rs index ca5cf2d..8d309c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,6 +76,7 @@ async fn rocket() -> _ { warn!("warn"); error!("error"); + // TODO: move to own fn let pool = PgPoolOptions::new() .max_connections(5) .connect(std::env::var("DATABASE_URL").unwrap().as_str()) @@ -96,6 +97,7 @@ async fn rocket() -> _ { Arc::new(Mutex::new(manager)) }; + // TODO: move to own func let memory_store: MemoryStore:: = MemoryStore::default(); let store: SessionStore = SessionStore { store: Box::new(memory_store), @@ -109,7 +111,8 @@ async fn rocket() -> _ { // slash which prevents the cookie from being sent for `example.com/myapp2/`). .path("/") }; - + + // TODO: move to constants let metadata = GlobalMetadata { app_name: env!("CARGO_PKG_NAME").to_string(), app_version: env!("CARGO_PKG_VERSION").to_string(), diff --git a/src/routes/ui/user.rs b/src/routes/ui/user.rs index 47f3271..98303d9 100644 --- a/src/routes/ui/user.rs +++ b/src/routes/ui/user.rs @@ -1,3 +1,4 @@ +use std::cell::OnceCell; use std::io::Cursor; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -13,6 +14,7 @@ use rocket_dyn_templates::{context, Template}; use serde::Serialize; use serde_json::Value; use tokio::sync::Mutex; +use crate::consts::FILE_CONSTANTS; use crate::guards::{AuthUser}; use crate::managers::libraries::LibraryManager; use crate::routes::ui::auth; @@ -30,14 +32,20 @@ pub async fn redirect_list_library_files(user: AuthUser, libraries: &State/<_>/")] -pub async fn list_library_files(user: AuthUser, route: &Route, libraries: &State>>, library_id: &str, path: PathBuf) - -> Result -{ +#[get("/library//<_>/?&&")] +pub async fn list_library_files( + user: AuthUser, + route: &Route, + libraries: &State>>, + library_id: &str, + path: PathBuf, + sort_key: Option, + sort_dir: Option, + display: Option, +) -> Result { let libs = libraries.lock().await; let library = libs.get(library_id).await?; let files = library.list_files(&PathBuf::from(&path)).await @@ -72,10 +80,36 @@ pub async fn list_library_files(user: AuthUser, route: &Route, libraries: &State library: library.model(), files: files, parent, - path_segments: segments + 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"), + }, + DATA: FILE_CONSTANTS })) } +/// Checks if option is in list of valid values, if not returns default_value +fn validate_option(option: Option, valid_values: &[&str], default_value: &str) -> String { + if let Some(option) = option { + if valid_values.contains(&&*option) { + return option.to_string() + } + } + default_value.to_string() +} + +#[derive(Serialize)] +struct FileDisplayOptions { + sort_key: String, + sort_dir: String, + display: String +} + #[derive(Debug, Serialize)] struct PathSegmentPiece { pub path: PathBuf, diff --git a/src/storage.rs b/src/storage.rs index 738a67c..6e8f16c 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -6,6 +6,7 @@ use std::io::BufReader; use std::path::PathBuf; use anyhow::{anyhow, Error}; use int_enum::IntEnum; +use rocket::FromFormField; use rocket::serde::json::Json; use rocket::serde::{Deserialize, Serialize}; use serde_json::Value; @@ -18,7 +19,7 @@ pub enum StorageBackendMap { S3(S3Storage) } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, FromFormField)] #[serde(rename_all = "lowercase")] pub enum FileType { File, diff --git a/templates/libraries.html.hbs b/templates/libraries.html.hbs index 70910c6..84aed15 100644 --- a/templates/libraries.html.hbs +++ b/templates/libraries.html.hbs @@ -36,9 +36,9 @@ @@ -57,7 +60,7 @@ - Sort by Name (asc) + Sort by {{ options.sort_key }} ({{ options.sort_dir }}) @@ -65,12 +68,20 @@ @@ -166,6 +177,7 @@ -{{!-- --}} {{/inline}} {{/layouts/main}}