From 6e95f942f1ae6c9c120c95eeb8b1aae1379bcd54 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Mon, 25 Feb 2019 20:22:58 +0100 Subject: Removed sorting from CLI + added sorting from HTML --- src/args.rs | 18 ------- src/listing.rs | 151 +++++++++++++++++++++++++++++++++++--------------------- src/main.rs | 17 +------ src/renderer.rs | 34 +++++++++++-- 4 files changed, 128 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/args.rs b/src/args.rs index 637c224..4f0dbf7 100644 --- a/src/args.rs +++ b/src/args.rs @@ -3,7 +3,6 @@ use std::path::PathBuf; use structopt::StructOpt; use crate::auth; -use crate::listing; /// Possible characters for random routes const ROUTE_ALPHABET: [char; 16] = [ @@ -45,21 +44,6 @@ struct CLIArgs { #[structopt(long = "random-route")] random_route: bool, - /// Sort files - #[structopt( - short = "s", - long = "sort", - raw( - possible_values = "&listing::SortingMethods::variants()", - case_insensitive = "true" - ) - )] - sort_method: Option, - - /// Reverse sorting - #[structopt(long = "reverse")] - reverse_sort: bool, - /// Do not follow symbolic links #[structopt(short = "P", long = "no-symlinks")] no_symlinks: bool, @@ -116,7 +100,5 @@ pub fn parse_args() -> crate::MiniserveConfig { path_explicitly_chosen, no_symlinks: args.no_symlinks, random_route, - sort_method: args.sort_method.unwrap_or(listing::SortingMethods::Natural), - reverse_sort: args.reverse_sort, } } diff --git a/src/listing.rs b/src/listing.rs index 9af2992..cec0f5e 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -1,34 +1,70 @@ use actix_web::{fs, HttpRequest, HttpResponse, Result}; use bytesize::ByteSize; -use clap::{_clap_count_exprs, arg_enum}; use htmlescape::encode_minimal as escape_html_entity; use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; -use std::cmp::Ordering; use std::io; use std::path::Path; use std::time::SystemTime; use crate::renderer; -arg_enum! { - #[derive(Clone, Copy, Debug)] - /// Available sorting methods - /// - /// Natural: natural sorting method - /// 1 -> 2 -> 3 -> 11 - /// - /// Alpha: pure alphabetical sorting method - /// 1 -> 11 -> 2 -> 3 - /// - /// DirsFirst: directories are listed first, alphabetical sorting is also applied - /// 1/ -> 2/ -> 3/ -> 11 -> 12 - /// - /// Date: sort by last modification date (most recent first) - pub enum SortingMethods { - Natural, - Alpha, - DirsFirst, - Date +/// Available sorting methods +#[derive(Debug)] +pub enum SortingMethod { + /// Sort by name + Name, + + /// Sort by size + Size, + + /// Sort by last modification date (natural sort: follows alphanumerical order) + Date, +} + +impl SortingMethod { + fn from_str(src: &str) -> Self { + match src { + "name" => SortingMethod::Name, + "size" => SortingMethod::Size, + "date" => SortingMethod::Date, + _ => SortingMethod::Name, + } + } + + pub fn to_string(&self) -> String { + match &self { + SortingMethod::Name => "name", + SortingMethod::Size => "size", + SortingMethod::Date => "date", + } + .to_string() + } +} + +/// Available sorting orders +#[derive(Debug)] +pub enum SortingOrder { + /// Ascending order + Ascending, + + /// Descending order + Descending, +} + +impl SortingOrder { + fn from_str(src: &str) -> Self { + match src { + "desc" => SortingOrder::Descending, + _ => SortingOrder::Ascending, + } + } + + pub fn to_string(&self) -> String { + match &self { + SortingOrder::Ascending => "asc", + SortingOrder::Descending => "desc", + } + .to_string() } } @@ -42,16 +78,6 @@ pub enum EntryType { File, } -impl PartialOrd for EntryType { - fn partial_cmp(&self, other: &EntryType) -> Option { - match (self, other) { - (EntryType::Directory, EntryType::File) => Some(Ordering::Less), - (EntryType::File, EntryType::Directory) => Some(Ordering::Greater), - _ => Some(Ordering::Equal), - } - } -} - /// Entry pub struct Entry { /// Name of the entry @@ -104,8 +130,6 @@ pub fn directory_listing( req: &HttpRequest, skip_symlinks: bool, random_route: Option, - sort_method: SortingMethods, - reverse_sort: bool, ) -> Result { let title = format!("Index of {}", req.path()); let base = Path::new(req.path()); @@ -113,6 +137,10 @@ pub fn directory_listing( let is_root = base.parent().is_none() || req.path() == random_route; let page_parent = base.parent().map(|p| p.display().to_string()); + let query = req.query(); + let sort_method = query.get("sort").map(|e| SortingMethod::from_str(e)); + let sort_order = query.get("order").map(|e| SortingOrder::from_str(e)); + let mut entries: Vec = Vec::new(); for entry in dir.path.read_dir()? { @@ -161,31 +189,44 @@ pub fn directory_listing( } } - match sort_method { - SortingMethods::Natural => entries - .sort_by(|e1, e2| alphanumeric_sort::compare_str(e1.name.clone(), e2.name.clone())), - SortingMethods::Alpha => { - entries.sort_by(|e1, e2| e1.entry_type.partial_cmp(&e2.entry_type).unwrap()); - entries.sort_by_key(|e| e.name.clone()) - } - SortingMethods::DirsFirst => { - entries.sort_by_key(|e| e.name.clone()); - entries.sort_by(|e1, e2| e1.entry_type.partial_cmp(&e2.entry_type).unwrap()); + if let Some(sorting_method) = &sort_method { + match sorting_method { + SortingMethod::Name => entries + .sort_by(|e1, e2| alphanumeric_sort::compare_str(e1.name.clone(), e2.name.clone())), + SortingMethod::Size => entries.sort_by(|e1, e2| { + // If we can't get the size of the entry (directory for instance) + // let's consider it's 0b + e2.size + .unwrap_or_else(|| ByteSize::b(0)) + .cmp(&e1.size.unwrap_or_else(|| ByteSize::b(0))) + }), + SortingMethod::Date => entries.sort_by(|e1, e2| { + // If, for some reason, we can't get the last modification date of an entry + // let's consider it was modified on UNIX_EPOCH (01/01/19270 00:00:00) + e2.last_modification_date + .unwrap_or(SystemTime::UNIX_EPOCH) + .cmp(&e1.last_modification_date.unwrap_or(SystemTime::UNIX_EPOCH)) + }), + }; + } + + if let Some(sorting_order) = &sort_order { + if let SortingOrder::Descending = sorting_order { + entries.reverse() } - SortingMethods::Date => entries.sort_by(|e1, e2| { - // If, for some reason, we can't get the last modification date of an entry - // let's consider it was modified on UNIX_EPOCH (01/01/19270 00:00:00) - e2.last_modification_date - .unwrap_or(SystemTime::UNIX_EPOCH) - .cmp(&e1.last_modification_date.unwrap_or(SystemTime::UNIX_EPOCH)) - }), - }; - - if reverse_sort { - entries.reverse(); } Ok(HttpResponse::Ok() .content_type("text/html; charset=utf-8") - .body(renderer::page(&title, entries, is_root, page_parent).into_string())) + .body( + renderer::page( + &title, + entries, + is_root, + page_parent, + sort_method, + sort_order, + ) + .into_string(), + )) } diff --git a/src/main.rs b/src/main.rs index e9b16df..37392e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,12 +40,6 @@ pub struct MiniserveConfig { /// Enable random route generation pub random_route: Option, - - /// Sort files/directories - pub sort_method: listing::SortingMethods, - - /// Enable inverse sorting - pub reverse_sort: bool, } fn main() { @@ -181,8 +175,6 @@ fn configure_app(app: App) -> App { let path = &app.state().path; let no_symlinks = app.state().no_symlinks; let random_route = app.state().random_route.clone(); - let sort_method = app.state().sort_method; - let reverse_sort = app.state().reverse_sort; if path.is_file() { None } else { @@ -191,14 +183,7 @@ fn configure_app(app: App) -> App { .expect("Couldn't create path") .show_files_listing() .files_listing_renderer(move |dir, req| { - listing::directory_listing( - dir, - req, - no_symlinks, - random_route.clone(), - sort_method, - reverse_sort, - ) + listing::directory_listing(dir, req, no_symlinks, random_route.clone()) }), ) } diff --git a/src/renderer.rs b/src/renderer.rs index 82937ab..2f25cad 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -11,6 +11,8 @@ pub fn page( entries: Vec, is_root: bool, page_parent: Option, + sort_method: Option, + sort_order: Option, ) -> Markup { html! { (page_header(page_title)) @@ -18,9 +20,9 @@ pub fn page( h1 { (page_title) } table { thead { - th { "Name" } - th { "Size" } - th { "Last modification" } + th { (build_link("name", "Name", &sort_method, &sort_order)) } + th { (build_link("size", "Size", &sort_method, &sort_order)) } + th { (build_link("date", "Last modification", &sort_method, &sort_order)) } } tbody { @if !is_root { @@ -43,6 +45,32 @@ pub fn page( } } +/// Partial: table header link +fn build_link( + name: &str, + title: &str, + sort_method: &Option, + sort_order: &Option, +) -> Markup { + let mut link = format!("?sort={}&order=asc", name); + let mut help = format!("Sort by {} in ascending order", name); + + if let Some(method) = sort_method { + if method.to_string() == name { + if let Some(order) = sort_order { + if order.to_string() == "asc" { + link = format!("?sort={}&order=desc", name); + help = format!("Sort by {} in descending order", name); + } + } + } + }; + + html! { + a href=(link) title=(help) { (title) } + } +} + /// Partial: page header fn page_header(page_title: &str) -> Markup { html! { -- cgit v1.2.3 From 34155e5c1b208ad989a3de3f09f85fb2a445ee5b Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 26 Feb 2019 23:26:12 +0100 Subject: Stylized table header + added chevrons --- src/renderer.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 2f25cad..24942d8 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -54,6 +54,7 @@ fn build_link( ) -> Markup { let mut link = format!("?sort={}&order=asc", name); let mut help = format!("Sort by {} in ascending order", name); + let mut chevron = chevron_up(); if let Some(method) = sort_method { if method.to_string() == name { @@ -61,16 +62,52 @@ fn build_link( if order.to_string() == "asc" { link = format!("?sort={}&order=desc", name); help = format!("Sort by {} in descending order", name); + chevron = chevron_down(); } } } }; html! { + (chevron) + a href=(link) title=(help) { (title) } } } +/// Partial: chevron up +fn chevron_up() -> Markup { + let svg = r#" + + + "# + .to_string(); + + (PreEscaped(svg)) +} + +/// Partial: chevron up +fn chevron_down() -> Markup { + let svg = r#" + + + "# + .to_string(); + + (PreEscaped(svg)) +} + /// Partial: page header fn page_header(page_title: &str) -> Markup { html! { @@ -213,6 +250,14 @@ fn css() -> Markup { .mobile-info { display: none; } + th svg { + margin-right: .5rem; + vertical-align: middle; + fill: #777c82; + } + th a, th a:visited { + color: #777c82; + } @media (max-width: 600px) { h1 { font-size: 1.375em; -- cgit v1.2.3 From db87865631477fafc8b4e62f444514e853014856 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 26 Feb 2019 23:54:36 +0100 Subject: Added highlight for current sorting column --- src/renderer.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 24942d8..846d18b 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -55,9 +55,11 @@ fn build_link( let mut link = format!("?sort={}&order=asc", name); let mut help = format!("Sort by {} in ascending order", name); let mut chevron = chevron_up(); + let mut class = ""; if let Some(method) = sort_method { if method.to_string() == name { + class = "active"; if let Some(order) = sort_order { if order.to_string() == "asc" { link = format!("?sort={}&order=desc", name); @@ -69,9 +71,10 @@ fn build_link( }; html! { - (chevron) - - a href=(link) title=(help) { (title) } + span class=(class) { + (chevron) + a href=(link) title=(help) { (title) } + } } } @@ -258,6 +261,12 @@ fn css() -> Markup { th a, th a:visited { color: #777c82; } + th span.active a { + color: #d24ca9; + } + th span.active svg { + fill: #d24ca9; + } @media (max-width: 600px) { h1 { font-size: 1.375em; -- cgit v1.2.3 From 3ece171c490f62233a996359d26575a8879c70db Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Wed, 27 Feb 2019 18:36:25 +0100 Subject: Switched to unicode characters + improved look and feel --- src/renderer.rs | 46 ++++++++++------------------------------------ 1 file changed, 10 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 846d18b..70e40a2 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -72,7 +72,7 @@ fn build_link( html! { span class=(class) { - (chevron) + span.chevron { (chevron) } a href=(link) title=(help) { (title) } } } @@ -80,35 +80,12 @@ fn build_link( /// Partial: chevron up fn chevron_up() -> Markup { - let svg = r#" - - - "# - .to_string(); - - (PreEscaped(svg)) + (PreEscaped("▴".to_string())) } /// Partial: chevron up fn chevron_down() -> Markup { - let svg = r#" - - - "# - .to_string(); - - (PreEscaped(svg)) + (PreEscaped("▾".to_string())) } /// Partial: page header @@ -194,6 +171,7 @@ fn css() -> Markup { padding: 0.125rem; } table { + margin-top: 2rem; width: 100%; background: white; border: 0; @@ -253,19 +231,15 @@ fn css() -> Markup { .mobile-info { display: none; } - th svg { - margin-right: .5rem; - vertical-align: middle; - fill: #777c82; - } - th a, th a:visited { + th a, th a:visited, .chevron { color: #777c82; } - th span.active a { - color: #d24ca9; + .chevron { + margin-right: .5rem; + font-size: 1.2em; } - th span.active svg { - fill: #d24ca9; + th span.active a, th span.active span { + color: #444444; } @media (max-width: 600px) { h1 { -- cgit v1.2.3 From 108f385e675e474f3dfb581d801df55b5c3820a0 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Wed, 27 Feb 2019 20:00:34 +0100 Subject: Actually use unicode characters --- src/renderer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 70e40a2..1253bec 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -80,12 +80,12 @@ fn build_link( /// Partial: chevron up fn chevron_up() -> Markup { - (PreEscaped("▴".to_string())) + (PreEscaped("▴".to_string())) } /// Partial: chevron up fn chevron_down() -> Markup { - (PreEscaped("▾".to_string())) + (PreEscaped("▾".to_string())) } /// Partial: page header -- cgit v1.2.3 From 3dd2d59789a0c93e62e6d7771a43adc2e2d71c07 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Wed, 27 Feb 2019 20:02:56 +0100 Subject: Improved parent directory link's style --- src/renderer.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 1253bec..3fb992e 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -29,8 +29,9 @@ pub fn page( @if let Some(parent) = page_parent { tr { td { + span.chevron { (chevron_left()) } a.root href=(parent) { - ".." + "Parent directory" } } } @@ -78,6 +79,11 @@ fn build_link( } } +/// Partial: chevron left +fn chevron_left() -> Markup { + (PreEscaped("◂".to_string())) +} + /// Partial: chevron up fn chevron_up() -> Markup { (PreEscaped("▴".to_string())) @@ -237,6 +243,7 @@ fn css() -> Markup { .chevron { margin-right: .5rem; font-size: 1.2em; + font-weight: bold; } th span.active a, th span.active span { color: #444444; -- cgit v1.2.3 From bbc7ef78f6da7de1e0b7d3a93d2bd547ea30ec21 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Wed, 27 Feb 2019 20:10:26 +0100 Subject: Improved readability on mobile + terminal browsers --- src/renderer.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 3fb992e..7128be4 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -79,6 +79,11 @@ fn build_link( } } +/// Partial: new line +fn br() -> Markup { + (PreEscaped("
".to_string())) +} + /// Partial: chevron left fn chevron_left() -> Markup { (PreEscaped("◂".to_string())) @@ -113,13 +118,15 @@ fn entry_row(entry: listing::Entry) -> Markup { html! { tr { td { - @if entry.is_dir() { - a.directory href=(entry.link) { - (entry.name) "/" - } - } @else { - a.file href=(entry.link) { - (entry.name) + p { + @if entry.is_dir() { + a.directory href=(entry.link) { + (entry.name) "/" + } + } @else { + a.file href=(entry.link) { + (entry.name) + } } } @if !entry.is_dir() { @@ -127,6 +134,7 @@ fn entry_row(entry: listing::Entry) -> Markup { span .mobile-info { strong { "Size: " } (size) + (br()) } } } @@ -138,6 +146,7 @@ fn entry_row(entry: listing::Entry) -> Markup { } @if let Some(modification_timer) = humanize_systemtime(entry.last_modification_date) { span .history { "(" (modification_timer) ")" } + (br()) } } @@ -150,10 +159,10 @@ fn entry_row(entry: listing::Entry) -> Markup { td.date-cell { @if let Some(modification_date) = convert_to_utc(entry.last_modification_date) { span { - (modification_date.0) + (modification_date.0) " " } span { - (modification_date.1) + (modification_date.1) " " } } @if let Some(modification_timer) = humanize_systemtime(entry.last_modification_date) { @@ -176,6 +185,10 @@ fn css() -> Markup { color: #444444; padding: 0.125rem; } + p { + margin: 0; + padding: 0; + } table { margin-top: 2rem; width: 100%; @@ -259,7 +272,7 @@ fn css() -> Markup { display: block; } .file, .directory{ - padding-bottom: 0.5rem; + padding-bottom: 1rem; } } @media (max-width: 400px) { -- cgit v1.2.3 From ea4995a0292d6b5a3311c2f1fb801f0faccdf141 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sat, 2 Mar 2019 21:22:07 +0100 Subject: Added back to top button + various CSS improvements + re-order functions in renderer --- src/renderer.rs | 100 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 7128be4..e419cb0 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -17,6 +17,7 @@ pub fn page( html! { (page_header(page_title)) body { + span #top { } h1 { (page_title) } table { thead { @@ -42,6 +43,9 @@ pub fn page( } } } + a.back href="#top" { + (arrow_up()) + } } } } @@ -79,40 +83,6 @@ fn build_link( } } -/// Partial: new line -fn br() -> Markup { - (PreEscaped("
".to_string())) -} - -/// Partial: chevron left -fn chevron_left() -> Markup { - (PreEscaped("◂".to_string())) -} - -/// Partial: chevron up -fn chevron_up() -> Markup { - (PreEscaped("▴".to_string())) -} - -/// Partial: chevron up -fn chevron_down() -> Markup { - (PreEscaped("▾".to_string())) -} - -/// Partial: page header -fn page_header(page_title: &str) -> Markup { - html! { - (DOCTYPE) - html { - meta charset="utf-8"; - meta http-equiv="X-UA-Compatible" content="IE=edge"; - meta name="viewport" content="width=device-width, initial-scale=1"; - title { (page_title) } - style { (css()) } - } - } -} - /// Partial: row for an entry fn entry_row(entry: listing::Entry) -> Markup { html! { @@ -178,6 +148,10 @@ fn entry_row(entry: listing::Entry) -> Markup { /// Partial: CSS fn css() -> Markup { (PreEscaped(r#" + html { + font-smoothing: antialiased; + text-rendering: optimizeLegibility; + } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Helvetica, Arial, sans-serif; @@ -185,6 +159,9 @@ fn css() -> Markup { color: #444444; padding: 0.125rem; } + strong { + font-weight: bold; + } p { margin: 0; padding: 0; @@ -261,6 +238,22 @@ fn css() -> Markup { th span.active a, th span.active span { color: #444444; } + .back { + position: fixed; + bottom: 1.1rem; + right: 0.625rem; + background: #e0e0e0; + border-radius: 100%; + box-shadow: 0 0 8px -4px #888888; + opacity: 0.8; + padding: 1rem 1.1rem; + color: #444444; + } + + .back:hover { + color: #3498db; + text-decoration: none; + } @media (max-width: 600px) { h1 { font-size: 1.375em; @@ -282,6 +275,45 @@ fn css() -> Markup { }"#.to_string())) } +/// Partial: up arrow +fn arrow_up() -> Markup { + (PreEscaped("⇪".to_string())) +} + +/// Partial: new line +fn br() -> Markup { + (PreEscaped("
".to_string())) +} + +/// Partial: chevron left +fn chevron_left() -> Markup { + (PreEscaped("◂".to_string())) +} + +/// Partial: chevron up +fn chevron_up() -> Markup { + (PreEscaped("▴".to_string())) +} + +/// Partial: chevron up +fn chevron_down() -> Markup { + (PreEscaped("▾".to_string())) +} + +/// Partial: page header +fn page_header(page_title: &str) -> Markup { + html! { + (DOCTYPE) + html { + meta charset="utf-8"; + meta http-equiv="X-UA-Compatible" content="IE=edge"; + meta name="viewport" content="width=device-width, initial-scale=1"; + title { (page_title) } + style { (css()) } + } + } +} + /// Converts a SystemTime object to a strings tuple (date, time) /// Date is formatted as %e %b, e.g. Jul 12 /// Time is formatted as %R, e.g. 22:34 -- cgit v1.2.3 From 9c0a5ad85af57b4646c64cc14102d8dc7a8011bc Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Sat, 2 Mar 2019 21:23:42 +0100 Subject: Reset color of visited link in back to top button --- src/renderer.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index e419cb0..2cb9ae7 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -249,7 +249,9 @@ fn css() -> Markup { padding: 1rem 1.1rem; color: #444444; } - + .back:visited { + color: #444444; + } .back:hover { color: #3498db; text-decoration: none; -- cgit v1.2.3 From 2b27f20a9602549beb36244240c669ba86ecb0b6 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Mon, 4 Mar 2019 22:35:48 +0100 Subject: Added color on hovering row --- src/renderer.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/renderer.rs b/src/renderer.rs index 2cb9ae7..89a9248 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -29,7 +29,7 @@ pub fn page( @if !is_root { @if let Some(parent) = page_parent { tr { - td { + td colspan="3" { span.chevron { (chevron_left()) } a.root href=(parent) { "Parent directory" @@ -185,7 +185,7 @@ fn css() -> Markup { line-height: 1.125rem; width: 33.333%; } - table thead tr th { + table tr th { padding: 0.5rem 0.625rem 0.625rem; font-weight: bold; color: #444444; @@ -193,6 +193,9 @@ fn css() -> Markup { table tr:nth-child(even) { background: #f6f6f6; } + table tr:hover { + background: #deeef7a6; + } a { text-decoration: none; color: #3498db; -- cgit v1.2.3 From 5372a5732ab31930478ee6b7131c8a093f346dc7 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Mon, 4 Mar 2019 22:38:01 +0100 Subject: Sort in alphanumeric order by default --- src/listing.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index cec0f5e..45d7af3 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -208,6 +208,10 @@ pub fn directory_listing( .cmp(&e1.last_modification_date.unwrap_or(SystemTime::UNIX_EPOCH)) }), }; + } else { + // Sort in alphanumeric order by default + entries + .sort_by(|e1, e2| alphanumeric_sort::compare_str(e1.name.clone(), e2.name.clone())) } if let Some(sorting_order) = &sort_order { -- cgit v1.2.3 From 08ec4f6a35b83c37a6a3e557aade09c7a0bb4e73 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 5 Mar 2019 00:02:36 +0100 Subject: Use actix::Query --- src/listing.rs | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index 45d7af3..c820a80 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -1,36 +1,38 @@ -use actix_web::{fs, HttpRequest, HttpResponse, Result}; +use actix_web::{fs, FromRequest, HttpRequest, HttpResponse, Query, Result}; use bytesize::ByteSize; use htmlescape::encode_minimal as escape_html_entity; use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; +use serde::Deserialize; use std::io; use std::path::Path; use std::time::SystemTime; use crate::renderer; +/// Query parameters +#[derive(Debug, Deserialize)] +struct SortingQueryParameters { + sort: Option, + order: Option, +} + /// Available sorting methods -#[derive(Debug)] +#[derive(Debug, Deserialize, Clone)] pub enum SortingMethod { /// Sort by name + #[serde(alias = "name")] Name, /// Sort by size + #[serde(alias = "size")] Size, /// Sort by last modification date (natural sort: follows alphanumerical order) + #[serde(alias = "date")] Date, } impl SortingMethod { - fn from_str(src: &str) -> Self { - match src { - "name" => SortingMethod::Name, - "size" => SortingMethod::Size, - "date" => SortingMethod::Date, - _ => SortingMethod::Name, - } - } - pub fn to_string(&self) -> String { match &self { SortingMethod::Name => "name", @@ -42,23 +44,18 @@ impl SortingMethod { } /// Available sorting orders -#[derive(Debug)] +#[derive(Debug, Deserialize, Clone)] pub enum SortingOrder { /// Ascending order + #[serde(alias = "asc")] Ascending, /// Descending order + #[serde(alias = "desc")] Descending, } impl SortingOrder { - fn from_str(src: &str) -> Self { - match src { - "desc" => SortingOrder::Descending, - _ => SortingOrder::Ascending, - } - } - pub fn to_string(&self) -> String { match &self { SortingOrder::Ascending => "asc", @@ -137,9 +134,13 @@ pub fn directory_listing( let is_root = base.parent().is_none() || req.path() == random_route; let page_parent = base.parent().map(|p| p.display().to_string()); - let query = req.query(); - let sort_method = query.get("sort").map(|e| SortingMethod::from_str(e)); - let sort_order = query.get("order").map(|e| SortingOrder::from_str(e)); + let mut sort_method: Option = None; + let mut sort_order: Option = None; + + if let Ok(query) = Query::::extract(req) { + sort_method = query.sort.clone(); + sort_order = query.order.clone(); + } let mut entries: Vec = Vec::new(); @@ -210,8 +211,7 @@ pub fn directory_listing( }; } else { // Sort in alphanumeric order by default - entries - .sort_by(|e1, e2| alphanumeric_sort::compare_str(e1.name.clone(), e2.name.clone())) + entries.sort_by(|e1, e2| alphanumeric_sort::compare_str(e1.name.clone(), e2.name.clone())) } if let Some(sorting_order) = &sort_order { -- cgit v1.2.3 From f5d1c005797e3e8bbfa815ce901090ff36bf74ff Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 5 Mar 2019 00:07:00 +0100 Subject: Renamed QueryParameters struct --- src/listing.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index c820a80..e86cc04 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -11,7 +11,7 @@ use crate::renderer; /// Query parameters #[derive(Debug, Deserialize)] -struct SortingQueryParameters { +struct QueryParameters { sort: Option, order: Option, } @@ -137,7 +137,7 @@ pub fn directory_listing( let mut sort_method: Option = None; let mut sort_order: Option = None; - if let Ok(query) = Query::::extract(req) { + if let Ok(query) = Query::::extract(req) { sort_method = query.sort.clone(); sort_order = query.order.clone(); } -- cgit v1.2.3 From 0433528a7c432b1e7784bd133353c5fc2d1cc8a1 Mon Sep 17 00:00:00 2001 From: boasting-squirrel Date: Tue, 5 Mar 2019 18:34:05 +0100 Subject: Refactored if/let for sorting methods --- src/listing.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/listing.rs b/src/listing.rs index e86cc04..57bef17 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -134,13 +134,11 @@ pub fn directory_listing( let is_root = base.parent().is_none() || req.path() == random_route; let page_parent = base.parent().map(|p| p.display().to_string()); - let mut sort_method: Option = None; - let mut sort_order: Option = None; - - if let Ok(query) = Query::::extract(req) { - sort_method = query.sort.clone(); - sort_order = query.order.clone(); - } + let (sort_method, sort_order) = if let Ok(query) = Query::::extract(req) { + (query.sort.clone(), query.order.clone()) + } else { + (None, None) + }; let mut entries: Vec = Vec::new(); -- cgit v1.2.3