Make bump session button pretty

This commit is contained in:
2021-04-30 16:56:04 +02:00
parent a680c4abaa
commit 766fd30842
10 changed files with 192 additions and 101 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,9 +339,7 @@ where
.num_seconds() as f32;
let weeks = days.iter().group_by(|(day, _)| day.iso_week());
CalendarCtx {
days: weeks
let mut weeks: Vec<_> = weeks
.into_iter()
.map(|(week, weekdays)| {
weekdays
@ -385,8 +383,13 @@ where
})
.collect()
})
.collect(),
}
.collect();
// calendar is shown as flex-direction: row-reverse
// because it should be scrolled from the right
weeks.reverse();
CalendarCtx { weeks }
}
#[cfg(test)]

View File

@ -1,6 +1,9 @@
.cal {
display: flex;
flex-direction: row;
flex-direction: row-reverse;
overflow-y: auto;
max-width: max-content;
padding-left: 2rem;
}
.cal_col {

View File

@ -120,6 +120,36 @@ ul.striped_list > li:nth-child(odd) ul li:nth-child(odd) { background-color:#30
border-width: 0px 0 0px 50px;
}
.category_bump_button {
position: absolute;
border: 0;
padding: 0;
margin: 0;
width: 3rem;
height: 3rem;
margin-left: -1.2rem;
border-radius: 1.5rem;
border: solid #a4829c 0.3rem;
font-family: Ubuntu;
font-weight: 1000;
background: dimgray;
color: wheat;
transition: all ease-in-out 0.2s;
}
.category_bump_button:hover {
background: wheat;
color: dimgray;
cursor: pointer;
transition: background color ease-in-out 0.2s;
}
.category_bump_button:active {
}
.history_entry {
padding: 0.2em;
padding-left: 0.5em;

View File

@ -4,14 +4,34 @@
style="background-color: {{this.category.color}}"
></div>
<span class="category_name">{{this.category.name}}</span>
{{#if this.category.started}}
<form action="/api/category/{{@key}}/bump_session/minutes/5", method="post">
<button style="height: 100%; color: green;" type="submit">+5</button>
</form>
{{/if}}
<div class="category_button_container">
{{#if this.category.started}}
<form
action="/category/{{@key}}/bump_session/minutes/5"
id="bump-form-{{@key}}"
method="post"></form>
<button
class="category_bump_button"
form="bump-form-{{@key}}"
type="submit">+5m</button>
{{/if}}
<!-- without this extra tag, every even noscript tag seems to not trigger -->
<!-- what is even happening help -->
<noscript></noscript>
<noscript>
<form
{{#if this.category.started}}
action="/category/{{@key}}/end_session"
{{else}}
action="/category/{{@key}}/start_session"
{{/if}}
id="toggle-form-{{@key}}"
method="post"></form>
</noscript>
<button
id="toggle-button-{{@key}}"
type="submit"
form="toggle-form-{{@key}}"
onClick="toggle_category('{{@key}}')"
{{#if this.category.started}}
class="category_button category_button_toggled"

View File

@ -2,7 +2,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<!--
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline'">
-->
<link rel="icon" type="image/svg+xml" href="/static/icon.svg">
<link rel="stylesheet" href="/static/styles/common.css">

View File

@ -2,6 +2,14 @@
<html lang="en">
{{> head}}
<body>
{{> header}}
<ul class="striped_list">
{{#each categories}}
{{>category_entry}}
{{/each}}
</ul>
<script>
function toggle_category(id) {
// Find out whether the button is in active (play) or inactive (paused) state
@ -26,16 +34,15 @@
//Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE) {
console.log(xhr.status, xhr.responseText);
document.location.reload(false /* don't reset scroll position */);
}
};
xhr.send();
}
</script>
{{> header}}
<ul class="striped_list">
{{#each categories}}
{{>category_entry}}
{{/each}}
</ul>
</body>
</html>

View File

@ -19,7 +19,7 @@
</h2>
<h2>Senaste veckorna:</h2>
<div class="cal">
{{#each calendar.days}}
{{#each calendar.weeks}}
<div class="cal_col">
{{#each this}}
{{#if this}}