feat: add, delete student route met user logic + .js in files
This commit is contained in:
parent
e0a5596994
commit
ecad27ea4d
29 changed files with 301 additions and 159 deletions
|
@ -16,6 +16,7 @@ import loginRouter from './routes/login.js';
|
||||||
const app: Express = express();
|
const app: Express = express();
|
||||||
const port: string | number = getNumericEnvVar(EnvVars.Port);
|
const port: string | number = getNumericEnvVar(EnvVars.Port);
|
||||||
|
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
// TODO Replace with Express routes
|
// TODO Replace with Express routes
|
||||||
app.get('/', (_, res: Response) => {
|
app.get('/', (_, res: Response) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Request, Response } from 'express'
|
import { Request, Response } from 'express'
|
||||||
import { getAllAssignments, getAssignment } from '../services/assignments';
|
import { getAllAssignments, getAssignment } from '../services/assignments.js';
|
||||||
|
|
||||||
// typescript is annoy with with parameter forwarding from class.ts
|
// typescript is annoy with with parameter forwarding from class.ts
|
||||||
interface AssignmentParams {
|
interface AssignmentParams {
|
||||||
|
@ -41,4 +41,4 @@ export async function getAssignmentHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(assignment);
|
res.json(assignment);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class';
|
import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class.js';
|
||||||
import { ClassDTO } from '../interfaces/classes';
|
|
||||||
|
|
||||||
export async function getAllClassesHandler(
|
export async function getAllClassesHandler(
|
||||||
req: Request,
|
req: Request,
|
||||||
|
@ -61,10 +60,10 @@ export async function getTeacherInvitationsHandler(
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const classId = req.params.id;
|
const classId = req.params.id;
|
||||||
const full = req.query.full === "true"; // TODO: not implemented yet
|
const full = req.query.full === "true"; // TODO: not implemented yet
|
||||||
|
|
||||||
const invitations = await getClassTeacherInvitations(classId, full);
|
const invitations = await getClassTeacherInvitations(classId, full);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
invitations: invitations,
|
invitations: invitations,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { getAllGroups, getGroup } from '../services/groups';
|
import { getAllGroups, getGroup } from '../services/groups.js';
|
||||||
|
|
||||||
// typescript is annoywith with parameter forwarding from class.ts
|
// typescript is annoywith with parameter forwarding from class.ts
|
||||||
interface GroupParams {
|
interface GroupParams {
|
||||||
|
@ -52,4 +52,4 @@ export async function getAllGroupsHandler(
|
||||||
res.json({
|
res.json({
|
||||||
groups: groups,
|
groups: groups,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +1,33 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students';
|
import {
|
||||||
import { ClassDTO } from '../interfaces/classes';
|
getStudentClasses,
|
||||||
import { getAllAssignments } from '../services/assignments';
|
getStudentClassIds,
|
||||||
|
StudentService
|
||||||
|
} from '../services/students.js';
|
||||||
|
import { ClassDTO } from '../interfaces/classes.js';
|
||||||
|
import { getAllAssignments } from '../services/assignments.js';
|
||||||
|
import {createUserHandler, deleteUserHandler, getAllUsersHandler, getUserHandler} from "./users.js";
|
||||||
|
import { Student } from "../entities/users/student.entity.js";
|
||||||
|
|
||||||
// TODO: accept arguments (full, ...)
|
// TODO: accept arguments (full, ...)
|
||||||
// TODO: endpoints
|
// TODO: endpoints
|
||||||
export async function getAllStudentsHandler (
|
export async function getAllStudentsHandler (req: Request, res: Response): Promise<void> {
|
||||||
req: Request,
|
await getAllUsersHandler<Student>(req, res, new StudentService());
|
||||||
res: Response,
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
|
||||||
const students = await getAllStudents();
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
students: students
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching learning objects:', error);
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStudentHandler(
|
export async function getStudentHandler(req: Request, res: Response): Promise<void> {
|
||||||
req: Request,
|
await getUserHandler<Student>(req, res, new StudentService());
|
||||||
res: Response,
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
|
||||||
const username = req.params.id;
|
|
||||||
const student = await getStudent(username);
|
|
||||||
|
|
||||||
if (!student) {
|
|
||||||
res.status(404).json({ error: "Student not found" });
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
student.endpoints = {
|
|
||||||
classes: `/student/${req.params.id}/classes`,
|
|
||||||
questions: `/student/${req.params.id}/submissions`,
|
|
||||||
invitations: `/student/${req.params.id}/assignments`,
|
|
||||||
groups: `/student/${req.params.id}/groups`,
|
|
||||||
}
|
|
||||||
res.json(student);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching learning objects:', error);
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function createStudentHandler(req: Request, res: Response): Promise<void> {
|
||||||
|
await createUserHandler<Student>(req, res, new StudentService(), Student);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteStudentHandler(req: Request, res: Response): Promise<void> {
|
||||||
|
await deleteUserHandler<Student>(req, res, new StudentService());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function getStudentClassesHandler (
|
export async function getStudentClassesHandler (
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
|
@ -75,6 +55,7 @@ export async function getStudentClassesHandler (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
// Might not be fully correct depending on if
|
// Might not be fully correct depending on if
|
||||||
// a class has an assignment, that all students
|
// a class has an assignment, that all students
|
||||||
// have this assignment.
|
// have this assignment.
|
||||||
|
@ -92,4 +73,6 @@ export async function getStudentAssignmentsHandler(
|
||||||
res.json({
|
res.json({
|
||||||
assignments: assignments
|
assignments: assignments
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
106
backend/src/controllers/users.ts
Normal file
106
backend/src/controllers/users.ts
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import { Request, Response } from 'express';
|
||||||
|
import { UserService } from "../services/users.js";
|
||||||
|
import {UserDTO} from "../interfaces/user.js";
|
||||||
|
import {User} from "../entities/users/user.entity.js";
|
||||||
|
|
||||||
|
export async function getAllUsersHandler<T extends User>(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
service: UserService<T>
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const full = req.query.full === 'true';
|
||||||
|
|
||||||
|
let users: UserDTO[] | string[] = full
|
||||||
|
? await service.getAllUsers()
|
||||||
|
: await service.getAllUserIds();
|
||||||
|
|
||||||
|
if (!users){
|
||||||
|
res.status(404).json({ error: `Users not found.` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(201).json(users);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error fetching users:", error);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserHandler<T extends User>(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
service: UserService<T>
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const username = req.params.username as string;
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
res.status(400).json({ error: 'Missing required field: username' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await service.getUserByUsername(username);
|
||||||
|
|
||||||
|
if (!user){
|
||||||
|
res.status(404).json({ error: `User with username '${username}' not found.` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(201).json(user);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error fetching users:", error);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createUserHandler<T extends User>(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
service: UserService<T>,
|
||||||
|
UserClass: new () => T
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
console.log("req", req)
|
||||||
|
const userData = req.body as UserDTO;
|
||||||
|
|
||||||
|
if (!userData.username || !userData.firstName || !userData.lastName) {
|
||||||
|
res.status(400).json({ error: "Missing required fields: username, firstName, lastName" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newUser = await service.createUser(userData, UserClass);
|
||||||
|
res.status(201).json(newUser);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error creating user:", error);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteUserHandler<T extends User> (
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
service: UserService<T>
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const username = req.params.username;
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
res.status(400).json({ error: "Missing required field: username" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedUser = await service.deleteUser(username);
|
||||||
|
if (!deletedUser) {
|
||||||
|
res.status(404).json({ error: `User with username '${username}' not found.` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json(deletedUser);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error deleting user:", error);
|
||||||
|
res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,7 +59,7 @@ function repositoryGetter<T extends AnyEntity, R extends EntityRepository<T>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Users */
|
/* Users */
|
||||||
export const getUserRepository = repositoryGetter<User, UserRepository>(User);
|
export const getUserRepository = repositoryGetter<User, UserRepository<User>>(User);
|
||||||
export const getStudentRepository = repositoryGetter<
|
export const getStudentRepository = repositoryGetter<
|
||||||
Student,
|
Student,
|
||||||
StudentRepository
|
StudentRepository
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
|
|
||||||
import { Student } from '../../entities/users/student.entity.js';
|
import { Student } from '../../entities/users/student.entity.js';
|
||||||
|
import {UserRepository} from "./user-repository.js";
|
||||||
|
|
||||||
export class StudentRepository extends DwengoEntityRepository<Student> {
|
export class StudentRepository extends UserRepository<Student> {}
|
||||||
public findByUsername(username: string): Promise<Student | null> {
|
|
||||||
return this.findOne({ username: username });
|
|
||||||
}
|
|
||||||
public deleteByUsername(username: string): Promise<void> {
|
|
||||||
return this.deleteWhere({ username: username });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
|
|
||||||
import { Teacher } from '../../entities/users/teacher.entity.js';
|
import { Teacher } from '../../entities/users/teacher.entity.js';
|
||||||
|
import {UserRepository} from "./user-repository.js";
|
||||||
|
|
||||||
export class TeacherRepository extends DwengoEntityRepository<Teacher> {
|
export class TeacherRepository extends UserRepository<Teacher> {}
|
||||||
public findByUsername(username: string): Promise<Teacher | null> {
|
|
||||||
return this.findOne({ username: username });
|
|
||||||
}
|
|
||||||
public deleteByUsername(username: string): Promise<void> {
|
|
||||||
return this.deleteWhere({ username: username });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
|
import { DwengoEntityRepository } from '../dwengo-entity-repository.js';
|
||||||
import { User } from '../../entities/users/user.entity.js';
|
import { User } from '../../entities/users/user.entity.js';
|
||||||
|
|
||||||
export class UserRepository extends DwengoEntityRepository<User> {
|
export class UserRepository<T extends User> extends DwengoEntityRepository<T> {
|
||||||
public findByUsername(username: string): Promise<User | null> {
|
public findByUsername(username: string): Promise<T | null> {
|
||||||
return this.findOne({ username: username });
|
return this.findOne({ username } as Partial<T>);
|
||||||
}
|
}
|
||||||
public deleteByUsername(username: string): Promise<void> {
|
public deleteByUsername(username: string): Promise<void> {
|
||||||
return this.deleteWhere({ username: username });
|
return this.deleteWhere({ username } as Partial<T>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,15 @@ import { Attachment } from './attachment.entity.js';
|
||||||
import { Teacher } from '../users/teacher.entity.js';
|
import { Teacher } from '../users/teacher.entity.js';
|
||||||
import { LearningObjectRepository } from '../../data/content/learning-object-repository.js';
|
import { LearningObjectRepository } from '../../data/content/learning-object-repository.js';
|
||||||
|
|
||||||
|
@Embeddable()
|
||||||
|
export class ReturnValue {
|
||||||
|
@Property({ type: 'string' })
|
||||||
|
callbackUrl!: string;
|
||||||
|
|
||||||
|
@Property({ type: 'json' })
|
||||||
|
callbackSchema!: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Entity({ repository: () => LearningObjectRepository })
|
@Entity({ repository: () => LearningObjectRepository })
|
||||||
export class LearningObject {
|
export class LearningObject {
|
||||||
@PrimaryKey({ type: 'string' })
|
@PrimaryKey({ type: 'string' })
|
||||||
|
@ -88,15 +97,6 @@ export class EducationalGoal {
|
||||||
id!: string;
|
id!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Embeddable()
|
|
||||||
export class ReturnValue {
|
|
||||||
@Property({ type: 'string' })
|
|
||||||
callbackUrl!: string;
|
|
||||||
|
|
||||||
@Property({ type: 'json' })
|
|
||||||
callbackSchema!: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ContentType {
|
export enum ContentType {
|
||||||
Markdown = 'text/markdown',
|
Markdown = 'text/markdown',
|
||||||
Image = 'image/image',
|
Image = 'image/image',
|
||||||
|
|
|
@ -11,12 +11,4 @@ export class Student extends User {
|
||||||
|
|
||||||
@ManyToMany(() => Group)
|
@ManyToMany(() => Group)
|
||||||
groups!: Collection<Group>;
|
groups!: Collection<Group>;
|
||||||
|
|
||||||
constructor(
|
|
||||||
public username: string,
|
|
||||||
public firstName: string,
|
|
||||||
public lastName: string
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Assignment } from "../entities/assignments/assignment.entity";
|
import { Assignment } from "../entities/assignments/assignment.entity.js";
|
||||||
import { Class } from "../entities/classes/class.entity";
|
import { GroupDTO, mapToGroupDTO } from "./groups.js";
|
||||||
import { GroupDTO, mapToGroupDTO } from "./groups";
|
|
||||||
|
|
||||||
export interface AssignmentDTO {
|
export interface AssignmentDTO {
|
||||||
id: number,
|
id: number,
|
||||||
|
@ -34,4 +33,4 @@ export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO {
|
||||||
language: assignment.learningPathLanguage,
|
language: assignment.learningPathLanguage,
|
||||||
// groups: assignment.groups.map(mapToGroupDTO),
|
// groups: assignment.groups.map(mapToGroupDTO),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Class } from "../entities/classes/class.entity";
|
import { Class } from "../entities/classes/class.entity.js";
|
||||||
|
|
||||||
export interface ClassDTO {
|
export interface ClassDTO {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Group } from "../entities/assignments/group.entity";
|
import { Group } from "../entities/assignments/group.entity.js";
|
||||||
import { AssignmentDTO, mapToAssignmentDTO } from "./assignments";
|
import { AssignmentDTO, mapToAssignmentDTO } from "./assignments.js";
|
||||||
import { mapToStudentDTO, StudentDTO } from "./students";
|
import { mapToStudentDTO, StudentDTO } from "./students.js";
|
||||||
|
|
||||||
export interface GroupDTO {
|
export interface GroupDTO {
|
||||||
assignment: number | AssignmentDTO,
|
assignment: number | AssignmentDTO,
|
||||||
|
@ -10,7 +10,7 @@ export interface GroupDTO {
|
||||||
|
|
||||||
export function mapToGroupDTO(group: Group): GroupDTO {
|
export function mapToGroupDTO(group: Group): GroupDTO {
|
||||||
return {
|
return {
|
||||||
assignment: mapToAssignmentDTO(group.assignment, group.assignment.within),
|
assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within),
|
||||||
groupNumber: group.groupNumber,
|
groupNumber: group.groupNumber,
|
||||||
members: group.members.map(mapToStudentDTO),
|
members: group.members.map(mapToStudentDTO),
|
||||||
}
|
}
|
||||||
|
@ -22,4 +22,4 @@ export function mapToGroupDTOId(group: Group): GroupDTO {
|
||||||
groupNumber: group.groupNumber,
|
groupNumber: group.groupNumber,
|
||||||
members: group.members.map(member => member.username),
|
members: group.members.map(member => member.username),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Student } from "../entities/users/student.entity";
|
import { Student } from "../entities/users/student.entity.js";
|
||||||
|
|
||||||
export interface StudentDTO {
|
export interface StudentDTO {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -20,4 +20,13 @@ export function mapToStudentDTO(student: Student): StudentDTO {
|
||||||
firstName: student.firstName,
|
firstName: student.firstName,
|
||||||
lastName: student.lastName,
|
lastName: student.lastName,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mapToStudent(studentData: StudentDTO): Student {
|
||||||
|
const student = new Student();
|
||||||
|
student.username = studentData.username;
|
||||||
|
student.firstName = studentData.firstName;
|
||||||
|
student.lastName = studentData.lastName;
|
||||||
|
|
||||||
|
return student;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity";
|
import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity.js";
|
||||||
import { ClassDTO, mapToClassDTO } from "./classes";
|
import { ClassDTO, mapToClassDTO } from "./classes.js";
|
||||||
import { mapToTeacherDTO, TeacherDTO } from "./teacher";
|
import { mapToTeacherDTO, TeacherDTO } from "./teacher.js";
|
||||||
|
|
||||||
export interface TeacherInvitationDTO {
|
export interface TeacherInvitationDTO {
|
||||||
sender: string | TeacherDTO,
|
sender: string | TeacherDTO,
|
||||||
|
@ -22,4 +22,4 @@ export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): Tea
|
||||||
receiver: invitation.receiver.username,
|
receiver: invitation.receiver.username,
|
||||||
class: invitation.class.classId,
|
class: invitation.class.classId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Teacher } from "../entities/users/teacher.entity";
|
import { Teacher } from "../entities/users/teacher.entity.js";
|
||||||
|
|
||||||
export interface TeacherDTO {
|
export interface TeacherDTO {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -20,4 +20,4 @@ export function mapToTeacherDTO(teacher: Teacher): TeacherDTO {
|
||||||
firstName: teacher.firstName,
|
firstName: teacher.firstName,
|
||||||
lastName: teacher.lastName,
|
lastName: teacher.lastName,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
30
backend/src/interfaces/user.ts
Normal file
30
backend/src/interfaces/user.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { User } from "../entities/users/user.entity.js";
|
||||||
|
|
||||||
|
export interface UserDTO {
|
||||||
|
id?: string,
|
||||||
|
username: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
endpoints?: {
|
||||||
|
self: string;
|
||||||
|
classes: string;
|
||||||
|
questions: string;
|
||||||
|
invitations: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapToUserDTO(user: User): UserDTO {
|
||||||
|
return {
|
||||||
|
id: user.username,
|
||||||
|
username: user.username,
|
||||||
|
firstName: user.firstName,
|
||||||
|
lastName: user.lastName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapToUser<T extends User>(userData: UserDTO, userInstance: T): T {
|
||||||
|
userInstance.username = userData.username;
|
||||||
|
userInstance.firstName = userData.firstName;
|
||||||
|
userInstance.lastName = userData.lastName;
|
||||||
|
return userInstance;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments';
|
import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments.js';
|
||||||
import groupRouter from './group.js';
|
import groupRouter from './group.js';
|
||||||
|
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
@ -28,4 +28,4 @@ router.get('/:id/questions', (req, res) => {
|
||||||
|
|
||||||
router.use('/:assignmentid/groups', groupRouter);
|
router.use('/:assignmentid/groups', groupRouter);
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes';
|
import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes.js';
|
||||||
import assignmentRouter from './assignment.js';
|
import assignmentRouter from './assignment.js';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
@ -16,4 +16,4 @@ router.get('/:id/students', getClassStudentsHandler);
|
||||||
|
|
||||||
router.use('/:classid/assignments', assignmentRouter);
|
router.use('/:classid/assignments', assignmentRouter);
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups';
|
import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups.js';
|
||||||
const router = express.Router({ mergeParams: true });
|
const router = express.Router({ mergeParams: true });
|
||||||
|
|
||||||
// root endpoint used to search objects
|
// root endpoint used to search objects
|
||||||
|
@ -15,4 +15,4 @@ router.get('/:id/question', (req, res) => {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { getAllStudentsHandler, getStudentAssignmentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students';
|
import {
|
||||||
|
createStudentHandler, deleteStudentHandler,
|
||||||
|
getAllStudentsHandler,
|
||||||
|
getStudentAssignmentsHandler,
|
||||||
|
getStudentClassesHandler,
|
||||||
|
getStudentHandler
|
||||||
|
} from '../controllers/students.js';
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
// root endpoint used to search objects
|
// root endpoint used to search objects
|
||||||
router.get('/', getAllStudentsHandler);
|
router.get('/', getAllStudentsHandler);
|
||||||
|
|
||||||
|
router.post('/', createStudentHandler);
|
||||||
|
|
||||||
|
router.delete('/:username', deleteStudentHandler);
|
||||||
|
|
||||||
// information about a student's profile
|
// information about a student's profile
|
||||||
router.get('/:id', getStudentHandler);
|
router.get('/:username', getStudentHandler);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// the list of classes a student is in
|
// the list of classes a student is in
|
||||||
router.get('/:id/classes', getStudentClassesHandler);
|
router.get('/:id/classes', getStudentClassesHandler);
|
||||||
|
@ -18,10 +30,10 @@ router.get('/:id/submissions', (req, res) => {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// the list of assignments a student has
|
// the list of assignments a student has
|
||||||
router.get('/:id/assignments', getStudentAssignmentsHandler);
|
router.get('/:id/assignments', getStudentAssignmentsHandler);
|
||||||
|
|
||||||
// the list of groups a student is in
|
// the list of groups a student is in
|
||||||
router.get('/:id/groups', (req, res) => {
|
router.get('/:id/groups', (req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
|
@ -36,4 +48,4 @@ router.get('/:id/questions', (req, res) => {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { getAssignmentRepository, getClassRepository } from "../data/repositories";
|
import { getAssignmentRepository, getClassRepository } from "../data/repositories.js";
|
||||||
import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments";
|
import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments.js";
|
||||||
|
|
||||||
export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> {
|
export async function getAllAssignments(classid: string, full: boolean): Promise<AssignmentDTO[]> {
|
||||||
const classRepository = getClassRepository();
|
const classRepository = getClassRepository();
|
||||||
|
@ -8,7 +8,7 @@ export async function getAllAssignments(classid: string, full: boolean): Promise
|
||||||
if (!cls) {
|
if (!cls) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const assignmentRepository = getAssignmentRepository();
|
const assignmentRepository = getAssignmentRepository();
|
||||||
const assignments = await assignmentRepository.findAllAssignmentsInClass(cls);
|
const assignments = await assignmentRepository.findAllAssignmentsInClass(cls);
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export async function getAssignment(classid: string, id: number): Promise<Assign
|
||||||
if (!cls) {
|
if (!cls) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assignmentRepository = getAssignmentRepository();
|
const assignmentRepository = getAssignmentRepository();
|
||||||
const assignment = await assignmentRepository.findByClassAndId(cls, id);
|
const assignment = await assignmentRepository.findByClassAndId(cls, id);
|
||||||
|
|
||||||
|
@ -35,4 +35,4 @@ export async function getAssignment(classid: string, id: number): Promise<Assign
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapToAssignmentDTO(assignment);
|
return mapToAssignmentDTO(assignment);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { getClassRepository, getTeacherInvitationRepository } from "../data/repositories";
|
import { getClassRepository, getTeacherInvitationRepository } from "../data/repositories.js";
|
||||||
import { Class } from "../entities/classes/class.entity";
|
import { ClassDTO, mapToClassDTO } from "../interfaces/classes.js";
|
||||||
import { ClassDTO, mapToClassDTO } from "../interfaces/classes";
|
import { mapToStudentDTO, StudentDTO } from "../interfaces/students.js";
|
||||||
import { mapToStudentDTO, StudentDTO } from "../interfaces/students";
|
import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from "../interfaces/teacher-invitation.js";
|
||||||
import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from "../interfaces/teacher-invitation";
|
|
||||||
|
|
||||||
export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[]> {
|
export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[]> {
|
||||||
const classRepository = getClassRepository();
|
const classRepository = getClassRepository();
|
||||||
|
@ -11,7 +10,7 @@ export async function getAllClasses(full: boolean): Promise<ClassDTO[] | string[
|
||||||
if (!classes) {
|
if (!classes) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full) {
|
if (full) {
|
||||||
return classes.map(mapToClassDTO);
|
return classes.map(mapToClassDTO);
|
||||||
} else {
|
} else {
|
||||||
|
@ -66,4 +65,4 @@ export async function getClassTeacherInvitations(classId: string, full: boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
return invitations.map(mapToTeacherInvitationDTOIds);
|
return invitations.map(mapToTeacherInvitationDTOIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { getAssignmentRepository, getClassRepository, getGroupRepository } from "../data/repositories";
|
import { getAssignmentRepository, getClassRepository, getGroupRepository } from "../data/repositories.js";
|
||||||
import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from "../interfaces/groups";
|
import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from "../interfaces/groups.js";
|
||||||
|
|
||||||
export async function getGroup(
|
export async function getGroup(
|
||||||
classId: string,
|
classId: string,
|
||||||
assignmentNumber: number,
|
assignmentNumber: number,
|
||||||
groupNumber: number,
|
groupNumber: number,
|
||||||
full: boolean,
|
full: boolean,
|
||||||
): Promise<GroupDTO | null> {
|
): Promise<GroupDTO | null> {
|
||||||
|
@ -64,4 +64,4 @@ export async function getAllGroups(
|
||||||
}
|
}
|
||||||
|
|
||||||
return groups.map(mapToGroupDTOId);
|
return groups.map(mapToGroupDTOId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,13 @@
|
||||||
import { getClassRepository, getStudentRepository } from "../data/repositories";
|
import { getClassRepository, getStudentRepository } from "../data/repositories.js";
|
||||||
import { Class } from "../entities/classes/class.entity";
|
import { Class } from "../entities/classes/class.entity.js";
|
||||||
import { Student } from "../entities/users/student.entity";
|
import { Student } from "../entities/users/student.entity.js";
|
||||||
import { ClassDTO, mapToClassDTO } from "../interfaces/classes";
|
import { ClassDTO, mapToClassDTO } from "../interfaces/classes.js";
|
||||||
import { StudentDTO, mapToStudentDTO } from "../interfaces/students";
|
import {UserService} from "./users.js";
|
||||||
|
|
||||||
|
export class StudentService extends UserService<Student> {
|
||||||
export async function getAllStudents(): Promise<StudentDTO[]> {
|
constructor() {
|
||||||
const studentRepository = getStudentRepository();
|
super(getStudentRepository());
|
||||||
const students = await studentRepository.find({});
|
|
||||||
|
|
||||||
return students.map(mapToStudentDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getStudent(username: string): Promise<StudentDTO | null> {
|
|
||||||
const studentRepository = getStudentRepository();
|
|
||||||
const student = await studentRepository.findByUsername(username);
|
|
||||||
|
|
||||||
if (!student) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapToStudentDTO(student);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchStudentClasses(username: string): Promise<Class[]> {
|
async function fetchStudentClasses(username: string): Promise<Class[]> {
|
||||||
|
|
39
backend/src/services/users.ts
Normal file
39
backend/src/services/users.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { UserRepository } from "../data/users/user-repository.js";
|
||||||
|
import { UserDTO, mapToUser, mapToUserDTO } from "../interfaces/user.js";
|
||||||
|
import {User} from "../entities/users/user.entity.js";
|
||||||
|
|
||||||
|
export class UserService<T extends User> {
|
||||||
|
protected repository: UserRepository<T>;
|
||||||
|
|
||||||
|
constructor(repository: UserRepository<T>) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllUsers(): Promise<UserDTO[]> {
|
||||||
|
const users = await this.repository.findAll();
|
||||||
|
return users.map(mapToUserDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllUserIds(): Promise<string[]> {
|
||||||
|
const users = await this.getAllUsers();
|
||||||
|
return users.map((user) => user.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserByUsername(username: string): Promise<UserDTO | null> {
|
||||||
|
const user = await this.repository.findByUsername(username)
|
||||||
|
return user ? mapToUserDTO(user) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createUser(userData: UserDTO, UserClass: new () => T): Promise<T> {
|
||||||
|
const newUser = mapToUser(userData, new UserClass());
|
||||||
|
await this.repository.save(newUser);
|
||||||
|
return newUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteUser(username: string): Promise<UserDTO | null> {
|
||||||
|
const user = await this.getUserByUsername(username);
|
||||||
|
if (!user) return null;
|
||||||
|
await this.repository.deleteByUsername(username)
|
||||||
|
return mapToUserDTO(user);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import {FALLBACK_LANG} from "../../config";
|
import {FALLBACK_LANG} from "../config.js";
|
||||||
|
|
||||||
export function loadTranslations<T>(language: string): T {
|
export function loadTranslations<T>(language: string): T {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue