Skip to content

Commit

Permalink
Feature: add a view for browsering all the submissions within a cours…
Browse files Browse the repository at this point in the history
…e, with tag filter enabled
  • Loading branch information
James-Leste committed Dec 20, 2024
1 parent d20f05f commit b8b2552
Show file tree
Hide file tree
Showing 5 changed files with 176 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}}
</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
43 changes: 42 additions & 1 deletion course/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,21 @@
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
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 +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')

0 comments on commit b8b2552

Please sign in to comment.