From 5fa1819beabb5f9e3d07bdaae6572427efb178e1 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Thu, 4 Feb 2021 19:53:28 +0100 Subject: [PATCH] Add stats_single page & header with links --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/main.rs | 3 +- src/routes/pages.rs | 3 +- src/routes/pages/stats.rs | 129 +++++++++++++++++++++++++++++-------- templates/edit_session.hbs | 59 +++++++---------- templates/head.hbs | 12 ++++ templates/header.hbs | 7 ++ templates/history.hbs | 48 ++++++-------- templates/index.hbs | 116 +++++++++++++++------------------ templates/login.hbs | 27 +++----- templates/stats.hbs | 55 ---------------- templates/stats_all.hbs | 13 ++++ templates/stats_chart.hbs | 33 ++++++++++ templates/stats_single.hbs | 8 +++ 15 files changed, 285 insertions(+), 232 deletions(-) create mode 100644 templates/head.hbs create mode 100644 templates/header.hbs delete mode 100644 templates/stats.hbs create mode 100644 templates/stats_all.hbs create mode 100644 templates/stats_chart.hbs create mode 100644 templates/stats_single.hbs diff --git a/Cargo.lock b/Cargo.lock index 0f7bc35..260afd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1879,7 +1879,7 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "stl" -version = "2.2.0" +version = "2.3.0" dependencies = [ "bincode", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 040c95b..288b2bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "stl" description = "studielogg aka scuffed toggl" -version = "2.2.0" +version = "2.3.0" authors = ["Joakim Hulthe "] license = "MPL-2.0" edition = "2018" diff --git a/src/main.rs b/src/main.rs index 4c2cf80..35527c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,8 @@ async fn main() -> io::Result<()> { routes::pages::index, routes::pages::history, routes::pages::session_edit, - routes::pages::stats::view, + routes::pages::stats::single_stats, + routes::pages::stats::all_stats, routes::api::edit_session, routes::api::create_category, routes::api::start_session, diff --git a/src/routes/pages.rs b/src/routes/pages.rs index 2b23068..969f6b7 100644 --- a/src/routes/pages.rs +++ b/src/routes/pages.rs @@ -3,8 +3,7 @@ pub mod stats; use crate::auth::Authorized; use crate::database::latest::trees::{categories, sessions}; use crate::status_json::StatusJson; -use bincode::deserialize; -use bincode::serialize; +use bincode::{deserialize, serialize}; use rocket::http::Status; use rocket::{get, State}; use rocket_contrib::templates::Template; diff --git a/src/routes/pages/stats.rs b/src/routes/pages/stats.rs index b8f18fa..b441be2 100644 --- a/src/routes/pages/stats.rs +++ b/src/routes/pages/stats.rs @@ -1,35 +1,120 @@ use crate::auth::Authorized; use crate::database::latest::trees::{categories, sessions}; use crate::status_json::StatusJson; -use bincode::deserialize; +use bincode::{deserialize, serialize}; use chrono::{DateTime, Local, Timelike}; +use rocket::http::Status; use rocket::{get, State}; use rocket_contrib::templates::Template; +use rocket_contrib::uuid::Uuid; use serde_derive::{Deserialize, Serialize}; use std::cmp::Ordering; use std::collections::{BTreeMap, HashMap}; +#[derive(Debug, Serialize, Deserialize)] +struct CategoryStatsContext { + category_id: categories::K, + category: categories::V, + + last_session_start: Option>, + secs_last_session: u64, + secs_last_week: u64, + secs_last_month: u64, + + bars_max: f64, + bars: Vec<(u32, f64, f64)>, +} + +fn sum_sessions<'a>(iter: impl IntoIterator) -> u64 { + iter.into_iter() + .map(|session| session.ended - session.started) + .map(|duration| duration.num_seconds() as u64) + .sum() +} + +#[get("/stats/")] +pub fn single_stats( + _auth: Authorized, + category_uuid: Uuid, + db: State<'_, sled::Db>, +) -> Result { + let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?); + + let categories_tree = db.open_tree(categories::NAME)?; + let sessions_tree = db.open_tree(sessions::NAME)?; + + let category: categories::V = match categories_tree.get(category_uuid_s)? { + None => Err(Status::NotFound)?, + Some(data) => deserialize(&data).unwrap(), + }; + + let sessions: HashMap = sessions_tree + .iter() + .map(|result| { + result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v)))) + }) + .collect::, _>>()??; + + let my_sessions = sessions + .values() + .filter(|session| session.category == *category_uuid); + + let last_session = my_sessions.clone().max_by_key(|session| &session.started); + + let secs_last_session = sum_sessions(last_session); + + let now = Local::now(); + + let secs_last_week = sum_sessions( + my_sessions + .clone() + .filter(|session| (now - session.started) <= chrono::Duration::days(7)), + ); + + let secs_last_month = sum_sessions( + my_sessions + .clone() + .filter(|session| (now - session.started) <= chrono::Duration::days(30)), + ); + + let mut stats_per_hour = compute_percentage_per_hour(my_sessions); + let biggest_hour = *stats_per_hour + .values() + .max_by(|f1, f2| match () { + _ if f1 == f2 => Ordering::Equal, + _ if f1 > f2 => Ordering::Greater, + _ => Ordering::Less, + }) + .unwrap_or(&1.0); + + let context = CategoryStatsContext { + category_id: *category_uuid, + category, + + last_session_start: last_session.map(|session| session.started), + secs_last_session, + secs_last_week, + secs_last_month, + + bars_max: biggest_hour, + bars: (0..24) + .map(|hour| { + let percentage = *stats_per_hour.entry(hour).or_default(); + (hour, percentage, biggest_hour - percentage) + }) + .collect(), + }; + + Ok(Template::render("stats_single", &context)) +} + #[get("/stats")] -pub fn view(_auth: Authorized, db: State<'_, sled::Db>) -> Result { +pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result { #[derive(Debug, Serialize, Deserialize)] struct StatsContext { categories_stats: Vec, } - #[derive(Debug, Serialize, Deserialize)] - struct CategoryStatsContext { - category_id: categories::K, - category: categories::V, - - last_session_start: Option>, - secs_last_session: u64, - secs_last_week: u64, - secs_last_month: u64, - - bars_max: f64, - bars: Vec<(u32, f64, f64)>, - } - let now = Local::now(); let categories_tree = db.open_tree(categories::NAME)?; @@ -52,13 +137,6 @@ pub fn view(_auth: Authorized, db: State<'_, sled::Db>) -> Result = categories .into_iter() .map(|(category_id, category)| { - fn sum_sessions<'a>(iter: impl IntoIterator) -> u64 { - iter.into_iter() - .map(|session| session.ended - session.started) - .map(|duration| duration.num_seconds() as u64) - .sum() - } - let my_sessions = sessions .values() .filter(|session| session.category == category_id); @@ -113,7 +191,7 @@ pub fn view(_auth: Authorized, db: State<'_, sled::Db>) -> Result(sessions: I) -> BTreeMap @@ -163,8 +241,7 @@ where } } - dbg!(&stats_per_hour); - let sum_weight: f64 = dbg!(stats_per_hour.values().sum()); + let sum_weight: f64 = stats_per_hour.values().sum(); for weight in stats_per_hour.values_mut() { *weight = *weight * 100.0 / sum_weight; *weight = (*weight * 10.0).trunc() / 10.0; diff --git a/templates/edit_session.hbs b/templates/edit_session.hbs index b0d1f93..5e1403c 100644 --- a/templates/edit_session.hbs +++ b/templates/edit_session.hbs @@ -1,39 +1,28 @@ - - - - + {{> head}} + +

stl

- - - - - stl - - - -

stl

- -
- tillbaka -
-
-
- - - Started: - -
- Ended: - -
- -
-
-
- -
-
- +
+ tillbaka +
+
+
+ + + Started: + +
+ Ended: + +
+ +
+
+
+ +
+
+ diff --git a/templates/head.hbs b/templates/head.hbs new file mode 100644 index 0000000..91aad2c --- /dev/null +++ b/templates/head.hbs @@ -0,0 +1,12 @@ + + + + + + + + + + + stl + diff --git a/templates/header.hbs b/templates/header.hbs new file mode 100644 index 0000000..8a950ca --- /dev/null +++ b/templates/header.hbs @@ -0,0 +1,7 @@ +

+ 🗠 + - + stl + - + 🕮 +

diff --git a/templates/history.hbs b/templates/history.hbs index ea61b3c..636d49d 100644 --- a/templates/history.hbs +++ b/templates/history.hbs @@ -1,33 +1,23 @@ - - - - + {{> head}} + + {{> header}} - - - - - stl - - - -

stl

-
    - {{#each entries}} -
  • - - under - {{pretty_seconds this.duration.secs}} - från - {{pretty_datetime this.session.started}} - tills - {{pretty_datetime this.session.ended}} - --- - ändra -
  • - {{/each}} -
- +
    + {{#each entries}} +
  • + + under + {{pretty_seconds this.duration.secs}} + från + {{pretty_datetime this.session.started}} + tills + {{pretty_datetime this.session.ended}} + --- + ändra +
  • + {{/each}} +
+ diff --git a/templates/index.hbs b/templates/index.hbs index c0f2b46..47482a3 100644 --- a/templates/index.hbs +++ b/templates/index.hbs @@ -1,72 +1,62 @@ - - - - + {{> head}} + + - //Send the proper header information along with the request - xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + {{> header}} - xhr.send(); - } - - - - -

stl

- -
    - {{#each categories}} -
  • -
    - {{this.1.name}} - {{#if this.1.started}} -
    - -
    - {{/if}} -
    - -
    -
  • - {{/each}} -
- +
    + {{#each categories}} +
  • +
    + {{this.1.name}} + {{#if this.1.started}} +
    + +
    + {{/if}} +
    + +
    +
  • + {{/each}} +
+ diff --git a/templates/login.hbs b/templates/login.hbs index 1701ba9..7465618 100644 --- a/templates/login.hbs +++ b/templates/login.hbs @@ -1,22 +1,11 @@ - - - - - - - - - - stl - - - -

stl

-

Logga in

-
- -
- + {{>head}} + +

stl

+

Logga in

+
+ +
+ diff --git a/templates/stats.hbs b/templates/stats.hbs deleted file mode 100644 index a00f212..0000000 --- a/templates/stats.hbs +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - stl - - - -

stl

- - {{#each categories_stats}} - {{#if this.last_session_start}} -
-

- Kategori: - {{this.category.name}} - -

-

- Senaste session: - {{pretty_datetime this.last_session_start}} - i - {{pretty_seconds this.secs_last_session}} -

-

- Senaste veckan: - {{pretty_seconds this.secs_last_week}} - Senaste månaden: - {{pretty_seconds this.secs_last_month}} -

-

Andel per timme:

-
-
{{this.bars_max}}%
- {{#each this.bars}} -
-
-
- {{this.1}}% -
-
{{this.0}}
-
- {{/each}} -
- {{/if}} - {{/each}} - - diff --git a/templates/stats_all.hbs b/templates/stats_all.hbs new file mode 100644 index 0000000..36a42cd --- /dev/null +++ b/templates/stats_all.hbs @@ -0,0 +1,13 @@ + + + {{> head}} + + {{> header}} + + {{#each categories_stats}} + {{#if this.last_session_start}} + {{> stats_chart this}} + {{/if}} + {{/each}} + + diff --git a/templates/stats_chart.hbs b/templates/stats_chart.hbs new file mode 100644 index 0000000..f41484c --- /dev/null +++ b/templates/stats_chart.hbs @@ -0,0 +1,33 @@ +
+
+

+ Kategori: + {{category.name}} + +

+

+ Senaste session: + {{pretty_datetime last_session_start}} + i + {{pretty_seconds secs_last_session}} +

+

+ Senaste veckan: + {{pretty_seconds secs_last_week}} + Senaste månaden: + {{pretty_seconds secs_last_month}} +

+

Andel per timme:

+
+
{{bars_max}}%
+ {{#each bars}} +
+
+
+ {{this.1}}% +
+
{{this.0}}
+
+ {{/each}} +
+
diff --git a/templates/stats_single.hbs b/templates/stats_single.hbs new file mode 100644 index 0000000..2e4889d --- /dev/null +++ b/templates/stats_single.hbs @@ -0,0 +1,8 @@ + + + {{> head}} + + {{> header}} + {{> stats_chart this}} + +