', { html: $(this).html() }); + }); + $("#signatureConfirmation").show(); + $("#signatureButtons").hide(); + } + }) + } +}); diff --git a/app/static/js/rosterManagement.js b/app/static/js/rosterManagement.js new file mode 100644 index 000000000..0010fd48f --- /dev/null +++ b/app/static/js/rosterManagement.js @@ -0,0 +1,90 @@ +import searchUser from './searchUser.js' + +$(document).ready(function(){ + var dt = $('#rosterTable').DataTable(); + + searchUser("searchStudentsInput", callback, "searchStudentsInput"); // initialize ONCE + + $("#searchIcon").click(function (e) { + e.preventDefault(); + callback($("#searchStudentsInput").val()); + }); + + $("#searchStudentsInput").focus(); + + $("#dismissModal").click(function() { + location.reload(); + }) +}); + +function callback(selected) { + var form = $("#searchStudentForm"); + form.attr("action", "/" + selected["username"] + "/addInterest/" + form.data("program") + "/False"); + $("#searchStudentForm").submit(); +} + +$('#searchStudentForm').on('submit', function(e) { + e.preventDefault(); // stops the browser's normal form submission/redirect + + var formData = $(this).serialize(); // or new FormData(this) if you have file inputs + $.ajax({ + url: $(this).attr('action'), + type: $(this).attr('method') || 'POST', + success: function(response) { + var targetDiv = $("#addedNameDivTarget"); + var targetP = $("#addedNameToClone").clone(); + targetDiv.append(targetP); + var targetSpan = targetP.find(".addedNameTarget"); + targetSpan.text(response['firstName'] + " " + response["lastName"]); + targetP.attr("hidden", false); + }, + error: function(xhr, status, error) { + var targetDiv = $("#addedNameDivTarget"); + var targetP = $("#addedNameToClone"); + var targetSpan = targetP.find(".addedNameTarget"); + targetP.html(targetSpan); + targetSpan.text("Uh oh... something went wrong. Contact a CELTS staff member."); + targetP.attr("hidden", false); + console.log(status, error); + } + }) +}); + +$("#exportRoster").click(function() { + var year = $(this).data("year"); + var program = $(this).data('program'); + $.ajax({ + url: "/exportRosters/" + program + "/" + year, + type: 'GET', + xhrFields: { responseType: "blob" }, + success: function(blob, status, xhr) { + msgFlash("Download Successful", "success"); + var filename = 'download.xlsx'; // fallback if header is missing/unparseable + var disposition = xhr.getResponseHeader('Content-Disposition'); + if (disposition) { + // handles both: filename="report.xlsx" and filename=report.xlsx + var match = disposition.match(/filename\*?=(?:UTF-\d['"]*)?["']?([^"';\n]+)["']?/i); + if (match && match[1]) { + filename = decodeURIComponent(match[1]); + } + } + + var xlsxBlob = new Blob([blob], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }); + + var url = window.URL.createObjectURL(xlsxBlob); + var a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + a.remove(); + window.URL.revokeObjectURL(url); + }, + error: function(xhr, status, error) { + console.log(status, error); + } + }) +}) + diff --git a/app/static/js/searchStudent.js b/app/static/js/searchStudent.js index 93062f6de..bdfcc9e1f 100644 --- a/app/static/js/searchStudent.js +++ b/app/static/js/searchStudent.js @@ -1,16 +1,16 @@ import searchUser from './searchUser.js' + function callback(selected) { - $("#searchStudent").submit(); + $("#searchStudentsInput").submit(); } + $(document).ready(function() { - $("#searchStudentsInput").on("input", function() { - searchUser("searchStudentsInput", callback); - }); - + searchUser("searchStudentsInput", callback); // initialize ONCE + $("#searchIcon").click(function (e) { e.preventDefault(); callback($("#searchStudentsInput").val()); }); - $("#searchStudentsInput").focus() -}) + $("#searchStudentsInput").focus(); +}); \ No newline at end of file diff --git a/app/static/js/searchUser.js b/app/static/js/searchUser.js index 5ebf57c70..db6ee7e7e 100644 --- a/app/static/js/searchUser.js +++ b/app/static/js/searchUser.js @@ -1,41 +1,36 @@ export default function searchUser(inputId, callback, clear=false, parentElementId=null, category = null) { - var query = $(`#${inputId}`).val() - let columnDict = {}; $(`#${inputId}`).autocomplete({ appendTo: (parentElementId === null) ? null : `#${parentElementId}`, minLength: 2, - source: function(request, response) { + source: function(request, response) { $.ajax({ - url: `/searchUser/${query}`, + url: `/searchUser/${request.term}`, // use the live term type: "GET", dataType: "json", - data:{"category":category}, + data: {"category": category}, success: function(searchResults) { - response(Object.entries(searchResults).map( (item) => { - return { - // label: firstName lastName (username) - // value: username - label: (item[1]["firstName"]+" "+item[1]["lastName"]+" ("+item[0]+")"), - value: item[1]["username"], - dictvalue: item[1], - } - } - ))}, + response(Object.entries(searchResults).map((item) => { + return { + label: (item[1]["firstName"] + " " + item[1]["lastName"] + " (" + item[0] + ")"), + value: item[1]["username"], + dictvalue: item[1], + } + })) + }, error: function(request, status, error) { console.log(status, error); } }) }, - select: function(event, ui) { - $(`#${inputId}`).val(ui.item.value); - callback(ui.item.dictvalue); - if(clear){ - $(`#${inputId}`).val(""); - } - - return false; - }, - autoFocus: true + select: function(event, ui) { + $(`#${inputId}`).val(ui.item.value); + callback(ui.item.dictvalue); + if(clear){ + $(`#${inputId}`).val(""); + } + return false; + }, + autoFocus: true }); -}; +}; \ No newline at end of file diff --git a/app/static/js/userManagement.js b/app/static/js/userManagement.js index 2e5e91998..f5dbd111c 100644 --- a/app/static/js/userManagement.js +++ b/app/static/js/userManagement.js @@ -27,6 +27,7 @@ function callbackProgramManager(selected, action = 'add') { } $(document).ready(function(){ + // Admin Management $("#searchCeltsAdminInput").on("input", function(){ searchUser("searchCeltsAdminInput", callbackAdmin, false, null, "celtsLinkAdmin") @@ -152,6 +153,13 @@ $(document).ready(function(){ }) }); +$('.viewRoster').on('click', function() { + // Openning the modal after the data was received + $('#programPlaceholder').data('programid', $(this).data('programid')) + let modal = new bootstrap.Modal($('#viewRosterModal')); + modal.show(); +}); + function submitRequest(method, username){ let data = { method: method, @@ -244,12 +252,12 @@ function submitTerm(){ url: "/admin/changeTerm", type: "POST", data: termInfo, - success: function(s){ - msgFlash("Current term successfully changed to " + selectedTerm.html(), "success") + success: function(response){ + reloadWithAccordion("term") }, error: function(error, status){ - msgFlash("Current term was not changed. Please try again.", "warning") - console.log(error, status) + msgFlash("Current term was not changed. Please reload the page and try again.", "warning") + console.log(error, status) } }) } @@ -262,7 +270,8 @@ function addNewTerm(){ reloadWithAccordion("term") }, error: function(error, status){ - console.log(error, status) + msgFlash("Failure adding new term. Please reload the page and try again.", "warning") + console.log(error, status) } }) } diff --git a/app/static/js/userProfile.js b/app/static/js/userProfile.js index 61af76787..acb9ec51c 100644 --- a/app/static/js/userProfile.js +++ b/app/static/js/userProfile.js @@ -1,6 +1,10 @@ -$(document).ready(function(){ +$(document).ready(function(){ + + $('#editVolunteerModal').modal({ + backdrop: 'static' + }); - $("#checkDietRestriction").on("change", function() { + $("#checkDietRestriction").on("change", function() { let norestrict = $(this).is(':checked'); if (norestrict) { $("#dietContainer").hide(); @@ -36,6 +40,7 @@ $(document).ready(function(){ }) $("#phoneInput").inputmask('(999)-999-9999'); + $(".notifyInput").click(function updateInterest(){ var programID = $(this).data("programid"); var username = $(this).data('username'); @@ -113,19 +118,19 @@ $(document).ready(function(){ var banNote = $("#banNote") var banValue = $(this).val() - banButton.text(banValue + " Volunteer"); + banButton.text("Set " + banValue); programID = $(this).data("programid"); // Assign value to programID variable banButton.data("programID", programID) banButton.data("username", $(".banEdit").data("username")) banButton.data("banOrUnban", banValue); banEndDateDiv.show(); banEndDatepicker.val("") - $(".modal-title-ban").text(banValue + " Volunteer from "+ $(this).data("name") + "?"); + $(".modal-title-ban").text("Mark Volunteer as " + banValue + " from "+ $(this).data("name") + "?"); $("#modalProgramName").text("Program: " + $(this).data("name")); $("#banModal").modal("toggle"); $("#banNoteTxtArea").val(""); $("#banButton").prop("disabled", true); - if(banValue == "Unban"){ + if(banValue == "Eligible"){ banEndDateDiv.hide() banEndDatepicker.val("0001-01-01") //This is a placeholder value for the if statement in line 52 to work properly #PLCHLD1 banNoteDiv.show() @@ -143,6 +148,12 @@ $(document).ready(function(){ $("#banButton").prop("disabled", true) var username = $(this).data("username") //Expected to be the unique username of a user in the database var route = ($(this).data("banOrUnban")).toLowerCase() //Expected to be "ban" or "unban" + + if(route =="eligible"){ // This handles the case where the user is being marked as eligible/ineligible and changes to ban and unban status for the route + route= 'unban' + }else{ + route= 'ban' + } var program = $(this).data("programID") //Expected to be a program's primary ID $.ajax({ @@ -160,45 +171,45 @@ $(document).ready(function(){ /* * Note Functionality */ - function bonnerNoteOff() { - $("#bonnerInput").prop("checked", false); - $("#noteDropdown").show() - $("#bonnerStatement").hide() - $("#visibilityLabel").show() - } + function bonnerNoteOff() { + $("#bonnerInput").prop("checked", false); + $("#noteDropdown").show() + $("#bonnerStatement").hide() + $("#visibilityLabel").show() + } - function bonnerNoteOn() { - $("#bonnerInput").prop("checked", true); - $("#noteDropdown").hide() - $("#bonnerStatement").show() - $("#visibilityLabel").hide() - } + function bonnerNoteOn() { + $("#bonnerInput").prop("checked", true); + $("#noteDropdown").hide() + $("#bonnerStatement").show() + $("#visibilityLabel").hide() + } - $("#addNoteButton").click(function() { - bonnerNoteOff() - $("#addNoteTextArea").val('') - $("#notesSaveButton").data('mode', 'add') - $("#notesSaveButton").data('noteid', null) - $("#noteModal").modal("toggle") - }); + $("#addNoteButton").click(function() { + bonnerNoteOff() + $("#addNoteTextArea").val('') + $("#notesSaveButton").data('mode', 'add') + $("#notesSaveButton").data('noteid', null) + $("#noteModal").modal("toggle") + }); - $("#addVisibility").click(function() { - var bonnerChecked = $("input[name='bonner']:checked").val() + $("#addVisibility").click(function() { + var bonnerChecked = $("input[name='bonner']:checked").val() - if (bonnerChecked == 'on') { - bonnerNoteOn() - } else { - bonnerNoteOff() - } - }); + if (bonnerChecked == 'on') { + bonnerNoteOn() + } else { + bonnerNoteOff() + } + }); - $("#addBonnerNoteButton").click(function() { - bonnerNoteOn() - $("#addNoteTextArea").val('') - $("#notesSaveButton").data('mode', 'add') - $("#notesSaveButton").data('noteid', null) - $("#noteModal").modal("toggle"); - }); + $("#addBonnerNoteButton").click(function() { + bonnerNoteOn() + $("#addNoteTextArea").val('') + $("#notesSaveButton").data('mode', 'add') + $("#notesSaveButton").data('noteid', null) + $("#noteModal").modal("toggle"); + }); $('#addNoteForm').submit(function(event) { @@ -220,9 +231,9 @@ $(document).ready(function(){ method: "POST", url: "/profile/addNote", data: {"username": username, - "visibility": $("#noteDropdown").val(), - "noteTextbox": $("#addNoteTextArea").val(), - "bonner": isBonner ? "yes" : "no"}, + "visibility": $("#noteDropdown").val(), + "noteTextbox": $("#addNoteTextArea").val(), + "bonner": isBonner ? "yes" : "no"}, success: function(response) { target = isBonner ? "bonner" : "notes" msgFlash("Successfully added a note", "success", 1300, true); @@ -238,7 +249,7 @@ $(document).ready(function(){ $("#confirmDeleteNote").data('username', $(this).data('username')) $("#confirmDeleteNote").data('noteid', $(this).data('noteid')) $("#deleteNoteWarning").modal("show") - + }); $("#confirmDeleteNote").click(function() { @@ -277,7 +288,8 @@ $(document).ready(function(){ $("#noteModal").modal("toggle") -}); + + $.ajax({ method: "POST", url: "/" + username + "/editNote", @@ -287,6 +299,7 @@ $(document).ready(function(){ } }); }); +}); /* * Background Check Functionality */ @@ -365,14 +378,16 @@ $(document).ready(function(){ }); // Popover functionality - var requiredTraining = $(".trainingPopover"); - requiredTraining.popover({ + var requiredTraining = document.querySelectorAll(".trainingPopover"); + requiredTraining.forEach(function(el) { + new bootstrap.Popover(el, { trigger: "hover", sanitize: false, html: true, content: function() { - return $(this).attr('data-content'); + return this.getAttribute('data-content'); } + }); }); setupPhoneNumber("#updatePhone", "#phoneInput") @@ -443,4 +458,4 @@ function updateManagers(el, volunteerUsername ) { console.log(error, status) } }) -} +} \ No newline at end of file diff --git a/app/templates/admin/graduationManagement.html b/app/templates/admin/graduationManagement.html index a84a658e8..58d3fa8a6 100644 --- a/app/templates/admin/graduationManagement.html +++ b/app/templates/admin/graduationManagement.html @@ -19,15 +19,10 @@
The following table includes all students who have indicated they are interested in {{program.programName}} on their profile.
+| Potential Volunteer | +Eligible | +All Volunteers Training | +Program Specific Training | +AY {{g.current_term.academicYear}} Handbook Signed | +Background Check | +|
|---|---|---|---|---|---|---|
| {% if trainedAndInterested[prospectiveVolunteer]['star']%} {% endif %}{{trainedAndInterested[prospectiveVolunteer]["userObj"].fullName}} | +{{trainedAndInterested[prospectiveVolunteer]["userObj"].email}} | +{% if trainedAndInterested[prospectiveVolunteer]['eligible'] %} Yes {% else %} No {% endif %} | +{% if trainedAndInterested[prospectiveVolunteer]['allVolunteer'] %} Attended {% else %} Not attended {% endif %} | +{% if trainedAndInterested[prospectiveVolunteer]['programSpecific'] %} Attended {% else %} Not attended {% endif %} | +{% if trainedAndInterested[prospectiveVolunteer]["userObj"].signatureTerm.academicYear == g.current_term.academicYear %} Signed {% else %} Not signed {% endif %} | +{% if trainedAndInterested[prospectiveVolunteer]['bgCheck'] == "Not submitted" %} {% else %} {% endif %}{{trainedAndInterested[prospectiveVolunteer]['bgCheck']}} | +
The following table includes all current students who have participated in at least one {{program.programName}} event in AY {{g.current_term.academicYear}}.
+ {% if currentYearsParticipants|length == 0%} +There are no participants currently in {{program.programName}} for AY {{g.current_term.academicYear}}
+ {% else %} +| Volunteer Name | +|
|---|---|
| {{currentYearparticipant.fullName}} | +{{currentYearparticipant.email}} | +
The following table includes all current students who participated in at least one {{program.programName}} event in AY {{g.current_term.previousAcademicYear}}.
+ {% if lastYearsParticipants|length == 0%} +There were no participants in {{program.programName}} during AY {{g.current_term.previousAcademicYear}}
+ {% else %} +| Volunteer Name | +|
|---|---|
| {{lastYearparticipant.fullName}} | +{{lastYearparticipant.email}} | +
| Program | +Indicated Interested | +Training | + {% if g.current_user.isCeltsAdmin or g.current_user.isCeltsStudentStaff%} +Eligibility | + {% if g.current_user.isCeltsAdmin%} +On Transcript | + {% endif %} + {% endif %} + +|
|---|---|---|---|---|---|
| {{row.program.programName}} | ++ | + {% set hasCompletedAllTrainings = row.completedTraining %} +    + View + | + {% if g.current_user.isCeltsAdmin or g.current_user.isCeltsStudentStaff %} + {% if row.isNotBanned %} +Eligible + {% set label = "Ban" %} + {% else %} + | Banned + {% set label = "Unban" %} + {% endif %} + + {% if g.current_user.isCeltsAdmin %} + + {% endif %} + | + + {% if g.current_user.isCeltsAdmin %} ++ + + | + {% endif %} + + + {% endif %} +
Step 1: Indicate your interest in a CELTS programs below. Your interest helps us get you involved!
+Step 2: Attend one of the All Volunteers Trainings listed below. Click to RSVP!
+Step 3: Attend the Program-specific training to learn more about volunteering with that program!
+ +| All programs require attending one All Volunteers Training! | +
+ {% for training in upcomingAllVolunteers %}
+ {% if not loop.first %} {% endif %} + {{training.name}} ({{training.startDate}} @ {{training.timeStart}}) + {% endfor %} + |
+
| Program | +Indicate Interest | +Upcoming Trainings (Required to participate) |
+
|---|---|---|
| {{program.programName}} | ++ + | +
+ {% for training in upcomingTrainings %}
+ {% if training.program.id == program.id %}
+ {{training.name}} ({{training.startDate}} @ {{training.timeStart}}){% if loop.index != 0 %} {% endif %} + {% endif %} + {% endfor %} + |
+
{{ event.program.description }}
- More Information - {% endif %} -{{ event.program.description }}
+ More Information + {% endif %} +Why the student was banned
+Why the student is ineligible