Merge pull request #65 from danieldupriest/new-report-form
New report form
This commit is contained in:
commit
16dbd04ef4
3 changed files with 175 additions and 46 deletions
|
@ -62,7 +62,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal" id="editReportModal" tabindex="-1" role="dialog">
|
<div class="modal fade" id="editReportModal" tabindex="-1" role="dialog">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -71,7 +71,13 @@
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body" id="editReportModalBody">
|
||||||
|
<div class="text-center">
|
||||||
|
<i class="fas fa-spinner fa-3x fa-spin"></i>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h5>Loading Report ...</h5>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-danger">Delete Report</button>
|
<button type="button" class="btn btn-danger">Delete Report</button>
|
||||||
|
@ -81,7 +87,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal" id="viewReportModal" tabindex="-1" role="dialog">
|
<div class="modal fade" id="viewReportModal" tabindex="-1" role="dialog">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -91,6 +97,12 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-view">
|
<div class="modal-view">
|
||||||
|
<div class="text-center">
|
||||||
|
<i class="fas fa-spinner fa-3x fa-spin"></i>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h5>Loading Report ...</h5>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
|
const reportType = {
|
||||||
|
NEW : 1,
|
||||||
|
EDIT : 2,
|
||||||
|
VIEW : 3
|
||||||
|
};
|
||||||
|
|
||||||
// Hack to change endpoint url
|
// Hack to change endpoint url
|
||||||
function getEndpointDomain() {
|
function getEndpointDomain() {
|
||||||
return "https://" + window.location.hostname + ":8444/";
|
return "https://" + window.location.hostname + ":8444/";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a GET request to url and pass response to callback function
|
// Make a GET request to url and pass response to callback function
|
||||||
function getDataFromEndpoint(url, callback) {
|
function getDataFromEndpoint(url, callback, optional) {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
console.log("Attempting a connection to the following endpoint: " + url);
|
console.log("Attempting a connection to the following endpoint: " + url);
|
||||||
|
|
||||||
|
|
||||||
xhr.open("GET", url, true);
|
xhr.open("GET", url, true);
|
||||||
xhr.setRequestHeader("Authorization", "Bearer " + token);
|
xhr.setRequestHeader("Authorization", "Bearer " + token);
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
|
@ -18,8 +23,8 @@ function getDataFromEndpoint(url, callback) {
|
||||||
if (this.status === 200) {
|
if (this.status === 200) {
|
||||||
console.log("GET SUCCESS!");
|
console.log("GET SUCCESS!");
|
||||||
console.log("Server response:\n" + this.response);
|
console.log("Server response:\n" + this.response);
|
||||||
parsedData = JSON.parse(this.response);
|
let parsedData = JSON.parse(this.response);
|
||||||
callback(parsedData);
|
optional ? callback(parsedData, optional) : callback(parsedData);
|
||||||
} else {
|
} else {
|
||||||
console.error("GET FAILURE!");
|
console.error("GET FAILURE!");
|
||||||
console.error("Server status: " + this.status);
|
console.error("Server status: " + this.status);
|
||||||
|
@ -35,22 +40,55 @@ function getDataFromEndpoint(url, callback) {
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make a POST request to url and pass response to callback function
|
||||||
|
function postDataToEndpoint(url, payload, callback, optional) {
|
||||||
|
const token = localStorage.getItem("token");
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
console.log("Attempting a connection to the following endpoint: " + url);
|
||||||
|
|
||||||
|
xhr.open("POST", url, true);
|
||||||
|
xhr.setRequestHeader("Authorization", "Bearer " + token);
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (this.readyState === 4) {
|
||||||
|
if (this.status === 200) {
|
||||||
|
console.log("POST SUCCESS!");
|
||||||
|
console.log("Server response:\n" + this.response);
|
||||||
|
let parsedData = JSON.parse(this.response);
|
||||||
|
optional ? callback(parsedData, optional) : callback(parsedData);
|
||||||
|
} else {
|
||||||
|
console.error("POST FAILURE!");
|
||||||
|
console.error("Server status: " + this.status);
|
||||||
|
console.error("Server response:\n" + this.response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function() {
|
||||||
|
alert("Connection error!");
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(payload);
|
||||||
|
}
|
||||||
|
|
||||||
// Wraps a Bootstrap form group around a field
|
// Wraps a Bootstrap form group around a field
|
||||||
function createFormGroup(key, field) {
|
function createFormGroup(field) {
|
||||||
const formGroup = document.createElement("div")
|
const formGroup = document.createElement("div")
|
||||||
formGroup.classList.add("form-group", "row");
|
formGroup.classList.add("form-group", "row");
|
||||||
|
|
||||||
const label = document.createElement("label");
|
const label = document.createElement("label");
|
||||||
label.classList.add("col-sm-4", "col-form");
|
label.classList.add("col-sm-4", "col-form");
|
||||||
label.innerHTML = field.label + ": ";
|
label.innerHTML = field.label + ": ";
|
||||||
label.setAttribute("for", key);
|
label.setAttribute("for", field.field_name);
|
||||||
|
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.classList.add("col-sm-6");
|
div.classList.add("col-sm-6");
|
||||||
|
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.name = key;
|
input.name = field.field_name;
|
||||||
input.id = key;
|
input.id = field.field_name;
|
||||||
|
|
||||||
switch(field.type) {
|
switch(field.type) {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
|
@ -60,6 +98,7 @@ function createFormGroup(key, field) {
|
||||||
input.classList.add("form-check-input");
|
input.classList.add("form-check-input");
|
||||||
label.className = "";
|
label.className = "";
|
||||||
label.classList.add("form-check-label");
|
label.classList.add("form-check-label");
|
||||||
|
label.innerHTML = field.label;
|
||||||
outerLabel = document.createElement("div");
|
outerLabel = document.createElement("div");
|
||||||
outerLabel.classList.add("col-sm-4");
|
outerLabel.classList.add("col-sm-4");
|
||||||
outerLabel.innerHTML = "Flight type: ";
|
outerLabel.innerHTML = "Flight type: ";
|
||||||
|
@ -72,10 +111,29 @@ function createFormGroup(key, field) {
|
||||||
formGroup.appendChild(div);
|
formGroup.appendChild(div);
|
||||||
break;
|
break;
|
||||||
case "date":
|
case "date":
|
||||||
|
case "string":
|
||||||
|
input.type = "text";
|
||||||
|
input.value = field.value;
|
||||||
|
input.classList.add("form-control");
|
||||||
|
formGroup.appendChild(label);
|
||||||
|
div.appendChild(input)
|
||||||
|
formGroup.appendChild(div);
|
||||||
|
break;
|
||||||
case "decimal":
|
case "decimal":
|
||||||
input.type = "text";
|
input.type = "text";
|
||||||
input.value = field.value;
|
input.value = field.value;
|
||||||
input.classList.add("form-control");
|
input.classList.add("form-control");
|
||||||
|
input.pattern = "\\d+(\\.\\d{2})?";
|
||||||
|
formGroup.appendChild(label);
|
||||||
|
div.appendChild(input)
|
||||||
|
formGroup.appendChild(div);
|
||||||
|
break;
|
||||||
|
case "integer":
|
||||||
|
input.type = "number";
|
||||||
|
input.value = field.value;
|
||||||
|
input.classList.add("form-control");
|
||||||
|
input.step = 1;
|
||||||
|
input.min = 0;
|
||||||
formGroup.appendChild(label);
|
formGroup.appendChild(label);
|
||||||
div.appendChild(input)
|
div.appendChild(input)
|
||||||
formGroup.appendChild(div);
|
formGroup.appendChild(div);
|
||||||
|
@ -120,10 +178,13 @@ function createCollapsibleCard(key, sectionTitle) {
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCollapsibleCardBody(key, form, sectionDescription, sectionCompleted) {
|
function createCollapsibleCardBody(key, form, type, sectionDescription, sectionCompleted) {
|
||||||
// Create wrapper div
|
// Create wrapper div
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
|
div.id = "collapse" + key;
|
||||||
const sectionAlert = document.createElement("div");
|
const sectionAlert = document.createElement("div");
|
||||||
|
const cardBody = document.createElement("div");
|
||||||
|
cardBody.classList.add("card-body");
|
||||||
|
|
||||||
if (sectionCompleted) {
|
if (sectionCompleted) {
|
||||||
div.classList.add("collapse");
|
div.classList.add("collapse");
|
||||||
|
@ -135,12 +196,13 @@ function createCollapsibleCardBody(key, form, sectionDescription, sectionComplet
|
||||||
sectionAlert.innerHTML = "This section is not complete";
|
sectionAlert.innerHTML = "This section is not complete";
|
||||||
}
|
}
|
||||||
|
|
||||||
div.setAttribute("data-parent", "#editReportAccordion");
|
if (type === reportType.EDIT) {
|
||||||
div.id = "collapse" + key;
|
div.setAttribute("data-parent", "#editReportAccordion");
|
||||||
|
} else {
|
||||||
|
div.setAttribute("data-parent", "#newReportAccordion");
|
||||||
|
}
|
||||||
|
|
||||||
// Create card body. Append form to body, body to wrapper div
|
// Create card body. Append form to body, body to wrapper div
|
||||||
const cardBody = document.createElement("div");
|
|
||||||
cardBody.classList.add("card-body");
|
|
||||||
cardBody.appendChild(sectionAlert);
|
cardBody.appendChild(sectionAlert);
|
||||||
cardBody.insertAdjacentHTML("beforeend", sectionDescription);
|
cardBody.insertAdjacentHTML("beforeend", sectionDescription);
|
||||||
cardBody.appendChild(form);
|
cardBody.appendChild(form);
|
||||||
|
@ -149,9 +211,25 @@ function createCollapsibleCardBody(key, form, sectionDescription, sectionComplet
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEditReportForm(parsedData) {
|
function createReportForm(parsedData, type) {
|
||||||
const modalBody = document.querySelector(".modal-body");
|
let modalBody;
|
||||||
const modalLabel = document.querySelector("#editReportModalLabel");
|
let modalLabl;
|
||||||
|
const accordion = document.createElement("div");
|
||||||
|
accordion.classList.add("accordion");
|
||||||
|
|
||||||
|
if (type === reportType.EDIT) {
|
||||||
|
console.log("reportType.EDIT");
|
||||||
|
modalBody = document.querySelector("#editReportModalBody");
|
||||||
|
modalLabel = document.querySelector("#editReportModalLabel");
|
||||||
|
accordion.id = "editReportAccordion";
|
||||||
|
} else if (type === reportType.NEW) {
|
||||||
|
console.log("reportType.NEW");
|
||||||
|
modalBody = document.querySelector("#newReportModalBody");
|
||||||
|
modalLabel = document.querySelector("#newReportModalLabel");
|
||||||
|
accordion.id = "newReportAccordion";
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (modalBody.firstChild) {
|
while (modalBody.firstChild) {
|
||||||
modalBody.removeChild(modalBody.firstChild);
|
modalBody.removeChild(modalBody.firstChild);
|
||||||
|
@ -162,11 +240,6 @@ function createEditReportForm(parsedData) {
|
||||||
const dateCreated = new Date(parsedData.date_created).toLocaleDateString("en-US");
|
const dateCreated = new Date(parsedData.date_created).toLocaleDateString("en-US");
|
||||||
modalLabel.innerHTML = reportTitle + " " + dateCreated;
|
modalLabel.innerHTML = reportTitle + " " + dateCreated;
|
||||||
|
|
||||||
// Create accordion
|
|
||||||
const accordion = document.createElement("div");
|
|
||||||
accordion.classList.add("accordion");
|
|
||||||
accordion.id = "editReportAccordion";
|
|
||||||
|
|
||||||
// Traverse the report's sections array
|
// Traverse the report's sections array
|
||||||
const sections = parsedData.sections;
|
const sections = parsedData.sections;
|
||||||
for (let key in sections) {
|
for (let key in sections) {
|
||||||
|
@ -188,7 +261,7 @@ function createEditReportForm(parsedData) {
|
||||||
console.log("Field value: " + field.value);
|
console.log("Field value: " + field.value);
|
||||||
|
|
||||||
// Create a form group for each field and add it to the form
|
// Create a form group for each field and add it to the form
|
||||||
let formGroup = createFormGroup(key, field);
|
let formGroup = createFormGroup(field);
|
||||||
form.appendChild(formGroup);
|
form.appendChild(formGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +273,7 @@ function createEditReportForm(parsedData) {
|
||||||
form.appendChild(saveButton);
|
form.appendChild(saveButton);
|
||||||
|
|
||||||
// Create collapsible card body, append form to it, append card to accordion
|
// Create collapsible card body, append form to it, append card to accordion
|
||||||
let cardBody = createCollapsibleCardBody(key, form, section.html_description, section.completed);
|
let cardBody = createCollapsibleCardBody(key, form, type, section.html_description, section.completed);
|
||||||
collapsibleCard.appendChild(cardBody);
|
collapsibleCard.appendChild(cardBody);
|
||||||
accordion.appendChild(collapsibleCard);
|
accordion.appendChild(collapsibleCard);
|
||||||
}
|
}
|
||||||
|
@ -326,21 +399,35 @@ function displayReport(parsedData){
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function(event) {
|
document.addEventListener("DOMContentLoaded", function(event) {
|
||||||
const url = getEndpointDomain() + "api/v1/reports";
|
if (window.location.pathname === "/edit_report.html") {
|
||||||
getDataFromEndpoint(url, displayListOfReports);
|
const url = getEndpointDomain() + "api/v1/reports";
|
||||||
|
getDataFromEndpoint(url, displayListOfReports);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("click", function(event) {
|
document.addEventListener("click", function(event) {
|
||||||
if (event.target && event.target.classList.contains("edit-report-button")) {
|
if (event.target) {
|
||||||
console.log("Edit button clicked");
|
if (event.target.classList.contains("edit-report-button")) {
|
||||||
const url = getEndpointDomain() + "api/v1/report/" + event.target.dataset.rid;
|
const url = getEndpointDomain() + "api/v1/report/" + event.target.dataset.rid;
|
||||||
getDataFromEndpoint(url, createEditReportForm);
|
const type = reportType.EDIT;
|
||||||
|
getDataFromEndpoint(url, createReportForm, type);
|
||||||
|
} else if (event.target.classList.contains("view-report-button")) {
|
||||||
|
console.log("View button clicked");
|
||||||
|
const url = getEndpointDomain() + "api/v1/report/" + event.target.dataset.rid;
|
||||||
|
getDataFromEndpoint(url, displayReport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(event.target && event.target.classList.contains("view-report-button"))
|
|
||||||
{
|
|
||||||
console.log("View button clicked");
|
|
||||||
const url = getEndpointDomain() + "api/v1/report/" + event.target.dataset.rid;
|
|
||||||
getDataFromEndpoint(url, displayReport);
|
|
||||||
}
|
|
||||||
// TODO: Add View Report
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const newReportForm = document.querySelector(".new-report-form");
|
||||||
|
if (newReportForm) {
|
||||||
|
newReportForm.addEventListener("submit", function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const url = getEndpointDomain() + "api/v1/report";
|
||||||
|
const payload = JSON.stringify({ "title": event.target.elements.title.value });
|
||||||
|
console.log("Payload:\n" + payload);
|
||||||
|
const type = reportType.NEW;
|
||||||
|
postDataToEndpoint(url, payload, createReportForm, type);
|
||||||
|
this.reset();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script>
|
||||||
<link rel="shortcut icon" href="img/favicon.ico">
|
<link rel="shortcut icon" href="img/favicon.ico">
|
||||||
<title>Reimbursinator</title>
|
<title>Reimbursinator</title>
|
||||||
</head>
|
</head>
|
||||||
|
@ -41,16 +42,45 @@
|
||||||
<div class="card bg-light text-dark">
|
<div class="card bg-light text-dark">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3>Create a new report</h3>
|
<h3>Create a new report</h3>
|
||||||
<div class="form-group">
|
|
||||||
<label for="title">Report title:</label>
|
|
||||||
<input type="text" class="form-control" id="title">
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn btn-primary" herf="#Create">Create</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form class="form new-report-form" autocomplete="off">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title">Report title:</label>
|
||||||
|
<input type="text" class="form-control" name="title" id="title">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary" data-toggle="modal" data-target="#newReportModal">Create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="js/logout.js"></script>
|
<div class="modal fade" id="newReportModal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="newReportModalLabel"></h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="newReportModalBody">
|
||||||
|
<div class="text-center">
|
||||||
|
<i class="fas fa-spinner fa-3x fa-spin"></i>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h5>Creating Report ...</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary">Submit Report</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="js/logout.js"></script>
|
||||||
|
<script src="js/viewHistory.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue