diff --git a/frontend/src/api/instructor_api.js b/frontend/src/api/instructor_api.js index fc50a59b..a7ceb1e0 100644 --- a/frontend/src/api/instructor_api.js +++ b/frontend/src/api/instructor_api.js @@ -1,4 +1,13 @@ import axios from 'axios'; +import http from './client'; + +let get_marks_csv = async (course_id, task) => { + try { + return await http.get(`/instructor/course/${course_id}/mark/all_csv?task=${task}`); + } catch (err) { + return err.response; + } +}; let all_tasks = async (course_id) => { let token = sessionStorage.getItem('token'); @@ -17,7 +26,6 @@ let all_tasks = async (course_id) => { } }; - let impersonate = async (course_id, username) => { let token = sessionStorage.getItem('token'); @@ -128,54 +136,69 @@ let submitMark = async (courseId, task, criteria, username, mark) => { // } // }; - let allGroups = async (course_id, task) => { - let token = sessionStorage.getItem("token") + let token = sessionStorage.getItem('token'); - let config = { - headers: { Authorization: `Bearer ${token}` } - }; + let config = { + headers: { Authorization: `Bearer ${token}` } + }; - try { - return await axios.get(process.env.REACT_APP_API_URL + "/instructor/course/" + course_id + "/group/all?task=" + task, config); - } catch (err) { - return err.response; - } -} + try { + return await axios.get( + process.env.REACT_APP_API_URL + + '/instructor/course/' + + course_id + + '/group/all?task=' + + task, + config + ); + } catch (err) { + return err.response; + } +}; let taskGroups = async (course_id, task) => { - /** - * Gets all groups for a particular task within a course. - */ - let token = sessionStorage.getItem("token"); - - let config = { - headers: { Authorization: `Bearer ${token}` } - }; + /** + * Gets all groups for a particular task within a course. + */ + let token = sessionStorage.getItem('token'); - try { - return await axios.get(process.env.REACT_APP_API_URL + "/instructor/course/" + course_id + "/group/all?task=" + task, config); - } catch (err) { - return err.response; - } -} + let config = { + headers: { Authorization: `Bearer ${token}` } + }; + try { + return await axios.get( + process.env.REACT_APP_API_URL + + '/instructor/course/' + + course_id + + '/group/all?task=' + + task, + config + ); + } catch (err) { + return err.response; + } +}; let InstructorApi = { - //Course related - all_tasks, - // Task related - impersonate, - taskGroups, - // - // // Group related - // check_group, - allGroups, - // - // // Interview related - // all_interviews, - // schedule_interview, - // delete_interview, + //Course related + all_tasks, + // Task related + impersonate, + taskGroups, + // + // // Group related + // check_group, + allGroups, + // + // // Interview related + // all_interviews, + // schedule_interview, + // delete_interview, + + // Mark related + get_marks_csv }; export default InstructorApi; diff --git a/frontend/src/components/General/AggregatedGradesTable/AggregatedGradesTable.jsx b/frontend/src/components/General/AggregatedGradesTable/AggregatedGradesTable.jsx index 2a7dca3e..475704e3 100644 --- a/frontend/src/components/General/AggregatedGradesTable/AggregatedGradesTable.jsx +++ b/frontend/src/components/General/AggregatedGradesTable/AggregatedGradesTable.jsx @@ -26,7 +26,6 @@ import { visuallyHidden } from '@mui/utils'; import FeatherIcon from 'feather-icons-react'; import CustomCheckbox from '../../FlexyMainComponents/forms/custom-elements/CustomCheckbox'; import CustomSwitch from '../../FlexyMainComponents/forms/custom-elements/CustomSwitch'; -import GetMarksCsvButton from './GetMarksCsvButton'; import TableSearchbar from './TableSearchbar'; function descendingComparator(a, b, orderBy) { @@ -219,7 +218,6 @@ const AggregatedGradesTable = ({ headCells, rows, tableWidth, courseId }) => { - { - /** - * Source: https://youtu.be/JPxzeG4N5nQ?t=660 - * Takes in a csv string and downloads it on the browsers - * @param text a string of characters in csv format - */ - const downloadCSV = (text) => { - const blob = new Blob([text], { type: 'application/csv' }); - const url = URL.createObjectURL(blob); - - const a = document.createElement('a'); - a.download = `course_${courseId}_marks.csv`; - a.href = url; - a.style.display = 'none'; - - document.body.append(a); - - a.click(); - a.remove(); - URL.revokeObjectURL(url); - }; - - const handleClick = () => { - StaffApi.getAllMarks(courseId) - .then((markRes) => { - StaffApi.all_tasks(courseId) - .then((taskRes) => { - const taskNames = taskRes.data.task.map((taskObj) => taskObj.task); - let csvHeader = 'username'; - for (const name of taskNames) { - csvHeader += `,${name}`; - } - const csvRows = Object.keys(markRes.data.marks).map((studentName) => { - // - let row = `${studentName}`; - - for (const taskName of Object.keys(markRes.data.marks[studentName])) { - const taskMark = markRes.data.marks[studentName][taskName]; - row += `,${taskMark.mark}/${taskMark.out_of}`; - } - - return row; - }); - let csvText = `${csvHeader}`; - for (const rowText of csvRows) { - csvText += `\n${rowText}`; - } - - downloadCSV(csvText); - }) - .catch((error) => toast.error('Unknown error', { theme: 'colored' })); - }) - .catch((error) => toast.error('Unknown error', { theme: 'colored' })); - }; - - return ( - - ); -}; - -export default getMarksCsvButton; diff --git a/frontend/src/components/Module/Mark/GetMarkCSVButton.jsx b/frontend/src/components/Module/Mark/GetMarkCSVButton.jsx new file mode 100644 index 00000000..518f9920 --- /dev/null +++ b/frontend/src/components/Module/Mark/GetMarkCSVButton.jsx @@ -0,0 +1,48 @@ +import { Button } from '@mui/material'; +import InstructorApi from '../../../api/instructor_api'; +import FileDownloadIcon from '@mui/icons-material/FileDownload'; + +/** + * Triggers a download of a CSV file containing marks for a given task within + * a given course + * @param task the task for which marks to fetch + * @param course_id the id of the course to which the task belongs to + * @returns {JSX.Element} + * @constructor + */ +const GetMarkCSVButton = ({ task, course_id }) => { + const downloadCSV = (text) => { + const blob = new Blob([text], { type: 'application/csv' }); + const url = URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.download = `course_${course_id}_marks.csv`; + a.href = url; + a.style.display = 'none'; + + document.body.append(a); + + a.click(); + a.remove(); + URL.revokeObjectURL(url); + }; + + const handleExport = () => { + InstructorApi.get_marks_csv(course_id, task) + .then((res) => res.data) + .then((data) => downloadCSV(data)); + }; + + return ( + + ); +}; + +export default GetMarkCSVButton;