merge: merge fix/183-post-assignment into dev
This commit is contained in:
commit
5a593cb88f
67 changed files with 2205 additions and 2129 deletions
|
@ -1,7 +1,7 @@
|
|||
import { EntityDTO } from '@mikro-orm/core';
|
||||
import { getGroupRepository, getSubmissionRepository } from '../data/repositories.js';
|
||||
import { Group } from '../entities/assignments/group.entity.js';
|
||||
import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js';
|
||||
import { mapToGroupDTO, mapToGroupDTOId, mapToShallowGroupDTO } from '../interfaces/group.js';
|
||||
import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js';
|
||||
import { GroupDTO, GroupDTOId } from '@dwengo-1/common/interfaces/group';
|
||||
import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission';
|
||||
|
|
|
@ -1,12 +1,34 @@
|
|||
import { getQuestionRepository } from '../data/repositories.js';
|
||||
import { getAnswerRepository, getAssignmentRepository, getClassRepository, getGroupRepository, getQuestionRepository } from '../data/repositories.js';
|
||||
import { mapToLearningObjectID, mapToQuestionDTO, mapToQuestionDTOId } from '../interfaces/question.js';
|
||||
import { Question } from '../entities/questions/question.entity.js';
|
||||
import { Answer } from '../entities/questions/answer.entity.js';
|
||||
import { mapToAnswerDTO, mapToAnswerDTOId } from '../interfaces/answer.js';
|
||||
import { QuestionRepository } from '../data/questions/question-repository.js';
|
||||
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
|
||||
import { QuestionData, QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
|
||||
import { AnswerDTO, AnswerId } from '@dwengo-1/common/interfaces/answer';
|
||||
import { mapToAssignment } from '../interfaces/assignment.js';
|
||||
import { AssignmentDTO } from '@dwengo-1/common/interfaces/assignment';
|
||||
import { fetchStudent } from './students.js';
|
||||
import { NotFoundException } from '../exceptions/not-found-exception.js';
|
||||
import { FALLBACK_VERSION_NUM } from '../config.js';
|
||||
import { fetchStudent } from './students.js';
|
||||
|
||||
export async function getQuestionsAboutLearningObjectInAssignment(
|
||||
loId: LearningObjectIdentifier,
|
||||
classId: string,
|
||||
assignmentId: number,
|
||||
full: boolean,
|
||||
studentUsername?: string
|
||||
): Promise<QuestionDTO[] | QuestionId[]> {
|
||||
const assignment = await getAssignmentRepository().findByClassIdAndAssignmentId(classId, assignmentId);
|
||||
|
||||
const questions = await getQuestionRepository().findAllQuestionsAboutLearningObjectInAssignment(loId, assignment!, studentUsername);
|
||||
|
||||
if (full) {
|
||||
return questions.map((q) => mapToQuestionDTO(q));
|
||||
}
|
||||
return questions.map((q) => mapToQuestionDTOId(q));
|
||||
}
|
||||
|
||||
export async function getAllQuestions(id: LearningObjectIdentifier, full: boolean): Promise<QuestionDTO[] | QuestionId[]> {
|
||||
const questionRepository: QuestionRepository = getQuestionRepository();
|
||||
|
@ -38,14 +60,40 @@ export async function getQuestion(questionId: QuestionId): Promise<QuestionDTO>
|
|||
return mapToQuestionDTO(question);
|
||||
}
|
||||
|
||||
export async function getAnswersByQuestion(questionId: QuestionId, full: boolean): Promise<AnswerDTO[] | AnswerId[]> {
|
||||
const answerRepository = getAnswerRepository();
|
||||
const question = await fetchQuestion(questionId);
|
||||
|
||||
if (!question) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const answers: Answer[] = await answerRepository.findAllAnswersToQuestion(question);
|
||||
|
||||
if (!answers) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (full) {
|
||||
return answers.map(mapToAnswerDTO);
|
||||
}
|
||||
|
||||
return answers.map(mapToAnswerDTOId);
|
||||
}
|
||||
|
||||
export async function createQuestion(loId: LearningObjectIdentifier, questionData: QuestionData): Promise<QuestionDTO> {
|
||||
const questionRepository = getQuestionRepository();
|
||||
const author = await fetchStudent(questionData.author!);
|
||||
const content = questionData.content;
|
||||
|
||||
const clazz = await getClassRepository().findById((questionData.inGroup.assignment as AssignmentDTO).within);
|
||||
const assignment = mapToAssignment(questionData.inGroup.assignment as AssignmentDTO, clazz!);
|
||||
const inGroup = await getGroupRepository().findByAssignmentAndGroupNumber(assignment, questionData.inGroup.groupNumber);
|
||||
|
||||
const question = await questionRepository.createQuestion({
|
||||
loId,
|
||||
author,
|
||||
inGroup: inGroup!,
|
||||
content,
|
||||
});
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
getSubmissionRepository,
|
||||
} from '../data/repositories.js';
|
||||
import { mapToClassDTO } from '../interfaces/class.js';
|
||||
import { mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js';
|
||||
import { mapToGroupDTO, mapToGroupDTOId, mapToShallowGroupDTO } from '../interfaces/group.js';
|
||||
import { mapToStudent, mapToStudentDTO } from '../interfaces/student.js';
|
||||
import { mapToSubmissionDTO, mapToSubmissionDTOId } from '../interfaces/submission.js';
|
||||
import { getAllAssignments } from './assignments.js';
|
||||
|
@ -24,6 +24,7 @@ import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/subm
|
|||
import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
|
||||
import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request';
|
||||
import { ConflictException } from '../exceptions/conflict-exception.js';
|
||||
import { Submission } from '../entities/assignments/submission.entity';
|
||||
|
||||
export async function getAllStudents(full: boolean): Promise<StudentDTO[] | string[]> {
|
||||
const studentRepository = getStudentRepository();
|
||||
|
@ -113,7 +114,8 @@ export async function getStudentSubmissions(username: string, full: boolean): Pr
|
|||
const student = await fetchStudent(username);
|
||||
|
||||
const submissionRepository = getSubmissionRepository();
|
||||
const submissions = await submissionRepository.findAllSubmissionsForStudent(student);
|
||||
|
||||
const submissions: Submission[] = await submissionRepository.findAllSubmissionsForStudent(student);
|
||||
|
||||
if (full) {
|
||||
return submissions.map(mapToSubmissionDTO);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { getSubmissionRepository } from '../data/repositories.js';
|
||||
import { getAssignmentRepository, getSubmissionRepository } from '../data/repositories.js';
|
||||
import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js';
|
||||
import { NotFoundException } from '../exceptions/not-found-exception.js';
|
||||
import { mapToSubmission, mapToSubmissionDTO } from '../interfaces/submission.js';
|
||||
|
@ -6,6 +6,7 @@ import { SubmissionDTO } from '@dwengo-1/common/interfaces/submission';
|
|||
import { fetchStudent } from './students.js';
|
||||
import { getExistingGroupFromGroupDTO } from './groups.js';
|
||||
import { Submission } from '../entities/assignments/submission.entity.js';
|
||||
import { Language } from '@dwengo-1/common/util/language';
|
||||
|
||||
export async function fetchSubmission(loId: LearningObjectIdentifier, submissionNumber: number): Promise<Submission> {
|
||||
const submissionRepository = getSubmissionRepository();
|
||||
|
@ -32,9 +33,7 @@ export async function getAllSubmissions(loId: LearningObjectIdentifier): Promise
|
|||
|
||||
export async function createSubmission(submissionDTO: SubmissionDTO): Promise<SubmissionDTO> {
|
||||
const submitter = await fetchStudent(submissionDTO.submitter.username);
|
||||
// TODO: fix
|
||||
// const group = submissionDTO.group ? await getExistingGroupFromGroupDTO(submissionDTO.group) : undefined;
|
||||
const group = undefined;
|
||||
const group = await getExistingGroupFromGroupDTO(submissionDTO.group!);
|
||||
|
||||
const submissionRepository = getSubmissionRepository();
|
||||
const submission = mapToSubmission(submissionDTO, submitter, group);
|
||||
|
@ -51,3 +50,22 @@ export async function deleteSubmission(loId: LearningObjectIdentifier, submissio
|
|||
|
||||
return mapToSubmissionDTO(submission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the submissions made by on behalf of any group the given student is in.
|
||||
*/
|
||||
export async function getSubmissionsForLearningObjectAndAssignment(
|
||||
learningObjectHruid: string,
|
||||
language: Language,
|
||||
version: number,
|
||||
classId: string,
|
||||
assignmentId: number,
|
||||
studentUsername?: string
|
||||
): Promise<SubmissionDTO[]> {
|
||||
const loId = new LearningObjectIdentifier(learningObjectHruid, language, version);
|
||||
const assignment = await getAssignmentRepository().findByClassIdAndAssignmentId(classId, assignmentId);
|
||||
|
||||
const submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!, studentUsername);
|
||||
|
||||
return submissions.map((s) => mapToSubmissionDTO(s));
|
||||
}
|
||||
|
|
87
backend/src/services/teacher-invitations.ts
Normal file
87
backend/src/services/teacher-invitations.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
import { fetchTeacher } from './teachers.js';
|
||||
import { getTeacherInvitationRepository } from '../data/repositories.js';
|
||||
import { mapToInvitation, mapToTeacherInvitationDTO } from '../interfaces/teacher-invitation.js';
|
||||
import { addClassTeacher, fetchClass } from './classes.js';
|
||||
import { TeacherInvitationData, TeacherInvitationDTO } from '@dwengo-1/common/interfaces/teacher-invitation';
|
||||
import { ConflictException } from '../exceptions/conflict-exception.js';
|
||||
import { NotFoundException } from '../exceptions/not-found-exception.js';
|
||||
import { TeacherInvitation } from '../entities/classes/teacher-invitation.entity.js';
|
||||
import { ClassStatus } from '@dwengo-1/common/util/class-join-request';
|
||||
|
||||
export async function getAllInvitations(username: string, sent: boolean): Promise<TeacherInvitationDTO[]> {
|
||||
const teacher = await fetchTeacher(username);
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
|
||||
let invitations;
|
||||
if (sent) {
|
||||
invitations = await teacherInvitationRepository.findAllInvitationsBy(teacher);
|
||||
} else {
|
||||
invitations = await teacherInvitationRepository.findAllInvitationsFor(teacher);
|
||||
}
|
||||
return invitations.map(mapToTeacherInvitationDTO);
|
||||
}
|
||||
|
||||
export async function createInvitation(data: TeacherInvitationData): Promise<TeacherInvitationDTO> {
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
const sender = await fetchTeacher(data.sender);
|
||||
const receiver = await fetchTeacher(data.receiver);
|
||||
|
||||
const cls = await fetchClass(data.class);
|
||||
|
||||
if (!cls.teachers.contains(sender)) {
|
||||
throw new ConflictException('The teacher sending the invite is not part of the class');
|
||||
}
|
||||
|
||||
const newInvitation = mapToInvitation(sender, receiver, cls);
|
||||
await teacherInvitationRepository.save(newInvitation, { preventOverwrite: true });
|
||||
|
||||
return mapToTeacherInvitationDTO(newInvitation);
|
||||
}
|
||||
|
||||
async function fetchInvitation(usernameSender: string, usernameReceiver: string, classId: string): Promise<TeacherInvitation> {
|
||||
const sender = await fetchTeacher(usernameSender);
|
||||
const receiver = await fetchTeacher(usernameReceiver);
|
||||
const cls = await fetchClass(classId);
|
||||
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
const invite = await teacherInvitationRepository.findBy(cls, sender, receiver);
|
||||
|
||||
if (!invite) {
|
||||
throw new NotFoundException('Teacher invite not found');
|
||||
}
|
||||
|
||||
return invite;
|
||||
}
|
||||
|
||||
export async function getInvitation(sender: string, receiver: string, classId: string): Promise<TeacherInvitationDTO> {
|
||||
const invitation = await fetchInvitation(sender, receiver, classId);
|
||||
return mapToTeacherInvitationDTO(invitation);
|
||||
}
|
||||
|
||||
export async function updateInvitation(data: TeacherInvitationData): Promise<TeacherInvitationDTO> {
|
||||
const invitation = await fetchInvitation(data.sender, data.receiver, data.class);
|
||||
invitation.status = ClassStatus.Declined;
|
||||
|
||||
if (data.accepted) {
|
||||
invitation.status = ClassStatus.Accepted;
|
||||
await addClassTeacher(data.class, data.receiver);
|
||||
}
|
||||
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
await teacherInvitationRepository.save(invitation);
|
||||
|
||||
return mapToTeacherInvitationDTO(invitation);
|
||||
}
|
||||
|
||||
export async function deleteInvitation(data: TeacherInvitationData): Promise<TeacherInvitationDTO> {
|
||||
const invitation = await fetchInvitation(data.sender, data.receiver, data.class);
|
||||
|
||||
const sender = await fetchTeacher(data.sender);
|
||||
const receiver = await fetchTeacher(data.receiver);
|
||||
const cls = await fetchClass(data.class);
|
||||
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
await teacherInvitationRepository.deleteBy(cls, sender, receiver);
|
||||
|
||||
return mapToTeacherInvitationDTO(invitation);
|
||||
}
|
|
@ -28,7 +28,7 @@ import { ClassDTO } from '@dwengo-1/common/interfaces/class';
|
|||
import { StudentDTO } from '@dwengo-1/common/interfaces/student';
|
||||
import { QuestionDTO, QuestionId } from '@dwengo-1/common/interfaces/question';
|
||||
import { ClassJoinRequestDTO } from '@dwengo-1/common/interfaces/class-join-request';
|
||||
import { ClassJoinRequestStatus } from '@dwengo-1/common/util/class-join-request';
|
||||
import { ClassStatus } from '@dwengo-1/common/util/class-join-request';
|
||||
import { ConflictException } from '../exceptions/conflict-exception.js';
|
||||
|
||||
export async function getAllTeachers(full: boolean): Promise<TeacherDTO[] | string[]> {
|
||||
|
@ -160,10 +160,10 @@ export async function updateClassJoinRequestStatus(studentUsername: string, clas
|
|||
throw new NotFoundException('Join request not found');
|
||||
}
|
||||
|
||||
request.status = ClassJoinRequestStatus.Declined;
|
||||
request.status = ClassStatus.Declined;
|
||||
|
||||
if (accepted) {
|
||||
request.status = ClassJoinRequestStatus.Accepted;
|
||||
request.status = ClassStatus.Accepted;
|
||||
await addClassStudent(classId, studentUsername);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue