Make bump session button pretty
This commit is contained in:
@ -64,6 +64,9 @@ async fn main() -> io::Result<()> {
|
||||
routes::pages::index,
|
||||
routes::pages::history,
|
||||
routes::pages::session_edit,
|
||||
routes::pages::start_session,
|
||||
routes::pages::end_session,
|
||||
routes::pages::bump_session,
|
||||
routes::pages::stats::single_stats,
|
||||
routes::pages::stats::all_stats,
|
||||
],
|
||||
@ -80,7 +83,6 @@ async fn main() -> io::Result<()> {
|
||||
routes::api::category::set_parent,
|
||||
routes::api::start_session,
|
||||
routes::api::end_session,
|
||||
routes::api::bump_session,
|
||||
routes::api::edit_session,
|
||||
routes::api::delete_session,
|
||||
routes::api::wait_for_event,
|
||||
|
||||
@ -15,50 +15,6 @@ use rocket_contrib::uuid::Uuid;
|
||||
use sled::Transactional;
|
||||
use stl_lib::wfe::WaitForEvent;
|
||||
|
||||
#[post("/category/<category_uuid>/bump_session/minutes/<minutes>")]
|
||||
pub fn bump_session(
|
||||
_auth: Authorized,
|
||||
category_uuid: Uuid,
|
||||
minutes: i64,
|
||||
db: State<'_, sled::Db>,
|
||||
) -> Result<Redirect, StatusJson> {
|
||||
use crate::database::latest::trees::category;
|
||||
|
||||
let duration = Duration::minutes(minutes);
|
||||
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
||||
|
||||
let categories_tree = db.open_tree(category::NAME)?;
|
||||
|
||||
(&categories_tree).transaction(|tx_categories| {
|
||||
match tx_categories.get(&category_uuid_s)? {
|
||||
None => Ok(Err(Status::NotFound.into())),
|
||||
Some(data) => {
|
||||
let mut category: category::V = deserialize(&data).unwrap();
|
||||
match category.started.as_mut() {
|
||||
Some(started) => {
|
||||
if let Some(new_started) = started.checked_sub_signed(duration) {
|
||||
*started = new_started;
|
||||
tx_categories
|
||||
.insert(&category_uuid_s, serialize(&category).unwrap())?;
|
||||
} else {
|
||||
return Ok(Err(StatusJson::new(
|
||||
Status::BadRequest,
|
||||
"Duration subtract resulted in overflow",
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(Ok(Redirect::to(uri!(pages::index))))
|
||||
}
|
||||
None => Ok(Err(StatusJson::new(
|
||||
Status::BadRequest,
|
||||
"No active session",
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
})?
|
||||
}
|
||||
|
||||
#[post("/category/<category_uuid>/start_session")]
|
||||
pub fn start_session(
|
||||
_auth: Authorized,
|
||||
|
||||
@ -3,9 +3,11 @@ pub mod stats;
|
||||
use crate::auth::Authorized;
|
||||
use crate::database::latest::trees::{category, session};
|
||||
use crate::status_json::StatusJson;
|
||||
use crate::util::EventNotifier;
|
||||
use bincode::{deserialize, serialize};
|
||||
use rocket::http::Status;
|
||||
use rocket::{get, State};
|
||||
use rocket::response::Redirect;
|
||||
use rocket::{get, post, uri, State};
|
||||
use rocket_contrib::templates::Template;
|
||||
use rocket_contrib::uuid::Uuid;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@ -89,6 +91,72 @@ pub fn index(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, Sta
|
||||
Ok(Template::render("index", &context))
|
||||
}
|
||||
|
||||
#[post("/category/<category_uuid>/start_session")]
|
||||
pub fn start_session(
|
||||
_auth: Authorized,
|
||||
category_uuid: Uuid,
|
||||
event_notifier: State<'_, EventNotifier>,
|
||||
db: State<'_, sled::Db>,
|
||||
) -> Result<Redirect, StatusJson> {
|
||||
super::api::toggle_category_session(category_uuid, true, event_notifier, db)?;
|
||||
Ok(Redirect::to(uri!(index)))
|
||||
}
|
||||
|
||||
#[post("/category/<category_uuid>/end_session")]
|
||||
pub fn end_session(
|
||||
_auth: Authorized,
|
||||
category_uuid: Uuid,
|
||||
event_notifier: State<'_, EventNotifier>,
|
||||
db: State<'_, sled::Db>,
|
||||
) -> Result<Redirect, StatusJson> {
|
||||
super::api::toggle_category_session(category_uuid, false, event_notifier, db)?;
|
||||
Ok(Redirect::to(uri!(index)))
|
||||
}
|
||||
|
||||
#[post("/category/<category_uuid>/bump_session/minutes/<minutes>")]
|
||||
pub fn bump_session(
|
||||
_auth: Authorized,
|
||||
category_uuid: Uuid,
|
||||
minutes: i64,
|
||||
db: State<'_, sled::Db>,
|
||||
) -> Result<Redirect, StatusJson> {
|
||||
use crate::database::latest::trees::category;
|
||||
|
||||
let duration = chrono::Duration::minutes(minutes);
|
||||
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
||||
|
||||
let categories_tree = db.open_tree(category::NAME)?;
|
||||
|
||||
(&categories_tree).transaction(|tx_categories| {
|
||||
match tx_categories.get(&category_uuid_s)? {
|
||||
None => Ok(Err(Status::NotFound.into())),
|
||||
Some(data) => {
|
||||
let mut category: category::V = deserialize(&data).unwrap();
|
||||
match category.started.as_mut() {
|
||||
Some(started) => {
|
||||
if let Some(new_started) = started.checked_sub_signed(duration) {
|
||||
*started = new_started;
|
||||
tx_categories
|
||||
.insert(&category_uuid_s, serialize(&category).unwrap())?;
|
||||
} else {
|
||||
return Ok(Err(StatusJson::new(
|
||||
Status::BadRequest,
|
||||
"Duration subtract resulted in overflow",
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(Ok(Redirect::to(uri!(index))))
|
||||
}
|
||||
None => Ok(Err(StatusJson::new(
|
||||
Status::BadRequest,
|
||||
"No active session",
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
})?
|
||||
}
|
||||
|
||||
#[get("/session/<session_uuid>/edit")]
|
||||
pub fn session_edit(
|
||||
_auth: Authorized,
|
||||
|
||||
@ -300,7 +300,7 @@ struct CalendarDayCtx {
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CalendarCtx {
|
||||
days: Vec<Vec<Option<CalendarDayCtx>>>,
|
||||
weeks: Vec<Vec<Option<CalendarDayCtx>>>,
|
||||
}
|
||||
|
||||
fn compute_calendar_stats<'a, I>(sessions: I) -> CalendarCtx
|
||||
@ -339,54 +339,57 @@ where
|
||||
.num_seconds() as f32;
|
||||
|
||||
let weeks = days.iter().group_by(|(day, _)| day.iso_week());
|
||||
let mut weeks: Vec<_> = weeks
|
||||
.into_iter()
|
||||
.map(|(week, weekdays)| {
|
||||
weekdays
|
||||
.map(|(&day, duration)| {
|
||||
let duration = if duration.is_zero() {
|
||||
None
|
||||
} else {
|
||||
Some(duration.num_seconds() as u64)
|
||||
};
|
||||
|
||||
CalendarCtx {
|
||||
days: weeks
|
||||
.into_iter()
|
||||
.map(|(week, weekdays)| {
|
||||
weekdays
|
||||
.map(|(&day, duration)| {
|
||||
let duration = if duration.is_zero() {
|
||||
None
|
||||
} else {
|
||||
Some(duration.num_seconds() as u64)
|
||||
};
|
||||
let month = day.month();
|
||||
|
||||
let month = day.month();
|
||||
let month_border = |other_day| match days.get(&other_day) {
|
||||
Some(_) => other_day.month() != month,
|
||||
None => true,
|
||||
};
|
||||
|
||||
let month_border = |other_day| match days.get(&other_day) {
|
||||
Some(_) => other_day.month() != month,
|
||||
None => true,
|
||||
};
|
||||
let month_or_week_border = |other_day| match days.get(&other_day) {
|
||||
Some(_) => other_day.iso_week() != week || month_border(other_day),
|
||||
None => true,
|
||||
};
|
||||
|
||||
let month_or_week_border = |other_day| match days.get(&other_day) {
|
||||
Some(_) => other_day.iso_week() != week || month_border(other_day),
|
||||
None => true,
|
||||
};
|
||||
const MIN_WEIGHT: f32 = 0.5;
|
||||
|
||||
const MIN_WEIGHT: f32 = 0.5;
|
||||
let ctx = CalendarDayCtx {
|
||||
border_left: month_border(day - Duration::weeks(1)),
|
||||
border_right: month_border(day + Duration::weeks(1)),
|
||||
border_top: month_or_week_border(day - Duration::days(1)),
|
||||
border_bottom: month_or_week_border(day + Duration::days(1)),
|
||||
|
||||
let ctx = CalendarDayCtx {
|
||||
border_left: month_border(day - Duration::weeks(1)),
|
||||
border_right: month_border(day + Duration::weeks(1)),
|
||||
border_top: month_or_week_border(day - Duration::days(1)),
|
||||
border_bottom: month_or_week_border(day + Duration::days(1)),
|
||||
weight: duration
|
||||
.map(|d| d as f32 / biggest_day_duration)
|
||||
.map(|w| (MIN_WEIGHT + w * (1.0 - MIN_WEIGHT)).clamp(0.0, 1.0))
|
||||
.unwrap_or(1.0),
|
||||
|
||||
weight: duration
|
||||
.map(|d| d as f32 / biggest_day_duration)
|
||||
.map(|w| (MIN_WEIGHT + w * (1.0 - MIN_WEIGHT)).clamp(0.0, 1.0))
|
||||
.unwrap_or(1.0),
|
||||
duration,
|
||||
};
|
||||
|
||||
duration,
|
||||
};
|
||||
//(day.weekday(), Some(ctx))
|
||||
Some(ctx)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
||||
//(day.weekday(), Some(ctx))
|
||||
Some(ctx)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
// calendar is shown as flex-direction: row-reverse
|
||||
// because it should be scrolled from the right
|
||||
weeks.reverse();
|
||||
|
||||
CalendarCtx { weeks }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user