Skip to content

Commit 7fe1748

Browse files
authored
Add backend routes for courses and classes (#1013)
* Add routes for adding and removing course * Update routes by moving validation to controller * Add route for update course colour * add OpenAPI for api-docs for backend using swagger library * Add ApiProperty for user's route * Add get route for courses and classes with update of routing urls * Update PUT request for setCourseColour to PATCH request * Update user routes to using AuthenticatedRequest Type * Add selectClass & removeClass route * Remove OpenAPI and Swagger Library, switched to use Postman * Update route for select and remove class * Remove unwanted routes with forwarding functions * Resolve usage of null and undefined * Resolve PR review comments * Slim down the Course and Class detail for graphql, and add validation function for update and remove class * Update routes returning status code * Refactor user.controller, move all business validation into service level * Remove duplicate getCourse request in addSelectedClass * Resolve issues on the PR code review * Resolve minor issue on function call, optimise prisma call * Resolve function name typo * Update service level function name corresponds to control level
1 parent 71413d0 commit 7fe1748

File tree

8 files changed

+484
-6
lines changed

8 files changed

+484
-6
lines changed

server/src/graphql/graphql.service.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Injectable } from '@nestjs/common';
22
import { GraphQLClient } from 'graphql-request';
33
import { getSdk } from '../generated/graphql';
4+
import type { ClassDetails } from './types';
45

56
const HASURAGRES_GRAPHQL_API = 'https://graphql.csesoc.app/v1/graphql';
67

@@ -21,4 +22,9 @@ export class GraphqlService {
2122

2223
return courseExists.aggregate != null && courseExists.aggregate.count > 0;
2324
}
25+
26+
async getClassDetails(classId: string): Promise<ClassDetails | undefined> {
27+
const { classDetails } = await this.sdk.ClassDetails({ classId });
28+
return classDetails ? classDetails : undefined;
29+
}
2430
}

server/src/graphql/queries.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,12 @@ export const COURSE_EXISTS = gql(`
1111
}
1212
}
1313
`);
14+
15+
export const CLASS_DETAILS = gql(`
16+
query ClassDetails($classId: String!) {
17+
classDetails: classes_by_pk(class_id: $classId) {
18+
activity
19+
section
20+
}
21+
}
22+
`);

server/src/graphql/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export class ClassDetails {
2+
activity: string;
3+
section: string;
4+
}

server/src/user/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,12 @@ export class UserSettings {
1515
unscheduleClassesByDefault: boolean;
1616
hideExamClasses: boolean;
1717
}
18+
19+
export class AddCourseDto {
20+
term: string;
21+
colour: string;
22+
}
23+
export class CourseDetails {
24+
id: string;
25+
selectedClasses: string[];
26+
}

server/src/user/user.controller.ts

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1-
import { Body, Controller, Get, Post, Req, UseGuards } from '@nestjs/common';
1+
import {
2+
Body,
3+
Controller,
4+
Delete,
5+
Get,
6+
HttpStatus,
7+
Param,
8+
Patch,
9+
Post,
10+
Req,
11+
UseGuards,
12+
} from '@nestjs/common';
213
import { UserService } from './user.service';
314
import { AuthenticatedGuard } from 'src/auth/authenticated.guard';
415
import { Request } from 'express';
5-
import { UserSettings } from './types';
16+
import { UserSettings, AddCourseDto } from './types';
617

718
interface AuthenticatedRequest extends Request {
819
user: {
@@ -49,4 +60,102 @@ export class UserController {
4960
await this.userService.setSettings(req.user.id, settings);
5061
return;
5162
}
63+
64+
@Get('courses/:timetableId')
65+
@UseGuards(AuthenticatedGuard)
66+
async getCourseIds(
67+
@Req() req: AuthenticatedRequest,
68+
@Param('timetableId') timetableId: string,
69+
) {
70+
return await this.userService.getCourseIds(req.user.id, timetableId);
71+
}
72+
73+
@Post('course/:timetableId/:courseId')
74+
@UseGuards(AuthenticatedGuard)
75+
async addCourse(
76+
@Req() req: AuthenticatedRequest,
77+
@Param('timetableId') timetableId: string,
78+
@Param('courseId') courseId: string,
79+
@Body() addCourseDto: AddCourseDto,
80+
) {
81+
await this.userService.addCourse(
82+
req.user.id,
83+
timetableId,
84+
courseId,
85+
addCourseDto,
86+
);
87+
return HttpStatus.CREATED;
88+
}
89+
90+
@Delete('course/:timetableId/:courseId')
91+
@UseGuards(AuthenticatedGuard)
92+
async removeCourse(
93+
@Req() req: AuthenticatedRequest,
94+
@Param('timetableId') timetableId: string,
95+
@Param('courseId') courseId: string,
96+
) {
97+
await this.userService.removeCourse(req.user.id, timetableId, courseId);
98+
}
99+
100+
@Patch('course/:timetableId/:courseId/colour')
101+
@UseGuards(AuthenticatedGuard)
102+
async setCourseColour(
103+
@Req() req: AuthenticatedRequest,
104+
@Param('timetableId') timetableId: string,
105+
@Param('courseId') courseId: string,
106+
@Body('colour') colour: string,
107+
) {
108+
await this.userService.setCourseColour(
109+
req.user.id,
110+
timetableId,
111+
courseId,
112+
colour,
113+
);
114+
}
115+
116+
@Get('classes/:timetableId/:courseId')
117+
@UseGuards(AuthenticatedGuard)
118+
async getSelectedClassIds(
119+
@Req() req: AuthenticatedRequest,
120+
@Param('timetableId') timetableId: string,
121+
@Param('courseId') courseId: string,
122+
) {
123+
return await this.userService.getSelectedClassIds(
124+
req.user.id,
125+
timetableId,
126+
courseId,
127+
);
128+
}
129+
130+
@Patch('class/:timetableId/:courseId')
131+
@UseGuards(AuthenticatedGuard)
132+
async updateSelectedClass(
133+
@Req() req: AuthenticatedRequest,
134+
@Param('timetableId') timetableId: string,
135+
@Param('courseId') courseId: string,
136+
@Body('classId') classId: string,
137+
) {
138+
await this.userService.updateSelectedClass(
139+
req.user.id,
140+
timetableId,
141+
courseId,
142+
classId,
143+
);
144+
}
145+
146+
@Delete('class/:timetableId/:courseId/:classId')
147+
@UseGuards(AuthenticatedGuard)
148+
async removeSelectedClass(
149+
@Req() req: AuthenticatedRequest,
150+
@Param('timetableId') timetableId: string,
151+
@Param('courseId') courseId: string,
152+
@Param('classId') classId: string,
153+
) {
154+
await this.userService.removeSelectedClass(
155+
req.user.id,
156+
timetableId,
157+
courseId,
158+
classId,
159+
);
160+
}
52161
}

server/src/user/user.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { Module } from '@nestjs/common';
2+
import { GraphqlService } from 'src/graphql/graphql.service';
23
import { PrismaService } from 'src/prisma/prisma.service';
34
import { UserService } from './user.service';
45
import { UserController } from './user.controller';
56

67
@Module({
7-
providers: [UserService, PrismaService],
8+
providers: [UserService, PrismaService, GraphqlService],
89
controllers: [UserController],
910
})
1011
export class UserModule {}

0 commit comments

Comments
 (0)