Merge pull request #93: Update section completion and show rule violations

Display rule violations and update section completion flag
This commit is contained in:
Daniel Dupriest 2019-02-20 21:14:25 -08:00 committed by GitHub
commit 8f290fe2ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 127 additions and 44 deletions

View file

@ -1,13 +0,0 @@
.signup
{
height: 200px;
width: 400px;
position: fixed;
left: 50%;
margin-left: -150px;
width:60%;
}
.border
{
border-color:black;
}

View file

@ -0,0 +1,10 @@
.fa-check-square {
float: right;
color: green;
}
.fa-exclamation-triangle {
float: right;
color: orange;
}

View file

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<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">
<link rel="stylesheet" href="css/style.css">
<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> <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script>
@ -53,7 +54,6 @@
<tr> <tr>
<th>Title</th> <th>Title</th>
<th>Date Created</th> <th>Date Created</th>
<th class="d-none d-lg-table-cell">State</th>
<th class="d-none d-md-table-cell">Date Submitted</th> <th class="d-none d-md-table-cell">Date Submitted</th>
<th>Action</th> <th>Action</th>
</tr> </tr>

View file

@ -9,12 +9,6 @@ function getEndpointDomain() {
return "https://" + window.location.hostname + ":8444/"; return "https://" + window.location.hostname + ":8444/";
} }
function saveSectionCallback(parsedData, saveButton) {
alert(JSON.stringify(parsedData));
saveButton.innerHTML = "Save";
saveButton.disabled = false;
}
function makeAjaxRequest(method, url, callback, optional, payload) { function makeAjaxRequest(method, url, callback, optional, payload) {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
@ -57,6 +51,45 @@ function makeAjaxRequest(method, url, callback, optional, payload) {
xhr.send(payload); xhr.send(payload);
} }
function updateSection(parsedData, saveButton) {
const sectionIdStr = "#section-" + parsedData.id + "-";
const sectionState = document.querySelector(sectionIdStr + "state");
const collapseDiv = document.querySelector(sectionIdStr + "collapse");
// A completed section gets a header icon
if (parsedData.completed) {
const sectionAlert = collapseDiv.querySelector(".section-alert");
console.log(sectionAlert);
if (sectionAlert) {
collapseDiv.firstChild.removeChild(sectionAlert);
}
if (parsedData.rule_violations.length === 0) {
// Complete with no rule violations
sectionState.classList = "fas fa-check-square";
collapseDiv.className = "collapse";
} else {
// Complete but with rule violations
sectionState.classList = "fas fa-exclamation-triangle";
}
}
const cardFooter = createCardFooter(parsedData.rule_violations);
if (collapseDiv.lastElementChild.classList.contains("card-footer")) {
collapseDiv.removeChild(collapseDiv.lastElementChild);
if (cardFooter) {
collapseDiv.appendChild(cardFooter);
}
} else {
if (cardFooter) {
collapseDiv.appendChild(cardFooter);
}
}
saveButton.innerHTML = "Save";
saveButton.disabled = false;
}
// Wraps a Bootstrap form group around a field // Wraps a Bootstrap form group around a field
function createFormGroup(sectionIdStr, field) { function createFormGroup(sectionIdStr, field) {
const inputId = sectionIdStr + field.field_name; const inputId = sectionIdStr + field.field_name;
@ -164,15 +197,27 @@ function createFormGroup(sectionIdStr, field) {
return formGroup; return formGroup;
} }
function createCollapsibleCard(sectionIdStr, sectionTitle) { function createCollapsibleCard(sectionIdStr, sectionTitle, sectionCompleted, ruleViolations) {
// Create card and header // Create card and header
const card = document.createElement("div"); const card = document.createElement("div");
card.classList.add("card"); card.classList.add("card");
const cardHeader = document.createElement("div"); const cardHeader = document.createElement("div");
cardHeader.classList.add("card-header"); cardHeader.classList.add("card-header");
const sectionState = document.createElement("i");
sectionState.id = sectionIdStr + "state";
// A completed section gets a header icon
if (sectionCompleted) {
if (ruleViolations.length === 0) {
sectionState.classList.add("fas", "fa-check-square");
} else {
sectionState.classList.add("fas", "fa-exclamation-triangle");
}
}
// Create h2, button. Append button to h2, h2 to header, and header to card // Create h2, button. Append button to h2, h2 to header, and header to card
const h2 = document.createElement("h2"); const h2 = document.createElement("h2");
h2.classList.add("mb-0");
const button = document.createElement("button"); const button = document.createElement("button");
button.classList.add("btn", "btn-link"); button.classList.add("btn", "btn-link");
button.type = "button"; button.type = "button";
@ -180,43 +225,75 @@ function createCollapsibleCard(sectionIdStr, sectionTitle) {
button.setAttribute("data-target", "#" + sectionIdStr + "collapse"); button.setAttribute("data-target", "#" + sectionIdStr + "collapse");
button.innerHTML = sectionTitle; button.innerHTML = sectionTitle;
h2.appendChild(button); h2.appendChild(button);
h2.appendChild(sectionState);
cardHeader.appendChild(h2); cardHeader.appendChild(h2);
card.appendChild(cardHeader); card.appendChild(cardHeader);
return card; return card;
} }
function createCollapsibleCardBody(form, type, sectionIdStr, sectionDescription, sectionCompleted) { function createCollapsibleCardBody(form, type, sectionIdStr, sectionDescription, sectionCompleted, ruleViolations) {
// Create wrapper div // Create wrapper div
const div = document.createElement("div"); const collapseDiv = document.createElement("div");
div.id = sectionIdStr + "collapse"; collapseDiv.id = sectionIdStr + "collapse";
const sectionAlert = document.createElement("div");
const cardBody = document.createElement("div"); const cardBody = document.createElement("div");
cardBody.classList.add("card-body"); cardBody.classList.add("card-body");
const sectionAlert = document.createElement("div");
if (sectionCompleted) { if (sectionCompleted) {
div.classList.add("collapse"); if (ruleViolations.length === 0) {
sectionAlert.classList.add("alert", "alert-success"); collapseDiv.classList.add("collapse");
sectionAlert.innerHTML = "This section is complete";
} else { } else {
div.classList.add("collapse", "show"); collapseDiv.classList.add("collapse", "show");
sectionAlert.classList.add("alert", "alert-danger"); }
} else {
sectionAlert.classList.add("alert", "alert-danger", "section-alert");
sectionAlert.innerHTML = "This section is not complete"; sectionAlert.innerHTML = "This section is not complete";
} }
if (type === reportType.EDIT) { if (type === reportType.EDIT) {
div.setAttribute("data-parent", "#editReportAccordion"); collapseDiv.setAttribute("data-parent", "#editReportAccordion");
} else { } else {
div.setAttribute("data-parent", "#newReportAccordion"); collapseDiv.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
cardBody.appendChild(sectionAlert); cardBody.appendChild(sectionAlert);
cardBody.insertAdjacentHTML("beforeend", sectionDescription); cardBody.insertAdjacentHTML("beforeend", sectionDescription);
cardBody.appendChild(form); cardBody.appendChild(form);
div.appendChild(cardBody); collapseDiv.appendChild(cardBody);
return div; return collapseDiv;
}
function createCardFooter(ruleViolations) {
if (ruleViolations.length === 0) {
return null;
}
const cardFooter = document.createElement("div");
cardFooter.classList.add("card-footer");
const violationMessage = document.createElement("div");
violationMessage.classList.add("alert", "alert-danger");
const heading = document.createElement("div");
heading.innerHTML = "Rule Violations";
heading.classList.add("alert-heading");
violationMessage.appendChild(heading);
violationMessage.appendChild(document.createElement("hr"));
for (let i = 0; i < ruleViolations.length; i++) {
let violation = document.createElement("p");
let violationLabel = document.createElement("strong");
violationLabel.innerHTML = ruleViolations[i].label;
violation.appendChild(violationLabel);
violation.appendChild(document.createElement("br"));
let ruleBreakText = document.createTextNode(ruleViolations[i].rule_break_text);
violation.appendChild(ruleBreakText);
violationMessage.appendChild(violation);
}
cardFooter.appendChild(violationMessage);
return cardFooter;
} }
function createReportForm(parsedData, type) { function createReportForm(parsedData, type) {
@ -252,16 +329,14 @@ function createReportForm(parsedData, type) {
} }
// Add report title and date // Add report title and date
const reportTitle = parsedData.title; modalLabel.innerHTML = parsedData.title;
modalLabel.innerHTML = reportTitle;
// Traverse the report's sections array // Traverse the report's sections array
const sections = parsedData.sections; const sections = parsedData.sections;
for (let i = 0; i < sections.length; i++) { for (let i = 0; i < sections.length; i++) {
let sectionIdStr = "section-" + sections[i].id + "-";
let collapsibleCard = createCollapsibleCard(sectionIdStr, sections[i].title)
// Create a new form with the section key index as id // Create a new form
let sectionIdStr = "section-" + sections[i].id + "-";
let form = document.createElement("form"); let form = document.createElement("form");
form.classList.add("form", "section-form"); form.classList.add("form", "section-form");
form.id = sectionIdStr + "form"; form.id = sectionIdStr + "form";
@ -272,9 +347,11 @@ function createReportForm(parsedData, type) {
let fields = sections[i].fields; let fields = sections[i].fields;
for (let j = 0; j < fields.length; j++) { for (let j = 0; j < fields.length; j++) {
/*
console.log("Field label: " + fields[j].label); console.log("Field label: " + fields[j].label);
console.log("Field type: " + fields[j].field_type); console.log("Field type: " + fields[j].field_type);
console.log("Field value: " + fields[j].value); console.log("Field value: " + fields[j].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
form.appendChild(createFormGroup(sectionIdStr, fields[j])); form.appendChild(createFormGroup(sectionIdStr, fields[j]));
@ -288,7 +365,14 @@ function createReportForm(parsedData, type) {
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(form, type, sectionIdStr, sections[i].html_description, sections[i].completed); let cardBody = createCollapsibleCardBody(form, type, sectionIdStr,
sections[i].html_description, sections[i].completed, sections[i].rule_violations);
let cardFooter = createCardFooter(sections[i].rule_violations);
if (cardFooter) {
cardBody.appendChild(cardFooter);
}
let collapsibleCard = createCollapsibleCard(sectionIdStr, sections[i].title,
sections[i].completed, sections[i].rule_violations)
collapsibleCard.appendChild(cardBody); collapsibleCard.appendChild(cardBody);
accordion.appendChild(collapsibleCard); accordion.appendChild(collapsibleCard);
} }
@ -323,9 +407,11 @@ function displayListOfReports(parsedData) {
bodyRow.insertCell(0).innerHTML = title; bodyRow.insertCell(0).innerHTML = title;
bodyRow.insertCell(1).innerHTML = dateCreated; bodyRow.insertCell(1).innerHTML = dateCreated;
/*
let stateCell = bodyRow.insertCell(2); let stateCell = bodyRow.insertCell(2);
stateCell.innerHTML = state; stateCell.innerHTML = state;
stateCell.classList.add("d-none", "d-lg-table-cell"); // Column visible only on large displays stateCell.classList.add("d-none", "d-lg-table-cell"); // Column visible only on large displays
*/
// Create edit/view button // Create edit/view button
let actionButton = document.createElement("button"); let actionButton = document.createElement("button");
@ -349,10 +435,10 @@ function displayListOfReports(parsedData) {
actionButton.setAttribute("data-target", "#viewReportModal"); actionButton.setAttribute("data-target", "#viewReportModal");
} }
let dateSubmittedCell = bodyRow.insertCell(3); let dateSubmittedCell = bodyRow.insertCell(2);
dateSubmittedCell.innerHTML = dateSubmitted; dateSubmittedCell.innerHTML = dateSubmitted;
dateSubmittedCell.classList.add("d-none", "d-md-table-cell"); // Column visible on medium and larger displays dateSubmittedCell.classList.add("d-none", "d-md-table-cell"); // Column visible on medium and larger displays
bodyRow.insertCell(4).appendChild(actionButton); bodyRow.insertCell(3).appendChild(actionButton);
} }
table.style.visibility = "visible"; table.style.visibility = "visible";
@ -468,7 +554,6 @@ if (newReportForm) {
console.log("Payload:\n" + payload); console.log("Payload:\n" + payload);
const type = reportType.NEW; const type = reportType.NEW;
makeAjaxRequest("POST", url, createReportForm, type, payload); makeAjaxRequest("POST", url, createReportForm, type, payload);
this.reset();
}); });
} }
@ -494,7 +579,7 @@ document.addEventListener("submit", function(event) {
saveButton.appendChild(document.createTextNode(" Saving...")); saveButton.appendChild(document.createTextNode(" Saving..."));
const formData = new FormData(event.target); const formData = new FormData(event.target);
const url = getEndpointDomain() + "api/v1/report/" + event.target.dataset.rid + "/section/" + event.target.dataset.sid; const url = getEndpointDomain() + "api/v1/report/" + event.target.dataset.rid + "/section/" + event.target.dataset.sid;
makeAjaxRequest("PUT", url, saveSectionCallback, saveButton, formData); makeAjaxRequest("PUT", url, updateSection, saveButton, formData);
} }
}); });

View file

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<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">
<link rel="stylesheet" href="css/style.css">
<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> <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20171210/classList.min.js"></script>