198 lines
6.8 KiB
Rust
198 lines
6.8 KiB
Rust
use crate::database::latest::trees::{categories, past_sessions};
|
|
use crate::routes::pages;
|
|
use crate::status_json::StatusJson;
|
|
use bincode::{deserialize, serialize};
|
|
use chrono::NaiveDateTime;
|
|
use chrono::{Duration, Utc};
|
|
use rocket::http::Status;
|
|
use rocket::request::{Form, FromForm};
|
|
use rocket::response::Redirect;
|
|
use rocket::{post, uri, State};
|
|
use rocket_contrib::uuid::Uuid;
|
|
use sled::Transactional;
|
|
|
|
#[derive(FromForm)]
|
|
pub struct NewCategory {
|
|
name: String,
|
|
color: String,
|
|
}
|
|
|
|
#[post("/create_category", data = "<category>")]
|
|
pub fn create_category(
|
|
category: Form<NewCategory>,
|
|
db: State<'_, sled::Db>,
|
|
) -> Result<StatusJson, StatusJson> {
|
|
let category = category.into_inner();
|
|
|
|
let categories_tree = db.open_tree(categories::NAME)?;
|
|
categories_tree.insert(
|
|
serialize(&uuid::Uuid::new_v4())?,
|
|
serialize(&categories::V {
|
|
name: category.name,
|
|
color: category.color,
|
|
started: None,
|
|
})?,
|
|
)?;
|
|
|
|
Ok(Status::Ok.into())
|
|
}
|
|
|
|
#[post("/category/<category_uuid>/start_session")]
|
|
pub fn start_session(
|
|
category_uuid: Uuid,
|
|
db: State<'_, sled::Db>,
|
|
) -> Result<StatusJson, StatusJson> {
|
|
toggle_category_session(category_uuid, true, db)
|
|
}
|
|
|
|
#[post("/category/<category_uuid>/end_session")]
|
|
pub fn end_session(category_uuid: Uuid, db: State<'_, sled::Db>) -> Result<StatusJson, StatusJson> {
|
|
toggle_category_session(category_uuid, false, db)
|
|
}
|
|
|
|
#[post("/category/<category_uuid>/bump_session/minutes/<minutes>")]
|
|
pub fn bump_session(
|
|
category_uuid: Uuid,
|
|
minutes: i64,
|
|
db: State<'_, sled::Db>,
|
|
) -> Result<Redirect, StatusJson> {
|
|
let duration = Duration::minutes(minutes);
|
|
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
|
|
|
let categories_tree = db.open_tree(categories::NAME)?;
|
|
|
|
Ok((&categories_tree).transaction(|tx_categories| {
|
|
match tx_categories.get(&category_uuid_s)? {
|
|
None => return Ok(Err(Status::NotFound.into())),
|
|
Some(data) => {
|
|
let mut category: categories::V = deserialize(&data).unwrap();
|
|
match category.started.as_mut() {
|
|
Some(started) => {
|
|
*started -= duration;
|
|
tx_categories.insert(&category_uuid_s, serialize(&category).unwrap())?;
|
|
Ok(Ok(Redirect::to(uri!(pages::index))))
|
|
}
|
|
None => {
|
|
return Ok(Err(StatusJson::new(
|
|
Status::BadRequest,
|
|
"No active session",
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})??)
|
|
}
|
|
|
|
pub fn toggle_category_session(
|
|
category_uuid: Uuid,
|
|
set_active: bool,
|
|
db: State<'_, sled::Db>,
|
|
) -> Result<StatusJson, StatusJson> {
|
|
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
|
|
|
let categories_tree = db.open_tree(categories::NAME)?;
|
|
let past_sessions_tree = db.open_tree(past_sessions::NAME)?;
|
|
|
|
Ok((&categories_tree, &past_sessions_tree).transaction(
|
|
|(tx_categories, tx_past_sessions)| {
|
|
match tx_categories.get(&category_uuid_s)? {
|
|
None => return Ok(Err(Status::NotFound)),
|
|
Some(data) => {
|
|
let mut category: categories::V = deserialize(&data).unwrap();
|
|
let now = Utc::now().naive_utc();
|
|
|
|
match (set_active, category.started.take()) {
|
|
(false, Some(started)) => {
|
|
// only save sessions longer than 5 minutes
|
|
let duration = now - started;
|
|
if duration > Duration::minutes(5) {
|
|
let session_uuid = serialize(&uuid::Uuid::new_v4()).unwrap();
|
|
let past_session = past_sessions::V {
|
|
category: category_uuid.into_inner(),
|
|
started,
|
|
ended: now,
|
|
};
|
|
tx_past_sessions
|
|
.insert(session_uuid, serialize(&past_session).unwrap())?;
|
|
}
|
|
}
|
|
(true, None) => {
|
|
category.started = Some(now);
|
|
}
|
|
_ => {
|
|
// Category is already in the correct state
|
|
return Ok(Ok(Status::Ok.into()));
|
|
}
|
|
}
|
|
|
|
tx_categories.insert(&category_uuid_s, serialize(&category).unwrap())?;
|
|
}
|
|
}
|
|
|
|
Ok(Ok(Status::Ok.into()))
|
|
},
|
|
)??)
|
|
}
|
|
|
|
#[derive(Debug, FromForm)]
|
|
pub struct EditSession {
|
|
category: Uuid,
|
|
started: String,
|
|
ended: String,
|
|
}
|
|
|
|
#[post("/session/<session_uuid>/edit", data = "<session>")]
|
|
pub fn edit_session(
|
|
session_uuid: Uuid,
|
|
session: Form<EditSession>,
|
|
db: State<'_, sled::Db>,
|
|
) -> Result<Redirect, StatusJson> {
|
|
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
|
|
|
dbg!(&session);
|
|
|
|
let session = past_sessions::V {
|
|
category: session.category.into_inner(),
|
|
started: NaiveDateTime::parse_from_str(&session.started, "%Y-%m-%d %H:%M")?,
|
|
ended: NaiveDateTime::parse_from_str(&session.ended, "%Y-%m-%d %H:%M")?,
|
|
};
|
|
|
|
if session.started >= session.ended {
|
|
return Err(StatusJson::new(
|
|
Status::BadRequest,
|
|
"started must be earlier than ended",
|
|
));
|
|
}
|
|
|
|
db.open_tree(past_sessions::NAME)?
|
|
.insert(session_uuid_s, serialize(&session)?)?;
|
|
|
|
// FIXME: Uuid does not implement FromUriParam for some reason... File an issue?
|
|
//Ok(Redirect::to(uri!(pages::session_edit: session_uuid)))
|
|
Ok(Redirect::to(format!("/session/{}/edit", session_uuid)))
|
|
}
|
|
|
|
#[post("/session/<session_uuid>/delete")]
|
|
pub fn delete_session(session_uuid: Uuid, db: State<'_, sled::Db>) -> Result<Redirect, StatusJson> {
|
|
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
|
|
|
let past_sessions_tree = db.open_tree(past_sessions::NAME)?;
|
|
|
|
match past_sessions_tree.remove(session_uuid_s)? {
|
|
Some(_) => Ok(Redirect::to(uri!(pages::history))),
|
|
None => Err(Status::NotFound.into()),
|
|
}
|
|
|
|
// TODO: mark as deleted instead of removing
|
|
// Ok(past_sessions_tree.transaction(|tx_past_sessions| {
|
|
// match tx_past_sessions.get(&session_uuid_s)? {
|
|
// None => return Ok(Err(Status::NotFound)),
|
|
// Some(data) => {
|
|
// let mut past_session: past_sessions::V = deserialize(&data).unwrap();
|
|
// }
|
|
// }
|
|
// Ok(Ok(Redirect::to(uri!(pages::history))))
|
|
// })??)
|
|
}
|