Update dependencies

This commit is contained in:
2021-10-22 13:00:29 +02:00
parent 7698911078
commit e2649165a7
13 changed files with 539 additions and 420 deletions

792
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package] [package]
name = "stl_cli" name = "stl_cli"
version = "2.6.7" version = "2.6.8"
authors = ["Joakim Hulthe <joakim@hulthe.net>"] authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0" license = "MPL-2.0"
edition = "2021" edition = "2021"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "stl_lib" name = "stl_lib"
version = "2.6.7" version = "2.6.8"
authors = ["Joakim Hulthe <joakim@hulthe.net>"] authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0" license = "MPL-2.0"
edition = "2021" edition = "2021"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "stl" name = "stl"
description = "studielogg aka scuffed toggl" description = "studielogg aka scuffed toggl"
version = "2.6.7" version = "2.6.8"
authors = ["Joakim Hulthe <joakim@hulthe.net>"] authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0" license = "MPL-2.0"
edition = "2021" edition = "2021"
@ -29,13 +29,9 @@ version = "1"
features = ["sync", "time"] features = ["sync", "time"]
[dependencies.rocket] [dependencies.rocket]
#version = "0.4" version = "0.5.0-rc.1"
git = "https://github.com/SergioBenitez/Rocket" features = ["secrets", "json", "uuid"]
branch = "master"
features = ["secrets"]
[dependencies.rocket_contrib] [dependencies.rocket_dyn_templates]
#version = "0.4" version = "0.1.0-rc.1"
git = "https://github.com/SergioBenitez/Rocket" features = ["handlebars"]
branch = "master"
features = ["handlebars_templates", "uuid"]

View File

@ -5,10 +5,10 @@ use rocket::{
http::{Cookie, CookieJar, Status}, http::{Cookie, CookieJar, Status},
post, post,
request::{FromRequest, Outcome, Request}, request::{FromRequest, Outcome, Request},
response::Redirect, response::{content::Html, Redirect},
uri, State, uri, State,
}; };
use rocket_contrib::templates::Template; use rocket_dyn_templates::Template;
pub struct MasterPassword(String); pub struct MasterPassword(String);
impl From<String> for MasterPassword { impl From<String> for MasterPassword {
@ -41,8 +41,8 @@ impl<'a> FromRequest<'a> for Authorized {
} }
#[catch(401)] #[catch(401)]
pub fn login_page(_req: &Request) -> Template { pub fn login_page(_req: &Request) -> Html<Template> {
Template::render("login", &()) Html(Template::render("login", &()))
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -54,7 +54,7 @@ pub struct Login {
pub fn login( pub fn login(
cookies: &CookieJar, cookies: &CookieJar,
login: Form<Login>, login: Form<Login>,
master_pass: State<MasterPassword>, master_pass: &State<MasterPassword>,
) -> Redirect { ) -> Redirect {
if login.password == master_pass.0 { if login.password == master_pass.0 {
cookies.add_private(Cookie::new(AUTH_COOKIE_KEY, AUTH_COOKIE_VAL)); cookies.add_private(Cookie::new(AUTH_COOKIE_KEY, AUTH_COOKIE_VAL));

View File

@ -1,6 +1,6 @@
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use handlebars::handlebars_helper; use handlebars::handlebars_helper;
use rocket_contrib::templates::Engines; use rocket_dyn_templates::Engines;
pub fn register_helpers(engines: &mut Engines) { pub fn register_helpers(engines: &mut Engines) {
handlebars_helper!(pretty_datetime: |dt: str| { handlebars_helper!(pretty_datetime: |dt: str| {

View File

@ -14,8 +14,8 @@ use crate::util::EventNotifier;
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
use chrono::NaiveDate; use chrono::NaiveDate;
use dotenv::dotenv; use dotenv::dotenv;
use rocket_contrib::serve::StaticFiles; use rocket::fs::FileServer;
use rocket_contrib::templates::Template; use rocket_dyn_templates::Template;
use std::{env, io}; use std::{env, io};
#[rocket::main] #[rocket::main]
@ -64,7 +64,7 @@ async fn main() -> io::Result<()> {
.manage(master_pass) .manage(master_pass)
.manage(birth_date) .manage(birth_date)
.manage(EventNotifier::new()) .manage(EventNotifier::new())
.mount("/static", StaticFiles::from("static")) .mount("/static", FileServer::from("static"))
.mount( .mount(
"/", "/",
rocket::routes![ rocket::routes![

View File

@ -9,9 +9,9 @@ use chrono::{Duration, Local, NaiveDateTime, TimeZone};
use rocket::form::{Form, FromForm}; use rocket::form::{Form, FromForm};
use rocket::http::Status; use rocket::http::Status;
use rocket::response::Redirect; use rocket::response::Redirect;
use rocket::serde::json::Json;
use rocket::serde::uuid::Uuid;
use rocket::{get, post, uri, State}; use rocket::{get, post, uri, State};
use rocket_contrib::json::Json;
use rocket_contrib::uuid::Uuid;
use sled::Transactional; use sled::Transactional;
use stl_lib::wfe::WaitForEvent; use stl_lib::wfe::WaitForEvent;
@ -19,8 +19,8 @@ use stl_lib::wfe::WaitForEvent;
pub fn start_session( pub fn start_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
event_notifier: State<'_, EventNotifier>, event_notifier: &State<EventNotifier>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
toggle_category_session(category_uuid, true, event_notifier, db) toggle_category_session(category_uuid, true, event_notifier, db)
} }
@ -29,8 +29,8 @@ pub fn start_session(
pub fn end_session( pub fn end_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
event_notifier: State<'_, EventNotifier>, event_notifier: &State<EventNotifier>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
toggle_category_session(category_uuid, false, event_notifier, db) toggle_category_session(category_uuid, false, event_notifier, db)
} }
@ -38,12 +38,12 @@ pub fn end_session(
pub fn toggle_category_session( pub fn toggle_category_session(
category_uuid: Uuid, category_uuid: Uuid,
set_active: bool, set_active: bool,
event_notifier: State<'_, EventNotifier>, event_notifier: &State<EventNotifier>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
use crate::database::latest::trees::{category, session}; use crate::database::latest::trees::{category, session};
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?); let category_uuid_s = sled::IVec::from(serialize(&category_uuid)?);
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?; let sessions_tree = db.open_tree(session::NAME)?;
@ -63,7 +63,7 @@ pub fn toggle_category_session(
if duration > Duration::minutes(5) { if duration > Duration::minutes(5) {
let session_uuid = serialize(&uuid::Uuid::new_v4()).unwrap(); let session_uuid = serialize(&uuid::Uuid::new_v4()).unwrap();
let session = session::V { let session = session::V {
category: category_uuid.into_inner(), category: category_uuid,
started, started,
ended: now, ended: now,
deleted: category.deleted, deleted: category.deleted,
@ -103,14 +103,14 @@ pub fn edit_session(
_auth: Authorized, _auth: Authorized,
session_uuid: Uuid, session_uuid: Uuid,
session: Form<EditSession>, session: Form<EditSession>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Redirect, StatusJson> { ) -> Result<Redirect, StatusJson> {
use crate::database::latest::trees::session; use crate::database::latest::trees::session;
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?); let session_uuid_s = sled::IVec::from(serialize(&session_uuid)?);
let session = session::V { let session = session::V {
category: session.category.into_inner(), category: session.category,
started: Local started: Local
.from_local_datetime(&NaiveDateTime::parse_from_str( .from_local_datetime(&NaiveDateTime::parse_from_str(
&session.started, &session.started,
@ -145,11 +145,11 @@ pub fn edit_session(
pub fn delete_session( pub fn delete_session(
_auth: Authorized, _auth: Authorized,
session_uuid: Uuid, session_uuid: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Redirect, StatusJson> { ) -> Result<Redirect, StatusJson> {
use crate::database::latest::trees::session; use crate::database::latest::trees::session;
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?); let session_uuid_s = sled::IVec::from(serialize(&session_uuid)?);
let sessions_tree = db.open_tree(session::NAME)?; let sessions_tree = db.open_tree(session::NAME)?;
@ -174,7 +174,7 @@ pub fn delete_session(
pub async fn wait_for_event( pub async fn wait_for_event(
_auth: Authorized, _auth: Authorized,
timeout: Option<u64>, timeout: Option<u64>,
event_notifier: State<'_, EventNotifier>, event_notifier: &State<EventNotifier>,
) -> Json<WaitForEvent> { ) -> Json<WaitForEvent> {
use std::time::Duration; use std::time::Duration;
match tokio::time::timeout( match tokio::time::timeout(

View File

@ -3,16 +3,16 @@ use crate::database::latest::trees::category;
use crate::status_json::StatusJson; use crate::status_json::StatusJson;
use rocket::form::{Form, FromForm}; use rocket::form::{Form, FromForm};
use rocket::http::Status; use rocket::http::Status;
use rocket::serde::json::Json;
use rocket::serde::uuid::Uuid;
use rocket::{delete, get, post, State}; use rocket::{delete, get, post, State};
use rocket_contrib::json::Json;
use rocket_contrib::uuid::Uuid;
use std::collections::HashMap; use std::collections::HashMap;
#[get("/category?<include_archived>")] #[get("/category?<include_archived>")]
pub fn get_all( pub fn get_all(
_auth: Authorized, _auth: Authorized,
include_archived: Option<bool>, include_archived: Option<bool>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Json<HashMap<category::K, category::V>>, StatusJson> { ) -> Result<Json<HashMap<category::K, category::V>>, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
let mut categories = category::get_all(&categories_tree)?; let mut categories = category::get_all(&categories_tree)?;
@ -26,10 +26,10 @@ pub fn get_all(
pub fn get( pub fn get(
_auth: Authorized, _auth: Authorized,
id: Uuid, id: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Json<category::V>, StatusJson> { ) -> Result<Json<category::V>, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
Ok(Json(category::get(&categories_tree, &id.into_inner())?)) Ok(Json(category::get(&categories_tree, &id)?))
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -43,7 +43,7 @@ pub struct NewCategory {
pub fn create( pub fn create(
_auth: Authorized, _auth: Authorized,
category: Form<NewCategory>, category: Form<NewCategory>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
let category = category.into_inner(); let category = category.into_inner();
@ -68,7 +68,7 @@ pub fn create(
pub fn remove_parent( pub fn remove_parent(
_auth: Authorized, _auth: Authorized,
id: Uuid, id: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
@ -87,16 +87,14 @@ pub fn set_parent(
_auth: Authorized, _auth: Authorized,
id: Uuid, id: Uuid,
parent_id: Json<Uuid>, parent_id: Json<Uuid>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
let parent_id = *parent_id.into_inner();
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
// check for parent cycles // check for parent cycles
let mut next_parent_id = parent_id; let mut next_parent_id = *parent_id;
loop { loop {
if next_parent_id == *id { if next_parent_id == id {
return Err(StatusJson::new(Status::BadRequest, "Parent cycle detected")); return Err(StatusJson::new(Status::BadRequest, "Parent cycle detected"));
} }
@ -112,7 +110,7 @@ pub fn set_parent(
let _parent = category::get(&categories_tree, &parent_id)?; let _parent = category::get(&categories_tree, &parent_id)?;
let category = category::V { let category = category::V {
parent: Some(parent_id), parent: Some(*parent_id),
..category::get(&categories_tree, &id)? ..category::get(&categories_tree, &id)?
}; };
@ -125,7 +123,7 @@ pub fn set_parent(
pub fn archive( pub fn archive(
_auth: Authorized, _auth: Authorized,
id: Uuid, id: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
@ -143,7 +141,7 @@ pub fn archive(
pub fn unarchive( pub fn unarchive(
_auth: Authorized, _auth: Authorized,
id: Uuid, id: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;

View File

@ -7,16 +7,17 @@ use crate::status_json::StatusJson;
use crate::util::EventNotifier; use crate::util::EventNotifier;
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
use rocket::http::Status; use rocket::http::Status;
use rocket::response::content::Html;
use rocket::response::Redirect; use rocket::response::Redirect;
use rocket::serde::uuid::Uuid;
use rocket::{get, post, uri, State}; use rocket::{get, post, uri, State};
use rocket_contrib::templates::Template; use rocket_dyn_templates::Template;
use rocket_contrib::uuid::Uuid;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::time::Duration; use std::time::Duration;
#[get("/")] #[get("/")]
pub fn index(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> { pub fn index(_auth: Authorized, db: &State<sled::Db>) -> Result<Html<Template>, StatusJson> {
#[derive(Debug, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq)] #[derive(Debug, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq)]
struct Node { struct Node {
category: category::V, category: category::V,
@ -89,15 +90,15 @@ pub fn index(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, Sta
categories: top_level_nodes, categories: top_level_nodes,
}; };
Ok(Template::render("index", &context)) Ok(Html(Template::render("index", &context)))
} }
#[post("/category/<category_uuid>/start_session")] #[post("/category/<category_uuid>/start_session")]
pub fn start_session( pub fn start_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
event_notifier: State<'_, EventNotifier>, event_notifier: &State<EventNotifier>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Redirect, StatusJson> { ) -> Result<Redirect, StatusJson> {
super::api::toggle_category_session(category_uuid, true, event_notifier, db)?; super::api::toggle_category_session(category_uuid, true, event_notifier, db)?;
Ok(Redirect::to(uri!(index))) Ok(Redirect::to(uri!(index)))
@ -107,8 +108,8 @@ pub fn start_session(
pub fn end_session( pub fn end_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
event_notifier: State<'_, EventNotifier>, event_notifier: &State<EventNotifier>,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Redirect, StatusJson> { ) -> Result<Redirect, StatusJson> {
super::api::toggle_category_session(category_uuid, false, event_notifier, db)?; super::api::toggle_category_session(category_uuid, false, event_notifier, db)?;
Ok(Redirect::to(uri!(index))) Ok(Redirect::to(uri!(index)))
@ -119,12 +120,12 @@ pub fn bump_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
minutes: i64, minutes: i64,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Redirect, StatusJson> { ) -> Result<Redirect, StatusJson> {
use crate::database::latest::trees::category; use crate::database::latest::trees::category;
let duration = chrono::Duration::minutes(minutes); let duration = chrono::Duration::minutes(minutes);
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?); let category_uuid_s = sled::IVec::from(serialize(&category_uuid)?);
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
@ -162,15 +163,15 @@ pub fn bump_session(
pub fn session_edit( pub fn session_edit(
_auth: Authorized, _auth: Authorized,
session_uuid: Uuid, session_uuid: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Template, StatusJson> { ) -> Result<Html<Template>, StatusJson> {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct SessionPageContext { struct SessionPageContext {
session: session::V, session: session::V,
session_id: uuid::Uuid, session_id: uuid::Uuid,
} }
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?); let session_uuid_s = sled::IVec::from(serialize(&session_uuid)?);
let sessions_tree = db.open_tree(session::NAME)?; let sessions_tree = db.open_tree(session::NAME)?;
match sessions_tree.get(session_uuid_s)? { match sessions_tree.get(session_uuid_s)? {
@ -178,16 +179,16 @@ pub fn session_edit(
Some(data) => { Some(data) => {
let context = SessionPageContext { let context = SessionPageContext {
session: deserialize(&data).unwrap(), session: deserialize(&data).unwrap(),
session_id: session_uuid.into_inner(), session_id: session_uuid,
}; };
Ok(Template::render("edit_session", &context)) Ok(Html(Template::render("edit_session", &context)))
} }
} }
} }
#[get("/history")] #[get("/history")]
pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> { pub fn history(_auth: Authorized, db: &State<sled::Db>) -> Result<Html<Template>, StatusJson> {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct HistoryEntryContext { struct HistoryEntryContext {
category: category::V, category: category::V,
@ -234,5 +235,5 @@ pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, S
context.entries.sort_by_key(|entry| entry.session.started); context.entries.sort_by_key(|entry| entry.session.started);
context.entries.reverse(); context.entries.reverse();
Ok(Template::render("history", &context)) Ok(Html(Template::render("history", &context)))
} }

View File

@ -4,10 +4,8 @@ use crate::status_json::StatusJson;
use crate::util::OrdL; use crate::util::OrdL;
use chrono::{Date, DateTime, Datelike, Duration, Local, Timelike}; use chrono::{Date, DateTime, Datelike, Duration, Local, Timelike};
use itertools::Itertools; use itertools::Itertools;
use rocket::http::Status; use rocket::{get, http::Status, response::content::Html, serde::uuid::Uuid, State};
use rocket::{get, State}; use rocket_dyn_templates::Template;
use rocket_contrib::templates::Template;
use rocket_contrib::uuid::Uuid;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
@ -142,8 +140,8 @@ fn category_stats_ctx(
pub fn single_stats( pub fn single_stats(
_auth: Authorized, _auth: Authorized,
category_id: Uuid, category_id: Uuid,
db: State<'_, sled::Db>, db: &State<sled::Db>,
) -> Result<Template, StatusJson> { ) -> Result<Html<Template>, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?; let categories_tree = db.open_tree(category::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?; let sessions_tree = db.open_tree(session::NAME)?;
@ -154,12 +152,12 @@ pub fn single_stats(
let sessions: HashMap<session::K, session::V> = session::get_all(&sessions_tree)?; let sessions: HashMap<session::K, session::V> = session::get_all(&sessions_tree)?;
let now = Local::now(); let now = Local::now();
let ctx = category_stats_ctx(now, *category_id, category, &sessions, &child_map); let ctx = category_stats_ctx(now, category_id, category, &sessions, &child_map);
Ok(Template::render("stats_single", dbg!(&ctx))) Ok(Html(Template::render("stats_single", dbg!(&ctx))))
} }
#[get("/stats")] #[get("/stats")]
pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> { pub fn all_stats(_auth: Authorized, db: &State<sled::Db>) -> Result<Html<Template>, StatusJson> {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct StatsContext { struct StatsContext {
categories_stats: Vec<CategoryStatsCtx>, categories_stats: Vec<CategoryStatsCtx>,
@ -187,7 +185,7 @@ pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template,
let context = StatsContext { categories_stats }; let context = StatsContext { categories_stats };
Ok(Template::render("stats_all", &context)) Ok(Html(Template::render("stats_all", &context)))
} }
/// Compute the duration of `day` that is covered by the span `start..end` /// Compute the duration of `day` that is covered by the span `start..end`

View File

@ -2,8 +2,8 @@ use crate::auth::Authorized;
use crate::status_json::StatusJson; use crate::status_json::StatusJson;
use chrono::{Duration, Local, NaiveDate}; use chrono::{Duration, Local, NaiveDate};
use itertools::Itertools; use itertools::Itertools;
use rocket::{get, State}; use rocket::{get, response::content::Html, State};
use rocket_contrib::templates::Template; use rocket_dyn_templates::Template;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::borrow::Cow; use std::borrow::Cow;
use std::iter::{once, repeat}; use std::iter::{once, repeat};
@ -11,7 +11,10 @@ use std::iter::{once, repeat};
pub struct BirthDate(pub NaiveDate); pub struct BirthDate(pub NaiveDate);
#[get("/weeks")] #[get("/weeks")]
pub fn weeks(_auth: Authorized, birth_date: State<BirthDate>) -> Result<Template, StatusJson> { pub fn weeks(
_auth: Authorized,
birth_date: &State<BirthDate>,
) -> Result<Html<Template>, StatusJson> {
type Color<'a> = Cow<'a, str>; type Color<'a> = Cow<'a, str>;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@ -105,5 +108,5 @@ pub fn weeks(_auth: Authorized, birth_date: State<BirthDate>) -> Result<Template
.collect(), .collect(),
}; };
Ok(Template::render("weeks", &context)) Ok(Html(Template::render("weeks", &context)))
} }

View File

@ -4,9 +4,8 @@ use duplicate::duplicate;
use log::{info, warn}; use log::{info, warn};
use rocket::http::Status; use rocket::http::Status;
use rocket::response::{Responder, Response}; use rocket::response::{Responder, Response};
use rocket::serde::json::{json, Json};
use rocket::Request; use rocket::Request;
use rocket_contrib::json;
use rocket_contrib::json::Json; // macro
/// An error message which can be serialized as JSON. /// An error message which can be serialized as JSON.
/// ///
@ -81,7 +80,7 @@ impl From<T> for StatusJson {
impl From<Status> for StatusJson { impl From<Status> for StatusJson {
fn from(status: Status) -> StatusJson { fn from(status: Status) -> StatusJson {
StatusJson { StatusJson {
description: status.reason.to_string(), description: status.reason().map(|r| r.to_string()).unwrap_or_default(),
status, status,
} }
} }