diff --git a/app/controllers/main_routes/main_routes.py b/app/controllers/main_routes/main_routes.py index 7106cb62..b4c34ea4 100755 --- a/app/controllers/main_routes/main_routes.py +++ b/app/controllers/main_routes/main_routes.py @@ -49,7 +49,7 @@ def supervisorPortal(): allSupervisors = Supervisor.select() supervisorFirstName = fn.COALESCE(Supervisor.preferred_name, Supervisor.legal_name) studentFirstName = fn.COALESCE(Student.preferred_name, Student.legal_name) - + department = None if currentUser.isLaborAdmin or currentUser.isFinancialAidAdmin or currentUser.isSaasAdmin: departments = Department.select().order_by(Department.isActive.desc(), Department.DEPT_NAME.asc()) departments = [department for department in departments] @@ -63,6 +63,8 @@ def supervisorPortal(): departments = [department for department in departments] deptNames = [department.DEPT_NAME for department in departments] + supervisorPrimaryDepartment = Department.select().join(SupervisorDepartment) # count up all forms for a supervisor in department and get the max + supervisors = (Supervisor.select(Supervisor, supervisorFirstName) .join_from(Supervisor, LaborStatusForm) .join_from(LaborStatusForm, Department) @@ -85,7 +87,7 @@ def supervisorPortal(): allSupervisors = allSupervisors, students = students, departments = departments, - department = None, + department = department, currentUser = currentUser ) @@ -101,9 +103,9 @@ def getDatatableData(request): sleJoin = False currentUser = require_login() - draw = int(request.form.get('draw', -1)) - rowNumber = int(request.form.get('start', -1)) - rowsPerPage = int(request.form.get('length', -1)) + draw = int(request.form.get('draw', 0)) + rowNumber = int(request.form.get('start', 0)) + rowsPerPage = int(request.form.get('length', 25)) queryFilterData = request.form.get('data') queryFilterDict = json.loads(queryFilterData) sortBy = queryFilterDict.get('sortBy', "term") @@ -167,6 +169,7 @@ def getDatatableData(request): # this maps all of the values we expect to receive from the sorting dropdowns in the frontend # to actual peewee objects we can sort by later + # the casing is weird because the columns that don't have any fields are are not capitalized sortValueColumnMap = { "term": Term.termCode, "department": Department.DEPT_NAME, @@ -174,8 +177,9 @@ def getDatatableData(request): "supervisorLastName": Supervisor.LAST_NAME, "studentFirstName": studentFirstNameCase, "studentLastName": Student.LAST_NAME, - "positionCode": LaborStatusForm.POSN_CODE, "positionWLS": LaborStatusForm.WLS, + "positionTitle": LaborStatusForm.POSN_TITLE, + "positionType": LaborStatusForm.jobType, "length": LaborStatusForm.startDate, "createdBy": User.username, "formStatus": FormHistory.status, @@ -183,20 +187,35 @@ def getDatatableData(request): } if order == "DESC": - filteredSearchResults = formSearchResults.order_by(sortValueColumnMap[sortBy].desc()).limit(rowsPerPage).offset(rowNumber) + filteredSearchResults = formSearchResults.order_by(fn.TRIM(sortValueColumnMap[sortBy]).desc()).limit(rowsPerPage).offset(rowNumber) else: - filteredSearchResults = formSearchResults.order_by(sortValueColumnMap[sortBy].asc()).limit(rowsPerPage).offset(rowNumber) - formattedData = getFormattedData(filteredSearchResults) + filteredSearchResults = formSearchResults.order_by(fn.TRIM(sortValueColumnMap[sortBy]).asc()).limit(rowsPerPage).offset(rowNumber) + formattedData = getFormattedData(filteredSearchResults, queryFilterDict['view']) formsDict = {"draw": draw, "recordsTotal": recordsTotal, "recordsFiltered": recordsTotal, "data": formattedData} return jsonify(formsDict) -def getFormattedData(filteredSearchResults): +def getFormattedData(filteredSearchResults, view ='simple'): ''' Putting the data in the correct format to be used by the JS file. Because this implementation is using server-side processing of datatables, the HTML for the datatables are also formatted here. ''' + if view == "simple": + formattedData = [] + for form in filteredSearchResults: + # The order in which you append the items to 'record' matters and it should match the order of columns on the table! + formattedData.append([f""" + + + {form.formID.studentSupervisee.FIRST_NAME} {form.formID.studentSupervisee.LAST_NAME} ({form.formID.studentSupervisee.ID}) + + + {form.status} +
+ {form.formID.termCode.termName} - {form.formID.POSN_TITLE} ({form.formID.jobType}) - {form.formID.department.DEPT_NAME} + """]) + return formattedData supervisorHTML = '{} ' studentHTML = '
{}
{}
' @@ -209,20 +228,30 @@ def getFormattedData(filteredSearchResults): record = [] # Term record.append(form.formID.termCode.termName) - # Department - record.append(departmentHTML.format( - form.formID.department.ORG, - form.formID.department.ACCOUNT, - form.formID.department.DEPT_NAME)) + # Student + record.append(studentHTML.format( + form.formID.laborStatusFormID, + form.formID.studentSupervisee.ID, + f'{form.formID.studentSupervisee.preferred_name if form.formID.studentSupervisee.preferred_name else form.formID.studentSupervisee.legal_name} {form.formID.studentSupervisee.LAST_NAME}', + form.formID.studentSupervisee.ID, + form.formID.studentSupervisee.STU_EMAIL)) # Supervisor supervisorField = supervisorHTML.format( form.formID.supervisor.ID, f'{form.formID.supervisor.preferred_name if form.formID.supervisor.preferred_name else form.formID.supervisor.legal_name } {form.formID.supervisor.LAST_NAME}', form.formID.supervisor.EMAIL) + record.append(supervisorField) + + # Department + record.append(departmentHTML.format( + form.formID.department.ORG, + form.formID.department.ACCOUNT, + form.formID.department.DEPT_NAME)) + # Position positionField = positionHTML.format( - form.formID.POSN_TITLE, - f'{form.formID.POSN_CODE} ({form.formID.WLS})') + form.formID.jobType, + f'{form.formID.jobType} ({form.formID.WLS})') # Hours hoursField = form.formID.weeklyHours if form.formID.weeklyHours else form.formID.contractHours # Adjustment Form Specific Data @@ -245,16 +274,10 @@ def getFormattedData(filteredSearchResults): newHours = form.adjustedForm.newValue hoursField = f'{hoursField}
{newHours}' - record.append(supervisorField) - # Student - record.append(studentHTML.format( - form.formID.laborStatusFormID, - form.formID.studentSupervisee.ID, - f'{form.formID.studentSupervisee.preferred_name if form.formID.studentSupervisee.preferred_name else form.formID.studentSupervisee.legal_name} {form.formID.studentSupervisee.LAST_NAME}', - form.formID.studentSupervisee.ID, - form.formID.studentSupervisee.STU_EMAIL)) + + - record.append(f'{form.formID.jobType}
{positionField}') + record.append(f'{form.formID.POSN_TITLE}
{positionField}') record.append(hoursField) # Contract Dates record.append("
".join([form.formID.startDate.strftime('%m/%d/%y'), @@ -280,7 +303,6 @@ def getFormattedData(filteredSearchResults): # TODO: Skipping adding to the table. Requires database work to get SLE out from form (formHistory, to be precise) formattedData.append(record) - return formattedData @main_bp.route('/supervisorPortal/addUserToDept', methods=['GET', 'POST']) diff --git a/app/static/js/supervisorPortal.js b/app/static/js/supervisorPortal.js index ab873b62..0bcda0b6 100644 --- a/app/static/js/supervisorPortal.js +++ b/app/static/js/supervisorPortal.js @@ -1,8 +1,16 @@ $(document).ready(function () { if ((document.cookie).includes("lsfSearchResults=")) { cookieStr = Cookies.get('lsfSearchResults') - createDataTable(cookieStr) - setFormSearchValues(JSON.parse(cookieStr)) + cookieJSON = JSON.parse(cookieStr) + // using the cookies, make sure the view is properly set as well + if (cookieJSON.view == 'advanced') { + createDataTable(cookieStr) + switchViewButton('simple') + } else { + fetchSimpleView(cookieStr) + switchViewButton('advanced') + } + setFormSearchValues(cookieJSON) } else { $('#formSearchTable').hide(); @@ -15,6 +23,18 @@ $(document).ready(function () { runFormSearchQuery(); $('#sortOptions').show(); }); + + $('#switchViewButton').on('click', function () { + // toggle the view and button value + buttonVal = $("#switchViewButton").val() + switchViewButton(buttonVal) + + // we can just rerun the form search query as it pulls down the value + // of the button to determine what button to render + runFormSearchQuery(); + $('#sortOptions').show(); + }); + $('#addUserToDept').on('click', function () { $("#addSupervisorToDeptModal").modal("show"); $('#addUser').prop('disabled', true) @@ -70,8 +90,9 @@ $(document).ready(function () { }); $('#columnPicker').on('change', function () { let column = $('#columnPicker :selected').text() - let fields = columnFieldMap[column] - + buttonVal = $("#switchViewButton").val() + let fields = buttonVal == "advanced" ? advancedColumnFieldMap[column] : simpleColumnFieldMap[column]; + // clear the options from the current field picker and replace // them with the ones from the columnFieldMap $('#fieldPicker').empty(); @@ -97,17 +118,25 @@ $(document).ready(function () { // this is a mapping which maps the column option to its field options. // many do not have multiple fields so the field is just the column itself (e.g. term) -const columnFieldMap = { +const advancedColumnFieldMap = { 'Term': [['Term', 'term']], 'Department': [['Department', 'department']], 'Supervisor': [['First name', 'supervisorFirstName'], ['Last Name', 'supervisorLastName']], 'Student': [['First name', 'studentFirstName'], ['Last Name', 'studentLastName']], - 'Position (WLS)': [['WLS', 'positionWLS'], ['Position Code', 'positionCode']], + 'Position (WLS)': [['WLS', 'positionWLS'], ['Position Type', 'positionType'], ['Position Title', 'positionTitle']], 'Length': [['Length', 'length']], 'Created By': [['Created By', 'createdBy']], 'Form Type (Status)': [['Form Type', 'formType'], ['Status', 'formStatus']] }; +const simpleColumnFieldMap = { + 'Term': [['Term', 'term']], + 'Department': [['Department', 'department']], + 'Student': [['First name', 'studentFirstName'], ['Last Name', 'studentLastName']], + 'Position': [['Position Type', 'positionType'], ['Position Title', 'positionTitle']], + 'Form Status': [['Status', 'formStatus']] +}; + function disableButtonHandler() { if ($('#departmentModalSelect :selected').val() == "" || $('#supervisorModalSelect :selected').val() == "") { @@ -119,11 +148,13 @@ function disableButtonHandler() { } function runFormSearchQuery(button) { + let view = $('#switchViewButton').val() let termCode, departmentID, supervisorID, studentID; let formStatusList = []; let formTypeList = []; var isDisabled = $('#fieldPicker').prop('disabled'); let sortBy = $('#fieldPicker').val() + // if the fieldPicker is disabled that means we should take the value // from the columnPicker instead @@ -138,7 +169,7 @@ function runFormSearchQuery(button) { departmentID = "" supervisorID = "currentUser" studentID = "" - formStatusList = [] + formStatusList = ["Approved", "Approved Reluctantly"] break; case "pendingForms": @@ -168,6 +199,7 @@ function runFormSearchQuery(button) { } queryDict = { + 'view': view, 'termCode': termCode, 'departmentID': departmentID, 'supervisorID': supervisorID, @@ -182,14 +214,82 @@ function runFormSearchQuery(button) { var inAnHour = new Date(new Date().getTime() + 60 * 60 * 1000); Cookies.set('lsfSearchResults', data, { expires: inAnHour }) + if (view === 'advanced') { + createDataTable(data) + } else { + fetchSimpleView(data) + } +} + +function resetColumns(columnFieldMap) { + // clear the current columnPicker options and populate it with new ones + // from either the simple or advanced columnFieldMap + $('#columnPicker').empty(); + let columns = Object.keys(columnFieldMap) + columns.forEach((column) => { + var option = $('