Skip to content

Commit

Permalink
Merge pull request #166 from SELab-2/164-dont-show-closed-courses
Browse files Browse the repository at this point in the history
fix courses list (no more closed courses)
  • Loading branch information
ReinhardDP authored May 18, 2024
2 parents ac476b5 + 5cd70b2 commit b729b85
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 24 deletions.
5 changes: 2 additions & 3 deletions backend/pigeonhole/apps/courses/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ def has_permission(self, request, view):
return True

if request.user.is_teacher:
if view.action in ["create", "list", "retrieve"]:
if view.action in ["create", "list", "retrieve", "get_open_courses"]:
return True
elif (
view.action in ["update", "partial_update", "destroy",
"get_projects"]
view.action in ["update", "partial_update", "destroy", "get_projects"]
and User.objects.filter(
id=request.user.id, course=view.kwargs["pk"]
).exists()
Expand Down
8 changes: 8 additions & 0 deletions backend/pigeonhole/apps/courses/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,11 @@ def get_archived_courses(self, request, *args, **kwargs):
queryset = self.order_queryset(paginated_queryset)
serializer = CourseSerializer(queryset, many=True)
return self.get_paginated_response(serializer.data)

@action(detail=False, methods=["GET"])
def get_open_courses(self, request, *args, **kwargs):
courses = Course.objects.filter(open_course=True)
course_filter = CourseFilter(request.GET, queryset=courses)
queryset = self.order_queryset(course_filter.qs)
serializer = CourseSerializer(self.paginate_queryset(queryset), many=True)
return self.get_paginated_response(serializer.data)
23 changes: 15 additions & 8 deletions backend/pigeonhole/apps/submissions/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ class CanAccessSubmission(permissions.BasePermission):
# to the submission data.
def has_permission(self, request, view):
user = request.user
if view.action in ['list']:
if view.action in ["list"]:
return False
elif view.action in ['download_selection']:
elif view.action in ["download_selection"]:
return user.is_teacher or user.is_admin or user.is_superuser
elif view.action in ['create']:
elif view.action in ["create"]:
if user.is_student:
group_id = request.data.get('group_id')
group_id = request.data.get("group_id")
if not Group.objects.filter(group_id=group_id).exists():
if user.is_admin or user.is_superuser:
return Response(status=status.HTTP_404_NOT_FOUND)
Expand All @@ -34,9 +34,11 @@ def has_permission(self, request, view):
else:
return False
else:
if ('pk' not in view.kwargs.keys()) and (user.is_teacher or user.is_admin or user.is_superuser):
if ("pk" not in view.kwargs.keys()) and (
user.is_teacher or user.is_admin or user.is_superuser
):
return True
submission = Submissions.objects.get(submission_id=view.kwargs['pk'])
submission = Submissions.objects.get(submission_id=view.kwargs["pk"])
group_id = submission.group_id.group_id
if not Group.objects.filter(group_id=group_id).exists():
if user.is_admin or user.is_superuser:
Expand All @@ -55,11 +57,16 @@ def has_permission(self, request, view):
return True
elif user.is_student:
if group.user.filter(id=user.id).exists():
return view.action in ['retrieve', 'create', 'download', 'get_project']
return view.action in [
"retrieve",
"create",
"download",
"get_project",
]
return False


class NotInGroupError(APIException):
status_code = status.HTTP_403_FORBIDDEN
default_detail = "you are not in a group for this project, please join one."
default_code = 'ERROR_NOT_IN_GROUP'
default_code = "ERROR_NOT_IN_GROUP"
27 changes: 16 additions & 11 deletions backend/pigeonhole/apps/submissions/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,25 @@ def create(self, request, *args, **kwargs):

if not group:
return Response(
{"message": "Group not found", "errorcode": "ERROR_GROUP_NOT_FOUND"}, status=status.HTTP_404_NOT_FOUND
{"message": "Group not found", "errorcode":
"ERROR_GROUP_NOT_FOUND"}, status=status.HTTP_404_NOT_FOUND
)

project = Project.objects.get(project_id=group.project_id.project_id)
if not project:
return Response(
{"message": "Project not found"},
status=status.HTTP_404_NOT_FOUND
{"message": "Project not found", "errorcode":
"ERROR_PROJECT_NOT_FOUND"}, status=status.HTTP_404_NOT_FOUND
)

now_naive = datetime.now().replace(
tzinfo=pytz.UTC
) # Making it timezone-aware in UTC
if project.deadline and now_naive > project.deadline:
return Response(
{"message": "Deadline expired"},
{"message": "Deadline expired",
"errorcode": "ERROR_DEADLINE_EXPIRED"},
status=status.HTTP_400_BAD_REQUEST

)

serializer.save()
Expand All @@ -116,8 +117,8 @@ def create(self, request, *args, **kwargs):
except IOError as e:
print(e)
return Response(
{"message": "Error uploading files"},
status=status.HTTP_400_BAD_REQUEST
{"message": "Error uploading files", "errorcode":
"ERROR_FILE_UPLOAD"}, status=status.HTTP_400_BAD_REQUEST
)

return Response(serializer.data, status=status.HTTP_201_CREATED)
Expand All @@ -133,13 +134,15 @@ def download(self, request, *args, **kwargs):
submission = self.get_object()
if submission is None:
return Response(
{"message": f"Submission with id {id} not found", "errorcode": "ERROR_SUBMISSION_NOT_FOUND"},
{"message": f"Submission with id {id} not found", "errorcode":
"ERROR_SUBMISSION_NOT_FOUND"},
status=status.HTTP_404_NOT_FOUND
)

archivename = "submission_" + str(submission.submission_id)
downloadspath = 'backend/downloads/'
submission_path = submission_folder_path(submission.group_id.group_id, submission.submission_id)
submission_path = submission_folder_path(submission.group_id.group_id,
submission.submission_id)

shutil.make_archive(downloadspath + archivename, 'zip', submission_path)

Expand All @@ -165,7 +168,8 @@ def download_selection(self, request, *args, **kwargs):
submission = Submissions.objects.get(submission_id=ids[0])
if submission is None:
return Response(
{"message": f"Submission with id {ids[0]} not found", "errorcode": "ERROR_SUBMISSION_NOT_FOUND"},
{"message": f"Submission with id {ids[0]} not found",
"errorcode": "ERROR_SUBMISSION_NOT_FOUND"},
status=status.HTTP_404_NOT_FOUND,
)

Expand All @@ -179,7 +183,8 @@ def download_selection(self, request, *args, **kwargs):
submission = Submissions.objects.get(submission_id=sid)
if submission is None:
return Response(
{"message": f"Submission with id {id} not found", "errorcode": "ERROR_SUBMISSION_NOT_FOUND"},
{"message": f"Submission with id {id} not found",
"errorcode": "ERROR_SUBMISSION_NOT_FOUND"},
status=status.HTTP_404_NOT_FOUND
)
submission_folders.append(
Expand Down
5 changes: 3 additions & 2 deletions frontend/app/[locale]/components/ListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ import {
getUser,
getUserData,
getUsers,
postData
postData,
getOpenCourses
} from '@lib/api';
import baseTheme from "../../../styles/theme";
import {useTranslation} from "react-i18next";
Expand Down Expand Up @@ -194,7 +195,7 @@ const ListView: NextPage<ListViewProps> = ({
return parse_pages(await getTeachers_by_course(get_id, currentPage, page_size, searchTerm, sortConfig.key.toLowerCase(), sortConfig.direction === 'asc' ? 'asc' : 'desc'));
},
'courses': async () => {
return parse_pages(await getCourses(currentPage, page_size, searchTerm, sortConfig.key.toLowerCase(), sortConfig.direction === 'asc' ? 'asc' : 'desc'));
return parse_pages(await getOpenCourses(currentPage, page_size, searchTerm, sortConfig.key.toLowerCase(), sortConfig.direction === 'asc' ? 'asc' : 'desc'));
},
'projects': async () => {
return parse_pages(await getProjects_by_course(get_id, currentPage, page_size, searchTerm, sortConfig.key.toLowerCase(), sortConfig.direction === 'asc' ? 'asc' : 'desc'));
Expand Down
18 changes: 18 additions & 0 deletions frontend/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,24 @@ export async function getArchivedCourses(page = 1, pageSize = 5, keyword?: strin
return await getRequest(url);
}

export async function getOpenCourses(page = 1, pageSize = 5, keyword?: string, orderBy?: string, sortOrder?: string): Promise<Course[]> {
let url = `/courses/get_open_courses?page=${page}&page_size=${pageSize}`;

if (keyword) {
url += `&keyword=${keyword}`;
}

if (orderBy) {
url += `&order_by=${orderBy}`;
}

if (sortOrder) {
url += `&sort_order=${sortOrder}`;
}

return await getRequest(url);
}

export async function archiveCourse(id: number): Promise<number> {
return (await patchData(`/courses/${id}/`, {
archived: true
Expand Down

0 comments on commit b729b85

Please sign in to comment.