Skip to content

Commit 48d3cbc

Browse files
Merge pull request #2324 from bcgov/feature/EAC-53
download xam file
2 parents c66f8c5 + d14557c commit 48d3cbc

File tree

4 files changed

+140
-86
lines changed

4 files changed

+140
-86
lines changed

backend/src/components/assessments/assessments.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const cacheService = require('../cache-service');
66
const { createMoreFiltersSearchCriteria } = require('./studentFilters');
77
const moment = require('moment');
88
const {DateTimeFormatter, LocalDate, LocalDateTime} = require('@js-joda/core');
9+
const log = require('../logger');
910

1011
async function getAssessmentSessions(req, res) {
1112
try {
@@ -195,6 +196,30 @@ async function updateAssessmentStudentByID(req, res) {
195196
}
196197
}
197198

199+
async function downloadXamFile(req, res) {
200+
try {
201+
const token = getAccessToken(req);
202+
const url = `${config.get('assessments:rootURL')}/report/${req.params.sessionID}/school/${req.params.schoolID}/download`;
203+
204+
const data = await getData(token, url);
205+
206+
const fileName = `${data?.reportType || 'SessionResults.xam'}`;
207+
res.setHeader('Content-Type', 'text/plain');
208+
res.setHeader('Content-Disposition', `attachment; filename=${fileName}`);
209+
210+
if (data && data.documentData) {
211+
const buffer = Buffer.from(data.documentData, 'base64');
212+
return res.send(buffer);
213+
} else {
214+
const emptyBuffer = Buffer.from('');
215+
return res.send(emptyBuffer);
216+
}
217+
} catch (e) {
218+
log.error(e, 'downloadXamFile', 'Error occurred while attempting to download XAM file.');
219+
return handleExceptionResponse(e, res);
220+
}
221+
}
222+
198223
function getSchoolName(school) {
199224
return school.mincode + ' - ' + school.schoolName;
200225
}
@@ -222,5 +247,7 @@ module.exports = {
222247
updateAssessmentStudentByID,
223248
deleteAssessmentStudentByID,
224249
getAssessmentSpecialCases,
225-
postAssessmentStudent
250+
postAssessmentStudent,
251+
downloadXamFile
226252
};
253+

backend/src/routes/assessments.js

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/src/components/assessments/reports/AssessmentReports.vue

Lines changed: 108 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<template>
22
<v-container fluid>
3-
43
<v-row>
54
<v-col>
65
<h3>Individual Student Reports</h3>
@@ -101,114 +100,123 @@
101100
<h3>Session Results</h3>
102101
</v-col>
103102
</v-row>
104-
<v-row v-if="userInfo.activeInstituteType === 'DISTRICT'" class="mt-n6">
103+
<v-row
104+
v-if="userInfo.activeInstituteType === 'DISTRICT'"
105+
class="mt-n6"
106+
>
105107
<v-col>
106108
<span
107-
style="color: gray;font-size: small"
108-
>
109-
Select a school and a session below to find the reports available for download.
110-
</span>
109+
style="color: gray;font-size: small"
110+
>
111+
Select a school and a session below to find the reports available for download.
112+
</span>
111113
</v-col>
112114
</v-row>
113-
<v-row v-else class="mt-n6">
115+
<v-row
116+
v-else
117+
class="mt-n6"
118+
>
114119
<v-col>
115120
<span
116-
style="color: gray;font-size: small"
117-
>
118-
Select a session below to find the reports available for download.
119-
</span>
121+
style="color: gray;font-size: small"
122+
>
123+
Select a session below to find the reports available for download.
124+
</span>
120125
</v-col>
121126
</v-row>
122127

123128
<v-row class="mt-n2">
124-
<v-col cols="4" v-if="userInfo.activeInstituteType === 'DISTRICT'">
125-
<v-autocomplete
126-
id="selectSchool"
127-
v-model="schoolNameNumberFilter"
128-
variant="underlined"
129-
:items="schoolSearchNames"
130-
color="#003366"
131-
label="School Name or Number"
132-
single-line
133-
:clearable="true"
134-
item-title="schoolCodeName"
135-
item-value="schoolCodeValue"
136-
autocomplete="off"
137-
/>
138-
</v-col>
129+
<v-col
130+
v-if="userInfo.activeInstituteType === 'DISTRICT'"
131+
cols="4"
132+
>
133+
<v-autocomplete
134+
id="selectSchool"
135+
v-model="schoolNameNumberFilter"
136+
variant="underlined"
137+
:items="schoolSearchNames"
138+
color="#003366"
139+
label="School Name or Number"
140+
single-line
141+
:clearable="true"
142+
item-title="schoolCodeName"
143+
item-value="schoolCodeValue"
144+
autocomplete="off"
145+
/>
146+
</v-col>
139147

140-
<v-col cols="4">
141-
<v-select
142-
id="selectedSession"
143-
v-model="selectedSessionID"
144-
variant="underlined"
145-
:items="sessionSearchNames"
146-
label="Session"
147-
item-title="sessionCodeName"
148-
item-value="sessionCodeValue"
149-
:rules="[rules.required()]"
150-
:clearable="true"
151-
/>
152-
</v-col>
148+
<v-col cols="4">
149+
<v-select
150+
id="selectedSession"
151+
v-model="selectedSessionID"
152+
variant="underlined"
153+
:items="sessionSearchNames"
154+
label="Session"
155+
item-title="sessionCodeName"
156+
item-value="sessionCodeValue"
157+
:rules="[rules.required()]"
158+
:clearable="true"
159+
/>
160+
</v-col>
153161
</v-row>
154162
<div :class="{ 'disabled-section': disableCondition }">
155163
<v-row
156164
no-gutters
157165
class="d-flex"
158166
>
159-
<v-card
160-
class="mt-2 mr-4"
161-
width="30em"
162-
border="sm"
163-
style="border: 1px solid black;border-radius: 10px;"
164-
>
165-
<v-card-title style="font-size: medium;">
166-
Assessment Results
167-
</v-card-title>
167+
<v-card
168+
class="mt-2 mr-4"
169+
width="30em"
170+
border="sm"
171+
style="border: 1px solid black;border-radius: 10px;"
172+
>
173+
<v-card-title style="font-size: medium;">
174+
Assessment Results
175+
</v-card-title>
168176

169-
<v-row class="pl-3 pb-3">
177+
<v-row class="pl-3 pb-3">
170178
<v-col cols="12">
171179
<DownloadLink
172180
label="Session Results.csv"
173181
:download-action="() => downloadDetailedDOARReport()"
174182
/>
175183
</v-col>
176-
</v-row>
177-
<v-row class="pl-3 pb-3 mt-n6">
184+
</v-row>
185+
<v-row class="pl-3 pb-3 mt-n6">
178186
<v-col cols="12">
179187
<DownloadLink
180188
label="Session Results.xam"
181-
:download-action="() => downloadDetailedDOARReport()"
189+
:download-action="() => downloadXamFile()"
182190
/>
183191
</v-col>
184-
</v-row>
185-
<v-row class="pl-3 pb-3 mt-n6">
192+
</v-row>
193+
<v-row class="pl-3 pb-3 mt-n6">
186194
<v-col cols="12">
187195
<DownloadLink
188196
label="Session Results by Student.pdf"
189-
:download-action="() => downloadDetailedDOARReport()"
197+
:download-action="() => downloadStudentReport()"
190198
/>
191199
</v-col>
192-
</v-row>
193-
<v-row class="pl-3 pb-3 mt-n6">
200+
</v-row>
201+
<v-row class="pl-3 pb-3 mt-n6">
194202
<v-col cols="12">
195203
<DownloadLink
196204
label="Session Results by Assessment.pdf"
197-
:download-action="() => downloadDetailedDOARReport()"
205+
:download-action="() => downloadAssessmentResults()"
198206
/>
199207
</v-col>
200-
</v-row>
201-
</v-card>
208+
</v-row>
209+
</v-card>
202210

203-
<v-card
204-
class="mt-2"
205-
width="30em"
206-
border="sm"
207-
style="border: 1px solid black;border-radius: 10px;"
208-
>
209-
<v-card-title style="font-size: medium;">
210-
Distribution of Assessment Results (DOAR)
211-
</v-card-title>
211+
<v-card
212+
class="mt-2"
213+
width="30em"
214+
border="sm"
215+
style="border: 1px solid black;border-radius: 10px;"
216+
>
217+
<v-card-title style="font-size: medium;">
218+
Distribution of Assessment Results (DOAR)
219+
</v-card-title>
212220
<v-row class="pl-3 pb-3">
213221
<v-col
214222
cols="12"
@@ -229,13 +237,11 @@
229237
/>
230238
</v-col>
231239
</v-row>
232-
</v-card>
240+
</v-card>
233241
</v-row>
234242
</div>
235243

236-
<div :class="{ 'disabled-section': !schoolNameNumberFilter }">
237-
238-
</div>
244+
<div :class="{ 'disabled-section': !schoolNameNumberFilter }" />
239245
</v-container>
240246
</template>
241247

@@ -283,6 +289,8 @@ export default {
283289
rules: Rules,
284290
schoolNameNumberFilter: null,
285291
schoolSearchNames: [],
292+
selectedSessionID: null,
293+
isDistrictUser: false
286294
};
287295
},
288296
computed: {
@@ -293,6 +301,9 @@ export default {
293301
}
294302
},
295303
async created() {
304+
authStore().getUserInfo().then(() => {
305+
this.isDistrictUser = this.userInfo.activeInstituteType !== 'SCHOOL';
306+
});
296307
await this.getAllSessions();
297308
this.setupSchoolLists();
298309
},
@@ -304,22 +315,22 @@ export default {
304315
this.schoolYearSessions = response.data.sort((a, b) =>
305316
LocalDateTime.parse(b.activeUntilDate).compareTo(LocalDateTime.parse(a.activeUntilDate))
306317
);
307-
}).catch((error) => {
308-
console.error(error);
309-
}).finally(() => {
310-
this.loading = false;
311-
this.setupSessions();
312-
});
318+
}).catch((error) => {
319+
console.error(error);
320+
}).finally(() => {
321+
this.loading = false;
322+
this.setupSessions();
323+
});
313324
},
314325
setupSessions() {
315326
let sessions = [];
316327
let sessionYearMinusTwo = LocalDate.now().minusYears(2).year();
317328
this.schoolYearSessions?.forEach((session) => {
318329
if(parseInt(session.courseYear) >= sessionYearMinusTwo){
319330
sessions.push({
320-
sessionCodeName: session.courseYear + '/' + session.courseMonth,
321-
sessionCodeValue: session.sessionID
322-
});
331+
sessionCodeName: session.courseYear + '/' + session.courseMonth,
332+
sessionCodeValue: session.sessionID
333+
});
323334
}
324335
});
325336
this.sessionSearchNames = sortBy(sessions, ['sessionCourseYear','sessionCourseMonth']);
@@ -358,7 +369,7 @@ export default {
358369
if (error?.response?.data?.message) {
359370
this.setErrorAlert(error?.response?.data?.message);
360371
} else {
361-
this.setErrorAlert(`PEN must be a valid.`);
372+
this.setErrorAlert('PEN must be a valid.');
362373
}
363374
}).finally(() => {
364375
this.isSearchingStudent = false;
@@ -378,7 +389,20 @@ export default {
378389
379390
},
380391
async downloadXamFile() {
381-
392+
this.isLoading = true;
393+
try {
394+
const url = `${ApiRoutes.assessments.BASE_REPORTS_URL}/${this.userInfo.activeInstituteType}/${this.selectedSessionID}/school/${this.schoolNameNumberFilter}/download`;
395+
window.open(url);
396+
} catch (error) {
397+
console.error(error);
398+
this.setFailureAlert(
399+
error?.response?.data?.message
400+
? error?.response?.data?.message
401+
: 'An error occurred while trying to retrieve your school\'s report.'
402+
);
403+
} finally {
404+
this.isLoading = false;
405+
}
382406
},
383407
async downloadGradProjections(){
384408

frontend/src/utils/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export const ApiRoutes = Object.freeze({
143143
GET_ASSESSMENT_SPECIALCASE_TYPES: assessmentsRoot + '/assessment-specialcase-types',
144144
ASSESSMENT_STUDENTS: assessmentsRoot + '/assessment-registrations/student',
145145
GET_ASSESSMENT_STUDENTS_PAGINATED: assessmentsRoot + '/assessment-registrations/paginated',
146+
BASE_REPORTS_URL: assessmentsRoot + '/reports',
146147
},
147148
challengeReports: {
148149
BASE_URL: challengeReportsRoot

0 commit comments

Comments
 (0)