diff options
Diffstat (limited to 'src/renderer.rs')
-rw-r--r-- | src/renderer.rs | 163 |
1 files changed, 138 insertions, 25 deletions
diff --git a/src/renderer.rs b/src/renderer.rs index 82937ab..89a9248 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -11,24 +11,28 @@ pub fn page( entries: Vec<listing::Entry>, is_root: bool, page_parent: Option<String>, + sort_method: Option<listing::SortingMethod>, + sort_order: Option<listing::SortingOrder>, ) -> Markup { html! { (page_header(page_title)) body { + span #top { } 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 { @if let Some(parent) = page_parent { tr { - td { + td colspan="3" { + span.chevron { (chevron_left()) } a.root href=(parent) { - ".." + "Parent directory" } } } @@ -39,20 +43,42 @@ pub fn page( } } } + a.back href="#top" { + (arrow_up()) + } } } } -/// Partial: page header -fn page_header(page_title: &str) -> Markup { +/// Partial: table header link +fn build_link( + name: &str, + title: &str, + sort_method: &Option<listing::SortingMethod>, + sort_order: &Option<listing::SortingOrder>, +) -> Markup { + 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); + help = format!("Sort by {} in descending order", name); + chevron = chevron_down(); + } + } + } + }; + 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()) } + span class=(class) { + span.chevron { (chevron) } + a href=(link) title=(help) { (title) } } } } @@ -62,13 +88,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() { @@ -76,6 +104,7 @@ fn entry_row(entry: listing::Entry) -> Markup { span .mobile-info { strong { "Size: " } (size) + (br()) } } } @@ -87,6 +116,7 @@ fn entry_row(entry: listing::Entry) -> Markup { } @if let Some(modification_timer) = humanize_systemtime(entry.last_modification_date) { span .history { "(" (modification_timer) ")" } + (br()) } } @@ -99,10 +129,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) { @@ -118,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; @@ -125,7 +159,15 @@ fn css() -> Markup { color: #444444; padding: 0.125rem; } + strong { + font-weight: bold; + } + p { + margin: 0; + padding: 0; + } table { + margin-top: 2rem; width: 100%; background: white; border: 0; @@ -143,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; @@ -151,6 +193,9 @@ fn css() -> Markup { table tr:nth-child(even) { background: #f6f6f6; } + table tr:hover { + background: #deeef7a6; + } a { text-decoration: none; color: #3498db; @@ -185,6 +230,35 @@ fn css() -> Markup { .mobile-info { display: none; } + th a, th a:visited, .chevron { + color: #777c82; + } + .chevron { + margin-right: .5rem; + font-size: 1.2em; + font-weight: bold; + } + 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:visited { + color: #444444; + } + .back:hover { + color: #3498db; + text-decoration: none; + } @media (max-width: 600px) { h1 { font-size: 1.375em; @@ -196,7 +270,7 @@ fn css() -> Markup { display: block; } .file, .directory{ - padding-bottom: 0.5rem; + padding-bottom: 1rem; } } @media (max-width: 400px) { @@ -206,6 +280,45 @@ fn css() -> Markup { }"#.to_string())) } +/// Partial: up arrow +fn arrow_up() -> Markup { + (PreEscaped("⇪".to_string())) +} + +/// Partial: new line +fn br() -> Markup { + (PreEscaped("<br>".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 |