This commit is contained in:
Nordi98 2025-08-14 13:21:51 +02:00
parent 48a36209b5
commit 884f3df7cf
262 changed files with 223207 additions and 2 deletions

View file

@ -0,0 +1,14 @@
class FileSearch{
constructor(){
this.timeout = null
}
startTimer(value, element){
if(this.timeout != null){
clearTimeout(this.timeout);
}
this.timeout = setTimeout(function(){
SearchFiles(element)
},value);
}
}

View file

@ -0,0 +1,685 @@
class Form{
constructor(){
}
static TextBox(mandatory, translation_key, value){
let validateClass = "";
if(mandatory){
validateClass = " needs-validation"
}
return `
<div class="form-control">
<label class="label">
<span class="label-text">${getTranslation(translation_key)}</span>
</label>
<input id="input-${translation_key}" type="text" placeholder="" class="input input-sm input-bordered ${validateClass}" value="${value}" />
</div>
`;
}
static Hidden(translation_key, value){
return `
<div class="form-control" style="display:none">
<input id="input-${translation_key}" type="text" placeholder="" class="input input-sm input-bordered" value="${value}" />
</div>
`;
}
static NumberField(mandatory, translation_key, value, field_class = "", readonly = false, includeLabel = true){
let validateClass = "";
let disabled = "";
if(mandatory){
validateClass = " needs-validation"
}
if(field_class != ""){
field_class = " " + field_class;
}
if(readonly){
disabled = " disabled";
}
let disabledKeys = ["+", "." , "-", ","];
let step = "1";
let onkeydownkeyCodes = "";
for(var i=0; i < disabledKeys.length;i++){
onkeydownkeyCodes += (onkeydownkeyCodes == "" ? "" : " || " ) + "event.key==='"+disabledKeys[i]+"'";
}
if(includeLabel){
return `
<div class="form-control">
<label class="label">
<span class="label-text">${getTranslation(translation_key)}</span>
</label>
<input id="input-${translation_key}" type="number" onpaste="return false;" onkeydown="if(${onkeydownkeyCodes}){event.preventDefault();}" placeholder="" class="input input-sm input-bordered ${validateClass} ${field_class}" value="${value}" ${disabled}/>
</div>
`;
}
else{
return `
<div class="form-control">
<input id="input-${translation_key}" type="number" onpaste="return false;" onkeydown="if(${onkeydownkeyCodes}){event.preventDefault();}" placeholder="" class="input input-sm input-bordered ${validateClass} ${field_class}" value="${value}" ${disabled}/>
</div>
`;
}
}
static TextAreaGrow(){
Array.from(document.querySelectorAll(".ta-autogrow")).forEach(function(ta){
ta.style.height='auto';
ta.style.height = (ta.scrollHeight + 2) + 'px';
});
}
static TextArea(mandatory, translation_key, value, autogrow = false, rows = 3){
let validateClass = "";
let onInput = "";
let autoGrowClass = "";
if(mandatory){
validateClass = " needs-validation"
}
if(autogrow){
onInput = `onInput="this.style.height='auto'; this.style.height = (this.scrollHeight + 2) + 'px';"`;
autoGrowClass = " ta-autogrow";
}
return `
<div class="form-control">
<label class="label">
<span class="label-text">${getTranslation(translation_key)}</span>
</label>
<textarea rows="${rows}" id="input-${translation_key}" type="text" placeholder="" ${onInput} class="textarea textarea-sm textarea-bordered ${validateClass}${autoGrowClass}" >${value}</textarea>
</div>
`;
}
static DateField(mandatory, translation_key, value){
let validateClass = "";
if(mandatory){
validateClass = " needs-validation"
}
return `
<div class="form-control">
<label class="label">
<span class="label-text">${getTranslation(translation_key)}</span>
</label>
<input id="input-${translation_key}" type="date" placeholder=""class="input input-sm input-bordered ${validateClass}" value="${value}" />
</div>
`;
}
static Combobox(mandatory, translation_key, value, options){
let validateClass = "";
if(mandatory){
validateClass = " needs-validation";
}
let optionsHtml = ``;
for(let i=0; i<options.length; i++){
let selected = "";
if(options[i].id == value){
selected = " selected";
}
optionsHtml += `<option value="${options[i].id}" ${selected}>${options[i].name}</option>`;
}
return `
<div class="form-control">
<label class="label">
<span class="label-text">${getTranslation(translation_key)}</span>
</label>
<select id="input-${translation_key}" class="select select-sm select-bordered ${validateClass}" value="${value}">
${optionsHtml}
</select>
</div>
`;
}
static refillFilesDropDown(element, data){
data = data.data
let filesOptions = [
{"id":-1, "name":getTranslation("unknown")}
,{"id":-2, "name":getTranslation("new_file"), "show_extra_field":true}
];
if(sync.isActive("files")){
filesOptions = [
{"id":-1, "name":getTranslation("unknown")}
];
}
data = [...filesOptions, ...data];
let parentDiv = element.parentElement;
let buttonLabel = "...";
let mandatory = element.getAttribute("data-mandatory") == "true";
let translation_key = element.getAttribute("data-translationkey");
let li = parentDiv.getElementsByTagName("li");
while (li[0]){
parentDiv.removeChild(li[0])
}
for(let i=0; i<data.length; i++){
let selected = "";
if(data[i].id == -1){
buttonLabel = data[i].name;
selected = " active"
}
let el = document.createElement("li");
el.setAttribute("data-validate", mandatory);
el.setAttribute("parentId", `input-${translation_key}`);
el.setAttribute("value", data[i].id);
el.setAttribute("show-childtext", data[i].show_extra_field ?? "false");
el.innerHTML = `<a class="${selected}">${data[i].name}</a>`;
el.onclick = function(){
if(!this.classList.contains("active")){
Array.from(this.parentElement.querySelectorAll(".active")).forEach(function(itm){
itm.classList.remove("active");
});
Array.from(this.getElementsByTagName("a")).forEach(function(itm){
itm.classList.add("active");
});
document.getElementById(this.getAttribute("parentId") + "-new-name").value = "";
document.getElementById(this.getAttribute("parentId") + "-button").innerText = this.innerText;
document.getElementById(this.getAttribute("parentId") + "-dropdown").blur();
document.getElementById(this.getAttribute("parentId")).value = this.getAttribute("value");
if(this.getAttribute("show-childtext") == "true"){
document.getElementById(this.getAttribute("parentId") + "-new-name").style.display = "";
if(this.getAttribute("data-validate") == "true"){
document.getElementById(this.getAttribute("parentId") + "-new-name").classList.add("needs-validation");
}
}
else{
document.getElementById(this.getAttribute("parentId") + "-new-name").style.display = "none";
document.getElementById(this.getAttribute("parentId") + "-new-name").classList.remove("needs-validation");
}
}
Form.validate();
}
parentDiv.appendChild(el)
}
}
static initSearchComboboxes(){
Array.from(document.getElementById("currentpage-content").querySelectorAll(".filterablecombobox-search")).forEach(function(item){
item.onkeyup = function(){
globalFileSearcher.startTimer(500, this)
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll(".filterablecombobox")).forEach(function(item){
//get children
let childs = item.getElementsByTagName("li");
for(let i=0; i<childs.length; i++){
childs[i].onclick = function(){
if(!this.classList.contains("active")){
Array.from(this.parentElement.querySelectorAll(".active")).forEach(function(itm){
itm.classList.remove("active");
});
Array.from(this.getElementsByTagName("a")).forEach(function(itm){
itm.classList.add("active");
});
document.getElementById(this.getAttribute("parentId") + "-new-name").value = "";
document.getElementById(this.getAttribute("parentId") + "-button").innerText = this.innerText;
document.getElementById(this.getAttribute("parentId") + "-dropdown").blur();
document.getElementById(this.getAttribute("parentId")).value = this.getAttribute("value");
if(this.getAttribute("show-childtext") == "true"){
document.getElementById(this.getAttribute("parentId") + "-new-name").style.display = "";
if(this.getAttribute("data-validate") == "true"){
document.getElementById(this.getAttribute("parentId") + "-new-name").classList.add("needs-validation");
}
}
else{
document.getElementById(this.getAttribute("parentId") + "-new-name").style.display = "none";
document.getElementById(this.getAttribute("parentId") + "-new-name").classList.remove("needs-validation");
}
}
Form.validate();
}
}
});
}
static SearchCombobox(mandatory, translation_key, value, options, database_id){
let validateClass = "";
if(mandatory){
validateClass = " needs-validation";
}
let optionsHtml = ``;
let buttonLabel = "..."
let activeFound = false;
for(let i=0; i<options.length; i++){
let selected = "";
if(options[i].id == value){
buttonLabel = options[i].name;
selected = " active"
activeFound = true;
}
optionsHtml += `<li data-validate="${mandatory}" parentId="input-${translation_key}" value="${options[i].id}" show-childtext="${options[i].show_extra_field ?? "false"}"><a class="${selected}">${options[i].name}</a></li>`;
}
return `
<div class="form-control">
<label class="label">
<span class="label-text">${getTranslation(translation_key)}</span>
</label>
<div class="dropdown" >
<button tabindex="0" class="select select-sm select-bordered w-full filterabledropdownbutton" id="input-${translation_key}-button">${buttonLabel}</button>
<ul tabindex="0" id="input-${translation_key}-dropdown" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52 filterablecombobox">
<input type="text" class="input input-sm input-bordered filterablecombobox-search" data-parentid = "${database_id}" data-mandatory="${mandatory}" data-translationkey="${translation_key}" placeholder="Search..">
${optionsHtml}
</ul>
</div>
<input type="text" style="display:none" class="input input-sm input-bordered" id="input-${translation_key}-new-name">
<input type="text" style="display:none" class="input input-sm input-bordered input-searchableDropDown ${validateClass}" id="input-${translation_key}" value="${value}" >
</div>
`;
}
static Divier(text = ""){
return `
<div class="divider">${text}</div>
`;
}
static validate(){
if(document.getElementById("input-save-button")){
let valid = true;
Array.from(document.getElementById("currentpage-content").querySelectorAll(".needs-validation")).forEach(function(el){
if(el.value.trim() === ""){
valid = false;
if(!el.classList.contains("text-pink-600")){
el.classList.add("text-pink-600");
el.classList.add("border-pink-500");
}
}
else{
if(el.classList.contains("text-pink-600")){
el.classList.remove("text-pink-600");
el.classList.remove("border-pink-500");
}
}
});
document.getElementById("input-save-button").disabled = !valid;
}
}
static initValidation(){
let ignoreValidationClass = "ignore-validation";
Array.from(document.getElementById("currentpage-content").querySelectorAll("input")).forEach(function(el){
if(!el.classList.contains("filterablecombobox-search")){
el.onkeyup = function(){
Form.validate();
}
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("input")).forEach(function(el){
if(!el.classList.contains(ignoreValidationClass)){
el.onchange = function(){
Form.validate();
}
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("textarea")).forEach(function(el){
if(!el.classList.contains(ignoreValidationClass)){
el.onkeyup = function(){
Form.validate();
}
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("select")).forEach(function(el){
if(!el.classList.contains(ignoreValidationClass)){
el.onchange = function(){
Form.validate();
}
}
});
}
static getFormData(){
let retval = {};
Array.from(document.getElementById("currentpage-content").querySelectorAll("input")).forEach(function(el){
if(!el.classList.contains("filterablecombobox-search")){
let key = el.id.replace("input-","");
if(el.type != "checkbox"){
retval[key] = el.value;
}
else{
retval[key] = el.checked ? 1 : 0;
}
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("textarea")).forEach(function(el){
let key = el.id.replace("input-","");
retval[key] = el.value;
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("onchange")).forEach(function(el){
let key = el.id.replace("input-","");
retval[key] = el.value;
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("select")).forEach(function(el){
let key = el.id.replace("input-","");
retval[key] = el.value;
});
return retval;
}
static disableAll(){
Array.from(document.getElementById("currentpage-content").querySelectorAll("input")).forEach(function(el){
if(!el.classList.contains("ignore-readonly")){
el.readOnly = true;
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("textarea")).forEach(function(el){
if(!el.classList.contains("ignore-readonly")){
el.readOnly = true;
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll("select")).forEach(function(el){
if(!el.classList.contains("ignore-readonly")){
el.disabled = true;
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll(".filterabledropdownbutton")).forEach(function(el){
if(!el.classList.contains("ignore-readonly")){
el.disabled = true;
el.readOnly = true;
}
});
}
static cancelButton(source, destination, destination_id){
return `<button id="input-cancel-button" data-destination="${destination}" data-destination-id="${destination_id}" class="btn btn-error btn-sm">${getTranslation("cancel")}</button>`;
}
static saveButton(source, destination, uid, destination_id){
return `<button id="input-save-button" class="btn btn-primary btn-sm" data-destination="${destination}" data-destination-id="${destination_id}" data-uid="${uid}" data-source="${source}" disabled>${getTranslation("save")}</button>`;
}
static initSaveButtons(){
document.getElementById("input-cancel-button").onclick = function(){
loadData(
this.getAttribute("data-destination"),
this.getAttribute("data-destination-id"),
true
)
}
document.getElementById("input-save-button").onclick = function(){
saveData(
this.getAttribute("data-source"),
this.getAttribute("data-destination"),
this.getAttribute("data-uid"),
this.getAttribute("data-destination-id")
)
}
}
static initViewModeTopButtons(){
if(document.getElementById("input-back-button")){
document.getElementById("input-back-button").onclick=function(){
loadPage(this.getAttribute("data-destination"), this.getAttribute("data-destinationId"), "true");
}
}
if(document.getElementById("input-edit-button")){
document.getElementById("input-edit-button").onclick=function(){
loadPage(this.getAttribute("data-destination"), this.getAttribute("data-destinationId"));
}
}
}
static BackEditBtn(backDestination, editDest, editId, allowEditButton, backDestinationId = -1 ){
let editBtn = ``;
if(allowEditButton){
editBtn = `<button id="input-edit-button" data-destination="${editDest}" data-destinationId="${editId}" class="btn btn-sm btn-warning">${getTranslation("edit")}</button>`;
}
return `
<div class="text-xl font-semibold inline-block mb-6">
<button id="input-back-button" data-destination="${backDestination}" data-destinationId="${backDestinationId}" class="btn btn-sm btn-error"><i class="fa-solid fa-arrow-left"></i></button>
${editBtn}
</div>
`;
}
static getViewButtonIcon(recordid, destination){
return `
<button class="btn btn-sm btn-accent table-viewbutton" data-id="${recordid}" data-destination="${destination}">
<i class="fa-solid fa-circle-info"></i>
</button>
`;
}
static getEditButtonIcon(recordid, destination, allowButton=true){
if(!allowButton){
return "";
}
return `
<button class="btn btn-sm btn-warning table-editbutton" data-id="${recordid}" data-destination="${destination}">
<i class="fa-solid fa-pen-to-square"></i>
</button>
`;
}
static getDeleteButtonIcon(recordid, delete_destination , allowButton=true){
if(!allowButton){
return ``;
}
return `
<button class="btn btn-sm btn-error table-deletebutton" data-deleteDestination="${delete_destination}" data-id="${recordid}">
<i class="fa-solid fa-trash-can"></i>
</button>
`;
}
static overviewHeadline(destination, inclSearch = true, allowAddNew = true){
let search = "";
if(inclSearch){
let addBtn = "";
if(allowAddNew){
addBtn = `<button class="btn px-6 btn-sm normal-case btn-primary table-addbutton mr-1" data-destination="${destination}"><i class="fa-solid fa-circle-plus"></i></button>`;
}
return `
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="input-group">
${addBtn}
<input id="global-searchbar" type="text" placeholder="${getTranslation("search")}" class="input input-sm input-bordered w-72 mr-1" value="${document.body.getAttribute("data-quicksearch") ?? ""}" />
<button id="global-searchbar-start" class="btn btn-sm btn-square">
<i class="fa-solid fa-magnifying-glass"></i>
</button>
</div>
</div>
`;
}
else{
if(allowAddNew){
return `
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="text-left">
<button class="btn px-6 btn-sm normal-case btn-primary table-addbutton" data-destination="${destination}"><i class="fa-solid fa-circle-plus"></i></button>
</div>
</div>
`;
}
else{
return ``;
}
}
}
static getPageChanger(curPage, maxPage){
curPage = curPage + 1;
let nextDisabled = "";
let prevDisabled = "";
if(curPage == 1){
prevDisabled = " disabled";
}
if(curPage >= maxPage){
nextDisabled = " disabled";
}
document.body.setAttribute("data-cur-pageNum", curPage);
return `
<div class="btn-group">
<button id="global-previous-page" class="btn btn-primary btn-sm" ${prevDisabled}>«</button>
<button class="btn btn-ghost btn-sm" data-currentpage="${curPage}" id="global-page-current">${curPage}</button>
<button id="global-next-page" class="btn btn-primary btn-sm" ${nextDisabled}>»</button>
</div>
`;
}
static initPageChange(){
if(document.getElementById("global-previous-page")){
document.getElementById("global-previous-page").onclick=function(){
let curpage = document.body.getAttribute("data-cur-pageNum");
curpage = 1*curpage;
let destPage = curpage-1;
document.body.setAttribute("data-cur-pageNum", destPage);
reload();
}
}
if(document.getElementById("global-next-page")){
document.getElementById("global-next-page").onclick=function(){
let curpage = document.body.getAttribute("data-cur-pageNum");
curpage = 1*curpage;
let destPage = curpage+1;
document.body.setAttribute("data-cur-pageNum", destPage);
reload();
}
}
}
static openInfoModal(){
document.getElementById("delete-modal-title").innerHTML = getTranslation("info");
document.getElementById("delete-modal-message").innerHTML = getTranslation("no_valid_data_found");
document.getElementById("delete-modal-cancel").innerHTML = getTranslation("okay");
document.getElementById("delete-modal-delete").style.display="none";
document.getElementById("delete-modal").checked = true;
}
static openDeleteModal(id, source){
document.getElementById("delete-modal-title").innerHTML = getTranslation("delete");
document.getElementById("delete-modal-message").innerHTML = getTranslation("delete_message");
document.getElementById("delete-modal-cancel").innerHTML = getTranslation("cancel");
document.getElementById("delete-modal-delete").innerHTML = getTranslation("delete");
document.getElementById("delete-modal").setAttribute("data-id", id);
document.getElementById("delete-modal").setAttribute("data-delete-destination", source);
document.getElementById("delete-modal-delete").style.display="block";
document.getElementById("delete-modal").checked = true;
}
static initTableButtons(){
Array.from(document.getElementById("currentpage-content").querySelectorAll(".table-deletebutton")).forEach(function(el){
el.onclick = function(){
Form.openDeleteModal(this.getAttribute("data-id"), this.getAttribute("data-deleteDestination"));
}
});
if(document.getElementById("global-searchbar")){
document.getElementById("global-searchbar").focus();
document.getElementById("global-searchbar").setSelectionRange(document.getElementById("global-searchbar").value.length, document.getElementById("global-searchbar").value.length);
document.getElementById("global-searchbar").onkeyup = function(e){
if(e.key.toLowerCase() == "enter"){
resetPageNum();
reload();
}
}
}
if(document.getElementById("global-searchbar-start")){
document.getElementById("global-searchbar-start").onclick=function(){
resetPageNum();
reload();
}
}
Array.from(document.getElementById("currentpage-content").querySelectorAll(".table-addbutton")).forEach(function(el){
el.onclick = function(){
loadPage(this.getAttribute("data-destination"), -1);
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll(".table-editbutton")).forEach(function(el){
el.onclick = function(){
loadPage(this.getAttribute("data-destination"), this.getAttribute("data-id"));
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll(".table-viewbutton")).forEach(function(el){
el.onclick = function(){
loadPage(this.getAttribute("data-destination"), this.getAttribute("data-id"));
}
});
}
}

View file

@ -0,0 +1,78 @@
class NavMenu{
constructor(navigation, cursystem){
this.navid = "main_navigation";
let navEl = document.getElementById(this.navid);
Array.from(navEl.getElementsByTagName("li")).forEach(function(itm){
if(!itm.classList.contains("noremoveonrebuild")){
itm.remove();
}
});
Array.from(navEl.querySelectorAll(".divider")).forEach(function(itm){
itm.remove();
});
if(!navigation[cursystem]){
cursystem = "default";
}
if(navigation[cursystem]){
navigation = navigation[cursystem]
Object.keys(navigation).forEach(key=>{
if(key !== "none"){
navEl.innerHTML+=`<div class="divider no-translation nav-checkfor-nextelements mt-1 mb-1" data-tkey="${key}">{{${key}}}</div>`
}
Object.keys(navigation[key]).forEach(subKey=>{
let skeyname = navigation[key][subKey].key;
let destination = navigation[key][subKey].destination;
let forceReload = navigation[key][subKey].forceReload;
navEl.innerHTML+=`
<li id="menuItem-li-${skeyname}" class="nav-checkrights divier-${key}" data-rightkey="${navigation[key][subKey].rightkey ?? ""}">
<a id="menuitem-${skeyname}" class="font-normal no-translation is-navigation-link" data-iconclasses="${navigation[key][subKey].img}" data-tkey="${destination}" data-destination="${destination}", data-forceReload="${forceReload}">
<i class="${navigation[key][subKey].img}"></i>
{{${skeyname}}}
</a>
</li>
`;
});
});
}
Array.from(document.getElementById(this.navid).querySelectorAll(".is-navigation-link")).forEach(function(item){
item.onclick=function(){
handleMenuItemClick(this);
}
});
Array.from(document.getElementById(this.navid).querySelectorAll(".no-translation")).forEach(function(item){
let icon = "";
if(item.getAttribute("data-iconclasses") !== null){
icon = `<i class="${item.getAttribute("data-iconclasses")}"></i> `;
}
item.innerHTML = icon + Translations[locale][item.getAttribute("data-tkey")];
item.classList.remove("no-translation");
});
}
setItemActive(item){
Array.from(document.getElementById(this.navid).querySelectorAll(".bordered")).forEach(function(currentitem){
currentitem.classList.remove("bordered");
});
item.parentElement.classList.add("bordered");
setCurrentPageHeadLine(item.innerText);
}
}

View file

@ -0,0 +1,90 @@
class RadioHud{
constructor(){
this.DefaultMargin = 1.5;
}
SetLocation(value){
this.location = value;
if(value.vertical == "left"){
document.getElementById("radiostates").style.left = 0;
}
else if(value.vertical == "middle"){
document.getElementById("radiostates").style.right = 0;
document.getElementById("radiostates").style.left = 0;
document.getElementById("radiostates").style.marginLeft = "auto";
document.getElementById("radiostates").style.marginRight = "auto";
}
else{
document.getElementById("radiostates").style.right = 0;
}
if(value.horizontal == "top"){
document.getElementById("radiostates").style.top = 0;
}
else if(value.horizontal == "middle"){
document.getElementById("radiostates").style.top = 0;
document.getElementById("radiostates").style.bottom = 0;
document.getElementById("radiostates").style.marginTop = "auto";
document.getElementById("radiostates").style.marginBottom = "auto";
}
else{
document.getElementById("radiostates").style.bottom = 0;
}
}
SetExtraMargins(value){
if(this.location.vertical != "middle"){
document.getElementById("radiostates").style.marginLeft = value.left + this.DefaultMargin + "%";
document.getElementById("radiostates").style.marginRight = value.right + this.DefaultMargin + "%";
}
if(this.location.horizontal != "middle"){
document.getElementById("radiostates").style.marginTop = value.top + this.DefaultMargin + "%";
document.getElementById("radiostates").style.marginBottom = value.bottom + this.DefaultMargin + "%";
}
}
DrawInfo(radioDetails){
document.getElementById("radiostates_info").innerHTML = `
<table class="text-white">
<tr>
<td>
<i class="fa-solid fa-car-on pr-1"></i>
</td>
<td>
${radioDetails.vehicle ?? ""}
</td>
</tr>
<tr>
<td>
<i class="fa-solid fa-tower-broadcast pr-1"></i>
</td>
<td>
${radioDetails.radio ?? radioDetails.radio_default}
</td>
</tr>
</table>
`;
}
DrawButtons(radiostates, current_id, default_state){
let buttons = ``;
if(current_id != -1){
buttons += `<button onclick="SetRadioStateShortcut(-1)" class="btn btn-block btn-sm btn-primary my-1">${default_state}</button>`;
}
if(radiostates.length > 0){
radiostates.forEach(function(element){
if(current_id != element.id){
let bgcolor = element.color;
let FgColor = System.GetFgColorByBgColor(bgcolor);
buttons += `<button onclick="SetRadioStateShortcut(${element.id})" class="btn btn-block btn-sm my-1" style="background-color:${bgcolor}; color:${FgColor}">${element.short_name}</button>`;
}
});
}
document.getElementById("radiostates_actions").innerHTML = buttons;
}
}

View file

@ -0,0 +1,20 @@
class Rights{
constructor(rights){
this.fullright = "*"
this.rights = rights;
}
has(right_key){
let retval = false;
if(this.rights[right_key] !== undefined){
retval = this.rights[right_key];
}
if(!retval && this.rights["*"] !== undefined){
retval = this.rights["*"]
}
return retval;
}
}

View file

@ -0,0 +1,22 @@
class Sync{
constructor(syncData){
this.sync = {}
this.sync.licenses = syncData.LicensesSync
if(syncData.MainSync.active){
this.sync.files = syncData.MainSync.types.Users
this.sync.files_licenses = syncData.MainSync.types.Users && syncData.MainSync.types.UserLicenses
this.sync.regvehicle = syncData.MainSync.types.Vehicles
}
}
isActive(key){
let retval = false;
if(this.sync[key] !== undefined){
retval = this.sync[key];
}
return retval;
}
}

View file

@ -0,0 +1,28 @@
const navigation = {
"mechanic" : {
"none":[
{key:"dashboard", img:"fa-solid fa-chart-line","destination":"dashboard.dataload", "forceReload":true, "rightkey" :null },
{key:"notes", img:"fa-solid fa-circle-info","destination":"notes.dataload", "forceReload":true, "rightkey" :null }
],
"customers":[
{key:"customers", img:"fa-regular fa-file", "destination":"files.overview", "forceReload":true, "rightkey" :"files.view"},
{key:"regvehicle", img:"fa-solid fa-car","destination":"regvehicle.overview", "forceReload":true, "rightkey" :"regvehicles.view"},
{key:"regvehicle_noomot", img:"fa-solid fa-car","destination":"regvehicle_nomot.overview", "forceReload":true, "rightkey" :"regvehicles.view"},
],
"employees":[
{key:"employees", img:"fa-solid fa-people-group","destination":"employees.overview", "forceReload":true, "rightkey" :"employees.view"},
{key:"trainings", img:"fa-solid fa-graduation-cap","destination":"trainings.overview", "forceReload":true, "rightkey" :"trainings.view"},
{key:"missionreport", img:"fa-solid fa-file-lines","destination":"missionreport.overview", "forceReload":true, "rightkey" :"missionreport.view"},
],
"radiotraffic":[
{key:"radiostate", img:"fa-solid fa-tower-broadcast","destination":"radiostate.overview", "forceReload":true, "rightkey" :null},
{key:"emergencyvehicle", img:"fa-solid fa-car-on","destination":"emergencyvehicle.overview", "forceReload":true, "rightkey" :null},
{key:"controlcentre", "img":"fa-solid fa-building-flag", "destination":"controlcentre.dataload", "forceReload":true, "rightkey" :"controlcentre.view"},
],
"system":[
{key:"rankmanagement", img:"fa-solid fa-user-group","destination":"rankmanagement.dataload", "forceReload":true, "rightkey" :"isboss"},
{key:"pricelistgroups", img:"fa-solid fa-dollar-sign","destination":"pricelistgroups.dataload", "forceReload":true, "rightkey" :"pricelists.view"},
{key:"tuningoptions", img:"fa-regular fa-newspaper","destination":"tuningoptions.overview", "forceReload":true, "rightkey" :"parts_acceptance.view"},
]
}
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,79 @@
class ControlCentre{
constructor(){
this.name = "controlcentre";
}
static isCustom(){
return true;
}
static allowTake(){
return userrights.has("controlcentre.take");
}
static CreateCustom(data){
let buttons = ``;
if(this.allowTake()){
if(data.data.control_centre.is_taken){
buttons = `<button onclick="takeControlCentre(true)" class="btn btn-sm btn-error">${getTranslation("current_control_centre_reset")}</button>`
buttons += `<button onclick="takeControlCentre(false)" class="btn btn-sm btn-primary">${getTranslation("current_control_centre_take")}</button>`
}
else{
buttons = `<button onclick="takeControlCentre(false)" class="btn btn-sm btn-primary">${getTranslation("current_control_centre_take")}</button>`
}
}
document.getElementById("currentpage-content").innerHTML = `
<div class="card w-full bg-info text-info-content">
<div class="card-body">
<h2 class="card-title uppercase font-bold">${getTranslation("current_control_centre")}</h2>
<p><strong>${data.data.control_centre.is_taken ? System.buildEmployeeName(data.data.control_centre.name) : getTranslation("no_control_centre") }</strong></p>
<p></p>
<div class="card-actions justify-start">
${buttons}
</div>
</div>
</div>
`;
document.getElementById("currentpage-content").innerHTML += `
<div class="collapse collapse-open border border-base-300 bg-base-100 rounded-box mt-4">
<div class="collapse-title text-xl font-medium">
${getTranslation("emergencyvehicle.overview")}
</div>
<div class="collapse-content">
${System.GetTable(ControlCentreEmergancyVehicles, data.data.emergency_vehicles)}
</div>
</div>
`;
document.getElementById("currentpage-content").innerHTML += `
<div class="collapse collapse-open border border-base-300 bg-base-100 rounded-box mt-4">
<div class="collapse-title text-xl font-medium">
${getTranslation("employees.overview")}
</div>
<div class="collapse-content">
${System.GetTable(ControlCentreEmployees, data.data.employees)}
</div>
</div>
`;
}
static GetEdit(data={}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"mandatory":true
,"isRow":true
}
,"short_name": {
"val" : data.short_name ?? ""
,"type" : "text"
,"mandatory":true
,"isRow":true
}
}
}
}

View file

@ -0,0 +1,57 @@
class ControlCentreEmergancyVehicles{
constructor(){
this.name = "controlcentreemployees";
}
static allowEdit(){
return userrights.has("controlcentre.take");
}
static isCustom(){
return true;
}
static GetColumns(){
return ["short_name","name","employees","radio_short_name","id"]
}
static TableDataCreate(row, key){
let FgColor = System.GetFgColorByBgColor(row["radio_color"]);
if(row["radio_color"] == ""){
row["radio_color"] = "#FFFFFF";
}
if(key == "id"){
if(this.allowEdit()){
return `
<td style="color:${FgColor}; background:${row["radio_color"]}">
<button type="button" class="btn btn-sm btn-primary" onclick="resetVehicle('${row["id"]}')">
<i class="fa-solid fa-delete-left"></i>
</button>
<button type="button" class="btn btn-sm btn-warning" onclick="loadPage('emergencyvehicleradio.edit','${row["id"]}')">
<i class="fa-solid fa-tower-broadcast"></i>
</button>
</td>`;
}
else{
return ``;
}
}
else if(key == "radio_short_name"){
return `
<td style="color:${FgColor}; background:${row["radio_color"]}">
${row[key] == "" ? getTranslation("emergency_vehicles_no_radio") : row[key]}
</td>`;
}
else if(key == "employees"){
return `
<td style="color:${FgColor}; background:${row["radio_color"]}">
${System.buildEmployeeName(row[key])}
</td>`;
}
else {
return `<td style="color:${FgColor}; background:${row["radio_color"]}">${row[key]}</td>`;
}
}
}

View file

@ -0,0 +1,60 @@
class ControlCentreEmployees{
constructor(){
this.name = "controlcentreemployees";
}
static allowEdit(){
return userrights.has("controlcentre.take");
}
static isCustom(){
return true;
}
static GetColumns(){
return ["name","radio_short_name","id"]
}
static TableDataCreate(row, key){
let FgColor = System.GetFgColorByBgColor(row["radio_color"]);
if(row["radio_color"] == ""){
row["radio_color"] = "#FFFFFF";
}
if(key == "id"){
if(!this.allowEdit()){
return `<td></td>`
}
return `
<td style="color:${FgColor}; background:${row["radio_color"]}">
<button type="button" class="btn btn-sm btn-primary" onclick="resetEmployeeRadio('${row["id"]}')">
<i class="fa-solid fa-delete-left"></i>
</button>
<button type="button" class="btn btn-sm btn-warning" onclick="loadPage('employeevehicle.edit', '${row["id"]}')">
<i class="fa-solid fa-car-on"></i>
</button>
<button type="button" class="btn btn-sm btn-warning" onclick="loadPage('employeeradio.edit','${row["id"]}')">
<i class="fa-solid fa-tower-broadcast"></i>
</button>
</td>`;
}
else if(key == "radio_short_name"){
return `
<td style="color:${FgColor}; background:${row["radio_color"]}">
${row[key] == "" ? getTranslation("emergency_vehicles_no_radio") : row[key]}
</td>`;
}
else if(key == "name"){
return `
<td style="color:${FgColor}; background:${row["radio_color"]}">
${row["serviceno"] ?? System.getServiceNo(row.id)} - ${System.buildEmployeeName(row[key])}
</td>`;
}
else {
return `<td style="color:${FgColor}; background:${row["radio_color"]}">${row[key]}</td>`;
}
}
}

View file

@ -0,0 +1,94 @@
class Dashboard{
constructor(){
this.name = "dashboard";
}
static isCustom(){
return true;
}
static CreateCustom(data){
let controlCenterBg = "";
if(data.data.control_centre == ""){
controlCenterBg = "error"
data.data.control_centre = getTranslation("no_control_centre");
}
else{
data.data.control_centre = System.buildEmployeeName(data.data.control_centre)
}
let stats = [];
stats = [
[
{name:"files.overview", text : data.data.info[0].files, goto:"files.overview", "gotoAllowed":userrights.has("files.view")},
{name:"regvehicle.overview", text : data.data.info[0].regvehicle},
{name:"regvehicle_nomot.overview", text : data.data.info[0].regvehicle_no_mot},
],
[
{name:"control_centre", text : data.data.control_centre, bg:controlCenterBg, goto:"controlcentre.dataload", "gotoAllowed":userrights.has("controlcentre.view")},
{name:"employees.overview", text : data.data.info[0].employees, goto:"employees.overview","gotoAllowed":userrights.has("employees.view")},
{name:"count_employees_available", text : data.data.info[0].employees_available},
],
[
{name:"open_documents.overview", text : data.data.info[0].open_documents},
{name:"declined_documents.overview", text : data.data.info[0].declined_documents},
{name:"invoiced_documents.overview", text : data.data.info[0].invoiced_documents},
{name:"done_documents.overview", text : data.data.info[0].done_documents},
],
[
{name:"vehicle_damages.overview", text : data.data.info[0].vehicle_damages},
{name:"vehicle_damages_repaired.overview", text : data.data.info[0].vehicle_damages_repaired},
{name:"partacceptance_pos.overview", text : data.data.info[0].partacceptance_pos},
],
];
let statsHTML = ``;
for(let i=0; i<stats.length; i++){
statsHTML += `<div class="grid pt-8 md:grid-cols-${stats[i].length} grid-cols-1 gap-6">`
for(let j=0; j<stats[i].length; j++){
let btn = ``;
let bgClasses = "";
let txtclasses = null;
let txtExtra = "";
if(stats[i][j].goto !== undefined && stats[i][j].goto !== null && stats[i][j].goto != ""){
let allowed = stats[i][j].gotoAllowed ?? true
if(allowed){
btn = `<button class="btn btn-xs" onclick="loadPage('${stats[i][j].goto}',-1)">${getTranslation("goto")} ${getTranslation(stats[i][j].goto)}</button>`
}
}
if(stats[i][j].nameextra !== undefined && stats[i][j].nameextra !== null && stats[i][j].nameextra != ""){
txtExtra = ` (${stats[i][j].nameextra})`
}
if(stats[i][j].bg !== undefined && stats[i][j].bg !== null && stats[i][j].bg != ""){
bgClasses = `bg-${stats[i][j].bg}`
txtclasses = `text-${stats[i][j].bg}-content`
}
let textclass2="text-primary"
textclass2 = "";
statsHTML += `
<div class="stats shadow ${bgClasses}">
<div class="stat">
<div class="stat-title ${txtclasses}">${getTranslation(stats[i][j].name)}${txtExtra}</div>
<div class="stat-value ${txtclasses ?? textclass2}">${stats[i][j].text}</div>
<div class="stat-actions">${btn}</div>
</div>
</div>
`
}
statsHTML += `</div>`
}
document.getElementById("currentpage-content").innerHTML = statsHTML;
}
}

View file

@ -0,0 +1,94 @@
class EmergencyVehicle{
constructor(){
this.name = "emergencyvehicle";
}
static allowAddNew(){
return userrights.has("emergencyvehicle.edit")
}
static allowEdit(){
return userrights.has("emergencyvehicle.edit")
}
static allowDelete(){
return userrights.has("emergencyvehicle.delete")
}
static GetExtraForOverview(data){
let retval = {
top:"",
bottom:""
}
let buttons = ``;
let currentVehicle = getTranslation("no_current_vehicle");
if(data.current_vehicle!== undefined && data.current_vehicle.length > 0 && data.current_vehicle[0].id !== undefined && data.current_vehicle[0].id > -1){
currentVehicle = data.current_vehicle[0].short_name + " - " + data.current_vehicle[0].name
buttons = `
<button type="button" class="btn btn-sm btn-primary" onclick="SetVehicle(-1,'emergencyvehicle.overview')">${getTranslation("leave_patrol")}</button>
`
}
retval.top = `
<div class="alert alert-info shadow-lg mb-4">
<div>
<div>${getTranslation("current_vehicle")}: <strong>${currentVehicle}</strong></div>
<div>
${buttons}
</div>
</div>
</div>
`;
return retval;
}
static GetColumns(){
return ["name","short_name","vehicle","action","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name, this.allowDelete())}
</td>`;
}
else if(key == "action"){
return `
<td>
<button type="button" class="btn btn-primary btn-sm" onclick="SetVehicle(${row["id"]}, 'emergencyvehicle.overview')">${getTranslation("set_state")}</button>
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data = {}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
,"short_name": {
"val" : data.short_name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
,"vehicle": {
"val" : data.vehicle ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
}
}
}

View file

@ -0,0 +1,33 @@
class EmergencyVehicleRadio{
constructor(){
this.name = "emergencyvehicleradio";
}
static GetCustomDestination(data, dest){
return "controlcentre.dataload";
}
static GetCustomDestID(data, destID){
return -1;
}
static GetColumns(){
return []
}
static TableDataCreate(row, key){
return `<td>${row[key]}</td>`;
}
static GetEdit(data={}){
return {
"radio_status_id": {
"val" : data.radio_status_id ?? "-1"
,"type" : "dropdown"
,"mandatory":true
,"isRow":true
,"options":data.extraData.radio_states
}
}
}
}

View file

@ -0,0 +1,33 @@
class EmployeeRadio{
constructor(){
this.name = "employeeradio";
}
static GetCustomDestination(data, dest){
return "controlcentre.dataload";
}
static GetCustomDestID(data, destID){
return -1;
}
static GetColumns(){
return []
}
static TableDataCreate(row, key){
return `<td>${row[key]}</td>`;
}
static GetEdit(data={}){
return {
"radio_status_id": {
"val" : data.radio_status_id ?? "-1"
,"type" : "dropdown"
,"mandatory":true
,"isRow":true
,"options":data.extraData.radio_states
}
}
}
}

View file

@ -0,0 +1,33 @@
class EmployeeVehicle{
constructor(){
this.name = "employeevehicle";
}
static GetCustomDestination(data, dest){
return "controlcentre.dataload";
}
static GetCustomDestID(data, destID){
return -1;
}
static GetColumns(){
return []
}
static TableDataCreate(row, key){
return `<td>${row[key]}</td>`;
}
static GetEdit(data={}){
return {
"emegency_vehicle_id": {
"val" : data.emegency_vehicle_id ?? "-1"
,"type" : "dropdown"
,"mandatory":true
,"isRow":true
,"options":data.extraData.vehicles
}
}
}
}

View file

@ -0,0 +1,247 @@
class Employees{
constructor(){
this.name = "employees";
}
static allowEdit(){
return userrights.has("employees.edit");
}
static allowAddNew(){
return false;
}
static allowSuspend(){
return userrights.has("employees.suspend")
}
static allowViewEmployeeEntries(){
return userrights.has("employeesentries.view")
}
static allowEditEmployeeEntries(){
return userrights.has("employeesentries.edit")
}
static allowDeleteEmployeeEntries(){
return userrights.has("employeesentries.delete")
}
static allowFinishEmployeeEntries(){
return userrights.has("employeesentries.finish")
}
static allowViewUserTrainings(){
return userrights.has("trainingsemployees.view")
}
static GetExtraForView(data){
let retval = {
top:"",
bottom:""
}
let suspendedText = getTranslation("suspend");
let suspended_new = 1;
if(data.extraData.is_suspended !== undefined && data.extraData.is_suspended.length > 0 && data.extraData.is_suspended[0].is_suspended == true){
suspendedText = getTranslation("unsuspend");
suspended_new = 0;
}
let buttons = ``;
if(this.allowSuspend()){
buttons += `<button type="button" class="btn btn-sm
btn-warning" onclick="changeDataInColumn('employees','is_suspended','${data.id}','${suspended_new}')">${suspendedText}</button>`;
//buttons += `<button type="button" class="btn btn-sm btn-warning" onclick="EmployeeSuspend('employees','${data.id}','${suspended_new}')">${suspendedText}</button>`;
}
if(this.allowEditEmployeeEntries()){
buttons += `<button type="button" class="btn btn-sm btn-primary" onclick="loadPage('employeesentry.add',-1,'false',{data:{employee_id:'${data.id}'}})">${getTranslation("fileentry.add")}</button>`;
}
if(this.allowViewUserTrainings()){
buttons += `<button type="button" class="btn btn-sm btn-primary" onclick="loadPage('employeestraining.dataload','${data.id}')">${getTranslation("employeestraining.dataload")}</button>`;
}
retval.bottom += `
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 pt-6">
${buttons}
</div>
`;
if(this.allowViewEmployeeEntries() && data.extraData.file_entries !== undefined){
let entryTypes = System.getEmployeeEntryTypes();
retval.bottom += `
<div class="collapse collapse-arrow border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">
${getTranslation("employees_file")}
</div>
<div class="collapse-content">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 pt-6">`;
for(let i=0;i<data.extraData.file_entries.length;i++){
let row = data.extraData.file_entries[i];
let bgColor = entryTypes[row.type_of_entry].color ?? "ghost";
let type_name = entryTypes[row.type_of_entry].name ?? "";
let badges = ``;
badges += `<div class="badge badge-${bgColor} gap-2">${type_name}</div>`;
if(row.closed){
badges += `<div class="badge badge-success gap-2">${getTranslation("entry_finished")}</div>`;
}
let buttons = ``;
if(!row.closed && this.allowFinishEmployeeEntries()){
buttons += `<button onclick="changeDataInColumn('employeesentry', 'closed', '${row.id}', 1)" class="btn btn-sm btn-primary">${getTranslation("finish_file_entry")}</button>`;
}
if(this.allowDeleteEmployeeEntries()){
buttons += `<button onclick="Form.openDeleteModal('${row.id}','employeesentry')" class="btn btn-sm btn-error">${getTranslation("delete")}</button>`;
}
let temp = `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body">
<h2 class="card-title uppercase font-bold">${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.creationdate)}</h2>
<h2 class="card-title uppercase font-bold">${badges}</h2>
<p class="border border-current rounded-xl p-1 break-all">${row.content.replace(/\n/g,"<br>")}</p>
<p></p>
<div class="card-actions justify-start">
${buttons}
</div>
</div>
</div>
`;
if( i % 2 === 0){
temp += `<div></div>`
}
else{
temp = `<div></div>` + temp
}
retval.bottom += temp;
}
retval.bottom += `
</div>
</div>
</div>`;
}
return retval;
}
static GetEdit(data={}){
let serviceno = null;
if(data !== null){
if(data.extraData.serviceno !== undefined && data.extraData.serviceno !== null && data.extraData.serviceno.length > 0){
serviceno = data.extraData.serviceno[0].serviceno ?? System.getServiceNo(data.identifier ?? data.citizenid)
}
else{
serviceno = System.getServiceNo(data.identifier ?? data.citizenid);
}
}
return {
"serviceno": {
"val" : serviceno ?? ""
,"type" : "text"
,isRow:true
,hideInEdit:false
},
"firstname": {
"val" : data.firstname ?? System.getFirstName(data.charinfo ?? "")
,"type" : "text"
,hideInEdit:true
},
"lastname": {
"val" : data.lastname ?? System.getLastName(data.charinfo ?? "")
,"type" : "text"
,"mandatory":true
,hideInEdit:true
}
,"rank": {
"val" : data.job_grade ?? System.getJobGrade(data.job)
,"type" : "dropdown"
,"mandatory":true
,isRow:true
,options:System.getRankOptions()
,hideInEdit:true
}
}
}
static GetColumns(){
return ["serviceno","name","rank_name","state","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getViewButtonIcon(row[key], this.name + ".view")}
${Form.getEditButtonIcon(row[key], this.name + ".edit", this.allowEdit())}
</td>`;
}
else if(key == "serviceno"){
return `
<td>
${row[key] ?? System.getServiceNo(row.id)}
</td>`;
}
else if(key == "name"){
return `
<td>
${System.buildEmployeeName(row[key])}
</td>`;
}
else if(key == "state"){
if(row[key] != ""){
return `
<td>
<div class="badge badge-warning font-bold">${getTranslation("state_" + row[key])}</div>
</td>`;
}
else{
return `<td></td>`
}
}
else if(key == "rank_name"){
let grade = -9999
try {
if(typeof JSON.parse(row[key]) == "number"){
grade = row[key]
}
}
catch (e) {
console.loh("catch");
grade = row[key]
}
if(grade == -9999){
grade = System.getJobGrade(row[key]);
}
return `
<td>
${System.getLabelByRank(grade)}
</td>
`;
}
else {
return `<td>${row[key]}</td>`;
}
}
}

View file

@ -0,0 +1,45 @@
class EmployeesEntry{
constructor(){
this.name = "employeesentry";
}
static GetCustomDestination(data, dest){
return (data.employee_id ?? "" != "" ? "employees.view" : "employees.overview");
}
static GetCustomDestID(data, destID){
return data.employee_id ?? destID;
}
static GetColumns(){
return [];
}
static TableDataCreate(row, key){
return `<td>${row[key]}</td>`;
}
static GetEdit(data = {}){
return {
"employee_id": {
"val" : data.employee_id ?? ""
,"type" : "hidden"
,"mandatory":true
}
,"content": {
"val" : data.content ?? ""
,"type" : "textarea"
,"mandatory":true
,"isRow":true
,autogrow: true
}
,"type_of_entry": {
"val" : data.type_of_entry ?? 0
,"type" : "dropdown"
,"mandatory":true
,"isRow":true
,"options":System.getEmployeeEntryTypesOptions()
}
};
}
}

View file

@ -0,0 +1,88 @@
class EmployeesTraining{
constructor(){
this.name = "employeestraining";
}
static GetCustomDestination(data, dest){
return (data.employee_id ?? "" != "" ? "employees.view" : "employees.overview");
}
static GetCustomDestID(data, destID){
return data.employee_id ?? destID;
}
static isCustom(){
return true;
}
static GetColumns(){
return ["name","action","passed","id"]
}
static CreateCustom(data){
document.getElementById("currentpage-content").innerHTML=Form.BackEditBtn("employees.view", "", -1, false, data.data.employee_id);
document.getElementById("currentpage-content").innerHTML+=System.GetTable(this, data.data.trainings);
Form.initViewModeTopButtons();
}
static TableDataCreate(row, key){
if(key == "id"){
if(row.passed > -1){
return `
<td>
<button type="button" class="btn btn-sm btn-error" onclick="trainingPassed(-1, '${row["employee_id"]}', '${row["id"]}', true)">
<i class="fa-solid fa-delete-left"></i>
</button>
</td>`;
}
else{
return `<td></td>`;
}
}
else if(key == "action"){
let disabled = "";
if(row.entered > 0){
disabled = " disabled"
}
let content = `<button type="button" class="btn btn-sm btn-primary" onclick="participateForTraining(${row["id"]}, '${row["employee_id"]}', true)" ${disabled}>${getTranslation("participate")}</button>`
return `
<td>
${content}
</td>`;
}
else if(key == "passed"){
let content = "";
if(row[key] == -1){
content = `
<button type="button" class="btn btn-sm btn-error" onclick="trainingPassed(0, '${row["employee_id"]}', '${row["id"]}', true)">
<i class="fa-solid fa-xmark"></i>
</button>
<button type="button" class="btn btn-sm btn-success" onclick="trainingPassed(1, '${row["employee_id"]}', '${row["id"]}', true)">
<i class="fa-solid fa-check"></i>
</button>`
;
}
else if(row[key] == 0){
content = `<i class="fa-solid fa-xmark text-error"></i>`;
}
else if(row[key] == 1){
content = `<i class="fa-solid fa-check text-success"></i>`;
}
return `
<td>
${content}
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
}

View file

@ -0,0 +1,177 @@
class Files{
constructor(){
this.name = "files";
}
static allowAddNew(){
return userrights.has("files.edit") && !sync.isActive("files");
}
static allowEdit(){
return userrights.has("files.edit");
}
static allowDelete(ingoreSync=false){
return userrights.has("files.delete") && (!sync.isActive("files") || ingoreSync);
}
static allowClose(){
return userrights.has("files.close");
}
static allowBlacken(){
return userrights.has("files.blacken");
}
static allowShare(){
return userrights.has("files.share");
}
static allowFinishmanhunt(){
return userrights.has("manhunt.finish");
}
static allowFinishEntry(){
return userrights.has("filesentry.finish");
}
static GetColumns(){
return ["name","alias","phone","id"];
}
static GetPropertyHTML(data){
if(data.extraData.properties == null || data.extraData.properties == undefined){
return "";
}
else{
let tbody = ``;
for(let i=0; i<data.extraData.properties.length; i++){
let row = data.extraData.properties[i];
tbody += `
<tr>
<td>
${row.label}
</td>
<td>
<button type="button" class="btn btn-primary btn-sm" data-entering='${row.entering}' onclick="GenerateRoute(this)">
<i class="fa-solid fa-location-dot"></i>
<button>
</td>
</tr>
`;
}
return `
<div class="collapse collapse-open border border-base-300 bg-base-100 rounded-box mt-4">
<div class="collapse-title text-xl font-medium">
${getTranslation("properties")}
</div>
<div class="collapse-content">
<table class="table table-compact w-full">
<thead>
<tr>
<th>
${getTranslation("name")}
</th>
<th>
</th>
</tr>
</thead>
<tbody>
${tbody}
</tbody>
</table>
</div>
</div>
`
}
}
static GetExtraForView(data){
let retval = {
top:"",
bottom:"",
initTableButtons:false,
}
if(RegVehicle.allowView()){
if(data.extraData.vehicles !== undefined){
retval.bottom += `
<div class="collapse collapse-open border border-base-300 bg-base-100 rounded-box mt-4">
<div class="collapse-title text-xl font-medium">
${getTranslation("regvehicle.overview")}
</div>
<div class="collapse-content">
${System.GetTable(RegVehicle, data.extraData.vehicles)}
</div>
</div>
`;
retval.initTableButtons = true
}
}
return retval;
}
static TableDataCreate(row, key){
if(key == "state"){
let badges = ``;
if(row[key] != ""){
badges += `<div class="badge badge-error font-bold">${getTranslation("tag_" + row[key])}</div>`;
}
if(row.blackend){
badges += `<div class="badge badge-warning font-bold">${getTranslation("tag_blackend")}</div>`;
}
if(row.closed){
badges += `<div class="badge badge-info font-bold">${getTranslation("tag_closed")}</div>`;
}
return `<td>${badges}</td>`;
}
else if(key == "id"){
return `
<td>
${Form.getViewButtonIcon(row[key], this.name + ".view")}
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
</td>`;
}
else if(key == "shared"){
if(row[key]){
return `
<td class="font-bold">
<i class="fa-solid fa-check"></i>
</td>
`;
}
else{
return `<td></td>`;
}
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data = {}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"mandatory":true
}
,"alias": {
"val" : data.alias ?? ""
,"type" : "text"
,"mandatory":false
}
,"phone": {
"val" : data.phone ?? ""
,"type" : "text"
,"mandatory":false
}
};
}
}

View file

@ -0,0 +1,92 @@
class MissionReport{
constructor(){
this.name = "missionreport";
}
static allowAddNew(){
return userrights.has("missionreport.edit");
}
static allowEdit(){
return userrights.has("missionreport.edit");
}
static allowDelete(){
return userrights.has("missionreport.delete");
}
static GetColumns(){
return ["name","mission_date","createddate","createdby","changeddate","changedby","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getViewButtonIcon(row[key], this.name + ".view")}
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name, this.allowDelete())}
</td>`;
}
else if(key == "mission_date"){
return `
<td>
${System.formatDate(row[key])}
</td>`;
}
else if(key == "name"){
return `
<td class="whitespace-normal">
${row[key]}
</td>`;
}
else if(key == "createddate" || key == "changeddate"){
return `
<td>
${System.formatTimestamp(row[key])}
</td>`;
}
else if(key == "createdby" || key == "changedby"){
return `
<td>
${System.buildEmployeeName(row[key])}
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"mandatory":true
}
,"mission_date": {
"val" : data.mission_date ?? new Date().toISOString().split('T')[0]
,"type" : "date"
,"mandatory":true
}
,"mission_location":{
"val" : data.mission_location ?? ""
,"type" : "text"
,"mandatory":true
}
,"involved_forces": {
"val" : data.involved_forces ?? ""
,"type" : "text"
,"mandatory":true
}
,"report":{
"val" : data.report ?? ""
,"type" : "textarea"
,"isRow": true
,"mandatory":true
,autogrow: true
,rows:3
}
}
}
}

View file

@ -0,0 +1,133 @@
class Notes{
constructor(){
this.name = "notes";
}
static allowAddNew(){
return userrights.has("notes.edit");
}
static allowEdit(){
return userrights.has("notes.edit");
}
static allowDelete(){
return userrights.has("notes.delete");
}
static isCustom(){
return true;
}
static GetEdit(data={}){
return {
"note_headline": {
"val" : data.note_headline ?? ""
,"type" : "text"
,"mandatory":true
,"isRow":true
},
"note": {
"val" : data.note ?? ""
,"type" : "textarea"
,"isRow": true
,"mandatory":true
,autogrow: true
,rows:3
}
,"is_important_note": {
"val" : data.is_important_note ?? ""
,"type" : "dropdown"
,"isRow": true
,"mandatory":true
,"options":System.GetBooleanOptions()
}
}
}
static CreateCustom(data){
document.getElementById("currentpage-content").innerHTML = Form.overviewHeadline(this.name.toLowerCase() + ".add", false, this.allowAddNew());
let statsHTML = ``;
if(data.data.important_notes.length > 0 || data.data.notes.length > 0){
let badges = ``;
if(data.data.important_notes.length > 0){
let gridCols = data.data.important_notes.length;
if(data.data.important_notes.length > 4){
gridCols = 4;
}
statsHTML += `<div class="grid pt-8 md:grid-cols-${gridCols} grid-cols-1 gap-6">`
for(let i = 0; i<data.data.important_notes.length; i++){
let row = data.data.important_notes[i];
badges = `<div class="badge badge-error gap-2 font-bold">${getTranslation("stat.is_important_note")}</div>`;
let buttons = ``;
if(this.allowEdit()){
buttons += `<button onclick="loadPage('notes.edit','${row.id}')" class="btn btn-primary btn-sm">${getTranslation("edit")}</button>`;
}
if(this.allowDelete()){
buttons += `<button onclick="Form.openDeleteModal('${row.id}','notes')" class="btn btn-sm btn-error">${getTranslation("delete")}</button>`;
}
statsHTML += `
<div class="card w-full bg-warning text-warning-content">
<div class="card-body">
<h2 class="card-title uppercase font-bold">${row.note_headline}</h2>
<h2>${badges}</h2>
<p><strong>${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.creationdate)}</strong></p>
<p class="border border-current rounded-xl p-1 break-all">${row.note.replace(/\n/g, "<br>")}</p>
<div class="card-actions justify-start">
${buttons}
</div>
</div>
</div>
`;
}
statsHTML += `</div>`;
}
if(data.data.notes.length > 0){
statsHTML += `<div class="grid pt-8 md:grid-cols-4 grid-cols-1 gap-6">`
for(let i = 0; i<data.data.notes.length; i++){
let row = data.data.notes[i];
let buttons = ``;
if(this.allowEdit()){
buttons += `<button onclick="loadPage('notes.edit','${row.id}')" class="btn btn-primary btn-sm">${getTranslation("edit")}</button>`;
}
if(this.allowDelete()){
buttons += `<button onclick="Form.openDeleteModal('${row.id}','notes')" class="btn btn-sm btn-error">${getTranslation("delete")}</button>`;
}
statsHTML += `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body">
<h2 class="card-title uppercase font-bold">${row.note_headline}</h2>
<p><strong>${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.creationdate)}</strong></p>
<p class="border border-current rounded-xl p-1 break-all">${row.note.replace(/\n/g, "<br>")}</p>
<div class="card-actions justify-start">
${buttons}
</div>
</div>
</div>
`;
}
statsHTML += `</div>`;
}
document.getElementById("currentpage-content").innerHTML += statsHTML;
}
Form.initTableButtons();
}
}

View file

@ -0,0 +1,99 @@
class Pricelist{
constructor(){
this.name = "pricelist";
}
static isCustom(){
return true;
}
static allowEdit(){
return userrights.has("pricelistgroups.edit");
}
static allowDelete(){
return userrights.has("pricelistgroups.delete");
}
static GetColumns(isEditList){
if(!isEditList){
return ["description","price","max_discount","id"]
}
else{
return ["description","price","amount","discount","total_price","id"]
}
}
static TableDataCreate(row, key, isEditList){
if(!isEditList){
if(key == "id"){
return `
<td>
${Form.getEditButtonIcon(row[key], this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name ,this.allowDelete())}
</td>`;
}
else if(key == "description") {
return `<td class="whitespace-normal">${row[key]}</td>`;
}
else if(key == "price") {
return `<td>${System.FormatNumber(row[key])}</td>`;
}
else {
return `<td>${row[key]}</td>`;
}
}
else{
if(key == "id"){
return `<td class="edittable_row" id = "edittable_row_${row.id}">
${Form.Hidden("id_" + row.id, row[key])}
${Form.Hidden("max_discount_" + row.id, row["max_discount"])}
${Form.Hidden("discounted_price_" + row.id, row["discounted_price"])}
</td>`;
}
else if(key == "description") {
return `<td class="whitespace-normal">${row[key]}</td>`;
}
else if(key == "price"){
return `<td>${Form.NumberField(false, "price_" + row.id, row[key], "", true, false)}</td>`;
}
else if(key == "amount"){
return `<td>${Form.NumberField(false, "amount_" + row.id, "0", "pricelistpos_calc_amount", false, false)}</td>`;
}
else if(key == "discount"){
return `<td>${Form.NumberField(false, "discount_" + row.id, "0", "pricelistpos_calc_discount", false, false)}</td>`;
}
else if(key == "total_price"){
return `<td>${Form.NumberField(false, "total_price_" + row.id, "0", "pricelistpos_calc_total_price", true, false)}</td>`;
}
else {
return `<td>${row[key]}</td>`;
}
}
}
static GetEdit(data={}){
return {
"pricelist_group_id": {
"val" : data.pricelist_group_id ?? "-1"
,"type" : "hidden"
},
"description": {
"val" : data.description ?? ""
,"type" : "text"
,"mandatory":true
}
,"price": {
"val" : data.price ?? ""
,"type" : "number"
,"mandatory":true
}
,"max_discount": {
"val" : data.max_discount ?? 0
,"type" : "number"
,"mandatory":true
}
}
}
}

View file

@ -0,0 +1,116 @@
class PriceListGroups{
constructor(){
this.name = "pricelistgroups";
}
static allowAddNew(){
return userrights.has("pricelists.edit");
}
static allowEdit(){
return userrights.has("pricelists.edit");
}
static allowDelete(){
return userrights.has("pricelists.delete");
}
static isCustom(){
return true;
}
static CreateCustom(data, isEditList = false ){
if(!isEditList){
document.getElementById("currentpage-content").innerHTML = Form.overviewHeadline(this.name.toLowerCase() + ".add", false, this.allowAddNew());
}
for(let i=0; i<data.data.length; i++){
let row = data.data[i];
let buttons = ``;
if(!isEditList && this.allowAddNew()){
buttons += `<button type="button" class="btn btn-sm btn-success pricelistgroups-add-price" data-parentID="${row.id}">${getTranslation("add_price")}</button>`;
}
if(!isEditList && this.allowEdit()){
buttons += `<button type="button" class="btn btn-sm btn-warning pricelistgroups-edit" data-parentID="${row.id}">${getTranslation("edit")}</button>`;
}
if(!isEditList && this.allowDelete()){
buttons += `<button type="button" class="btn btn-sm btn-error" onclick="Form.openDeleteModal(${row.id}, 'pricelistgroups')">${getTranslation("delete")}</button>`;
}
let collapseClass = "collapse-arrow";
if(isEditList){
collapseClass = "collapse-open";
}
document.getElementById("currentpage-content").innerHTML += `
<div class="collapse ${collapseClass} border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">
${row.name}
</div>
<div class="collapse-content">
<div class="mb-2">
${buttons}
</div>
${System.GetTable(System.getClassByName("pricelist"), row.pricelist, isEditList)}
</div>
</div>
`
}
if(!isEditList){
Form.initTableButtons();
Array.from(document.querySelectorAll(".pricelistgroups-add-price")).forEach(function(button){
button.onclick = function(){
let staticData = {
data:{
pricelist_group_id:this.getAttribute("data-parentID")
}
}
loadPage("pricelist.add",-1,"false", staticData)
}
});
Array.from(document.querySelectorAll(".pricelistgroups-edit")).forEach(function(button){
button.onclick = function(){
loadPage("pricelistgroups.edit",this.getAttribute("data-parentID"),"false", {})
}
});
}
else{
document.getElementById("currentpage-content").innerHTML += `
<table class="table table-compact w-full mt-4">
<tbody>
<tr>
<td class="text-right">
<strong>${getTranslation("total_price_no_discount")}: </strong>
<strong id = "summary_total_price_no_discount">0</strong>
</td>
</tr>
<tr>
<td class="text-right">
<strong>${getTranslation("total_price")}: </strong>
<strong id = "summary_total_price">0</strong>
</td>
</tr>
</tbody>
</table>
`;
}
}
static GetEdit(data={}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"mandatory":true
,"isRow":true
}
}
}
}

View file

@ -0,0 +1,118 @@
class RadioState{
constructor(){
this.name = "radio_state";
}
static allowAddNew(){
return userrights.has("radiostate.edit")
}
static allowEdit(){
return userrights.has("radiostate.edit")
}
static allowDelete(){
return userrights.has("radiostate.delete")
}
static GetExtraForOverview(data){
let retval = {
top:"",
bottom:""
}
let buttons = ``;
let radioDetails = System.getRadioState(data.current_state_vehicle, data.current_state_person);
let currentRadio = radioDetails.radio_default;
if(radioDetails.vehicle == null){
if(radioDetails.radio !== null){
currentRadio = data.current_state_person[0].state_name
buttons = `
<button type="button" class="btn btn-sm btn-primary" onclick="SetRadioState(-1,'radiostate.overview')">${getTranslation("emergency_vehicles_no_radio")}</button>
`
}
}
else{
currentRadio = currentRadio + " (" + radioDetails.vehicle + ")"
if(radioDetails.radio !== null){
currentRadio = radioDetails.radio + " (" + radioDetails.vehicle + ")"
buttons = `
<button type="button" class="btn btn-sm btn-warning" onclick="SetVehicle(-1,'radiostate.overview')">${getTranslation("leave_patrol")}</button>
<button type="button" class="btn btn-sm btn-primary" onclick="SetRadioState(-1,'radiostate.overview')">${getTranslation("emergency_vehicles_no_radio")}</button>
`
}
else{
buttons = `
<button type="button" class="btn btn-sm btn-warning" onclick="SetVehicle(-1,'radiostate.overview')">${getTranslation("leave_patrol")}</button>
`
}
}
retval.top = `
<div class="alert alert-info shadow-lg mb-4">
<div>
<div>${getTranslation("current_state")}: <strong>${currentRadio}</strong></div>
<div>
${buttons}
</div>
</div>
</div>
`;
return retval;
}
static GetColumns(){
return ["name","short_name","setstate","id"]
}
static TableDataCreate(row, key){
let FgColor = System.GetFgColorByBgColor(row["color"]);
if(key == "id"){
return `
<td style="color:${FgColor}; background:${row["color"]}">
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name, this.allowDelete())}
</td>`;
}
else if(key == "setstate"){
return `
<td style="color:${FgColor}; background:${row["color"]}">
<button type="button" class="btn btn-sm btn-primary" onclick="SetRadioState(${row["id"]},'radiostate.overview')">${getTranslation("set_state")}</button>
</td>`;
}
else if(key != "id"){
return `<td style="color:${FgColor}; background:${row["color"]}">${row[key]}</td>`;
}
else{
return `<td style="color:${FgColor}; background:${row["color"]}">${row[key]}</td>`;
}
}
static GetEdit(data = {}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
,"short_name": {
"val" : data.short_name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
,"color": {
"val" : data.color ?? ""
,"type" : "dropdown"
,"isRow": true
,"mandatory":true
,options:System.GetColorOptions()
}
}
}
}

View file

@ -0,0 +1,52 @@
class RankManagement{
static isCustom(){
return true;
}
static allowAddNew(){
return false;
}
static CreateCustom(data){
data.noLimit = true;
data.pageNum = 1;
data.count = data.data.length;
let tempdata = [];
for(let i=0; i<data.data.length; i++){
tempdata[data.data[i].grade] = data.data[i]
}
data.data = []
tempdata.forEach(function(element){
data.data.push(element)
});
System.CreateOverView(this, data)
}
static GetColumns(){
return ["name","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
let disabled = "";
if(row.isboss){
disabled = " disabled"
}
return `
<td>
<button type="button" onclick="loadPage('rankmanagementrights.dataload', '${row.grade}')" class="btn btn-sm btn-primary" ${disabled}>${getTranslation("set_rights")}</button>
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
}
}

View file

@ -0,0 +1,102 @@
class RankManagementRights{
static isCustom(){
return true;
}
static allowAddNew(){
return false;
}
static CreateCustom(data){
let thead = `
<tr>
<th>
<input type="checkbox" id="toggle-all-checkboxes" class="toggle toggle-success"/>
</th>
<th>
${getTranslation("name")}
</th>
</tr>
`
let tbody = ``;
for(let i=0; i<data.data.rights.length; i++){
tbody += `
<tr>
${this.TableDataCreate(data.data.rights[i],"id")}
${this.TableDataCreate(data.data.rights[i],"right_key")}
</tr>
`;
}
document.getElementById("currentpage-content").innerHTML = `
<div class="card w-full p-2 bg-base-100 shadow-xl mt-2 mb-6">
<div class="h-full w-full bg-base-100">
<div class="overflow-x-auto w-full">
<table class="table table-compact w-full">
<thead>
${thead}
</thead>
<tbody>
${tbody}
</tbody>
</table>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 pt-6">
<button id="input-cancel-button" class="btn btn-sm btn-error">${getTranslation("cancel")}</button>
<button id="input-save-button" data-rankid="${data.data.id}" class="btn btn-sm btn-primary">${getTranslation("save")}</button>
</div">
</div>
</div>
</div>
`;
document.getElementById("toggle-all-checkboxes").onclick=function(){
let check = this.checked;
Array.from(document.getElementById("currentpage-content").querySelectorAll(".toggler-input")).forEach(function(item){
item.checked = check ?? false;
});
}
document.getElementById("input-cancel-button").onclick=function(){
loadPage("rankmanagement.dataload",-1)
}
document.getElementById("input-save-button").onclick=function(){
let temp = Form.getFormData();
delete temp["toggle-all-checkboxes"];
let formData = {
rank_id: this.getAttribute("data-rankid"),
data:temp
}
sendDataToAPI("rankmanagementrights", "rankmanagement.dataload",-1, -1, formData);
}
}
static GetColumns(){
return ["name", "id"]
}
static TableDataCreate(row, key){
if(key == "id"){
let checked = "";
if(row.active){
checked = " checked";
}
return `<td><input id="input-${row.right_key}" data-id="${row[key]}" type="checkbox" class="toggle toggle-success toggler-input" ${checked} /></td>`
}
else if(key == "right_key"){
return `<td>${getTranslation(row[key])}</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
}
}

View file

@ -0,0 +1,409 @@
class RegVehicle{
constructor(){
this.name = "regvehicle";
}
static allowView(){
return userrights.has("regvehicles.view");
}
static allowAddNew(){
return userrights.has("regvehicles.edit") && !sync.isActive("regvehicle");
}
static allowEdit(){
return userrights.has("regvehicles.edit");
}
static allowDelete(){
return userrights.has("regvehicles.delete") && !sync.isActive("regvehicle");
}
static allowViewMotList(){
return userrights.has("regvehicles_mot.view");
}
static allowAddMotList(){
return userrights.has("regvehicles_mot.add");
}
static allowViewOrders(){
return userrights.has("regvehicles_orders.view");
}
static allowAddOrder(){
return userrights.has("regvehicles_orders.add");
}
static allowViewRegisteredParts(){
return userrights.has("regvehicles_parts_registered.view");
}
static allowAddRegisteredParts(){
return userrights.has("regvehicles_parts_registered.add");
}
static allowRemoveRegisteredParts(){
return userrights.has("rregvehicles_parts_registered.delete");
}
static allowViewDamageReports(){
return userrights.has("regvehicles_damage_reports.view");
}
static allowAddDamageReport(){
return userrights.has("regvehicles_damage_reports.add");
}
static GetColumns(){
return ["plate","veh_type","veh_model","owner","mot","mechanic_state","id"]
}
static GetExtraForView(data){
let retval = {
top:"",
bottom:""
}
let buttons = ``;
buttons += `<button type="button" onclick="changeDataInColumn('regvehicle','mechanic_vehicle_state','${data.id}','1')" class="btn btn-sm btn-accent" ${data.mechanic_vehicle_state != 1 ? "" : " disabled"}>${getTranslation("in_shop")}</button>`;
buttons += `<button type="button" onclick="changeDataInColumn('regvehicle','mechanic_vehicle_state','${data.id}','2')" class="btn btn-sm btn-error" ${data.mechanic_vehicle_state != 2 ? "" : " disabled"}>${getTranslation("waiting_for_cops")}</button>`;
buttons += `<button type="button" onclick="changeDataInColumn('regvehicle','mechanic_vehicle_state','${data.id}','3')" class="btn btn-sm btn-primary" ${data.mechanic_vehicle_state != 3 ? "" : " disabled"}>${getTranslation("order_is_done")}</button>`;
buttons += `<button type="button" onclick="changeDataInColumn('regvehicle','mechanic_vehicle_state','${data.id}','0')" class="btn btn-sm btn-success" ${data.mechanic_vehicle_state != 0 ? "" : " disabled"}>${getTranslation("given_back")}</button>`;
retval.bottom += `
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 pt-6">
${buttons}
</div>
`;
if(data.extraData.mot_data !== undefined && data.extraData.mot_data !== null && RegVehicle.allowViewMotList()){
let row = data.extraData.mot_data[0];
let onlyOne = data.extraData.mot_data.length == 1;
let addMotButton = ``;
if(RegVehicle.allowAddMotList()){
addMotButton = `<button type="button" class="btn btn-sm btn-warning" onclick="loadPage('regvehicle_mot.add',-1,'false',{data:{vehicle_id:'${data.id}', vehicle_mot:'${data.mot}'}})">${getTranslation("regvehicle_mot.add")}</button>`;
}
retval.bottom += `
<div class="collapse border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<summary class="collapse-title text-xl font-medium">
${getTranslation("regvehicle_mot.overview")}
</summary>
<div class="collapse-content">
${addMotButton}
<div class="grid grid-cols-1 md:grid-cols-1 gap-4 pt-6">
${RegVehicle_MOT.GetDetailView(row, data.id, !onlyOne)}
</div>
</div>
</div>
`;
}
if(data.extraData.open_offer_data !== undefined && data.extraData.open_offer_data !== null && RegVehicle.allowViewOrders()){
let allowAddOrderBtn = ``;
if(RegVehicle.allowAddOrder()){
allowAddOrderBtn = `<button type="button" class="btn btn-sm btn-warning" onclick="loadPage('regvehicle_dochead.dataload',${data.id},'true')">${getTranslation("regvehicle_dochead.add")}</button>`;
}
retval.bottom += `
<div class="collapse border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<summary class="collapse-title text-xl font-medium">
${getTranslation("regvehicle_dochead.overview")}
</summary>
<div class="collapse-content">
${allowAddOrderBtn}
<div class="grid grid-cols-1 md:grid-cols-1 gap-4 pt-6">
${System.GetTable(System.getClassByName("regvehicle_dochead"), data.extraData.open_offer_data, {})}
</div>
<button onclick="loadPage('regvehicle_dochead_history.dataload',${data.id})" class="btn btn-sm btn-primary btn-block" >${getTranslation("view_history")}</button>
</div>
</div>
`;
}
if(data.extraData.part_acceptance !== undefined && data.extraData.part_acceptance !== null && RegVehicle.allowViewRegisteredParts()){
let addNewPartAcceptanceBtn = ``;
if(RegVehicle.allowAddRegisteredParts()){
addNewPartAcceptanceBtn = `<button type="button" class="btn btn-sm btn-warning" onclick="loadPage('regvehicle_partacceptance.add',${data.id},'true',{data:{vehicle_id:'${data.id}'}})">${getTranslation("regvehicle_part_acceptance.add")}</button>`;
}
retval.bottom += `
<div class="collapse border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<summary class="collapse-title text-xl font-medium">
${getTranslation("regvehicle_part_acceptance.overview")}
</summary>
<div class="collapse-content">
${addNewPartAcceptanceBtn}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 pt-6">
`;
let i=0;
let temp = "";
for(const row of data.extraData.part_acceptance){
buttons = ``;
if(RegVehicle.allowRemoveRegisteredParts()){
buttons = `<button onclick="deleteData('regvehicle_partacceptance','${row.id}')" class="btn btn-sm btn-error">${getTranslation("revoke")}</button>`;
}
if(i < 9999){
let temp = `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body">
<p><strong>${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.createddate)}</strong></p>
<p><strong>${getTranslation("price")}</strong>: $${System.FormatNumber(row.total_price)}</p>
<p></p>
<p class="border border-current rounded-xl p-1 break-all">${row.content.replace(/\n/g,"<br>")}</p>
<p>
<p class="p-1 break-all">${(row["_acceptance_name"] ?? "").replace(/\n/g,"<br>")}</p>
<div class="card-actions justify-start">
${buttons}
</div>
</div>
</div>
`;
retval.bottom += temp;
}
i++;
}
retval.bottom += `
</div>
</div>
</div>
`;
}
if(data.extraData.damages !== undefined && data.extraData.damages !== null && RegVehicle.allowViewDamageReports()){
let addDamageRportBtn = ``;
if(RegVehicle.allowAddDamageReport()){
addDamageRportBtn = `<button type="button" class="btn btn-sm btn-primary" onclick="loadPage('regvehicle_damage.add',-1,'false',{data:{vehicle_id:'${data.id}'}})">${getTranslation("regvehicle_damage.add")}</button>`;
}
retval.bottom += `
<div class="collapse border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<summary class="collapse-title text-xl font-medium">
${getTranslation("regvehicle_damage.overview")}
</summary>
<div class="collapse-content">
${addDamageRportBtn}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 pt-6">
`;
let i=0;
let temp = "";
for(const row of data.extraData.damages){
buttons = "";
if(i < 5){
let badges = "";
let contentHTML = "";
if(row.content.replace(/ /g, "") !== ""){
contentHTML = `<p class="border border-current rounded-xl p-1 break-all">${row.content.replace(/\n/g,"<br>")}</p>`;
}
if(row.repaired != true){
buttons += `<button onclick="changeDataInColumn('regvehicle_damage','repaired','${row.id}','1')" class="btn btn-sm btn-primary">${getTranslation("repaired")}</button>`;
}
else{
badges += `<div class="badge badge-primary gap-2 font-bold">${getTranslation("repaired")}</div>`;
}
let temp = `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body">
<p><strong>${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.createddate)}</strong></p>
<p></p>
${contentHTML}
<h2>${badges}</h2>
<p></p>
<p></p>
${RegVehicle_Damage.GetVehicleInteractiveModel(row, true, 1)}
<div class="card-actions justify-start">
${buttons}
</div>
</div>
</div>
`;
retval.bottom += temp;
}
i++;
if(i>5){
let temp = `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body flex justify-center">
<button onclick="loadPage('regvehicle_damage.dataload',${data.id})" class="btn btn-sm btn-primary btn-block" >${getTranslation("view all")}</button>
</div>
</div>
`;
retval.bottom += temp;
}
}
retval.bottom += `
</div>
</div>
</div>
`;
}
return retval;
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getViewButtonIcon(row[key], this.name + ".view")}
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name , this.allowDelete())}
</td>`;
}
else if(key == "owner"){
let val = row[key];
if(val == ""){
val = getTranslation("unknown");
}
return `
<td>
${val}
</td>`;
}
else if(key == "mechanic_state"){
let val = row[key];
if(val != ""){
if(val == "in_shop"){
val = `<div class="badge badge-accent font-bold">${getTranslation(row[key])}</div>`;
}
else if(val == "waiting_for_cops"){
val = `<div class="badge badge-error font-bold">${getTranslation(row[key])}</div>`;
}
else if(val == "order_is_done"){
val = `<div class="badge badge-primary font-bold">${getTranslation(row[key])}</div>`;
}
}
return `
<td>
${val}
</td>`;
}
else if(key == "mot"){
if(row[key] == ""){
return `<td></td>`;
}
if(new Date(row[key]) < new Date()){
return `
<td>
<div class="badge badge-error font-bold">${System.formatDate(row[key])}</div>
</td>`
;
}
else{
return `
<td>
<div class="badge badge-success font-bold">${System.formatDate(row[key])}</div>
</td>`
;
}
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
let filesOptions = [
{"id":-1, "name":getTranslation("unknown")}
,{"id":-2, "name":getTranslation("new_file"), "show_extra_field":true}
];
if(sync.isActive("files")){
filesOptions = [
{"id":-1, "name":getTranslation("unknown")}
];
}
filesOptions = [...filesOptions, ...data.extraData.files];
return {
"plate": {
"val" : data.plate ?? ""
,"type" : "text"
,"mandatory":true
}
,"owner": {
"val" : data.owner_id ?? "-1"
,"type" : "searchdropdown"
,"mandatory":false
,options:filesOptions
}
,"veh_type": {
"val" : data.veh_type ?? ""
,"type" : "text"
,"mandatory":false
}
,"veh_model": {
"val" : data.veh_model ?? ""
,"type" : "text"
,"mandatory":false
}
,"color": {
"val" : data.color ?? ""
,"type" : "text"
,"mandatory":false
}
,"-": {
"type" : "divider"
}
,"others": {
"val" : data.others ?? ""
,"type" : "textarea"
,"isRow": true
,"mandatory":false
,autogrow: true
,rows:3
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,360 @@
class RegVehicle_DocHead{
constructor(){
this.name = "RegVehicle_DocHead";
}
static GetCustomDestination(data, dest){
return (data.vehicle_id ?? "" != "" ? "regvehicle.view" : "regvehicle.overview");
}
static GetCustomDestID(data, destID){
return data.vehicle_id ?? destID;
}
static allowView(){
return userrights.has("regvehicles.view");
}
static allowAddNew(){
return true;
}
static allowEdit(){
return userrights.has("regvehicles.edit");
}
static allowDelete(){
return userrights.has("regvehicles.edit");
}
static GetColumns(){
return ["doc_number", "creationdate" ,"status", "totalprice_no_discount","totalprice_discount","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
<button onclick="loadPage('regvehicle_dochead_details.dataload','regvehicle.view|${row[key]}')" class="btn btn-sm btn-accent">
<i class="fa-solid fa-circle-info"></i>
</button>
</td>`;
}
else if(key == "creationdate"){
return `
<td>
${System.formatTimestamp(row.creationdate)}<br>${System.buildEmployeeName(row.creator)}
</td>`;
}
else if(key == "totalprice_no_discount" || key == "totalprice_discount"){
return `
<td>
${System.FormatNumber(row[key])}
</td>`;
}
else if(key == "status"){
let selectClass = "";
let selected1="";
let selected2="";
let selected3="";
let selected4="";
if(row["done"] == 1){
selectClass = "success";
selected4 = " selected";
}
else if(row["declined"] == 1){
selectClass = "error";
selected2 = " selected";
}
else if(row["invoiced"] == 1){
selectClass = "primary";
selected3 = " selected";
}
else{
selectClass = "info";
selected1 = " selected";
}
if(row.allow_decline){
return `
<td>
<select onchange="RegVehicle_DocHead.SetStatus(${row.id}, ${row.vehicle_id}, this)" class="select ignore-readonly bg-${selectClass} text-${selectClass}-content select-${selectClass} select-sm">
<option value="0" class="btn btn-info btn-sm btn-block" ${selected1}>${getTranslation("status.open")}</option>
<option value="1" class="btn btn-error btn-sm btn-block"${selected2}>${getTranslation("status.declined")}</option>
<option value="2" class="btn btn-primary btn-sm btn-block" ${selected3}>${getTranslation("status.invoiced")}</option>
<option value="3" class="btn btn-success btn-sm btn-block" ${selected4}>${getTranslation("status.done")}</option>
</select>
</td>`
;
}
else{
return `
<td>
<select onchange="RegVehicle_DocHead.SetStatus(${row.id}, ${row.vehicle_id}, this)" class="select ignore-readonly bg-${selectClass} text-${selectClass}-content select-${selectClass} select-sm">
<option value="0" class="btn btn-info btn-sm btn-block" ${selected1}>${getTranslation("status.open")}</option>
<option value="2" class="btn btn-primary btn-sm btn-block" ${selected3}>${getTranslation("status.invoiced")}</option>
<option value="3" class="btn btn-success btn-sm btn-block" ${selected4}>${getTranslation("status.done")}</option>
</select>
</td>`
;
}
}
else{
return `<td>${row[key]}</td>`;
}
}
static SetStatus(docId, vehicle_id, senderEl){
let backEndData = {
done: senderEl.value == "3" ? "1" : "0",
declined: senderEl.value == "1" ? "1" : "0",
invoiced: senderEl.value == "2" ? "1" : "0"
}
sendDataToAPI("regvehicle_dochead", "regvehicle.view",docId, vehicle_id, backEndData);
}
static CreateCustom(data){
document.getElementById("currentpage-content").innerHTML = Form.BackEditBtn("regvehicle.view", "",-1, false, data.data.vehicle_id);
let pricelistGroupData = {};
pricelistGroupData.data = data.data.pricelist_groups
PriceListGroups.CreateCustom({data: data.data.pricelist_groups}, true);
document.getElementById("currentpage-content").innerHTML += `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 pt-6">
<button id="input-cancel-button" data-vehicle-id="${data.data.vehicle_id}" class="btn btn-sm btn-error">${getTranslation("cancel")}</button>
<button id="input-save-button" data-vehicle-id="${data.data.vehicle_id}" class="btn btn-sm btn-primary">${getTranslation("save")}</button>
</div>
`;
Form.initViewModeTopButtons();
document.getElementById("input-cancel-button").onclick=function(){
loadPage("regvehicle.view", this.getAttribute("data-vehicle-id"))
}
document.getElementById("input-save-button").onclick=function(){
let saveData = RegVehicle_DocHead.GetDataForSave("edittable_row_", ".edittable_row", ["price","amount","discount","discounted_price","total_price","id"], "amount");
if(!saveData.isValid){
Form.openInfoModal();
}
else{
let headData = {
vehicle_id : this.getAttribute("data-vehicle-id"),
totalprice_no_discount : 0,
totalprice_discount : 0
};
for (const key in saveData.posData) {
headData.totalprice_no_discount += parseInt(saveData.posData[key].amount) * parseInt(saveData.posData[key].price);
headData.totalprice_discount += parseInt(saveData.posData[key].total_price);
saveData.posData[key].total_price_no_discount = parseInt(saveData.posData[key].amount) * parseInt(saveData.posData[key].price);
saveData.posData[key].pricelist_id = saveData.posData[key].id;
saveData.posData[key].tuning_option_id = -1;
saveData.posData[key].default_price = saveData.posData[key].price;
saveData.posData[key].id = null;
delete saveData.posData[key].price;
delete saveData.posData[key].discounted_price;
}
let formData = {
headData: headData,
posData: saveData.posData
}
sendDataToAPI("regvehicle_dochead", "regvehicle.view",-1, this.getAttribute("data-vehicle-id"), formData);
}
}
Array.from(document.getElementById("currentpage-content").querySelectorAll(".pricelistpos_calc_amount")).forEach(function(item){
item.onkeyup=function(){
RegVehicle_DocHead.CalcAmountAndDiscount(this);
}
});
Array.from(document.getElementById("currentpage-content").querySelectorAll(".pricelistpos_calc_discount")).forEach(function(item){
item.onkeyup=function(){
RegVehicle_DocHead.CalcAmountAndDiscount(this);
}
});
}
static GetDataForSave(row_id_prefix, classToSearch, subElements, mustBeBiggerZero){
let idElements = Array.from(document.querySelectorAll(classToSearch));
let retval = [];
let isValid = false;
idElements.forEach(function(row){
let rowIsValid = false;
let rowID = row.id.replace(row_id_prefix, "");
let rowData = {};
for (const key in subElements) {
rowData[subElements[key]] = document.getElementById("input-" + subElements[key] + "_" + rowID).value;
if(subElements[key] == mustBeBiggerZero && (document.getElementById("input-" + subElements[key] + "_" + rowID).value*1) > 0){
isValid = true;
rowIsValid = true;
}
}
if(rowIsValid){
retval.push(rowData);
}
});
return {
isValid: isValid,
posData: retval
}
}
static CalcAmountAndDiscount(element){
let rowId = element.id.replace("input-amount_", "").replace("input-discount_","");
let amount = document.getElementById("input-amount_" + rowId).value;
let discount = document.getElementById("input-discount_" + rowId).value;
let price = document.getElementById("input-price_" + rowId).value;
let max_discount = document.getElementById("input-max_discount_" + rowId).value;
let discountedPriceEl = document.getElementById("input-discounted_price_" + rowId);
let totalPriceEl = document.getElementById("input-total_price_" + rowId);
if(discount.startsWith("0")){
document.getElementById("input-discount_" + rowId).value = 1*discount;
}
if(1*discount > 1*max_discount){
discount = max_discount;
document.getElementById("input-discount_" + rowId).value = discount;
}
if(1*amount < 0){
document.getElementById("input-amount_" + rowId).value = 0;
amount = 0;
}
let percentage = -1 * ((1*discount / 100) - 1.0)
let discountedPrice = parseInt(price * percentage);
discountedPriceEl.value = discountedPrice;
totalPriceEl.value = discountedPrice * amount;
let dataForSave = RegVehicle_DocHead.GetDataForSave("edittable_row_", ".edittable_row", ["price","amount","total_price"], "amount")
let sum_total_price = 0;
let sum_total_price_no_discount = 0;
if(dataForSave.isValid){
for (const key in dataForSave.posData) {
sum_total_price_no_discount += parseInt(dataForSave.posData[key].amount) * parseInt(dataForSave.posData[key].price);
sum_total_price += parseInt(dataForSave.posData[key].total_price);
}
}
document.getElementById("summary_total_price_no_discount").innerHTML = System.FormatNumber(sum_total_price_no_discount);
document.getElementById("summary_total_price").innerHTML = System.FormatNumber(sum_total_price);
}
static GetDetailView(row, vehicle_id = -1, drawViewButton = false){
let bottomButton = "";
let contentHtml = ``;
if(row === undefined || row === null ){
return "";
}
if(row.note !== undefined && row.note !== null && row.note.replace(/ /g, "") != ""){
contentHtml = `<p class="border border-current rounded-xl p-1 break-all">${row.note.replace(/\n/g,"<br>")}</p>`;
}
if(drawViewButton){
bottomButton = `<button onclick="loadPage('regvehicle_mot.dataload',${vehicle_id})" class="btn btn-sm btn-primary btn-block" >${getTranslation("view_history")}</button>`
}
return `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body">
<p><strong>${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.createddate)}</strong></p>
<p></p>
<p><strong>${getTranslation("passed")}</strong>: <span class="badge badge-${row.passed ? "success" : "error"} gap-2 font-bold">${getTranslation(row.passed == 1 ? "yes": "no")}</span></p>
<p><strong>${getTranslation("new_mot")}</strong>: ${System.formatDate(row.new_mot) }</p>
<p><strong>${getTranslation("old_mot")}</strong>: ${System.formatDate(row.old_mot) }</p>
${contentHtml}
<table>
<thead>
<tr>
<th>${getTranslation("mot.lights")}</th>
<th>${getTranslation("mot.brakes_tyres")}</th>
<th>${getTranslation("mot.windows")}</th>
<th>${getTranslation("mot.others")}</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center"><span class="badge badge-${row.headlights ? "success" : "error"} gap-2 font-bold">${getTranslation("headlights")}</span></td>
<td class="text-center"><span class="badge badge-${row.front_brakes ? "success" : "error"} gap-2 font-bold">${getTranslation("front_brakes")}</span></td>
<td class="text-center"><span class="badge badge-${row.windscreen ? "success" : "error"} gap-2 font-bold">${getTranslation("windscreen")}</span></td>
<td class="text-center"><span class="badge badge-${row.horn ? "success" : "error"} gap-2 font-bold">${getTranslation("horn")}</span></td>
</tr>
<tr>
<td class="text-center"><span class="badge badge-${row.rear_lights ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_lights")}</span></td>
<td class="text-center"><span class="badge badge-${row.rear_brakes ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_brakes")}</span></td>
<td class="text-center"><span class="badge badge-${row.rear_window ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_window")}</span></td>
<td class="text-center"><span class="badge badge-${row.exhaust_system ? "success" : "error"} gap-2 font-bold">${getTranslation("exhaust_system")}</span></td>
</tr>
<tr>
<td class="text-center"><span class="badge badge-${row.indicators ? "success" : "error"} gap-2 font-bold">${getTranslation("indicators")}</span></td>
<td class="text-center"><span class="badge badge-${row.front_tyres ? "success" : "error"} gap-2 font-bold">${getTranslation("front_tyres")}</span></td>
<td class="text-center"><span class="badge badge-${row.side_windows ? "success" : "error"} gap-2 font-bold">${getTranslation("side_windows")}</span></td>
<td class="text-center"><span class="badge badge-${row.engine ? "success" : "error"} gap-2 font-bold">${getTranslation("engine")}</span></td>
</tr>
<tr>
<td></td>
<td class="text-center"><span class="badge badge-${row.rear_tyres ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_tyres")}</span></td>
<td></td>
<td class="text-center"><span class="badge badge-${row.bodywork ? "success" : "error"} gap-2 font-bold">${getTranslation("bodywork")}</span></td>
</tr>
</tbody>
</table>
<p></p>
${bottomButton}
</div>
</div>
`;
}
static GetEdit(data={}){
let retval = {
"vehicle_id": {
"val" : data.vehicle_id ?? -1
,"type" : "text"
,"mandatory":true
,"isRow":true
},
}
return retval;
}
}

View file

@ -0,0 +1,138 @@
class RegVehicle_DocHead_Details{
constructor(){
this.name = "regvehicle_dochead_details";
}
static GetColumns(){
return ["positionNo","position_type", "name","amount","total_price"]
}
static allowAddNew(){
return userrights.has("regvehicles.edit")
}
static allowEdit(){
return userrights.has("regvehicles.edit")
}
static allowDelete(){
return userrights.has("regvehicles.delete")
}
static CreateCustom(data){
document.getElementById("currentpage-content").innerHTML = Form.BackEditBtn(data.data.extraData.fromPage, "",-1, false, data.data.data.headData.vehicle_id);
let badge = "";
if(data.data.data.headData["done"] == 1){
badge = `<span class="badge badge-success font-bold">${getTranslation("status.done")}</span>`;
}
else if(data.data.data.headData["declined"] == 1){
badge = `<span class="badge badge-error font-bold">${getTranslation("status.declined")}</span>`;
}
else if(data.data.data.headData["invoiced"] == 1){
badge = `<span class="badge badge-primary font-bold">${getTranslation("status.invoiced")}</span>`;
}
else{
badge = `<span class="badge badge-info font-bold">${getTranslation("status.open")}</span>`;
}
document.getElementById("currentpage-content").innerHTML += `
<div class="collapse collapse-open border border-base-300 bg-base-100 rounded-box mt-4">
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">
${data.data.data.headData.doc_number} - ${System.formatTimestamp(data.data.data.headData.creationdate)} ${badge}
</div>
<div class="collapse-content">
<b>${getTranslation("total_price_no_discount")}: </b>${System.FormatNumber(data.data.data.headData.totalprice_no_discount)}<br>
<b>${getTranslation("total_price")}: </b>${System.FormatNumber(data.data.data.headData.totalprice_discount)}
<div class="mt-2">
${System.GetTable(System.getClassByName("regvehicle_dochead_details"), data.data.data.posData, {})}
</div>
</div>
</div>
`;
Form.initViewModeTopButtons();
}
static TableDataCreate(row, key){
"positionNo","position_type", "name","amount","total_price"
if(key == "position_type"){
if(row.is_part_acceptance == 1){
return `
<td>
${getTranslation("part_acceptance_pos")}
</td>`;
}
else{
return `
<td>
${getTranslation("offer_pos")}
</td>`;
}
}
else if(key == "name"){
if(row.is_part_acceptance == 1){
return `
<td>
${row.part_acceptance_name}
</td>`;
}
else{
return `
<td>
${row.pricelist_group_name}<br>${row.pricelist_name}
</td>`;
}
}
else if(key == "total_price"){
if(row.discount == 0){
return `
<td>
<strong>${System.FormatNumber(row.total_price)}</strong>
</td>`;
}
else{
return `
<td>
${System.FormatNumber(row.total_price_no_discount)}
<br>
<span class="text-error"><b>-${System.FormatNumber(row.discount)}%</b></span>
<br>
<br>
<strong>${System.FormatNumber(row.total_price)}</strong>
</td>`;
}
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
},
"price": {
"val" : data.price ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
}
}
}

View file

@ -0,0 +1,83 @@
class RegVehicle_DocHead_History{
constructor(){
this.name = "regvehicle_dochead_history";
}
static GetColumns(){
return ["doc_number","creationdate","status","totalprice_no_discount","totalprice_discount", "id"]
}
static allowAddNew(){
return userrights.has("regvehicles.edit")
}
static allowEdit(){
return userrights.has("regvehicles.edit")
}
static allowDelete(){
return userrights.has("regvehicles.delete")
}
static CreateCustom(data){
document.getElementById("currentpage-content").innerHTML = Form.BackEditBtn("regvehicle.view", "",-1, false, data.data.extraData.vehicle_id);
document.getElementById("currentpage-content").innerHTML += System.GetTable(System.getClassByName("regvehicle_dochead_history"), data.data.data, {})
Form.initViewModeTopButtons();
Form.initTableButtons();
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getViewButtonIcon("regvehicle_dochead_history.dataload|" + row[key], "regvehicle_dochead_details.dataload")}
</td>`;
}
else if(key == "creationdate"){
return `
<td>
${System.formatTimestamp(row.creationdate)}<br>${System.buildEmployeeName(row.creator)}
</td>`;
}
else if(key == "totalprice_no_discount" || key == "totalprice_discount"){
return `
<td>
${System.FormatNumber(row[key])}
</td>`;
}
else if(key == "status"){
if(row["done"] == 1){
return `<td class="text-center"><span class="badge badge-success font-bold">${getTranslation("status.done")}</span></td>`;
}
else if(row["declined"] == 1){
return `<td class="text-center"><span class="badge badge-error font-bold">${getTranslation("status.declined")}</span></td>`;
}
else if(row["invoiced"] == 1){
return `<td class="text-center"><span class="badge badge-primary font-bold">${getTranslation("status.invoiced")}</span></td>`;
}
else{
return `<td class="text-center"><span class="badge badge-info font-bold">${getTranslation("status.open")}</span></td>`;
}
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
},
"price": {
"val" : data.price ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
}
}
}

View file

@ -0,0 +1,288 @@
class RegVehicle_MOT{
constructor(){
this.name = "regvehicle_mot";
}
static GetCustomDestination(data, dest){
return (data.vehicle_id ?? "" != "" ? "regvehicle.view" : "regvehicle.overview");
}
static GetCustomDestID(data, destID){
return data.vehicle_id ?? destID;
}
static allowView(){
return userrights.has("regvehicles.view");
}
static allowAddNew(){
return true;
}
static allowEdit(){
return userrights.has("regvehicles.edit");
}
static allowDelete(){
return userrights.has("regvehicles.edit");
}
static GetColumns(){
return ["plate","veh_type","veh_model","owner","mot","state","id"]
}
static CreateCustom(data){
let html = Form.BackEditBtn("regvehicle.view", "",-1, false, data.data.id);
html += `<div class="grid grid-cols-1 md:grid-cols-1 gap-4 pt-6">`;
for(const row of data.data.data){
html += this.GetDetailView(row, data.data.id, false);
}
html += `</div>`;
document.getElementById("currentpage-content").innerHTML = html;
Form.initViewModeTopButtons();
}
static GetDetailView(row, vehicle_id = -1, drawViewButton = false){
let bottomButton = "";
let contentHtml = ``;
if(row === undefined || row === null ){
return "";
}
if(row.note !== undefined && row.note !== null && row.note.replace(/ /g, "") != ""){
contentHtml = `<p class="border border-current rounded-xl p-1 break-all">${row.note.replace(/\n/g,"<br>")}</p>`;
}
if(drawViewButton){
bottomButton = `<button onclick="loadPage('regvehicle_mot.dataload',${vehicle_id})" class="btn btn-sm btn-primary btn-block" >${getTranslation("view_history")}</button>`
}
return `
<div class="card w-full bg-neutral text-neutral-content">
<div class="card-body">
<p><strong>${System.buildEmployeeName(row.creator)} - ${System.formatTimestamp(row.createddate)}</strong></p>
<p></p>
<p><strong>${getTranslation("passed")}</strong>: <span class="badge badge-${row.passed ? "success" : "error"} gap-2 font-bold">${getTranslation(row.passed == 1 ? "yes": "no")}</span></p>
<p><strong>${getTranslation("new_mot")}</strong>: ${System.formatDate(row.new_mot) }</p>
<p><strong>${getTranslation("old_mot")}</strong>: ${System.formatDate(row.old_mot) }</p>
${contentHtml}
<table>
<thead>
<tr>
<th>${getTranslation("mot.lights")}</th>
<th>${getTranslation("mot.brakes_tyres")}</th>
<th>${getTranslation("mot.windows")}</th>
<th>${getTranslation("mot.others")}</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center"><span class="badge badge-${row.headlights ? "success" : "error"} gap-2 font-bold">${getTranslation("headlights")}</span></td>
<td class="text-center"><span class="badge badge-${row.front_brakes ? "success" : "error"} gap-2 font-bold">${getTranslation("front_brakes")}</span></td>
<td class="text-center"><span class="badge badge-${row.windscreen ? "success" : "error"} gap-2 font-bold">${getTranslation("windscreen")}</span></td>
<td class="text-center"><span class="badge badge-${row.horn ? "success" : "error"} gap-2 font-bold">${getTranslation("horn")}</span></td>
</tr>
<tr>
<td class="text-center"><span class="badge badge-${row.rear_lights ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_lights")}</span></td>
<td class="text-center"><span class="badge badge-${row.rear_brakes ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_brakes")}</span></td>
<td class="text-center"><span class="badge badge-${row.rear_window ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_window")}</span></td>
<td class="text-center"><span class="badge badge-${row.exhaust_system ? "success" : "error"} gap-2 font-bold">${getTranslation("exhaust_system")}</span></td>
</tr>
<tr>
<td class="text-center"><span class="badge badge-${row.indicators ? "success" : "error"} gap-2 font-bold">${getTranslation("indicators")}</span></td>
<td class="text-center"><span class="badge badge-${row.front_tyres ? "success" : "error"} gap-2 font-bold">${getTranslation("front_tyres")}</span></td>
<td class="text-center"><span class="badge badge-${row.side_windows ? "success" : "error"} gap-2 font-bold">${getTranslation("side_windows")}</span></td>
<td class="text-center"><span class="badge badge-${row.engine ? "success" : "error"} gap-2 font-bold">${getTranslation("engine")}</span></td>
</tr>
<tr>
<td></td>
<td class="text-center"><span class="badge badge-${row.rear_tyres ? "success" : "error"} gap-2 font-bold">${getTranslation("rear_tyres")}</span></td>
<td></td>
<td class="text-center"><span class="badge badge-${row.bodywork ? "success" : "error"} gap-2 font-bold">${getTranslation("bodywork")}</span></td>
</tr>
</tbody>
</table>
<p></p>
${bottomButton}
</div>
</div>
`;
}
static GetPassedState(){
return [
{id:0, "name" : getTranslation("mot.not_passed")},
{id:1, "name" : getTranslation("mot.passed")}
]
}
static GetEdit(data={}){
let passedOptions = this.GetPassedState();
let retval = {
"vehicle_id": {
"val" : data.vehicle_id ?? -1
,"type" : "hidden"
,"mandatory":true
,"isRow":true
},
"old_mot": {
"val" : data.vehicle_mot ?? -1
,"type" : "hidden"
,"mandatory":false
,"isRow":true
},
"mot_validity_num": {
"val" : mot_validity.num ?? 1
,"type" : "hidden"
,"mandatory":true
,"isRow":true
},
"mot_validity_type": {
"val" : (mot_validity.type ?? "w").toLowerCase()
,"type" : "hidden"
,"mandatory":true
,"isRow":true
}
,"divider_lights": {
"type" : "divider"
,"text" : getTranslation("mot.lights")
}
,"headlights": {
"val" : data.headlights ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"rear_lights": {
"val" : data.rear_lights ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"indicators": {
"val" : data.indicators ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"divider_brakes_tyres": {
"type" : "divider"
,"text" : getTranslation("mot.brakes_tyres")
}
,"front_brakes": {
"val" : data.front_brakes ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"rear_brakes": {
"val" : data.rear_brakes ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"front_tyres": {
"val" : data.front_tyres ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"rear_tyres": {
"val" : data.rear_tyres ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"divider_windows": {
"type" : "divider"
,"text" : getTranslation("mot.windows")
}
,"windscreen": {
"val" : data.windscreen ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"rear_window": {
"val" : data.rear_window ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"side_windows": {
"val" : data.side_windows ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"divider_others": {
"type" : "divider"
,"text" : getTranslation("mot.others")
}
,"horn": {
"val" : data.horn ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"exhaust_system": {
"val" : data.exhaust_system ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"engine": {
"val" : data.engine ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"bodywork": {
"val" : data.bodywork ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":passedOptions
}
,"divider_summary": {
"type" : "divider"
,"text" : getTranslation("mot.summary")
}
,"passed": {
"val" : data.passed ?? 1
,"type" : "dropdown"
,"mandatory":true
,"options":System.GetBooleanOptions()
,isRow: true
}
,"note": {
"val" : data.note ?? ""
,"type" : "textarea"
,"mandatory":false
,isRow: true
}
}
return retval;
}
}

View file

@ -0,0 +1,160 @@
class RegVehicle_NoMOT{
constructor(){
this.name = "regvehicle_nomot";
}
static allowView(){
return userrights.has("regvehicles.view");
}
static allowAddNew(){
return false;
}
static allowEdit(){
return userrights.has("regvehicles.edit");
}
static allowDelete(){
return false;
}
static GetColumns(){
return ["plate","veh_type","veh_model","owner","mot","state","id"]
}
static GetExtraForView(data){
let retval = {
top:"",
bottom:""
}
return retval;
}
static TableDataCreate(row, key){
if(key == "state"){
let badges = ""
return `
<td>
${badges}
</td>`;
}
else if(key == "id"){
return `
<td>
${Form.getViewButtonIcon(row[key], "regvehicle.view")}
${Form.getEditButtonIcon(row[key] , "regvehicle.edit", this.allowEdit())}
</td>`;
}
else if(key == "owner"){
let val = row[key];
if(val == ""){
val = getTranslation("unknown");
}
return `
<td>
${val}
</td>`;
}
else if(key == "mot"){
if(row[key] == ""){
return `<td></td>`;
}
if(new Date(row[key]) < new Date()){
return `
<td>
<div class="badge badge-error font-bold">${System.formatDate(row[key])}</div>
</td>`
;
}
else{
return `
<td>
<div class="badge badge-success font-bold">${System.formatDate(row[key])}</div>
</td>`
;
}
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
let filesOptions = [
{"id":-1, "name":getTranslation("unknown")}
,{"id":-2, "name":getTranslation("new_file"), "show_extra_field":true}
];
if(sync.isActive("files")){
filesOptions = [
{"id":-1, "name":getTranslation("unknown")}
];
}
filesOptions = [...filesOptions, ...data.extraData.files];
return {
"plate": {
"val" : data.plate ?? ""
,"type" : "text"
,"mandatory":true
}
,"owner": {
"val" : data.owner_id ?? "-1"
,"type" : "searchdropdown"
,"mandatory":false
,options:filesOptions
}
,"veh_type": {
"val" : data.veh_type ?? ""
,"type" : "text"
,"mandatory":false
}
,"mot": {
"val" : data.mot ?? ""
,"type" : "date"
,"mandatory":false
}
,"veh_model": {
"val" : data.veh_model ?? ""
,"type" : "text"
,"mandatory":false
}
,"color": {
"val" : data.color ?? ""
,"type" : "text"
,"mandatory":false
}
,"-": {
"type" : "divider"
}
,"others": {
"val" : data.others ?? ""
,"type" : "textarea"
,"isRow": true
,"mandatory":false
,autogrow: true
,rows:3
}
,"is_wanted": {
"val" : (data.is_wanted ?? false ? 1 : 0)
,"type" : (this.allowSetManhunt() ? "dropdown" : "hidden")
,"isRow": true
,"mandatory":false
,"hideInViewMode":true
,"options":System.GetBooleanOptions()
}
,"is_wanted_reason": {
"val" : data.is_wanted_reason ?? ""
,"type" : (this.allowSetManhunt() ? "text" : "hidden")
,"isRow": true
,"hideInViewMode":true
,"mandatory":false
}
}
}
}

View file

@ -0,0 +1,161 @@
class RegVehicle_PartAcceptance{
constructor(){
this.name = "regvehicle_partacceptance";
}
static GetCustomDestination(data, dest){
return (data.vehicle_id ?? "" != "" ? "regvehicle.view" : "regvehicle.overview");
}
static GetCustomDestID(data, destID){
return data.vehicle_id ?? destID;
}
static allowView(){
return userrights.has("regvehicles.view");
}
static allowAddNew(){
return userrights.has("regvehicles.edit");
}
static allowEdit(){
return userrights.has("regvehicles.edit");
}
static allowDelete(){
return userrights.has("regvehicles.edit");
}
static GetExtraForEdit(data){
let retval = {
top:"",
bottom:""
}
let gridData = data.extraData.tuning_options;
let html = "";
if(gridData.length == 0 || gridData.length == undefined){
html += `<h2>${getTranslation("no_data_found")}</h2>`;
retval.top = html;
return retval;
}
let columns = ["name", "price", "id"];
html = `<table class = "table table-compact w-full">`
for(let i=0; i<gridData.length;i++){
let row = gridData[i];
if(i==0){
html += `<thead>`;
html += `<tr>`;
for(let k=0; k<columns.length;k++){
html += `<th>${getTranslation(columns[k])}</th>`;
}
html += `</tr>`;
html += `</thead>`;
html += `<tbody>`;
}
html+=`<tr>`;
for(let j=0; j<columns.length;j++){
let key = columns[j];
if(key == "id"){
html += `
<td>
<input onchange="RegVehicle_PartAcceptance.CustomValidation(this)" data-price="${row.price}" type="checkbox" id="input-part_accepted_${row.id}" class="toggle toggle-success ignore-validation part-accepted" />
${Form.Hidden("input-part_accepted_price_" + row.id, row.price)}
</td>
`;
}
else if(key == "price"){
html += `
<td>
${System.FormatNumber(row[key])}
</td>
`;
}
else{
html += `
<td>
${row[key] ?? ""}
</td>
`;
}
}
html+=`</tr>`;
}
html += `
<tr>
<td class="text-right">
<strong>${getTranslation("sum_total")}:</strong>
</td>
<td id="part_acceptance_total_price" class="font-bold">
0
</td>
<td>
</td>
</tr>
`;
html += `</tbody>`;
html += `</table>`;
retval.top = html;
return retval;
}
static CustomValidation(){
let elements = Array.from(document.querySelectorAll(".part-accepted"));
let totalPrice = 0;
elements.forEach(function(checkbox){
let price = parseInt(checkbox.getAttribute("data-price"));
if(price > 0 && checkbox.checked){
totalPrice += price;
}
});
document.getElementById("part_acceptance_total_price").innerHTML = System.FormatNumber(totalPrice);
Form.validate();
}
static GetEdit(data={}){
let retval = {
"vehicle_id": {
"val" : data.vehicle_id ?? -1
,"type" : "hidden"
,"mandatory":true
,"isRow":true
},
"content": {
"val" : data.content ?? ""
,"type" : "textarea"
,"mandatory":true
,isRow:true
}
}
return retval;
}
}

View file

@ -0,0 +1,122 @@
class Trainings{
constructor(){
this.name = "trainings";
}
static allowAddNew(){
return userrights.has("trainings.edit")
}
static allowEdit(){
return userrights.has("trainings.edit")
}
static allowDelete(){
return userrights.has("trainings.delete")
}
static allowViewEmployeeTrainings(){
return userrights.has("trainingsemployees.view")
}
static GetExtraForView(data){
let retval = {
top:"",
bottom:""
}
if(this.allowViewEmployeeTrainings){
retval.bottom += `
<div class="collapse collapse-open border border-base-300 bg-base-100 rounded-box mt-4">
<div class="collapse-title text-xl font-medium">
${getTranslation("trainingsparticipants.overview")}
</div>
<div class="collapse-content">
${System.GetTable(TrainingsParticipants, data.extraData.participants)}
</div>
</div>
`;
}
return retval;
}
static GetColumns(){
return ["name","short_name","action","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getViewButtonIcon(row[key], this.name + ".view")}
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name, this.allowDelete())}
</td>`;
}
else if(key == "action"){
let content = "";
if(row.allow_self_entry){
let disabled = "";
if(row.entered > 0){
disabled = " disabled"
}
content = `<button type="button" class="btn btn-sm btn-primary" onclick="participateForTraining(${row["id"]})" ${disabled}>${getTranslation("participate")}</button>`
}
return `
<td>
${content}
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
for(let i=0; i<data.extraData.trainees.length; i++){
data.extraData.trainees[i].name = System.buildEmployeeName(data.extraData.trainees[i].name)
}
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
,"short_name": {
"val" : data.short_name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
}
,"content": {
"val" : data.content ?? ""
,"type" : "textarea"
,"isRow": true
,"mandatory":true
,autogrow: true
,rows:3
}
,"allow_self_entry": {
"val" : data.allow_self_entry ?? ""
,"type" : "dropdown"
,"mandatory":true
,options:System.GetBooleanOptions()
}
,"min_rank_id": {
"val" : data.min_rank_id ?? ""
,"type" : "dropdown"
,"mandatory":true
,options:System.getRankOptions()
}
,"trainee": {
"val" : data.trainee ?? ""
,"type" : "dropdown"
,"isRow": true
,"mandatory":true
,options:data.extraData.trainees
}
}
}
}

View file

@ -0,0 +1,90 @@
class TrainingsParticipants{
constructor(){
this.name = "trainingsparticipants";
}
static allowEditEmployeeTrainings(){
return userrights.has("trainingsemployees.edit")
}
static GetColumns(){
return ["name","action","passed","id"]
}
static TableDataCreate(row, key){
if(key == "id"){
if(row.passed > -1){
let btn = ``;
if(this.allowEditEmployeeTrainings()){
btn = `
<button type="button" class="btn btn-sm btn-error" onclick="trainingPassed(-1, '${row["employee_id"]}', '${row["training_id"]}')">
<i class="fa-solid fa-delete-left"></i>
</button>
`;
}
return `
<td>
${btn}
</td>`;
}
else{
return `<td></td>`;
}
}
else if(key == "action"){
let disabled = "";
let content = ``;
if(row.participate > 0){
disabled = " disabled"
}
if(this.allowEditEmployeeTrainings()){
content = `<button type="button" class="btn btn-sm btn-primary" onclick="participateForTraining(${row["training_id"]}, '${row["employee_id"]}')" ${disabled}>${getTranslation("participate")}</button>`
}
return `
<td>
${content}
</td>`;
}
else if(key == "passed"){
let content = "";
if(row[key] == -1 && this.allowEditEmployeeTrainings()){
content = `
<button type="button" class="btn btn-sm btn-error" onclick="trainingPassed(0, '${row["employee_id"]}', '${row["training_id"]}')">
<i class="fa-solid fa-xmark"></i>
</button>
<button type="button" class="btn btn-sm btn-success" onclick="trainingPassed(1, '${row["employee_id"]}', '${row["training_id"]}')">
<i class="fa-solid fa-check"></i>
</button>`
;
}
else if(row[key] == 0){
content = `<i class="fa-solid fa-xmark text-error"></i>`;
}
else if(row[key] == 1){
content = `<i class="fa-solid fa-check text-success"></i>`;
}
return `
<td>
${content}
</td>`;
}
else if(key == "name"){
return `
<td>
${System.buildEmployeeName(row[key])}
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
}

View file

@ -0,0 +1,53 @@
class TuningOptions{
constructor(){
this.name = "tuningoptions";
}
static GetColumns(){
return ["name","price","id"]
}
static allowAddNew(){
return userrights.has("parts_acceptance.edit")
}
static allowEdit(){
return userrights.has("parts_acceptance.edit")
}
static allowDelete(){
return userrights.has("parts_acceptance.delete")
}
static TableDataCreate(row, key){
if(key == "id"){
return `
<td>
${Form.getEditButtonIcon(row[key] , this.name + ".edit", this.allowEdit())}
${Form.getDeleteButtonIcon(row[key], this.name, this.allowDelete())}
</td>`;
}
else if(key == "price"){
return `
<td>
${System.FormatNumber(row[key])}
</td>`;
}
else{
return `<td>${row[key]}</td>`;
}
}
static GetEdit(data={}){
return {
"name": {
"val" : data.name ?? ""
,"type" : "text"
,"isRow": true
,"mandatory":true
},
"price": {
"val" : data.price ?? ""
,"type" : "number"
,"isRow": true
,"mandatory":true
}
}
}
}

View file

@ -0,0 +1,698 @@
let locale = 'en';
let navMenu;
let isInit = true;
let userrights;
let lastjob;
let lastjobgrade;
let currentSystem;
let job_grades = [];
let sync;
let useWeaponRegister = true;
let useMyImpound = true;
let useMySpeedcam = true;
let mot_validity = {}
let globalFileSearcher = new FileSearch()
const coreFile = "myMDT_core";
(function(){
document.onkeydown = function(e){
if(e.key.toLowerCase() == "escape"){
closeWin();
}
}
document.getElementById("delete-modal-delete").onclick=function(){
let id = document.getElementById("delete-modal").getAttribute("data-id");
let src = document.getElementById("delete-modal").getAttribute("data-delete-destination");
deleteData(src, id);
}
window.addEventListener('message', function( event ) {
if(event.data.message == "show"){
document.documentElement.setAttribute("data-theme",event.data.theme)
useWeaponRegister = event.data.useWeaponRegister
useMyImpound = event.data.useMyImpound
useMySpeedcam = event.data.useMySpeedcam
mot_validity = event.data.mot_validity
sync=new Sync(event.data.Sync)
locale = event.data.locale
document.getElementById("main_navigation_copname").innerHTML = System.buildEmployeeName(event.data.username);
document.getElementById("main").style.display = "";
document.getElementById("radiostates").style.display = "none";
userrights = new Rights(event.data.rights);
job_grades = event.data.job_grades;
if(lastjob != event.data.job || lastjobgrade != event.data.jobgrade){
isInit = true;
lastjob = event.data.job;
lastjobgrade = event.data.jobgrade;
}
currentSystem = event.data.currentsystem;
System.SetColor(event.data.currentsystem);
navMenu = new NavMenu(navigation, event.data.currentsystem);
Array.from(document.querySelectorAll(".nav-checkrights")).forEach(function(item){
if(item.getAttribute("data-rightkey") != ""){
if(userrights.has(item.getAttribute("data-rightkey"))){
item.style.display = "";
}
else{
item.style.display = "none";
}
if (item.id == "menuItem-li-regweapons" && !useWeaponRegister){
item.style.display = "none";
}
if (item.id == "menuItem-li-speedcamsmobile" && !useMySpeedcam){
item.style.display = "none";
}
if (item.id == "menuItem-li-speedcamsprofit" && !useMySpeedcam){
item.style.display = "none";
}
if (item.id == "menuItem-li-regvehicleimpounded" && !useMyImpound){
item.style.display = "none";
}
}
});
Array.from(document.querySelectorAll(".nav-checkfor-nextelements")).forEach(function(item){
let itemsVisible = false;
Array.from(document.querySelectorAll(".divier-" + item.getAttribute("data-tkey"))).forEach(function(child){
if(child.style.display != "none"){
itemsVisible = true;
}
});
if(!itemsVisible){
item.style.display="none";
}
else{
item.style.display="";
}
});
if(isInit){
loadPage("dashboard.dataload",-1);
isInit=false;
}
}
else if(event.data.message == "show-radio-states"){
locale = event.data.locale
document.documentElement.setAttribute("data-theme",event.data.theme)
document.getElementById("radiostates").style.display = "block";
document.getElementById("main").style.display = "none";
let radioDetails = System.getRadioState(event.data.curstate.vehicle, event.data.curstate.person);
let radioHud = new RadioHud();
radioHud.SetLocation(event.data.config.Position);
radioHud.SetExtraMargins(event.data.config.extraMargins);
radioHud.DrawInfo(radioDetails);
radioHud.DrawButtons(event.data.data, radioDetails.radio_id, radioDetails.radio_default);
}
});
fetch(`http://${location.host}/NuiReady`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({})
}).then((response) => {
response.json().then(function(retobj){});
});
})();
function handleMenuItemClick(item){
navMenu.setItemActive(item);
showLoading();
loadPage(item.getAttribute("data-destination"), -1, item.getAttribute("data-forceReload"));
}
function showLoading(){
document.getElementById("currentpage-content").innerHTML = `
Loading..
<progress class="progress progress-accent w-100 "></progress>
`;
}
function setCurrentPageHeadLine(text){
document.getElementById("current_page_name").innerHTML = text;
}
function changeDestination(input){
if(input == "pricelist.dataload"){
input = "pricelistgroups.dataload"
}
return input;
}
function loadPage(destination, id, force = "false", staticData={}){
destination = changeDestination(destination);
document.body.setAttribute("data-quicksearch","")
if(destination.endsWith(".dataload") || destination.endsWith(".overview")){
force = "true";
if(destination.endsWith(".overview")){
document.body.setAttribute("data-quicksearch",document.getElementById("global-searchbar") ? document.getElementById("global-searchbar").value.trim() : "")
}
}
if(destination != document.body.getAttribute("data-lastdest")){
resetPageNum();
document.body.setAttribute("data-quicksearch","");
}
else if(id != document.body.getAttribute("data-last-id")){
resetPageNum();
}
document.body.setAttribute("data-lastdest", destination);
document.body.setAttribute("data-last-id", id);
document.body.setAttribute("data-force-load", force);
setActiveItem(destination);
setCurrentPageHeadLine(getTranslation(destination));
showLoading();
if(id == -1 && force == "false" && destination!="trainings.add" && destination!="criminalcomplaint.add" && destination!="regvehicle.add" && destination!="regweapons.add"){
if(destination.endsWith(".view") || destination.endsWith(".edit") || destination.endsWith(".add")){
let loadtype = destination.replace(".view","").replace(".edit","").replace(".add","");
ShowDetails(destination, loadtype, staticData);
}
}
else{
loadData(destination, id)
}
}
function reload(){
loadPage(document.body.getAttribute("data-lastdest"),document.body.getAttribute("data-last-id"),document.body.getAttribute("data-force-load") )
}
function setActiveItem(destination){
let type = destination.replace(".overview","").replace(".dataload","").replace(".add","").replace(".edit","").replace(".view","");
let item;
if(destination == "trainings.add" || destination == "missionreport.add"){
type += ".add"
}
if(document.getElementById("menuitem-" + type)){
item = document.getElementById("menuitem-" + type);
}
if(item){
navMenu.setItemActive(item);
}
}
function ShowCustom(destination, loadtype, retobj){
let _class = System.getClassByName(loadtype);
if(_class !== null){
_class.CreateCustom(retobj);
}
else{
console.log("no class defined for " + loadtype);
}
}
function ShowOverview(loadtype, data){
let _class = System.getClassByName(loadtype);
if(_class !== null){
System.CreateOverView(
_class
,data
);
}
else{
console.log("no overview defined for " + loadtype)
}
}
function ShowDetails(destination, loadtype = "", data = {}){
let isViewMode = destination.endsWith(".view");
loadtype = loadtype.toLocaleLowerCase();
let _class = System.getClassByName(loadtype);
if(_class !== null){
let dest = "overview";
if (_class.hasOwnProperty("isCustom") && _class.isCustom()) {
dest = "dataload";
}
System.CreateEdit(
_class
,data.data
,isViewMode
,destination
,loadtype + "." + dest
);
}
else{
console.log("no detailsview defined for " + loadtype)
}
}
async function loadData(destination, id){
destination = changeDestination(destination);
setActiveItem(destination.toLowerCase());
setCurrentPageHeadLine(getTranslation(destination.toLowerCase()));
showLoading();
destination = destination.toLowerCase()
let loadDest = destination;
let loadinfo = destination;
if(destination.endsWith(".overview")){
loadDest = "overview";
loadinfo = destination.replace(".overview","");
}
else if(destination.endsWith(".view") || destination.endsWith(".edit") || destination.endsWith(".add")){
loadDest = "loadDetails";
loadinfo = destination.replace(".view","");
loadinfo = loadinfo.replace(".edit","");
loadinfo = loadinfo.replace(".add","");
}
else{
loadDest = "custom"
loadinfo = destination.replace(".dataload","");
}
let data;
try{
const response = await fetch(`http://${location.host}/${loadDest}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"pageNum": 1*((document.body.getAttribute("data-cur-pageNum")) ?? 1)-1,
"id": id,
"quicksearch": document.body.getAttribute("data-quicksearch"),
"load_info": loadinfo
})
});
data = await response.json();
}
catch(error){
console.log('Error fetching data:', error);
console.log(`--------------------------------------------`)
console.log(`info : http://${location.host}/${loadDest}`)
console.log(`pageNum : ${1*((document.body.getAttribute("data-cur-pageNum")) ?? 1)-1}`)
console.log(`id : ${id}`)
console.log(`load_info : ${loadinfo}`)
console.log(`quicksearch : ${quicksearch}`)
console.log(`--------------------------------------------`)
}
if(data){
if(loadDest == "overview"){
ShowOverview(loadinfo, data);
}
else if(loadDest == "loadDetails"){
ShowDetails(destination, loadinfo, data);
}
else if(loadDest == "custom"){
ShowCustom(destination, loadinfo, data);
}
}
}
function sendDataToAPI(source, destination, id, destination_id, formdata){
fetch(`http://${location.host}/save-data`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"source": source,
"id": id,
"formData": formdata,
"source": source.toLowerCase()
})
}).then((response) => {
response.json().then(function(retobj){
loadPage(destination.toLowerCase(), destination_id);
});
});
}
function deleteData(source, id){
fetch(`http://${location.host}/delete-data`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"id": id,
"source": source.toLowerCase()
})
}).then((response) => {
response.json().then(function(retobj){
document.getElementById("delete-modal").checked = false;
reload();
});
});
}
function saveData(source, destination, id, destination_id){
sendDataToAPI(source, destination, id, destination_id, Form.getFormData())
}
function finishManhunt(source, id){
fetch(`http://${location.host}/finish-manhunt`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"source": source,
"id": id,
"source": source.toLowerCase()
})
}).then((response) => {
response.json().then(function(retobj){
reload();
});
});
}
async function takeControlCentre(isReset){
let data;
try{
const response = await fetch(`http://${location.host}/takeControlCentre`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"isReset": isReset
})
});
data = await response.json();
reload();
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/takeControlCentre?isReset=${isReset}`)
}
}
async function SetRadioState(newID, destinationPage){
let data;
try{
const response = await fetch(`http://${location.host}/SetRadioState`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"new_state": newID
})
});
data = await response.json();
loadPage(destinationPage,-1)
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/SetRadioState?new_state=${newID}`)
}
}
async function SetRadioStateShortcut(newID){
let data;
try{
const response = await fetch(`http://${location.host}/SetRadioState`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"new_state": newID
})
});
data = await response.json();
closeWin()
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/SetRadioState?new_state=${newID}`)
}
}
async function SetVehicle(newID, destinationPage){
let data;
try{
const response = await fetch(`http://${location.host}/SetVehicle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"new_state": newID
})
});
data = await response.json();
loadPage(destinationPage, -1);
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/SetVehicle?new_state=${newID}`)
console.log(`destinationpage : ${destinationPage}`)
}
}
async function changeDataInColumn(loadType, columnName, id, new_value){
let formdata = {};
formdata[columnName] = new_value
sendDataToAPI(loadType, document.body.getAttribute("data-lastdest") ,id, document.body.getAttribute("data-last-id"), formdata)
}
async function EmployeeSuspend(loadType, employeeid, value){
let data;
try{
const response = await fetch(`http://${coreFile}/employee_suspend`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"id": employeeid
,"value": value
})
});
data = await response.json();
loadPage(loadType, -1);
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/employee_suspend?id=${employeeid}&value=${value}`)
}
}
async function resetVehicle(vehicleId){
let data;
try{
const response = await fetch(`http://${location.host}/resetVehicle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"id": vehicleId
})
});
data = await response.json();
loadPage("controlcentre.dataload".toLowerCase(), -1);
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/resetVehicle?id=${vehicleId}`)
}
}
async function resetEmployeeRadio(employeeid){
let data;
try{
const response = await fetch(`http://${location.host}/resetEmployeeRadio`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
"id": employeeid
})
});
data = await response.json();
loadPage("controlcentre.dataload".toLowerCase(), -1);
}
catch(error){
console.log('Error fetching data:', error);
console.log(`info : http://${location.host}/resetEmployeeRadio?id=${employeeid}`)
}
}
async function closeWin(){
let data;
try{
const response = await fetch(`http://${location.host}/closeWindow`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({})
});
data = await response.json();
document.getElementById("main").style.display = "none";
document.getElementById("radiostates").style.display = "none";
}
catch(error){
console.log('Error while closing');
}
}
async function participateForTraining(trainingId, employee_id = null, fromEmployee = false){
let formdata = {};
formdata.training_id = trainingId
formdata.employee_id = employee_id
let destination = "trainings.overview";
let destId = -1;
if(employee_id !== null){
destination = "trainings.view";
destId = trainingId;
}
if(!fromEmployee){
sendDataToAPI("trainingsemployees", destination,-1, destId, formdata);
}
else{
sendDataToAPI("employeestraining", "employeestraining.dataload",-1, employee_id, formdata)
}
}
async function trainingPassed(passed, employee_id, training_id, fromEmployee = false){
let formdata = {};
formdata.training_id = training_id
formdata.employee_id = employee_id
formdata.passed = passed
if(!fromEmployee){
sendDataToAPI("trainingsemployees", "trainings.view",-1, training_id, formdata)
}
else{
sendDataToAPI("employeestraining", "employeestraining.dataload",-1, employee_id, formdata)
}
}
async function GenerateRoute(buttonEl){
let data;
let coords = buttonEl.getAttribute("data-entering")
let parsed = JSON.parse(coords);
try{
const response = await fetch(`http://${location.host}/GenerateRoute`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
x: parsed.x,
y: parsed.y
})
});
data = await response.json();
closeWin();
}
catch(error){
console.log('Error while set route');
}
}
async function SearchFiles(htmlEl){
let data;
try{
const response = await fetch(`http://${location.host}/filterFilesDropdown`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
id: htmlEl.getAttribute("data-parentid"),
search: htmlEl.value
})
});
data = await response.json();
}
catch(error){
console.log('Error while set SearchFiles');
}
Form.refillFilesDropDown(htmlEl, data)
}
function resetPageNum(){
document.body.setAttribute("data-cur-pageNum",1);
}

View file

@ -0,0 +1,730 @@
class System{
static Files(){
return Files;
}
static RegVehicle(){
return RegVehicle;
}
static RegVehicle_Damage(){
return RegVehicle_Damage;
}
static RegVehicle_MOT(){
return RegVehicle_MOT;
}
static RegVehicle_DocHead(){
return RegVehicle_DocHead;
}
static RegVehicle_DocHead_History(){
return RegVehicle_DocHead_History;
}
static RegVehicle_DocHead_Details(){
return RegVehicle_DocHead_Details;
}
static RegVehicle_NoMOT(){
return RegVehicle_NoMOT;
}
static RegVehicle_PartAcceptance(){
return RegVehicle_PartAcceptance;
}
static ControlCentre(){
return ControlCentre;
}
static Employees(){
return Employees;
}
static EmployeesEntry(){
return EmployeesEntry;
}
static RankManagement(){
return RankManagement;
}
static RankManagementRights(){
return RankManagementRights;
}
static Trainings(){
return Trainings;
}
static TuningOptions(){
return TuningOptions;
}
static MissionReport(){
return MissionReport;
}
static RadioState(){
return RadioState;
}
static EmergencyVehicle(){
return EmergencyVehicle;
}
static PriceListGroups(){
return PriceListGroups;
}
static Pricelist(){
return Pricelist;
}
static EmployeeVehicle(){
return EmployeeVehicle;
}
static EmergencyVehicleRadio(){
return EmergencyVehicleRadio;
}
static EmployeeRadio(){
return EmployeeRadio;
}
static EmployeesTraining(){
return EmployeesTraining;
}
static Dashboard(){
return Dashboard;
}
static Notes(){
return Notes;
}
static getServiceNo(str){
if(str){
return str.toLowerCase().replace(new RegExp("[a-z]","gm"),"").replace(":","").substr(1,6)
}
else{
return "error..";
}
}
static GetFgColorByBgColor(bgColor){
let colors = this.GetColors();
if(colors[bgColor]){
return colors[bgColor].fgColor;
}
else{
return "#000000";
}
}
static ToggleDamage(sender){
//todo
let fieldId = sender.id.replace("injury-","input-");
let inputEl = document.getElementById(fieldId);
if(inputEl){
if(sender.querySelector("path").classList.contains("active")){
sender.querySelector("path").classList.remove("active");
inputEl.value = 0;
}
else{
sender.querySelector("path").classList.add("active");
inputEl.value = 1;
}
Form.validate();
}
else{
console.log("no field found for " + fieldId);
}
}
static GetComplaintByID(id){
return this.getComplaintStates()[id] ?? {}
}
static getFirstName(input){
if(input == ""){
return "";
}
let parsed = JSON.parse(input);
return parsed.firstname
}
static getLastName(input){
if(input == ""){
return "";
}
let parsed = JSON.parse(input);
return parsed.lastname
}
static getJobGrade(input){
if(input === null || input == ""){
return 0;
}
let parsed = JSON.parse(input);
return parsed.grade.level
}
static buildEmployeeName(input){
if(input == null){
return `<s>${getTranslation("employee.unknown")}</s>`;
}
if(input == ""){
return "";
}
let JSONS = input.split("<SEPERATOR>")
let retval = "";
for(let i=0; i<JSONS.length; i++){
let valueseperator = JSONS[i].split("<VALSEPERATOR>");
let parsed = {};
let validJson = false;
let identifier = valueseperator[1] ?? '';
let serviceno = valueseperator[2] ?? '';
let retServiceno = serviceno;
if(retServiceno === '' && identifier !== ''){
retServiceno = System.getServiceNo(identifier);
}
try{
parsed = JSON.parse(valueseperator[0]);
validJson = true;
}
catch(e){
}
if(!validJson){
let json = valueseperator[0].replace('{','').replace('}','').split(",");
let temp = {};
for(let i=0; i<json.length; i++){
let splitted = json[i].split(":");
parsed[splitted[0]] = splitted[1];
}
}
retval += (retval == "" ? "" : "<br> ") + (retServiceno == '' ? '' : retServiceno + ' - ') + parsed.firstname + " " + parsed.lastname;
}
return retval;
}
static SetColor(sys){
let colors = {
mechanic : "warning",
default : "accent"
}
let el = document.getElementById("main_navigation_copname");
if(!colors[sys]){
sys = "default";
}
Object.keys(colors).forEach(function(job){
if(el.classList.contains("bg-" + colors[job])){
el.classList.remove("bg-" + colors[job]);
el.classList.remove("text-" + colors[job] + "-content");
}
});
el.classList.add("bg-" + colors[sys] ?? "ghost");
el.classList.add("text-" + colors[sys] + "-content" ?? "text-ghost-content");
}
static getRadioState(vehicleData, persondata){
let retval = {
vehicle:null,
radio:null,
radio_default:getTranslation("emergency_vehicles_no_radio"),
radio_id:-1
}
if(vehicleData.length == 0){
if(persondata[0] !== null && persondata[0] !== undefined && persondata[0].state_name !== undefined && persondata[0].state_name !== ""){
retval.radio = persondata[0].state_name
retval.radio_id = persondata[0].state_id
}
}
else{
retval.vehicle = vehicleData[0].vehname_short + " - " + vehicleData[0].vehname
if(vehicleData[0].state_name !== undefined && vehicleData[0].state_name !== ""){
retval.radio = vehicleData[0].state_name
retval.radio_id = vehicleData[0].state_id
}
}
return retval;
}
static getDate(){
let date = new Date();
let yyyy = date.getFullYear().toString();
let MM = this.padNum(date.getMonth() + 1,2);
let dd = this.padNum(date.getDate(), 2);
let hh = this.padNum(date.getHours(), 2);
let mm = this.padNum(date.getMinutes(), 2)
let ss = this.padNum(date.getSeconds(), 2)
return yyyy + MM + dd + "-" + hh + mm + ss;
}
static padNum(num, length){
var str = '' + num;
while (str.length < length) {
str = '0' + str;
}
return str;
}
static formatDate(input){
if(input == ""){
return "";
}
if(locale == "de"){
let temp = input.split("-");
return `${temp[2]}.${temp[1]}.${temp[0]}`
}
else{
return input;
}
}
static formatTimestamp(input){
if(input == ""){
return "";
}
if(locale == "de"){
let splitted = input.split(" ");
let datesplit = splitted[0].split("-");
let timesplit = splitted[1].split(":");
return `${datesplit[2]}.${datesplit[1]}.${datesplit[0]} ${timesplit[0]}:${timesplit[1]}`
}
else{
let splitted = input.split(" ");
let datesplit = splitted[0].split("-");
let timesplit = splitted[1].split(":");
return `${splitted[0]} ${timesplit[0]}:${timesplit[1]}`
}
}
static getEmployeeEntryTypes(){
return {
"0" : {name:getTranslation("note"), "color":"info"},
"1" : {name:getTranslation("positiv"), "color":"success"},
"2" : {name:getTranslation("negative"), "color":"error"}
}
}
static getEmployeeEntryTypesOptions(){
let retval = [];
let json = this.getEmployeeEntryTypes();
Object.keys(json).forEach(function(key){
retval.push({"id": key, "name":json[key].name })
});
return retval;
}
static getFileEntryTypes(){
return {
"0" : {name:getTranslation("fine_crime"), "color":"error"},
"1" : {name:getTranslation("positiv"), "color":"success"},
"2" : {name:getTranslation("neutral"), "color":"info"}
}
}
static getRankOptions(){
let retval = [];
Object.keys(job_grades).forEach(function(i){
retval.push({"id": job_grades[i].grade, "name":job_grades[i].label})
})
return retval;
}
static getLabelByRank(in_rank_id){
let retval = "unknown";
Object.keys(job_grades).forEach(function(i){
if(job_grades[i].grade == in_rank_id){
retval = job_grades[i].label;
}
})
return retval;
}
static getFileEntryTypesOptions(){
let retval = [];
let json = this.getFileEntryTypes();
Object.keys(json).forEach(function(key){
retval.push({"id": key, "name":json[key].name })
});
return retval;
}
static GetCompaintStateOptions(){
let retval = [];
let json = this.getComplaintStates();
Object.keys(json).forEach(function(key){
retval.push({"id": key, "name":json[key].name })
});
return retval;
}
static getComplaintStates(){
return {
"0" : {name:getTranslation("state_open"), "color":"badge-error"},
"1" : {name:getTranslation("state_inprogress"), "color":"badge-warning"},
"2" : {name:getTranslation("state_closed"), "color":"badge-success"}
}
}
static GetColors(){
return {
"#008000": {
bgcolor : "#008000"
,fgColor : "#FFFFFF"
,name : getTranslation("color-green")
},
"#FF0000": {
bgcolor : "#FF0000"
,fgColor : "#FFFFFF"
,name : getTranslation("color-red")
},
"#0000FF": {
bgcolor : "#0000FF"
,fgColor : "#FFFFFF"
,name : getTranslation("color-blue")
},
"#ffa500": {
bgcolor : "#ffa500"
,fgColor : "#000000"
,name : getTranslation("color-orange")
},
"#ffc0cb": {
bgcolor : "#ffc0cb"
,fgColor : "#000000"
,name : getTranslation("color-pink")
},
"#888888": {
bgcolor : "#888888"
,fgColor : "#000000"
,name : getTranslation("color-gray")
},
"#880000": {
bgcolor : "#880000"
,fgColor : "#FFFFFF"
,name : getTranslation("color-dark_red")
},
"#000000": {
bgcolor : "#000000"
,fgColor : "#FFFFFF"
,name : getTranslation("color-black")
}
}
}
static GetColorOptions(){
let json = this.GetColors();
let options = [];
Object.keys(json).forEach(function(key){
options.push({"id": key, "name":json[key].name })
});
return options;
}
static getClassByName(name){
let _classes = {
"files": this.Files()
,"regvehicle": this.RegVehicle()
,"regvehicle_damage": this.RegVehicle_Damage()
,"regvehicle_mot": this.RegVehicle_MOT()
,"regvehicle_dochead": this.RegVehicle_DocHead()
,"regvehicle_dochead_history": this.RegVehicle_DocHead_History()
,"regvehicle_dochead_details": this.RegVehicle_DocHead_Details()
,"regvehicle_partacceptance": this.RegVehicle_PartAcceptance()
,"regvehicle_nomot": this.RegVehicle_NoMOT()
,"radiostate": this.RadioState()
,"emergencyvehicle": this.EmergencyVehicle()
,"trainings": this.Trainings()
,"missionreport": this.MissionReport()
,"employees": this.Employees()
,"employeesentry": this.EmployeesEntry()
,"employeestraining": this.EmployeesTraining()
,"pricelistgroups": this.PriceListGroups()
,"pricelist": this.Pricelist()
,"controlcentre": this.ControlCentre()
,"tuningoptions": this.TuningOptions()
,"employeevehicle": this.EmployeeVehicle()
,"employeeradio": this.EmployeeRadio()
,"emergencyvehicleradio": this.EmergencyVehicleRadio()
,"dashboard": this.Dashboard()
,"notes": this.Notes()
,"rankmanagement": this.RankManagement()
,"rankmanagementrights": this.RankManagementRights()
}
if(_classes[name]){
return _classes[name];
}
else{
return null;
}
}
static GetBooleanOptions(){
return [
{id:0, "name" : getTranslation("no")},
{id:1, "name" : getTranslation("yes")}
]
}
static GetTable(_class, gridData, additionalData = null){
if(gridData.length == 0 || gridData.length == undefined){
return `<h2>${getTranslation("no_data_found")}</h2>`;
}
let columns = _class.GetColumns(additionalData);
let html = `<table class = "table table-compact w-full">`
for(let i=0; i<gridData.length;i++){
if(i==0){
html += `<thead>`;
html += `<tr>`;
for(let k=0; k<columns.length;k++){
html += `<th>${getTranslation(columns[k])}</th>`;
}
html += `</tr>`;
html += `</thead>`;
html += `<tbody>`;
}
html+=`<tr>`;
for(let j=0; j<columns.length;j++){
let key = columns[j];
html+= _class.TableDataCreate(gridData[i], key, additionalData)
}
html+=`</tr>`;
}
html += `</tbody>`;
html += `</table>`;
return html;
}
static CreateOverView(_class, data={}){
let html = ``;
let gridData = data.data;
let maxData = data.count;
let maxPages = data.count / 10;
let curPage = data.pageNum ?? 0;
let withoutLimit = data.noLimit;
let extraHtml = {}
let allowAddNew = true;
if (_class.hasOwnProperty("allowAddNew")) {
allowAddNew = _class.allowAddNew();
}
if (_class.hasOwnProperty("GetExtraForOverview")) {
extraHtml = _class.GetExtraForOverview(data.xtraData);
}
html = extraHtml.top ?? "";
html += Form.overviewHeadline(_class.name.toLowerCase() + ".add", !withoutLimit, allowAddNew);
html += `<div class="card w-full p-2 bg-base-100 shadow-xl mt-2 mb-6 " >`
html += `<div class="h-full w-full bg-base-100" >`
html += `<div class="overflow-x-auto w-full" >`
html += this.GetTable(_class, gridData);
html += `</div>`
html += `</div>`
html += `</div>`
if(!withoutLimit){
html += Form.getPageChanger(curPage,maxPages);
}
document.getElementById("currentpage-content").innerHTML = html;
Form.initTableButtons();
Form.initPageChange();
}
static CreateEdit(_class, data = {}, readMode = false, src = "", dest = "", destid = -1){
let inputData = {};
let initTableButtons = false
if (_class.hasOwnProperty("GetEdit")) {
inputData = _class.GetEdit(data);
}
if (_class.hasOwnProperty("GetCustomDestID")) {
destid = _class.GetCustomDestID(data, destid);
}
if (_class.hasOwnProperty("GetCustomDestination")) {
dest = _class.GetCustomDestination(data, dest);
}
let html = ``;
let groupInit = false;
Object.keys(inputData).forEach(key=>{
if(inputData[key].hideInViewMode != true && readMode || (!readMode && inputData[key].hideInEdit != true)){
if(inputData[key].isRow != true && inputData[key].type != "divider" && !groupInit){
html += `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
`;
groupInit=true;
}
else if((inputData[key].isRow == true || inputData[key].type == "divider") && groupInit ){
html += `
</div>
`;
groupInit=false;
}
if(inputData[key].type === "text"){
html += Form.TextBox(inputData[key].mandatory, key, inputData[key].val);
}
else if(inputData[key].type === "hidden"){
html += Form.Hidden(key, inputData[key].val);
}
else if(inputData[key].type === "date"){
html += Form.DateField(inputData[key].mandatory, key, inputData[key].val);
}
else if(inputData[key].type === "number"){
html += Form.NumberField(inputData[key].mandatory, key, inputData[key].val);
}
else if(inputData[key].type === "textarea"){
html += Form.TextArea(inputData[key].mandatory, key, inputData[key].val, inputData[key].autogrow, inputData[key].rows);
}
else if(inputData[key].type === "dropdown"){
html += Form.Combobox(inputData[key].mandatory, key, inputData[key].val, inputData[key].options);
}
else if(inputData[key].type === "searchdropdown"){
//html += Form.SearchCombobox("", "", 1, "");
html += Form.SearchCombobox(inputData[key].mandatory, key, inputData[key].val, inputData[key].options, data.id ?? -1);
}
else if(inputData[key].type === "divider"){
html += Form.Divier(inputData[key].text);
}
}
});
if(groupInit){
html+=`</div>`;
}
if(!readMode){
let extraHtml = {}
if (_class.hasOwnProperty("GetExtraForEdit")) {
extraHtml = _class.GetExtraForEdit(data);
}
if(extraHtml.bottom!== undefined && extraHtml.bottom!= null && extraHtml.bottom != ""){
html += extraHtml.bottom;
}
html += `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 pt-6">
${Form.cancelButton(src, dest, destid)}
${Form.saveButton(_class.name, dest, data.id ?? -1, destid)}
</div">
`;
if(extraHtml.top!== undefined && extraHtml.top!= null && extraHtml.top != ""){
html = extraHtml.top + html;
}
}
else{
let extraHtml = {}
if (_class.hasOwnProperty("GetExtraForView")) {
extraHtml = _class.GetExtraForView(data);
}
if(extraHtml.initTableButtons == true){
initTableButtons = true;
}
let editDest = src.replace(".view",".edit")
let allowEdit = true;
if (_class.hasOwnProperty("allowEdit")) {
allowEdit = _class.allowEdit();
}
let tempTop = Form.BackEditBtn(dest, editDest, data.id ?? destid, allowEdit);
if(extraHtml.top!== undefined && extraHtml.top!= null && extraHtml.top != ""){
tempTop += extraHtml.top;
}
html = tempTop + html;
if(extraHtml.bottom!== undefined && extraHtml.bottom!= null && extraHtml.bottom != ""){
html += extraHtml.bottom;
}
}
document.getElementById("currentpage-content").innerHTML = html;
if(!readMode){
Form.initSearchComboboxes();
Form.initValidation();
Form.initSaveButtons();
if(Object.keys(inputData).length == 1){
Form.validate();
}
}
else{
if(initTableButtons){
Form.initTableButtons();
}
Form.disableAll();
Form.initViewModeTopButtons();
}
Form.TextAreaGrow();
}
static FormatNumber(input){
input = parseInt(input);
return input.toLocaleString(locale == 'de' ? "de-DE" : "en-US")
}
}