FEA: event unit instances

This commit is contained in:
Keanu D?lle 2021-05-31 13:38:27 +02:00
parent fa078ce5da
commit 0e67bba258
18 changed files with 657 additions and 140 deletions

View File

@ -122,19 +122,19 @@ comment on table eu_positions_templates is 'Connects eu_positions/eu_vehicle_pos
create table eu_position_instances
(
instance_id uuid not null
constraint eu_position_instances_pk
primary key
constraint eu_position_instances_entities_entity_id_fk
references entities
on update cascade on delete cascade,
position_id uuid
position_id uuid not null
constraint eu_position_instances_entities_entity_id_fk_2
references entities
on update cascade on delete cascade,
taken_by uuid
constraint eu_position_instances_entities_entity_id_fk_3
references entities
on update cascade on delete cascade
on update cascade on delete cascade,
constraint eu_position_instances_pk
primary key (instance_id, position_id)
);
comment on table eu_position_instances is 'assigns member or vehicle to member or vehicle position';

View File

@ -1,28 +1,30 @@
<div class="row">
<div class="col-9">
<h5 >Einsatzeinheiten:</h5>
<div id="instances_container" class="row">
</div>
</div>
<div class="col-3 border">
<h5 class="border-bottom" style="padding-top: 5px;">Kräfte</h5>
<p class="font-weight-bold">Einheit einfügen:</p>
<div class="form-group row">
<label for="edit_event_cast_template_search-searchbar" class="col-sm-3 col-form-label">Vorlage: </label>
<div class="col-sm-9">
{{> search base="edit_event_cast_template_search" type="template"}}
<div class="col-3">
<div class="card ">
<div class="card-header">Kräfte</div>
<div class="card-body">
<p class="font-weight-bold">Einheit einfügen:</p>
<div class="form-group row">
<label for="edit_event_cast_template_search-searchbar" class="col-sm-3 col-form-label">Vorlage: </label>
<div class="col-sm-9">
{{> search base="edit_event_cast_template_search" type="template"}}
</div>
</div>
<div class="form-group row">
<label for="edit_event_cast_instance_name" class="col-sm-3 col-form-label">Name: </label>
<div class="col-sm-9">
<input type="text" class="form-control" id="edit_event_cast_instance_name">
</div>
</div>
<button class="btn btn-success edit_event_cast_add_template" style="float: right">Hinzufügen</button><br><br>
</div>
</div>
<div class="form-group row">
<label for="edit_event_cast_instance_name" class="col-sm-3 col-form-label">Name: </label>
<div class="col-sm-9">
<input type="text" class="form-control" id="edit_event_cast_instance_name">
</div>
</div>
<button class="btn btn-success edit_event_cast_add_template" style="float: right">Hinzufügen</button><br><br>
<p class="font-weight-bold">Personal eingesetzt:</p>
<p class="font-weight-bold">Personal hinzufügen:</p>
</div>
</div>

View File

@ -1,10 +1,36 @@
<div class="instance col-4" style="border: 1px solid black">
<p>Personal:</p>
<div class="form-group row">
<label class="col-3 col-form-label">KTW Fahrer:</label>
<div class="col-sm-9">
<select class="form-control" ></select>
<div class="instance col-4" style="padding: 2px;" data-instance-id="{{instance_id}}" data-template-id="{{template_id}}">
<div class="card">
<div class="card-header">
{{name}}<button class="iconbutton remove_instance_button" style="float: right;"><svg color="red" width="20" height="20" fill="currentColor">
<use xlink:href="/img/bootstrap-icons.svg#trash"></use>
</svg></button>
</div>
<div class="card-body">
<h5>Personal:</h5>
<div class="eu_cast_instance_personal">
{{#each positions}}
<div class="form-group row eu_cast_instance_personal_position" data-instance-id="{{../instance_id}}" data-position-id="{{position_id}}" data-member-name="{{member_name}}" data-member-id="{{taken_by}}">
<label class="col-4 col-form-label">{{name}}</label>
<div class="input-group mb-3 col-8">
{{> search base=this.base type="member"}}
</div>
</div>
{{/each}}
</div>
{{#if vehicle_positions}}
<h5>Fahrzeuge:</h5>
<div class="eu_cast_instance_vehicles">
{{#each vehicle_positions}}
<div class="form-group row eu_cast_instance_vehicle_position" data-instance-id="{{../instance_id}}" data-position-id="{{position_id}}" data-identifier="{{identifier}}" data-entity-id="{{taken_by}}">
<label class="col-4 col-form-label">{{name}}</label>
<div class="input-group mb-3 col-8">
{{> search base=this.base type="vehicle"}}
</div>
</div>
{{/each}}
</div>
{{/if}}
</div>
</div>
<span>Fahrzeuge:</span>
</div>

View File

@ -3,7 +3,7 @@ let limit = 10;
let offset = 0;
let page = 1;
$( document ).ready(function() {
$(document).ready(function () {
let searchParams = new URLSearchParams(window.location.search);
event_id = searchParams.get('id');
@ -11,27 +11,31 @@ $( document ).ready(function() {
//Do not execute code here which relies on templates. Use EventUnitTemplateModule.start function instead
});
EventEditModule = ( function() {
EventEditModule = (function () {
let templates = {};
let event = {};
let load_templates = function(){
$.get("/templates/em_edit_event_core_data.hbs", function(res) {
let load_templates = function () {
$.get("/templates/em_edit_event_core_data.hbs", function (res) {
templates.core_data_view = Handlebars.compile(res);
start();
});
$.get("/templates/search.hbs", function(res) {
$.get("/templates/search.hbs", function (res) {
templates.search = res;
start();
});
$.get("/templates/em_edit_event_cast.hbs", function(res) {
$.get("/templates/em_edit_event_cast.hbs", function (res) {
templates.cast_view = Handlebars.compile(res);
start();
});
$.get("/templates/em_edit_event_cast_instances.hbs", function (res) {
templates.cast_instance = Handlebars.compile(res);
start();
});
load_event();
};
let start = function(){
if(templates.core_data_view && templates.search && !jQuery.isEmptyObject(event)){
let start = function () {
if (templates.core_data_view && templates.search && templates.cast_view && templates.cast_instance && !jQuery.isEmptyObject(event)) {
Handlebars.registerPartial('search', templates.search);
$(".edit_event_core_data").append(templates.core_data_view(event));
var member_search = new MiniSearchbar("edit_event_search", null, event.member_responsible, event.member_responsible_name);
@ -52,10 +56,10 @@ EventEditModule = ( function() {
load_instances();
}
};
let load_event = function(){
let load_event = function () {
$.ajax({
type: "GET",
url: "/api/events/"+event_id,
url: "/api/events/" + event_id,
contentType: 'application/json',
timeout: 3000,
error: function () {
@ -63,31 +67,31 @@ EventEditModule = ( function() {
},
success: async function (data) {
if (is_ok(data)) {
if(data.member_responsible){
let member = await get_member(data.member_responsible);
data.member_responsible_name = member.firstname + " " + member.lastname;
if (data.member_responsible) {
let member = await get_member(data.member_responsible);
data.member_responsible_name = member.firstname + " " + member.lastname;
}
if(data.organiser_id){
if (data.organiser_id) {
let org = await get_organiser(data.organiser_id);
if(org.company){
if (org.company) {
data.organiser_name = org.company;
}else{
data.organiser_name = org.firstname+" "+org.lastname;
} else {
data.organiser_name = org.firstname + " " + org.lastname;
}
}
data.start = data.start.slice(0,-3);
data.end = data.end.slice(0,-3);
data.start = data.start.slice(0, -3);
data.end = data.end.slice(0, -3);
data.etypes = await load_event_types_async();
$(data.etypes).each(function(){
if(this.type_id === data.etype){
$(data.etypes).each(function () {
if (this.type_id === data.etype) {
this.selected = true;
}
});
data.groups = await load_groups_async();
$(data.groups).each(function(){
if(this.group_id === data.related_group){
this.selected = true;
}
$(data.groups).each(function () {
if (this.group_id === data.related_group) {
this.selected = true;
}
});
event = data;
@ -96,41 +100,41 @@ EventEditModule = ( function() {
}
});
};
let save_event = function(){
if($("#edit_event_core_data_form")[0].checkValidity()) {
let save_event = function () {
if ($("#edit_event_core_data_form")[0].checkValidity()) {
let event = {};
event.name = $("#name").val();
event.start = $("#start").val();
event.end = $("#end").val();
if($("#site").val().length > 0){
if ($("#site").val().length > 0) {
event.site = $("#site").val();
}
if($("#etype").val().length > 0){
if ($("#etype").val().length > 0) {
event.etype = $("#etype option:selected").val();
}
event.related_group = $("#related_group option:selected").val();
if($("#edit_event_search").data("entity-id")){
if ($("#edit_event_search").data("entity-id")) {
event.member_responsible = $("#edit_event_search").data("entity-id");
}
if($("#edit_event_organiser_search").data("entity-id")){
if ($("#edit_event_organiser_search").data("entity-id")) {
event.organiser_id = $("#edit_event_organiser_search").data("entity-id");
}
if($("#other").val().length > 0){
if ($("#other").val().length > 0) {
event.other = $("#other").val();
}
if($("#other_intern").val().length > 0){
if ($("#other_intern").val().length > 0) {
event.other_intern = $("#other_intern").val();
}
if($("#contact_on_site_name").val().length > 0){
if ($("#contact_on_site_name").val().length > 0) {
event.contact_on_site_name = $("#contact_on_site_name").val();
}
if($("#contact_on_site_phone").val().length > 0){
if ($("#contact_on_site_phone").val().length > 0) {
event.contact_on_site_phone = $("#contact_on_site_phone").val();
}
console.log(event);
$.ajax({
url: '/api/events/'+event_id,
url: '/api/events/' + event_id,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(event),
@ -145,57 +149,192 @@ EventEditModule = ( function() {
alert("Verbindung zum Server unterbrochen!");
}
});
}else{
} else {
$('<input type="submit">').hide().appendTo("#create_event_form").click().remove();
}
};
let add_template_instance = function(){
let template = $("#edit_event_cast_template_search").data("entity-id");
let instance_name = $("#edit_event_cast_instance_name").val();
let add_template_instance = function () {
let template = $("#edit_event_cast_template_search").data("entity-id");
let instance_name = $("#edit_event_cast_instance_name").val();
if(!template || !instance_name){
alert("Bitte Vorlage auswählen und Namen eingeben.");
return;
}
if (!template || !instance_name) {
alert("Bitte Vorlage auswählen und Namen eingeben.");
return;
}
let instance = {};
instance.template_id = template;
instance.name = instance_name;
instance.event_id = event_id;
let instance = {};
instance.template_id = template;
instance.name = instance_name;
instance.event_id = event_id;
$.ajax({
url: '/api/events/'+event_id+'/instances',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(instance),
success: function (data) {
if (is_ok(data)) {
$.ajax({
url: '/api/events/' + event_id + '/instances',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(instance),
success: function (data) {
if (is_ok(data)) {
location.reload();
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let load_instances = function () {
$.ajax({
url: '/api/events/' + event_id + '/instances',
type: 'GET',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
$(data).each(async function(){
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let load_instances = function(){
$.ajax({
url: '/api/events/'+event_id+'/instances',
type: 'GET',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
console.log(data);
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
}
return{
this.positions = await load_positions_for_instance(this.instance_id);
this.vehicle_positions = await load_vehicle_positions_for_instance(this.instance_id);
for(let i=0;i<this.positions.length;i++){
this.positions[i].base = "search_"+this.positions[i].instance_id+"_"+this.positions[i].position_id;
if(this.positions[i].taken_by){
let member = await get_member(this.positions[i].taken_by);
this.positions[i].member_name = member.firstname + " "+member.lastname;
}
}
for(let i=0;i<this.vehicle_positions.length;i++){
this.vehicle_positions[i].base = "search_"+this.vehicle_positions[i].instance_id+"_"+this.vehicle_positions[i].position_id;
if(this.vehicle_positions[i].taken_by){
let vehicle = await get_vehicle(this.vehicle_positions[i].taken_by);
this.vehicle_positions[i].identifier = vehicle.identifier;
}
}
$("#instances_container").append(templates.cast_instance(this));
$(".remove_instance_button").off("click").on("click", remove_instance);
$(".eu_cast_instance_personal_position").each(function(){
let pos = $(this).data("position-id");
let instance = $(this).data("instance-id");
let callback = function(caller){
let ms = this;
$("#"+ms.base+"-search").hide();
$("#"+ms.base).val($(caller).data("firstname")+" "+$(caller).data("lastname")).attr("data-entity-id", $(caller).data("entity-id")).data("entity-id", $(caller).data("entity-id"));
$("#"+ms.base+"_input_group").show();
add_entity_to_position(instance, pos, $(caller).data("entity-id"))
};
let delete_callback = function(){
remove_entity_from_position(instance, pos);
};
var member_search = new MiniSearchbar("search_"+$(this).data("instance-id")+"_"+$(this).data("position-id"), callback, $(this).data("member-id"), $(this).data("member-name"), delete_callback);
member_search.setup();
});
$(".eu_cast_instance_vehicle_position").each(function(){
let pos = $(this).data("position-id");
let instance = $(this).data("instance-id");
let callback = function(caller){
let ms = this;
$("#"+ms.base+"-search").hide();
$("#"+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();
add_entity_to_position(instance, pos, $(caller).data("entity-id"))
};
let delete_callback = function(){
remove_entity_from_position(instance, pos);
};
var vehicle_search = new MiniSearchbar("search_"+$(this).data("instance-id")+"_"+$(this).data("position-id"), callback, $(this).data("entity-id"), $(this).data("identifier"), delete_callback);
vehicle_search.setup();
});
});
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let add_entity_to_position = function(instance, position, entity){
$.ajax({
url: '/api/events/instances/'+instance+'/positions/'+position+'/entities/'+entity,
type: 'PUT',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let remove_entity_from_position = function(instance, position){
$.ajax({
url: '/api/events/instances/'+instance+'/positions/'+position+'/entities/',
type: 'DELETE',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
};
let load_positions_for_instance = async function(instance_id){
const res = await $.ajax({
url: '/api/events/instances/'+instance_id+'/positions',
type: 'GET',
contentType: 'application/json',
timeout: 3000,
error: function () {
alert("Verbindung zum Server unterbrochen!");
}
});
if (is_ok(res)) {
return res;
}
};
let load_vehicle_positions_for_instance = async function(instance_id){
const res = await $.ajax({
url: '/api/events/instances/'+instance_id+'/vehicle_positions',
type: 'GET',
contentType: 'application/json',
timeout: 3000,
error: function () {
alert("Verbindung zum Server unterbrochen!");
}
});
if (is_ok(res)) {
return res;
}
};
let remove_instance = function(){
let caller = this;
let instance = $(caller).closest(".instance");
let instance_id = instance.data("instance-id");
$.ajax({
url: '/api/events/instances/'+instance_id,
type: 'DELETE',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
instance.remove();
}
},
timeout: 3000,
error: function () {
alert("Es ist ein Fehler aufgetreten!");
}
});
}
return {
load_templates: load_templates,
start: start,
};

View File

@ -54,6 +54,22 @@ let get_member = async function (entity_id){
}
};
let get_vehicle = async function (entity_id){
const res = await $.ajax({
type: "GET",
url: "/api/resources/vehicles/" + entity_id,
contentType: 'application/json',
timeout: 3000,
error: function () {
alert("Verbindung zum Server unterbrochen!");
},
});
if (is_ok(res)) {
return res;
}
};
let get_organiser = async function(entity_id){
const res = await $.ajax({
type: "GET",

View File

@ -1,4 +1,4 @@
function MiniSearchbar(pbase, pcallback, value_id, value_name){
function MiniSearchbar(pbase, pcallback, value_id, value_name, delete_callback){
this.value_id = value_id;
this.value_name = value_name
this.base = pbase;
@ -7,6 +7,7 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name){
this.overlay = $("."+this.base+"-search-result-overlay");
this.overlay_list = $("."+this.base+"-search-result-overlay-list");
this.searchtype = this.searchbar.data("search-type");
this.delete_callback = delete_callback;
this.setup = function(){
var ms = this;
@ -31,17 +32,23 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name){
}
}else if(ms.searchtype === "template"){
ms.callback = function(caller){
console.log("set default callback for template");
$("#"+ms.base+"-search").hide();
$("#"+ms.base).val($(caller).data("name")).attr("data-entity-id", $(caller).data("entity-id")).data("entity-id", $(caller).data("entity-id"));
$("#"+ms.base+"_input_group").show();
}
}else if(ms.searchtype === "vehicle"){
ms.callback = function(caller){
$("#"+ms.base+"-search").hide();
$("#"+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{
console.log("unknown searchtype:"+ms.searchtype);
}
}
$("#"+ms.base+"_remove").off("click").on("click", function(){
ms.remove(ms);
ms.delete_callback(this);
});
$('body').click(function(evt){
if(evt.target.class === ms.base+"-search-result-overlay")
@ -49,16 +56,16 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name){
if($(evt.target).closest("."+ms.base+"-search-result-overlay").length)
return;
ms.overlay.hide();
ms.searchbar.on("click", function(){
ms.searchbar.off("click").on("click", function(){
ms.searchbar_onclick(ms);
});
ms.searchbar.on("keyup paste cut", function(){
ms.searchbar.off("keyup paste cut").on("keyup paste cut", function(){
ms.searchbar_typing(ms);
});
ms.searchbar.on("mouseenter focusin", function (){
ms.searchbar.off("mouseenter focusin").on("mouseenter focusin", function (){
ms.overlay.show();
});
ms.overlay.on("mouseleave", function (){
ms.overlay.off("mouseleave").on("mouseleave", function (){
ms.overlay.hide();
})
})
@ -166,7 +173,6 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name){
}
});
}else if(ms.searchtype === "template"){
console.log("template search")
$.ajax({
url: '/api/events/units/templates?q='+ms.searchbar.val(),
type: 'GET',
@ -190,6 +196,35 @@ function MiniSearchbar(pbase, pcallback, value_id, value_name){
});
}
},
timeout: 3000,
error: function () {
alert("Verbindung zum Server unterbrochen!");
}
});
}else if(ms.searchtype === "vehicle"){
$.ajax({
url: '/api/resources/vehicles?q='+ms.searchbar.val(),
type: 'GET',
contentType: 'application/json',
success: function (data) {
if (is_ok(data)) {
ms.overlay_list.html("");
$.each(data.vehicle_list, 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-identifier=\"" + value.identifier + "\"><li class='list-group-item'><span class=\"badge badge-secondary\">Hinzufügen:</span> "+value.identifier+"</li></span>")
});
//select search result on click
$("." + ms.base + "-search-result-overlay-result").off("click").on("click", function () {
ms.callback(this)
});
//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);
}
});
}
},
timeout: 3000,
error: function () {

View File

@ -1 +1 @@
v0.1-66-ge9981d8
v0.1-69-gfa078ce

View File

@ -1,11 +1,13 @@
use diesel::{RunQueryDsl, ExpressionMethods, JoinOnDsl, PgTextExpressionMethods, BoolExpressionMethods};
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};
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 crate::database::controller::members::TempQuery;
use diesel::pg::types::sql_types::Uuid;
use crate::schema::eu_vehicle_positions::dsl::eu_vehicle_positions;
pub fn add_event(settings: &State<Settings>, data: Event) -> Result<Event, diesel::result::Error>{
@ -254,6 +256,20 @@ pub fn get_event_unit_positions_for_template(settings: &State<Settings>, templat
}
}
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);
Err(e)
}
}
}
pub fn remove_positions_from_template(settings: &State<Settings>, template: uuid::Uuid, position_list: Vec<uuid::Uuid>) -> Result<(), diesel::result::Error>{
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
@ -293,6 +309,38 @@ pub fn add_instance(settings: &State<Settings>, instance: EventUnitInstance) ->
}
}
pub fn add_position_instances_for_instance(settings: &State<Settings>, instance_id2: uuid::Uuid, template_id2: uuid::Uuid) -> Result<(), diesel::result::Error>{
use crate::schema::eu_position_instances::dsl::*;
let positions = match get_event_unit_positions_for_template(settings, template_id2){
Ok(pos) => pos,
Err(e) => return Err(e)
};
let vehicle_positions = match get_event_unit_vehicle_positions_for_template(settings, template_id2){
Ok(pos) => pos,
Err(e) => return Err(e)
};
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 position in vehicle_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)
}
}
Ok(())
}
pub fn get_instances(settings: &State<Settings>, event: uuid::Uuid) -> Result<Vec<EventUnitInstance>, diesel::result::Error>{
use crate::schema::eu_instances::dsl::*;
@ -306,6 +354,46 @@ pub fn get_instances(settings: &State<Settings>, event: uuid::Uuid) -> Result<Ve
}
}
pub fn get_instance_positions(settings: &State<Settings>, instance_id2: uuid::Uuid) -> Result<Vec<EventUnitInstancePosition>, diesel::result::Error>{
use crate::schema::eu_position_instances::dsl::*;
use crate::schema::eu_positions::dsl::*;
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;",
)
.bind::<Uuid, _>(instance_id2)
.get_results(&connection);
match position_instances{
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get instance positions: {}", e);
Err(e)
}
}
}
pub fn get_instance_vehicle_positions(settings: &State<Settings>, instance_id2: uuid::Uuid) -> Result<Vec<EventUnitInstanceVehiclePosition>, diesel::result::Error>{
use crate::schema::eu_position_instances::dsl::*;
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
let position_instances: Result<Vec<EventUnitInstanceVehiclePosition>, diesel::result::Error> = sql_query(
"SELECT instance_id, position_id, taken_by, name, description, required_vehicle_category FROM eu_position_instances INNER JOIN eu_vehicle_positions ON position_id = entity_id WHERE instance_id = $1;",
)
.bind::<Uuid, _>(instance_id2)
.get_results(&connection);
match position_instances{
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get instance vehicle positions: {}", e);
Err(e)
}
}
}
pub fn add_vehicle_position(settings: &State<Settings>, position: EventUnitVehiclePosition) -> Result<EventUnitVehiclePosition, diesel::result::Error>{
use crate::schema::eu_vehicle_positions::dsl::*;
@ -330,4 +418,17 @@ pub fn get_vehicle_positions_for_template(settings: &State<Settings>, template_i
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::*;
let connection = establish_connection(settings);
match diesel::update(eu_position_instances).filter(instance_id.eq(instance_id2)).filter(position_id.eq(position_id2)).set(taken_by.eq(taken_by2)).execute(&connection){
Ok(count) => Ok(count),
Err(e) => {
error!("Couldn't update position instances: {}", e);
Err(e)
}
}
}

View File

@ -2,12 +2,7 @@ use crate::helper::settings::Settings;
use rocket::State;
use crate::database::model::vehicles::{VehicleCategory, Vehicle};
use crate::database::controller::connector::establish_connection;
use diesel::{RunQueryDsl, ExpressionMethods};
use diesel::query_dsl::methods::{OrderDsl,OffsetDsl};
use diesel::query_dsl::limit_dsl::LimitDsl;
use diesel::expression::dsl::count;
use diesel::{QueryDsl, RunQueryDsl, ExpressionMethods, PgTextExpressionMethods};
pub fn get_vehicle_categories(settings: &State<Settings>) -> Result<Vec<VehicleCategory>, diesel::result::Error> {
use crate::schema::vehicle_categories::dsl::*;
@ -22,12 +17,21 @@ pub fn get_vehicle_categories(settings: &State<Settings>) -> Result<Vec<VehicleC
}
}
pub fn get_vehicles(settings: &State<Settings>, limit: i64, offset: i64) -> Result<Vec<Vehicle>, diesel::result::Error>{
pub fn get_vehicles(settings: &State<Settings>, limit: i64, offset: i64, q: Option<String>) -> Result<Vec<Vehicle>, diesel::result::Error>{
use crate::schema::vehicles::dsl::*;
let connection = establish_connection(settings);
match vehicles.order(identifier.asc()).limit(limit).offset(offset).load(&connection){
let mut query = vehicles.order(identifier.asc()).limit(limit).offset(offset).into_boxed();
match q{
Some(q) => {
query = query.filter(identifier.ilike(format!("%{}%", q)))
},
None => {}
}
match query.load(&connection){
Ok(vehicle_list) => Ok(vehicle_list),
Err(e) => {
error!("Couldn't retrieve vehicles: {}", e);
@ -36,9 +40,24 @@ pub fn get_vehicles(settings: &State<Settings>, limit: i64, offset: i64) -> Resu
}
}
pub fn get_vehicle(settings: &State<Settings>, id: uuid::Uuid) -> Result<Vehicle, diesel::result::Error>{
use crate::schema::vehicles::dsl::*;
let connection = establish_connection(settings);
match vehicles.filter(entity_id.eq(id)).get_result(&connection){
Ok(vehicle) => Ok(vehicle),
Err(e) => {
error!("Couldn't retrieve vehicle: {}", e);
Err(e)
}
}
}
pub fn get_vehicle_count(settings: &State<Settings>) -> Result<i64, diesel::result::Error>{
use crate::schema::vehicles::dsl::*;
use crate::diesel::query_dsl::select_dsl::SelectDsl;
use diesel::dsl::count;
let connection = establish_connection(settings);

View File

@ -5,6 +5,7 @@ use crate::schema::eu_positions;
use crate::schema::eu_templates;
use crate::schema::eu_instances;
use crate::schema::eu_vehicle_positions;
use diesel::sql_types::{Uuid, Text, Nullable, Jsonb};
#[derive(Queryable, Clone, Deserialize, Serialize, AsChangeset, Insertable)]
#[table_name = "events"]
@ -79,4 +80,36 @@ pub struct EventUnitVehiclePosition{
pub(crate) description: Option<String>,
pub(crate) required_vehicle_category: uuid::Uuid,
pub(crate) template_id: uuid::Uuid,
}
#[derive(Queryable, Clone, Deserialize, Serialize, QueryableByName)]
pub struct EventUnitInstancePosition{
#[sql_type = "Uuid"]
pub(crate) instance_id: uuid::Uuid,
#[sql_type = "Uuid"]
pub(crate) position_id: uuid::Uuid,
#[sql_type = "Nullable<Uuid>"]
pub(crate) taken_by: Option<uuid::Uuid>,
#[sql_type = "Text"]
pub(crate) name: String,
#[sql_type = "Nullable<Text>"]
pub(crate) description: Option<String>,
#[sql_type = "Nullable<Jsonb>"]
pub(crate) requirements: Option<serde_json::Value>
}
#[derive(Queryable, Clone, Deserialize, Serialize, QueryableByName)]
pub struct EventUnitInstanceVehiclePosition{
#[sql_type = "Uuid"]
pub(crate) instance_id: uuid::Uuid,
#[sql_type = "Uuid"]
pub(crate) position_id: uuid::Uuid,
#[sql_type = "Nullable<Uuid>"]
pub(crate) taken_by: Option<uuid::Uuid>,
#[sql_type = "Text"]
pub(crate) name: String,
#[sql_type = "Nullable<Text>"]
pub(crate) description: Option<String>,
#[sql_type = "Uuid"]
pub(crate) required_vehicle_category: uuid::Uuid,
}

View File

@ -200,6 +200,12 @@ fn main() {
modules::api::events::event_units::position::create::create_event_unit_vehicle_position,
modules::api::events::event_units::templates::read::read_event_unit_template_vehicle_positions,
modules::api::events::event_units::position::delete::delete_event_unit_vehicle_positions,
modules::api::events::instances::read::read_positions_for_instance,
modules::api::events::instances::update::remove_entity_from_position,
modules::api::events::instances::update::put_entity_in_position,
modules::api::events::instances::read::read_vehicle_positions_for_instance,
modules::api::resources::vehicles::read::read_vehicle,
modules::api::events::instances::delete::delete_instance,
],
)
.mount("/css", StaticFiles::from("resources/css"))

View File

@ -6,8 +6,9 @@ use crate::database::model::events::EventUnitInstance;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid};
use crate::database::controller::entities::generate_entity;
use crate::database::controller::events::add_instance;
use crate::database::controller::events::{add_instance, add_position_instances_for_instance};
use crate::helper::translate_diesel_error::translate_diesel;
use diesel::result::Error;
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct CreateInstanceData{
@ -48,8 +49,13 @@ pub fn create_instance(
event_id: parse_uuid(event_id)?
};
match add_position_instances_for_instance(&settings, instance.instance_id, instance.template_id){
Ok(_) => {}
Err(e) => return Err(translate_diesel(e))
}
match add_instance(&settings, instance){
Ok(instance) => Ok(Json(instance)),
Err(e) => Err(translate_diesel(e))
Ok(instance) => return Ok(Json(instance)),
Err(e) => return Err(translate_diesel(e))
}
}

View File

@ -0,0 +1,27 @@
use rocket::State;
use crate::helper::settings::Settings;
use crate::helper::session_cookies::model::SessionCookie;
use rocket_contrib::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid};
use crate::database::controller::entities::remove_entity;
use crate::helper::translate_diesel_error::translate_diesel;
#[delete("/api/events/instances/<instance_id>", format = "json")]
pub fn delete_instance(
settings: State<Settings>,
cookie: SessionCookie,
instance_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 Einsätze zu bearbeiten!".to_string()).to_wrapper(),
));
}
match remove_entity(&settings, parse_uuid(instance_id)?){
Ok(_) => Ok(()),
Err(e) => return Err(translate_diesel(e))
}
}

View File

@ -1,3 +1,4 @@
pub mod create;
pub mod delete;
pub mod read;
pub mod read;
pub mod update;

View File

@ -1,11 +1,11 @@
use crate::helper::settings::Settings;
use rocket::State;
use crate::helper::session_cookies::model::SessionCookie;
use crate::database::model::events::EventUnitInstance;
use crate::database::model::events::{EventUnitInstance, EventUnitInstancePosition, EventUnitInstanceVehiclePosition};
use rocket_contrib::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid};
use crate::database::controller::events::get_instances;
use crate::database::controller::events::{get_instances, get_instance_positions, get_instance_vehicle_positions};
use crate::helper::translate_diesel_error::translate_diesel;
#[get("/api/events/<event_id>/instances", format = "json", rank = 1)]
@ -25,4 +25,42 @@ pub fn read_instances(
Ok(pos) => Ok(Json(pos)),
Err(e) => return Err(translate_diesel(e))
}
}
#[get("/api/events/instances/<instance_id>/positions", format = "json", rank = 1)]
pub fn read_positions_for_instance(
settings: State<Settings>,
cookie: SessionCookie,
instance_id: String,
) -> Result<Json<Vec<EventUnitInstancePosition>>, 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 Einsätze zu bearbeiten!".to_string()).to_wrapper(),
));
}
match get_instance_positions(&settings, parse_uuid(instance_id)?){
Ok(pos) => Ok(Json(pos)),
Err(e) => return Err(translate_diesel(e))
}
}
#[get("/api/events/instances/<instance_id>/vehicle_positions", format = "json", rank = 1)]
pub fn read_vehicle_positions_for_instance(
settings: State<Settings>,
cookie: SessionCookie,
instance_id: String,
) -> Result<Json<Vec<EventUnitInstanceVehiclePosition>>, 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 Einsätze zu bearbeiten!".to_string()).to_wrapper(),
));
}
match get_instance_vehicle_positions(&settings, parse_uuid(instance_id)?){
Ok(pos) => Ok(Json(pos)),
Err(e) => return Err(translate_diesel(e))
}
}

View File

@ -0,0 +1,49 @@
use crate::helper::settings::Settings;
use rocket::State;
use crate::helper::session_cookies::model::SessionCookie;
use rocket_contrib::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid};
use crate::database::controller::events::change_position_instances;
use crate::helper::translate_diesel_error::translate_diesel;
#[put("/api/events/instances/<instance_id>/positions/<position_id>/entities/<entity_id>", format = "json", rank = 1)]
pub fn put_entity_in_position(
settings: State<Settings>,
cookie: SessionCookie,
instance_id: String,
position_id: String,
entity_id: String,
) -> Result<Json<usize>, 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 Einsätze zu bearbeiten!".to_string()).to_wrapper(),
));
}
match change_position_instances(&settings, parse_uuid(instance_id)?, parse_uuid(position_id)?, Some(parse_uuid(entity_id)?)){
Ok(pos) => Ok(Json(pos)),
Err(e) => return Err(translate_diesel(e))
}
}
#[delete("/api/events/instances/<instance_id>/positions/<position_id>/entities", format = "json", rank = 1)]
pub fn remove_entity_from_position(
settings: State<Settings>,
cookie: SessionCookie,
instance_id: String,
position_id: String,
) -> Result<Json<usize>, 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 Einsätze zu bearbeiten!".to_string()).to_wrapper(),
));
}
match change_position_instances(&settings, parse_uuid(instance_id)?, parse_uuid(position_id)?, None){
Ok(pos) => Ok(Json(pos)),
Err(e) => return Err(translate_diesel(e))
}
}

View File

@ -4,8 +4,8 @@ use crate::helper::session_cookies::model::SessionCookie;
use rocket_contrib::json::Json;
use crate::modules::api::model::api_outcome::{ApiErrorWrapper, ApiError};
use crate::database::model::vehicles::{VehicleCategory, Vehicle};
use crate::modules::api::member_management::controller::parser::parse_member_cookie;
use crate::database::controller::vehicles::{get_vehicle_categories, get_vehicles, get_vehicle_count};
use crate::modules::api::member_management::controller::parser::{parse_member_cookie, parse_uuid};
use crate::database::controller::vehicles::{get_vehicle_categories, get_vehicles, get_vehicle_count, get_vehicle};
use crate::helper::translate_diesel_error::translate_diesel;
@ -27,12 +27,13 @@ pub struct VehicleList{
pub(crate) total_vehicle_count: i64,
}
#[get("/api/resources/vehicles?<entries>&<page>", format = "json")]
#[get("/api/resources/vehicles?<entries>&<page>&<q>", format = "json")]
pub fn read_vehicle_list(
settings: State<Settings>,
cookie: SessionCookie,
entries: Option<i64>,
page: Option<i64>,
q: Option<String>
) -> Result<Json<VehicleList>, Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
@ -69,7 +70,7 @@ pub fn read_vehicle_list(
total_vehicle_count: 0
};
match get_vehicles(&settings, entries, (page-1)*entries){
match get_vehicles(&settings, entries, (page-1)*entries, q){
Ok(vehicles) => res.vehicle_list = vehicles,
Err(e) => return Err(translate_diesel(e))
};
@ -80,4 +81,22 @@ pub fn read_vehicle_list(
};
Ok(Json(res))
}
#[get("/api/resources/vehicles/<entity_id>", format = "json")]
pub fn read_vehicle(
settings: State<Settings>,
cookie: SessionCookie,
entity_id: String,
) -> Result<Json<Vehicle>, Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
if !caller.has_permission(crate::permissions::modules::resource_management::vehicles::list::VIEW.to_string()){
return Err(Json(ApiError::new(403, "Keine Berechtigung Fahrzeugliste abzurufen!".to_string()).to_wrapper()))
}
match get_vehicle(&settings, parse_uuid(entity_id)?){
Ok(vehicle) => Ok(Json(vehicle)),
Err(e) => Err(translate_diesel(e))
}
}

View File

@ -126,9 +126,9 @@ table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
eu_position_instances (instance_id) {
eu_position_instances (instance_id, position_id) {
instance_id -> Uuid,
position_id -> Nullable<Uuid>,
position_id -> Uuid,
taken_by -> Nullable<Uuid>,
}
}