From aa23f156827ff4b8813f49bd958034de5708d50b Mon Sep 17 00:00:00 2001 From: philipp Date: Sun, 29 Oct 2023 18:42:12 +0100 Subject: [PATCH 01/27] first draft --- migration.sql | 1 + seeds.sql | 6 +++--- src/model/logbook.rs | 47 ++++++++++++++++++++++++++++++++++++++++---- src/tera/log.rs | 34 ++++++++++++++++---------------- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/migration.sql b/migration.sql index bff1516..f81938d 100644 --- a/migration.sql +++ b/migration.sql @@ -87,6 +87,7 @@ CREATE TABLE IF NOT EXISTS "logbook" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "boat_id" INTEGER NOT NULL REFERENCES boat(id), "shipmaster" INTEGER NOT NULL REFERENCES user(id), + "steering_person" INTEGER NOT NULL REFERENCES user(id), "shipmaster_only_steering" boolean not null, "departure" datetime not null, "arrival" datetime, -- None -> ship is on water diff --git a/seeds.sql b/seeds.sql index e825338..888f552 100644 --- a/seeds.sql +++ b/seeds.sql @@ -26,9 +26,9 @@ INSERT INTO "boat" (name, amount_seats, location_id) VALUES ('Ottensheim Boot', INSERT INTO "boat" (name, amount_seats, location_id, owner) VALUES ('second_private_boat_from_rower', 1, 1, 2); INSERT INTO "logbook_type" (name) VALUES ('Wanderfahrt'); INSERT INTO "logbook_type" (name) VALUES ('Regatta'); -INSERT INTO "logbook" (boat_id, shipmaster, shipmaster_only_steering, departure) VALUES (2, 2, false, '1142-12-24 10:00'); -INSERT INTO "logbook" (boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km) VALUES (1, 4, false, '1141-12-24 10:00', '2141-12-24 15:00', 'Ottensheim', 25); -INSERT INTO "logbook" (boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km) VALUES (3, 4, false, '1142-12-24 10:00', '2142-12-24 11:30', 'Ottensheim + Regattastrecke', 29); +INSERT INTO "logbook" (boat_id, shipmaster,steering_person, shipmaster_only_steering, departure) VALUES (2, 2, 2, false, '1142-12-24 10:00'); +INSERT INTO "logbook" (boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km) VALUES (1, 4, 4, false, '1141-12-24 10:00', '2141-12-24 15:00', 'Ottensheim', 25); +INSERT INTO "logbook" (boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km) VALUES (3, 4, 4, false, '1142-12-24 10:00', '2142-12-24 11:30', 'Ottensheim + Regattastrecke', 29); INSERT INTO "rower" (logbook_id, rower_id) VALUES(3,3); INSERT INTO "boat_damage" (boat_id, desc, user_id_created, created_at) VALUES(4,'Dolle bei Position 2 fehlt', 5, '2142-12-24 15:02'); INSERT INTO "boat_damage" (boat_id, desc, user_id_created, created_at, lock_boat) VALUES(5, 'TOHT', 5, '2142-12-24 15:02', 1); diff --git a/src/model/logbook.rs b/src/model/logbook.rs index 4289231..5d2e763 100644 --- a/src/model/logbook.rs +++ b/src/model/logbook.rs @@ -11,6 +11,7 @@ pub struct Logbook { pub id: i64, pub boat_id: i64, pub shipmaster: i64, + pub steering_person: i64, #[serde(default = "bool::default")] pub shipmaster_only_steering: bool, pub departure: NaiveDateTime, @@ -31,6 +32,7 @@ impl PartialEq for Logbook { pub struct LogToAdd { pub boat_id: i32, pub shipmaster: i64, + pub steering_person: i64, pub shipmaster_only_steering: bool, pub departure: String, pub arrival: Option, @@ -43,6 +45,11 @@ pub struct LogToAdd { #[derive(FromForm, Debug)] pub struct LogToFinalize { + pub shipmaster: i64, + pub steering_person: i64, + pub shipmaster_only_steering: bool, + pub departure: String, + pub arrival: String, pub destination: String, pub distance_in_km: i64, pub comments: Option, @@ -56,6 +63,7 @@ pub struct LogbookWithBoatAndRowers { pub logbook: Logbook, pub boat: Boat, pub shipmaster_user: User, + pub steering_user: User, pub rowers: Vec, } @@ -93,7 +101,7 @@ impl Logbook { sqlx::query_as!( Self, " - SELECT id,boat_id,shipmaster,shipmaster_only_steering,departure,arrival,destination,distance_in_km,comments,logtype + SELECT id,boat_id,shipmaster,steering_person,shipmaster_only_steering,departure,arrival,destination,distance_in_km,comments,logtype FROM logbook WHERE id like ? ", @@ -107,7 +115,7 @@ impl Logbook { pub async fn on_water(db: &SqlitePool) -> Vec { let rows = sqlx::query!( " -SELECT id, boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype +SELECT id, boat_id, shipmaster,steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype FROM logbook WHERE arrival is null ORDER BY departure DESC @@ -123,6 +131,7 @@ ORDER BY departure DESC id: row.id, boat_id: row.boat_id, shipmaster: row.shipmaster, + steering_person: row.steering_person, shipmaster_only_steering: row.shipmaster_only_steering, departure: row.departure, arrival: row.arrival, @@ -139,6 +148,9 @@ ORDER BY departure DESC rowers: Rower::for_log(db, &log).await, boat: Boat::find_by_id(db, log.boat_id as i32).await.unwrap(), shipmaster_user: User::find_by_id(db, log.shipmaster as i32).await.unwrap(), + steering_user: User::find_by_id(db, log.steering_person as i32) + .await + .unwrap(), logbook: log, }); } @@ -149,7 +161,7 @@ ORDER BY departure DESC let logs = sqlx::query_as!( Logbook, " - SELECT id, boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype + SELECT id, boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype FROM logbook WHERE arrival is not null ORDER BY departure DESC @@ -165,6 +177,9 @@ ORDER BY departure DESC rowers: Rower::for_log(db, &log).await, boat: Boat::find_by_id(db, log.boat_id as i32).await.unwrap(), shipmaster_user: User::find_by_id(db, log.shipmaster as i32).await.unwrap(), + steering_user: User::find_by_id(db, log.steering_person as i32) + .await + .unwrap(), logbook: log, }); } @@ -252,9 +267,10 @@ ORDER BY departure DESC //}); //let arrival = log.arrival.map(|a| format!("{}+02:00", a)); let inserted_row = sqlx::query!( - "INSERT INTO logbook(boat_id, shipmaster, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?) RETURNING id", + "INSERT INTO logbook(boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING id", log.boat_id, log.shipmaster, + log.steering_person, log.shipmaster_only_steering, log.departure, log.arrival, @@ -444,6 +460,7 @@ mod test { LogToAdd { boat_id: 3, shipmaster: 4, + steering_person: 4, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -468,6 +485,7 @@ mod test { LogToAdd { boat_id: 999, shipmaster: 5, + steering_person: 5, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -493,6 +511,7 @@ mod test { LogToAdd { boat_id: 5, shipmaster: 5, + steering_person: 5, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -518,6 +537,7 @@ mod test { LogToAdd { boat_id: 2, shipmaster: 5, + steering_person: 5, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -543,6 +563,7 @@ mod test { LogToAdd { boat_id: 3, shipmaster: 5, + steering_person: 5, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: Some("2128-05-20T11:00".into()), @@ -568,6 +589,7 @@ mod test { LogToAdd { boat_id: 3, shipmaster: 2, + steering_person: 2, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -593,6 +615,7 @@ mod test { LogToAdd { boat_id: 3, shipmaster: 5, + steering_person: 5, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -618,6 +641,7 @@ mod test { LogToAdd { boat_id: 1, shipmaster: 5, + steering_person: 5, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -666,6 +690,11 @@ mod test { comments: Some("Perfect water".into()), logtype: None, rowers: vec![], + shipmaster: 2, + steering_person: 2, + shipmaster_only_steering: false, + departure: "1990-01-01T10:00".into(), + arrival: "1990-01-01T12:00".into(), }, ) .await @@ -689,6 +718,11 @@ mod test { comments: Some("Perfect water".into()), logtype: None, rowers: vec![], + shipmaster: 1, + steering_person: 1, + shipmaster_only_steering: false, + departure: "1990-01-01T10:00".into(), + arrival: "1990-01-01T12:00".into(), }, ) .await; @@ -713,6 +747,11 @@ mod test { comments: Some("Perfect water".into()), logtype: None, rowers: vec![1], + shipmaster: 2, + steering_person: 2, + shipmaster_only_steering: false, + departure: "1990-01-01T10:00".into(), + arrival: "1990-01-01T12:00".into(), }, ) .await; diff --git a/src/tera/log.rs b/src/tera/log.rs index fc4acba..b3787dc 100644 --- a/src/tera/log.rs +++ b/src/tera/log.rs @@ -162,15 +162,6 @@ async fn create_logbook( data: Form, user: &NonGuestUser, ) -> Flash { - Log::create( - db, - format!( - "User {} tries to create log entry={:?}", - user.user.name, data - ), - ) - .await; - match Logbook::create( db, data.into_inner(), @@ -201,6 +192,15 @@ async fn create( data: Form, user: NonGuestUser, ) -> Flash { + Log::create( + db, + format!( + "User {} tries to create log entry={:?}", + user.user.name, data + ), + ) + .await; + create_logbook(db, data, &user).await } @@ -515,7 +515,7 @@ mod test { let req = client .post("/log") .header(ContentType::Form) - .body("boat_id=1&shipmaster=4&departure=2199-12-31T10:00"); + .body("boat_id=1&shipmaster=4&departure=2199-12-31T10:00&steering_person=4"); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -546,7 +546,7 @@ mod test { let req = client .post("/log/1") .header(ContentType::Form) - .body("destination=Ottensheim&distance_in_km=25"); + .body("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure=1990-01-01T10:00&arrival=1990-01-01T12:00"); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -655,7 +655,7 @@ mod test { let shipmaster_id = User::find_by_name(&db, "rower2".into()).await.unwrap().id; let req = client.post("/log").header(ContentType::Form).body(format!( - "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00" + "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}" )); let response = req.dispatch().await; @@ -684,7 +684,7 @@ mod test { let req = client .post(format!("/log/{log_id}")) .header(ContentType::Form) - .body("destination=Ottensheim&distance_in_km=25"); + .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1990-01-01T10:00&arrival=1990-01-01T12:00")); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -875,7 +875,7 @@ mod test { let req = client .post("/log/1") .header(ContentType::Form) - .body("destination=Ottensheim&distance_in_km=25"); + .body("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure=1199-12-12T10:00&arrival=1199-12-12T12:00"); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -902,7 +902,7 @@ mod test { let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id; let req = client.post("/log").header(ContentType::Form).body(format!( - "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00" + "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}" )); let response = req.dispatch().await; @@ -924,7 +924,7 @@ mod test { let req = client .post(format!("/log/{log_id}")) .header(ContentType::Form) - .body("destination=Ottensheim&distance_in_km=25"); + .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1199-12-31T10:00&arrival=1199-12-31T12:00")); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -952,7 +952,7 @@ mod test { let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id; let req = client.post("/log").header(ContentType::Form).body(format!( - "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=2199-12-31T10:00" + "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=2199-12-31T10:00&steering_person={shipmaster_id}" )); let response = req.dispatch().await; From 1689f4a1eef409f6368cf461672918316d25d46a Mon Sep 17 00:00:00 2001 From: philipp Date: Sun, 29 Oct 2023 20:41:30 +0100 Subject: [PATCH 02/27] finish backend tests of new db layout --- src/model/boat.rs | 8 +- src/model/log.rs | 8 +- src/model/logbook.rs | 259 ++++++++++++++++++++++++++++--------------- src/model/user.rs | 17 ++- src/tera/log.rs | 30 ++--- 5 files changed, 216 insertions(+), 106 deletions(-) diff --git a/src/model/boat.rs b/src/model/boat.rs index e939493..f5a1d2d 100644 --- a/src/model/boat.rs +++ b/src/model/boat.rs @@ -1,6 +1,6 @@ use rocket::serde::{Deserialize, Serialize}; use rocket::FromForm; -use sqlx::{FromRow, SqlitePool}; +use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use super::user::User; @@ -70,6 +70,12 @@ impl Boat { .await .ok() } + pub async fn find_by_id_tx(db: &mut Transaction<'_, Sqlite>, id: i32) -> Option { + sqlx::query_as!(Self, "SELECT * FROM boat WHERE id like ?", id) + .fetch_one(db) + .await + .ok() + } pub async fn find_by_name(db: &SqlitePool, name: String) -> Option { sqlx::query_as!(Self, "SELECT * FROM boat WHERE name like ?", name) diff --git a/src/model/log.rs b/src/model/log.rs index b862c79..3b9b4a8 100644 --- a/src/model/log.rs +++ b/src/model/log.rs @@ -1,6 +1,6 @@ use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc}; use serde::{Deserialize, Serialize}; -use sqlx::{FromRow, SqlitePool}; +use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; #[derive(FromRow, Debug, Serialize, Deserialize)] pub struct Log { @@ -15,6 +15,12 @@ impl Log { .await .is_ok() } + pub async fn create_with_tx(db: &mut Transaction<'_, Sqlite>, msg: String) -> bool { + sqlx::query!("INSERT INTO log(msg) VALUES (?)", msg,) + .execute(db) + .await + .is_ok() + } async fn last(db: &SqlitePool) -> Vec { sqlx::query_as!( diff --git a/src/model/logbook.rs b/src/model/logbook.rs index 5d2e763..9729a59 100644 --- a/src/model/logbook.rs +++ b/src/model/logbook.rs @@ -1,5 +1,4 @@ -use chrono::{NaiveDateTime, TimeZone}; -use chrono_tz::Europe::Vienna; +use chrono::NaiveDateTime; use rocket::FromForm; use serde::Serialize; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; @@ -28,7 +27,7 @@ impl PartialEq for Logbook { } } -#[derive(FromForm, Debug)] +#[derive(FromForm, Debug, Clone)] pub struct LogToAdd { pub boat_id: i32, pub shipmaster: i64, @@ -57,6 +56,30 @@ pub struct LogToFinalize { pub rowers: Vec, } +impl TryFrom for LogToFinalize { + type Error = String; + + fn try_from(value: LogToAdd) -> Result { + if let (Some(arrival), Some(destination), Some(distance_in_km)) = + (value.arrival, value.destination, value.distance_in_km) + { + return Ok(LogToFinalize { + arrival, + destination, + distance_in_km, + shipmaster: value.shipmaster, + steering_person: value.steering_person, + shipmaster_only_steering: value.shipmaster_only_steering, + departure: value.departure, + comments: value.comments, + logtype: value.logtype, + rowers: value.rowers, + }); + } + Err("Arrival, destination or distance_in_km not set".into()) + } +} + #[derive(Serialize, Debug)] pub struct LogbookWithBoatAndRowers { #[serde(flatten)] @@ -73,6 +96,9 @@ pub enum LogbookUpdateError { TooManyRowers(usize, usize), RowerCreateError(i64, String), ArrivalNotAfterDeparture, + ShipmasterNotInRowers, + SteeringPersonNotInRowers, + UserNotAllowedToUseBoat, } #[derive(Debug, PartialEq)] @@ -82,18 +108,40 @@ pub enum LogbookDeleteError { #[derive(Debug, PartialEq)] pub enum LogbookCreateError { - ArrivalSetButNoDestination, UserNotAllowedToUseBoat, - ArrivalSetButNoDistance, BoatAlreadyOnWater, BoatLocked, BoatNotFound, TooManyRowers(usize, usize), - ShipmasterAlreadyOnWater, RowerAlreadyOnWater(User), RowerCreateError(i64, String), - SamePersonShipmasterAndRower, ArrivalNotAfterDeparture, + SteeringPersonNotInRowers, + ShipmasterNotInRowers, + NotYourEntry, + ArrivalSetButNotRemainingTwo, +} + +impl From for LogbookCreateError { + fn from(value: LogbookUpdateError) -> Self { + return match value { + LogbookUpdateError::NotYourEntry => LogbookCreateError::NotYourEntry, + LogbookUpdateError::TooManyRowers(a, b) => LogbookCreateError::TooManyRowers(a, b), + LogbookUpdateError::RowerCreateError(a, b) => { + LogbookCreateError::RowerCreateError(a, b) + } + LogbookUpdateError::ArrivalNotAfterDeparture => { + LogbookCreateError::ArrivalNotAfterDeparture + } + LogbookUpdateError::ShipmasterNotInRowers => LogbookCreateError::ShipmasterNotInRowers, + LogbookUpdateError::SteeringPersonNotInRowers => { + LogbookCreateError::SteeringPersonNotInRowers + } + LogbookUpdateError::UserNotAllowedToUseBoat => { + LogbookCreateError::UserNotAllowedToUseBoat + } + }; + } } impl Logbook { @@ -115,7 +163,7 @@ impl Logbook { pub async fn on_water(db: &SqlitePool) -> Vec { let rows = sqlx::query!( " -SELECT id, boat_id, shipmaster,steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype +SELECT id, boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype FROM logbook WHERE arrival is null ORDER BY departure DESC @@ -191,6 +239,44 @@ ORDER BY departure DESC log: LogToAdd, created_by_user: &User, ) -> Result<(), LogbookCreateError> { + println!("{log:#?}"); + if let Ok(log_to_finalize) = TryInto::::try_into(log.clone()) { + //TODO: fix clone() + let mut tx = db.begin().await.unwrap(); + + let inserted_row = sqlx::query!( + "INSERT INTO logbook(boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING id", + log.boat_id, + log.shipmaster, + log.steering_person, + log.shipmaster_only_steering, + log.departure, + log.arrival, + log.destination, + log.distance_in_km, + log.comments, + log.logtype + ) + .fetch_one(&mut tx) + .await.unwrap().id; + + let logbook = Logbook::find_by_id(db, inserted_row as i32).await.unwrap(); //ok + + return match logbook + .home_with_transaction(&mut tx, created_by_user, log_to_finalize) + .await + { + Ok(_) => { + tx.commit().await.unwrap(); + Ok(()) + } + Err(a) => Err(a.into()), + }; + } + if log.arrival.is_some() { + return Err(LogbookCreateError::ArrivalSetButNotRemainingTwo); + } + let Some(boat) = Boat::find_by_id(db, log.boat_id).await else { return Err(LogbookCreateError::BoatNotFound); }; @@ -203,39 +289,22 @@ ORDER BY departure DESC return Err(LogbookCreateError::BoatAlreadyOnWater); } - let shipmaster = User::find_by_id(db, log.shipmaster as i32).await.unwrap(); - - if shipmaster.on_water(db).await { - return Err(LogbookCreateError::ShipmasterAlreadyOnWater); + if !log.rowers.contains(&log.shipmaster) { + return Err(LogbookCreateError::ShipmasterNotInRowers); + } + if !log.rowers.contains(&log.steering_person) { + return Err(LogbookCreateError::SteeringPersonNotInRowers); } - if let Some(arrival) = &log.arrival { - let dep = NaiveDateTime::parse_from_str(&log.departure, "%Y-%m-%dT%H:%M").unwrap(); - let arr = NaiveDateTime::parse_from_str(arrival, "%Y-%m-%dT%H:%M").unwrap(); - if arr <= dep { - return Err(LogbookCreateError::ArrivalNotAfterDeparture); - } - - if log.destination.is_none() { - return Err(LogbookCreateError::ArrivalSetButNoDestination); - } - if log.distance_in_km.is_none() { - return Err(LogbookCreateError::ArrivalSetButNoDistance); - } - } - - if log.rowers.len() > boat.amount_seats as usize - 1 { + if log.rowers.len() > boat.amount_seats as usize { return Err(LogbookCreateError::TooManyRowers( boat.amount_seats as usize, - log.rowers.len() + 1, + log.rowers.len(), )); } for rower in &log.rowers { let user = User::find_by_id(db, *rower as i32).await.unwrap(); - if *rower == log.shipmaster { - return Err(LogbookCreateError::SamePersonShipmasterAndRower); - } if user.on_water(db).await { return Err(LogbookCreateError::RowerAlreadyOnWater(user)); @@ -251,21 +320,6 @@ ORDER BY departure DESC let mut tx = db.begin().await.unwrap(); - //let departure = NaiveDateTime::parse_from_str(&log.departure, "%Y-%m-%dT%H:%M").unwrap(); - //let departure_vienna = chrono::Utc - // .from_local_datetime(&departure) - // .single() - // .unwrap(); - //let departure_utc = departure_vienna.with_timezone(&Vienna); - - //let arrival = log.arrival.map(|a| { - // let arr = NaiveDateTime::parse_from_str(&a, "%Y-%m-%dT%H:%M").unwrap(); - // let arr_vienna = Vienna.from_local_datetime(&arr).single().unwrap(); - // arr_vienna - // .with_timezone(&chrono::Utc) - // .format("%Y-%m-%d %H:%M") - //}); - //let arrival = log.arrival.map(|a| format!("{}+02:00", a)); let inserted_row = sqlx::query!( "INSERT INTO logbook(boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING id", log.boat_id, @@ -335,51 +389,80 @@ ORDER BY departure DESC user: &User, log: LogToFinalize, ) -> Result<(), LogbookUpdateError> { + let mut tx = db.begin().await.unwrap(); + self.home_with_transaction(&mut tx, user, log).await?; + tx.commit().await.unwrap(); + Ok(()) + } + + async fn home_with_transaction( + &self, + db: &mut Transaction<'_, Sqlite>, + user: &User, + log: LogToFinalize, + ) -> Result<(), LogbookUpdateError> { + //TODO: extract common tests with `create()` if user.id != self.shipmaster { return Err(LogbookUpdateError::NotYourEntry); } - let boat = Boat::find_by_id(db, self.boat_id as i32).await.unwrap(); //ok + if !log.rowers.contains(&log.shipmaster) { + return Err(LogbookUpdateError::ShipmasterNotInRowers); + } + if !log.rowers.contains(&log.steering_person) { + return Err(LogbookUpdateError::SteeringPersonNotInRowers); + } - if log.rowers.len() > boat.amount_seats as usize - 1 { + let boat = Boat::find_by_id_tx(db, self.boat_id as i32).await.unwrap(); //ok + + if !boat.shipmaster_allowed(&user).await && self.shipmaster != user.id { + //second part: + //shipmaster has + //entered a + //different user, + //then the user + //should be able + //to `home` it + return Err(LogbookUpdateError::UserNotAllowedToUseBoat); + } + + if log.rowers.len() > boat.amount_seats as usize { return Err(LogbookUpdateError::TooManyRowers( boat.amount_seats as usize, - log.rowers.len() + 1, + log.rowers.len(), )); } - let arrival = chrono::offset::Utc::now().naive_utc(); - let arrival = Vienna.from_utc_datetime(&arrival); - - if arrival.timestamp() + 60 * 60 * 2 <= self.departure.timestamp() { - //TODO: fixme + let dep = NaiveDateTime::parse_from_str(&log.departure, "%Y-%m-%dT%H:%M").unwrap(); + let arr = NaiveDateTime::parse_from_str(&log.arrival, "%Y-%m-%dT%H:%M").unwrap(); + if arr.timestamp() <= dep.timestamp() { return Err(LogbookUpdateError::ArrivalNotAfterDeparture); } - Log::create(db, format!("New trip: {log:?}")).await; - let mut tx = db.begin().await.unwrap(); - - sqlx::query!( - "UPDATE logbook SET destination=?, distance_in_km=?, comments=?, logtype=?, arrival=? WHERE id=?", - log.destination, - log.distance_in_km, - log.comments, - log.logtype, - arrival, - self.id - ) - .execute(&mut tx) - .await.unwrap(); //TODO: fixme - - self.remove_rowers(&mut tx).await; + Log::create_with_tx(db, format!("New trip: {log:?}")).await; + self.remove_rowers(db).await; for rower in &log.rowers { - Rower::create(&mut tx, self.id, *rower) + Rower::create(db, self.id, *rower) .await .map_err(|e| LogbookUpdateError::RowerCreateError(*rower, e.to_string()))?; } - tx.commit().await.unwrap(); + sqlx::query!( + "UPDATE logbook SET shipmaster=?, steering_person=?, shipmaster_only_steering=?, departure=?, destination=?, distance_in_km=?, comments=?, logtype=?, arrival=? WHERE id=?", + log.shipmaster, + log.steering_person, + log.shipmaster_only_steering, + log.departure, + log.destination, + log.distance_in_km, + log.comments, + log.logtype, + log.arrival, + self.id + ) + .execute(db) + .await.unwrap(); //TODO: fixme Ok(()) } @@ -468,7 +551,7 @@ mod test { distance_in_km: None, comments: None, logtype: None, - rowers: Vec::new(), + rowers: vec![4], }, &User::find_by_id(&pool, 4).await.unwrap(), ) @@ -493,7 +576,7 @@ mod test { distance_in_km: None, comments: None, logtype: None, - rowers: Vec::new(), + rowers: vec![5], }, &User::find_by_id(&pool, 4).await.unwrap(), ) @@ -519,7 +602,7 @@ mod test { distance_in_km: None, comments: None, logtype: None, - rowers: Vec::new(), + rowers: vec![5], }, &User::find_by_id(&pool, 4).await.unwrap(), ) @@ -545,7 +628,7 @@ mod test { distance_in_km: None, comments: None, logtype: None, - rowers: Vec::new(), + rowers: vec![5], }, &User::find_by_id(&pool, 5).await.unwrap(), ) @@ -571,17 +654,17 @@ mod test { distance_in_km: None, comments: None, logtype: None, - rowers: Vec::new(), + rowers: vec![5], }, &User::find_by_id(&pool, 5).await.unwrap(), ) .await; - assert_eq!(res, Err(LogbookCreateError::ArrivalNotAfterDeparture)); + assert_eq!(res, Err(LogbookCreateError::ArrivalSetButNotRemainingTwo)); } #[sqlx::test] - fn test_create_shipmaster_on_water() { + fn test_create_shipmaster_not_in_rowers() { let pool = testdb!(); let res = Logbook::create( @@ -603,11 +686,11 @@ mod test { ) .await; - assert_eq!(res, Err(LogbookCreateError::ShipmasterAlreadyOnWater)); + assert_eq!(res, Err(LogbookCreateError::ShipmasterNotInRowers)); } #[sqlx::test] - fn test_create_same_person_cox_and_rower() { + fn test_create_steering_person_not_in_rowers() { let pool = testdb!(); let res = Logbook::create( @@ -615,7 +698,7 @@ mod test { LogToAdd { boat_id: 3, shipmaster: 5, - steering_person: 5, + steering_person: 1, shipmaster_only_steering: false, departure: "2128-05-20T12:00".into(), arrival: None, @@ -629,7 +712,7 @@ mod test { ) .await; - assert_eq!(res, Err(LogbookCreateError::SamePersonShipmasterAndRower)); + assert_eq!(res, Err(LogbookCreateError::SteeringPersonNotInRowers)); } #[sqlx::test] @@ -649,7 +732,7 @@ mod test { distance_in_km: None, comments: None, logtype: None, - rowers: vec![1], + rowers: vec![1, 5], }, &User::find_by_id(&pool, 5).await.unwrap(), ) @@ -689,7 +772,7 @@ mod test { distance_in_km: 42, comments: Some("Perfect water".into()), logtype: None, - rowers: vec![], + rowers: vec![2], shipmaster: 2, steering_person: 2, shipmaster_only_steering: false, @@ -717,7 +800,7 @@ mod test { distance_in_km: 42, comments: Some("Perfect water".into()), logtype: None, - rowers: vec![], + rowers: vec![1], shipmaster: 1, steering_person: 1, shipmaster_only_steering: false, @@ -746,7 +829,7 @@ mod test { distance_in_km: 42, comments: Some("Perfect water".into()), logtype: None, - rowers: vec![1], + rowers: vec![1, 2], shipmaster: 2, steering_person: 2, shipmaster_only_steering: false, diff --git a/src/model/user.rs b/src/model/user.rs index 8a0dc85..8a6366d 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -11,7 +11,7 @@ use rocket::{ Request, }; use serde::{Deserialize, Serialize}; -use sqlx::{FromRow, SqlitePool}; +use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use super::{log::Log, tripdetails::TripDetails, Day}; @@ -103,6 +103,21 @@ WHERE id like ? .ok() } + pub async fn find_by_id_tx(db: &mut Transaction<'_, Sqlite>, id: i32) -> Option { + sqlx::query_as!( + Self, + " +SELECT id, name, pw, is_cox, is_admin, is_guest, deleted, last_access, is_tech +FROM user +WHERE id like ? + ", + id + ) + .fetch_one(db) + .await + .ok() + } + pub async fn find_by_name(db: &SqlitePool, name: &str) -> Option { sqlx::query_as!( Self, diff --git a/src/tera/log.rs b/src/tera/log.rs index b3787dc..1e2bdbb 100644 --- a/src/tera/log.rs +++ b/src/tera/log.rs @@ -171,17 +171,17 @@ async fn create_logbook( { Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt erfolgreich hinzugefügt"), Err(LogbookCreateError::BoatAlreadyOnWater) => Flash::error(Redirect::to("/log"), "Boot schon am Wasser"), - Err(LogbookCreateError::ShipmasterAlreadyOnWater) => Flash::error(Redirect::to("/log"), "Schiffsführer schon am Wasser"), Err(LogbookCreateError::RowerAlreadyOnWater(rower)) => Flash::error(Redirect::to("/log"), format!("Ruderer {} schon am Wasser", rower.name)), Err(LogbookCreateError::BoatLocked) => Flash::error(Redirect::to("/log"),"Boot gesperrt"), Err(LogbookCreateError::BoatNotFound) => Flash::error(Redirect::to("/log"), "Boot gibt's ned"), Err(LogbookCreateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")), Err(LogbookCreateError::RowerCreateError(rower, e)) => Flash::error(Redirect::to("/log"), format!("Fehler bei Ruderer {rower}: {e}")), - Err(LogbookCreateError::SamePersonShipmasterAndRower) => Flash::error(Redirect::to("/log"), "Selbe Person als Schiffsführer und Ruderer ausgewählt"), - Err(LogbookCreateError::ArrivalSetButNoDistance) => Flash::error(Redirect::to("/log"), "Distanz notwendig, wenn Ankunftszeit angegeben wurde"), - Err(LogbookCreateError::ArrivalSetButNoDestination) => Flash::error(Redirect::to("/log"), "Ziel notwendig, wenn Ankunftszeit angegeben wurde"), Err(LogbookCreateError::ArrivalNotAfterDeparture) => Flash::error(Redirect::to("/log"), "Ankunftszeit kann nicht vor der Abfahrtszeit sein"), Err(LogbookCreateError::UserNotAllowedToUseBoat) => Flash::error(Redirect::to("/log"), "Schiffsführer darf dieses Boot nicht verwenden"), + Err(LogbookCreateError::SteeringPersonNotInRowers) => Flash::error(Redirect::to("/log"), "Steuerperson nicht in Liste der Ruderer!"), + Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(Redirect::to("/log"), "Schiffsführer nicht in Liste der Ruderer!"), + Err(LogbookCreateError::NotYourEntry) => Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!"), + Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(Redirect::to("/log"), "Ankunftszeit gesetzt aber nicht Distanz + Strecke"), } } @@ -240,9 +240,9 @@ async fn home_logbook( match logbook.home(db, &user.user, data.into_inner()).await { Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt korrekt eingetragen"), Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")), - Err(_) => Flash::error( + Err(e) => Flash::error( Redirect::to("/log"), - format!("Eintrag {} konnte nicht abgesendet werden!", logbook_id), + format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"), ), } } @@ -515,7 +515,7 @@ mod test { let req = client .post("/log") .header(ContentType::Form) - .body("boat_id=1&shipmaster=4&departure=2199-12-31T10:00&steering_person=4"); + .body("boat_id=1&shipmaster=4&departure=2199-12-31T10:00&steering_person=4&rowers[]=4"); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -546,7 +546,7 @@ mod test { let req = client .post("/log/1") .header(ContentType::Form) - .body("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure=1990-01-01T10:00&arrival=1990-01-01T12:00"); + .body("destination=Ottensheim&distance_in_km=25&shipmaster=2&steering_person=2&departure=1990-01-01T10:00&arrival=1990-01-01T12:00&rowers[]=2"); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -655,7 +655,7 @@ mod test { let shipmaster_id = User::find_by_name(&db, "rower2".into()).await.unwrap().id; let req = client.post("/log").header(ContentType::Form).body(format!( - "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}" + "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}" )); let response = req.dispatch().await; @@ -684,7 +684,7 @@ mod test { let req = client .post(format!("/log/{log_id}")) .header(ContentType::Form) - .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1990-01-01T10:00&arrival=1990-01-01T12:00")); + .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1990-01-01T10:00&arrival=1990-01-01T12:00&rowers[]={shipmaster_id}")); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -875,7 +875,7 @@ mod test { let req = client .post("/log/1") .header(ContentType::Form) - .body("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure=1199-12-12T10:00&arrival=1199-12-12T12:00"); + .body("destination=Ottensheim&distance_in_km=25&shipmaster=1&steering_person=1&departure=1199-12-12T10:00&arrival=1199-12-12T12:00&rowers[]=1"); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -888,7 +888,7 @@ mod test { assert_eq!( flash_cookie.value(), - "5:errorEintrag 1 konnte nicht abgesendet werden!" + "5:errorEintrag 1 konnte nicht abgesendet werden (Fehler: NotYourEntry)!" ); } @@ -902,7 +902,7 @@ mod test { let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id; let req = client.post("/log").header(ContentType::Form).body(format!( - "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}" + "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=1199-12-31T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}" )); let response = req.dispatch().await; @@ -924,7 +924,7 @@ mod test { let req = client .post(format!("/log/{log_id}")) .header(ContentType::Form) - .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1199-12-31T10:00&arrival=1199-12-31T12:00")); + .body(format!("destination=Ottensheim&distance_in_km=25&shipmaster={shipmaster_id}&steering_person={shipmaster_id}&departure=1199-12-31T10:00&arrival=1199-12-31T12:00&rowers[]={shipmaster_id}")); let response = req.dispatch().await; assert_eq!(response.status(), Status::SeeOther); @@ -952,7 +952,7 @@ mod test { let shipmaster_id = User::find_by_name(db, &shipmaster_name).await.unwrap().id; let req = client.post("/log").header(ContentType::Form).body(format!( - "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=2199-12-31T10:00&steering_person={shipmaster_id}" + "boat_id={boat_id}&shipmaster={shipmaster_id}&departure=2199-12-31T10:00&steering_person={shipmaster_id}&rowers[]={shipmaster_id}" )); let response = req.dispatch().await; From 67d86bb908b7a6cc72c2cbfa3f1d8f0b13d41182 Mon Sep 17 00:00:00 2001 From: philipp Date: Mon, 30 Oct 2023 09:21:35 +0100 Subject: [PATCH 03/27] do proper things in ui @ new log --- frontend/main.ts | 65 ++++++++++++++++++++------ templates/includes/forms/log.html.tera | 54 +++++---------------- 2 files changed, 63 insertions(+), 56 deletions(-) diff --git a/frontend/main.ts b/frontend/main.ts index f65bfe0..30c14ac 100644 --- a/frontend/main.ts +++ b/frontend/main.ts @@ -62,20 +62,8 @@ function selectBoatChange() { } } } as any); - - choiceObjects[boatSelect.id] = boatChoice; - } - const shipmasterSelect = document.querySelector('#shipmaster'); - if(shipmasterSelect) { - const shipmasterChoice = new Choices(shipmasterSelect, { - loadingText: 'Wird geladen...', - noResultsText: 'Keine Ergebnisse gefunden', - noChoicesText: 'Keine Ergebnisse gefunden', - itemSelectText: 'Zum Auswählen klicken', - }); - - choiceObjects[shipmasterSelect.id] = shipmasterChoice; + choiceObjects[boatSelect.id] = boatChoice; } } @@ -180,6 +168,16 @@ function initChoices() { } } +interface ChoiceEvent extends Event{ + detail: { + value: string; + label: string, + customProperties: { + is_cox: boolean, + } + }; +} + function initNewChoice(select: HTMLInputElement) { const choice = new Choices(select, { removeItemButton: true, @@ -194,9 +192,50 @@ function initNewChoice(select: HTMLInputElement) { }, }); + select.addEventListener('addItem', function(e) { + const event = e as ChoiceEvent; + const user_id = event.detail.value; + const name = event.detail.label; + + if (event.detail.customProperties.is_cox) { + const coxSelect = document.querySelector('#cox'); + if (coxSelect){ + coxSelect.add(new Option(name, user_id)); + } + } + + const steeringSelect = document.querySelector('#steering_person'); + if (steeringSelect) { + steeringSelect.add(new Option(name, user_id)); + } + },false); + + select.addEventListener('removeItem', function(e) { + const event = e as ChoiceEvent; + + const user_id = event.detail.value; + + const coxSelect = document.querySelector('#cox'); + if (coxSelect) { + for (var i=0; idocument.querySelector('#steering_person'); + if (steeringSelect) { + for (var i=0; i>document.querySelectorAll('.filter-trips-js'); diff --git a/templates/includes/forms/log.html.tera b/templates/includes/forms/log.html.tera index be74871..d0437ff 100644 --- a/templates/includes/forms/log.html.tera +++ b/templates/includes/forms/log.html.tera @@ -30,67 +30,35 @@ {% macro new(only_ones, shipmaster) %}
{{ log::boat_select(only_ones=only_ones) }} - -
- - - -
{% if not only_ones %} -
-
Bootssteuerung
-
- {{ macros::checkbox(label='handgesteuert', name='shipmaster_only_steering', disabled=true) }} -
-
+
+
Bootssteuerung
+
+ {{ macros::checkbox(label='handgesteuert', name='shipmaster_only_steering', disabled=true) }} +
+
{% endif %} - {% if not only_ones %} {{ log::rower_select(id="newrower", selected=[], class="col-span-4", init=true) }} {% endif %} - + {{ macros::select(label="Schiffsführer", data=[], name='cox', wrapper_class="col-span-2") }} + {{ macros::select(label="Steuerperson", data=[], name='steering_person', wrapper_class="col-span-2") }} {{ macros::input(label='Abfahrtszeit', name='departure', type='datetime-local', required=true, wrapper_class='col-span-2') }} {{ macros::input(label='Ankunftszeit', name='arrival', type='datetime-local', wrapper_class='col-span-2') }} -
- - {% for distance in distances %} -
-
{{ macros::input(label="Distanz", name="distance_in_km", id="distance_in_km" , type="number", min=0, value='', class="rounded-md") }} km
- {{ macros::input(label="Kommentar", name="comments", type="text", wrapper_class="col-span-4") }} - {{ macros::select(label="Typ", data=logtypes, name='logtype', default="Normal", wrapper_class="col-span-4") }} -
{% endmacro new %} @@ -108,7 +76,7 @@ {% macro rower_select(id, selected, amount_seats='', class='', init='false') %} {% if not amount_seats or amount_seats > 1 %}
- + @@ -241,9 +244,9 @@ km
- {{ macros::input(label="Kommentar", name="comments", id="comments" ~ log.id, type="text", value=log.comments, class="rounded-md change-id-js") }} - {{ macros::select(label="Typ", data=logtypes, name="logtype", id="logtype" ~ log.id, default="Normal", selected_id=log.logtype, class="rounded-md change-id-js") }} + {{ macros::input(label="Kommentar", name="comments", id="comments" ~ log.id, type="text", value=log.comments, class="rounded-md change-id-js", wrapper_class="col-span-2") }} + {{ macros::select(label="Typ", data=logtypes, name="logtype", id="logtype" ~ log.id, default="Normal", selected_id=log.logtype, class="rounded-md change-id-js col-span-2") }} - + {% endmacro home %} diff --git a/templates/includes/macros.html.tera b/templates/includes/macros.html.tera index 3d9cca8..5e43784 100644 --- a/templates/includes/macros.html.tera +++ b/templates/includes/macros.html.tera @@ -78,29 +78,29 @@ {% endmacro checkbox %} -{% macro select(label, data, name='trip_type', default='', id='', selected_id='', display='', extras='', class='', wrapper_class='') %} +{% macro select(label, data, name='trip_type', default='', id='', selected_id='', display='', extras='', class='', wrapper_class='', required=false) %}
- - {% if display == '' %} - {% set display = ["name"] %} - {% endif %} - -
+ + {% if display == '' %} + {% set display = ["name"] %} + {% endif %} + + {% endmacro select %} From 855962369ac584ee41b8aac72a1042c067c084d8 Mon Sep 17 00:00:00 2001 From: philipp Date: Mon, 30 Oct 2023 13:49:49 +0100 Subject: [PATCH 07/27] use proper names for new form fields --- templates/includes/forms/log.html.tera | 50 +++++++++++++------------- templates/log.html.tera | 43 +++++++++++----------- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/templates/includes/forms/log.html.tera b/templates/includes/forms/log.html.tera index e95a6d0..8c8e8e4 100644 --- a/templates/includes/forms/log.html.tera +++ b/templates/includes/forms/log.html.tera @@ -74,27 +74,27 @@ {% endmacro boat_select %} {% macro rower_select(id, selected, amount_seats='', class='', init='false', cox_on_boat='', steering_person_id='') %} - {% if not amount_seats or amount_seats > 1 %} -
- - + {% for user in users %} + {% set_global sel = false %} + {% for rower in selected %} + {% if rower.id == user.id %} + {% set_global sel = true %} + {% endif %} {% endfor %} - -
- {% endif %} + + {% endfor %} + + + {#{% endif %}#} {% endmacro rower_select %} {% macro show(log, state, allowed_to_close=false, only_ones) %} @@ -213,13 +213,11 @@ {% endmacro show_old %} {% macro home(log, only_ones) %} - {# @MB: Maaaarieeee, please fix col-span-2 craziness #} + {# @MB: Maaaarieeee, please fix col-span-2 madness #}
- {% if not only_ones %} - {{ log::rower_select(id="rowers"~log.id, selected=log.rowers, amount_seats=log.boat.amount_seats, class="col-span-2", steering_person_id=log.steering_user.id, cox_on_boat=log.shipmaster_user.id) }} - {{ macros::select(label="Schiffsführer", data=[], name='shipmaster', id="shipmaster-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.shipmaster_user.id, required=true) }} - {{ macros::select(label="Steuerperson", data=[], name='steering_person', id="steering_person-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.steering_user.id, required=true) }} - {% endif %} + {{ log::rower_select(id="rowers"~log.id, selected=log.rowers, amount_seats=log.boat.amount_seats, class="col-span-2", steering_person_id=log.steering_user.id, cox_on_boat=log.shipmaster_user.id) }} + {{ macros::select(label="Schiffsführer", data=[], name='shipmaster', id="shipmaster-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.shipmaster_user.id, required=true) }} + {{ macros::select(label="Steuerperson", data=[], name='steering_person', id="steering_person-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.steering_user.id, required=true) }}
{{ macros::checkbox(label="Handgesteuert", name="shipmaster_only_steering", id="shipmaster_only_steering" ~ log.id , checked=log.shipmaster_only_steering,class="rounded-md change-id-js") }} diff --git a/templates/log.html.tera b/templates/log.html.tera index d762149..6126e50 100644 --- a/templates/log.html.tera +++ b/templates/log.html.tera @@ -4,20 +4,19 @@ {% extends "base" %} {% block content %} -

Logbuch

- - {% if flash %} -
- {{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }} -
- {% endif %} - + + {% if flash %} +
+ {{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }} +
+ {% endif %} +

Am Wasser

- - {% if on_water | length > 0 %} - {% for log in on_water %} - {% if log.shipmaster == loggedin_user.id %} - {{ log::show(log=log, state="on_water", allowed_to_close=true, only_ones=loggedin_user.is_cox==false) }} - {% else %} - {{ log::show(log=log, state="on_water", only_ones=true) }} - {% endif %} - {% endfor %} - {% else %} -

Kein Boot am Wasser

- {% endif %} + + {% if on_water | length > 0 %} + {% for log in on_water %} + {% if log.shipmaster == loggedin_user.id %} + {{ log::show(log=log, state="on_water", allowed_to_close=true, only_ones=loggedin_user.is_cox==false) }} + {% else %} + {{ log::show(log=log, state="on_water", only_ones=true) }} + {% endif %} + {% endfor %} + {% else %} +

Kein Boot am Wasser

+ {% endif %}
- + {% endblock content%} From 93c6fd2ce7f822059d66c905c193c5e07c39d6fc Mon Sep 17 00:00:00 2001 From: philipp Date: Mon, 30 Oct 2023 15:19:43 +0100 Subject: [PATCH 08/27] finish frontend(?) --- frontend/main.ts | 65 ++++++++++---------------- templates/includes/forms/log.html.tera | 4 +- templates/includes/macros.html.tera | 4 +- 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/frontend/main.ts b/frontend/main.ts index e17a717..abd5e5b 100644 --- a/frontend/main.ts +++ b/frontend/main.ts @@ -38,30 +38,21 @@ function selectBoatChange() { noResultsText: 'Keine Ergebnisse gefunden', noChoicesText: 'Keine Ergebnisse gefunden', itemSelectText: 'Zum Auswählen klicken', - callbackOnCreateTemplates: function () { - return { - option: ({ label, value, customProperties, active, disabled, }: any) => { - const opt: HTMLOptionElement = Choices.defaults.templates.option.call( - this, - { label, value, customProperties, active, disabled } - ); - - // We get the original
+ {#{% endif %}#} {% endmacro rower_select %} {% macro show(log, state, allowed_to_close=false, only_ones) %} @@ -213,13 +213,11 @@ {% endmacro show_old %} {% macro home(log, only_ones) %} - {# @MB: Maaaarieeee, please fix col-span-2 craziness #} + {# @MB: Maaaarieeee, please fix col-span-2 madness #}
- {% if not only_ones %} - {{ log::rower_select(id="rowers"~log.id, selected=log.rowers, amount_seats=log.boat.amount_seats, class="col-span-2", steering_person_id=log.steering_user.id, cox_on_boat=log.shipmaster_user.id) }} - {{ macros::select(label="Schiffsführer", data=[], name='shipmaster', id="shipmaster-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.shipmaster_user.id, required=true) }} - {{ macros::select(label="Steuerperson", data=[], name='steering_person', id="steering_person-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.steering_user.id, required=true) }} - {% endif %} + {{ log::rower_select(id="rowers"~log.id, selected=log.rowers, amount_seats=log.boat.amount_seats, class="col-span-2", steering_person_id=log.steering_user.id, cox_on_boat=log.shipmaster_user.id) }} + {{ macros::select(label="Schiffsführer", data=[], name='shipmaster', id="shipmaster-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.shipmaster_user.id, required=true) }} + {{ macros::select(label="Steuerperson", data=[], name='steering_person', id="steering_person-rowers"~log.id, wrapper_class="col-span-2", class="change-id-js", selected_id=log.steering_user.id, required=true) }}
{{ macros::checkbox(label="Handgesteuert", name="shipmaster_only_steering", id="shipmaster_only_steering" ~ log.id , checked=log.shipmaster_only_steering,class="rounded-md change-id-js") }} diff --git a/templates/log.html.tera b/templates/log.html.tera index d762149..6126e50 100644 --- a/templates/log.html.tera +++ b/templates/log.html.tera @@ -4,20 +4,19 @@ {% extends "base" %} {% block content %} -

Logbuch

- - {% if flash %} -
- {{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }} -
- {% endif %} - + + {% if flash %} +
+ {{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }} +
+ {% endif %} +

Am Wasser

- - {% if on_water | length > 0 %} - {% for log in on_water %} - {% if log.shipmaster == loggedin_user.id %} - {{ log::show(log=log, state="on_water", allowed_to_close=true, only_ones=loggedin_user.is_cox==false) }} - {% else %} - {{ log::show(log=log, state="on_water", only_ones=true) }} - {% endif %} - {% endfor %} - {% else %} -

Kein Boot am Wasser

- {% endif %} + + {% if on_water | length > 0 %} + {% for log in on_water %} + {% if log.shipmaster == loggedin_user.id %} + {{ log::show(log=log, state="on_water", allowed_to_close=true, only_ones=loggedin_user.is_cox==false) }} + {% else %} + {{ log::show(log=log, state="on_water", only_ones=true) }} + {% endif %} + {% endfor %} + {% else %} +

Kein Boot am Wasser

+ {% endif %}
- + {% endblock content%} From 388ed175bd1aae6c49743c90be5dcb6597f234da Mon Sep 17 00:00:00 2001 From: philipp Date: Mon, 30 Oct 2023 15:19:43 +0100 Subject: [PATCH 17/27] finish frontend(?) --- frontend/main.ts | 65 ++++++++++---------------- templates/includes/forms/log.html.tera | 4 +- templates/includes/macros.html.tera | 4 +- 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/frontend/main.ts b/frontend/main.ts index e17a717..abd5e5b 100644 --- a/frontend/main.ts +++ b/frontend/main.ts @@ -38,30 +38,21 @@ function selectBoatChange() { noResultsText: 'Keine Ergebnisse gefunden', noChoicesText: 'Keine Ergebnisse gefunden', itemSelectText: 'Zum Auswählen klicken', - callbackOnCreateTemplates: function () { - return { - option: ({ label, value, customProperties, active, disabled, }: any) => { - const opt: HTMLOptionElement = Choices.defaults.templates.option.call( - this, - { label, value, customProperties, active, disabled } - ); - - // We get the original