Skip to content

Commit 7b8cd65

Browse files
authored
Merge pull request #27 from DevOps-Cloud-Team5/SCRUM-90-Course-info
lecture series
2 parents ea86b2e + c916787 commit 7b8cd65

File tree

3 files changed

+72
-17
lines changed

3 files changed

+72
-17
lines changed

api/serializers.py

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class AddLectureSerializer(serializers.Serializer):
104104
start_time = serializers.DateTimeField(required=True)
105105
end_time = serializers.DateTimeField(required=True)
106106
lecture_type = serializers.CharField(required=True)
107+
lecture_series = serializers.BooleanField(default=False)
107108

108109
def validate(self, attrs):
109110
start_time, end_time = attrs["start_time"], attrs["end_time"]

api/urls.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from django_rest_passwordreset.views import ResetPasswordConfirm, ResetPasswordValidateToken
2020
from .views import (
2121
AddLectureView,
22+
DestroyLectureView,
2223
DisenrollCourseView,
2324
GetCourseLecturesView,
2425
GetFullCoursePage,
@@ -76,23 +77,26 @@
7677
path('course/update/<pk>', UpdateCourseView.as_view(), name='course_update'),
7778
path('course/delete/<pk>', DestroyCourseView.as_view(), name='course_delete'),
7879
path('course/enroll/<pk>', EnrollCourseView.as_view(), name='course_enroll'),
79-
path('course/disenroll/<pk>', DisenrollCourseView.as_view(), name='course_enroll'),
80+
path('course/enroll/<pk>/<username>', EnrollCourseView.as_view(), name='course_enroll_username'),
81+
path('course/disenroll/<pk>', DisenrollCourseView.as_view(), name='course_disenroll'),
82+
path('course/disenroll/<pk>/<username>', DisenrollCourseView.as_view(), name='course_disenroll_username'),
8083
path('course/mass_enroll/<pk>', MassEnrollCourseView.as_view(), name='course_mass_enroll'),
8184
path('course/get/<pk>', GetFullCoursePage.as_view(), name='course_get'),
8285
path('course/getall/', GetCoursesAll.as_view(), name='course_getall'),
8386

8487

8588
path('course/lecture/<pk>/get', GetCourseLecturesView.as_view(), name='course_get_lecture'),
8689
path('course/lecture/<pk>/add', AddLectureView.as_view(), name='course_add_lecture'),
90+
path('course/lecture/<pk>/delete', DestroyLectureView.as_view(), name='course_lecture_delete'),
8791
# path('course/lecture/<pk>/update', GetCourseByName.as_view(), name='lecture_add'), # TODO
88-
# path('course/lecture/<pk>/delete', GetCourseByName.as_view(), name='lecture_add'),
8992

9093
path('lecture/<pk>/get', GetLectureView.as_view(), name='lecture_get'),
9194
path('lecture/<pk>/student_set_att', SetStudentAttView.as_view(), name='lecture_set_att_student'),
9295
path('lecture/<pk>/student_unset_att', UnsetStudentAttView.as_view(), name='lecture_unset_att_student'),
9396
path('lecture/<pk>/teacher_att', SetTeacherAttView.as_view(), name='lecture_att_teacher'),
9497

9598
path('schedule/get/<year>/<week>', GetScheduleView.as_view(), name='schedule_get'),
99+
path('schedule/get/<year>/<week>/<course_id>', GetScheduleView.as_view(), name='schedule_get'),
96100

97101
# Documentation
98102
path('schema/', SpectacularAPIView.as_view(), name='schema'),

api/views.py

+65-15
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ def get(self, request):
278278
for course_serialized in serializer.data:
279279
course : Course = queryset.filter(pk=course_serialized["id"])[0]
280280
course_serialized["enrolled"] = course.is_user_enrolled(user=request.user)
281+
course_serialized["num_students"] = len(course.get_enrolled_students())
282+
course_serialized["num_teachers"] = len(course.get_teachers())
283+
281284
return Response(serializer.data, status=status.HTTP_200_OK)
282285

283286
class EnrollCourseView(generics.GenericAPIView):
@@ -288,15 +291,23 @@ class EnrollCourseView(generics.GenericAPIView):
288291
queryset = Course.objects.all()
289292
serializer_class = CourseSerializer
290293

291-
def post(self, request, *args, **kwargs):
292-
if request.user.role == AccountRoles.ADMIN:
294+
def post(self, request, username=None, *args, **kwargs):
295+
if username is not None:
296+
if user.role != AccountRoles.ADMIN:
297+
return Response({"error": f"unauthorized"}, status=status.HTTP_401_UNAUTHORIZED)
298+
queryset = User.objects.all().filter(username=username)
299+
if not queryset:
300+
return Response({"error": f"{username} is not a valid user"}, status=status.HTTP_400_BAD_REQUEST)
301+
user = queryset[0]
302+
else:
303+
user = request.user
304+
username = user.username
305+
306+
if user.role == AccountRoles.ADMIN:
293307
return Response({"error": f"cannot enroll an admin account into a course"}, status=status.HTTP_400_BAD_REQUEST)
294308

295309
obj : Course = self.get_object()
296-
user = request.user
297-
username = user.username
298-
299-
if obj.is_user_enrolled(request.user):
310+
if obj.is_user_enrolled(user):
300311
return Response({"error": f"{username} is already enrolled in {obj.course_name}"}, status=status.HTTP_400_BAD_REQUEST)
301312

302313
obj.add_user_to_course(user)
@@ -314,12 +325,20 @@ class DisenrollCourseView(generics.GenericAPIView):
314325
queryset = Course.objects.all()
315326
serializer_class = CourseSerializer
316327

317-
def post(self, request, *args, **kwargs):
318-
obj : Course = self.get_object()
319-
user = request.user
320-
username = user.username
328+
def post(self, request, username=None, *args, **kwargs):
329+
if username is not None:
330+
if request.user.role != AccountRoles.ADMIN:
331+
return Response({"error": f"unauthorized"}, status=status.HTTP_401_UNAUTHORIZED)
332+
queryset = User.objects.all().filter(username=username)
333+
if not queryset:
334+
return Response({"error": f"{username} is not a valid user"}, status=status.HTTP_400_BAD_REQUEST)
335+
user = queryset[0]
336+
else:
337+
user = request.user
338+
username = user.username
321339

322-
if not obj.is_user_enrolled(request.user):
340+
obj : Course = self.get_object()
341+
if not obj.is_user_enrolled(user):
323342
return Response({"error": f"{username} is not enrolled in {obj.course_name}"}, status=status.HTTP_400_BAD_REQUEST)
324343

325344
obj.remove_user_from_course(user)
@@ -376,6 +395,8 @@ class AddLectureView(generics.GenericAPIView):
376395
queryset = Course.objects.all()
377396
serializer_class = CourseSerializer
378397

398+
holiday_weeks = [1, 8, 18, 29, 30, 31, 32, 33, 34, 42, 52]
399+
379400
def post(self, request, *args, **kwargs):
380401
course : Course = self.get_object()
381402
result = AddLectureSerializer(data=request.data, context={ "course": course })
@@ -384,10 +405,32 @@ def post(self, request, *args, **kwargs):
384405
data = result.data
385406
start_time = datetime.datetime.fromisoformat(data["start_time"])
386407
end_time = datetime.datetime.fromisoformat(data["end_time"])
387-
course.add_lecture_to_course(start_time, end_time, data["lecture_type"])
388408

409+
if not data["lecture_series"]:
410+
course.add_lecture_to_course(start_time, end_time, data["lecture_type"])
411+
else:
412+
curr_week = start_time.strftime("%W")
413+
exclude_weeks = list(self.holiday_weeks)
414+
if curr_week in exclude_weeks: exclude_weeks.remove(curr_week)
415+
416+
start_string = start_time.strftime("%Y %a %H %M %S ")
417+
end_string = end_time.strftime("%Y %a %H %M %S ")
418+
for i in range(1, 53):
419+
if i in exclude_weeks: continue
420+
new_start = datetime.datetime.strptime(start_string + str(i), "%Y %a %H %M %S %W")
421+
new_end = datetime.datetime.strptime(end_string + str(i), "%Y %a %H %M %S %W")
422+
course.add_lecture_to_course(new_start, new_end, data["lecture_type"])
423+
389424
return Response({"ok": f"successfully created lecture"}, status=status.HTTP_200_OK)
425+
426+
class DestroyLectureView(generics.DestroyAPIView):
427+
authentication_classes = [JWTAuthentication]
428+
permission_classes = [IsTeacher]
429+
lookup_field = 'pk'
390430

431+
queryset = CourseLecture.objects.all()
432+
serializer_class = LectureSerializer
433+
391434
class GetLectureView(generics.RetrieveAPIView):
392435
authentication_classes = [JWTAuthentication]
393436
permission_classes = [IsStudent]
@@ -431,7 +474,6 @@ class UnsetStudentAttView(generics.GenericAPIView):
431474
serializer_class = CourseLecture
432475

433476
def post(self, request, *args, **kwargs):
434-
print(request.user)
435477
return setAttendence(self, request, False)
436478

437479
class SetTeacherAttView(generics.GenericAPIView):
@@ -460,14 +502,22 @@ class GetScheduleView(generics.GenericAPIView):
460502
authentication_classes = [JWTAuthentication]
461503
permission_classes = [IsStudent]
462504

463-
def get(self, request, year, week):
505+
def get(self, request, year, week, course_id=None):
464506
if not year.isdigit() or int(year) < 1970:
465507
return Response({"error": f"invalid year parameter"}, status=status.HTTP_400_BAD_REQUEST)
466508
if not week.isdigit() or int(week) < 0 or int(week) > 52:
467509
return Response({"error": f"invalid week parameter"}, status=status.HTTP_400_BAD_REQUEST)
468510

469511
user = User.objects.all().filter(username=request.user.username)[0]
470-
courses : List[Course] = user.get_enrolled_courses()
512+
513+
if course_id is None:
514+
courses : List[Course] = user.get_enrolled_courses()
515+
else:
516+
queryset = Course.objects.all().filter(pk=course_id)
517+
if not queryset:
518+
return Response({"error": f"course ID is not valid"}, status=status.HTTP_400_BAD_REQUEST)
519+
courses : List[Course] = [queryset[0]]
520+
471521
all_lectures = []
472522
for course in courses:
473523
lectures_obj = course.get_lectures_week(int(year), int(week))

0 commit comments

Comments
 (0)