From 2e985ee9e47ed80cbc6e918f14cf546891856731 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 17 Jul 2023 22:32:42 +0200 Subject: [PATCH 01/74] Vision More realistic alternative to `current` Add custom elements scaffold looks right, doesn't open found a way to use import, but not have icons modal texts displayed before script is loaded fix usage of custom elements prototype before it was loaded make it open the modal dont know some progess with native dialogs make it look somewhat like bootstrap progress? make animations work implement confirmation logic ough, now the slots inherit values from the .card-header bar Use `:defined` instead of `.loaded` class more modals and fix blocktrans Allow putting extra stuff under `confirmation-modal` more modals format more modals --- .../contributor_evaluation_form.html | 31 ++-- .../templates/contributor_index.html | 73 +++------ evap/evaluation/templates/base.html | 2 + .../confirmation_modal_template.html | 33 +++++ .../evaluation/templates/custom_elements.html | 9 ++ evap/grades/templates/grades_course_view.html | 59 +++++--- .../templates/grades_semester_view.html | 75 +++++----- evap/staff/templates/staff_semester_view.html | 138 +++++++++++------- evap/staff/templates/staff_user_import.html | 33 ++--- evap/staff/views.py | 3 +- evap/static/scss/_components.scss | 1 + .../scss/components/_confirmation-modal.scss | 77 ++++++++++ evap/static/ts/src/confirmation-modal.ts | 62 ++++++++ evap/static/ts/src/utils.ts | 2 +- 14 files changed, 386 insertions(+), 212 deletions(-) create mode 100644 evap/evaluation/templates/confirmation_modal_template.html create mode 100644 evap/evaluation/templates/custom_elements.html create mode 100644 evap/static/scss/components/_confirmation-modal.scss create mode 100644 evap/static/ts/src/confirmation-modal.ts diff --git a/evap/contributor/templates/contributor_evaluation_form.html b/evap/contributor/templates/contributor_evaluation_form.html index ecd2e22c5..9fb2b90d4 100644 --- a/evap/contributor/templates/contributor_evaluation_form.html +++ b/evap/contributor/templates/contributor_evaluation_form.html @@ -90,9 +90,18 @@
{% trans 'Evaluation data' %}
{% if editable %} - {# webtest does not allow submission with value "approve" if no such button exists #} - - + + + {% trans 'Approve evaluation' %} + {% trans 'Approve evaluation' %} + + {% blocktrans %} + Do you want to approve this evaluation? This will allow the evaluation team to proceed with the preparation, but you won't be able to make any further changes. + {% endblocktrans %} + + + + {% endif %} {% if edit %}{% trans 'Cancel' %}{% else %}{% trans 'Back' %}{% endif %} @@ -121,22 +130,6 @@ {% block modals %} {{ block.super }} - {% trans 'Approve evaluation' as title %} - {% blocktrans asvar question%}Do you want to approve this evaluation? This will allow the evaluation team to proceed with the preparation, but you won't be able to make any further changes.{% endblocktrans %} - {% trans 'Approve evaluation' as action_text %} - {% include 'confirmation_modal.html' with modal_id='approveEvaluationModal' title=title question=question action_text=action_text btn_type='primary' %} - {% blocktrans asvar title with evaluation_name=evaluation.full_name %}Request account creation for {{ evaluation_name }}{% endblocktrans %} {% trans 'Please tell us which new account we should create. We need the name and email for all new accounts.' as teaser %} diff --git a/evap/contributor/templates/contributor_index.html b/evap/contributor/templates/contributor_index.html index e61132d2c..d49eef391 100644 --- a/evap/contributor/templates/contributor_index.html +++ b/evap/contributor/templates/contributor_index.html @@ -157,12 +157,22 @@ {% if not evaluation|has_nonresponsible_editor %} - - - + + {% trans 'Delegate preparation' %} + {% trans 'Delegate preparation' %} + + {% blocktrans with evaluation_name=evaluation.full_name %} + Do you really want to delegate the preparation of the evaluation {{ evaluation_name }}? + {% endblocktrans %} +
+ {% include 'bootstrap_form.html' with form=delegate_selection_form wide=True %} +
+
+ + + + +
{% endif %} {% elif evaluation.state == evaluation.State.EDITOR_APPROVED or evaluation.state == evaluation.State.APPROVED %} + + {% endif %} {% endfor %} {% endblock %} - -{% block modals %} - {{ block.super }} - - {% with modal_id='delegateSelectionModal' %} - - - - {% endwith %} -{% endblock %} diff --git a/evap/evaluation/templates/base.html b/evap/evaluation/templates/base.html index e43781306..3dcbad3df 100644 --- a/evap/evaluation/templates/base.html +++ b/evap/evaluation/templates/base.html @@ -28,6 +28,8 @@ + {% include "custom_elements.html" %} + {% block modals %} {% if user.is_authenticated %} {% trans 'Feedback' as title %} diff --git a/evap/evaluation/templates/confirmation_modal_template.html b/evap/evaluation/templates/confirmation_modal_template.html new file mode 100644 index 000000000..bf13e9072 --- /dev/null +++ b/evap/evaluation/templates/confirmation_modal_template.html @@ -0,0 +1,33 @@ +{% load static %} + + diff --git a/evap/evaluation/templates/custom_elements.html b/evap/evaluation/templates/custom_elements.html new file mode 100644 index 000000000..f2093a71a --- /dev/null +++ b/evap/evaluation/templates/custom_elements.html @@ -0,0 +1,9 @@ +{% load static %} + +{% include "confirmation_modal_template.html" %} + + diff --git a/evap/grades/templates/grades_course_view.html b/evap/grades/templates/grades_course_view.html index 1bf12162c..1f4f60be2 100644 --- a/evap/grades/templates/grades_course_view.html +++ b/evap/grades/templates/grades_course_view.html @@ -1,4 +1,5 @@ {% extends 'grades_course_base.html' %} +{% load static %} {% block content %} {{ block.super }} @@ -30,13 +31,45 @@

{{ course.name }} ({{ semester.name }})

{% if user.is_grade_publisher %} - + + {% trans 'Delete grade document' %} + {% trans 'Delete grade document' %} + + {% blocktrans with description=grade_document.description %} + Do you really want to delete the grade document {{ description }}? + {% endblocktrans %} + + + + {% endif %} {% endfor %} + + {% else %} @@ -49,23 +82,3 @@

{{ course.name }} ({{ semester.name }})

{% trans 'Upload new final grades' %} {% endif %} {% endblock %} - -{% block modals %} - {{ block.super }} - {% trans 'Delete grade document' as title %} - {% trans 'Do you really want to delete the grade document ?' as question %} - {% trans 'Delete grade document' as action_text %} - {% include 'confirmation_modal.html' with modal_id='deleteGradedocumentModal' title=title question=question action_text=action_text btn_type='danger' %} - -{% endblock %} diff --git a/evap/grades/templates/grades_semester_view.html b/evap/grades/templates/grades_semester_view.html index 73ed72cd0..7e50dd199 100644 --- a/evap/grades/templates/grades_semester_view.html +++ b/evap/grades/templates/grades_semester_view.html @@ -64,17 +64,47 @@

{% if num_final_grades > 0 %} {{ num_final_grades }} {% elif course.gets_no_grade_documents %} - - - +
+ {{ csrf_token }} + + + + {% trans 'Will final grades be uploaded?' %} + {% trans 'Confirm' %} + + {% blocktrans with course_name=course.name %} + Please confirm that a grade document for the course {{ course_name }} will be uploaded later on. + {% endblocktrans %} + + + + + + +
{% endif %} {% if not course.gets_no_grade_documents %} {% if num_final_grades == 0 %} - +
+ {{ csrf_token }} + + + {% trans 'Have final grades been submitted?' %} + {% trans 'Confirm' %} + + {% blocktrans with course_name=course.name %} + Please confirm that the final grades for the course {{ course_name }} have been submitted but will not be uploaded. + {% endblocktrans %} + + + + +
+
{% endblock %} -{% block modals %} - {{ block.super }} - {% trans 'Have final grades been submitted?' as title %} - {% trans 'Please confirm that the final grades for the course have been submitted but will not be uploaded.' as question %} - {% trans 'Confirm' as action_text %} - {% include 'confirmation_modal.html' with modal_id='confirmNouploadModal' title=title question=question action_text=action_text btn_type='primary' %} - - {% trans 'Will final grades be uploaded?' as title %} - {% trans 'Please confirm that a grade document for the course will be uploaded later on.' as question %} - {% trans 'Confirm' as action_text %} - {% include 'confirmation_modal.html' with modal_id='confirmLateruploadModal' title=title question=question action_text=action_text btn_type='primary' %} - -{% endblock %} - {% block additional_javascript %} + + + {% endif %} {% if request.user.is_manager %}
@@ -72,8 +116,25 @@

{% trans 'Reward points active' %}
- - +
+ {% csrf_token %} + + + {% trans 'Activate reward points' %} + {% trans 'Activate reward points' %} + + {% blocktrans with semester_name=semester.name %} + Do you want to activate the reward points for the semester {{ semester_name }}? + The activation will allow participants to receive reward points when voting and will also grant all eligible points for participants who have already voted so far. + The process will take a while. + {% endblocktrans %} + + + + + + +

@@ -464,26 +525,6 @@

}).catch(error => {window.alert("{% trans 'The server is not responding.' %}");}); } - {% trans 'Delete semester' as title %} - {% blocktrans asvar question %}Do you really want to delete the semester ? All courses and evaluations will be deleted as well as all results. If you are sure, enter the name of the semester below.{% endblocktrans %} - {% trans 'Delete semester' as action_text %} - {% include 'confirmation_text_modal.html' with modal_id='deleteSemesterModal' title=title question=question action_text=action_text btn_type='danger' %} - {% trans 'Archive participations' as title %} {% blocktrans asvar question %}Do you really want to archive all participations in the semester ? Further changes to the evaluations won't be possible and you can't undo this action.{% endblocktrans %} {% trans 'Archive participations' as action_text %} @@ -564,15 +605,6 @@

}).catch(error => {window.alert("{% trans 'The server is not responding.' %}");}); }; - {% trans 'Activate reward points' as title %} - {% blocktrans asvar question %}Do you want to activate the reward points for the semester ? The activation will allow participants to receive reward points when voting and will also grant all eligible points for participants who have already voted so far. The process will take a while.{% endblocktrans %} - {% trans 'Activate reward points' as action_text %} - {% include 'confirmation_modal.html' with modal_id='activateRewardPointsModal' title=title question=question action_text=action_text btn_type='primary' %} - {% endblock %} {% block additional_javascript %} diff --git a/evap/staff/templates/staff_user_import.html b/evap/staff/templates/staff_user_import.html index b31605214..6593fd135 100644 --- a/evap/staff/templates/staff_user_import.html +++ b/evap/staff/templates/staff_user_import.html @@ -34,33 +34,24 @@

{% trans 'Import users' %}

{% else %} + + + {% trans 'Import Users' %} + {% trans 'Import Users' %} + + {% blocktrans %} + Do you really want to import the users from the Excel file? + {% endblocktrans %} + + + + {% endif %} {% endblock %} -{% block modals %} -{{ block.super }} - {% trans 'Import Users' as title %} - {% blocktrans asvar question %}Do you really want to import the users from the Excel file?{% endblocktrans %} - {% trans 'Import Users' as action_text %} - {% include 'confirmation_modal.html' with modal_id='importUserModal' title=title question=question action_text=action_text btn_type='primary' %} - - -{% endblock %} - {% block additional_javascript %} {% endblock %} diff --git a/evap/staff/views.py b/evap/staff/views.py index c9a8f7ddb..b2a4c1496 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -635,7 +635,8 @@ def semester_delete(request): Contribution.objects.filter(evaluation__course__semester=semester).delete() Evaluation.objects.filter(course__semester=semester).delete() Course.objects.filter(semester=semester).delete() - semester.delete() + # TODO: revert + # semester.delete() return redirect("staff:index") diff --git a/evap/static/scss/_components.scss b/evap/static/scss/_components.scss index 9fc73c5d1..1ff81aa9e 100644 --- a/evap/static/scss/_components.scss +++ b/evap/static/scss/_components.scss @@ -17,6 +17,7 @@ @import "components/modal"; @import "components/tooltip"; +@import "components/confirmation-modal"; @import "components/distribution-bar"; @import "components/quick-review"; @import "components/notebook"; diff --git a/evap/static/scss/components/_confirmation-modal.scss b/evap/static/scss/components/_confirmation-modal.scss new file mode 100644 index 000000000..593828e13 --- /dev/null +++ b/evap/static/scss/components/_confirmation-modal.scss @@ -0,0 +1,77 @@ +confirmation-modal:not(:defined) > :not([slot="submit-group"]) { + // Without this, the elements that are slotted into the dialog element show up as if they are just normal child + // elements and disappear once the custom element registration is done. To avoid a short flicker of these elements, + // we hide them until the constructor of the custom element has run. + display: none; +} + +dialog.evap-modal-dialog { + padding: 0; + border: 1px solid $dark-gray; + border-radius: 0.5rem; + z-index: 1050; + inset-block-start: -70vh; + + font-weight: initial; + line-height: initial; + + // https://youtu.be/4prVdA7_6u0 + &[open] { + animation: modal-enter 300ms forwards; + } + + &[closing] { + display: block; + pointer-events: none; + animation: modal-exit 300ms forwards; + } + + @keyframes modal-enter { + from { + transform: translateY(-100%); + opacity: 0; + } + to { + transform: translateY(0%); + opacity: 1; + } + } + + @keyframes modal-exit { + from { + transform: translateY(0%); + opacity: 1; + } + to { + transform: translateY(-100%); + opacity: 0; + } + } + + &::backdrop { + background-color: black; + opacity: 50%; + } + + .evap-modal-container { + > * { + padding: 1rem; + } + + > :not(:first-child) { + border-top: 1px solid $light-gray; + } + + header { + display: flex; + flex-direction: row; + justify-content: space-between; + } + + .button-area { + display: flex; + flex-flow: wrap; + justify-content: center; + } + } +} diff --git a/evap/static/ts/src/confirmation-modal.ts b/evap/static/ts/src/confirmation-modal.ts new file mode 100644 index 000000000..29c2d0d6e --- /dev/null +++ b/evap/static/ts/src/confirmation-modal.ts @@ -0,0 +1,62 @@ +import { selectOrError } from "./utils.js"; + +export class ConfirmationModal extends HTMLElement { + static formAssociated = true; + + readonly dialog: HTMLDialogElement; + readonly dialogForm: HTMLFormElement; + readonly type: string; + readonly internals: ElementInternals; + + constructor() { + super(); + + const template = selectOrError("#confirmation-modal-template").content; + const shadowRoot = this.attachShadow({ mode: "open" }); + shadowRoot.appendChild(template.cloneNode(true)); + + this.type = this.getAttribute("type") ?? "button"; + this.internals = this.attachInternals(); + + this.dialog = selectOrError("dialog", shadowRoot); + this.dialogForm = selectOrError("form[method=dialog]", this.dialog); + + const confirmButton = selectOrError("[data-event-type=confirm]", this.dialog); + const confirmButtonExtraClass = this.getAttribute("confirm-button-class") ?? "btn-primary"; + confirmButton.className += " " + confirmButtonExtraClass; + + selectOrError("[slot=show-button]", this).addEventListener("click", () => this.dialog.showModal()); + this.dialogForm.addEventListener("submit", this.onDialogFormSubmit); + } + + onDialogFormSubmit = (event: SubmitEvent) => { + event.preventDefault(); + + this.closeDialogSlowly(); + + if (event.submitter?.dataset?.eventType === "confirm") { + this.dispatchEvent(new CustomEvent("confirmed", { detail: new FormData(this.dialogForm) })); + + if (this.type === "submit") { + // Unfortunately, `this` cannot act as the submitter of the form. Instead, we make our `value` attribute + // visible to the form until submission is finished (the `submit` handlers of the form might cancel the + // submission again, which is why we hide reset the visible value again afterwards). + this.internals.setFormValue(this.getAttribute("value")); + this.internals.form?.requestSubmit(); + this.internals.setFormValue(null); + } + } + }; + + closeDialogSlowly = () => { + this.dialog.addEventListener( + "animationend", + () => { + this.dialog.removeAttribute("closing"); + this.dialog.close(); + }, + { once: true } + ); + this.dialog.setAttribute("closing", ""); + }; +} diff --git a/evap/static/ts/src/utils.ts b/evap/static/ts/src/utils.ts index 9a9f61b2a..2289db21f 100644 --- a/evap/static/ts/src/utils.ts +++ b/evap/static/ts/src/utils.ts @@ -1,4 +1,4 @@ -export const selectOrError = (selector: string, root: Element | Document = document): T => { +export const selectOrError = (selector: string, root: ParentNode = document): T => { const elem = root.querySelector(selector); assert(elem, `Element with selector ${selector} not found`); return elem; From 37e8a9dfbeea3b1bfeca41ddd541cd54f5f818c3 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 19:24:41 +0100 Subject: [PATCH 02/74] grade semester view --- evap/grades/templates/grades_semester_view.html | 11 ++++++----- evap/grades/views.py | 2 +- evap/static/scss/_utilities.scss | 4 ++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/evap/grades/templates/grades_semester_view.html b/evap/grades/templates/grades_semester_view.html index 7e50dd199..2e823852b 100644 --- a/evap/grades/templates/grades_semester_view.html +++ b/evap/grades/templates/grades_semester_view.html @@ -64,11 +64,11 @@

{% if num_final_grades > 0 %} {{ num_final_grades }} {% elif course.gets_no_grade_documents %} -
- {{ csrf_token }} + + {% csrf_token %} - + {% trans 'Will final grades be uploaded?' %} {% trans 'Confirm' %} @@ -87,9 +87,10 @@

{% if not course.gets_no_grade_documents %} {% if num_final_grades == 0 %} - - {{ csrf_token }} + + {% csrf_token %} + {% trans 'Have final grades been submitted?' %} {% trans 'Confirm' %} diff --git a/evap/grades/views.py b/evap/grades/views.py index 88d779df9..dc9d0869f 100644 --- a/evap/grades/views.py +++ b/evap/grades/views.py @@ -165,7 +165,7 @@ def set_no_grades(request): if course.gets_no_grade_documents: on_grading_process_finished(course) - return HttpResponse() # 200 OK + return redirect("grades:semester_view", course.semester.id) @require_GET diff --git a/evap/static/scss/_utilities.scss b/evap/static/scss/_utilities.scss index dd91f2ce3..2650a8688 100644 --- a/evap/static/scss/_utilities.scss +++ b/evap/static/scss/_utilities.scss @@ -53,6 +53,10 @@ a.no-underline:hover { } } +.d-contents { + display: contents !important; +} + .fa-fw-absolute { text-align: center; width: #{20rem / 16}; From fb7c93a12275b267857460b8b9926234344615d9 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 19:38:51 +0100 Subject: [PATCH 03/74] semester import --- .../templates/staff_semester_import.html | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/evap/staff/templates/staff_semester_import.html b/evap/staff/templates/staff_semester_import.html index c1d3b4ed2..8faecc1a2 100644 --- a/evap/staff/templates/staff_semester_import.html +++ b/evap/staff/templates/staff_semester_import.html @@ -34,34 +34,19 @@

{% trans 'Import semester data' %}

{% else %} - + + {% trans 'Import semester data' %} + {% trans 'Import semester data' %} + {% trans 'Do you really want to import semester data from the Excel file?' %} + + + {% endif %} {% endblock %} -{% block modals %} -{{ block.super }} - {% trans 'Import semester data' as title %} - {% trans 'Do you really want to import semester data from the Excel file?' as question %} - {% trans 'Import semester data' as action_text %} - {% include 'confirmation_modal.html' with modal_id='importSemesterModal' title=title question=question action_text=action_text btn_type='primary' %} - - -{% endblock %} - {% block additional_javascript %} {% include 'bootstrap_datetimepicker.html' %} From 9c188d538571ec99c02246f75aef5cffbdcb28be Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 19:48:57 +0100 Subject: [PATCH 04/74] semester preparation reminder --- .../staff_semester_preparation_reminder.html | 38 +++++++------------ evap/staff/views.py | 2 +- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/evap/staff/templates/staff_semester_preparation_reminder.html b/evap/staff/templates/staff_semester_preparation_reminder.html index 053ec9303..14fb70c92 100644 --- a/evap/staff/templates/staff_semester_preparation_reminder.html +++ b/evap/staff/templates/staff_semester_preparation_reminder.html @@ -13,7 +13,20 @@ {% if responsible_list %}
- + +
+ {% csrf_token %} + + + + + {% trans 'Remind all' %} + {% trans 'Import semester data' %} + {% trans 'Do you really want to remind everyone?' %} + + + +
{% endif %} @@ -69,26 +82,3 @@ {% endfor %} {% endblock %} - -{% block modals %} - {{ block.super }} - {% trans 'Remind all' as title %} - {% trans 'Do you really want to remind everyone?' as question %} - {% trans 'Remind all' as action_text %} - {% include 'confirmation_modal.html' with modal_id='remindAllModal' title=title question=question action_text=action_text btn_type='primary' %} - -{% endblock %} diff --git a/evap/staff/views.py b/evap/staff/views.py index b2a4c1496..14df8fec7 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -900,7 +900,7 @@ def semester_preparation_reminder(request, semester_id): body_params = {"user": responsible, "evaluations": evaluations} template.send_to_user(responsible, subject_params, body_params, use_cc=True, request=request) messages.success(request, _("Successfully sent reminders to everyone.")) - return HttpResponse() + return redirect("staff:semester_preparation_reminder", semester.id) template_data = {"semester": semester, "responsible_list": responsible_list} return render(request, "staff_semester_preparation_reminder.html", template_data) From 407a55cc201ced1fdb0915e9f5c6de69df72f58a Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 19:51:24 +0100 Subject: [PATCH 05/74] format --- evap/static/ts/src/confirmation-modal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evap/static/ts/src/confirmation-modal.ts b/evap/static/ts/src/confirmation-modal.ts index 29c2d0d6e..f65609dfe 100644 --- a/evap/static/ts/src/confirmation-modal.ts +++ b/evap/static/ts/src/confirmation-modal.ts @@ -55,7 +55,7 @@ export class ConfirmationModal extends HTMLElement { this.dialog.removeAttribute("closing"); this.dialog.close(); }, - { once: true } + { once: true }, ); this.dialog.setAttribute("closing", ""); }; From 4c1d3c6e7fcf1f33288ef88013c7afeab5f89cfc Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 20:53:17 +0100 Subject: [PATCH 06/74] delete semesters --- evap/staff/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/evap/staff/views.py b/evap/staff/views.py index 14df8fec7..e1747b5d0 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -635,8 +635,7 @@ def semester_delete(request): Contribution.objects.filter(evaluation__course__semester=semester).delete() Evaluation.objects.filter(course__semester=semester).delete() Course.objects.filter(semester=semester).delete() - # TODO: revert - # semester.delete() + semester.delete() return redirect("staff:index") From 0218b57f21d54f3395a8556d861da71be8cbab1c Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 20:53:43 +0100 Subject: [PATCH 07/74] add `submit_with_modal` --- evap/contributor/tests/test_views.py | 4 ++-- evap/evaluation/tests/tools.py | 8 ++++++++ evap/staff/tests/test_views.py | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/evap/contributor/tests/test_views.py b/evap/contributor/tests/test_views.py index 970c7ee10..545ce6b1e 100644 --- a/evap/contributor/tests/test_views.py +++ b/evap/contributor/tests/test_views.py @@ -5,7 +5,7 @@ from model_bakery import baker from evap.evaluation.models import Contribution, Course, Evaluation, Questionnaire, UserProfile -from evap.evaluation.tests.tools import WebTestWith200Check, create_evaluation_with_responsible_and_editor, render_pages +from evap.evaluation.tests.tools import WebTestWith200Check, create_evaluation_with_responsible_and_editor, render_pages, submit_with_modal class TestContributorDirectDelegationView(WebTest): @@ -197,7 +197,7 @@ def test_contributor_evaluation_edit(self): self.evaluation = Evaluation.objects.get(pk=self.evaluation.pk) self.assertEqual(self.evaluation.state, Evaluation.State.PREPARED) - form.submit(name="operation", value="approve") + submit_with_modal(page, "evaluation-form", name="operation", value="approve") self.evaluation = Evaluation.objects.get(pk=self.evaluation.pk) self.assertEqual(self.evaluation.state, Evaluation.State.EDITOR_APPROVED) diff --git a/evap/evaluation/tests/tools.py b/evap/evaluation/tests/tools.py index 55a60127e..8dd6577cb 100644 --- a/evap/evaluation/tests/tools.py +++ b/evap/evaluation/tests/tools.py @@ -4,6 +4,7 @@ from contextlib import contextmanager from datetime import timedelta +import webtest from django.conf import settings from django.contrib.auth.models import Group from django.db import DEFAULT_DB_ALIAS, connections @@ -124,6 +125,13 @@ def test_check_response_code_200(self): for user in self.test_users: self.app.get(self.url, user=user, status=200) +def submit_with_modal(page: webtest.TestResponse, form_id: str, *, name: str, value: str) -> webtest.TestResponse: + # Like form.submit, but looks for a modal instead of a submit button. + assert page.html.select_one(f"confirmation-modal[type=submit][name={name}][value={value}]") + form = page.forms[form_id] + params = form.submit_fields() + [(name, value)] + return form.response.goto(form.action, method=form.method, params=params) + def get_form_data_from_instance(form_cls, instance, **kwargs): assert form_cls._meta.model == type(instance) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 8e00308a4..77b9f49d5 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -954,7 +954,7 @@ def test_remind_all(self, email_template_mock): email_template_mock.objects.get.return_value = email_template_mock email_template_mock.EDITOR_REVIEW_REMINDER = EmailTemplate.EDITOR_REVIEW_REMINDER - self.app.post(self.url, user=self.manager, status=200) + self.app.post(self.url, user=self.manager).follow(status=200) subject_params = {} body_params = {"user": user, "evaluations": [evaluation]} From 64650ccbdec274b9ef06989c78ece149e42445f0 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 21:03:42 +0100 Subject: [PATCH 08/74] another test --- evap/contributor/tests/test_views.py | 2 +- evap/evaluation/tests/test_misc.py | 4 ++-- evap/evaluation/tests/tools.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/evap/contributor/tests/test_views.py b/evap/contributor/tests/test_views.py index 545ce6b1e..b694a6529 100644 --- a/evap/contributor/tests/test_views.py +++ b/evap/contributor/tests/test_views.py @@ -197,7 +197,7 @@ def test_contributor_evaluation_edit(self): self.evaluation = Evaluation.objects.get(pk=self.evaluation.pk) self.assertEqual(self.evaluation.state, Evaluation.State.PREPARED) - submit_with_modal(page, "evaluation-form", name="operation", value="approve") + submit_with_modal(page, form, name="operation", value="approve") self.evaluation = Evaluation.objects.get(pk=self.evaluation.pk) self.assertEqual(self.evaluation.state, Evaluation.State.EDITOR_APPROVED) diff --git a/evap/evaluation/tests/test_misc.py b/evap/evaluation/tests/test_misc.py index 56f1dd077..2a9310cef 100644 --- a/evap/evaluation/tests/test_misc.py +++ b/evap/evaluation/tests/test_misc.py @@ -9,7 +9,7 @@ from model_bakery import baker from evap.evaluation.models import CourseType, Degree, Semester, UserProfile -from evap.evaluation.tests.tools import make_manager +from evap.evaluation.tests.tools import make_manager, submit_with_modal from evap.staff.tests.utils import WebTestStaffMode @@ -36,7 +36,7 @@ def test_sample_semester_file(self): form = page.forms["semester-import-form"] form["vote_start_datetime"] = "2015-01-01 11:11:11" form["vote_end_date"] = "2099-01-01" - form.submit(name="operation", value="import") + submit_with_modal(page, form, name="operation", value="import") self.assertEqual(UserProfile.objects.count(), original_user_count + 4) diff --git a/evap/evaluation/tests/tools.py b/evap/evaluation/tests/tools.py index 8dd6577cb..3d007bf91 100644 --- a/evap/evaluation/tests/tools.py +++ b/evap/evaluation/tests/tools.py @@ -125,10 +125,10 @@ def test_check_response_code_200(self): for user in self.test_users: self.app.get(self.url, user=user, status=200) -def submit_with_modal(page: webtest.TestResponse, form_id: str, *, name: str, value: str) -> webtest.TestResponse: +def submit_with_modal(page: webtest.TestResponse, form: webtest.Form, *, name: str, value: str) -> webtest.TestResponse: # Like form.submit, but looks for a modal instead of a submit button. + assert page.forms[form.id] == form assert page.html.select_one(f"confirmation-modal[type=submit][name={name}][value={value}]") - form = page.forms[form_id] params = form.submit_fields() + [(name, value)] return form.response.goto(form.action, method=form.method, params=params) From 0cea99860bc48e77ee66df02662375d45136b7b8 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 21:07:40 +0100 Subject: [PATCH 09/74] another test --- evap/staff/tests/test_views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 77b9f49d5..26bb32e58 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -42,6 +42,7 @@ assert_no_database_modifications, create_evaluation_with_responsible_and_editor, let_user_vote_for_evaluation, + submit_with_modal, make_manager, make_rating_answer_counters, render_pages, @@ -1067,7 +1068,7 @@ def test_import_valid_file(self): form = page.forms["semester-import-form"] form["vote_start_datetime"] = "2000-01-01 00:00:00" form["vote_end_date"] = "2012-01-01" - form.submit(name="operation", value="import") + submit_with_modal(page, form, name="operation", value="import") self.assertEqual(UserProfile.objects.count(), original_user_count + 23) From b1c9c6be238b2d671fb95a55bd41953cd2da482c Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 21:11:31 +0100 Subject: [PATCH 10/74] another test --- evap/staff/tests/test_views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 26bb32e58..46fb6e45e 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -1217,8 +1217,7 @@ def test_missing_evaluation_period(self): ) page = form.submit(name="operation", value="test") - form = page.forms["semester-import-form"] - page = form.submit(name="operation", value="import") + page = submit_with_modal(page, page.forms["semester-import-form"], name="operation", value="import") self.assertContains(page, "This field is required.") self.assertContains(page, "Import previously uploaded file") From b9e2f2b80559c5871ee3813a99d50bebae539529 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 21:13:12 +0100 Subject: [PATCH 11/74] another test --- evap/grades/tests.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/evap/grades/tests.py b/evap/grades/tests.py index 1e02bfc27..1864caf0c 100644 --- a/evap/grades/tests.py +++ b/evap/grades/tests.py @@ -149,8 +149,7 @@ def test_set_no_grades(self): "/grades/set_no_grades", params={"course_id": evaluation.course.id, "status": "1"}, user=self.grade_publisher, - status=200, - ) + ).follow(status=200) evaluation = Evaluation.objects.get(id=evaluation.id) self.assertTrue(evaluation.course.gets_no_grade_documents) # evaluation should get published here @@ -163,8 +162,7 @@ def test_set_no_grades(self): "/grades/set_no_grades", params={"course_id": evaluation.course.id, "status": "0"}, user=self.grade_publisher, - status=200, - ) + ).follow(status=200) evaluation = Evaluation.objects.get(id=evaluation.id) self.assertFalse(evaluation.course.gets_no_grade_documents) @@ -172,8 +170,7 @@ def test_set_no_grades(self): "/grades/set_no_grades", params={"course_id": evaluation.course.id, "status": "0"}, user=self.grade_publisher, - status=200, - ) + ).follow(status=200) evaluation = Evaluation.objects.get(id=evaluation.id) self.assertFalse(evaluation.course.gets_no_grade_documents) From 615c825c3180c5e5ebe29622991ede6475a03f26 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 20 Nov 2023 21:20:07 +0100 Subject: [PATCH 12/74] formatting, linting --- evap/contributor/tests/test_views.py | 7 ++++++- evap/evaluation/tests/tools.py | 1 + evap/staff/tests/test_views.py | 2 +- pyproject.toml | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/evap/contributor/tests/test_views.py b/evap/contributor/tests/test_views.py index b694a6529..4bce3f1ba 100644 --- a/evap/contributor/tests/test_views.py +++ b/evap/contributor/tests/test_views.py @@ -5,7 +5,12 @@ from model_bakery import baker from evap.evaluation.models import Contribution, Course, Evaluation, Questionnaire, UserProfile -from evap.evaluation.tests.tools import WebTestWith200Check, create_evaluation_with_responsible_and_editor, render_pages, submit_with_modal +from evap.evaluation.tests.tools import ( + WebTestWith200Check, + create_evaluation_with_responsible_and_editor, + render_pages, + submit_with_modal, +) class TestContributorDirectDelegationView(WebTest): diff --git a/evap/evaluation/tests/tools.py b/evap/evaluation/tests/tools.py index 3d007bf91..c1a07d5a5 100644 --- a/evap/evaluation/tests/tools.py +++ b/evap/evaluation/tests/tools.py @@ -125,6 +125,7 @@ def test_check_response_code_200(self): for user in self.test_users: self.app.get(self.url, user=user, status=200) + def submit_with_modal(page: webtest.TestResponse, form: webtest.Form, *, name: str, value: str) -> webtest.TestResponse: # Like form.submit, but looks for a modal instead of a submit button. assert page.forms[form.id] == form diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 46fb6e45e..3b6705a54 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -42,10 +42,10 @@ assert_no_database_modifications, create_evaluation_with_responsible_and_editor, let_user_vote_for_evaluation, - submit_with_modal, make_manager, make_rating_answer_counters, render_pages, + submit_with_modal, ) from evap.grades.models import GradeDocument from evap.results.tools import TextResult, cache_results, get_results diff --git a/pyproject.toml b/pyproject.toml index 137717643..0e9299396 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,6 +97,7 @@ module = [ "debug_toolbar.*", "mozilla_django_oidc.*", "model_bakery.*", + "webtest.*", "xlrd.*", "xlwt.*", From e379b5d3a0f00c514c1fa0c45d28fbec133dbd37 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 20:10:56 +0100 Subject: [PATCH 13/74] User delete modal --- evap/staff/templates/staff_user_form.html | 37 +++++++++++------------ evap/staff/views.py | 2 +- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/evap/staff/templates/staff_user_form.html b/evap/staff/templates/staff_user_form.html index e0df5146d..84b92586e 100644 --- a/evap/staff/templates/staff_user_form.html +++ b/evap/staff/templates/staff_user_form.html @@ -103,9 +103,24 @@
{% trans 'Export evaluation results' %}
{% if form.instance and form.instance.can_be_deleted_by_manager %} - + + +
+ {% csrf_token %} + + + {% trans 'Delete user' %} + {% trans 'Delete user' %} + + {% blocktrans with user_fullname=form.instance.full_name %} + Do you really want to delete the user {{ user_fullname }}?
+ This person will also be removed from every other user having this person as a delegated or CC-user. + {% endblocktrans %} +
+ + +
+
{% else %} +
+ {% csrf_token %} + + + {% trans 'Send notification email' %} + {% trans 'Send email' %} + + {% blocktrans %} + The email will notify the user about all their due evaluations. Do you want to send the email now? + {% endblocktrans %} + + + + +
{% else %}
@@ -135,21 +149,5 @@
{% trans 'Export evaluation results' %}
{% block modals %} {{ block.super }} {% if form.instance.id %} - {% trans 'Send notification email' as title %} - {% trans 'The email will notify the user about all their due evaluations. Do you want to send the email now?' as question %} - {% trans 'Send email' as action_text %} - {% include 'confirmation_modal.html' with modal_id='resendEmailModal' title=title question=question action_text=action_text btn_type='success' %} - {% endif %} {% endblock %} diff --git a/evap/staff/views.py b/evap/staff/views.py index ed987b223..e7202118e 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -2258,7 +2258,7 @@ def user_resend_email(request): template.send_to_user(user, {}, body_params, use_cc=False) messages.success(request, _("Successfully resent evaluation started email.")) - return HttpResponse() # 200 OK + return redirect("staff:user_edit", user.pk) @manager_required From f706eab9f0ade08cf882c3d60cbed409dda226ca Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 21:34:14 +0100 Subject: [PATCH 15/74] reward event deletion --- ...ds_reward_point_redemption_event_list.html | 42 ++++++++++++++++--- ...ewards_reward_point_redemption_events.html | 21 ---------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/evap/rewards/templates/rewards_reward_point_redemption_event_list.html b/evap/rewards/templates/rewards_reward_point_redemption_event_list.html index 3648befac..bcaec789e 100644 --- a/evap/rewards/templates/rewards_reward_point_redemption_event_list.html +++ b/evap/rewards/templates/rewards_reward_point_redemption_event_list.html @@ -3,6 +3,28 @@
{% if events %} +
+ {% csrf_token %} +
+ + + @@ -19,14 +41,24 @@ - + - {% for questionnaire in questionnaires %} - - - - + + + + - - - - {% endfor %} + + + + {% endfor %}
{{ event.date }} {{ event.redeem_end_date }} {{ event.name }} {{ event.redemptions_by_user|length }} - + {{ event.redemptions_by_user|length }} {% if event.can_delete %} - + + {% trans 'Delete event' %} + {% trans 'Delete event' %} + + {% blocktrans with event_name=event.name %} + Do you really want to delete the event {{ event_name }}? + {% endblocktrans %} + + + + {% else %}
- {{ questionnaire.name }} -
- {% blocktrans count questionnaire.questions.count as count %}{{ count }} question{% plural %}{{ count }} questions{% endblocktrans %}, - {% blocktrans count questionnaire.contributions.count as count %}used {{ count }} time{% plural %}used {{ count }} times{% endblocktrans %} -
- {% if type != 'contributor' %} -
- - + {% for questionnaire in questionnaires %} +
+ {{ questionnaire.name }} +
+ {% blocktrans count questionnaire.questions.count as count %}{{ count }} question{% plural %}{{ count }} questions{% endblocktrans %}, + {% blocktrans count questionnaire.contributions.count as count %}used {{ count }} time{% plural %}used {{ count }} times{% endblocktrans %} +
+ {% if type != 'contributor' %} +
+ + +
+ {% endif %} +
+
+ + +
- {% endif %} -
-
- - - -
-
- - - - - {% if questionnaire.can_be_deleted_by_manager %} - - {% else %} - - {% endif %} -
+ + + + + {% if questionnaire.can_be_deleted_by_manager %} + + {% else %} + + {% endif %} +
From d4d5921a6a13a9d4743118340d67d14f6032289c Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 21:48:16 +0100 Subject: [PATCH 18/74] questionnaire deletion modal --- .../templates/staff_questionnaire_index.html | 43 ++++++++++--------- .../staff_questionnaire_index_list.html | 16 +++++-- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/evap/staff/templates/staff_questionnaire_index.html b/evap/staff/templates/staff_questionnaire_index.html index 8a83c0065..e3f76c1ea 100644 --- a/evap/staff/templates/staff_questionnaire_index.html +++ b/evap/staff/templates/staff_questionnaire_index.html @@ -32,6 +32,29 @@ {% if general_questionnaires_top or general_questionnaires_bottom or contributor_questionnaires %} +
+ {% csrf_token %} +
+ + + + {% trans 'Top general questionnaires' as headline %} {% include 'staff_questionnaire_index_list.html' with questionnaires=general_questionnaires_top headline=headline extra_classes='mb-3' type='top' %} {% trans 'Contributor questionnaires' as headline %} @@ -45,26 +68,6 @@ {% endif %} {% endblock %} -{% block modals %} - {{ block.super }} - {% trans 'Delete questionnaire' as title %} - {% trans 'Do you really want to delete the questionnaire ?' as question %} - {% trans 'Delete questionnaire' as action_text %} - {% include 'confirmation_modal.html' with modal_id='deleteQuestionnaireModal' title=title question=question action_text=action_text btn_type='danger' %} - -{% endblock %} - {% block additional_javascript %} - diff --git a/evap/rewards/templates/rewards_reward_point_redemption_events.html b/evap/rewards/templates/rewards_reward_point_redemption_events.html index 64b99a0d7..a4cac262e 100644 --- a/evap/rewards/templates/rewards_reward_point_redemption_events.html +++ b/evap/rewards/templates/rewards_reward_point_redemption_events.html @@ -16,6 +16,28 @@ + + {% csrf_token %} + + + +
{% trans 'Upcoming events' as title %} {% include 'rewards_reward_point_redemption_event_list.html' with title=title events=upcoming_events %} From 3090a9282727d0ae902f61c73bb9ead87050205d Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 22:05:31 +0100 Subject: [PATCH 20/74] import participants modal --- .../staff_evaluation_person_management.html | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index 55ad0ab6d..b827d50d4 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -28,7 +28,18 @@
{% trans 'From Excel file' %}
{% else %}
- + + {% trans 'Import participants' %} + {% trans 'Import participants' %} + + {% blocktrans %} + Do you really want to import the Excel file with participant data? + {% endblocktrans %} + + + + +
{% endif %} @@ -130,23 +141,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Import participants' as title %} - {% blocktrans asvar question %}Do you really want to import the Excel file with participant data?{% endblocktrans %} - {% trans 'Import participants' as action_text %} - {% include 'confirmation_modal.html' with modal_id='importParticipantsModal' title=title question=question action_text=action_text btn_type='primary' %} - - {% trans 'Replace participants' as title %} {% blocktrans asvar question %}Do you really want to delete all existing participants and replace them with participant data from the Excel file?{% endblocktrans %} {% trans 'Replace participants' as action_text %} From 1b454e3313554dd0b2d08061adde6aefb32404c4 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 22:07:55 +0100 Subject: [PATCH 21/74] import replace participants modal --- .../staff_evaluation_person_management.html | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index b827d50d4..25613a9e5 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -40,7 +40,17 @@
{% trans 'From Excel file' %}
- + + {% trans 'Replace participants' %} + {% trans 'Replace participants' %} + + {% blocktrans %} + Do you really want to delete all existing participants and replace them with participant data from the Excel file? + {% endblocktrans %} + + + +
{% endif %} @@ -141,23 +151,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Replace participants' as title %} - {% blocktrans asvar question %}Do you really want to delete all existing participants and replace them with participant data from the Excel file?{% endblocktrans %} - {% trans 'Replace participants' as action_text %} - {% include 'confirmation_modal.html' with modal_id='replaceParticipantsModal' title=title question=question action_text=action_text btn_type='danger' %} - - {% trans 'Copy participants' as title %} {% blocktrans asvar question %}Do you really want to copy the participants?{% endblocktrans %} {% trans 'Copy participants' as action_text %} From c6dc60f84a1bce67cc5a3267142893ad87abd654 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 22:38:16 +0100 Subject: [PATCH 22/74] remove duplicated button in user import --- evap/staff/templates/staff_user_import.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/evap/staff/templates/staff_user_import.html b/evap/staff/templates/staff_user_import.html index 6593fd135..c93551e97 100644 --- a/evap/staff/templates/staff_user_import.html +++ b/evap/staff/templates/staff_user_import.html @@ -33,8 +33,6 @@

{% trans 'Import users' %}

{% else %} - - {% trans 'Import Users' %} {% trans 'Import Users' %} @@ -44,7 +42,7 @@

{% trans 'Import users' %}

{% endblocktrans %} - +
{% endif %} From a9b1633a709f2956393d77895c41ab1b12a9bbdd Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 11 Dec 2023 22:55:27 +0100 Subject: [PATCH 23/74] fix tests --- evap/evaluation/tests/test_misc.py | 2 +- evap/staff/tests/test_views.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/evap/evaluation/tests/test_misc.py b/evap/evaluation/tests/test_misc.py index 2a9310cef..c042df7df 100644 --- a/evap/evaluation/tests/test_misc.py +++ b/evap/evaluation/tests/test_misc.py @@ -50,7 +50,7 @@ def test_sample_user_file(self): page = form.submit(name="operation", value="test") form = page.forms["user-import-form"] - form.submit(name="operation", value="import") + submit_with_modal(page, form, name="operation", value="import") self.assertEqual(UserProfile.objects.count(), original_user_count + 2) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 3b6705a54..1782e702b 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -606,7 +606,7 @@ def test_success_handling(self): self.assertContains(page, "Import previously uploaded file") form = page.forms["user-import-form"] - form.submit(name="operation", value="import") + submit_with_modal(page, form, name="operation", value="import") page = self.app.get(self.url, user=self.manager) self.assertNotContains(page, "Import previously uploaded file") @@ -2326,7 +2326,7 @@ def test_import_valid_participants_file(self): self.assertEqual(self.evaluation.participants.count(), original_participant_count) form = page.forms["participant-import-form"] - form.submit(name="operation", value="import-participants") + submit_with_modal(page, form, name="operation", value="import-participants") self.assertEqual(self.evaluation.participants.count(), original_participant_count + 2) page = self.app.get(self.url, user=self.manager) @@ -2342,7 +2342,7 @@ def test_replace_valid_participants_file(self): self.assertNotEqual(self.evaluation2.participants.count(), 2) form = page.forms["participant-import-form"] - form.submit(name="operation", value="import-replace-participants") + submit_with_modal(page, form, name="operation", value="import-replace-participants") self.assertEqual(self.evaluation2.participants.count(), 2) page = self.app.get(self.url2, user=self.manager) From e0207745f0cd1408942e2b9486b5538757d96717 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 17:39:45 +0100 Subject: [PATCH 24/74] copy participants modal --- .../staff_evaluation_person_management.html | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index 25613a9e5..db077be7b 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -68,7 +68,17 @@
{% trans 'From other evaluation' %} @@ -151,23 +161,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Copy participants' as title %} - {% blocktrans asvar question %}Do you really want to copy the participants?{% endblocktrans %} - {% trans 'Copy participants' as action_text %} - {% include 'confirmation_modal.html' with modal_id='copyParticipantsModal' title=title question=question action_text=action_text btn_type='primary' %} - - {% trans 'Replace participants' as title %} {% blocktrans asvar question %}Do you really want to delete all existing participants and copy the participants into the evaluation?{% endblocktrans %} {% trans 'Replace participants' as action_text %} From aa46f6dba46783e189b815afe3e633e939201980 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 17:51:19 +0100 Subject: [PATCH 25/74] copy replace participants --- .../staff_evaluation_person_management.html | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index db077be7b..29f0d0403 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -79,7 +79,17 @@
{% trans 'From other evaluation' %}{% trans 'Copy participants' %} - + + {% trans 'Replace participants' %} + {% trans 'Replace participants' %} + + {% blocktrans %} + Do you really want to delete all existing participants and copy the participants into the evaluation? + {% endblocktrans %} + + + + @@ -161,23 +171,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Replace participants' as title %} - {% blocktrans asvar question %}Do you really want to delete all existing participants and copy the participants into the evaluation?{% endblocktrans %} - {% trans 'Replace participants' as action_text %} - {% include 'confirmation_modal.html' with modal_id='copyReplaceParticipantsModal' title=title question=question action_text=action_text btn_type='danger' %} - - {% trans 'Import contributors' as title %} {% blocktrans asvar question %}Do you really want to import the Excel file with contributor data?{% endblocktrans %} {% trans 'Import contributors' as action_text %} From a58fd38b238d9de017d9999926017bcdbcace788 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 18:30:27 +0100 Subject: [PATCH 26/74] import contributors modal --- .../staff_evaluation_person_management.html | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index 29f0d0403..96dac3546 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -118,7 +118,17 @@
{% trans 'From Excel file' %}
{% else %}
- + + {% trans 'Import contributors' %} + {% trans 'Import contributors' %} + + {% blocktrans %} + Do you really want to import the Excel file with contributor data? + {% endblocktrans %} + + + +
{% endif %} @@ -171,23 +181,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Import contributors' as title %} - {% blocktrans asvar question %}Do you really want to import the Excel file with contributor data?{% endblocktrans %} - {% trans 'Import contributors' as action_text %} - {% include 'confirmation_modal.html' with modal_id='importContributorsModal' title=title question=question action_text=action_text btn_type='primary' %} - - {% trans 'Replace contributors' as title %} {% blocktrans asvar question %}Do you really want to delete all existing contributors and replace them with contributor data from the Excel file?{% endblocktrans %} {% trans 'Replace contributors' as action_text %} From 03d58666054f60823eaea1f30d64ce6e90084690 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 18:34:21 +0100 Subject: [PATCH 27/74] import replace contributors modal --- .../staff_evaluation_person_management.html | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index 96dac3546..3c316d485 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -129,7 +129,17 @@
{% trans 'From Excel file' %}
- + + {% trans 'Replace contributors' %} + {% trans 'Replace contributors' %} + + {% blocktrans %} + Do you really want to delete all existing contributors and replace them with contributor data from the Excel file? + {% endblocktrans %} + + + + {% endif %} @@ -181,23 +191,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Replace contributors' as title %} - {% blocktrans asvar question %}Do you really want to delete all existing contributors and replace them with contributor data from the Excel file?{% endblocktrans %} - {% trans 'Replace contributors' as action_text %} - {% include 'confirmation_modal.html' with modal_id='replaceContributorsModal' title=title question=question action_text=action_text btn_type='danger' %} - - {% trans 'Copy contributors' as title %} {% blocktrans asvar question %}Do you really want to copy the contributors?{% endblocktrans %} {% trans 'Copy contributors' as action_text %} From fd1717b6b1385776f9353254c3eed90633d20238 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 18:37:04 +0100 Subject: [PATCH 28/74] copy contributors modal --- .../staff_evaluation_person_management.html | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index 3c316d485..32fc2ccc7 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -157,7 +157,17 @@
{% trans 'From other evaluation' %} @@ -191,23 +201,6 @@
{% trans 'To CSV file' %}
{% block modals %} {{ block.super }} - {% trans 'Copy contributors' as title %} - {% blocktrans asvar question %}Do you really want to copy the contributors?{% endblocktrans %} - {% trans 'Copy contributors' as action_text %} - {% include 'confirmation_modal.html' with modal_id='copyContributorsModal' title=title question=question action_text=action_text btn_type='primary' %} - - {% trans 'Replace contributors' as title %} {% blocktrans asvar question %}Do you really want to delete all existing contributors and copy the contributors into the evaluation?{% endblocktrans %} {% trans 'Replace contributors' as action_text %} From 9b2a1e96f96260c44ac9a66b9668613acfc4d53a Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 18:39:52 +0100 Subject: [PATCH 29/74] copy replace contributor modal --- .../staff_evaluation_person_management.html | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/evap/staff/templates/staff_evaluation_person_management.html b/evap/staff/templates/staff_evaluation_person_management.html index 32fc2ccc7..00fe58e84 100644 --- a/evap/staff/templates/staff_evaluation_person_management.html +++ b/evap/staff/templates/staff_evaluation_person_management.html @@ -168,7 +168,17 @@
{% trans 'From other evaluation' %}{% trans 'Copy contributors' %} - + + {% trans 'Replace contributors' %} + {% trans 'Replace contributors' %} + + {% blocktrans %} + Do you really want to delete all existing contributors and copy the contributors into the evaluation? + {% endblocktrans %} + + + + @@ -199,27 +209,6 @@
{% trans 'To CSV file' %}
{% endblock %} -{% block modals %} -{{ block.super }} - {% trans 'Replace contributors' as title %} - {% blocktrans asvar question %}Do you really want to delete all existing contributors and copy the contributors into the evaluation?{% endblocktrans %} - {% trans 'Replace contributors' as action_text %} - {% include 'confirmation_modal.html' with modal_id='copyReplaceContributorsModal' title=title question=question action_text=action_text btn_type='danger' %} - - -{% endblock %} - {% block additional_javascript %} {% endblock %} From 2cf2f512f92398618d0ea4c04bffbda15be6779b Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 20:27:57 +0100 Subject: [PATCH 30/74] make semester active modal --- evap/staff/templates/staff_semester_view.html | 54 +++++++++---------- evap/staff/views.py | 2 +- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 0c506693a..609e68708 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -11,16 +11,30 @@

{{ semester.name }}

{% if request.user.is_manager %}   {% trans 'Edit' %} - +
+ {% csrf_token %} + + {% trans 'Make this the active semester' %} + {% trans 'Make active' %} + + {% blocktrans %} + Do you want to make this the active semester? + {% endblocktrans %} + + + + +
{% csrf_token %} @@ -505,26 +519,6 @@

{{ semester.name }}

{% block modals %} {{ block.super }} - {% trans 'Make this the active semester' as title %} - {% trans 'Do you want to make this the active semester?' as question %} - {% trans 'Make active' as action_text %} - {% include 'confirmation_modal.html' with modal_id='makeActiveSemesterModal' title=title question=question action_text=action_text btn_type='primary' %} - {% trans 'Archive participations' as title %} {% blocktrans asvar question %}Do you really want to archive all participations in the semester ? Further changes to the evaluations won't be possible and you can't undo this action.{% endblocktrans %} {% trans 'Archive participations' as action_text %} diff --git a/evap/staff/views.py b/evap/staff/views.py index e7202118e..692c4a5c2 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -619,7 +619,7 @@ def semester_make_active(request): semester.is_active = True semester.save() - return HttpResponse() + return redirect("staff:semester_view", semester.id) @require_POST From f5ff5848b82683e4d8754318e991f6e5409c24e6 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 20:41:55 +0100 Subject: [PATCH 31/74] archive participations modal --- evap/staff/templates/staff_semester_view.html | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 609e68708..ef17675c1 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -95,7 +95,21 @@

{{ semester.name }}

{% if semester.participations_can_be_archived %} - + + {% csrf_token %} + + {% trans 'Archive participations' %} + {% trans 'Archive participations' %} + + {% blocktrans with semster_name=semester.name %} + Do you really want to archive all participations in the semester {{ semester_name }}? + Further changes to the evaluations won't be possible and you can't undo this action. + {% endblocktrans %} + + + + + {% elif semester.participations_are_archived %} {% else %} @@ -519,22 +533,6 @@

{{ semester.name }}

{% block modals %} {{ block.super }} - {% trans 'Archive participations' as title %} - {% blocktrans asvar question %}Do you really want to archive all participations in the semester ? Further changes to the evaluations won't be possible and you can't undo this action.{% endblocktrans %} - {% trans 'Archive participations' as action_text %} - {% include 'confirmation_modal.html' with modal_id='archiveParticipationsModal' title=title question=question action_text=action_text btn_type='danger' %} - {% trans 'Delete grade documents' as title %} {% blocktrans asvar question %}Do you really want to delete the grade documents in the semester ? This will delete all existing grade documents for this semester's courses and will disable new uploads. You can't undo this action.{% endblocktrans %} {% trans 'Delete grade documents' as action_text %} From 639db547afa0c12bd40d92f9399e80aceaeebe37 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 20:48:48 +0100 Subject: [PATCH 32/74] fix tooltip (never shown on disabled elements) --- evap/staff/templates/staff_semester_view.html | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index ef17675c1..7bb2f77c3 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -13,7 +13,7 @@

{{ semester.name }}

{% trans 'Edit' %}
{% csrf_token %} - + {% trans 'Make this the active semester' %} {% trans 'Make active' %} @@ -24,13 +24,10 @@

{{ semester.name }}

From 38462864a4a4449170adacdf6b8c9eeed3346a37 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 20:51:27 +0100 Subject: [PATCH 33/74] delete grade documents modal --- evap/staff/templates/staff_semester_view.html | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 7bb2f77c3..824657952 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -115,7 +115,22 @@

{{ semester.name }}

{% trans 'Archive participations' %} {% endif %} {% if semester.grade_documents_can_be_deleted %} - + + {% csrf_token %} + + {% trans 'Delete grade documents' %} + {% trans 'Delete grade documents' %} + + {% blocktrans with semester_name=semester.name %} + Do you really want to delete the grade documents in the semester {{ semester_name }}? + This will delete all existing grade documents for this semester's courses and will disable new uploads. + You can't undo this action. + {% endblocktrans %} + + + + + {% elif semester.grade_documents_are_deleted %} {% endif %} @@ -530,22 +545,6 @@

{{ semester.name }}

{% block modals %} {{ block.super }} - {% trans 'Delete grade documents' as title %} - {% blocktrans asvar question %}Do you really want to delete the grade documents in the semester ? This will delete all existing grade documents for this semester's courses and will disable new uploads. You can't undo this action.{% endblocktrans %} - {% trans 'Delete grade documents' as action_text %} - {% include 'confirmation_modal.html' with modal_id='deleteGradeDocumentsModal' title=title question=question action_text=action_text btn_type='danger' %} - {% trans 'Archive results' as title %} {% blocktrans asvar question %}Do you really want to archive the results in the semester ? This will make the results of all evaluations inaccessible for all users except their contributors and managers. You can't undo this action.{% endblocktrans %} {% trans 'Archive results' as action_text %} From 8b37a93a51648a11e82d2c457dc4f81ca1d0ec25 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 20:51:40 +0100 Subject: [PATCH 34/74] fix typo --- evap/staff/templates/staff_semester_view.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 824657952..005baa971 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -98,7 +98,7 @@

{{ semester.name }}

{% trans 'Archive participations' %} {% trans 'Archive participations' %} - {% blocktrans with semster_name=semester.name %} + {% blocktrans with semester_name=semester.name %} Do you really want to archive all participations in the semester {{ semester_name }}? Further changes to the evaluations won't be possible and you can't undo this action. {% endblocktrans %} From 5005dab4677e531308eb0e4db47c72162dd82523 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 20:53:44 +0100 Subject: [PATCH 35/74] archive results modal --- evap/staff/templates/staff_semester_view.html | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 005baa971..d1057af5f 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -135,7 +135,22 @@

{{ semester.name }}

{% endif %} {% if semester.results_can_be_archived %} - +
+ {% csrf_token %} + + {% trans 'Archive results' %} + {% trans 'Archive results' %} + + {% blocktrans with semester_name=semester.name %} + Do you really want to archive the results in the semester {{ semester_name }}? + This will make the results of all evaluations inaccessible for all users except their contributors and managers. + You can't undo this action. + {% endblocktrans %} + + + + + {% elif semester.results_are_archived %} {% endif %} @@ -545,22 +560,6 @@

{{ semester.name }}

{% block modals %} {{ block.super }} - {% trans 'Archive results' as title %} - {% blocktrans asvar question %}Do you really want to archive the results in the semester ? This will make the results of all evaluations inaccessible for all users except their contributors and managers. You can't undo this action.{% endblocktrans %} - {% trans 'Archive results' as action_text %} - {% include 'confirmation_modal.html' with modal_id='archiveResultsModal' title=title question=question action_text=action_text btn_type='danger' %} - {% trans 'Delete evaluation' as title %} {% trans 'Do you really want to delete the evaluation ?' as question %} {% trans 'Delete evaluation' as action_text %} From 3bc5aba2dbd44ee9bc2ada40e2cde25c5ec2bbf9 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 21:11:00 +0100 Subject: [PATCH 36/74] evaluation deletion modal --- evap/staff/templates/staff_semester_view.html | 19 +++---------------- .../staff_semester_view_evaluation.html | 16 +++++++++++++--- evap/staff/views.py | 2 +- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index d1057af5f..216cac433 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -375,6 +375,9 @@

{{ semester.name }}

+
+ {% csrf_token %} +
{% if num_evaluations > 0 %}
@@ -560,22 +563,6 @@

{{ semester.name }}

{% block modals %} {{ block.super }} - {% trans 'Delete evaluation' as title %} - {% trans 'Do you really want to delete the evaluation ?' as question %} - {% trans 'Delete evaluation' as action_text %} - {% include 'confirmation_modal.html' with modal_id='deleteEvaluationModal' title=title question=question action_text=action_text btn_type='danger' %} - {% trans 'Delete course' as title %} {% trans 'Do you really want to delete the course ?' as question %} {% trans 'Delete course' as action_text %} diff --git a/evap/staff/templates/staff_semester_view_evaluation.html b/evap/staff/templates/staff_semester_view_evaluation.html index fc3626b7d..b3a6ba90f 100644 --- a/evap/staff/templates/staff_semester_view_evaluation.html +++ b/evap/staff/templates/staff_semester_view_evaluation.html @@ -208,9 +208,19 @@ {% endif %} {% if request.user.is_manager and evaluation.can_be_deleted_by_manager %} - + + {% trans 'Delete evaluation' %} + {% trans 'Delete evaluation' %} + + {% blocktrans with evaluation_name=evaluation.full_name %} + Do you really want to delete the evaluation {{ evaluation_name }}? + {% endblocktrans %} + + + + {% endif %} {% endif %} diff --git a/evap/staff/views.py b/evap/staff/views.py index 692c4a5c2..f9eb13507 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -1359,7 +1359,7 @@ def evaluation_delete(request): RatingAnswerCounter.objects.filter(contribution__evaluation=evaluation).delete() evaluation.delete() update_template_cache_of_published_evaluations_in_course(evaluation.course) - return HttpResponse() # 200 OK + return redirect("staff:semester_view", evaluation.course.semester.id) @manager_required From 1684c0f28ab393170be8cf58ff6c82d5c96b974c Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 21:17:59 +0100 Subject: [PATCH 37/74] course deletion modal --- evap/staff/templates/staff_semester_view.html | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 216cac433..09858dfd8 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -485,6 +485,27 @@

{{ semester.name }}

{% if courses %} + + {% csrf_token %} + + +
@@ -540,9 +561,19 @@

{{ semester.name }}

{% endif %} {% if course.can_be_deleted_by_manager %} - + + {% trans 'Delete course' %} + {% trans 'Delete course' %} + + {% blocktrans with course_name=course.name %} + Do you really want to delete the course {{ course_name }}? + {% endblocktrans %} + + + + {% endif %} @@ -561,26 +592,6 @@

{{ semester.name }}

{% endblock %} -{% block modals %} - {{ block.super }} - {% trans 'Delete course' as title %} - {% trans 'Do you really want to delete the course ?' as question %} - {% trans 'Delete course' as action_text %} - {% include 'confirmation_modal.html' with modal_id='deleteCourseModal' title=title question=question action_text=action_text btn_type='danger' %} - -{% endblock %} - {% block additional_javascript %} From e41de6f098b11df5efd2c057a58807bff92c18af Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 21:18:49 +0100 Subject: [PATCH 39/74] `rm evap/evaluation/templates/confirmation_modal.html` --- .../templates/confirmation_modal.html | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 evap/evaluation/templates/confirmation_modal.html diff --git a/evap/evaluation/templates/confirmation_modal.html b/evap/evaluation/templates/confirmation_modal.html deleted file mode 100644 index e8e089e52..000000000 --- a/evap/evaluation/templates/confirmation_modal.html +++ /dev/null @@ -1,33 +0,0 @@ -{% load evaluation_filters %} - - - - From f56d999ee189cd68a95b5ce19b2afc0574b39bbf Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 18 Dec 2023 21:25:48 +0100 Subject: [PATCH 40/74] fix tests --- evap/staff/tests/test_views.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 1782e702b..f64582f2c 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -2239,7 +2239,7 @@ def test_single_result_deletion(self): RatingAnswerCounter, contribution__evaluation=self.evaluation, _quantity=5, _bulk_create=True ) - self.app.post(self.url, user=self.manager, params=self.post_params, status=200) + self.app.post(self.url, user=self.manager, params=self.post_params) self.assertFalse(Evaluation.objects.filter(pk=self.evaluation.pk).exists()) self.assertFalse(RatingAnswerCounter.objects.filter(pk__in=[c.pk for c in counters]).exists()) @@ -2355,7 +2355,7 @@ def test_copy_participants(self): form = page.forms["participant-copy-form"] form["pc-evaluation"] = str(self.evaluation2.pk) - page = form.submit(name="operation", value="copy-participants") + page = submit_with_modal(page, form, name="operation", value="copy-participants") self.assertEqual( self.evaluation.participants.count(), original_participant_count + self.evaluation2.participants.count() @@ -2368,7 +2368,7 @@ def test_replace_copy_participants(self): form = page.forms["participant-copy-form"] form["pc-evaluation"] = str(self.evaluation2.pk) - page = form.submit(name="operation", value="copy-replace-participants") + page = submit_with_modal(page, form, name="operation", value="copy-replace-participants") self.assertEqual(self.evaluation.participants.count(), self.evaluation2.participants.count()) @@ -2387,7 +2387,7 @@ def test_import_valid_contributors_file(self): ) form = page.forms["contributor-import-form"] - form.submit(name="operation", value="import-contributors") + submit_with_modal(page, form, name="operation", value="import-contributors") self.assertEqual( UserProfile.objects.filter(contributions__evaluation=self.evaluation).count(), original_contributor_count + 2, @@ -2406,7 +2406,7 @@ def test_replace_valid_contributors_file(self): self.assertNotEqual(UserProfile.objects.filter(contributions__evaluation=self.evaluation2).count(), 2) form = page.forms["contributor-import-form"] - form.submit(name="operation", value="import-replace-contributors") + submit_with_modal(page, form, name="operation", value="import-replace-contributors") self.assertEqual(UserProfile.objects.filter(contributions__evaluation=self.evaluation2).count(), 2) page = self.app.get(self.url, user=self.manager) @@ -2419,7 +2419,7 @@ def test_copy_contributors(self): form = page.forms["contributor-copy-form"] form["cc-evaluation"] = str(self.evaluation2.pk) - page = form.submit(name="operation", value="copy-contributors") + page = submit_with_modal(page, form, name="operation", value="copy-contributors") new_contributor_count = UserProfile.objects.filter(contributions__evaluation=self.evaluation).count() self.assertEqual( @@ -2437,7 +2437,7 @@ def test_copy_replace_contributors(self): form = page.forms["contributor-copy-form"] form["cc-evaluation"] = str(self.evaluation2.pk) - page = form.submit(name="operation", value="copy-replace-contributors") + page = submit_with_modal(page, form, name="operation", value="copy-replace-contributors") new_contributor_count = UserProfile.objects.filter(contributions__evaluation=self.evaluation).count() self.assertEqual( @@ -3689,7 +3689,7 @@ def test_make_other_semester_active(self): semester1 = baker.make(Semester, is_active=True) semester2 = baker.make(Semester, is_active=False) - self.app.post(self.url, user=manager, status=200, params={"semester_id": semester2.id}) + self.app.post(self.url, user=manager, params={"semester_id": semester2.id}) semester1.refresh_from_db() semester2.refresh_from_db() From 42f0d41354b85e344613de4fb7d4788dd5e6e02c Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 8 Jan 2024 19:57:33 +0100 Subject: [PATCH 41/74] fix remaining todos --- .../templates/contributor_index.html | 34 +++++++++++-------- evap/grades/templates/grades_course_view.html | 4 +-- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/evap/contributor/templates/contributor_index.html b/evap/contributor/templates/contributor_index.html index d49eef391..193b16b8e 100644 --- a/evap/contributor/templates/contributor_index.html +++ b/evap/contributor/templates/contributor_index.html @@ -157,22 +157,26 @@ {% if not evaluation|has_nonresponsible_editor %} - - {% trans 'Delegate preparation' %} - {% trans 'Delegate preparation' %} - - {% blocktrans with evaluation_name=evaluation.full_name %} - Do you really want to delegate the preparation of the evaluation {{ evaluation_name }}? - {% endblocktrans %} -
- {% include 'bootstrap_form.html' with form=delegate_selection_form wide=True %} -
-
+
+ {% csrf_token %} - - - -
+ + {% trans 'Delegate preparation' %} + {% trans 'Delegate preparation' %} + + {% blocktrans with evaluation_name=evaluation.full_name %} + Do you really want to delegate the preparation of the evaluation {{ evaluation_name }}? + {% endblocktrans %} +
+ {% include 'bootstrap_form.html' with form=delegate_selection_form wide=True %} +
+
+ + + + +
+ {% endif %} {% elif evaluation.state == evaluation.State.EDITOR_APPROVED or evaluation.state == evaluation.State.APPROVED %} {{ course.name }} ({{ semester.name }}) - {% trans 'Top general questionnaires' as headline %} {% include 'staff_questionnaire_index_list.html' with questionnaires=general_questionnaires_top headline=headline extra_classes='mb-3' type='top' %} {% trans 'Contributor questionnaires' as headline %} From 6c4e82010b60f80b0bbe219095662caa36752a36 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 8 Jan 2024 20:18:54 +0100 Subject: [PATCH 43/74] Clean up scss a bit --- evap/static/scss/components/_confirmation-modal.scss | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/evap/static/scss/components/_confirmation-modal.scss b/evap/static/scss/components/_confirmation-modal.scss index 593828e13..fb7c3b695 100644 --- a/evap/static/scss/components/_confirmation-modal.scss +++ b/evap/static/scss/components/_confirmation-modal.scss @@ -6,16 +6,19 @@ confirmation-modal:not(:defined) > :not([slot="submit-group"]) { } dialog.evap-modal-dialog { - padding: 0; + z-index: 1050; + inset-block-start: -70vh; // moves the modal to the top of the page, by default, it is centered + max-width: 80ch; border: 1px solid $dark-gray; border-radius: 0.5rem; - z-index: 1050; - inset-block-start: -70vh; + padding: 0; + // These attributes are inherited from parent elements, although it usually does not make any sense, because the + // dialog is not displayed inside of the parent element. This list might grow over time. font-weight: initial; line-height: initial; + cursor: initial; - // https://youtu.be/4prVdA7_6u0 &[open] { animation: modal-enter 300ms forwards; } From 5ae441d72d08bd56e0ed4580b2b4697f983c964a Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 8 Jan 2024 20:19:05 +0100 Subject: [PATCH 44/74] fix a button group --- evap/staff/templates/staff_semester_view.html | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 09858dfd8..f86f85044 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -168,12 +168,11 @@

{{ semester.name }}

{% trans 'Preparation reminder' %} {% trans 'Grade publish reminder' %} {% endif %} -
-
{% trans 'Reward points active' %}
-
-
- {% csrf_token %} - + + {% csrf_token %} +
+
{% trans 'Reward points active' %}
+
{% trans 'Activate reward points' %} {% trans 'Activate reward points' %} @@ -189,9 +188,9 @@

{{ semester.name }}

- +
-
+
{% endif %} From 646344935e3ae345a1ad1863bae0bff9146ab29b Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 8 Jan 2024 21:26:27 +0100 Subject: [PATCH 45/74] Use bootstrap z-index variables --- evap/static/scss/components/_confirmation-modal.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evap/static/scss/components/_confirmation-modal.scss b/evap/static/scss/components/_confirmation-modal.scss index fb7c3b695..7e597cf56 100644 --- a/evap/static/scss/components/_confirmation-modal.scss +++ b/evap/static/scss/components/_confirmation-modal.scss @@ -6,7 +6,7 @@ confirmation-modal:not(:defined) > :not([slot="submit-group"]) { } dialog.evap-modal-dialog { - z-index: 1050; + z-index: $zindex-modal; inset-block-start: -70vh; // moves the modal to the top of the page, by default, it is centered max-width: 80ch; border: 1px solid $dark-gray; @@ -52,6 +52,7 @@ dialog.evap-modal-dialog { } &::backdrop { + z-index: $zindex-modal-backdrop; background-color: black; opacity: 50%; } From e226f4bf4c177264acb6556a45e3570ab0dc9a2d Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 18:06:23 +0100 Subject: [PATCH 46/74] Feedback grades course view modal --- evap/grades/templates/grades_course_view.html | 6 +----- evap/static/scss/components/_confirmation-modal.scss | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/evap/grades/templates/grades_course_view.html b/evap/grades/templates/grades_course_view.html index 5f8d4faac..2a28ce074 100644 --- a/evap/grades/templates/grades_course_view.html +++ b/evap/grades/templates/grades_course_view.html @@ -1,5 +1,4 @@ {% extends 'grades_course_base.html' %} -{% load static %} {% block content %} {{ block.super }} @@ -40,7 +39,7 @@

{{ course.name }} ({{ semester.name }})

{% endblocktrans %} - @@ -50,9 +49,6 @@

{{ course.name }} ({{ semester.name }})

{% endfor %} + + {% block additional_javascript %}{% endblock %} diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index ae3c8a33a..c37718f2d 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -92,7 +92,7 @@

{{ semester.name }}

{% if semester.participations_can_be_archived %} -
+ {% csrf_token %} {% trans 'Archive participations' %} @@ -115,7 +115,7 @@

{{ semester.name }}

{% trans 'Archive participations' %} {% endif %} {% if semester.grade_documents_can_be_deleted %} - + {% csrf_token %} {% trans 'Delete grade documents' %} @@ -135,7 +135,7 @@

{{ semester.name }}

{% endif %} {% if semester.results_can_be_archived %} - + {% csrf_token %} {% trans 'Archive results' %} @@ -484,24 +484,12 @@

{{ semester.name }}

{% if courses %} - + {% csrf_token %} diff --git a/evap/static/ts/src/custom-success-form.ts b/evap/static/ts/src/custom-success-form.ts new file mode 100644 index 000000000..657c21f3b --- /dev/null +++ b/evap/static/ts/src/custom-success-form.ts @@ -0,0 +1,42 @@ +import "./translation.js"; +import { assert } from "./utils.js"; + +const overrideSuccessfulSubmit = ( + form: HTMLFormElement, + onSuccess: (context: { body: FormData; response: Response }) => void, +) => { + form.addEventListener("submit", event => { + event.preventDefault(); + + const body = new FormData(form); + + fetch(form.action, { method: form.method, body }) + .then(response => { + assert(response.ok); + onSuccess({ body, response }); + }) + .catch(error => { + console.error(error); + window.alert(window.gettext("The server is not responding.")); + }); + }); +}; + +const makeCustomSuccessForm = (form: HTMLFormElement) => { + overrideSuccessfulSubmit(form, ({ body }) => { + form.dispatchEvent(new CustomEvent("submit-success", { detail: { body } })); + }); +}; + +const makeReloadOnSuccessForm = (form: HTMLFormElement) => { + overrideSuccessfulSubmit(form, () => window.location.reload()); +}; + +export const setupForms = () => { + document.querySelectorAll("form[custom-success]").forEach(form => { + makeCustomSuccessForm(form as HTMLFormElement); + }); + document.querySelectorAll("form[reload-on-success]").forEach(form => { + makeReloadOnSuccessForm(form as HTMLFormElement); + }); +}; From cc3f4b50086c8113435b0f201e61d620fd5ce9c0 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:11:13 +0100 Subject: [PATCH 50/74] remove todo, it already submits --- evap/contributor/templates/contributor_index.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/evap/contributor/templates/contributor_index.html b/evap/contributor/templates/contributor_index.html index 193b16b8e..8512e34be 100644 --- a/evap/contributor/templates/contributor_index.html +++ b/evap/contributor/templates/contributor_index.html @@ -205,8 +205,6 @@ {% endfor %}
- - {% endif %} From ce5fc90d44992b86a8903351e62087bccd0483c4 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:15:02 +0100 Subject: [PATCH 51/74] fix evaluation deletion submit behavior --- evap/staff/templates/staff_semester_view.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index c37718f2d..5b3d586da 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -374,9 +374,16 @@

{{ semester.name }}

-
+ {% csrf_token %}
+ + +
{% if num_evaluations > 0 %} From 86d42404c2ce54535034b669e82cb65ab2f993bb Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:16:48 +0100 Subject: [PATCH 52/74] dont emit `confirmed` event if `type=submit` --- evap/static/ts/src/confirmation-modal.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evap/static/ts/src/confirmation-modal.ts b/evap/static/ts/src/confirmation-modal.ts index f65609dfe..93b1912b9 100644 --- a/evap/static/ts/src/confirmation-modal.ts +++ b/evap/static/ts/src/confirmation-modal.ts @@ -35,8 +35,6 @@ export class ConfirmationModal extends HTMLElement { this.closeDialogSlowly(); if (event.submitter?.dataset?.eventType === "confirm") { - this.dispatchEvent(new CustomEvent("confirmed", { detail: new FormData(this.dialogForm) })); - if (this.type === "submit") { // Unfortunately, `this` cannot act as the submitter of the form. Instead, we make our `value` attribute // visible to the form until submission is finished (the `submit` handlers of the form might cancel the @@ -44,6 +42,8 @@ export class ConfirmationModal extends HTMLElement { this.internals.setFormValue(this.getAttribute("value")); this.internals.form?.requestSubmit(); this.internals.setFormValue(null); + } else { + this.dispatchEvent(new CustomEvent("confirmed", { detail: new FormData(this.dialogForm) })); } } }; From c2c69e7a9f8d30a77fab973a927ef7eecc65c313 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:29:24 +0100 Subject: [PATCH 53/74] Use `reload-on-success` for `set_no_grades` --- evap/grades/templates/grades_semester_view.html | 4 ++-- evap/grades/tests.py | 9 ++++++--- evap/grades/views.py | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/evap/grades/templates/grades_semester_view.html b/evap/grades/templates/grades_semester_view.html index 2e823852b..0e5621bd8 100644 --- a/evap/grades/templates/grades_semester_view.html +++ b/evap/grades/templates/grades_semester_view.html @@ -64,7 +64,7 @@

{% if num_final_grades > 0 %} {{ num_final_grades }} {% elif course.gets_no_grade_documents %} - + {% csrf_token %} @@ -87,7 +87,7 @@

{% if not course.gets_no_grade_documents %} {% if num_final_grades == 0 %} - + {% csrf_token %} diff --git a/evap/grades/tests.py b/evap/grades/tests.py index 1864caf0c..1e02bfc27 100644 --- a/evap/grades/tests.py +++ b/evap/grades/tests.py @@ -149,7 +149,8 @@ def test_set_no_grades(self): "/grades/set_no_grades", params={"course_id": evaluation.course.id, "status": "1"}, user=self.grade_publisher, - ).follow(status=200) + status=200, + ) evaluation = Evaluation.objects.get(id=evaluation.id) self.assertTrue(evaluation.course.gets_no_grade_documents) # evaluation should get published here @@ -162,7 +163,8 @@ def test_set_no_grades(self): "/grades/set_no_grades", params={"course_id": evaluation.course.id, "status": "0"}, user=self.grade_publisher, - ).follow(status=200) + status=200, + ) evaluation = Evaluation.objects.get(id=evaluation.id) self.assertFalse(evaluation.course.gets_no_grade_documents) @@ -170,7 +172,8 @@ def test_set_no_grades(self): "/grades/set_no_grades", params={"course_id": evaluation.course.id, "status": "0"}, user=self.grade_publisher, - ).follow(status=200) + status=200, + ) evaluation = Evaluation.objects.get(id=evaluation.id) self.assertFalse(evaluation.course.gets_no_grade_documents) diff --git a/evap/grades/views.py b/evap/grades/views.py index dc9d0869f..88d779df9 100644 --- a/evap/grades/views.py +++ b/evap/grades/views.py @@ -165,7 +165,7 @@ def set_no_grades(request): if course.gets_no_grade_documents: on_grading_process_finished(course) - return redirect("grades:semester_view", course.semester.id) + return HttpResponse() # 200 OK @require_GET From d9b37f6904a4e4d6ffaf9a4acc0b04155d0bf099 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:33:05 +0100 Subject: [PATCH 54/74] Restore `staff/views.py` to before this PR --- evap/staff/views.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/evap/staff/views.py b/evap/staff/views.py index f9eb13507..c9a8f7ddb 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -619,7 +619,7 @@ def semester_make_active(request): semester.is_active = True semester.save() - return redirect("staff:semester_view", semester.id) + return HttpResponse() @require_POST @@ -899,7 +899,7 @@ def semester_preparation_reminder(request, semester_id): body_params = {"user": responsible, "evaluations": evaluations} template.send_to_user(responsible, subject_params, body_params, use_cc=True, request=request) messages.success(request, _("Successfully sent reminders to everyone.")) - return redirect("staff:semester_preparation_reminder", semester.id) + return HttpResponse() template_data = {"semester": semester, "responsible_list": responsible_list} return render(request, "staff_semester_preparation_reminder.html", template_data) @@ -1359,7 +1359,7 @@ def evaluation_delete(request): RatingAnswerCounter.objects.filter(contribution__evaluation=evaluation).delete() evaluation.delete() update_template_cache_of_published_evaluations_in_course(evaluation.course) - return redirect("staff:semester_view", evaluation.course.semester.id) + return HttpResponse() # 200 OK @manager_required @@ -2241,7 +2241,7 @@ def user_delete(request): raise SuspiciousOperation("Deleting user not allowed") user.delete() messages.success(request, _("Successfully deleted user.")) - return redirect("staff:user_index") + return HttpResponse() # 200 OK @require_POST @@ -2258,7 +2258,7 @@ def user_resend_email(request): template.send_to_user(user, {}, body_params, use_cc=False) messages.success(request, _("Successfully resent evaluation started email.")) - return redirect("staff:user_edit", user.pk) + return HttpResponse() # 200 OK @manager_required From cfe31fc46ae5b7b6f4a2536e046ca0412295624f Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:47:05 +0100 Subject: [PATCH 55/74] Use `reload-on-success` for the staff views --- evap/staff/templates/staff_semester_preparation_reminder.html | 2 +- evap/staff/templates/staff_semester_view.html | 2 +- evap/staff/templates/staff_user_form.html | 4 ++-- evap/staff/tests/test_views.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/evap/staff/templates/staff_semester_preparation_reminder.html b/evap/staff/templates/staff_semester_preparation_reminder.html index df3be1ada..2755b6a1d 100644 --- a/evap/staff/templates/staff_semester_preparation_reminder.html +++ b/evap/staff/templates/staff_semester_preparation_reminder.html @@ -14,7 +14,7 @@
- + {% csrf_token %} diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index 5b3d586da..30d970a92 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -11,7 +11,7 @@

{{ semester.name }}

{% if request.user.is_manager %}   {% trans 'Edit' %} - + {% csrf_token %} {% trans 'Make this the active semester' %} diff --git a/evap/staff/templates/staff_user_form.html b/evap/staff/templates/staff_user_form.html index f48fe4276..9dc909b2d 100644 --- a/evap/staff/templates/staff_user_form.html +++ b/evap/staff/templates/staff_user_form.html @@ -21,7 +21,7 @@

{% if form.instance.id %}{% trans 'Edit user' %}{% else %}{% trans 'Create u
{% if has_due_evaluations %}
- + {% csrf_token %} @@ -119,7 +119,7 @@
{% trans 'Export evaluation results' %}
{% if form.instance and form.instance.can_be_deleted_by_manager %} - + {% csrf_token %} diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index f64582f2c..f74046705 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -955,7 +955,7 @@ def test_remind_all(self, email_template_mock): email_template_mock.objects.get.return_value = email_template_mock email_template_mock.EDITOR_REVIEW_REMINDER = EmailTemplate.EDITOR_REVIEW_REMINDER - self.app.post(self.url, user=self.manager).follow(status=200) + self.app.post(self.url, user=self.manager, status=200) subject_params = {} body_params = {"user": user, "evaluations": [evaluation]} From be31c450a70d5217a038fee8d423840818d608d4 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 20:59:15 +0100 Subject: [PATCH 56/74] Use `custom-success` for grade document deletion --- evap/grades/templates/grades_course_view.html | 97 +++++++++---------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/evap/grades/templates/grades_course_view.html b/evap/grades/templates/grades_course_view.html index 2a28ce074..755b7aa5e 100644 --- a/evap/grades/templates/grades_course_view.html +++ b/evap/grades/templates/grades_course_view.html @@ -11,63 +11,54 @@

{{ course.name }} ({{ semester.name }})

{% if grade_documents %} - - - - - - - - - - - {% for grade_document in grade_documents %} - - - - - +
{% trans 'Description' %}{% trans 'Type' %}{% trans 'Last edited' %}{% trans 'Actions' %}
{{ grade_document.description }}{{ grade_document.get_type_display }}{{ grade_document.last_modified_time }}, {% trans 'by' %} {{ grade_document.last_modified_user }} - - {% if user.is_grade_publisher %} - - - {% trans 'Delete grade document' %} - {% trans 'Delete grade document' %} - - {% blocktrans with description=grade_document.description %} - Do you really want to delete the grade document {{ description }}? - {% endblocktrans %} - + + {% csrf_token %} - - - {% endif %} -
+ + + + + + - {% endfor %} + + + {% for grade_document in grade_documents %} + + + + + -
{% trans 'Description' %}{% trans 'Type' %}{% trans 'Last edited' %}{% trans 'Actions' %}
{{ grade_document.description }}{{ grade_document.get_type_display }}{{ grade_document.last_modified_time }}, {% trans 'by' %} {{ grade_document.last_modified_user }} + + {% if user.is_grade_publisher %} + + + {% trans 'Delete grade document' %} + {% trans 'Delete grade document' %} + + {% blocktrans with description=grade_document.description %} + Do you really want to delete the grade document {{ description }}? + {% endblocktrans %} + - -
+ {% else %} {% trans 'No grade documents have been uploaded yet' %} {% endif %} From b1141c0c0b9a13d974c677a6bbd1c5063f2bc393 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 22 Jan 2024 21:04:46 +0100 Subject: [PATCH 57/74] Undo unneeded changes in `staff/tests/test_views.py` --- evap/staff/tests/test_views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index f74046705..fd40f245b 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -2239,7 +2239,7 @@ def test_single_result_deletion(self): RatingAnswerCounter, contribution__evaluation=self.evaluation, _quantity=5, _bulk_create=True ) - self.app.post(self.url, user=self.manager, params=self.post_params) + self.app.post(self.url, user=self.manager, params=self.post_params, status=200) self.assertFalse(Evaluation.objects.filter(pk=self.evaluation.pk).exists()) self.assertFalse(RatingAnswerCounter.objects.filter(pk__in=[c.pk for c in counters]).exists()) @@ -3689,7 +3689,7 @@ def test_make_other_semester_active(self): semester1 = baker.make(Semester, is_active=True) semester2 = baker.make(Semester, is_active=False) - self.app.post(self.url, user=manager, params={"semester_id": semester2.id}) + self.app.post(self.url, user=manager, status=200, params={"semester_id": semester2.id}) semester1.refresh_from_db() semester2.refresh_from_db() From 4ab3ad87235c8a00aa2625b137e530e0c0517c40 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 29 Jan 2024 18:04:26 +0100 Subject: [PATCH 58/74] Replace `async` with `type="module"` --- .../templates/rewards_reward_point_redemption_events.html | 2 +- evap/staff/templates/staff_questionnaire_index.html | 2 +- evap/staff/templates/staff_semester_view.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/evap/rewards/templates/rewards_reward_point_redemption_events.html b/evap/rewards/templates/rewards_reward_point_redemption_events.html index 6aa632ac8..834f38772 100644 --- a/evap/rewards/templates/rewards_reward_point_redemption_events.html +++ b/evap/rewards/templates/rewards_reward_point_redemption_events.html @@ -20,7 +20,7 @@ {% csrf_token %} - - - - {% endif %} + modal.querySelectorAll("[data-must-equal]").forEach(element => { + element.addEventListener("change", () => { + if (element.value === element.dataset.mustEqual) { + element.setCustomValidity(""); + } else { + element.setCustomValidity("{% trans 'Please enter the required text.' %}"); + } + element.reportValidity(); + }); + element.dispatchEvent(new Event("change")); + }); + + + +
+ {% endif %} + {% if request.user.is_manager %}
From eb0cce5658010162a53b0b946892286dfee9e5d9 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 12 Feb 2024 20:02:40 +0100 Subject: [PATCH 66/74] Sync modal disabled state with show button for style reasons --- evap/static/ts/src/confirmation-modal.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/evap/static/ts/src/confirmation-modal.ts b/evap/static/ts/src/confirmation-modal.ts index 93b1912b9..43dc31868 100644 --- a/evap/static/ts/src/confirmation-modal.ts +++ b/evap/static/ts/src/confirmation-modal.ts @@ -19,13 +19,22 @@ export class ConfirmationModal extends HTMLElement { this.internals = this.attachInternals(); this.dialog = selectOrError("dialog", shadowRoot); - this.dialogForm = selectOrError("form[method=dialog]", this.dialog); const confirmButton = selectOrError("[data-event-type=confirm]", this.dialog); const confirmButtonExtraClass = this.getAttribute("confirm-button-class") ?? "btn-primary"; confirmButton.className += " " + confirmButtonExtraClass; - selectOrError("[slot=show-button]", this).addEventListener("click", () => this.dialog.showModal()); + const showButton = selectOrError("[slot=show-button]", this); + showButton.addEventListener("click", () => this.dialog.showModal()); + const updateDisabledAttribute = () => { + this.toggleAttribute("disabled", showButton.hasAttribute("disabled")); + }; + new MutationObserver(updateDisabledAttribute).observe(showButton, { + attributeFilter: ["disabled"], + }); + updateDisabledAttribute(); + + this.dialogForm = selectOrError("form[method=dialog]", this.dialog); this.dialogForm.addEventListener("submit", this.onDialogFormSubmit); } @@ -55,7 +64,7 @@ export class ConfirmationModal extends HTMLElement { this.dialog.removeAttribute("closing"); this.dialog.close(); }, - { once: true }, + { once: true } ); this.dialog.setAttribute("closing", ""); }; From 00f5940fe4f4bc75eab550c21989eb4a2b993a19 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 12 Feb 2024 20:19:57 +0100 Subject: [PATCH 67/74] make semester name confirmation box in semester deletion modal look not broken --- evap/staff/templates/staff_semester_view.html | 2 +- evap/static/scss/components/_confirmation-modal.scss | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/evap/staff/templates/staff_semester_view.html b/evap/staff/templates/staff_semester_view.html index c611656df..bbbc64442 100644 --- a/evap/staff/templates/staff_semester_view.html +++ b/evap/staff/templates/staff_semester_view.html @@ -49,7 +49,7 @@

{{ semester.name }}

- +
diff --git a/evap/static/scss/components/_confirmation-modal.scss b/evap/static/scss/components/_confirmation-modal.scss index 4f291341d..beae4e3e0 100644 --- a/evap/static/scss/components/_confirmation-modal.scss +++ b/evap/static/scss/components/_confirmation-modal.scss @@ -72,6 +72,12 @@ dialog.evap-modal-dialog { justify-content: space-between; } + .question-area { + display: flex; + flex-direction: column; + gap: 0.5rem; + } + .button-area { display: flex; flex-flow: wrap; From a6bdd9836ee835adf178eeea6060a91de4b12b77 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 12 Feb 2024 22:19:47 +0100 Subject: [PATCH 68/74] Fix bug in chrome where clicking with an open modal triggers a click on an `` ancestor, even if the dialog stops event propagation in a handler --- evap/static/ts/src/confirmation-modal.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/evap/static/ts/src/confirmation-modal.ts b/evap/static/ts/src/confirmation-modal.ts index 43dc31868..ce982e449 100644 --- a/evap/static/ts/src/confirmation-modal.ts +++ b/evap/static/ts/src/confirmation-modal.ts @@ -25,7 +25,10 @@ export class ConfirmationModal extends HTMLElement { confirmButton.className += " " + confirmButtonExtraClass; const showButton = selectOrError("[slot=show-button]", this); - showButton.addEventListener("click", () => this.dialog.showModal()); + showButton.addEventListener("click", event => { + event.stopPropagation(); + this.dialog.showModal(); + }); const updateDisabledAttribute = () => { this.toggleAttribute("disabled", showButton.hasAttribute("disabled")); }; @@ -36,6 +39,8 @@ export class ConfirmationModal extends HTMLElement { this.dialogForm = selectOrError("form[method=dialog]", this.dialog); this.dialogForm.addEventListener("submit", this.onDialogFormSubmit); + + this.dialog.addEventListener("click", event => event.stopPropagation()); } onDialogFormSubmit = (event: SubmitEvent) => { From ad3663ef02d15108198456e5ad36262e2f34e9e9 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Thu, 22 Feb 2024 18:38:45 +0100 Subject: [PATCH 69/74] Use `form=` instead of wrapping table in form for grade document deletion --- evap/grades/templates/grades_course_view.html | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/evap/grades/templates/grades_course_view.html b/evap/grades/templates/grades_course_view.html index 56fb53e67..a7b3d7779 100644 --- a/evap/grades/templates/grades_course_view.html +++ b/evap/grades/templates/grades_course_view.html @@ -13,46 +13,46 @@

{{ course.name }} ({{ semester.name }})

{% if grade_documents %}
{% csrf_token %} +
- - - - - - - - - - - {% for grade_document in grade_documents %} - - - - - + + {% endfor %} + +
{% trans 'Description' %}{% trans 'Type' %}{% trans 'Last edited' %}{% trans 'Actions' %}
{{ grade_document.description }}{{ grade_document.get_type_display }}{{ grade_document.last_modified_time }}, {% trans 'by' %} {{ grade_document.last_modified_user }} - - {% if user.is_grade_publisher %} - - - {% trans 'Delete grade document' %} - {% trans 'Delete grade document' %} - - {% blocktrans trimmed with description=grade_document.description %} - Do you really want to delete the grade document {{ description }}? - {% endblocktrans %} - + + + + + + + + + + + {% for grade_document in grade_documents %} + + + + + - - {% endfor %} - -
{% trans 'Description' %}{% trans 'Type' %}{% trans 'Last edited' %}{% trans 'Actions' %}
{{ grade_document.description }}{{ grade_document.get_type_display }}{{ grade_document.last_modified_time }}, {% trans 'by' %} {{ grade_document.last_modified_user }} + + {% if user.is_grade_publisher %} + + + {% trans 'Delete grade document' %} + {% trans 'Delete grade document' %} + + {% blocktrans trimmed with description=grade_document.description %} + Do you really want to delete the grade document {{ description }}? + {% endblocktrans %} + - - - {% endif %} -
- + +
+ {% endif %} +
+ {% endwith %} +{% endblock %} From 216472fe260b293fe3caeec634be8e02091d4a92 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 26 Feb 2024 00:43:49 +0100 Subject: [PATCH 73/74] Fixes for the old modal --- .../templates/contributor_index.html | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/evap/contributor/templates/contributor_index.html b/evap/contributor/templates/contributor_index.html index e61132d2c..354303088 100644 --- a/evap/contributor/templates/contributor_index.html +++ b/evap/contributor/templates/contributor_index.html @@ -157,12 +157,13 @@
{% if not evaluation|has_nonresponsible_editor %} - - + {% endif %} {% elif evaluation.state == evaluation.State.EDITOR_APPROVED or evaluation.state == evaluation.State.APPROVED %} {% trans 'Delegate preparation'
- {% endwith %} {% endblock %} From 4dbbaecf4082b16c9c1222b02a9de4295aaeced4 Mon Sep 17 00:00:00 2001 From: Niklas Mohrin Date: Mon, 26 Feb 2024 00:47:16 +0100 Subject: [PATCH 74/74] `./manage.py format` --- evap/static/ts/src/confirmation-modal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evap/static/ts/src/confirmation-modal.ts b/evap/static/ts/src/confirmation-modal.ts index ce982e449..459a55be6 100644 --- a/evap/static/ts/src/confirmation-modal.ts +++ b/evap/static/ts/src/confirmation-modal.ts @@ -69,7 +69,7 @@ export class ConfirmationModal extends HTMLElement { this.dialog.removeAttribute("closing"); this.dialog.close(); }, - { once: true } + { once: true }, ); this.dialog.setAttribute("closing", ""); };