Skip to content

Commit

Permalink
feat: sort by date created/modified (#373)
Browse files Browse the repository at this point in the history
Co-authored-by: Esteban Borai <estebanborai@gmail.com>
  • Loading branch information
Antosser and EstebanBorai committed Nov 3, 2023
1 parent 9c273cf commit 04d73b7
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 63 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dhat-profiling = ["dhat"]
anyhow = "1.0.75"
async-stream = "0.3.5"
async-trait = "0.1.72"
chrono = "0.4.31"
chrono = { version = "0.4.31", features = ["serde"] }
dhat = { version = "0.2.4", optional = true }
futures = "0.3.29"
flate2 = "1.0.28"
Expand Down
19 changes: 14 additions & 5 deletions src/addon/file_server/directory_entry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::Serialize;
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use std::cmp::{Ord, Ordering};

/// A Directory entry used to display a File Explorer's entry.
Expand All @@ -11,8 +12,8 @@ pub struct DirectoryEntry {
pub(crate) size: String,
pub(crate) len: u64,
pub(crate) entry_path: String,
pub(crate) created_at: String,
pub(crate) updated_at: String,
pub(crate) date_created: Option<DateTime<Local>>,
pub(crate) date_modified: Option<DateTime<Local>>,
}

impl Ord for DirectoryEntry {
Expand Down Expand Up @@ -60,6 +61,14 @@ pub struct DirectoryIndex {
/// Directory listing entry
pub(crate) entries: Vec<DirectoryEntry>,
pub(crate) breadcrumbs: Vec<BreadcrumbItem>,
pub(crate) sort_by_name: bool,
pub(crate) sort_by_size: bool,
pub(crate) sort: Sort,
}

#[derive(Serialize, Debug, PartialEq, Deserialize)]
pub enum Sort {
Directory,
Name,
Size,
DateCreated,
DateModified,
}
84 changes: 54 additions & 30 deletions src/addon/file_server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ mod http_utils;
mod query_params;
mod scoped_file_system;

use chrono::{DateTime, Local};

pub use file::{File, FILE_BUFFER_SIZE};
pub use scoped_file_system::{Directory, Entry, ScopedFileSystem};

use anyhow::{Context, Result};
use handlebars::Handlebars;
use handlebars::{handlebars_helper, Handlebars};
use http::response::Builder as HttpResponseBuilder;
use http::{StatusCode, Uri};
use hyper::{Body, Response};
Expand All @@ -18,10 +20,10 @@ use std::path::{Component, Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;

use crate::utils::fmt::{format_bytes, format_system_date};
use crate::utils::fmt::format_bytes;
use crate::utils::url_encode::{decode_uri, encode_uri, PERCENT_ENCODE_SET};

use self::directory_entry::{BreadcrumbItem, DirectoryEntry, DirectoryIndex};
use self::directory_entry::{BreadcrumbItem, DirectoryEntry, DirectoryIndex, Sort};
use self::http_utils::{make_http_file_response, CacheControlDirective};
use self::query_params::{QueryParams, SortBy};

Expand Down Expand Up @@ -58,6 +60,26 @@ impl<'a> FileServer {
.register_template_string(EXPLORER_TEMPLATE, template)
.unwrap();

handlebars_helper!(date: |d: Option<DateTime<Local>>| {
match d {
Some(d) => d.format("%Y/%m/%d %H:%M:%S").to_string(),
None => "-".to_owned(),
}
});
handlebars.register_helper("date", Box::new(date));

handlebars_helper!(sort_name: |sort: Sort| sort == Sort::Name);
handlebars.register_helper("sort_name", Box::new(sort_name));

handlebars_helper!(sort_size: |sort: Sort| sort == Sort::Size);
handlebars.register_helper("sort_size", Box::new(sort_size));

handlebars_helper!(sort_date_created: |sort: Sort| sort == Sort::DateCreated);
handlebars.register_helper("sort_date_created", Box::new(sort_date_created));

handlebars_helper!(sort_date_modified: |sort: Sort| sort == Sort::DateModified);
handlebars.register_helper("sort_date_modified", Box::new(sort_date_modified));

Arc::new(handlebars)
}

Expand Down Expand Up @@ -224,15 +246,15 @@ impl<'a> FileServer {
for entry in entries {
let entry = entry.context("Unable to read entry")?;
let metadata = entry.metadata()?;
let created_at = if let Ok(time) = metadata.created() {
format_system_date(time)
let date_created = if let Ok(time) = metadata.created() {
Some(time.into())
} else {
String::default()
None
};
let updated_at = if let Ok(time) = metadata.modified() {
format_system_date(time)
let date_modified = if let Ok(time) = metadata.modified() {
Some(time.into())
} else {
String::default()
None
};

directory_entries.push(DirectoryEntry {
Expand All @@ -245,8 +267,8 @@ impl<'a> FileServer {
size: format_bytes(metadata.len() as f64),
len: metadata.len(),
entry_path: FileServer::make_dir_entry_link(&root_dir, &entry.path()),
created_at,
updated_at,
date_created,
date_modified,
});
}

Expand All @@ -255,25 +277,28 @@ impl<'a> FileServer {
match sort_by {
SortBy::Name => {
directory_entries.sort_by_key(|entry| entry.display_name.clone());

return Ok(DirectoryIndex {
entries: directory_entries,
breadcrumbs,
sort_by_name: true,
sort_by_size: false,
});
}
SortBy::Size => {
directory_entries.sort_by_key(|entry| entry.len);

return Ok(DirectoryIndex {
entries: directory_entries,
breadcrumbs,
sort_by_name: false,
sort_by_size: true,
});
SortBy::Size => directory_entries.sort_by_key(|entry| entry.len),
SortBy::DateCreated => {
directory_entries.sort_by_key(|entry| entry.date_created)
}
}
SortBy::DateModified => {
directory_entries.sort_by_key(|entry| entry.date_modified)
}
};

let sort_enum = match sort_by {
SortBy::Name => Sort::Name,
SortBy::Size => Sort::Size,
SortBy::DateCreated => Sort::DateCreated,
SortBy::DateModified => Sort::DateModified,
};

return Ok(DirectoryIndex {
entries: directory_entries,
breadcrumbs,
sort: sort_enum,
});
}
}

Expand All @@ -282,8 +307,7 @@ impl<'a> FileServer {
Ok(DirectoryIndex {
entries: directory_entries,
breadcrumbs,
sort_by_name: false,
sort_by_size: false,
sort: Sort::Directory,
})
}

Expand Down
8 changes: 6 additions & 2 deletions src/addon/file_server/query_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::str::FromStr;
pub enum SortBy {
Name,
Size,
DateCreated,
DateModified,
}

impl FromStr for SortBy {
Expand All @@ -16,8 +18,10 @@ impl FromStr for SortBy {
let lower = lower.as_str();

match lower {
"name" => Ok(SortBy::Name),
"size" => Ok(SortBy::Size),
"name" => Ok(Self::Name),
"size" => Ok(Self::Size),
"date_created" => Ok(Self::DateCreated),
"date_modified" => Ok(Self::DateModified),
_ => Err(Error::msg("Value doesnt correspond")),
}
}
Expand Down
21 changes: 15 additions & 6 deletions src/addon/file_server/template/explorer.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,27 @@
<ul id="explorer">
<li class="hrow">
<span class="hcol icon-col"></span>
{{#if sort_by_name}}
{{#if (sort_name sort)}}
<a class="hcol" href="?sort_by=">Name&nbsp;↓</a>
{{else}}
<a class="hcol" href="?sort_by=name">Name</a>
{{/if}}
{{#if sort_by_size}}
{{#if (sort_size sort)}}
<a class="hcol" href="?sort_by=">Size&nbsp;↓</a>
{{else}}
<a class="hcol" href="?sort_by=size">Size</a>
{{/if}}
<a class="hcol">Date created</a>
<a class="hcol">Date modified</a>
{{#if (sort_date_created sort)}}
<a class="hcol" href="?sort_by=">Date created&nbsp;↓</a>
{{else}}
<a class="hcol" href="?sort_by=date_created">Date created</a>
{{/if}}
{{#if (sort_date_modified sort)}}
<a class="hcol" href="?sort_by=">Date modified&nbsp;↓</a>
{{else}}
<a class="hcol" href="?sort_by=date_modified">Date modified</a>
{{/if}}

</li>
{{#each entries}}
<li class="brow">
Expand All @@ -215,8 +224,8 @@
</span>
<span class="bcol">{{display_name}}</span>
<span class="bcol">{{size}}</span>
<span class="bcol">{{created_at}}</span>
<span class="bcol">{{updated_at}}</span>
<span class="bcol">{{date date_created}}</span>
<span class="bcol">{{date date_modified}}</span>
</a>
</li>
{{/each}}
Expand Down
19 changes: 0 additions & 19 deletions src/utils/fmt.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
use chrono::prelude::*;
use chrono::{DateTime, Local};
use std::time::SystemTime;

/// Byte size units
const BYTE_SIZE_UNIT: [&str; 9] = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];

Expand All @@ -18,21 +14,6 @@ pub fn format_bytes(bytes: f64) -> String {
format!("{:.2} {}", value, BYTE_SIZE_UNIT[i as usize])
}

/// Formats a `SystemTime` into a YYYY/MM/DD HH:MM:SS time `String`
pub fn format_system_date(system_time: SystemTime) -> String {
let datetime: DateTime<Local> = DateTime::from(system_time);

format!(
"{}/{:0>2}/{:0>2} {:0>2}:{:0>2}:{:0>2}",
datetime.year(),
datetime.month(),
datetime.day(),
datetime.hour(),
datetime.minute(),
datetime.second()
)
}

#[cfg(test)]
mod tests {
use std::vec;
Expand Down

0 comments on commit 04d73b7

Please sign in to comment.