frontend for new db

This commit is contained in:
philipp 2023-10-30 13:39:58 +01:00
parent 4e607e135a
commit be5a235418
4 changed files with 173 additions and 118 deletions

View File

@ -22,11 +22,10 @@ document.addEventListener('DOMContentLoaded', function() {
function setCurrentdate(input: HTMLInputElement) { function setCurrentdate(input: HTMLInputElement) {
if(input) { if(input) {
const inputElement = document.getElementById("departure") as HTMLInputElement;
const now = new Date(); const now = new Date();
const formattedDateTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}T${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`; const formattedDateTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}T${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
inputElement.value = formattedDateTime; input.value = formattedDateTime;
} }
} }
@ -53,9 +52,8 @@ function selectBoatChange() {
)[0]; )[0];
const rowers = Number(originalOption.dataset.amount_seats); const rowers = Number(originalOption.dataset.amount_seats);
const isShipmasterSteering = originalOption.dataset.default_shipmaster_only_steering;
setMaxAmountRowers(rowers,isShipmasterSteering); setMaxAmountRowers("newrower", rowers);
return opt; return opt;
} }
@ -83,51 +81,51 @@ function reloadPage() {
}); });
} }
function setMaxAmountRowers(rowers: number, isShipmasterSteering='false') { function setMaxAmountRowers(name: string, rowers: number) {
if(choiceObjects['newrower']) { if(choiceObjects[name]) {
let curSelection = choiceObjects['newrower'].getValue(true); let curSelection = choiceObjects[name].getValue(true);
let amount_to_delete = (<any>curSelection).length - rowers; let amount_to_delete = (<any>curSelection).length - rowers;
if (amount_to_delete > 0){ if (amount_to_delete > 0){
let to_delete = (<any>curSelection).slice(-amount_to_delete); let to_delete = (<any>curSelection).slice(-amount_to_delete);
for (let del of to_delete) { for (let del of to_delete) {
choiceObjects['newrower'].removeActiveItemsByValue(del); choiceObjects[name].removeActiveItemsByValue(del);
} }
} }
let input = <HTMLElement>document.querySelector('#newrower'); let input = <HTMLElement>document.querySelector('#'+name);
if(input) { if(input) {
choiceObjects['newrower'].config.maxItemCount = rowers; choiceObjects[name].config.maxItemCount = rowers;
if (rowers === 0) { if (rowers === 0) {
choiceObjects['newrower'].disable() choiceObjects[name].disable()
input.parentElement?.parentElement?.parentElement?.classList.add('hidden'); input.parentElement?.parentElement?.parentElement?.classList.add('hidden');
input.parentElement?.parentElement?.parentElement?.classList.add('md:block'); input.parentElement?.parentElement?.parentElement?.classList.add('md:block');
input.parentElement?.parentElement?.parentElement?.classList.add('opacity-50'); input.parentElement?.parentElement?.parentElement?.classList.add('opacity-50');
} else{ } else{
choiceObjects['newrower'].enable(); choiceObjects[name].enable();
input.parentElement?.parentElement?.parentElement?.classList.remove('hidden'); input.parentElement?.parentElement?.parentElement?.classList.remove('hidden');
input.parentElement?.parentElement?.parentElement?.classList.remove('md:block'); input.parentElement?.parentElement?.parentElement?.classList.remove('md:block');
input.parentElement?.parentElement?.parentElement?.classList.remove('opacity-50'); input.parentElement?.parentElement?.parentElement?.classList.remove('opacity-50');
} }
} }
let only_steering = <HTMLSelectElement>document.querySelector('#shipmaster_only_steering'); //let only_steering = <HTMLSelectElement>document.querySelector('#shipmaster_only_steering');
if(only_steering) { //if(only_steering) {
if(isShipmasterSteering == 'true') { // if(isShipmasterSteering == 'true') {
only_steering.removeAttribute('disabled'); // only_steering.removeAttribute('disabled');
only_steering.setAttribute('checked', 'true'); // only_steering.setAttribute('checked', 'true');
only_steering.parentElement?.parentElement?.parentElement?.classList.remove('hidden'); // only_steering.parentElement?.parentElement?.parentElement?.classList.remove('hidden');
only_steering.parentElement?.parentElement?.parentElement?.classList.remove('md:block'); // only_steering.parentElement?.parentElement?.parentElement?.classList.remove('md:block');
only_steering.parentElement?.parentElement?.parentElement?.classList.remove('opacity-50'); // only_steering.parentElement?.parentElement?.parentElement?.classList.remove('opacity-50');
} else { // } else {
only_steering.setAttribute('disabled', 'disabled'); // only_steering.setAttribute('disabled', 'disabled');
only_steering.removeAttribute('checked'); // only_steering.removeAttribute('checked');
only_steering.parentElement?.parentElement?.parentElement?.classList.add('hidden'); // only_steering.parentElement?.parentElement?.parentElement?.classList.add('hidden');
only_steering.parentElement?.parentElement?.parentElement?.classList.add('md:block'); // only_steering.parentElement?.parentElement?.parentElement?.classList.add('md:block');
only_steering.parentElement?.parentElement?.parentElement?.classList.add('opacity-50'); // only_steering.parentElement?.parentElement?.parentElement?.classList.add('opacity-50');
} // }
} //}
} }
} }
@ -138,9 +136,8 @@ function initBoatActions() {
select.addEventListener('click', function() { select.addEventListener('click', function() {
if(select.dataset.seats) { if(select.dataset.seats) {
const rowers = Number(select.dataset.seats); const rowers = Number(select.dataset.seats);
const isShipmasterSteering = select.dataset.default_shipmaster_only_steering;
setMaxAmountRowers(rowers, isShipmasterSteering); setMaxAmountRowers("newrower", rowers);
if (select.dataset.id) { if (select.dataset.id) {
choiceObjects['boat_id'].setChoiceByValue(select.dataset.id); choiceObjects['boat_id'].setChoiceByValue(select.dataset.id);
@ -174,6 +171,8 @@ interface ChoiceEvent extends Event{
label: string, label: string,
customProperties: { customProperties: {
is_cox: boolean, is_cox: boolean,
steers: boolean,
cox_on_boat: boolean,
} }
}; };
} }
@ -190,7 +189,50 @@ function initNewChoice(select: HTMLInputElement) {
maxItemText: (maxItemCount) => { maxItemText: (maxItemCount) => {
return `Nur ${maxItemCount} Ruderer können hinzugefügt werden`; return `Nur ${maxItemCount} Ruderer können hinzugefügt werden`;
}, },
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 <option> from choicejs
//const originalOption: HTMLOptionElement = this._presetOptions.filter(
// (option: HTMLOptionElement) => option.value === value
//)[0];
//
//const rowers = Number(originalOption.dataset.amount_seats);
//const isShipmasterSteering = originalOption.dataset.default_shipmaster_only_steering;
//setMaxAmountRowers(select.id, curr_boat_rowers, isShipmasterSteering);
return opt;
}
}
},
callbackOnInit: function() {
this._currentState.items.forEach(function(obj){
if (obj.customProperties && obj.customProperties.is_cox){
const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster-' + select.id + 'js');
var new_option = new Option(obj.label, obj.value);
if (obj.customProperties.cox_on_boat){
new_option.selected = true;
}
coxSelect.add(new_option);
}
const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person-' + select.id + 'js');
if (steeringSelect) {
var new_option = new Option(obj.label, obj.value);
if (obj.customProperties && obj.customProperties.steers){
new_option.selected = true;
}
steeringSelect.add(new_option);
}
}); });
}
});
choiceObjects[select.id] = choice;
select.addEventListener('addItem', function(e) { select.addEventListener('addItem', function(e) {
const event = e as ChoiceEvent; const event = e as ChoiceEvent;
@ -198,13 +240,13 @@ function initNewChoice(select: HTMLInputElement) {
const name = event.detail.label; const name = event.detail.label;
if (event.detail.customProperties.is_cox) { if (event.detail.customProperties.is_cox) {
const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster'); const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster-' + select.id + 'js');
if (coxSelect){ if (coxSelect){
coxSelect.add(new Option(name, user_id)); coxSelect.add(new Option(name, user_id));
} }
} }
const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person'); const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person-' + select.id + 'js');
if (steeringSelect) { if (steeringSelect) {
steeringSelect.add(new Option(name, user_id)); steeringSelect.add(new Option(name, user_id));
} }
@ -215,7 +257,7 @@ function initNewChoice(select: HTMLInputElement) {
const user_id = event.detail.value; const user_id = event.detail.value;
const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster'); const coxSelect = <HTMLSelectElement>document.querySelector('#shipmaster-' + select.id + 'js');
if (coxSelect) { if (coxSelect) {
for (var i=0; i<coxSelect.length; i++) { for (var i=0; i<coxSelect.length; i++) {
if (coxSelect.options[i].value == user_id) if (coxSelect.options[i].value == user_id)
@ -223,7 +265,7 @@ function initNewChoice(select: HTMLInputElement) {
} }
} }
const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person'); const steeringSelect = <HTMLSelectElement>document.querySelector('#steering_person-' + select.id + 'js');
if (steeringSelect) { if (steeringSelect) {
for (var i=0; i<steeringSelect.length; i++) { for (var i=0; i<steeringSelect.length; i++) {
if (steeringSelect.options[i].value == user_id) if (steeringSelect.options[i].value == user_id)
@ -419,12 +461,6 @@ function initTripSidebar(triggerElement: HTMLElement) {
let bodyElement = <HTMLElement>body.cloneNode(true); let bodyElement = <HTMLElement>body.cloneNode(true);
let bodyContainerElement = <HTMLElement>sidebarElement.querySelector('.body-js'); let bodyContainerElement = <HTMLElement>sidebarElement.querySelector('.body-js');
const selects = bodyElement.querySelectorAll('select[multiple]');
if(selects) {
Array.prototype.forEach.call(selects, (select: HTMLInputElement) => {
initNewChoice(select);
});
}
/* Quickfix duplicate ids checkboxes */ /* Quickfix duplicate ids checkboxes */
const checkboxes = <NodeListOf<HTMLElement>>bodyElement.querySelectorAll('input[type="checkbox"]'); const checkboxes = <NodeListOf<HTMLElement>>bodyElement.querySelectorAll('input[type="checkbox"]');
@ -447,6 +483,7 @@ function initTripSidebar(triggerElement: HTMLElement) {
} }
}); });
if(bodyContainerElement) { if(bodyContainerElement) {
bodyContainerElement.innerHTML = ''; bodyContainerElement.innerHTML = '';
bodyContainerElement.append(bodyElement); bodyContainerElement.append(bodyElement);
@ -464,7 +501,18 @@ function initTripSidebar(triggerElement: HTMLElement) {
if(headerElement) { if(headerElement) {
headerElement.innerHTML = triggerElement.dataset.header; headerElement.innerHTML = triggerElement.dataset.header;
} }
const selects = bodyElement.querySelectorAll('select[multiple]');
if(selects) {
Array.prototype.forEach.call(selects, (select: HTMLInputElement) => {
initNewChoice(select);
});
} }
}
const defaultDateTimes = <NodeListOf<HTMLInputElement>>document.querySelectorAll('.current-date-time');
defaultDateTimes.forEach((defaultDateTime) => {
setCurrentdate(defaultDateTime);
});
} }
function addRelationMagic(bodyElement: HTMLElement) { function addRelationMagic(bodyElement: HTMLElement) {

View File

@ -239,9 +239,17 @@ ORDER BY departure DESC
log: LogToAdd, log: LogToAdd,
created_by_user: &User, created_by_user: &User,
) -> Result<(), LogbookCreateError> { ) -> Result<(), LogbookCreateError> {
println!("{log:#?}"); let Some(boat) = Boat::find_by_id(db, log.boat_id).await else {
return Err(LogbookCreateError::BoatNotFound);
};
if let Ok(log_to_finalize) = TryInto::<LogToFinalize>::try_into(log.clone()) { if let Ok(log_to_finalize) = TryInto::<LogToFinalize>::try_into(log.clone()) {
//TODO: fix clone() //TODO: fix clone()
if !boat.shipmaster_allowed(created_by_user).await {
return Err(LogbookCreateError::UserNotAllowedToUseBoat);
}
let mut tx = db.begin().await.unwrap(); let mut tx = db.begin().await.unwrap();
let inserted_row = sqlx::query!( let inserted_row = sqlx::query!(
@ -277,10 +285,6 @@ ORDER BY departure DESC
return Err(LogbookCreateError::ArrivalSetButNotRemainingTwo); return Err(LogbookCreateError::ArrivalSetButNotRemainingTwo);
} }
let Some(boat) = Boat::find_by_id(db, log.boat_id).await else {
return Err(LogbookCreateError::BoatNotFound);
};
if boat.is_locked(db).await { if boat.is_locked(db).await {
return Err(LogbookCreateError::BoatLocked); return Err(LogbookCreateError::BoatLocked);
} }

View File

@ -41,8 +41,8 @@
{% if not only_ones %} {% if not only_ones %}
{{ log::rower_select(id="newrower", selected=[], class="col-span-4", init=true) }} {{ log::rower_select(id="newrower", selected=[], class="col-span-4", init=true) }}
{% endif %} {% endif %}
{{ macros::select(label="Schiffsführer", data=[], name='shipmaster', wrapper_class="col-span-2") }} {{ macros::select(label="Schiffsführer", data=[], name='shipmaster', id="shipmaster-newrowerjs", wrapper_class="col-span-2") }}
{{ macros::select(label="Steuerperson", data=[], name='steering_person', wrapper_class="col-span-2") }} {{ macros::select(label="Steuerperson", data=[], name='steering_person', id="steering_person-newrowerjs", wrapper_class="col-span-2") }}
{{ macros::input(label='Abfahrtszeit', name='departure', type='datetime-local', required=true, 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') }} {{ macros::input(label='Ankunftszeit', name='arrival', type='datetime-local', wrapper_class='col-span-2') }}
<div class="relative col-span-2"> <div class="relative col-span-2">
@ -73,7 +73,7 @@
{% endif %} {% endif %}
{% endmacro boat_select %} {% endmacro boat_select %}
{% macro rower_select(id, selected, amount_seats='', class='', init='false') %} {% macro rower_select(id, selected, amount_seats='', class='', init='false', cox_on_boat='', steering_person_id='') %}
{% if not amount_seats or amount_seats > 1 %} {% if not amount_seats or amount_seats > 1 %}
<div class="{{ class }}"> <div class="{{ class }}">
<label for="{{id}}" class="text-sm text-gray-600 ">Ruderer</label> <label for="{{id}}" class="text-sm text-gray-600 ">Ruderer</label>
@ -85,7 +85,7 @@
{% set_global sel = true %} {% set_global sel = true %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<option value="{{ user.id }}" {% if sel %} selected {% endif %} {% if user.on_water %} disabled="disabled" {% endif %} data-custom-properties='{"is_cox": {{ user.is_cox }}}'> <option value="{{ user.id }}" {% if sel %} selected {% endif %} {% if user.on_water %} disabled="disabled" {% endif %} data-custom-properties='{"is_cox": {{ user.is_cox }}, "steers": {{ user.id == steering_person_id }}, "cox_on_boat": {{ user.id == cox_on_boat}}}'>
{{user.name}} {{user.name}}
{% if user.on_water %} {% if user.on_water %}
(am Wasser) (am Wasser)
@ -134,22 +134,16 @@
{{ log.destination }} {{ log.destination }}
{% endif %} {% endif %}
{% for user in users %}
{% if user.id == log.shipmaster %}
<p>
<strong>{{ user.name }}</strong>
</p>
{% endif %}
{% endfor %}
{% for rower in log.rowers %} {% for rower in log.rowers %}
<p>{{ rower.name }}</p> <p>{{ rower.name }} {% if rower.id == log.shipmaster %}Schiffsführer {% endif %}{% if rower.id == log.steering_person%}Steuerperson{% endif %}</p>
{# @MB: shipmaster + steering_person could be prettier :') #}
{% endfor %} {% endfor %}
{% set amount_rowers = log.rowers | length %} {% set amount_rowers = log.rowers | length %}
{% set amount_guests = log.boat.amount_seats - amount_rowers -1 %} {% set amount_guests = log.boat.amount_seats - amount_rowers -1 %}
{% if amount_guests > 0 %} {% if amount_guests > 0 %}
Gäste (ohne Account): {{ amount_guests }} Gäste (ohne Account):
{{ amount_guests }}
{% endif %} {% endif %}
{% if allowed_to_close and state == "on_water" %} {% if allowed_to_close and state == "on_water" %}
@ -219,18 +213,27 @@
{% endmacro show_old %} {% endmacro show_old %}
{% macro home(log, only_ones) %} {% macro home(log, only_ones) %}
{# @MB: Maaaarieeee, please fix col-span-2 craziness #}
<form class="grid grid-cols-1 gap-3" action="/log/{{log.id}}" method="post"> <form class="grid grid-cols-1 gap-3" action="/log/{{log.id}}" method="post">
{% for user in users %}
{% if user.id == log.shipmaster %}
<p>
<strong>{{ user.name }}</strong>
</p>
{% endif %}
{% endfor %}
{% if not only_ones %} {% if not only_ones %}
{{ log::rower_select(id="rowers"~log.id, selected=log.rowers, amount_seats=log.boat.amount_seats) }} {{ 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 %} {% endif %}
<div class="relative">
<div class="col-span-2">
{{ 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") }}
</div>
<div class="col-span-2">
{{ macros::input(label='Abfahrtszeit', name='departure', type='datetime-local', required=true, class="change-id-js rounded-md", value=log.departure) }}
</div>
<div class="col-span-2">
{{ macros::input(label='Ankunftszeit', name='arrival', type='datetime-local', required=true, class="change-id-js rounded-md current-date-time") }}
</div>
<div class="col-span-2">
<label for="destination" class="text-sm text-gray-600">Ziel</label> <label for="destination" class="text-sm text-gray-600">Ziel</label>
<input class="input rounded-md set-distance-js change-id-js" type="search" list="destinations" placeholder="Destination" required="required" id="destination{{ log.id }}" name="destination" value="{{log.destination}}" data-relation="distance_in_km{{log.id}}"/> <input class="input rounded-md set-distance-js change-id-js" type="search" list="destinations" placeholder="Destination" required="required" id="destination{{ log.id }}" name="destination" value="{{log.destination}}" data-relation="distance_in_km{{log.id}}"/>
@ -241,9 +244,9 @@
<span class="absolute right-0 bottom-0 py-1.5 px-2 bg-white border-0 text-gray-600 ring-1 ring-inset ring-gray-300 rounded-br-md rounded-tr-md">km</span> <span class="absolute right-0 bottom-0 py-1.5 px-2 bg-white border-0 text-gray-600 ring-1 ring-inset ring-gray-300 rounded-br-md rounded-tr-md">km</span>
</div> </div>
{{ macros::input(label="Kommentar", name="comments", id="comments" ~ log.id, type="text", value=log.comments, 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") }} {{ 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") }}
<input class="btn btn-primary" type="submit" value="Ausfahrt beenden"/> <input class="btn btn-primary col-span-2" type="submit" value="Ausfahrt beenden"/>
</form> </form>
{% endmacro home %} {% endmacro home %}

View File

@ -78,18 +78,18 @@
</label> </label>
{% endmacro checkbox %} {% 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) %}
<div class="{{wrapper_class}}"> <div class="{{wrapper_class}}">
<label for="{{ name }}" class="text-sm text-gray-600">{{ label }}</label> <label for="{{ name }}" class="text-sm text-gray-600">{{ label }}</label>
{% if display == '' %} {% if display == '' %}
{% set display = ["name"] %} {% set display = ["name"] %}
{% endif %} {% endif %}
<select name="{{ name }}" {% if id %} id="{{ id }}" {% else %} id="{{ name }}" {% endif %} class="input rounded-md {{ class }}"> <select name="{{ name }}" {% if id %} id="{{ id }}" {% else %} id="{{ name }}" {% endif %} class="input rounded-md {{ class }}" {% if required %}required="required"{% endif %}>
{% if default %} {% if default %}
<option selected value>{{ default }}</option> <option selected value>{{ default }}</option>
{% endif %} {% endif %}
{% for d in data %} {% for d in data %}
<option value="{{ d.id }}" {% if d.id == selected_id %} selected {% endif %} {% if extras != '' %} {% for extra in extras %} {% if extra != 'on_water' %} data-{{extra}}={{d[extra]}} {% else %} {% if d[extra] %} disabled {% endif %} {% endif %} {% endfor %} {% endif %}> <option value="{{ d.id }}" {% if d.id == selected_id %} selected {% endif %} {% if extras != '' %} {% for extra in extras %} {% if extra != 'on_water' %} data- {{extra}}={{d[extra]}} {% else %} {% if d[extra] %} disabled {% endif %} {% endif %} {% endfor %} {% endif %}>
{% for displa in display -%} {% for displa in display -%}
{%- if d[displa] -%} {%- if d[displa] -%}
{{- d[displa] -}} {{- d[displa] -}}