Merge pull request 'update logbook entries' (#634) from update-logbook-entries into main
Reviewed-on: #634
This commit is contained in:
commit
1db09cd8ac
@ -60,6 +60,22 @@ pub struct LogToFinalize {
|
||||
pub rowers: Vec<i64>,
|
||||
}
|
||||
|
||||
#[derive(FromForm, Debug, Clone)]
|
||||
pub struct LogToUpdate {
|
||||
pub id: i64,
|
||||
pub boat_id: i64,
|
||||
pub shipmaster: i64,
|
||||
pub steering_person: i64,
|
||||
pub shipmaster_only_steering: bool,
|
||||
pub departure: String,
|
||||
pub arrival: Option<String>,
|
||||
pub destination: Option<String>,
|
||||
pub distance_in_km: Option<i64>,
|
||||
pub comments: Option<String>,
|
||||
pub logtype: Option<i64>,
|
||||
pub rowers: Vec<i64>,
|
||||
}
|
||||
|
||||
impl TryFrom<LogToAdd> for LogToFinalize {
|
||||
type Error = String;
|
||||
|
||||
@ -94,6 +110,11 @@ pub struct LogbookWithBoatAndRowers {
|
||||
pub rowers: Vec<User>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LogbookAdminUpdateError {
|
||||
NotAllowed,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LogbookUpdateError {
|
||||
NotYourEntry,
|
||||
@ -172,7 +193,7 @@ impl Logbook {
|
||||
.await
|
||||
.ok()
|
||||
}
|
||||
pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> {
|
||||
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
"
|
||||
@ -437,6 +458,35 @@ ORDER BY departure DESC
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub async fn update(
|
||||
&self,
|
||||
db: &SqlitePool,
|
||||
data: LogToUpdate,
|
||||
user: &User,
|
||||
) -> Result<(), LogbookAdminUpdateError> {
|
||||
if !user.has_role(db, "Vorstand").await {
|
||||
return Err(LogbookAdminUpdateError::NotAllowed);
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"UPDATE logbook SET boat_id=?, shipmaster=?, steering_person=?, shipmaster_only_steering=?, departure=?, arrival=?, destination=?, distance_in_km=?, comments=?, logtype=? WHERE id=?",
|
||||
data.boat_id,
|
||||
data.shipmaster,
|
||||
data.steering_person,
|
||||
data.shipmaster_only_steering,
|
||||
data.departure,
|
||||
data.arrival,
|
||||
data.destination,
|
||||
data.distance_in_km,
|
||||
data.comments,
|
||||
data.logtype,
|
||||
self.id
|
||||
)
|
||||
.execute(db)
|
||||
.await.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn distances(db: &SqlitePool) -> Vec<(String, i64)> {
|
||||
let result = sqlx::query!("SELECT destination, distance_in_km FROM logbook WHERE id IN (SELECT MIN(id) FROM logbook GROUP BY destination) AND destination IS NOT NULL AND distance_in_km IS NOT NULL;")
|
||||
.fetch_all(db)
|
||||
|
@ -20,11 +20,11 @@ use crate::model::{
|
||||
boatreservation::BoatReservation,
|
||||
log::Log,
|
||||
logbook::{
|
||||
LogToAdd, LogToFinalize, Logbook, LogbookCreateError, LogbookDeleteError,
|
||||
LogbookUpdateError,
|
||||
LogToAdd, LogToFinalize, LogToUpdate, Logbook, LogbookAdminUpdateError, LogbookCreateError,
|
||||
LogbookDeleteError, LogbookUpdateError,
|
||||
},
|
||||
logtype::LogType,
|
||||
user::{AdminUser, DonauLinzUser, User, UserWithDetails},
|
||||
user::{AdminUser, DonauLinzUser, User, UserWithDetails, VorstandUser},
|
||||
};
|
||||
|
||||
pub struct KioskCookie(());
|
||||
@ -282,10 +282,40 @@ async fn create_kiosk(
|
||||
create_logbook(db, data, &DonauLinzUser(creator)).await //TODO: fixme
|
||||
}
|
||||
|
||||
#[post("/update", data = "<data>")]
|
||||
async fn update(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<LogToUpdate>,
|
||||
user: VorstandUser,
|
||||
) -> Flash<Redirect> {
|
||||
Log::create(
|
||||
db,
|
||||
format!("User {} tries to update log entry={:?}", &user.name, data),
|
||||
)
|
||||
.await;
|
||||
|
||||
let data = data.into_inner();
|
||||
|
||||
let Some(logbook) = Logbook::find_by_id(db, data.id).await else {
|
||||
return Flash::error(Redirect::to("/log"), &format!("Logbucheintrag kann nicht bearbeitet werden, da es einen Logbuch-Eintrag mit ID={} nicht gibt", data.id));
|
||||
};
|
||||
|
||||
match logbook.update(db, data, &user.0).await {
|
||||
Ok(()) => Flash::success(
|
||||
Redirect::to("/log/show"),
|
||||
format!("Logbucheintrag erfolgreich bearbeitet"),
|
||||
),
|
||||
Err(LogbookAdminUpdateError::NotAllowed) => Flash::error(
|
||||
Redirect::to("/log/show"),
|
||||
format!("Du hast keine Erlaubnis, diesen Logbucheintrag zu bearbeiten!"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn home_logbook(
|
||||
db: &SqlitePool,
|
||||
data: Form<LogToFinalize>,
|
||||
logbook_id: i32,
|
||||
logbook_id: i64,
|
||||
user: &DonauLinzUser,
|
||||
) -> Flash<Redirect> {
|
||||
let logbook: Option<Logbook> = Logbook::find_by_id(db, logbook_id).await;
|
||||
@ -312,7 +342,7 @@ async fn home_logbook(
|
||||
async fn home_kiosk(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<LogToFinalize>,
|
||||
logbook_id: i32,
|
||||
logbook_id: i64,
|
||||
_kiosk: KioskCookie,
|
||||
) -> Flash<Redirect> {
|
||||
let logbook = Logbook::find_by_id(db, logbook_id).await.unwrap(); //TODO: fixme
|
||||
@ -340,7 +370,7 @@ async fn home_kiosk(
|
||||
async fn home(
|
||||
db: &State<SqlitePool>,
|
||||
data: Form<LogToFinalize>,
|
||||
logbook_id: i32,
|
||||
logbook_id: i64,
|
||||
user: DonauLinzUser,
|
||||
) -> Flash<Redirect> {
|
||||
Log::create(
|
||||
@ -356,7 +386,7 @@ async fn home(
|
||||
}
|
||||
|
||||
#[get("/<logbook_id>/delete", rank = 2)]
|
||||
async fn delete(db: &State<SqlitePool>, logbook_id: i32, user: DonauLinzUser) -> Flash<Redirect> {
|
||||
async fn delete(db: &State<SqlitePool>, logbook_id: i64, user: DonauLinzUser) -> Flash<Redirect> {
|
||||
let logbook = Logbook::find_by_id(db, logbook_id).await;
|
||||
if let Some(logbook) = logbook {
|
||||
Log::create(
|
||||
@ -385,7 +415,7 @@ async fn delete(db: &State<SqlitePool>, logbook_id: i32, user: DonauLinzUser) ->
|
||||
#[get("/<logbook_id>/delete")]
|
||||
async fn delete_kiosk(
|
||||
db: &State<SqlitePool>,
|
||||
logbook_id: i32,
|
||||
logbook_id: i64,
|
||||
_kiosk: KioskCookie,
|
||||
) -> Flash<Redirect> {
|
||||
let logbook = Logbook::find_by_id(db, logbook_id).await;
|
||||
@ -425,7 +455,8 @@ pub fn routes() -> Vec<Route> {
|
||||
show_kiosk,
|
||||
show_for_year,
|
||||
delete,
|
||||
delete_kiosk
|
||||
delete_kiosk,
|
||||
update
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -169,77 +169,101 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro show %}
|
||||
{% macro show_old(log, state, allowed_to_close=false, index) %}
|
||||
{% macro show_old(log, state, allowed_to_close=false, allowed_to_edit=false, index) %}
|
||||
<div class="border-t bg-white dark:bg-primary-900 py-3 px-4 relative"
|
||||
data-filterable="true"
|
||||
data-filter="{{ log.boat.name }} {% for rower in log.rowers %}{{ rower.name }}{% endfor %}">
|
||||
{% if log.logtype %}
|
||||
<div class="absolute top-0 right-0 bg-primary-100 rounded-bl-md text-primary-950 text-xs w-32 px-2 py-1 text-center font-bold">
|
||||
{% if log.logtype == 1 %}
|
||||
Wanderfahrt
|
||||
{% else %}
|
||||
{% if log.logtype == 2 %}
|
||||
Regatta
|
||||
{% else %}
|
||||
{{ log.logtype }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div {% if log.logtype %}class="mt-4 sm:mt-0"{% endif %}>
|
||||
<strong class="text-black dark:text-white">{{ log.boat.name }}</strong>
|
||||
<small class="text-gray-600 dark:text-gray-100">({{ log.shipmaster_user.name -}}
|
||||
{% if log.shipmaster_only_steering %}
|
||||
- handgesteuert
|
||||
{%- endif -%}
|
||||
)</small>
|
||||
<small class="block text-gray-600 dark:text-gray-100">
|
||||
{% if state == "completed" and log.departure | date(format='%d.%m.%Y') == log.arrival | date(format='%d.%m.%Y') %}
|
||||
{{ log.departure | date(format='%d.%m.%Y') }}
|
||||
({{ log.departure | date(format='%H:%M') }}
|
||||
-
|
||||
{{ log.arrival | date(format='%H:%M') }})
|
||||
{% else %}
|
||||
{{ log.departure | date(format='%d.%m.%Y (%H:%M)') }}
|
||||
{% if state == "completed" %}
|
||||
-
|
||||
{{ log.arrival | date(format='%d.%m.%Y (%H:%M)') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</small>
|
||||
{% set amount_rowers = log.rowers | length %}
|
||||
{% set amount_guests = log.boat.amount_seats - amount_rowers %}
|
||||
{% if allowed_to_close and state == "on_water" %}
|
||||
{{ log::home(log=log) }}
|
||||
{% else %}
|
||||
<div class="text-black dark:text-white">
|
||||
{{ log.destination }}
|
||||
{% if state == "completed" %}
|
||||
<small class="text-gray-600 dark:text-gray-100">({{ log.distance_in_km }}
|
||||
km)</small>
|
||||
{% endif %}
|
||||
{% if log.comments %}<span class="text-sm italic">- "{{ log.comments }}"</span>{% endif %}
|
||||
</div>
|
||||
{% if amount_guests > 0 or log.rowers | length > 0 %}
|
||||
{% if not log.boat.amount_seats == 1 %}
|
||||
<div class="text-sm text-gray-600 dark:text-gray-100">
|
||||
Ruderer:
|
||||
{% for rower in log.rowers -%}
|
||||
{{ rower.name }}
|
||||
{%- if rower.id == log.steering_user.id and rower.id != log.shipmaster_user.id %}
|
||||
(Steuerperson){%- endif -%}
|
||||
{%- if not loop.last or amount_guests > 0 and not log.boat.external %},{% endif %}
|
||||
{% endfor -%}
|
||||
{% if amount_guests > 0 and not log.boat.external %}
|
||||
Gäste
|
||||
<small class="text-gray-600 dark:text-gray-100">(ohne Account)</small>:
|
||||
{{ amount_guests }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<details>
|
||||
<summary style="list-style: none;">
|
||||
{% if log.logtype %}
|
||||
<div class="absolute top-0 right-0 bg-primary-100 rounded-bl-md text-primary-950 text-xs w-32 px-2 py-1 text-center font-bold">
|
||||
{% if log.logtype == 1 %}
|
||||
Wanderfahrt
|
||||
{% else %}
|
||||
{% if log.logtype == 2 %}
|
||||
Regatta
|
||||
{% else %}
|
||||
{{ log.logtype }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div {% if log.logtype %}class="mt-4 sm:mt-0"{% endif %}>
|
||||
<strong class="text-black dark:text-white">{{ log.boat.name }}</strong>
|
||||
<small class="text-gray-600 dark:text-gray-100">({{ log.shipmaster_user.name -}}
|
||||
{% if log.shipmaster_only_steering %}
|
||||
- handgesteuert
|
||||
{%- endif -%}
|
||||
)</small>
|
||||
<small class="block text-gray-600 dark:text-gray-100">
|
||||
{% if state == "completed" and log.departure | date(format='%d.%m.%Y') == log.arrival | date(format='%d.%m.%Y') %}
|
||||
{{ log.departure | date(format='%d.%m.%Y') }}
|
||||
({{ log.departure | date(format='%H:%M') }}
|
||||
-
|
||||
{{ log.arrival | date(format='%H:%M') }})
|
||||
{% else %}
|
||||
{{ log.departure | date(format='%d.%m.%Y (%H:%M)') }}
|
||||
{% if state == "completed" %}
|
||||
-
|
||||
{{ log.arrival | date(format='%d.%m.%Y (%H:%M)') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</small>
|
||||
{% set amount_rowers = log.rowers | length %}
|
||||
{% set amount_guests = log.boat.amount_seats - amount_rowers %}
|
||||
{% if allowed_to_close and state == "on_water" %}
|
||||
{{ log::home(log=log) }}
|
||||
{% else %}
|
||||
<div class="text-black dark:text-white">
|
||||
{{ log.destination }}
|
||||
{% if state == "completed" %}
|
||||
<small class="text-gray-600 dark:text-gray-100">({{ log.distance_in_km }}
|
||||
km)</small>
|
||||
{% endif %}
|
||||
{% if log.comments %}<span class="text-sm italic">- "{{ log.comments }}"</span>{% endif %}
|
||||
</div>
|
||||
{% if amount_guests > 0 or log.rowers | length > 0 %}
|
||||
{% if not log.boat.amount_seats == 1 %}
|
||||
<div class="text-sm text-gray-600 dark:text-gray-100">
|
||||
Ruderer:
|
||||
{% for rower in log.rowers -%}
|
||||
{{ rower.name }}
|
||||
{%- if rower.id == log.steering_user.id and rower.id != log.shipmaster_user.id %}
|
||||
(Steuerperson){%- endif -%}
|
||||
{%- if not loop.last or amount_guests > 0 and not log.boat.external %},{% endif %}
|
||||
{% endfor -%}
|
||||
{% if amount_guests > 0 and not log.boat.external %}
|
||||
Gäste
|
||||
<small class="text-gray-600 dark:text-gray-100">(ohne Account)</small>:
|
||||
{{ amount_guests }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</summary>
|
||||
{% if allowed_to_edit %}
|
||||
<form action="/log/update" method="post">
|
||||
<input type="hidden" name="id" value="{{ log.id }}" />
|
||||
<input type="hidden" name="boat_id" value="{{ log.boat_id }}" />
|
||||
<input type="hidden" name="shipmaster" value="{{ log.shipmaster }}" />
|
||||
<input type="hidden"
|
||||
name="steering_person"
|
||||
value="{{ log.steering_person }}" />
|
||||
<input type="hidden"
|
||||
name="shipmaster_only_steering"
|
||||
value="{{ log.shipmaster_only_steering }}" />
|
||||
<input type="datetime-local" name="departure" value="{{ log.departure }}" />
|
||||
<input type="datetime-local" name="arrival" value="{{ log.arrival }}" />
|
||||
<input type="hidden" name="destination" value="{{ log.destination }}" />
|
||||
<input type="hidden" name="distance_in_km" value="{{ log.distance_in_km }}" />
|
||||
<input type="hidden" name="comments" value="{{ log.comments }}" />
|
||||
<input type="hidden" name="logtype" value="{{ log.logtype }}" />
|
||||
<input type="submit" value="Updaten" />
|
||||
</form>
|
||||
{% endif %}
|
||||
</details>
|
||||
</div>
|
||||
{% endmacro show_old %}
|
||||
{% macro home(log) %}
|
||||
|
@ -143,9 +143,9 @@
|
||||
<input type="checkbox"
|
||||
id="{{ name }}{{ id }}"
|
||||
name="{{ name }}"
|
||||
{% if checked %} checked{% endif %}
|
||||
{% if disabled %} disabled{% endif %}
|
||||
{% if readonly %} readonly="readonly"{% endif %}
|
||||
{% if checked %}checked{% endif %}
|
||||
{% if disabled %}disabled{% endif %}
|
||||
{% if readonly %}readonly="readonly"{% endif %}
|
||||
class="h-4 w-4 accent-primary-600 dark:accent-primary-200 mr-2" />
|
||||
{{ label }}
|
||||
</label>
|
||||
|
@ -23,7 +23,15 @@
|
||||
placeholder="Suchen nach Bootsname oder Ruderer...">
|
||||
</div>
|
||||
<div id="filter-result-js" class="search-result"></div>
|
||||
{% for log in logs %}{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }}{% endfor %}
|
||||
{% for log in logs %}
|
||||
{% set_global allowed_to_edit = false %}
|
||||
{% if loggedin_user %}
|
||||
{% if "Vorstand" in loggedin_user.roles %}
|
||||
{% set_global allowed_to_edit = true %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index, allowed_to_edit=allowed_to_edit) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
Loading…
Reference in New Issue
Block a user