wip
This commit is contained in:
167
server/src/routes/api/session.rs
Normal file
167
server/src/routes/api/session.rs
Normal file
@ -0,0 +1,167 @@
|
||||
use crate::auth::Authorized;
|
||||
use crate::routes::pages;
|
||||
use crate::status_json::StatusJson;
|
||||
use crate::util::EventNotifier;
|
||||
use bincode::{deserialize, serialize};
|
||||
use chrono::{Duration, Local, NaiveDateTime, TimeZone};
|
||||
use rocket::form::{Form, FromForm};
|
||||
use rocket::http::Status;
|
||||
use rocket::response::Redirect;
|
||||
use rocket::serde::uuid::Uuid;
|
||||
use rocket::{post, uri, State};
|
||||
use sled::Transactional;
|
||||
|
||||
#[post("/category/<category_uuid>/start_session")]
|
||||
pub fn start_session(
|
||||
_auth: Authorized,
|
||||
category_uuid: Uuid,
|
||||
event_notifier: &State<EventNotifier>,
|
||||
db: &State<sled::Db>,
|
||||
) -> Result<StatusJson, StatusJson> {
|
||||
toggle_category_session(category_uuid, true, event_notifier, db)
|
||||
}
|
||||
|
||||
#[post("/category/<category_uuid>/end_session")]
|
||||
pub fn end_session(
|
||||
_auth: Authorized,
|
||||
category_uuid: Uuid,
|
||||
event_notifier: &State<EventNotifier>,
|
||||
db: &State<sled::Db>,
|
||||
) -> Result<StatusJson, StatusJson> {
|
||||
toggle_category_session(category_uuid, false, event_notifier, db)
|
||||
}
|
||||
|
||||
pub fn toggle_category_session(
|
||||
category_uuid: Uuid,
|
||||
set_active: bool,
|
||||
event_notifier: &State<EventNotifier>,
|
||||
db: &State<sled::Db>,
|
||||
) -> Result<StatusJson, StatusJson> {
|
||||
use crate::database::latest::trees::{category, session};
|
||||
|
||||
let category_uuid_s = sled::IVec::from(serialize(&category_uuid)?);
|
||||
|
||||
let categories_tree = db.open_tree(category::NAME)?;
|
||||
let sessions_tree = db.open_tree(session::NAME)?;
|
||||
|
||||
Ok(
|
||||
(&categories_tree, &sessions_tree).transaction(|(tx_categories, tx_sessions)| {
|
||||
match tx_categories.get(&category_uuid_s)? {
|
||||
None => return Ok(Err(Status::NotFound)),
|
||||
Some(data) => {
|
||||
let mut category: category::V = deserialize(&data).unwrap();
|
||||
let now = Local::now();
|
||||
|
||||
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 session = session::V {
|
||||
category: category_uuid,
|
||||
started,
|
||||
ended: now,
|
||||
deleted: category.deleted,
|
||||
};
|
||||
tx_sessions.insert(session_uuid, serialize(&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())?;
|
||||
event_notifier.notify_event();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Ok(Status::Ok.into()))
|
||||
})??,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, FromForm)]
|
||||
pub struct EditSession {
|
||||
category: Uuid,
|
||||
started: String,
|
||||
ended: String,
|
||||
deleted: bool,
|
||||
}
|
||||
|
||||
#[post("/session/<session_uuid>/edit", data = "<session>")]
|
||||
pub fn edit_session(
|
||||
_auth: Authorized,
|
||||
session_uuid: Uuid,
|
||||
session: Form<EditSession>,
|
||||
db: &State<sled::Db>,
|
||||
) -> Result<Redirect, StatusJson> {
|
||||
use crate::database::latest::trees::session;
|
||||
|
||||
let session_uuid_s = sled::IVec::from(serialize(&session_uuid)?);
|
||||
|
||||
let session = session::V {
|
||||
category: session.category,
|
||||
started: Local
|
||||
.from_local_datetime(&NaiveDateTime::parse_from_str(
|
||||
&session.started,
|
||||
"%Y-%m-%d %H:%M",
|
||||
)?)
|
||||
.unwrap(),
|
||||
ended: Local
|
||||
.from_local_datetime(&NaiveDateTime::parse_from_str(
|
||||
&session.ended,
|
||||
"%Y-%m-%d %H:%M",
|
||||
)?)
|
||||
.unwrap(),
|
||||
deleted: session.deleted,
|
||||
};
|
||||
|
||||
if session.started >= session.ended {
|
||||
return Err(StatusJson::new(
|
||||
Status::BadRequest,
|
||||
"started must be earlier than ended",
|
||||
));
|
||||
}
|
||||
|
||||
db.open_tree(session::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(
|
||||
_auth: Authorized,
|
||||
session_uuid: Uuid,
|
||||
db: &State<sled::Db>,
|
||||
) -> Result<Redirect, StatusJson> {
|
||||
use crate::database::latest::trees::session;
|
||||
|
||||
let session_uuid_s = sled::IVec::from(serialize(&session_uuid)?);
|
||||
|
||||
let sessions_tree = db.open_tree(session::NAME)?;
|
||||
|
||||
match 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(sessions_tree.transaction(|tx_sessions| {
|
||||
// match tx_sessions.get(&session_uuid_s)? {
|
||||
// None => return Ok(Err(Status::NotFound)),
|
||||
// Some(data) => {
|
||||
// let mut session: session::V = deserialize(&data).unwrap();
|
||||
// }
|
||||
// }
|
||||
// Ok(Ok(Redirect::to(uri!(pages::history))))
|
||||
// })??)
|
||||
}
|
||||
Reference in New Issue
Block a user