import axios, { AxiosInstance, AxiosResponse } from 'axios' import { errorInterceptor } from '@/util/interceptor' import { Credentials } from '@/store/modules/authentication' import { Assignment, Exam, Feedback, FeedbackComment, JSONWebToken, Statistics, StudentInfo, StudentInfoForListView, Submission, SubmissionNoType, SubmissionType, Tutor, UserAccount, LabelStatisticsForSubType, FeedbackLabel, SolutionComment, CreateUpdateFeedback, AvailableSubmissionCounts, Group, Config, GitlabRelease, } from '@/models' import { CreateAssignment } from './models' export function getInstanceBaseUrl (): string { if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') { return `${window.location.protocol}//${window.location.host}${window.location.pathname}`.replace(/\/+$/, '') } else { return 'http://localhost:8000/' } } let ax: AxiosInstance = axios.create({ baseURL: getInstanceBaseUrl() }) export async function registerTutor (credentials: Credentials): Promise<AxiosResponse<Tutor>> { return ax.post<Tutor>('/api/corrector/register/', credentials) } export async function fetchJWT (credentials: Credentials): Promise<JSONWebToken> { const token: string = (await ax.post('/api/get-token/', credentials)).data.token ax.defaults.headers['Authorization'] = `JWT ${token}` return { token } } export async function refreshJWT (oldToken: string): Promise<JSONWebToken> { const token: string = (await ax.post('/api/refresh-token/', { token: oldToken })).data.token ax.defaults.headers['Authorization'] = `JWT ${token}` return { token } } export async function fetchConfig (): Promise<Config> { return (await ax.get('/api/config/')).data } export async function fetchStudentSelfData (): Promise<StudentInfo> { return (await ax.get('/api/student-page/')).data } export async function fetchStudentSubmissions (): Promise<Array<Submission>> { return (await ax.get('/api/student-submissions/')).data } export async function fetchSubmissionFeedbackTests ({ pk }: {pk: string}): Promise<SubmissionNoType> { return (await ax.get(`/api/submission/${pk}/`)).data } export async function fetchSubmissionSourceCode(pk: string): Promise<{sourceCode: string}> { return (await ax.get(`/api/submission/${pk}/source_code/`)).data } export async function fetchNotebookSubmissionAsHtml(pk: string): Promise<any> { return (await ax.get(`/api/submission/${pk}/html/`)).data } export async function fetchAllStudents (): Promise<Array<StudentInfoForListView>> { const url = '/api/student/' return (await ax.get(url)).data } export async function fetchStudent ({ pk }: {pk: string}): Promise<StudentInfoForListView> { const url = `/api/student/${pk}/` return (await ax.get(url)).data } export async function fetchAllTutors (): Promise<Array<Tutor>> { const url = '/api/corrector/' return (await ax.get(url)).data } export async function fetchAllFeedback (): Promise<Array<Feedback>> { const url = '/api/feedback/' return (await ax.get(url)).data } export async function fetchFeedback ({ ofSubmission }: {ofSubmission: string}): Promise<Feedback> { const url = `/api/feedback/${ofSubmission}/` return (await ax.get(url)).data } export async function fetchExamTypes (): Promise<Array<Exam>> { const url = '/api/examtype/' return (await ax.get(url)).data } export async function fetchStatistics (): Promise<Statistics> { const url = '/api/statistics/' return (await ax.get(url)).data } export async function fetchLabelStatistics (): Promise<LabelStatisticsForSubType[]> { const url = '/api/label-statistics' return (await ax.get(url)).data } export async function createAssignment (data: CreateAssignment): Promise<Assignment> { return (await ax.post('/api/assignment/', data)).data } export async function submitFeedbackForAssignment ({ feedback, assignment }: { feedback: Partial<CreateUpdateFeedback>, assignment: Assignment}): Promise<CreateUpdateFeedback> { return (await ax.post(`/api/assignment/${assignment.pk}/finish/`, feedback)).data } export async function submitUpdatedFeedback ({ feedback }: {feedback: CreateUpdateFeedback}): Promise<CreateUpdateFeedback> { return (await ax.patch(`/api/feedback/${feedback.ofSubmission}/`, feedback)).data } export async function submitFeedback ({ feedback }: {feedback: CreateUpdateFeedback}): Promise<Feedback> { return (await ax.post('/api/feedback/', feedback)).data } export async function fetchSubmissionTypes (): Promise<Array<SubmissionType>> { const url = '/api/submissiontype/' return (await ax.get(url)).data } export async function fetchSubmissionType (pk: string): Promise<SubmissionType> { const url = `/api/submissiontype/${pk}/` return (await ax.get(url)).data } export async function fetchAvailableSubmissionCounts(group: Group | undefined): Promise<AvailableSubmissionCounts> { const query = group ? '?group=' + group.pk : '' const url = '/api/submissiontype/available/' + query return (await ax.get(url)).data } export async function fetchGroups(): Promise<Group[]> { const url = '/api/group/' return (await ax.get(url)).data } export async function deleteSolutionComment (pk: number): Promise<AxiosResponse<void>> { const url = `/api/solution-comment/${pk}/` return ax.delete(url) } export async function createSolutionComment(comment: Partial<SolutionComment>): Promise<SolutionComment> { const url = '/api/solution-comment/' return (await ax.post(url, comment)).data } export async function patchSolutionComment(comment: Partial<SolutionComment>): Promise<SolutionComment> { const url = `/api/solution-comment/${comment.pk}/` return (await ax.patch(url, comment)).data } export async function fetchAllAssignments (): Promise<Array<Assignment>> { const url = '/api/assignment/' return (await ax.get(url)).data } export async function fetchActiveAssignments (): Promise<Assignment[]> { const url = '/api/assignment/active/' return (await ax.get(url)).data } export async function deleteAssignment ({ assignment }: {assignment: Assignment}): Promise<AxiosResponse<void>> { const url = `/api/assignment/${assignment.pk}/` return ax.delete(url) } export async function deleteAllActiveAssignments () { const url = '/api/assignment/active/' return ax.delete(url) } export async function deleteComment (comment: FeedbackComment): Promise<AxiosResponse<void>> { const url = `/api/feedback-comment/${comment.pk}/` return ax.delete(url) } export async function activateAllStudentAccess (): Promise<AxiosResponse<void>> { return ax.post('/api/student/activate/') } export async function deactivateAllStudentAccess (): Promise<AxiosResponse<void>> { return ax.post('/api/student/deactivate/') } export async function changePassword (userPk: string, data: {password: string}): Promise<UserAccount> { return (await ax.patch(`/api/user/${userPk}/change_password/`, data)).data } export async function getOwnUser (): Promise<UserAccount> { return (await ax.get('/api/user/me/')).data } export async function changeActiveForUser (userPk: string, active: boolean): Promise<UserAccount> { return (await ax.patch(`/api/user/${userPk}/change_active/`, { 'is_active': active })).data } export async function getLabels (): Promise<FeedbackLabel[]> { return (await ax.get('/api/label/')).data } export async function createLabel (payload: Partial<FeedbackLabel>) { return (await ax.post('/api/label/', payload)).data } export async function updateLabel (payload: FeedbackLabel) { return (await ax.put('/api/label/' + payload.pk + '/', payload)).data } export async function fetchSubmissionCounts () { return (await ax.get('/api/submissiontype/available_counts/')).data } export async function releaseUndoneAssignments () { return (await ax.delete('/api/assignment/release')).data } export async function patchInstanceSettings(config: { [config: string]: boolean }) { return (await ax.patch('/api/config/change_config/', config)).data } /** * Issues a synchronized request to release all undone assignments of given user * @param accessToken The access token to authenticate against the backend */ export function releaseUndoneAssignmentsSynchronized (accessToken: string) { var request = new XMLHttpRequest() request.open('DELETE', getInstanceBaseUrl() + 'api/assignment/release/', false) request.setRequestHeader('Authorization', 'JWT ' + accessToken) request.send() } /** * Issues a synchronized request to disable the account for the given details * @param accessToken The access token to authenticate against the backend * @param userPk The pk of the user account to disable */ export function disableAccount (accessToken: string, userPk: string) { var request = new XMLHttpRequest() request.open('PATCH', getInstanceBaseUrl() + `api/user/${userPk}/change_active/`, false) request.setRequestHeader('Authorization', 'JWT ' + accessToken) request.setRequestHeader('Content-Type', 'application/json') request.send('{ "is_active": false }') } export async function fetchReleases () { const id = 'j.michal%2Fgrady' const url = `https://gitlab.gwdg.de/api/v4/projects/${id}/releases` return (await ax.get(url)).data as GitlabRelease[] } export interface StudentExportOptions { setPasswords?: boolean } export interface StudentExportItem { Matrikel: string, Name: string, Username: string, Sum: number, Exam: string, Password: string, Email: string, Scores: { type: string, score: number }[] } export async function fetchStudentExportData (options: StudentExportOptions): Promise<StudentExportItem[]> { return (await ax.post('/api/export/json/', options)).data } export async function importData (data: Object): Promise<AxiosResponse<void>> { return ax.post('/api/import/', data) } // Note, this interface does not represent all of the returned data, // but only the fields which have to be transformed for deanonymisation export interface InstanceExportData { students: { name: string, matrikelNo: string }[] } export async function fetchInstanceExportData (): Promise<InstanceExportData> { return (await ax.get('/api/instance/export')).data } ax.interceptors.response.use(undefined, errorInterceptor) export default ax