From a8e1128a0a8f5c997ef392e7dc0a552a3cdd37d6 Mon Sep 17 00:00:00 2001 From: mightycox Date: Wed, 11 Sep 2024 00:15:18 -0700 Subject: [PATCH] EDX-2853 - switches sldmove to use sdc api EDX-2869 - shows merged data on sld history and compare screens --- backend/package-lock.json | 40 +- backend/package.json | 3 +- backend/src/components/sdc/sdc.js | 15 +- backend/src/components/validator.js | 16 + backend/src/routes/sdc.js | 5 +- backend/src/util/constants.js | 4 + backend/src/validations/sdc.js | 14 + frontend/src/components/CompareStudents.vue | 14 +- .../common/CompareDemographicModal.vue | 56 +- .../common/CompareDemographicsCommon.vue | 1098 +---------------- .../common/CompareDemographicsCommonV1.vue | 1094 ++++++++++++++++ .../common/CompareDemographicsCommonV2.vue | 127 +- .../src/components/common/CustomTable.vue | 48 +- .../penreg/student/StudentSLDHistoryV2.vue | 80 +- frontend/src/router.js | 2 +- 15 files changed, 1394 insertions(+), 1222 deletions(-) create mode 100644 backend/src/components/validator.js create mode 100644 backend/src/validations/sdc.js create mode 100644 frontend/src/components/common/CompareDemographicsCommonV1.vue diff --git a/backend/package-lock.json b/backend/package-lock.json index f7f18f754..006bf2e6b 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -47,7 +47,8 @@ "strip-ansi": "^6.0.0", "uuid": "^8.3.2", "winston": "^3.5.0", - "winston-daily-rotate-file": "^4.5.0" + "winston-daily-rotate-file": "^4.5.0", + "yup": "^1.4.0" }, "devDependencies": { "@babel/cli": "^7.16.8", @@ -5286,6 +5287,11 @@ "node": ">=6.1" } }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -6152,6 +6158,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -6181,6 +6192,11 @@ "node": ">=0.6" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -6659,6 +6675,28 @@ "engines": { "node": ">=10" } + }, + "node_modules/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/backend/package.json b/backend/package.json index 8b3b21c05..4e5b3dc0c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -54,7 +54,8 @@ "strip-ansi": "^6.0.0", "uuid": "^8.3.2", "winston": "^3.5.0", - "winston-daily-rotate-file": "^4.5.0" + "winston-daily-rotate-file": "^4.5.0", + "yup": "^1.4.0" }, "devDependencies": { "@babel/cli": "^7.16.8", diff --git a/backend/src/components/sdc/sdc.js b/backend/src/components/sdc/sdc.js index 1e4bd79c7..79c5435ae 100644 --- a/backend/src/components/sdc/sdc.js +++ b/backend/src/components/sdc/sdc.js @@ -161,7 +161,7 @@ async function getSDCSchoolCollectionStudentPaginated(req, res) { if(req.query.assignedStudentID) { search.push({ condition: null, - searchCriteriaList: [{ key: 'assignedStudentId', value: req.query.assignedStudentID, operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.UUID }] + searchCriteriaList: [{ key: 'assignedStudentId', value: req.query.assignedStudentID.join(','), operation: FILTER_OPERATION.IN_NOT_DISTINCT, valueType: VALUE_TYPE.UUID }] }); } @@ -888,6 +888,16 @@ async function downloadSdcReport(req, res) { } } +async function moveSld (req, res) { + try { + await postData(`${config.get('sdc:schoolCollectionStudentURL')}/move-sld`, req.body); + return res.status(HttpStatus.OK).json(''); + } catch (e) { + logApiError(e, 'Error attempting to move sld record(s)'); + return errorResponse(res); + } +} + function getFileDetails(reportType) { const mappings = { 'ALL_STUDENT_DIS_CSV': { filename: 'AllDistrictStudents.csv', contentType: 'text/csv' }, @@ -929,5 +939,6 @@ module.exports = { getSdcSchoolCollections, getSdcDistrictCollections, downloadSdcReport, - updateBandCode + updateBandCode, + moveSld }; diff --git a/backend/src/components/validator.js b/backend/src/components/validator.js new file mode 100644 index 000000000..abb59d2f3 --- /dev/null +++ b/backend/src/components/validator.js @@ -0,0 +1,16 @@ +const validate = (schema) => async (req, res, next) => { + try { + await schema.validate({ + body: req.body, + query: req.query, + params: req.params, + }, { + stripUnknown: false + }); + next(); + } catch (e) { + return res.status(400).send(e.message); + } +}; + +module.exports = validate; diff --git a/backend/src/routes/sdc.js b/backend/src/routes/sdc.js index 82762cdae..731ce0678 100644 --- a/backend/src/routes/sdc.js +++ b/backend/src/routes/sdc.js @@ -8,7 +8,7 @@ const { getSnapshotFundingDataForSchool, getAllCollectionsForSchool, getActiveCo getIndySdcSchoolCollectionMonitoringByCollectionId, unsubmitSdcDistrictCollection, unsubmitSdcSchoolCollection, getInDistrictDuplicates, getSDCSchoolCollectionStudentPaginatedSlice, getSDCSchoolCollectionStudentPaginated, getSDCSchoolCollectionStudentDetail, updateStudentPEN, checkDuplicatesInCollection, updateAndValidateSdcSchoolCollectionStudent, resolveDuplicates, postProvincialDuplicates, resolveRemainingDuplicates, getInFlightDistrictProvincialDuplicates, getInFlightSchoolProvincialDuplicates, closeCollection, getCollectionPaginated, getSDCSchoolCollectionDetail, downloadSdcReport, - getCollectionByID, getSdcSchoolCollections, getSdcDistrictCollections, updateBandCode + getCollectionByID, getSdcSchoolCollections, getSdcDistrictCollections, updateBandCode, moveSld } = require('../components/sdc/sdc'); const {getCachedSDCData} = require('../components/sdc/sdc-cache'); const constants = require('../util/constants'); @@ -16,6 +16,8 @@ const {getCodes} = require('../components/utils'); const PERMISSION = perm.PERMISSION; const permUtils = require('../components/permissionUtils'); const auth = require('../components/auth'); +const validate = require('../components/validator'); +const { moveSldSchema } = require('../validations/sdc'); //cached code table calls router.get('/band-codes', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.STUDENT_DATA_COLLECTION), extendSession, getCachedSDCData(constants.CACHE_KEYS.SDC_BAND_CODES, 'sdc:bandCodesURL')); @@ -63,6 +65,7 @@ router.post('/sdcSchoolCollectionStudent/:sdcSchoolCollectionStudentID/update-pe //update student router.post('/sdcSchoolCollectionStudent', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.STUDENT_DATA_COLLECTION), extendSession, updateAndValidateSdcSchoolCollectionStudent); +router.post('/move-sld', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.STUDENT_DATA_COLLECTION), validate(moveSldSchema), extendSession, moveSld); //district collection router.post('/sdcDistrictCollection/:sdcDistrictCollectionID/unsubmit', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.STUDENT_DATA_COLLECTION), extendSession, permUtils.isValidUUIDParam('sdcDistrictCollectionID'), unsubmitSdcDistrictCollection); diff --git a/backend/src/util/constants.js b/backend/src/util/constants.js index 5a626ada2..5987b9cf3 100644 --- a/backend/src/util/constants.js +++ b/backend/src/util/constants.js @@ -106,6 +106,10 @@ const FILTER_OPERATION = Object.freeze( * Ends with filter operation. */ ENDS_WITH: 'ends_with', + /** + * In operation that does not include the DISTINCT condition + */ + IN_NOT_DISTINCT: 'in_not_distinct' } ); const CONDITION = Object.freeze( diff --git a/backend/src/validations/sdc.js b/backend/src/validations/sdc.js new file mode 100644 index 000000000..b71ca93c2 --- /dev/null +++ b/backend/src/validations/sdc.js @@ -0,0 +1,14 @@ +const { object, string, array } = require('yup'); + +const moveSldSchema = object({ + body: object({ + toStudentPen: string().nonNullable(), + sdcSchoolCollectionIdsToUpdate: array().of(string().nonNullable()) + }).noUnknown(), + params: object().noUnknown(), + query: object().noUnknown(), +}).noUnknown(); + +module.exports = { + moveSldSchema +}; diff --git a/frontend/src/components/CompareStudents.vue b/frontend/src/components/CompareStudents.vue index 0c87738a7..8ff53ebb7 100644 --- a/frontend/src/components/CompareStudents.vue +++ b/frontend/src/components/CompareStudents.vue @@ -5,35 +5,35 @@ id="compareClearBtn" text="Clear" secondary - @click-action="[cancel, clearError]" + @click-action="[cancel(), clearError()]" /> diff --git a/frontend/src/components/common/CompareDemographicModal.vue b/frontend/src/components/common/CompareDemographicModal.vue index deccff819..b6c413c5d 100644 --- a/frontend/src/components/common/CompareDemographicModal.vue +++ b/frontend/src/components/common/CompareDemographicModal.vue @@ -17,10 +17,11 @@ - - - @@ -113,15 +71,11 @@ import CompareDemographicsCommon from './CompareDemographicsCommon.vue'; import {deepCloneObject} from '@/utils/common'; import alertMixin from '@/mixins/alertMixin'; import staleStudentRecordMixin from '@/mixins/staleStudentRecordMixin'; -import CompareDemographicsCommonV2 from '@/components/common/CompareDemographicsCommonV2.vue'; -import {mapState} from 'pinia'; -import {appStore} from '@/store/modules/app'; export default { name: 'CompareDemographicModal', components: { CompareDemographicsCommon, - CompareDemographicsCommonV2, PrimaryButton, TertiaryButton }, @@ -140,7 +94,7 @@ export default { required: true } }, - emits: ['update:selectedRecords','closeCompare'], + emits: ['update:selectedRecords','closeCompare', 'refresh-sld-data'], data() { return { compareModalOpen: false, @@ -148,7 +102,6 @@ export default { }; }, computed: { - ...mapState(appStore, ['config']), studentRecords: { get: function() { return this.selectedRecords; @@ -156,9 +109,6 @@ export default { set: function(value) { this.$emit('update:selectedRecords', value); } - }, - useEdxRelease() { - return !this.config.DISABLE_SDC_FUNCTIONALITY; } }, created() { diff --git a/frontend/src/components/common/CompareDemographicsCommon.vue b/frontend/src/components/common/CompareDemographicsCommon.vue index 3d100bea4..2e4912432 100644 --- a/frontend/src/components/common/CompareDemographicsCommon.vue +++ b/frontend/src/components/common/CompareDemographicsCommon.vue @@ -1,1094 +1,56 @@