feat: teacher invitation backend
This commit is contained in:
parent
a91e4b2a73
commit
311e76149c
7 changed files with 151 additions and 5 deletions
38
backend/src/controllers/teacher-invitations.ts
Normal file
38
backend/src/controllers/teacher-invitations.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { Request, Response } from 'express';
|
||||
import {requireFields} from "./error-helper";
|
||||
import {createInvitation, deleteInvitationFor, getAllInvitations} from "../services/teacher-invitations";
|
||||
import {TeacherInvitationData} from "@dwengo-1/common/interfaces/teacher-invitation";
|
||||
|
||||
export async function getAllInvitationsHandler(req: Request, res: Response): Promise<void> {
|
||||
const username = req.params.username;
|
||||
const by = req.query.by === 'true';
|
||||
requireFields({ username });
|
||||
|
||||
const invitations = getAllInvitations(username, by);
|
||||
|
||||
res.json({ invitations });
|
||||
}
|
||||
|
||||
export async function createInvitationHandler(req: Request, res: Response): Promise<void> {
|
||||
const sender = req.body.sender;
|
||||
const receiver = req.body.receiver;
|
||||
const classId = req.body.class;
|
||||
requireFields({ sender, receiver, classId });
|
||||
|
||||
const data = req.body as TeacherInvitationData;
|
||||
const invitation = await createInvitation(data);
|
||||
|
||||
res.json({ invitation });
|
||||
}
|
||||
|
||||
export async function deleteInvitationForHandler(req: Request, res: Response): Promise<void> {
|
||||
const sender = req.params.sender;
|
||||
const receiver = req.params.receiver;
|
||||
const classId = req.params.class;
|
||||
const accepted = req.body.accepted !== 'false';
|
||||
requireFields({ sender, receiver, classId });
|
||||
|
||||
const invitation = deleteInvitationFor(sender, receiver, classId, accepted);
|
||||
|
||||
res.json({ invitation });
|
||||
}
|
|
@ -20,4 +20,11 @@ export class TeacherInvitationRepository extends DwengoEntityRepository<TeacherI
|
|||
class: clazz,
|
||||
});
|
||||
}
|
||||
public async findBy(clazz: Class, sender: Teacher, receiver: Teacher): Promise<TeacherInvitation | null> {
|
||||
return this.findOne({
|
||||
sender: sender,
|
||||
receiver: receiver,
|
||||
class: clazz,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ import { TeacherInvitation } from '../entities/classes/teacher-invitation.entity
|
|||
import { mapToClassDTO } from './class.js';
|
||||
import { mapToUserDTO } from './user.js';
|
||||
import { TeacherInvitationDTO } from '@dwengo-1/common/interfaces/teacher-invitation';
|
||||
import {getTeacherInvitationRepository} from "../data/repositories";
|
||||
import {Teacher} from "../entities/users/teacher.entity";
|
||||
import {Class} from "../entities/classes/class.entity";
|
||||
|
||||
export function mapToTeacherInvitationDTO(invitation: TeacherInvitation): TeacherInvitationDTO {
|
||||
return {
|
||||
|
@ -18,3 +21,9 @@ export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): Tea
|
|||
class: invitation.class.classId!,
|
||||
};
|
||||
}
|
||||
|
||||
export function mapToInvitation(sender: Teacher, receiver: Teacher, cls: Class): TeacherInvitation {
|
||||
return getTeacherInvitationRepository().create({
|
||||
sender, receiver, class: cls
|
||||
});
|
||||
}
|
||||
|
|
17
backend/src/routes/teacher-invitations.ts
Normal file
17
backend/src/routes/teacher-invitations.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import express from "express";
|
||||
import {
|
||||
createInvitationHandler,
|
||||
deleteInvitationForHandler,
|
||||
getAllInvitationsHandler
|
||||
} from "../controllers/teacher-invitations";
|
||||
|
||||
const router = express.Router({ mergeParams: true });
|
||||
|
||||
router.get('/:username', getAllInvitationsHandler);
|
||||
|
||||
router.post('/', createInvitationHandler);
|
||||
|
||||
router.delete('/:sender/:receiver/:classId', deleteInvitationForHandler);
|
||||
|
||||
|
||||
export default router;
|
|
@ -10,6 +10,8 @@ import {
|
|||
getTeacherStudentHandler,
|
||||
updateStudentJoinRequestHandler,
|
||||
} from '../controllers/teachers.js';
|
||||
import invitationRouter from './teacher-invitations.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Root endpoint used to search objects
|
||||
|
@ -32,10 +34,6 @@ router.get('/:username/joinRequests/:classId', getStudentJoinRequestHandler);
|
|||
router.put('/:username/joinRequests/:classId/:studentUsername', updateStudentJoinRequestHandler);
|
||||
|
||||
// Invitations to other classes a teacher received
|
||||
router.get('/:id/invitations', (_req, res) => {
|
||||
res.json({
|
||||
invitations: ['0'],
|
||||
});
|
||||
});
|
||||
router.get('/invitations', invitationRouter);
|
||||
|
||||
export default router;
|
||||
|
|
71
backend/src/services/teacher-invitations.ts
Normal file
71
backend/src/services/teacher-invitations.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
import {fetchTeacher} from "./teachers";
|
||||
import {getTeacherInvitationRepository} from "../data/repositories";
|
||||
import {mapToInvitation, mapToTeacherInvitationDTO} from "../interfaces/teacher-invitation";
|
||||
import {addClassTeacher, fetchClass} from "./classes";
|
||||
import {TeacherInvitationData, TeacherInvitationDTO} from "@dwengo-1/common/interfaces/teacher-invitation";
|
||||
import {ConflictException} from "../exceptions/conflict-exception";
|
||||
import {Teacher} from "../entities/users/teacher.entity";
|
||||
import {Class} from "../entities/classes/class.entity";
|
||||
import {NotFoundException} from "../exceptions/not-found-exception";
|
||||
import {TeacherInvitation} from "../entities/classes/teacher-invitation.entity";
|
||||
|
||||
export async function getAllInvitations(username: string, by: boolean): Promise<TeacherInvitationDTO[]> {
|
||||
const teacher = await fetchTeacher(username);
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
|
||||
let invitations;
|
||||
if (by) {
|
||||
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(sender: Teacher, receiver: Teacher, cls: Class): Promise<TeacherInvitation> {
|
||||
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 deleteInvitationFor(usernameSender: string, usernameReceiver: string, classId: string, accepted: boolean) {
|
||||
const teacherInvitationRepository = getTeacherInvitationRepository();
|
||||
const sender = await fetchTeacher(usernameSender);
|
||||
const receiver = await fetchTeacher(usernameReceiver);
|
||||
|
||||
const cls = await fetchClass(classId);
|
||||
|
||||
const invitation = await fetchInvitation(sender, receiver, cls);
|
||||
await teacherInvitationRepository.deleteBy(cls, sender, receiver);
|
||||
|
||||
if (accepted){
|
||||
await addClassTeacher(classId, usernameReceiver);
|
||||
}
|
||||
|
||||
return mapToTeacherInvitationDTO(invitation);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -6,3 +6,9 @@ export interface TeacherInvitationDTO {
|
|||
receiver: string | UserDTO;
|
||||
class: string | ClassDTO;
|
||||
}
|
||||
|
||||
export interface TeacherInvitationData {
|
||||
sender: string;
|
||||
receiver: string;
|
||||
class: string;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue