From f1f91c0b680aad99a2eaa72a77bc927e8aea5bc2 Mon Sep 17 00:00:00 2001 From: Eckerman Date: Wed, 20 Nov 2024 13:37:44 -0800 Subject: [PATCH] displays student registrations for sch/dis --- backend/src/components/cache-service.js | 42 +++- backend/src/components/eas/eas.js | 13 +- backend/src/components/eas/studentFilters.js | 36 +--- backend/src/server.js | 15 ++ ...Detail.vue => AssessmentSessionDetail.vue} | 15 +- .../assessments/AssessmentSessions.vue | 45 +++-- .../registrations/StudentRegistrations.vue | 60 +++--- .../StudentRegistrationsCustomTable.vue | 90 ++------- .../StudentRegistrationsFilter.vue | 142 ++++--------- .../assessments/sessions/SessionCard.vue | 31 +-- frontend/src/router.js | 23 +++ frontend/src/utils/constants.js | 1 + .../StudentRegistrationTableConfiguration.js | 189 ++++++++++++++++++ 13 files changed, 427 insertions(+), 275 deletions(-) rename frontend/src/components/assessments/{AssessmentSessionsDetail.vue => AssessmentSessionDetail.vue} (83%) create mode 100644 frontend/src/utils/eas/StudentRegistrationTableConfiguration.js diff --git a/backend/src/components/cache-service.js b/backend/src/components/cache-service.js index 6d8bcc7e..232ac92d 100644 --- a/backend/src/components/cache-service.js +++ b/backend/src/components/cache-service.js @@ -32,6 +32,8 @@ let specialEducationCodesMap = new Map(); let homeLanguageSpokenCodesMap = new Map(); let rolePermissionsMap = new Map(); let documentTypeCodesMap = new Map(); +let assessmentTypeCodesMap = new Map(); +let assessmentSpecialCaseTypeCodesMap = new Map(); let documentTypeCodes = []; const cachedData = {}; @@ -102,6 +104,38 @@ const cacheService = { }); }, + async loadAllAssessmentTypeCodesToMap() { + log.debug('Loading all assessment Type Codes during start up'); + await retry(async () => { + const data = await getApiCredentials(); + const assessmentTypeCodesResponse = await getData(data.accessToken, `${config.get('eas:assessmentTypeCodeURL')}`); + if (assessmentTypeCodesResponse && assessmentTypeCodesResponse.length > 0) { + assessmentTypeCodesMap.clear(); + assessmentTypeCodesResponse.forEach(entry => { + assessmentTypeCodesMap.set(entry.assessmentTypeCode, entry.label); + }); + } + log.info(`Loaded ${assessmentTypeCodesMap.size} assessmentTypeCodes.`); + }, { + retries: 50 + }); + }, + async loadAllSpecialCaseTypeCodesToMap() { + log.debug('Loading all specialcase Type Codes during start up'); + await retry(async () => { + const data = await getApiCredentials(); + const provincialSpecialCaseTypeCodesResponse = await getData(data.accessToken, `${config.get('eas:assessmentSpecialCaseTypeCodeURL')}`); + if (provincialSpecialCaseTypeCodesResponse && provincialSpecialCaseTypeCodesResponse.length > 0) { + assessmentSpecialCaseTypeCodesMap.clear(); + provincialSpecialCaseTypeCodesResponse.forEach(entry => { + assessmentSpecialCaseTypeCodesMap.set(entry.provincialSpecialCaseCode, entry.label); + }); + } + log.info(`Loaded ${assessmentSpecialCaseTypeCodesMap.size} assessmentSpecialCaseTypeCodes.`); + }, { + retries: 50 + }); + }, getAllActiveAuthoritiesJSON(){ return activeAuthorities; }, @@ -346,7 +380,13 @@ const cacheService = { }, getAllStudentValidationIssueCodes() { return cachedData[constants.CACHE_KEYS.SDC_VALIDATION_ISSUE_TYPE_CODES].records; - } + }, + getAssessmentTypeLabelByCode(assessmentTypeCode) { + return assessmentTypeCodesMap.get(assessmentTypeCode); + }, + getSpecialCaseTypeLabelByCode(specialCaseTypeCode) { + return assessmentSpecialCaseTypeCodesMap.get(specialCaseTypeCode); + }, }; module.exports = cacheService; diff --git a/backend/src/components/eas/eas.js b/backend/src/components/eas/eas.js index 7645fd57..33273e9b 100644 --- a/backend/src/components/eas/eas.js +++ b/backend/src/components/eas/eas.js @@ -1,5 +1,5 @@ 'use strict'; -const { logApiError, getAccessToken, getData, errorResponse, handleExceptionResponse } = require('../utils'); +const { logApiError, getAccessToken, getData, getDataWithParams, errorResponse, handleExceptionResponse } = require('../utils'); const HttpStatus = require('http-status-codes'); const config = require('../../config'); const cacheService = require('../cache-service'); @@ -36,7 +36,8 @@ async function getActiveAssessmentSessions(req, res) { async function getAssessmentSessionsBySchoolYear(req, res) { try { const url = `${config.get('eas:assessmentSessionsURL')}/school-year/${req.params.schoolYear}`; - let data = await getData(url); + const token = getAccessToken(req); + let data = await getData(token, url); data.forEach(session => { session.assessments.forEach(assessment => { assessment.assessmentTypeName = cacheService.getAssessmentTypeLabelByCode(assessment.assessmentTypeCode)+' ('+assessment.assessmentTypeCode+')'; @@ -49,7 +50,6 @@ async function getAssessmentSessionsBySchoolYear(req, res) { } } - async function getAssessmentStudentsPaginated(req, res) { try { const search = []; @@ -70,7 +70,8 @@ async function getAssessmentStudentsPaginated(req, res) { } }; - let data = await getData(`${config.get('eas:assessmentStudentsURL')}/paginated`, params); + const token = getAccessToken(req); + let data = await getDataWithParams(token,`${config.get('eas:assessmentStudentsURL')}/paginated`, params); if (req?.query?.returnKey) { let result = data?.content.map((student) => student[req?.query?.returnKey]); @@ -79,7 +80,7 @@ async function getAssessmentStudentsPaginated(req, res) { data?.content.forEach(value => { let school = cacheService.getSchoolBySchoolID(value.schoolID); let assessmentCenter = cacheService.getSchoolBySchoolID(value.assessmentCenterID); - let district = cacheService.getDistrictJSONByDistrictId(school.districtID); + let district = cacheService.getDistrictJSONByDistrictID(school.districtID); value.schoolNumber = school.mincode; value.schoolName = getSchoolName(school); @@ -90,7 +91,7 @@ async function getAssessmentStudentsPaginated(req, res) { value.assessmentCenterName = getSchoolName(assessmentCenter); value.assessmentTypeName = cacheService.getAssessmentTypeLabelByCode(value.assessmentTypeCode)+' ('+value.assessmentTypeCode+')'; - value.provincialSpecialCaseName = cacheService.getSpecialCaseTypeLabelByCode(value.provincialSpecialCaseCode); + value.provincialSpecialCaseName = value.provincialSpecialCaseName ? cacheService.getSpecialCaseTypeLabelByCode(value.provincialSpecialCaseCode) : '-'; value.sessionName = moment(value.courseMonth, 'MM').format('MMMM') +' '+value.courseYear; }); diff --git a/backend/src/components/eas/studentFilters.js b/backend/src/components/eas/studentFilters.js index fe51dcc4..b3767d12 100644 --- a/backend/src/components/eas/studentFilters.js +++ b/backend/src/components/eas/studentFilters.js @@ -4,7 +4,6 @@ const { FILTER_OPERATION, VALUE_TYPE, CONDITION} = require('../../util/constants function createMoreFiltersSearchCriteria(searchFilter = []) { let searchCriteriaList = []; - let districtNameNumberFilter = []; let schoolNameNumberFilter = []; let assessmentCenterNameNumberFilter = []; @@ -21,6 +20,10 @@ function createMoreFiltersSearchCriteria(searchFilter = []) { searchCriteriaList.push({ key: 'surName', value: pValue.toString(), operation: FILTER_OPERATION.CONTAINS_IGNORE_CASE, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND }); } + if (key === 'givenName' && pValue) { + searchCriteriaList.push({ key: 'givenName', value: pValue.toString(), operation: FILTER_OPERATION.CONTAINS_IGNORE_CASE, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND }); + } + if (key === 'pen' && pValue) { searchCriteriaList.push({ key: 'pen', value: pValue.toString(), operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND }); } @@ -29,9 +32,12 @@ function createMoreFiltersSearchCriteria(searchFilter = []) { searchCriteriaList.push({ key: 'localID', value: pValue.toString(), operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND }); } - if (key === 'districtNameNumber' && pValue) { - let districtNameNumberCriteria = createDistrictNameNumberSearchCriteria(pValue.toString()); - districtNameNumberFilter = [...districtNameNumberCriteria]; + if (key === 'districtID' && pValue) { + searchCriteriaList.push({key: 'districtID', value: pValue[0], operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.UUID, condition: CONDITION.AND}) + } + + if (key === 'schoolID' && pValue) { + searchCriteriaList.push({key: 'schoolID', value: pValue[0], operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.UUID, condition: CONDITION.AND}) } if (key === 'schoolNameNumber' && pValue) { @@ -69,13 +75,7 @@ function createMoreFiltersSearchCriteria(searchFilter = []) { } } - const search = []; - if (districtNameNumberFilter.length > 0) { - search.push({ - condition: CONDITION.AND, - searchCriteriaList: districtNameNumberFilter - }); - } + const search = []; if (schoolNameNumberFilter.length > 0) { search.push({ condition: CONDITION.AND, @@ -97,20 +97,6 @@ function createMoreFiltersSearchCriteria(searchFilter = []) { return search; } -function createDistrictNameNumberSearchCriteria(value) { - const searchDistrictCriteriaList = []; - - searchDistrictCriteriaList.push({ - key: 'districtID', - operation: FILTER_OPERATION.EQUAL, - value: value, - valueType: VALUE_TYPE.UUID, - condition: CONDITION.AND - }); - - return searchDistrictCriteriaList; -} - function createSchoolNameNumberSearchCriteria(value) { const searchSchoolCriteriaList = []; diff --git a/backend/src/server.js b/backend/src/server.js index 37e71eba..05c18349 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -24,6 +24,7 @@ const NATS = require('./messaging/message-pub-sub'); if(process.env.NODE_ENV !== 'test'){ //do not cache for test environment to stop GitHub Actions test from hanging. const cacheService = require('./components/cache-service'); const sdcDisabled = config.get('frontendConfig').disableSdcFunctionality; + const easDisabled = config.get('frontendConfig').disableEASFunctionality; cacheService.loadAllSchoolsToMap().then(() => { log.info('Loaded school data to memory'); }).catch((e) => { @@ -106,6 +107,20 @@ if(process.env.NODE_ENV !== 'test'){ //do not cache for test environment to sto log.error('Error loading DISTRICT_CONTACT_TYPES data during boot .', e); require('./schedulers/cache-service-scheduler'); }); + + if(!easDisabled) { + cacheService.loadAllAssessmentTypeCodesToMap().then(() => { + log.info('Loaded AssessmentTypeCodes data to memory'); + }).catch((e) => { + log.error('Error loading AssessmentTypeCodes during boot .', e); + }); + cacheService.loadAllSpecialCaseTypeCodesToMap().then(() => { + log.info('Loaded SpecialCaseTypeCodes data to memory'); + }).catch((e) => { + log.error('Error loading SpecialCaseTypeCodes during boot .', e); + }); + } + if(!sdcDisabled) { cacheService.loadDataToCache(constants.CACHE_KEYS.SDC_BAND_CODES, 'sdc:bandCodesURL').then(() => { log.info('Loaded SDC_BAND_CODES data to memory'); diff --git a/frontend/src/components/assessments/AssessmentSessionsDetail.vue b/frontend/src/components/assessments/AssessmentSessionDetail.vue similarity index 83% rename from frontend/src/components/assessments/AssessmentSessionsDetail.vue rename to frontend/src/components/assessments/AssessmentSessionDetail.vue index 5e3e4406..cb88811e 100644 --- a/frontend/src/components/assessments/AssessmentSessionsDetail.vue +++ b/frontend/src/components/assessments/AssessmentSessionDetail.vue @@ -41,11 +41,11 @@ diff --git a/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue b/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue index 95c01761..2dbf6da2 100644 --- a/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue +++ b/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue @@ -18,7 +18,7 @@ diff --git a/frontend/src/router.js b/frontend/src/router.js index 1fe3a867..ff42476f 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -35,6 +35,7 @@ import {PERMISSION} from './utils/constants/Permission'; import GraduationTableComponent from './components/graduation/GraduationTableComponent.vue'; import GradUploadDataComponent from './components/graduation/grad-data-collection/GradUploadDataComponent.vue'; import AssessmentSessions from './components/assessments/AssessmentSessions.vue'; +import AssessmentSessionDetail from './components/assessments/AssessmentSessionDetail.vue'; import GradProjectionsTVR from './components/graduation/grad-data-collection/projections/GradProjectionsTVR.vue'; import GradReportsAndTranscripts from './components/graduation/grad-data-collection/reports/GradReportsAndTranscripts.vue'; @@ -366,6 +367,28 @@ const router = createRouter({ permission: PERMISSION.EAS_SCH_EDIT }, }, + { + path: '/assessment-sessions/details/:schoolYear/:sessionID?', + name: 'district-assessment-session-detail', + component: AssessmentSessionDetail, + props: true, + meta: { + pageTitle: PAGE_TITLES.ASSESSMENT_SESSION_DETAIL, + requiresAuth: true, + permission: PERMISSION.EAS_DIS_EDIT + }, + }, + { + path: '/assessment-sessions/details/:schoolYear/:sessionID?', + name: 'school-assessment-session-detail', + component: AssessmentSessionDetail, + props: true, + meta: { + pageTitle: PAGE_TITLES.ASSESSMENT_SESSION_DETAIL, + requiresAuth: true, + permission: PERMISSION.EAS_SCH_EDIT + }, + }, { path: 'graduation/:schoolID/projections', name: 'grad-projections', diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index d1e1381a..0ddaa488 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -161,6 +161,7 @@ export const PAGE_TITLES = Object.freeze({ GRAD_DATA_COLLECTION: 'Graduation Records and Achievement Data Collection', ASSESSMENT: 'Assessments', ASSESSMENT_SESSIONS: 'Assessment Sessions', + ASSESSMENT_SESSION_DETAIL: 'Assessment Session Detail', GRAD_PROJECTIONS: 'Graduation Projections and TVRs', GRAD_REPORTS: 'Graduation Reports and Transcripts' }); diff --git a/frontend/src/utils/eas/StudentRegistrationTableConfiguration.js b/frontend/src/utils/eas/StudentRegistrationTableConfiguration.js new file mode 100644 index 00000000..9bf40493 --- /dev/null +++ b/frontend/src/utils/eas/StudentRegistrationTableConfiguration.js @@ -0,0 +1,189 @@ +export const SESSION_CODE_FILTER = Object.freeze( + { + heading: 'Session', + id: 'sessionTypeCode', + multiple: false, + key: 'sessionTypeCode', + filterOptions: [ + ] + } +); + +export const ASSESSMENT_TYPE_CODE_FILTER = Object.freeze( + { + heading: 'Assessment / Course', + id: 'assessmentTypeCode', + multiple: true, + key: 'assessmentTypeCode', + filterOptions: [ + ] + } +); + +export const SPECIAL_CASE_FILTER = Object.freeze( + { + heading: 'Special Case', + id: 'specialCaseCode', + multiple: true, + key: 'specialCaseCode', + filterOptions: [ + { + title: 'Aegrotat', + id: 'aegrotat', + value: 'A' + }, + { + title: 'Exemption', + id: 'exemption', + value: 'E' + }, + { + title: 'Disqualified', + id: 'disqualified', + value: 'D' + } + ] + } +); + +export const PROFICIENCY_SCORE_FILTER = Object.freeze( + { + heading: 'Proficiency Score', + id: 'proficiencyScore', + multiple: false, + key: 'proficiencyScore', + filterOptions: [ + { + title: 'Have Results', + id: 'results', + value: 'true' + }, + { + title: 'No Results Received', + id: 'noResults', + value: 'false' + } + ] + } +); + +export const PROFICIENCY_SCORE_RANGE_FILTER = Object.freeze( + { + heading: '', + id: 'proficiencyScoreValue', + multiple: true, + key: 'proficiencyScoreValue', + filterOptions: [ + { + title: '1', + id: '1', + value: '1' + }, + { + title: '2', + id: '2', + value: '2' + }, + { + title: '3', + id: '3', + value: '3' + }, + { + title: '4', + id: '4', + value: '4' + } + ] + } +); + +export const SCHOOL_YEAR_REGISTRATIONS_VIEW_DISTRICT = Object.freeze( + { + tableHeaders: [ + { title: 'Session', key: 'sessionName'}, + { title: 'School', key: 'schoolName' }, + { title: 'Assessment Center', key: 'assessmentCenterName' }, + { title: 'PEN', key: 'pen' }, + { title: 'Local ID', key: 'localID' }, + { title: 'Surname', key: 'surName' }, + { title: 'Given Name', key: 'givenName' }, + { title: 'Course Name (Code)', key: 'assessmentTypeName' }, + { title: 'Special Case', key: 'provincialSpecialCaseName' }, + { title: 'Proficiency Score', key: 'proficiencyScore' }, + ], + allowedFilters: { + session: SESSION_CODE_FILTER, + assessmentTypeCode: ASSESSMENT_TYPE_CODE_FILTER, + specialCaseCode: SPECIAL_CASE_FILTER, + proficiencyScore: PROFICIENCY_SCORE_FILTER, + proficiencyScoreValue: PROFICIENCY_SCORE_RANGE_FILTER + } + }); + +export const SCHOOL_YEAR_REGISTRATIONS_VIEW_SCHOOL = Object.freeze( + { + tableHeaders: [ + { title: 'Session', key: 'sessionName'}, + { title: 'Assessment Center', key: 'assessmentCenterName' }, + { title: 'PEN', key: 'pen' }, + { title: 'Local ID', key: 'localID' }, + { title: 'Surname', key: 'surName' }, + { title: 'Given Name', key: 'givenName' }, + { title: 'Course Name (Code)', key: 'assessmentTypeName' }, + { title: 'Special Case', key: 'provincialSpecialCaseName' }, + { title: 'Proficiency Score', key: 'proficiencyScore' }, + ], + allowedFilters: { + session: SESSION_CODE_FILTER, + assessmentTypeCode: ASSESSMENT_TYPE_CODE_FILTER, + specialCaseCode: SPECIAL_CASE_FILTER, + proficiencyScore: PROFICIENCY_SCORE_FILTER, + proficiencyScoreValue: PROFICIENCY_SCORE_RANGE_FILTER + } + }); + +export const SESSION_REGISTRATIONS_VIEW_DISTRICT = Object.freeze( + { + tableHeaders: [ + { title: 'Session', key: 'sessionName'}, + { title: 'School', key: 'schoolName' }, + { title: 'Assessment Center', key: 'assessmentCenterName' }, + { title: 'PEN', key: 'pen' }, + { title: 'Local ID', key: 'localID' }, + { title: 'Surname', key: 'surName' }, + { title: 'Given Name', key: 'givenName' }, + { title: 'Course Name (Code)', key: 'assessmentTypeName' }, + { title: 'Special Case', key: 'provincialSpecialCaseName' }, + { title: 'Proficiency Score', key: 'proficiencyScore' }, + ], + allowedFilters: { + session: SESSION_CODE_FILTER, + assessmentTypeCode: ASSESSMENT_TYPE_CODE_FILTER, + specialCaseCode: SPECIAL_CASE_FILTER, + proficiencyScore: PROFICIENCY_SCORE_FILTER, + proficiencyScoreValue: PROFICIENCY_SCORE_RANGE_FILTER + } + }); + +export const SESSION_REGISTRATIONS_VIEW_SCHOOL = Object.freeze( + { + tableHeaders: [ + { title: 'Session', key: 'sessionName'}, + { title: 'Assessment Center', key: 'assessmentCenterName' }, + { title: 'PEN', key: 'pen' }, + { title: 'Local ID', key: 'localID' }, + { title: 'Surname', key: 'surName' }, + { title: 'Given Name', key: 'givenName' }, + { title: 'Course Name (Code)', key: 'assessmentTypeName' }, + { title: 'Special Case', key: 'provincialSpecialCaseName' }, + { title: 'Proficiency Score', key: 'proficiencyScore' }, + ], + allowedFilters: { + session: SESSION_CODE_FILTER, + assessmentTypeCode: ASSESSMENT_TYPE_CODE_FILTER, + specialCaseCode: SPECIAL_CASE_FILTER, + proficiencyScore: PROFICIENCY_SCORE_FILTER, + proficiencyScoreValue: PROFICIENCY_SCORE_RANGE_FILTER + } + });