Merge pull request 'template_design' (#1) from template_design into develop

Reviewed-on: #1
This commit is contained in:
anghenfil 2022-01-19 03:48:58 +00:00
commit e30fd12fdb
37 changed files with 1264 additions and 311 deletions

View File

@ -0,0 +1,8 @@
-- This file should undo anything in `up.sql`
alter table eu_position_instances drop constraint eu_position_instances_pk;
alter table eu_position_instances
add constraint eu_position_instances_pk
primary key (instance_id, position_id);
alter table eu_position_instances
drop position_instance_id;

View File

@ -0,0 +1,9 @@
-- Your SQL goes here
alter table eu_position_instances
add position_instance_id uuid default uuid_generate_v1();
alter table eu_position_instances drop constraint eu_position_instances_pk;
alter table eu_position_instances
add constraint eu_position_instances_pk
primary key (position_instance_id);

View File

@ -0,0 +1,16 @@
-- This file should undo anything in `up.sql`
alter table eu_positions_templates
drop constraint eu_positions_templates_pk;
alter table eu_positions_templates
add constraint eu_positions_templates_pk
primary key (position_entity_id, template_id);
alter table eu_positions_templates
drop position_template_id;
alter table eu_positions_templates
drop num;
alter table eu_positions_templates
drop tag;

View File

@ -0,0 +1,15 @@
alter table eu_positions_templates
add position_template_id uuid default uuid_generate_v1();
alter table eu_positions_templates
add num int default 1 not null;
alter table eu_positions_templates
add tag text;
alter table eu_positions_templates drop constraint eu_positions_templates_pk;
alter table eu_positions_templates
add constraint eu_positions_templates_pk
primary key (position_template_id);

View File

@ -0,0 +1 @@
<div class="alert alert-{{level}}" role="alert">{{content}}</div>

View File

@ -1,119 +1,60 @@
<div class="card-body template_detailed_card_body">
<div class="form-group row">
<label for="template_detailed_name" class="col-sm-3 col-form-label">Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="template_detailed_name" value="{{name}}">
</div>
</div>
<div class="form-group row">
<label for="template_detailed_description" class="col-sm-3 col-form-label">Beschreibung</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="template_detailed_description" value="{{description}}">
</div>
</div>
<div>
<hr>
<h3>Positionen</h3><br>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
<button class="iconbutton template_detailed_check_all_positions">
<svg width="1.25em" height="1.25em" fill="currentColor">
<use xlink:href="/img/bootstrap-icons.svg#check-all"></use>
</svg>
</button>
</th>
<th scope="col">Name</th>
<th scope="col">Beschreibung</th>
</tr>
</thead>
<tbody class="template_detailed_positions_tbody">
{{#each positions}}
<tr>
<td><input type="checkbox" class="template_detailed_position_checkbox" data-position-id="{{entity_id}}">
</td>
<td>{{name}}</td>
<td>{{description}}</td>
</tr>
{{/each}}
</tbody>
</table>
<button type="button" class="btn btn-danger btn-sm templates_detailed_delete_position_button">Löschen</button>
<br><br>
<div class="row">
<b class="col-3">Hinzufügen: </b>
<div id="add_position-search" class="col-9">
<div class="input-group">
<input type="text" class="form-control" id="add_position_search-searchbar" data-search-type="position">
<span class="input-group-append">
<span class="btn btn-outline-secondary" type="button">
<svg width="16" height="16" fill="currentColor">
<use xlink:href="/img/bootstrap-icons.svg#search"></use>
</svg>
</span>
</span>
</div>
<div class="add_position_search-search-result-overlay" style="">
<ul class="add_position_search-search-result-overlay-list">
</ul>
</div>
</div>
</div>
<hr>
<h3>Fahrzeugpositionen</h3><br>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
<button class="iconbutton template_detailed_check_all_vehicles">
<svg width="1.25em" height="1.25em" fill="currentColor">
<use xlink:href="/img/bootstrap-icons.svg#check-all"></use>
</svg>
</button>
</th>
<th scope="col">Name</th>
<th scope="col">Beschreibung</th>
<th scope="col">Fahrzeugkategorie</th>
</tr>
</thead>
<tbody class="template_detailed_vehicles_tbody">
{{#each vehicle_positions}}
<tr>
<td><input type="checkbox" class="template_detailed_vehicle_checkbox" data-vehicle-id="{{id}}">
</td>
<td>{{name}}</td>
<td>{{description}}</td>
<td>{{required_vehicle_category}}</td>
</tr>
{{/each}}
</tbody>
</table>
<button type="button" class="btn btn-danger btn-sm templates_detailed_delete_vehicle_button">Löschen</button>
<br><br>
<b>Hinzufügen:</b>
<form action="javascript:void(0);" id="template_detailed_form">
<div class="form-group row">
<label for="template_detailed_vehicle_name" class="col-sm-3 col-form-label">Bezeichnung</label>
<label for="template_detailed_name" class="col-sm-3 col-form-label">Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="template_detailed_vehicle_name" value="{{vehicle_name}}">
<input class="form-control qsf" id="template_detailed_name"
oninvalid="this.setCustomValidity('Es muss ein Vorlagenname angegeben werden!')" required
type="text" value="{{name}}"></input>
</div>
</div>
<div class="form-group row">
<label for="template_detailed_vehicle_description" class="col-sm-3 col-form-label">Beschreibung</label>
<label for="template_detailed_description" class="col-sm-3 col-form-label">Beschreibung</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="template_detailed_vehicle_description" value="{{vehicle_description}}">
<input class="form-control qsf" id="template_detailed_description" type="text"
value="{{description}}"></input>
</div>
</div>
<div class="form-group row">
<label for="template_detailed_vehicle_category_select" class="col-sm-3 col-form-label">Fahrzeugkategorie:</label>
<div class="col-sm-9">
<select id="template_detailed_vehicle_category_select" class="form-control col-9"></select>
</div>
<div>
<hr>
<h3>Positionen</h3><br>
<table class="table table-striped table-hover">
<thead>
<tr>
<th scope="col">Position</th>
<th scope="col">Beschreibung</th>
<th scope="col">Bezeichnung</th>
<th scope="col" style="width:15%">Anzahl</th>
<th scope="col">Aktionen</th>
</tr>
</thead>
<tbody class="template_detailed_positions_tbody">
{{#each positions}}
{{> em_event_unit_templates_template_detailed_position_row}}
{{/each}}
{{> em_event_unit_templates_template_detailed_position_row_empty base="add_position_search_first"}}
</tbody>
</table>
<hr>
<h3>Fahrzeugpositionen</h3><br>
<table class="table table-striped table-hover">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Beschreibung</th>
<th scope="col">Fahrzeugkategorie</th>
<th scope="col">Aktionen</th>
</tr>
</thead>
<tbody class="template_detailed_vehicle_positions_tbody">
{{#each vehicle_positions}}
{{> em_event_unit_templates_template_detailed_vehicle_position_row
vehicle_categories=../vehicle_categories }}
{{/each}}
{{> em_event_unit_templates_template_detailed_vehicle_position_row_empty}}
</tbody>
</table>
</div>
<button type="button" class="template_detailed_vehicle_add btn btn-secondary">Fahrzeugposition hinzufügen</button>
</div>
<input type="hidden" id="template_detailed_entity_id" value="{{entity_id}}"><br>
<button type="button" class="template_detailed_submit btn btn-primary" style="float: right; margin-bottom:15px;">
Änderungen Speichern
</button>
<input id="template_detailed_entity_id" type="hidden" value="{{entity_id}}"></input><br>
</form>
</div>

View File

@ -0,0 +1,19 @@
<tr class="position_row" data-position-id="{{position.entity_id}}" data-position-template-id="{{position_template_id}}">
<td>{{position.name}}</td>
<td>{{position.description}}</td>
<td><input class="form-control qsf position_tag" type="text" value="{{tag}}"></input></td>
<td><input class="form-control qsf position_num" type="number" value="{{num}}"></input></td>
<td>
<button class="iconbutton remove_position_btn qsf" title="Position von Template entfernen" type="button">
<svg fill="currentColor" height="1.5em" width="1.5em">
<use xlink:href="/img/bootstrap-icons.svg#trash"></use>
</svg>
</button>
<button class="iconbutton unremove_position_btn qsf" style="display: none;"
title="Das Entfernen der Position von Template rückgängig machen" type="button">
<svg fill="currentColor" height="1.5em" width="1.5em">
<use xlink:href="/img/bootstrap-icons.svg#arrow-counterclockwise"></use>
</svg>
</button>
</td>
</tr>

View File

@ -0,0 +1,13 @@
<tr class="empty_row position_row">
<td colspan="2">{{> search type="position"}}</td>
<td><input class="form-control add_position_tag" type="text"></input></td>
<td><input class="form-control add_position_num" min="1" type="number" value="1"></input></td>
<td>
<button class="iconbutton remove_position_new_row_btn qsf" title="Position von Template entfernen"
type="button">
<svg fill="currentColor" height="1.5em" width="1.5em">
<use xlink:href="/img/bootstrap-icons.svg#trash"></use>
</svg>
</button>
</td>
</tr>

View File

@ -0,0 +1,24 @@
<tr class="vehicle_position_row" data-vehicle-position-id="{{entity_id}}">
<td><input class="form-control qsf vehicle_position_name" type="text" value="{{name}}"></input></td>
<td><input class="form-control qsf vehicle_position_description" type="text" value="{{description}}"></input></td>
<td><select class="vehicle_position_category form-control qsf"
data-selected-category="{{required_vehicle_category}}">
{{#each vehicle_categories}}
<option title="{{description}}" value="{{id}}">{{name}}</option>
{{/each}}
</select></td>
<td>
<button class="iconbutton remove_vehicle_position_btn qsf" title="Fahrzeugposition von Template entfernen"
type="button">
<svg fill="currentColor" height="1.5em" width="1.5em">
<use xlink:href="/img/bootstrap-icons.svg#trash"></use>
</svg>
</button>
<button class="iconbutton unremove_vehicle_position_btn qsf" style="display: none;"
title="Das Entfernen der Fahrzeugposition von Template rückgängig machen" type="button">
<svg fill="currentColor" height="1.5em" width="1.5em">
<use xlink:href="/img/bootstrap-icons.svg#arrow-counterclockwise"></use>
</svg>
</button>
</td>
</tr>

View File

@ -0,0 +1,17 @@
<tr class="empty_row vehicle_position_row">
<td><input class="form-control add_vehicle_position_name" type="text"></input></td>
<td><input class="form-control add_vehicle_position_description" type="text"></input></td>
<td><select class="add_vehicle_position_category form-control">
{{#each vehicle_categories}}
<option title="{{description}}" value="{{id}}">{{name}}</option>
{{/each}}
</select></td>
<td>
<button class="iconbutton remove_vehicle_position_new_row_btn" title="Fahrzeugposition von Template entfernen"
type="button">
<svg fill="currentColor" height="1.5em" width="1.5em">
<use xlink:href="/img/bootstrap-icons.svg#trash"></use>
</svg>
</button>
</td>
</tr>

View File

@ -1,6 +0,0 @@
<tr class="eu_vehicle_position_tr" data-entity_id="{{entity_id}}">
<td><input type="checkbox" class="eu_vehicle_position_checkbox" data-entity-id="{{entity_id}}"></td>
<td>{{name}}</td>
<td>{{description}}</td>
<td>{{required_vehicle_category_name}}</td>
</tr>

View File

@ -1,6 +1,7 @@
<div id="{{base}}-search">
<div class="eo-search" id="{{base}}-search">
<div class="input-group">
<input type="text" class="form-control" id="{{base}}-searchbar" autocomplete="off" data-search-type="{{type}}">
<input autocomplete="off" class="form-control eo-searchbar" data-search-type="{{type}}" id="{{base}}-searchbar"
type="text">
<span class="input-group-append">
<span class="btn btn-outline-secondary" type="button">
<svg width="16" height="16" fill="currentColor">
@ -14,7 +15,7 @@
</div>
</div>
<div class="input-group" id="{{base}}_input_group" style="display: none;">
<input type="text" disabled id="{{base}}" class="form-control">
<input class="form-control eo-search-selected" disabled id="{{base}}" type="text">
<span class="input-group-append">
<span class="btn btn-outline-secondary" id="{{base}}_remove"
type="button">

7
resources/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -244,17 +244,37 @@ th.rotate > div > span {
padding: 7px;
text-align: center;
}
#sidebar .sidebar-navigation {
text-align: center;
}
}
/* Quick save fields */
input.qsf{
input.qsf {
background-color: #E8EEE9;
}
.modified{
select.qsf {
background-color: #E8EEE9;
}
button.modified {
background-color: initial !important;
border-style: none !important;
}
.modified {
background-color: white !important;
border-style: dashed !important;
}
.marked-for-delete {
background-image: linear-gradient(136deg, #ffd9d9 13.64%, #ffffff 13.64%, #ffffff 50%, #ffd9d9 50%, #ffd9d9 63.64%, #ffffff 63.64%, #ffffff 100%);
background-size: 15.84px 15.29px;
}
/* Overwriting card-header min-height to unify header height if some cards have buttons inside */
.card-header {
min-height: 56px !important;
}

View File

@ -0,0 +1,587 @@
limit = 10;
$(document).ready(async function () {
await EventUnitTemplatesModule.load_templates();
EventUnitTemplatesModule.setup_pagination();
await EventUnitTemplatesModule.load_eu_template_list();
});
EventUnitTemplatesApi = (function () {
let requests = [];
let run_all = async function (successCallback, failureCallback) {
await Promise.all(requests.map(req => $.ajax(req))).then(successCallback, failureCallback);
requests = [];
};
let add_position_to_template = function (position_template_entry) {
requests.push({
url: '/api/events/units/templates/' + position_template_entry.template_id + '/positions/' + position_template_entry.position_entity_id,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(position_template_entry),
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte neue Position nicht speichern!");
}
});
};
let update_position_for_template = function (position_template_entry) {
requests.push({
url: '/api/events/units/templates/' + position_template_entry.template_id + '/positions/' + position_template_entry.position_entity_id + '/' + position_template_entry.position_template_id,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(position_template_entry),
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte geänderte Position nicht speichern!");
}
});
};
let remove_position_from_template = function (position_template_id, template_id, position_id) {
requests.push({
url: '/api/events/units/templates/' + template_id + '/positions/' + position_id + '/' + position_template_id,
type: 'DELETE',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte Position nicht von der Vorlage entfernen!");
}
});
};
let update_template_core_data = function (template) {
requests.push({
url: '/api/events/units/templates/' + template.entity_id,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(template),
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte Namen & Beschreibung des Templates nicht speichern!");
}
});
};
let add_vehicle_position = function (vehicle_position_entry) {
requests.push({
url: '/api/events/units/vehicle_positions',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(vehicle_position_entry),
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte neue Fahrzeugposition nicht speichern!");
}
});
};
let remove_vehicle_position = function (vehicle_position_id) {
requests.push({
url: '/api/events/units/vehicle_positions/' + vehicle_position_id,
type: 'DELETE',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte Position nicht von der Vorlage entfernen!");
}
});
};
let update_vehicle_position = function (vehicle_position_entry) {
requests.push({
url: '/api/events/units/vehicle_positions/' + vehicle_position_entry.entity_id,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(vehicle_position_entry),
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
EventUnitTemplatesModule.show_alert("danger", "Konnte geänderte Position nicht speichern!");
}
});
};
return {
add_position_to_template,
update_position_for_template,
remove_position_from_template,
update_template_core_data,
add_vehicle_position,
remove_vehicle_position,
update_vehicle_position,
run_all
}
}());
EventUnitTemplatesModule = (function () {
let templates = {};
let eu_templates = new Map();
let loaded_template = {};
let old_offset = 0;
let searchbar_counter = 0;
let pag = null;
let all_checked = false;
let template_modified = false;
let activate_modified = function () {
if (!template_modified) { //Only execute on first modification
template_modified = true;
$(".save-button").off("click").on("click", save).show(); //Show save button
}
$(this).addClass("modified");
};
let deactivate_modified = function () {
if (template_modified) { //Only execute on first modification
template_modified = false;
$(".save-button").hide(); //Show save button
}
};
let show_alert = function (level, msg) {
let alerto = {};
alerto.level = level;
alerto.content = msg;
$(".alertbox").append(templates.alert(alerto));
$(".alert").delay(4000).slideUp(500, function () {
$(this).alert('close');
});
};
let delete_templates = function () {
let template_list = [];
$(".eu_template_checkbox").each(function (k, v) {
if ($(v).prop("checked")) {
template_list.push($(v).data("entity-id"));
}
});
$.ajax({
url: '/api/events/units/templates/',
type: 'DELETE',
data: JSON.stringify(template_list),
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
$(".eu_template_checkbox").each(function (k, v) {
if (template_list.includes($(v).data("entity-id"))) {
$(this).parent().parent().remove();
}
})
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let create_template = function () {
let pdata = {};
if (!$("#template_new_name").val()) {
alert("Bitte alle Felder ausfüllen!");
return
} else {
pdata.name = $("#template_new_name").val();
}
if ($("#template_new_description").val().length > 0) {
pdata.description = $("#template_new_description").val();
}
$.ajax({
url: '/api/events/units/templates',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(pdata),
success: function (data) {
if (is_ok(data)) {
location.reload();
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let mod_positions = (function () {
let save = function () {
// Save new positions
$(".position_row.new_row").each(function () {
let position_template_entry = {};
position_template_entry.template_id = loaded_template.entity_id || undefined;
position_template_entry.position_entity_id = $(this).find(".eo-search-selected").data("entity-id") || undefined;
position_template_entry.tag = $(this).find(".add_position_tag").val() || undefined;
position_template_entry.num = $(this).find(".add_position_num").val() || undefined;
if (!position_template_entry.position_entity_id || !position_template_entry.num) { //Skip row if no num or position
return false;
}
EventUnitTemplatesApi.add_position_to_template(position_template_entry);
})
// Save modified positions
// Using .position_row .modified (with whitespace) to select all position_rows where any child has .modified
$(".position_row .modified").each(function () {
let row = $(this).closest(".position_row");
if (row.length === 0 || row.hasClass("marked-for-delete") || row.hasClass("new_row") || row.hasClass("empty_row")) { //Skip row if also marked for deletion or is new (don't edit rows which going to be deleted)
return false;
}
let position_template_entry = {};
position_template_entry.position_template_id = row.data("position-template-id") || undefined;
position_template_entry.template_id = loaded_template.entity_id || undefined;
position_template_entry.position_entity_id = row.data("position-id") || undefined;
position_template_entry.tag = row.find(".position_tag").val() || undefined;
position_template_entry.num = row.find(".position_num").val() || undefined;
EventUnitTemplatesApi.update_position_for_template(position_template_entry);
})
// Save deleted positions
// Using .position_row.marked-for-delete to select all position_rows which also have .marked-for-delete
$(".position_row.marked-for-delete").each(function () {
EventUnitTemplatesApi.remove_position_from_template($(this).data("position-template-id"), loaded_template.entity_id, $(this).data("position-id"));
})
};
let mark_for_delete = function () {
let row = $(this).closest(".position_row");
row.addClass("marked-for-delete");
$(this).hide();
row.find(".unremove_position_btn").show();
};
let unmark_for_delete = function () {
let row = $(this).closest(".position_row");
row.removeClass("marked-for-delete");
$(this).hide();
row.find(".remove_position_btn").show();
}
return {
save,
mark_for_delete,
unmark_for_delete,
}
}());
let mod_vehicle_positions = (function () {
let save = function () {
// Save new vehicle positions
$(".vehicle_position_row.new_row").each(function () {
let vehicle_position_entry = {};
vehicle_position_entry.template_id = loaded_template.entity_id || undefined;
vehicle_position_entry.name = $(this).find(".add_vehicle_position_name").val() || undefined;
vehicle_position_entry.description = $(this).find(".add_vehicle_position_description").val() || undefined;
vehicle_position_entry.required_vehicle_category = $(this).find(".add_vehicle_position_category").val() || undefined;
if (!vehicle_position_entry.template_id || !vehicle_position_entry.name || !vehicle_position_entry.required_vehicle_category) { //Skip row if no num or position
return false;
}
EventUnitTemplatesApi.add_vehicle_position(vehicle_position_entry);
});
// Save modified vehicle positions
// Using .vehicle_position_row .modified (with whitespace) to select all vehicle_position_rows where any child has .modified
$(".vehicle_position_row .modified").each(function () {
let row = $(this).closest(".vehicle_position_row");
if (row.length === 0 || row.hasClass("marked-for-delete") || row.hasClass("new_row") || row.hasClass("empty_row")) { //Skip row if also marked for deletion or is new (don't edit rows which going to be deleted)
return false;
}
let vehicle_position_entry = {};
vehicle_position_entry.entity_id = row.data("vehicle-position-id") || undefined;
vehicle_position_entry.template_id = loaded_template.entity_id || undefined;
vehicle_position_entry.name = row.find(".vehicle_position_name").val() || undefined;
vehicle_position_entry.description = row.find(".vehicle_position_description").val() || undefined;
vehicle_position_entry.required_vehicle_category = row.find(".vehicle_position_category").val() || undefined;
EventUnitTemplatesApi.update_vehicle_position(vehicle_position_entry);
});
// Save deleted vehicle positions
// Using .vehicle_position_row.marked-for-delete to select all vehicle_position_rows which also have .marked-for-delete
$(".vehicle_position_row.marked-for-delete").each(function () {
EventUnitTemplatesApi.remove_vehicle_position($(this).data("vehicle-position-id"));
})
};
let mark_for_delete = function () {
let row = $(this).closest(".vehicle_position_row");
row.addClass("marked-for-delete");
$(this).hide();
row.find(".unremove_vehicle_position_btn").show();
};
let unmark_for_delete = function () {
let row = $(this).closest(".vehicle_position_row");
row.removeClass("marked-for-delete");
$(this).hide();
row.find(".remove_vehicle_position_btn").show();
}
return {
save,
mark_for_delete,
unmark_for_delete,
}
}());
let mod_template = (function () {
let save = function () {
let template = {};
template.entity_id = loaded_template.entity_id || undefined;
template.name = $("#template_detailed_name").val() || undefined;
template.description = $("#template_detailed_description").val() || undefined;
if (template.name !== loaded_template.name || template.description !== loaded_template.description) {
//Name or description changed!
EventUnitTemplatesApi.update_template_core_data(template);
}
};
return {
save: save,
}
}());
let save = async function () {
mod_positions.save();
mod_template.save();
mod_vehicle_positions.save();
EventUnitTemplatesApi.run_all(async function () {
template_modified = false; //Reset modified variable
$(".save-button").hide(); //Hide save button
$(".modified").removeClass("modified"); //Remove modified style from all fields
//TODO: save animation/confirmation
let active_template = loaded_template.entity_id;
await load_eu_template_list(old_offset);
await load_detailed_template(null, active_template);
}, function () {
console.log("Error occurred during one or more requests");
})
};
let load_templates = async function () {
const template_row = $.get("/templates/em_event_unit_templates_template_row.hbs");
const template_detailed = $.get("/templates/em_event_unit_templates_template_detailed.hbs");
const template_detailed_position_row = $.get("/templates/em_event_unit_templates_template_detailed_position_row.hbs");
const template_detailed_position_row_empty = $.get("/templates/em_event_unit_templates_template_detailed_position_row_empty.hbs");
const template_detailed_vehicle_position_row = $.get("/templates/em_event_unit_templates_template_detailed_vehicle_position_row.hbs");
const template_detailed_vehicle_position_row_empty = $.get("/templates/em_event_unit_templates_template_detailed_vehicle_position_row_empty.hbs");
const search = $.get("/templates/search.hbs");
const pagination = $.get("/templates/pagination.hbs");
const alert = $.get("/templates/alert.hbs");
await Promise.all([template_row, template_detailed, template_detailed_position_row, template_detailed_position_row_empty, search, pagination, alert, template_detailed_vehicle_position_row, template_detailed_vehicle_position_row_empty]).then(function (res) {
Handlebars.registerPartial('search', Handlebars.compile(res[4]));
Handlebars.registerPartial('em_event_unit_templates_template_detailed_position_row', Handlebars.compile(res[2]));
Handlebars.registerPartial('em_event_unit_templates_template_detailed_position_row_empty', Handlebars.compile(res[3]));
Handlebars.registerPartial('em_event_unit_templates_template_detailed_vehicle_position_row', Handlebars.compile(res[7]));
Handlebars.registerPartial('em_event_unit_templates_template_detailed_vehicle_position_row_empty', Handlebars.compile(res[8]));
templates.template_row = Handlebars.compile(res[0]);
templates.template_detailed = Handlebars.compile(res[1]);
templates.template_detailed_position_row_empty = Handlebars.compile(res[3]);
templates.template_detailed_vehicle_position_row_empty = Handlebars.compile(res[8]);
templates.pagination = Handlebars.compile(res[5]);
templates.alert = Handlebars.compile(res[6]);
});
};
let setup_pagination = function(){
pag = new Pagination("em_eu_templates_pagination", templates.pagination, ".pag", limit, load_eu_template_list);
}
let load_eu_template_list = async function(offset){
if(offset === undefined || !Number.isInteger(offset)){
offset = 0;
}
old_offset = offset;
await $.ajax({
url: '/api/events/units/templates?limit=' + limit + '&offset=' + offset,
type: 'GET',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
eu_templates = new Map();
for (let t in data.templates) {
eu_templates.set(data.templates[t].entity_id, data.templates[t]);
}
$("#template_list_tbody").empty();
for (const [key, value] of eu_templates.entries()) {
$("#template_list_tbody").append(templates.template_row(value));
}
pag.render(data.total_template_count, offset);
$(".eu_template_tr").off("click").on("click", load_detailed_template);
$(".templates_delete_button").on("click", delete_templates);
$(".template_new_submit").on("click", create_template);
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let load_detailed_template = async function (context, selected_template) {
//TODO: add warning modal if pending changes
deactivate_modified(); //Reset modified variable
$(".template_detailed_card").show();
all_checked = false;
$(".eu_template_tr").removeClass("table-primary");
$(this).addClass("table-primary");
let entity_id = ((selected_template) ? selected_template : $(this).data("entity_id"));
$(".template_detailed_card_body").remove();
loaded_template = eu_templates.get(entity_id);
if (loaded_template) { //Check if template found for id
await load_positions_for_template(loaded_template);
//await load_vehicle_positions();
//Apply qsf handler:
$(".qsf").off("focusin focusout").on("focusin focusout", activate_modified).keyup(function (e) {
if (event.which === 13) {
activate_modified(e.target);
}
});
$(".template_detailed_card").show();
}
};
let load_positions_for_template = async function(eu_template) {
let positions = await $.ajax({
url: '/api/events/units/templates/' + eu_template.entity_id + '/positions',
type: 'GET',
contentType: 'application/json',
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
let vehicle_positions = await $.ajax({
url: '/api/events/units/templates/' + eu_template.entity_id + '/vehicle_positions',
type: 'GET',
contentType: 'application/json',
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
let vehicle_categories = await $.ajax({
url: '/api/resources/vehicles/categories',
type: 'GET',
contentType: 'application/json',
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
await Promise.all([positions, vehicle_positions, vehicle_categories]).then(function (res) {
positions = res[0];
vehicle_positions = res[1];
vehicle_categories = res[2];
});
//const vehicle_categories =
if (is_ok(positions) && is_ok(vehicle_positions) && is_ok(vehicle_categories)) {
eu_template.positions = positions;
eu_template.vehicle_positions = vehicle_positions;
eu_template.vehicle_categories = vehicle_categories;
$(".template_detailed_card").append(templates.template_detailed(eu_template));
// --- Positions ---
//Add position search
let position_search = new MiniSearchbar("add_position_search_first", null);
position_search.setup();
//Add position remove / unremove buttons
$(".remove_position_btn").off("click").on("click", mod_positions.mark_for_delete); //Add delete button listener
$(".unremove_position_btn").off("click").on("click", mod_positions.unmark_for_delete); //Add undelete button listener
//Add new empty row when existing new row is clicked
let add_new_empty_position_row = function () {
$(".empty_row.position_row").removeClass("empty_row").addClass("new_row"); //Change row status from empty to new
$(".new_row").off("click focus"); //Remove this function from row
let sid = {};
sid.base = "add_position_search_" + searchbar_counter;
searchbar_counter++;
$(".template_detailed_positions_tbody").append(templates.template_detailed_position_row_empty(sid)); //Add new empty row
let position_search = new MiniSearchbar(sid.base, null);
position_search.setup();
$(".remove_position_btn").off("click").on("click", mod_positions.mark_for_delete); //Add delete button listener
$(".unremove_position_btn").off("click").on("click", mod_positions.unmark_for_delete); //Add undelete button listener
$(".remove_position_new_row_btn").off("click").on("click", function () {
$(this).closest(".new_row").remove();
})
$(".empty_row.position_row").on("click focus", add_new_empty_position_row); //Add this function to the empty row.
activate_modified();
};
$(".empty_row.position_row").on("click focus", add_new_empty_position_row);
// --- Vehicle Positions ---
//Add new empty row when existing new row is clicked
let add_new_empty_vehicle_position_row = function () {
$(".empty_row.vehicle_position_row").removeClass("empty_row").addClass("new_row"); //Change row status from empty to new
$(".new_row").off("click focus"); //Remove this function from row
$(".template_detailed_vehicle_positions_tbody").append(templates.template_detailed_vehicle_position_row_empty(loaded_template)); //Add new empty row
$(".remove_vehicle_position_btn").off("click").on("click", mod_vehicle_positions.mark_for_delete); //Add delete button listener
$(".unremove_vehicle_position_btn").off("click").on("click", mod_vehicle_positions.unmark_for_delete); //Add undelete button listener
$(".remove_vehicle_position_new_row_btn").off("click").on("click", function () {
$(this).closest(".new_row").remove();
})
$(".empty_row.vehicle_position_row").on("click focus", add_new_empty_vehicle_position_row); //Add this function to the empty row.
activate_modified();
};
$(".empty_row.vehicle_position_row").on("click focus", add_new_empty_vehicle_position_row);
//Set vehicle category selects to current category
$(".vehicle_position_category").each(function () {
$(this).val($(this).data("selected-category"));
})
//Add position remove / unremove buttons
$(".remove_vehicle_position_btn").off("click").on("click", mod_vehicle_positions.mark_for_delete); //Add delete button listener
$(".unremove_vehicle_position_btn").off("click").on("click", mod_vehicle_positions.unmark_for_delete); //Add undelete button listener
}
};
return {
load_templates: load_templates,
setup_pagination: setup_pagination,
load_eu_template_list: load_eu_template_list,
show_alert: show_alert,
}
}());

View File

@ -1,3 +1,6 @@
// DO NOT USE. DEPRECATED! USE em_eu_templates.js instead!!!
// TODO: remove
let all_checked = false;
let all_checked_vehicles = false;
let limit = 10;
@ -9,9 +12,12 @@ let current_template_selected;
$( document ).ready(function() {
EventUnitTemplatesModule.load_templates();
console.log("Don't use this script you honk! If someone pushed this to production hang him!");
//Do not execute code here which relies on templates. Use EventUnitTemplateModule.start function instead
});
// DO NOT USE. DEPRECATED! USE em_eu_templates.js instead!!!
EventUnitTemplatesModule = ( function() {
let templates = {};
let vehicle_categories = [];
@ -168,6 +174,7 @@ EventUnitTemplatesModule = ( function() {
});
if(is_ok(data)){
templ.positions = data;
console.log(templ);
$(".template_detailed_card").append(templates.template_detailed(templ));
$(".template_detailed_check_all_positions").off("click").on("click", function(){
$($(".template_detailed_position_checkbox")).prop("checked", !positions_all_checked);
@ -203,7 +210,7 @@ EventUnitTemplatesModule = ( function() {
};
let add_position_search_callback = function(sr){
$.ajax({
url: '/api/events/units/templates/'+current_template_selected+'/positions/'+$(sr).data("entity-id"),
url: '/api/events/units/templates/'+current_template_selected+'/positions/'+$(sr).data("entity-id")+"/times/1",
type: 'PUT',
contentType: 'application/json',
success: function (data) {

View File

@ -42,6 +42,16 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name, delete_callback){
$("#"+ms.base).val($(caller).data("identifier")).attr("data-entity-id", $(caller).data("entity-id")).data("entity-id", $(caller).data("entity-id"));
$("#"+ms.base+"_input_group").show();
}
}else if(ms.searchtype === "position"){
ms.callback = function(caller){
$("#"+ms.base+"-search").hide();
let description = "";
if(caller.description){
description = " ("+caller.description+")"
}
$("#"+ms.base).val(caller.name+description).attr("data-entity-id", caller.entity_id);
$("#"+ms.base+"_input_group").show();
}
}else{
console.log("unknown searchtype:"+ms.searchtype);
}
@ -150,18 +160,30 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name, delete_callback){
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
let res_map = new Map();
ms.overlay_list.html("");
$.each(data.positions, function (index, value) {
ms.overlay_list.append("<span tabindex=\"0\" class=\"" + ms.base + "-search-result-overlay-result\" style=\"cursor: pointer\" data-entity-id=\"" + value.entity_id + "\" data-name=\"" + value.name + "\" data-description=\"" + value.description + "\"><li class='list-group-item'><span class=\"badge badge-secondary\">Hinzufügen:</span> "+value.name+"</li></span>")
res_map.set(value.entity_id, value);
ms.overlay_list.append("<span tabindex=\"0\" class=\"" + ms.base + "-search-result-overlay-result\" style=\"cursor: pointer\" data-entity-id=\"" + value.entity_id+"\"><li class='list-group-item'><span class=\"badge badge-secondary\">Hinzufügen:</span> "+value.name+"</li></span>")
});
// We are using the new way to pass the data to the callback: Instead of using data attributes
// for each field we save all retrieved data in a Map (res_map) and pass the entry from
// this Map to the callback.
// TODO: implement this for each search type! But be careful, you will need to change every callback.
//select search result on click
$("." + ms.base + "-search-result-overlay-result").off("click").on("click", function () {
ms.callback(this)
let res = res_map.get($(this).data("entity-id"));
ms.callback(res);
});
//select search result on enter key press
$("." + ms.base + "-search-result-overlay-result").off("keyup").on("keyup", function (e) {
if (e.keyCode === 13) {
ms.callback(this);
let res = res_map.get($(this).data("entity-id"));
ms.callback(res);
}
});
}

View File

@ -5,6 +5,7 @@
{{> sidebar }}
{{> searchbar}}
<hr>
<div class="alertbox"></div>
<h1>Vorlagen</h1>
<div class="col">
<div class="row">
@ -24,21 +25,8 @@
</tbody>
</table>
<button class="iconbutton check_all_templates"><svg width="1.25em" height="1.25em" style="margin-left: 12px;margin-right: 12px; fill="currentColor"><use xlink:href="/img/bootstrap-icons.svg#check-all"></use></svg></button><button type="button" class="btn btn-danger btn-sm templates_delete_button">Löschen</button>
<div class="row">
<nav aria-label="vehicle list" class="mx-auto">
<ul class="pagination">
<li class="page-item template_list_nav_back_li">
<a class="page-link template_list_nav_back" href="#" aria-label="Vorherige Seite">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<li class="page-item">
<a class="page-link template_list_nav_next" href="#" aria-label="Nächste Seite">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
<div class="row pag">
</div>
</div>
</div>
@ -67,7 +55,11 @@
</div>
<div class="col col-lg-6">
<div class="card bg-light mb-3 template_detailed_card" style="display: none">
<div class="card-header">Vorlage</div>
<div class="card-header d-flex justify-content-between align-items-center">Vorlage
<button class="btn btn-success btn-sm save-button" style="display: none;">Änderungen
Speichern
</button>
</div>
</div>
</div>
</div>

View File

@ -4,9 +4,9 @@
<div class="col-lg-9" style="align-self: center;">
<h1>Willkommen bei einsatz.online!</h1>
</div>
<div class="col-lg-3">
<!--<div class="col-lg-3">
<img src="/img/Santa-Sleigh-PNG.png" style="float: right; width: inherit;">
</div>
</div>-->
</div>
</div>
<div class="login row">

View File

@ -1 +1 @@
v0.2-62-gdd0d248
v0.2-71-g4b9ea4a

View File

@ -1,12 +1,12 @@
use crate::helper::settings::Settings;
use rocket::State;
use crate::database::controller::connector::establish_connection;
use diesel::{RunQueryDsl, ExpressionMethods};
use crate::schema::entities::dsl::entities;
use diesel::{ExpressionMethods, RunQueryDsl};
use diesel::query_dsl::filter_dsl::FilterDsl;
use rocket::State;
pub fn generate_entity(settings: &State<Settings>) -> Result<uuid::Uuid, diesel::result::Error>{
use crate::database::controller::connector::establish_connection;
use crate::helper::settings::Settings;
use crate::schema::entities::dsl::entities;
pub fn generate_entity(settings: &State<Settings>) -> Result<uuid::Uuid, diesel::result::Error> {
let connection = establish_connection(settings);
match diesel::insert_into(entities).default_values().returning(crate::schema::entities::dsl::entity_id).get_result(&connection){
@ -18,11 +18,14 @@ pub fn generate_entity(settings: &State<Settings>) -> Result<uuid::Uuid, diesel:
}
}
pub fn remove_entity(settings: &State<Settings>, entity_id: uuid::Uuid) -> Result<(), diesel::result::Error>{
/// Deprecated!
/// Security Issue: This method doesn't check the entity type. This allows users to delete any resource
// TODO: remove
#[deprecated]
pub fn remove_entity(settings: &State<Settings>, entity_id: uuid::Uuid) -> Result<(), diesel::result::Error> {
let connection = establish_connection(settings);
match diesel::delete(entities.filter(crate::schema::entities::dsl::entity_id.eq(entity_id))).execute(&connection){
match diesel::delete(entities.filter(crate::schema::entities::dsl::entity_id.eq(entity_id))).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't delete entity_id: {}", e);

View File

@ -1,20 +1,26 @@
use diesel::{RunQueryDsl, ExpressionMethods, JoinOnDsl, PgTextExpressionMethods, BoolExpressionMethods, sql_query};
use rocket::State;
use crate::helper::settings::Settings;
use crate::database::model::events::{Event, EventType, EventUnitPosition, EventUnitTemplate, EventUnitInstance, EventUnitVehiclePosition, EventUnitInstancePosition, EventUnitInstanceVehiclePosition};
use crate::database::controller::connector::establish_connection;
use chrono::NaiveDateTime;
use crate::diesel::QueryDsl;
use diesel::pg::types::sql_types::Uuid;
use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, PgTextExpressionMethods, RunQueryDsl, sql_query};
use diesel::dsl::any;
use diesel::pg::types::sql_types::Uuid;
use rocket::State;
use crate::database::controller::connector::establish_connection;
use crate::database::controller::events::templates::vehicle_positions::get_eu_vehicle_positions_for_template;
use crate::database::model::events::{Event, EventType, EventUnitInstance, EventUnitInstancePosition, EventUnitInstanceVehiclePosition, EventUnitPosition, EventUnitTemplate, EventUnitVehiclePosition};
use crate::diesel::QueryDsl;
use crate::helper::settings::Settings;
use crate::schema::eu_positions_templates;
pub fn add_event(settings: &State<Settings>, data: Event) -> Result<Event, diesel::result::Error>{
pub mod templates;
//TODO: migrate to multiple files to improve readability
pub fn add_event(settings: &State<Settings>, data: Event) -> Result<Event, diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(events).values(data).get_result(&connection){
match diesel::insert_into(events).values(data).get_result(&connection) {
Ok(org) => Ok(org),
Err(e) => {
error!("Couldn't create event: {}", e);
@ -207,11 +213,11 @@ pub fn add_event_unit_template(settings: &State<Settings>, eut: EventUnitTemplat
}
}
pub fn add_position_to_template(settings: &State<Settings>, template_id2 : uuid::Uuid, position_id : uuid::Uuid) -> Result<(), diesel::result::Error>{
pub fn add_position_to_template(settings: &State<Settings>, data: RawEventUnitTemplatePosition) -> Result<(), diesel::result::Error> {
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(eu_positions_templates).values((position_entity_id.eq(position_id), template_id.eq(template_id2))).execute(&connection){
match diesel::insert_into(eu_positions_templates).values(data).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't add position to template: {}", e);
@ -258,40 +264,76 @@ pub fn get_event_unit_templates_count(settings: &State<Settings>,) -> Result<i64
}
}
pub fn get_event_unit_positions_for_template(settings: &State<Settings>, template: uuid::Uuid) -> Result<Vec<EventUnitPosition>, diesel::result::Error>{
#[derive(Queryable, Clone, Deserialize, Serialize, AsChangeset, Insertable, Identifiable)]
#[table_name = "eu_positions_templates"]
#[changeset_options(treat_none_as_null = "true")]
#[primary_key(position_template_id)]
pub struct RawEventUnitTemplatePosition{
pub(crate) position_entity_id: uuid::Uuid,
pub(crate) template_id: uuid::Uuid,
pub(crate) position_template_id: uuid::Uuid, //primary key
pub(crate) num: i32,
pub(crate) tag: Option<String>,
}
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct EventUnitTemplatePosition{
pub(crate) position_template_id: uuid::Uuid,
pub(crate) tag: Option<String>,
pub(crate) num: i32,
pub(crate) template_id: uuid::Uuid,
pub(crate) position: EventUnitPosition,
}
pub fn get_event_unit_positions_for_template(settings: &State<Settings>, template: uuid::Uuid) -> Result<Vec<EventUnitTemplatePosition>, diesel::result::Error>{
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
let mut res: Vec<EventUnitTemplatePosition> = vec![];
let positions : Vec<RawEventUnitTemplatePosition> = match eu_positions_templates.filter(template_id.eq(template)).get_results(&connection){
Ok(pos) => pos,
Err(e) => {
error!("Couldn't get unit positions for template: {}", e);
return Err(e)
}
};
for position in positions{
res.push(EventUnitTemplatePosition{
position_template_id: position.position_template_id,
tag: position.tag,
num: position.num,
template_id: position.template_id,
position: get_event_unit_position(settings, position.position_entity_id)?
})
}
Ok(res)
}
fn get_event_unit_position(settings: &State<Settings>, position_id: uuid::Uuid) -> Result<EventUnitPosition, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
match eu_positions.left_join(eu_positions_templates.on(position_entity_id.eq(entity_id))).filter(template_id.eq(template)).select((entity_id, name, description, requirements)).get_results(&connection){
match eu_positions.filter(entity_id.eq(position_id)).get_result(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit positions for template: {}", e);
Err(e)
}
}
}
pub fn get_event_unit_vehicle_positions_for_template(settings: &State<Settings>, template: uuid::Uuid) -> Result<Vec<EventUnitVehiclePosition>, diesel::result::Error>{
use crate::schema::eu_vehicle_positions::dsl::*;
let connection = establish_connection(settings);
match eu_vehicle_positions.filter(template_id.eq(template)).get_results(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit positions for template: {}", e);
error!("Couldn't get unit position: {}", e);
Err(e)
}
}
}
pub fn remove_positions_from_template(settings: &State<Settings>, template: uuid::Uuid, position_list: Vec<uuid::Uuid>) -> Result<(), diesel::result::Error>{
pub fn remove_position_from_template(settings: &State<Settings>, template: uuid::Uuid, position: uuid::Uuid, position_template_id2: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::delete(eu_positions_templates.filter(template_id.eq(template)).filter(position_entity_id.eq_any(position_list))).execute(&connection){
match diesel::delete(eu_positions_templates.filter(template_id.eq(template)).filter(position_entity_id.eq(position)).filter(position_template_id.eq(position_template_id2))).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't delete position from template: {}", e);
@ -300,11 +342,32 @@ pub fn remove_positions_from_template(settings: &State<Settings>, template: uuid
}
}
pub fn update_eu_template(settings: &State<Settings>, template: EventUnitTemplate) -> Result<EventUnitTemplate, diesel::result::Error>{
pub fn update_positions_templates(settings: &State<Settings>, data: RawEventUnitTemplatePosition) -> Result<EventUnitTemplatePosition, diesel::result::Error> {
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
let res: RawEventUnitTemplatePosition = match diesel::update(eu_positions_templates).filter(position_template_id.eq(data.position_template_id)).set(data).get_result(&connection) {
Ok(res) => res,
Err(e) => {
error!("Couldn't update position for template: {}", e);
return Err(e)
}
};
Ok(EventUnitTemplatePosition {
position_template_id: res.position_template_id,
tag: res.tag,
num: res.num,
template_id: res.template_id,
position: get_event_unit_position(settings, res.position_entity_id)?,
})
}
pub fn update_eu_template(settings: &State<Settings>, template: EventUnitTemplate) -> Result<EventUnitTemplate, diesel::result::Error> {
use crate::schema::eu_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::update(eu_templates.filter(entity_id.eq(template.entity_id))).set(template).get_result(&connection){
match diesel::update(eu_templates.filter(entity_id.eq(template.entity_id))).set(template).get_result(&connection) {
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't update event unit template: {}", e);
@ -334,7 +397,7 @@ pub fn add_position_instances_for_instance(settings: &State<Settings>, instance_
Err(e) => return Err(e)
};
let vehicle_positions = match get_event_unit_vehicle_positions_for_template(settings, template_id2){
let vehicle_positions = match get_eu_vehicle_positions_for_template(settings, template_id2) {
Ok(pos) => pos,
Err(e) => return Err(e)
};
@ -342,9 +405,11 @@ pub fn add_position_instances_for_instance(settings: &State<Settings>, instance_
let connection = establish_connection(settings);
for position in positions{
match diesel::insert_into(eu_position_instances).values((instance_id.eq(instance_id2), position_id.eq(position.entity_id))).execute(&connection){
Ok(_) => {},
Err(e) => return Err(e)
for i in 1..position.num+1{
match diesel::insert_into(eu_position_instances).values((instance_id.eq(instance_id2), position_id.eq(position.position.entity_id))).execute(&connection){
Ok(_) => {},
Err(e) => return Err(e)
}
}
}
@ -375,7 +440,7 @@ pub fn get_instance_positions(settings: &State<Settings>, instance_id2: uuid::Uu
let connection = establish_connection(settings);
let position_instances: Result<Vec<EventUnitInstancePosition>, diesel::result::Error> = sql_query(
"SELECT instance_id, position_id, taken_by, name, description, requirements FROM eu_position_instances INNER JOIN eu_positions ON position_id = entity_id WHERE instance_id = $1;",
"SELECT position_instance_id, instance_id, position_id, taken_by, name, description, requirements FROM eu_position_instances INNER JOIN eu_positions ON position_id = entity_id WHERE instance_id = $1;",
)
.bind::<Uuid, _>(instance_id2)
.get_results(&connection);
@ -420,19 +485,6 @@ pub fn add_vehicle_position(settings: &State<Settings>, position: EventUnitVehic
}
}
pub fn get_vehicle_positions_for_template(settings: &State<Settings>, template_id: uuid::Uuid) -> Result<Vec<EventUnitVehiclePosition>, diesel::result::Error>{
use crate::schema::eu_vehicle_positions::dsl;
let connection = establish_connection(settings);
match dsl::eu_vehicle_positions.filter(dsl::template_id.eq(template_id)).get_results(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get vehicle positions for template: {}", e);
Err(e)
}
}
}
pub fn change_position_instances(settings: &State<Settings>, instance_id2: uuid::Uuid, position_id2: uuid::Uuid, taken_by2: Option<uuid::Uuid>) -> Result<usize, diesel::result::Error>{
use crate::schema::eu_position_instances::dsl::*;

View File

@ -0,0 +1,2 @@
pub mod positions;
pub mod vehicle_positions;

View File

@ -0,0 +1,45 @@
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use rocket::State;
use crate::database::controller::connector::establish_connection;
use crate::database::model::events::EventUnitVehiclePosition;
use crate::Settings;
pub fn get_eu_vehicle_positions_for_template(settings: &State<Settings>, template_id: uuid::Uuid) -> Result<Vec<EventUnitVehiclePosition>, diesel::result::Error> {
use crate::schema::eu_vehicle_positions::dsl;
let connection = establish_connection(settings);
match dsl::eu_vehicle_positions.filter(dsl::template_id.eq(template_id)).get_results(&connection) {
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get vehicle positions for template: {}", e);
Err(e)
}
}
}
pub fn delete_eu_vehicle_position(settings: &State<Settings>, vehicle_position_id: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::eu_vehicle_positions::dsl::*;
let connection = establish_connection(settings);
match diesel::delete(eu_vehicle_positions.filter(entity_id.eq(vehicle_position_id))).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't delete vehicle_position: {}", e);
Err(e)
}
}
}
pub fn update_eu_vehicle_position(settings: &State<Settings>, vehicle_position_data: EventUnitVehiclePosition) -> Result<EventUnitVehiclePosition, diesel::result::Error> {
use crate::schema::eu_vehicle_positions::dsl::*;
let connection = establish_connection(settings);
match diesel::update(eu_vehicle_positions.filter(entity_id.eq(vehicle_position_data.entity_id))).set(vehicle_position_data).get_result(&connection) {
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't update vehicle position: {}", e);
Err(e)
}
}
}

View File

@ -101,6 +101,8 @@ pub struct EventUnitVehiclePosition{
#[derive(Queryable, Clone, Deserialize, Serialize, QueryableByName)]
pub struct EventUnitInstancePosition{
#[sql_type = "Uuid"]
pub(crate) position_instance_id: uuid::Uuid,
#[sql_type = "Uuid"]
pub(crate) instance_id: uuid::Uuid,
#[sql_type = "Uuid"]

View File

@ -1,30 +1,33 @@
extern crate argon2;
extern crate base64;
extern crate chrono;
extern crate config;
#[macro_use]
extern crate diesel;
extern crate iban;
extern crate log;
#[macro_use]
extern crate rocket;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate argon2;
extern crate chrono;
extern crate iban;
extern crate base64;
extern crate serde_json;
use std::{thread, time};
use std::io::Write;
use std::process::Command;
use std::sync::Arc;
use rocket::fs::FileServer;
use rocket_dyn_templates::handlebars::Handlebars;
use rocket_dyn_templates::Template;
use helper::settings::Settings;
use crate::helper::handlebars_in_list_helper::in_list_block_helper;
use crate::helper::mail_queue::queue::MailQueue;
use crate::helper::mail_templates::MailTemplates;
use crate::helper::session_cookies::model::SessionCookieStorage;
use helper::settings::Settings;
use std::io::Write;
use std::process::Command;
use std::sync::Arc;
use std::{thread, time};
use rocket_dyn_templates::Template;
use rocket::fs::FileServer;
use rocket_dyn_templates::handlebars::Handlebars;
pub mod database;
pub mod helper;
@ -196,13 +199,15 @@ fn rocket() -> _ {
modules::api::events::event_units::position::read::read_event_unit_position,
modules::api::events::event_units::position::delete::delete_event_unit_positions,
modules::api::events::event_units::position::update::update_event_unit_position,
modules::api::events::event_units::position::update::update_vehicle_position,
modules::api::events::event_units::templates::create::create_event_unit_template,
modules::api::events::event_units::templates::update::put_position_in_template,
modules::api::events::event_units::templates::create::put_position_in_template,
modules::api::events::event_units::templates::read::read_event_unit_templates,
modules::api::events::event_units::templates::delete::delete_templates,
modules::api::events::event_units::templates::delete::delete_positions_from_template,
modules::api::events::event_units::templates::read::read_event_unit_template_positions,
modules::api::events::event_units::templates::update::update_template,
modules::api::events::event_units::templates::update::update_position_for_template,
modules::event_management::edit_event::edit_event,
modules::api::events::instances::create::create_instance,
modules::api::events::instances::read::read_instances,

View File

@ -1,11 +1,14 @@
use rocket::State;
use crate::helper::settings::Settings;
use crate::helper::session_cookies::model::SessionCookie;
use diesel::result::Error;
use rocket::serde::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::parse_member_cookie;
use rocket::State;
use crate::database::controller::entities::remove_entity;
use crate::database::controller::events::templates::vehicle_positions::delete_eu_vehicle_position;
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::helper::translate_diesel_error::translate_diesel;
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
#[delete("/api/events/units/positions", format = "json", data = "<delete_list>")]
pub fn delete_event_unit_positions(
@ -32,11 +35,11 @@ pub fn delete_event_unit_positions(
Ok(())
}
#[delete("/api/events/units/vehicle_positions", format = "json", data = "<delete_list>")]
#[delete("/api/events/units/vehicle_positions/<vehicle_position_id>", format = "json")]
pub fn delete_event_unit_vehicle_positions(
settings: &State<Settings>,
cookie: SessionCookie,
delete_list: Json<Vec<uuid::Uuid>>,
vehicle_position_id: String,
) -> Result<(), Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
@ -45,14 +48,8 @@ pub fn delete_event_unit_vehicle_positions(
));
}
let delete_list = delete_list.into_inner();
for position in delete_list {
match remove_entity(settings, position){
Ok(_) => {}
Err(e) => return Err(translate_diesel(e)),
}
match delete_eu_vehicle_position(settings, parse_uuid_string(vehicle_position_id)?) {
Ok(()) => Ok(()),
Err(e) => return Err(translate_diesel(e))
}
Ok(())
}

View File

@ -1,21 +1,22 @@
use crate::helper::session_cookies::model::SessionCookie;
use rocket::State;
use crate::helper::settings::Settings;
use rocket::serde::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use rocket::State;
use crate::database::model::events::EventUnitPosition;
use crate::database::controller::events::{set_event_unit_position};
use crate::database::controller::events::set_event_unit_position;
use crate::database::controller::events::templates::vehicle_positions::update_eu_vehicle_position;
use crate::database::model::events::{EventUnitPosition, EventUnitVehiclePosition};
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::helper::translate_diesel_error::translate_diesel;
use crate::modules::api::events::event_units::position::create::CreatePositionData;
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
#[put("/api/events/units/positions/<entity_id>", format = "json", data = "<update_position_data>")]
pub fn update_event_unit_position(
settings: &State<Settings>,
cookie: SessionCookie,
update_position_data: Json<CreatePositionData>,
entity_id : String,
entity_id: String,
) -> Result<Json<EventUnitPosition>, Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
@ -41,9 +42,59 @@ pub fn update_event_unit_position(
requirements
};
match set_event_unit_position(settings, event_position){
match set_event_unit_position(settings, event_position) {
Ok(eup) => Ok(Json(eup)),
Err(e) => Err(translate_diesel(e))
Err(e) => Err(translate_diesel(e))
}
}
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct UpdateVehiclePositionData {
pub entity_id: String,
pub name: String,
pub description: Option<String>,
pub required_vehicle_category: String,
pub template_id: String,
}
/// Update vehicle_position
/// Parameters:
/// * vehicle_position_id: entity_id in eu_vehicle_positions
/// Method: PUT
/// Returns: EventUnitVehiclePosition or ApiError as JSON
#[put("/api/events/units/vehicle_positions/<vehicle_position_id>", format = "json", data = "<update_vehicle_position_data>")]
pub fn update_vehicle_position(
settings: &State<Settings>,
cookie: SessionCookie,
vehicle_position_id: String,
update_vehicle_position_data: Json<UpdateVehiclePositionData>,
) -> Result<Json<EventUnitVehiclePosition>, Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
return Err(Json(
ApiError::new(403, "Keine Berechtigung Fahrzeugposition zu verändern!".to_string()).to_wrapper(),
));
}
let data = update_vehicle_position_data.into_inner();
if data.entity_id != vehicle_position_id {
return Err(Json(
ApiError::new(400, "vehicle_position_id in URI doesn't match PUT data!".to_string()).to_wrapper(),
));
}
let pos = EventUnitVehiclePosition {
entity_id: parse_uuid_string(data.entity_id)?,
name: data.name,
description: data.description,
required_vehicle_category: parse_uuid_string(data.required_vehicle_category)?,
template_id: parse_uuid_string(data.template_id)?,
};
match update_eu_vehicle_position(settings, pos) {
Ok(pos) => Ok(Json(pos)),
Err(e) => Err(translate_diesel(e))
}
}

View File

@ -1,16 +1,17 @@
use rocket::State;
use crate::helper::settings::Settings;
use crate::helper::session_cookies::model::SessionCookie;
use rocket::serde::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::parse_member_cookie;
use rocket::State;
use crate::database::controller::entities::generate_entity;
use crate::database::controller::events::{add_event_unit_template, add_position_to_template, RawEventUnitTemplatePosition};
use crate::database::model::events::EventUnitTemplate;
use crate::database::controller::events::add_event_unit_template;
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::helper::translate_diesel_error::translate_diesel;
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct CreateTemplateData{
pub struct CreateTemplateData {
pub entity_id: Option<String>,
pub name: String,
pub description: Option<String>,
@ -41,9 +42,69 @@ pub fn create_event_unit_template(
description: create_template_data.description,
};
match add_event_unit_template(settings, event_position){
match add_event_unit_template(settings, event_position) {
Ok(eup) => Ok(Json(eup)),
Err(e) => Err(translate_diesel(e))
Err(e) => Err(translate_diesel(e))
}
}
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct PutPositionInTemplateData {
pub template_id: String,
pub position_entity_id: String,
pub tag: Option<String>,
pub num: String,
}
#[post("/api/events/units/templates/<template_id>/positions/<position_id>", format = "json", data = "<put_position_in_template_data>")]
pub fn put_position_in_template(
settings: &State<Settings>,
cookie: SessionCookie,
put_position_in_template_data: Json<PutPositionInTemplateData>,
template_id: String,
position_id: String,
) -> Result<(), Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
return Err(Json(
ApiError::new(403, "Keine Berechtigung Vorlagen zu verändern!".to_string()).to_wrapper(),
));
}
let data = put_position_in_template_data.into_inner();
if (data.template_id != template_id || data.position_entity_id != position_id) {
return Err(Json(
ApiError::new(400, "template_id or position_entity_id in URI doesn't match POST data!".to_string()).to_wrapper(),
));
}
let entity_id = match generate_entity(settings) {
Ok(entity) => entity,
Err(_) => {
return Err(Json(ApiError::new(500, "Konnte keine neue Entität anlegen.".to_string()).to_wrapper()))
},
};
let num = match data.num.parse() {
Ok(num) => num,
Err(e) => {
warn!("Wrong data type for num while putting position in template: {}", e);
return Err(Json(ApiError::new(400, "Wrong data type for num.".to_string()).to_wrapper()))
}
};
let res = RawEventUnitTemplatePosition {
position_entity_id: parse_uuid_string(position_id)?,
template_id: parse_uuid_string(template_id)?,
position_template_id: entity_id,
num,
tag: data.tag,
};
match add_position_to_template(settings, res) {
Ok(()) => Ok(()),
Err(e) => Err(translate_diesel(e))
}
}

View File

@ -1,12 +1,13 @@
use crate::helper::settings::Settings;
use rocket::State;
use crate::helper::session_cookies::model::SessionCookie;
use rocket::serde::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use rocket::State;
use crate::database::controller::entities::remove_entity;
use crate::database::controller::events::remove_position_from_template;
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::helper::translate_diesel_error::translate_diesel;
use crate::database::controller::events::remove_positions_from_template;
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
#[delete("/api/events/units/templates", format = "json", data = "<template_list>")]
pub fn delete_templates(
@ -33,12 +34,13 @@ pub fn delete_templates(
Ok(())
}
#[delete("/api/events/units/templates/<template_id>/positions", format = "json", data = "<position_list>")]
#[delete("/api/events/units/templates/<template_id>/positions/<position_id>/<position_template_id>", format = "json")]
pub fn delete_positions_from_template(
settings: &State<Settings>,
cookie: SessionCookie,
template_id: String,
position_list: Json<Vec<uuid::Uuid>>,
position_id: String,
position_template_id: String,
) -> Result<(), Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
@ -47,9 +49,7 @@ pub fn delete_positions_from_template(
));
}
let position_list = position_list.into_inner();
match remove_positions_from_template(settings, parse_uuid_string(template_id)?, position_list){
match remove_position_from_template(settings, parse_uuid_string(template_id)?, parse_uuid_string(position_id)?, parse_uuid_string(position_template_id)?) {
Ok(_) => {}
Err(e) => return Err(translate_diesel(e)),
}

View File

@ -1,15 +1,17 @@
use crate::database::model::events::{EventUnitTemplate, EventUnitPosition, EventUnitVehiclePosition};
use rocket::State;
use crate::helper::settings::Settings;
use crate::helper::session_cookies::model::SessionCookie;
use rocket::serde::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use rocket::State;
use crate::database::controller::events::{EventUnitTemplatePosition, get_event_unit_positions_for_template, get_event_unit_templates, get_event_unit_templates_count};
use crate::database::controller::events::templates::vehicle_positions::get_eu_vehicle_positions_for_template;
use crate::database::model::events::{EventUnitPosition, EventUnitTemplate, EventUnitVehiclePosition};
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::helper::translate_diesel_error::translate_diesel;
use crate::database::controller::events::{get_event_unit_templates, get_event_unit_templates_count, get_event_unit_positions_for_template, get_vehicle_positions_for_template};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct EventUnitTemplateList{
pub struct EventUnitTemplateList {
pub(crate) templates: Vec<EventUnitTemplate>,
pub(crate) total_template_count: i64,
}
@ -60,7 +62,7 @@ pub fn read_event_unit_template_positions(
settings: &State<Settings>,
cookie: SessionCookie,
template_id: String
) -> Result<Json<Vec<EventUnitPosition>>, Json<ApiErrorWrapper>> {
) -> Result<Json<Vec<EventUnitTemplatePosition>>, Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
return Err(Json(
@ -90,7 +92,7 @@ pub fn read_event_unit_template_vehicle_positions(
));
}
let positions = match get_vehicle_positions_for_template(settings, parse_uuid_string(template_id)?){
let positions = match get_eu_vehicle_positions_for_template(settings, parse_uuid_string(template_id)?) {
Ok(pos) => pos,
Err(e) => return Err(translate_diesel(e))
};

View File

@ -1,37 +1,15 @@
use crate::helper::settings::Settings;
use rocket::State;
use crate::helper::session_cookies::model::SessionCookie;
use diesel::sql_types::Integer;
use rocket::serde::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::database::controller::events::{add_position_to_template, update_eu_template};
use crate::helper::translate_diesel_error::translate_diesel;
use rocket::State;
use crate::database::controller::events::{add_position_to_template, EventUnitTemplatePosition, RawEventUnitTemplatePosition, update_eu_template, update_positions_templates};
use crate::database::model::events::EventUnitTemplate;
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::helper::translate_diesel_error::translate_diesel;
use crate::modules::api::events::event_units::templates::create::CreateTemplateData;
#[put("/api/events/units/templates/<template_id>/positions/<position_id>", format = "json")]
pub fn put_position_in_template(
settings: &State<Settings>,
cookie: SessionCookie,
template_id: String,
position_id: String,
) -> Result<(), Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
return Err(Json(
ApiError::new(403, "Keine Berechtigung Vorlagen zu verändern!".to_string()).to_wrapper(),
));
}
let template_id = parse_uuid_string(template_id)?;
let position_id = parse_uuid_string(position_id)?;
match add_position_to_template(settings, template_id, position_id){
Ok(_) => Ok(()),
Err(e) => Err(translate_diesel(e))
}
}
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid_string};
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
#[put("/api/events/units/templates/<template_id>", format = "json", data = "<template>")]
pub fn update_template(
@ -55,9 +33,69 @@ pub fn update_template(
description: template.description
};
match update_eu_template(settings, template){
match update_eu_template(settings, template) {
Ok(template) => Ok(Json(template)),
Err(e) => Err(translate_diesel(e))
Err(e) => Err(translate_diesel(e))
}
}
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct PositionTemplateData {
pub position_template_id: String,
pub template_id: String,
pub position_entity_id: String,
pub tag: Option<String>,
pub num: String,
}
/// Updates eu_positions_templates
/// Parameters:
/// * template_id: current template as uuid
/// * position_id: current position as uuid
/// * position_template_id: position_template to edit
/// * position_template_data: JSON data for update
#[put("/api/events/units/templates/<template_id>/positions/<position_id>/<position_template_id>", format = "json", data = "<position_template_data>")]
pub fn update_position_for_template(
settings: &State<Settings>,
cookie: SessionCookie,
position_template_data: Json<PositionTemplateData>,
template_id: String,
position_id: String,
position_template_id: String,
) -> Result<Json<EventUnitTemplatePosition>, Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::event_management::events::EDIT.to_string()) {
return Err(Json(
ApiError::new(403, "Keine Berechtigung Vorlagen zu verändern!".to_string()).to_wrapper(),
));
}
let data = position_template_data.into_inner();
if (data.template_id != template_id || data.position_entity_id != position_id || data.position_template_id != position_template_id) {
return Err(Json(
ApiError::new(400, "template_id or position_entity_id or position_template_id in URI doesn't match PUT data!".to_string()).to_wrapper(),
));
}
let num = match data.num.parse() {
Ok(num) => num,
Err(e) => {
warn!("Wrong data type for num while putting position in template: {}", e);
return Err(Json(ApiError::new(400, "Wrong data type for num.".to_string()).to_wrapper()))
}
};
let res = RawEventUnitTemplatePosition {
position_entity_id: parse_uuid_string(position_id)?,
template_id: parse_uuid_string(template_id)?,
position_template_id: parse_uuid_string(position_template_id)?,
num,
tag: data.tag,
};
match update_positions_templates(settings, res) {
Ok(res) => Ok(Json(res)),
Err(e) => Err(translate_diesel(e))
}
}

View File

@ -224,8 +224,6 @@ pub fn http_basic_auth(
let pwd = auth.password;
let username = auth.username;
warn!("user: {}, pwd: {}", username, pwd);
match get_user_by_username(username.clone(), &settings){
None => {
match login_attempts_usernames_exceeded(settings, username.clone()){

View File

@ -31,9 +31,11 @@ pub fn event_unit_templates(cookie: SessionCookie, _settings: &State<Settings>)
};
let footer = Footer {
scripts: vec![Script {
path: "/js/em_event_unit_templates.js".to_string(),
path: "/js/em_eu_templates.js".to_string(),
}, Script {
path: "/js/mini_searchbar.js".to_string(),
}, Script {
path: "/js/pagination.js".to_string(),
}],
};
let mut sidebar = Sidebar::new(member.clone());

View File

@ -10,9 +10,7 @@ pub fn get_context(alert: Option<Alert>) -> WelcomeModule {
path: "/css/errms.css".to_string(),
}],
};
let footer = Footer { scripts: vec![Script{
path: "/js/lib/snowstorm-min.js".to_string()
}] };
let footer = Footer { scripts: vec![] };
WelcomeModule {
header,

View File

@ -126,10 +126,11 @@ table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
eu_position_instances (instance_id, position_id) {
eu_position_instances (position_instance_id) {
instance_id -> Uuid,
position_id -> Uuid,
taken_by -> Nullable<Uuid>,
position_instance_id -> Uuid,
}
}
@ -149,9 +150,12 @@ table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
eu_positions_templates (position_entity_id, template_id) {
eu_positions_templates (position_template_id) {
position_entity_id -> Uuid,
template_id -> Uuid,
position_template_id -> Uuid,
num -> Int4,
tag -> Nullable<Text>,
}
}