allow edits of boatreservations, Fixes #417
This commit is contained in:
		| @@ -1,4 +1,5 @@ | |||||||
| use crate::model::{boat::Boat, user::User}; | use crate::model::{boat::Boat, user::User}; | ||||||
|  | use crate::tera::boatreservation::ReservationEditForm; | ||||||
| use chrono::NaiveDate; | use chrono::NaiveDate; | ||||||
| use chrono::NaiveDateTime; | use chrono::NaiveDateTime; | ||||||
| use rocket::serde::{Deserialize, Serialize}; | use rocket::serde::{Deserialize, Serialize}; | ||||||
| @@ -177,6 +178,20 @@ AND start_date <= ? AND end_date >= ?;", | |||||||
|             > 0 |             > 0 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub async fn update(&self, db: &SqlitePool, data: ReservationEditForm) { | ||||||
|  |         let time_desc = data.time_desc.trim(); | ||||||
|  |         let usage = data.usage.trim(); | ||||||
|  |         sqlx::query!( | ||||||
|  |             "UPDATE boat_reservation SET time_desc = ?, usage = ? where id = ?", | ||||||
|  |             time_desc, | ||||||
|  |             usage, | ||||||
|  |             self.id | ||||||
|  |         ) | ||||||
|  |         .execute(db) | ||||||
|  |         .await | ||||||
|  |         .unwrap(); //Okay, because we can only create a User of a valid id | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub async fn delete(&self, db: &SqlitePool) { |     pub async fn delete(&self, db: &SqlitePool) { | ||||||
|         sqlx::query!("DELETE FROM boat_reservation WHERE id=?", self.id) |         sqlx::query!("DELETE FROM boat_reservation WHERE id=?", self.id) | ||||||
|             .execute(db) |             .execute(db) | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ use crate::{ | |||||||
|     model::{ |     model::{ | ||||||
|         boat::Boat, |         boat::Boat, | ||||||
|         boatreservation::{BoatReservation, BoatReservationToAdd}, |         boatreservation::{BoatReservation, BoatReservationToAdd}, | ||||||
|  |         log::Log, | ||||||
|         user::{DonauLinzUser, User, UserWithRoles}, |         user::{DonauLinzUser, User, UserWithRoles}, | ||||||
|     }, |     }, | ||||||
|     tera::log::KioskCookie, |     tera::log::KioskCookie, | ||||||
| @@ -90,7 +91,7 @@ pub struct FormBoatReservationToAdd<'r> { | |||||||
|     pub user_id_applicant: Option<i64>, |     pub user_id_applicant: Option<i64>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[post("/", data = "<data>", rank = 2)] | #[post("/new", data = "<data>", rank = 2)] | ||||||
| async fn create<'r>( | async fn create<'r>( | ||||||
|     db: &State<SqlitePool>, |     db: &State<SqlitePool>, | ||||||
|     data: Form<FormBoatReservationToAdd<'r>>, |     data: Form<FormBoatReservationToAdd<'r>>, | ||||||
| @@ -115,7 +116,7 @@ async fn create<'r>( | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[post("/", data = "<data>")] | #[post("/new", data = "<data>")] | ||||||
| async fn create_from_kiosk<'r>( | async fn create_from_kiosk<'r>( | ||||||
|     db: &State<SqlitePool>, |     db: &State<SqlitePool>, | ||||||
|     data: Form<FormBoatReservationToAdd<'r>>, |     data: Form<FormBoatReservationToAdd<'r>>, | ||||||
| @@ -142,6 +143,50 @@ async fn create_from_kiosk<'r>( | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(FromForm, Debug)] | ||||||
|  | pub struct ReservationEditForm { | ||||||
|  |     pub(crate) id: i32, | ||||||
|  |     pub(crate) time_desc: String, | ||||||
|  |     pub(crate) usage: String, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[post("/", data = "<data>")] | ||||||
|  | async fn update( | ||||||
|  |     db: &State<SqlitePool>, | ||||||
|  |     data: Form<ReservationEditForm>, | ||||||
|  |     user: User, | ||||||
|  | ) -> Flash<Redirect> { | ||||||
|  |     let Some(reservation) = BoatReservation::find_by_id(db, data.id).await else { | ||||||
|  |         return Flash::error( | ||||||
|  |             Redirect::to("/boatreservation"), | ||||||
|  |             format!("Reservation with ID {} does not exist!", data.id), | ||||||
|  |         ); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     if user.id != reservation.user_id_applicant && !user.has_role(db, "admin").await { | ||||||
|  |         return Flash::error( | ||||||
|  |             Redirect::to("/boatreservation"), | ||||||
|  |             format!("Not allowed to update reservation (only admins + creator do so)."), | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Log::create( | ||||||
|  |         db, | ||||||
|  |         format!( | ||||||
|  |             "{} updated reservation from {reservation:?} to {data:?}", | ||||||
|  |             user.name | ||||||
|  |         ), | ||||||
|  |     ) | ||||||
|  |     .await; | ||||||
|  |  | ||||||
|  |     reservation.update(db, data.into_inner()).await; | ||||||
|  |  | ||||||
|  |     Flash::success( | ||||||
|  |         Redirect::to("/boatreservation"), | ||||||
|  |         "Reservierung erfolgreich bearbeitet", | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  |  | ||||||
| #[get("/<reservation_id>/delete")] | #[get("/<reservation_id>/delete")] | ||||||
| async fn delete<'r>( | async fn delete<'r>( | ||||||
|     db: &State<SqlitePool>, |     db: &State<SqlitePool>, | ||||||
| @@ -167,5 +212,12 @@ async fn delete<'r>( | |||||||
| } | } | ||||||
|  |  | ||||||
| pub fn routes() -> Vec<Route> { | pub fn routes() -> Vec<Route> { | ||||||
|     routes![index, index_kiosk, create, create_from_kiosk, delete] |     routes![ | ||||||
|  |         index, | ||||||
|  |         index_kiosk, | ||||||
|  |         create, | ||||||
|  |         create_from_kiosk, | ||||||
|  |         delete, | ||||||
|  |         update | ||||||
|  |     ] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ pub(crate) mod admin; | |||||||
| mod auth; | mod auth; | ||||||
| pub(crate) mod board; | pub(crate) mod board; | ||||||
| mod boatdamage; | mod boatdamage; | ||||||
| mod boatreservation; | pub(crate) mod boatreservation; | ||||||
| mod cox; | mod cox; | ||||||
| mod ergo; | mod ergo; | ||||||
| mod log; | mod log; | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ | |||||||
|         </h2> |         </h2> | ||||||
|         <div class="hidden"> |         <div class="hidden"> | ||||||
|             <div id="new-reservation"> |             <div id="new-reservation"> | ||||||
|                 <form action="/boatreservation" method="post" class="grid gap-3"> |                 <form action="/boatreservation/new" method="post" class="grid gap-3"> | ||||||
|                     {{ log::boat_select(only_ones=false, id='boat') }} |                     {{ log::boat_select(only_ones=false, id='boat') }} | ||||||
|                     {% if not loggedin_user %}{{ macros::select(label='Reserviert von', data=user, name='user_id_applicant') }}{% endif %} |                     {% if not loggedin_user %}{{ macros::select(label='Reserviert von', data=user, name='user_id_applicant') }}{% endif %} | ||||||
|                     {{ macros::input(label='Beginn', name='start_date', type='date', required=true, wrapper_class='col-span-4') }} |                     {{ macros::input(label='Beginn', name='start_date', type='date', required=true, wrapper_class='col-span-4') }} | ||||||
| @@ -41,6 +41,12 @@ | |||||||
|         </div> |         </div> | ||||||
|         <div id="filter-result-js" class="search-result"></div> |         <div id="filter-result-js" class="search-result"></div> | ||||||
|         {% for reservation in boatreservations %} |         {% for reservation in boatreservations %} | ||||||
|  |             {% set allowed_to_edit = false %} | ||||||
|  |             {% if loggedin_user %} | ||||||
|  |                 {% if loggedin_user.id == reservation.user_applicant.id or "admin" in loggedin_user.roles %} | ||||||
|  |                     {% set allowed_to_edit = true %} | ||||||
|  |                 {% endif %} | ||||||
|  |             {% endif %} | ||||||
|             <div data-filterable="true" |             <div data-filterable="true" | ||||||
|                  data-filter="{{ reservation.user_applicant.name }} {{ reservation.boat.name }}" |                  data-filter="{{ reservation.user_applicant.name }} {{ reservation.boat.name }}" | ||||||
|                  class="w-full border-t bg-white dark:bg-primary-900 text-black dark:text-white p-3"> |                  class="w-full border-t bg-white dark:bg-primary-900 text-black dark:text-white p-3"> | ||||||
| @@ -58,13 +64,22 @@ | |||||||
|                         {{ reservation.end_date }} |                         {{ reservation.end_date }} | ||||||
|                     {% endif %} |                     {% endif %} | ||||||
|                     <br /> |                     <br /> | ||||||
|                     <strong>Uhrzeit:</strong> |                     {% if not allowed_to_edit %} | ||||||
|                     {{ reservation.time_desc }} |                         <strong>Uhrzeit:</strong> | ||||||
|                     <br /> |                         {{ reservation.time_desc }} | ||||||
|                     <strong>Zweck:</strong> |                         <br /> | ||||||
|                     {{ reservation.usage }} |                         <strong>Zweck:</strong> | ||||||
|                     {% if loggedin_user %} |                         {{ reservation.usage }} | ||||||
|                         {% if loggedin_user.id == reservation.user_applicant.id or "admin" in loggedin_user.roles %} |                     {% endif %} | ||||||
|  |                     {% if allowed_to_edit %} | ||||||
|  |                         <form action="/boatreservation" | ||||||
|  |                               method="post" | ||||||
|  |                               class="bg-white dark:bg-primary-900 p-3 rounded-md w-full"> | ||||||
|  |                             <div class="w-full grid gap-3"> | ||||||
|  |                                 <input type="hidden" name="id" value="{{ reservation.id }}" /> | ||||||
|  |                                 {{ macros::input(label='Uhrzeit', name='time_desc', id=loop.index, type="text", value=reservation.time_desc, readonly=false) }} | ||||||
|  |                                 {{ macros::input(label='Zweck', name='usage', id=loop.index, type="text", value=reservation.usage, readonly=false) }} | ||||||
|  |                             </div> | ||||||
|                             <div class="mt-3 text-right"> |                             <div class="mt-3 text-right"> | ||||||
|                                 <a href="/boatreservation/{{ reservation.id }}/delete" |                                 <a href="/boatreservation/{{ reservation.id }}/delete" | ||||||
|                                    class="w-28 btn btn-alert" |                                    class="w-28 btn btn-alert" | ||||||
| @@ -72,8 +87,9 @@ | |||||||
|                                     {% include "includes/delete-icon" %} |                                     {% include "includes/delete-icon" %} | ||||||
|                                     Löschen |                                     Löschen | ||||||
|                                 </a> |                                 </a> | ||||||
|  |                                 <input value="Ändern" type="submit" class="w-28 btn btn-primary ml-1" /> | ||||||
|                             </div> |                             </div> | ||||||
|                         {% endif %} |                         </form> | ||||||
|                     {% endif %} |                     {% endif %} | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user