From b8b2552d7a6a98cee2007d2a6b4b1fd872be94eb Mon Sep 17 00:00:00 2001 From: Ziqi Wang Date: Mon, 16 Dec 2024 15:17:40 +0200 Subject: [PATCH] Feature: add a view for browsering all the submissions within a course, with tag filter enabled --- course/long_urls.py | 3 + course/templates/course/_course_menu.html | 6 + .../staff/all_exercise_submissions.html | 124 ++++++++++++++++++ course/viewbase.py | 1 + course/views.py | 43 +++++- 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 course/templates/course/staff/all_exercise_submissions.html diff --git a/course/long_urls.py b/course/long_urls.py index c88552668..4f2eba841 100644 --- a/course/long_urls.py +++ b/course/long_urls.py @@ -44,4 +44,7 @@ re_path(EDIT_URL_PREFIX + r'groups/(?P\d+)/delete/$', staff_views.GroupsDeleteView.as_view(), name="groups-delete"), + re_path(EDIT_URL_PREFIX + r'all-exercise-submissions/$', + views.AllSubmissionsView.as_view(), + name="all-exercise-submissions"), ] diff --git a/course/templates/course/_course_menu.html b/course/templates/course/_course_menu.html index 0649608f9..57261b9dc 100644 --- a/course/templates/course/_course_menu.html +++ b/course/templates/course/_course_menu.html @@ -232,6 +232,12 @@

{% translate "COURSE_STAFF" %}

{% translate "SUBMISSION_DEVIATIONS" %} + {% endif %} diff --git a/course/templates/course/staff/all_exercise_submissions.html b/course/templates/course/staff/all_exercise_submissions.html new file mode 100644 index 000000000..79cc24b8d --- /dev/null +++ b/course/templates/course/staff/all_exercise_submissions.html @@ -0,0 +1,124 @@ +{% extends "course/course_base.html" %} +{% load i18n %} +{% load course %} +{% load exercise %} +{% load static %} +{% load colortag %} + +{% block title %}{% translate "ALL_SUBMISSIONS" %} | {{ block.super }}{% endblock %} +{% block view_tag %}{% translate "ALL_SUBMISSIONS" %}{% endblock %} + +{% block breadcrumblist %} +{{ block.super }} +
  • {% translate "ALL_SUBMISSIONS" %}
  • +{% endblock %} + +{% block columns %} +
    +
    +

    + {% if count <= default_limit and not limited %} + {% blocktranslate trimmed with count=count url=all_url %} + NUM_OF_SUBMISSIONS_DISPLAYED -- {{ count }}, {{ url }} + {% endblocktranslate %} + {% elif limited %} + {% blocktranslate trimmed with limit=default_limit url=all_url %} + NUM_OF_SUBMISSIONS_DISPLAYED_AND_SHOW_ALL_BTN -- {{ limit }}, {{ url }} + {% endblocktranslate %} + {% else %} + {% blocktranslate trimmed with count=count url=not_all_url limit=default_limit %} + NUM_OF_SUBMISSIONS_DISPLAYED_AND_SHOW_LATEST_BTN -- {{ count }}, {{ url }}, {{ limit }} + {% endblocktranslate %} + {% endif %} +

    +
    + +

    + {% trans "FILTER_SUBMISSIONS_BY_TAG" %}: + {% for tag in tags %} + + {% endfor %} +

    + + + + + + + + + + + + + + + + + {% for summary in submission_data %} + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
    {% translate "SUBMITTERS" %}{% translate "TIME" %}{% translate "STATUS" %}{% translate "GRADE" %}{% translate "TAGS" %} + {% translate "ASSESSED_MANUALLY" %} + {% translate "INSPECT" %}{% translate "EXERCISE" %}
    + {% profiles summary.submitters instance summary.is_teacher %} + + {{ summary.submission.submission_time|date:'DATETIME_SECONDS_FORMAT' }} + {% if summary.submission.late_penalty_applied %} + + {% blocktranslate trimmed with percent=summary.submission.late_penalty_applied|percent %} + LATE_W_PENALTY -- {{ percent }} + {% endblocktranslate %} + + {% endif %} + + {{ summary.submission.status|submission_status }} + + {% format_points summary.submission.grade True True %} + + {% for tagging in summary.submission.submission_taggings.all %} + {{ tagging.tag|colortag }} + {% endfor %} + + {% if summary.submission.grader %} + + {% translate "YES" %} + {% else %} + + {% translate "NO" %} + {% endif %} + + + + {% translate "INSPECT" %} + + + + {{summary.exercise}} + +
    {% translate "NO_SUBMISSIONS" %}
    +
    + + +{% endblock %} diff --git a/course/viewbase.py b/course/viewbase.py index df057fe1c..7366acf46 100644 --- a/course/viewbase.py +++ b/course/viewbase.py @@ -107,6 +107,7 @@ def get_resource_objects(self): self.is_teacher = self.instance.is_teacher(user) self.is_course_staff = self.is_teacher or self.is_assistant self.url_without_language = remove_query_param_from_url(self.request.get_full_path(), 'hl') + self.url_without_limited = remove_query_param_from_url(self.request.get_full_path(), 'limited') self.query_language = None self.user_language = None self.pseudonymize = self.request.session.get('pseudonymize', False) diff --git a/course/views.py b/course/views.py index 61c529452..16a254e78 100644 --- a/course/views.py +++ b/course/views.py @@ -17,8 +17,12 @@ from django.utils.translation import gettext_lazy as _ from authorization.permissions import ACCESS + from exercise.cache.hierarchy import NoSuchContent from exercise.models import LearningObject +from exercise.submission_models import Submission + +#from exercise.views import ResultView from lib.helpers import settings_text, remove_query_param_from_url, is_ajax from lib.viewbase import BaseTemplateView, BaseRedirectMixin, BaseFormView, BaseView, BaseRedirectView from userprofile.viewbase import UserProfileView @@ -26,7 +30,8 @@ from .models import Course, CourseInstance, CourseModule, Enrollment from .permissions import EnrollInfoVisiblePermission from .renders import group_info_context -from .viewbase import CourseModuleBaseView, CourseInstanceMixin, EnrollableViewMixin, CourseMixin +from .viewbase import CourseModuleBaseView, CourseInstanceMixin,\ + EnrollableViewMixin, CourseMixin, CourseInstanceBaseView class HomeView(UserProfileView): @@ -380,3 +385,39 @@ def post(self, request, *args, **kwargs): ) request.REQUEST_LANG = lang_code return response + +class AllSubmissionsView(CourseInstanceBaseView): + access_mode = ACCESS.ASSISTANT + template_name = 'course/staff/all_exercise_submissions.html' + + def get_common_objects(self): + super().get_common_objects() + + self.tags = self.instance.submissiontags.all() + self.default_limit = 50 + + submissions_data = ( + Submission.objects + .filter(exercise__course_module__course_instance=self.instance.id) + ) + row_data = [] + for submission in submissions_data: + row_data.append({ + 'submission': submission, + 'exercise': submission.exercise, + 'submitters': submission.submitters.all(), + 'is_teacher': self.instance.is_teacher(self.request.user), + }) + self.count = len(row_data) + self.limited = self.request.GET.get('limited', False) + self.submission_data = row_data[:self.default_limit] if self.limited else row_data + self.not_all_url = self.url_without_limited + '?limited=true' + self.all_url = self.url_without_limited + + self.note('submission_data', + 'count', + 'default_limit', + 'tags', + 'limited', + 'not_all_url', + 'all_url')