Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add preparation reminder text view #2408

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 57 additions & 30 deletions evap/staff/templates/staff_semester_preparation_reminder.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

{% block content %}
{{ block.super }}

{% if responsible_list %}
<div class="d-flex mb-3">
<div class="me-auto">

<h3>
{% translate 'Preparation reminder' %} ({{ semester.name }})
</h3>
<div class="d-flex mb-3">
<div class="me-auto">
{% if responsible_list and interactive %}
<form reload-on-success method="POST" action="{% url 'staff:semester_preparation_reminder' semester_id=semester.id %}">
{% csrf_token %}

Expand All @@ -27,35 +28,47 @@
<button slot="show-button" type="button" id="remindAllButton" class="btn btn-sm btn-light">{% translate 'Remind all' %}</button>
</confirmation-modal>
</form>
{% endif %}
</div>
<div class="btn-switch btn-switch-light ms-2 d-print-none h-">
<div class="btn-switch-label">{% translate 'View' %}</div>
<div class="btn-switch btn-group">
<a href="{% url 'staff:semester_preparation_reminder' semester_id=semester.id %}" role="button" class="btn btn-sm btn-light {% if interactive %} active{% endif %}">
{% translate 'Interactive' %}
</a>
<a href="{% url 'staff:semester_preparation_reminder' semester_id=semester.id %}?mode=text" role="button" class="btn btn-sm btn-light{% if not interactive %} active{% endif %}">
{% translate 'Text' %}
</a>
</div>
</div>
{% endif %}
</div>

{% for responsible, evaluations, delegates in responsible_list %}
<div class="card{% if not forloop.last %} mb-3{% endif %}">
<div class="card-header d-flex">
<span class="ps-1 me-auto">
<a href="{% url 'staff:user_edit' responsible.id %}">{{ responsible.full_name }}</a>, {% translate 'Delegates' %}:
{% for delegate in delegates %}
<a href="{% url 'staff:user_edit' delegate.id %}">{{ delegate.full_name }}</a>{% if not forloop.last %},{% endif %}
{% empty %}
&mdash;
{% endfor %}
</span>
<div>
<a href="{% url 'staff:send_reminder' semester.id responsible.id %}" class="btn btn-sm btn-light">{% translate 'Send reminder' %}</a>
{% if interactive %}
{% for responsible, evaluations, delegates in responsible_list %}
<div class="card{% if not forloop.last %} mb-3{% endif %}">
<div class="card-header d-flex">
<span class="ps-1 me-auto">
<a href="{% url 'staff:user_edit' responsible.id %}">{{ responsible.full_name }}</a>, {% translate 'Delegates' %}:
{% for delegate in delegates %}
<a href="{% url 'staff:user_edit' delegate.id %}">{{ delegate.full_name }}</a>{% if not forloop.last %},{% endif %}
{% empty %}
&mdash;
{% endfor %}
</span>
<div>
<a href="{% url 'staff:send_reminder' semester.id responsible.id %}" class="btn btn-sm btn-light">{% translate 'Send reminder' %}</a>
</div>
</div>
</div>
<div class="card-body">
<table class="table table-striped">
<thead>
<div class="card-body">
<table class="table table-striped">
<thead>
<tr>
<th class="width-percent-57">{% translate 'Name' %}</th>
<th class="width-percent-18">{% translate 'Start of evaluation' %}</th>
<th class="width-percent-25">{% translate 'Last modified by' %}</th>
</tr>
</thead>
<tbody>
</tr>
</thead>
<tbody>
{% for evaluation in evaluations %}
<tr{% if evaluation.state != evaluation.State.PREPARED %} class="deactivate"{% endif %}>
<th scope="row">
Expand All @@ -75,10 +88,24 @@
</td>
</tr>
{% endfor %}
</tbody>
</table>
</tbody>
</table>
</div>
</div>
{% endfor %}
{% else %}
<div class="card">
<div class="card-body">
{% for responsible, evaluations, _ in responsible_list %}
<b>{{ responsible.full_name }}</b><br />
{% for evaluation in evaluations %}
- {{ evaluation.full_name }} (<span class="fst-italic">{{ evaluation.course.type }}</span>)<br />
{% endfor %}
{% if not forloop.last %}
<br />
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}

{% endif %}
{% endblock %}
38 changes: 18 additions & 20 deletions evap/staff/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,41 +938,36 @@ class TestSemesterPreparationReminderView(WebTestStaffModeWith200Check):
@classmethod
def setUpTestData(cls):
cls.manager = make_manager()
cls.user = baker.make(UserProfile, _fill_optional=["email"])
cls.semester = baker.make(Semester)

cls.url = f"/staff/semester/{cls.semester.pk}/preparation_reminder"
cls.test_users = [cls.manager]

def test_preparation_reminder(self):
user = baker.make(UserProfile, email="[email protected]")
evaluation = baker.make(
cls.evaluation = baker.make(
Evaluation,
course=baker.make(Course, semester=self.semester, responsibles=[user]),
course=baker.make(Course, semester=cls.semester, responsibles=[cls.user]),
state=Evaluation.State.PREPARED,
name_en="name_to_find",
name_de="name_to_find",
)
baker.make(
cls.contribution = baker.make(
Contribution,
evaluation=evaluation,
contributor=user,
evaluation=cls.evaluation,
contributor=cls.user,
role=Contribution.Role.EDITOR,
textanswer_visibility=Contribution.TextAnswerVisibility.GENERAL_TEXTANSWERS,
)

def test_preparation_reminder(self) -> None:
response = self.app.get(self.url, user=self.manager)
self.assertContains(response, "user_to_find")
self.assertContains(response, "name_to_find")
self.assertContains(response, self.user.full_name)
self.assertContains(response, self.evaluation.full_name)

@patch("evap.staff.views.EmailTemplate")
def test_remind_all(self, email_template_mock):
user = baker.make(UserProfile)
evaluation = baker.make(
Evaluation,
course=baker.make(Course, semester=self.semester, responsibles=[user]),
state=Evaluation.State.PREPARED,
)
response = self.app.get(self.url, params={"mode": "text"}, user=self.manager)
self.assertContains(response, self.user.full_name)
self.assertContains(response, self.evaluation.full_name)

@patch("evap.staff.views.EmailTemplate")
def test_remind_all(self, email_template_mock) -> None:
email_template_mock.objects.get.return_value = email_template_mock
email_template_mock.EDITOR_REVIEW_REMINDER = EmailTemplate.EDITOR_REVIEW_REMINDER

Expand All @@ -981,9 +976,12 @@ def test_remind_all(self, email_template_mock):
email_template_mock.send_to_user.assert_called_once()
kwargs = email_template_mock.send_to_user.mock_calls[0][2]
self.assertEqual(kwargs["subject_params"], {})
self.assertEqual(kwargs["body_params"], {"user": user, "evaluations": [evaluation]})
self.assertEqual(kwargs["body_params"], {"user": self.user, "evaluations": [self.evaluation]})
self.assertEqual(kwargs["use_cc"], True)

def test_invalid_mode(self) -> None:
self.app.get(self.url, params={"mode": "invalid"}, user=self.manager, status=400)
self.app.post(self.url + "?mode=text", user=self.manager, status=400)

class TestGradeReminderView(WebTestStaffMode):
@classmethod
Expand Down
13 changes: 7 additions & 6 deletions evap/staff/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,11 @@ def semester_questionnaire_assign(request, semester_id):


@manager_required
def semester_preparation_reminder(request, semester_id):
def semester_preparation_reminder(request: HttpRequest, semester_id: int) -> HttpResponse:
mode = request.GET.get("mode", "interactive")
if request.method == "POST" and mode == "text" or mode not in ["interactive", "text"]:
raise SuspiciousOperation

semester = get_object_or_404(Semester, id=semester_id)

evaluations = semester.evaluations.filter(
Expand All @@ -940,16 +944,13 @@ def semester_preparation_reminder(request, semester_id):

if request.method == "POST":
template = EmailTemplate.objects.get(name=EmailTemplate.EDITOR_REVIEW_REMINDER)
subject_params = {}
for responsible, evaluations, __ in responsible_list:
body_params = {"user": responsible, "evaluations": evaluations}
template.send_to_user(
responsible, subject_params=subject_params, body_params=body_params, use_cc=True, request=request
)
template.send_to_user(responsible, subject_params={}, body_params=body_params, use_cc=True, request=request)
messages.success(request, _("Successfully sent reminders to everyone."))
return HttpResponse()

template_data = {"semester": semester, "responsible_list": responsible_list}
template_data = {"semester": semester, "responsible_list": responsible_list, "interactive": mode == "interactive"}
return render(request, "staff_semester_preparation_reminder.html", template_data)


Expand Down
Loading