Skip to content

Commit

Permalink
Feature: add a view for browsing all the submissions within a course,…
Browse files Browse the repository at this point in the history
… with the tags filter enabled
  • Loading branch information
James-Leste committed Dec 20, 2024
1 parent d20f05f commit 59bee4c
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 1 deletion.
3 changes: 3 additions & 0 deletions course/long_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,7 @@
re_path(EDIT_URL_PREFIX + r'groups/(?P<group_id>\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"),
]
6 changes: 6 additions & 0 deletions course/templates/course/_course_menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ <h4>{% translate "COURSE_STAFF" %}</h4>
{% translate "SUBMISSION_DEVIATIONS" %}
</a>
</li>
<li class="menu-all-exercise-submissions">
<a href="{{ instance|url:'all-exercise-submissions' }}">
<span class="glyphicon glyphicon-list" aria-hidden="true"></span>
All Submissions
</a>
</li>

{% endif %}

Expand Down
124 changes: 124 additions & 0 deletions course/templates/course/staff/all_exercise_submissions.html
Original file line number Diff line number Diff line change
@@ -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 }}
<li class="active">{% translate "ALL_SUBMISSIONS" %}</li>
{% endblock %}

{% block columns %}
<div class="col-md-12">
<div class="clearfix">
<p>
{% 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 %}
</p>
</div>

<p class="filter-submissions">
<small>{% trans "FILTER_SUBMISSIONS_BY_TAG" %}:</small>
{% for tag in tags %}
<button class="btn btn-default btn-xs filter-tag" style="background-color:{{ tag.color }};color:{{ tag.font_color }};" data-tagslug="{{ tag.slug }};" data-status="{{ tag.status }}" >
<span class="glyphicon glyphicon-unchecked" aria-hidden="true"></span>
{{ tag.name }}
</button>
{% endfor %}
</p>

<table class="table table-bordered{% if not limited or count < default_limit %} filtered-table ordered-table{% endif %}" id="submissions_table">
<thead>
<tr>
<th>{% translate "SUBMITTERS" %}</th>
<th>{% translate "TIME" %}</th>
<th>{% translate "STATUS" %}</th>
<th>{% translate "GRADE" %}</th>
<th>{% translate "TAGS" %}</th>

<th
data-filter-type="options"
data-filter-options="{% translate 'YES' %}|{% translate 'NO' %}"
data-order-disable="true"
>
{% translate "ASSESSED_MANUALLY" %}
</th>
<th data-filter-type="none" data-order-disable="true">{% translate "INSPECT" %}</th>
<th>{% translate "EXERCISE" %}</th>
</tr>
</thead>
<tbody>
{% for summary in submission_data %}
<tr id="summary.submission-{{ summary.submission.id }}">
<td>
{% profiles summary.submitters instance summary.is_teacher %}
</td>
<td data-datetime="{{ summary.submission.submission_time|date:'Y-m-d H:i:s' }}">
{{ summary.submission.submission_time|date:'DATETIME_SECONDS_FORMAT' }}
{% if summary.submission.late_penalty_applied %}
<span class="label label-warning">
{% blocktranslate trimmed with percent=summary.submission.late_penalty_applied|percent %}
LATE_W_PENALTY -- {{ percent }}
{% endblocktranslate %}
</span>
{% endif %}
</td>
<td>
{{ summary.submission.status|submission_status }}
</td>
<td>
{% format_points summary.submission.grade True True %}
</td>
<td id="submission_tags">
{% for tagging in summary.submission.submission_taggings.all %}
{{ tagging.tag|colortag }}
{% endfor %}
</td>
<td>
{% if summary.submission.grader %}
<span class="glyphicon glyphicon-ok"></span>
{% translate "YES" %}
{% else %}
<span class="glyphicon glyphicon-remove"></span>
{% translate "NO" %}
{% endif %}
</td>
<td>
<a href="{{ summary.submission|url:'submission-inspect' }}" class="aplus-button--secondary aplus-button--xs">
<span class="glyphicon glyphicon-zoom-in" aria-hidden="true"></span>
{% translate "INSPECT" %}
</a>
</td>
<td>
<a href="{{ summary.exercise|url }}">
{{ summary.exercise | parse_localization }}
</a>
</td>
</tr>
{% empty %}
<tr>
<td class="5">{% translate "NO_SUBMISSIONS" %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

<script src="{% static 'exercise/filter_submissions_by_tag.js' %}"></script>
{% endblock %}
1 change: 1 addition & 0 deletions course/viewbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
42 changes: 41 additions & 1 deletion course/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@
from authorization.permissions import ACCESS
from exercise.cache.hierarchy import NoSuchContent
from exercise.models import LearningObject
from exercise.submission_models import Submission
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

from .forms import GroupsForm, GroupSelectForm
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):
Expand Down Expand Up @@ -380,3 +383,40 @@ 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()
row_data = []

submissions_data = (
Submission.objects
.filter(exercise__course_module__course_instance=self.instance.id)
)

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.tags = self.instance.submissiontags.all()
self.default_limit = 50
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')

0 comments on commit 59bee4c

Please sign in to comment.