From 6b794156bf6d16297bff1df793359bd0a790b8aa Mon Sep 17 00:00:00 2001 From: JasonGrace2282 Date: Fri, 10 Jan 2025 21:30:09 -0500 Subject: [PATCH] Simplify UI --- tin/apps/assignments/forms.py | 51 +++++------ tin/apps/assignments/urls.py | 11 --- tin/apps/assignments/views.py | 51 +++-------- .../assignments/choose_submission_cap.html | 87 ------------------- .../edit_create_submission_cap.html | 31 ------- tin/templates/assignments/show.html | 1 - .../assignments/student_submissions.html | 25 ++++++ 7 files changed, 61 insertions(+), 196 deletions(-) delete mode 100644 tin/templates/assignments/choose_submission_cap.html delete mode 100644 tin/templates/assignments/edit_create_submission_cap.html diff --git a/tin/apps/assignments/forms.py b/tin/apps/assignments/forms.py index 4ab52eb7..260b52c9 100644 --- a/tin/apps/assignments/forms.py +++ b/tin/apps/assignments/forms.py @@ -15,6 +15,9 @@ class AssignmentForm(forms.ModelForm): due = forms.DateTimeInput() + submission_cap = forms.IntegerField(min_value=1) + submission_cap_after_due = forms.IntegerField(min_value=1, required=False) + def __init__(self, course, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["folder"].queryset = Folder.objects.filter(course=course) @@ -136,6 +139,8 @@ class Meta: "submission_limit_count", "submission_limit_interval", "submission_limit_cooldown", + "submission_cap", + "submission_cap_after_due", ), "collapsed": True, }, @@ -152,7 +157,8 @@ class Meta: "seconds). This is not recommended unless necessary.", "use_submission_cap": "This enables setting a limit on the number of submissions that can be made on assignments." "It has no effect on quizzes", - "submission_cap": "The maximum number of submissions that can be made. It can be overridden on a per-student basis.", + "submission_cap": "The maximum number of submissions that can be made, or empty for unlimited.", + "submission_cap_after_due": "The maximum number of submissions that can be made after the due date, or empty for unlimited.", "submission_limit_count": "", "submission_limit_interval": "Tin sets rate limits on submissions. If a student tries " "to submit too many submissions in a given interval, " @@ -183,6 +189,21 @@ class Meta: def __str__(self) -> str: return f"AssignmentForm(\"{self['name'].value()}\")" + def save(self, **kwargs) -> Assignment: + assignment = super().save(**kwargs) + sub_cap = self.cleaned_data.get("submission_cap") + sub_cap_after_due = self.cleaned_data.get("submission_cap_after_due") + if sub_cap is not None or sub_cap_after_due is not None: + SubmissionCap.objects.update_or_create( + assignment=assignment, + student=None, + defaults={ + "submission_cap": sub_cap, + "submission_cap_after_due": sub_cap_after_due, + }, + ) + return assignment + class GraderScriptUploadForm(forms.Form): grader_file = forms.FileField( @@ -247,38 +268,18 @@ class Meta: class SubmissionCapForm(forms.ModelForm): - def __init__(self, assignment: Assignment, **kwargs) -> None: + def __init__(self, **kwargs) -> None: super().__init__(**kwargs) - nonrequired = ("student", "submission_cap", "submission_cap_after_due") + nonrequired = ("submission_cap", "submission_cap_after_due") for f in nonrequired: self.fields[f].required = False - self._assignment = assignment - class Meta: model = SubmissionCap - fields = ["submission_cap", "submission_cap_after_due", "student"] + fields = ["submission_cap", "submission_cap_after_due"] help_texts = { "submission_cap_after_due": "The submission cap after the due date (or empty for unlimited)", - "student": ( - "The student to apply the cap to, or leave empty to apply to all students." - ), + "student": "The student to apply the cap to.", } labels = {"submission_cap_after_due": "Submission cap after due date"} - - # In Django 5.0+, this should be handled by django - # with the nulls_distinct=False argument to the student UniqueConstraint - def clean_student(self): - student = self.cleaned_data["student"] - if student is not None: - return student - default_cap = self._assignment.submission_caps.filter(student__isnull=True).first() - if default_cap is None: - return student - - if self.instance.id != default_cap.id: - raise forms.ValidationError( - "To edit the submission cap for all students please use the existing default submission cap." - ) - return student diff --git a/tin/apps/assignments/urls.py b/tin/apps/assignments/urls.py index d3a55dc8..13924cff 100644 --- a/tin/apps/assignments/urls.py +++ b/tin/apps/assignments/urls.py @@ -13,17 +13,6 @@ path("/delete", views.delete_view, name="delete"), path("/grader", views.manage_grader_view, name="manage_grader"), path("/grader/download", views.download_grader_view, name="download_grader"), - path("/submission-cap", views.choose_submission_cap, name="submission_cap"), - path( - "/submission-cap/create", - views.create_submission_cap, - name="create_submission_cap", - ), - path( - "/submission-cap/", - views.create_submission_cap, - name="edit_submission_cap", - ), path("/files", views.manage_files_view, name="manage_files"), path( "/files/download/", diff --git a/tin/apps/assignments/views.py b/tin/apps/assignments/views.py index ed355d27..6f93abd3 100644 --- a/tin/apps/assignments/views.py +++ b/tin/apps/assignments/views.py @@ -301,47 +301,6 @@ def delete_view(request, assignment_id): return redirect(reverse("courses:show", args=(course.id,))) -@teacher_or_superuser_required -def choose_submission_cap(request, assignment_id): - assignment = get_object_or_404(Assignment, id=assignment_id) - caps = assignment.submission_caps.all() - return render( - request, - "assignments/choose_submission_cap.html", - {"assignment": assignment, "caps": caps}, - ) - - -@teacher_or_superuser_required -def create_submission_cap(request, assignment_id, submission_cap_id: int | None = None): - assignment = get_object_or_404( - Assignment.objects.prefetch_related("course__students"), - id=assignment_id, - ) - cap = ( - get_object_or_404(assignment.submission_caps, id=submission_cap_id) - if submission_cap_id is not None - else None - ) - - form = SubmissionCapForm(assignment, instance=cap) - if request.method == "POST": - form = SubmissionCapForm(assignment, data=request.POST, instance=cap) - if form.is_valid(): - form.instance.assignment = assignment - form.save() - return redirect("assignments:show", assignment_id) - return render( - request, - "assignments/edit_create_submission_cap.html", - { - "form": form, - "assignment": assignment, - "cap": cap, - }, - ) - - @teacher_or_superuser_required def manage_grader_view(request, assignment_id): """Uploads a grader for an assignment @@ -559,6 +518,15 @@ def student_submissions_view(request, assignment_id, student_id): ) student = get_object_or_404(User, id=student_id) + cap = assignment.submission_caps.filter(student=student).first() + form = SubmissionCapForm(instance=cap) + if request.method == "POST": + form = SubmissionCapForm(data=request.POST, instance=cap) + if form.is_valid(): + form.instance.assignment = assignment + form.instance.student = student + form.save() + submissions = Submission.objects.filter(student=student, assignment=assignment) publishes = PublishedSubmission.objects.filter(student=student, assignment=assignment) latest_submission = submissions.latest() if submissions else None @@ -582,6 +550,7 @@ def student_submissions_view(request, assignment_id, student_id): "latest_submission": latest_submission, "published_submission": published_submission, "log_messages": log_messages, + "form": form, }, ) diff --git a/tin/templates/assignments/choose_submission_cap.html b/tin/templates/assignments/choose_submission_cap.html deleted file mode 100644 index be7e4a92..00000000 --- a/tin/templates/assignments/choose_submission_cap.html +++ /dev/null @@ -1,87 +0,0 @@ -{% extends "base.html" %} -{% load static %} - -{% block head %} - -{% endblock head %} - -{% block main %} -

Submission Caps

- -
- - - - - - {% if caps %} - - {% endif %} - - {% for cap in caps %} - - - - - - - {% empty %} - - - - - - {% endfor %} -
Max Submissions before Due DateMax Submissions after Due DateApplicable to:
{{ cap.submission_cap }}{{ cap.submission_cap_after_due }}{{ cap.student | default:"All" }} - - Edit - -
UnlimitedUnlimitedAll
-
- -{% endblock %} diff --git a/tin/templates/assignments/edit_create_submission_cap.html b/tin/templates/assignments/edit_create_submission_cap.html deleted file mode 100644 index e347a9ef..00000000 --- a/tin/templates/assignments/edit_create_submission_cap.html +++ /dev/null @@ -1,31 +0,0 @@ -{% extends "base.html" %} - -{% block main %} - {% if cap %} -

Editing Submission Cap

- {% else %} -

Creating Submission Cap

- {% endif %} -

{{ name }}

- -
- {% csrf_token %} - - {{ form.errors }} -
- {% for field in form.visible_fields %} -
- {{ field.label_tag }} - {{ field }}{% if field.help_text %}
{{ field.help_text }}{% endif %}
-
- {% endfor %} - {% for field in form.hidden_fields %} - {{ field }} - {% endfor %} -
- -
- -
- Back -{% endblock %} diff --git a/tin/templates/assignments/show.html b/tin/templates/assignments/show.html index 536530c2..44e32a2e 100644 --- a/tin/templates/assignments/show.html +++ b/tin/templates/assignments/show.html @@ -36,7 +36,6 @@

{% if assignment.is_quiz %}[QUIZ] {% endif %}{{ assignment.name Upload grader {% endif %} Manage files - Submission cap {% if log_file_exists %} Download log {% endif %} diff --git a/tin/templates/assignments/student_submissions.html b/tin/templates/assignments/student_submissions.html index 3d0976f5..aecdc3e6 100644 --- a/tin/templates/assignments/student_submissions.html +++ b/tin/templates/assignments/student_submissions.html @@ -111,4 +111,29 @@

All Submissions

+ +

Edit Submission Cap

+ To change the submission cap for this student, enter a new cap below. +
+ {% csrf_token %} + {{ form.errors }} +
+ {% for field in form.visible_fields %} +
+ {{ field.label }} + + {{ field }} + {% if field.help_text %} +
{{ field.help_text }} + {% endif %} +
+
+ {% endfor %} + {% for field in form.hidden_fields %} + {{ field }} + {% endfor %} +
+ +
+ {% endblock %}