From d88c2ecc1ef4bc0f55ca6279c96f6ad24905b1d9 Mon Sep 17 00:00:00 2001 From: KoKonuts Date: Mon, 15 Nov 2021 22:18:31 +0100 Subject: [PATCH 1/6] Prioritize evaluations with finished grading for review --- evap/staff/views.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/evap/staff/views.py b/evap/staff/views.py index c3c9e69685..5438d6bd72 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -1452,7 +1452,13 @@ def evaluation_textanswers(request, semester_id, evaluation_id): request.session["review-visited"] = visited sections = evaluation_sections + contributor_sections - template_data.update(dict(sections=sections, next_evaluations=next_evaluations)) + # Evaluations where the grading process is finished should be shown first, need to be sorted in Python + template_data.update( + dict( + sections=sections, + next_evaluations=sorted(next_evaluations, key=lambda e: e.grading_process_is_finished, reverse=True), + ) + ) return render(request, "staff_evaluation_textanswers_quick.html", template_data) template_data.update(dict(evaluation_sections=evaluation_sections, contributor_sections=contributor_sections)) From e50d2ac23687636b1d7f8d81af0f3ec062a333c5 Mon Sep 17 00:00:00 2001 From: KoKonuts Date: Thu, 31 Mar 2022 21:48:20 +0200 Subject: [PATCH 2/6] Prioritize evaluations with finished grading for review including test --- evap/staff/tests/test_views.py | 67 ++++++++++++++++++++++++++++++---- evap/staff/tools.py | 20 +++++----- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 478089d82f..1d3c0c8061 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -2187,16 +2187,16 @@ class TestEvaluationTextAnswerView(WebTest): @classmethod def setUpTestData(cls): cls.manager = make_manager() - semester = baker.make(Semester, pk=1) - student1 = baker.make(UserProfile, email="student@institution.example.com") + cls.semester = baker.make(Semester, pk=1) + cls.student1 = baker.make(UserProfile, email="student@institution.example.com") cls.student2 = baker.make(UserProfile, email="student2@example.com") cls.evaluation = baker.make( Evaluation, pk=1, - course__semester=semester, - participants=[student1, cls.student2], - voters=[student1], + course__semester=cls.semester, + participants=[cls.student1, cls.student2], + voters=[cls.student1], state=Evaluation.State.IN_EVALUATION, ) top_general_questionnaire = baker.make(Questionnaire, type=Questionnaire.Type.TOP) @@ -2216,9 +2216,9 @@ def setUpTestData(cls): cls.evaluation2 = baker.make( Evaluation, - course__semester=semester, - participants=[student1], - voters=[student1, cls.student2], + course__semester=cls.semester, + participants=[cls.student1], + voters=[cls.student1, cls.student2], vote_start_datetime=datetime.datetime.now() - datetime.timedelta(days=5), vote_end_date=datetime.date.today() - datetime.timedelta(days=4), can_publish_text_results=True, @@ -2280,6 +2280,57 @@ def test_exclude_unfinished_evaluations(self): # unfinished because still in EVALUATION_END_OFFSET_HOURS self.assertNotContains(page, self.evaluation2.full_name) + def test_suggested_evaluation_ordering(self): + evaluations = baker.make( + Evaluation, + course__semester=self.semester, + participants=[self.student1, self.student2], + voters=[self.student1, self.student2], + state=Evaluation.State.IN_EVALUATION, + vote_start_datetime=datetime.datetime.now() - datetime.timedelta(days=42), + vote_end_date=datetime.date.today() - datetime.timedelta(days=2), + can_publish_text_results=True, + _quantity=2, + ) + + for i, evaluation in enumerate(evaluations): + evaluation.general_contribution.questionnaires.set([baker.make(Questionnaire, type=Questionnaire.Type.TOP)]) + question = baker.make(Question, type=Question.TEXT) + contribution = baker.make( + Contribution, + evaluation=evaluation, + contributor=baker.make(UserProfile), + questionnaires=[question.questionnaire], + ) + baker.make(TextAnswer, contribution=contribution, question=question, answer=self.answer) + if i == 1: + baker.make(TextAnswer, contribution=contribution, question=question, answer=self.answer) + + url = f"/staff/semester/{self.semester.pk}/evaluation/{self.evaluation2.pk}/textanswers" + + with run_in_staff_mode(self): + # Since Evaluation 1 has an extra text answer, it should be first + page = self.app.get(url, user=self.manager) + self.assertTrue( + f'data-evaluation="{evaluations[1].pk}"' in str(page.html.select("span[data-next-evaluation-index]")[0]) + ) + + # Since Evaluation 0 has an earlier end date, it should now be first + evaluations[0].vote_end_date = datetime.date.today() - datetime.timedelta(days=4) + evaluations[0].save() + page = self.app.get(url, user=self.manager) + self.assertTrue( + f'data-evaluation="{evaluations[0].pk}"' in str(page.html.select("span[data-next-evaluation-index]")[0]) + ) + + # Since the grading process for Evaluation 1 is finished, it should be first + evaluations[1].wait_for_grade_upload_before_publishing = False + evaluations[1].save() + page = self.app.get(url, user=self.manager) + self.assertTrue( + f'data-evaluation="{evaluations[1].pk}"' in str(page.html.select("span[data-next-evaluation-index]")[0]) + ) + def test_num_queries_is_constant(self): let_user_vote_for_evaluation(self.student2, self.evaluation) with run_in_staff_mode(self): diff --git a/evap/staff/tools.py b/evap/staff/tools.py index 63ecd57478..8fd38e1ee9 100644 --- a/evap/staff/tools.py +++ b/evap/staff/tools.py @@ -334,15 +334,17 @@ def find_unreviewed_evaluations(semester, excluded): if datetime.now().hour < settings.EVALUATION_END_OFFSET_HOURS: exclude_date -= timedelta(days=1) - return ( - semester.evaluations.exclude(pk__in=excluded) - .exclude(state=Evaluation.State.PUBLISHED) - .exclude(vote_end_date__gte=exclude_date) - .exclude(can_publish_text_results=False) - .filter(contributions__textanswer_set__state=TextAnswer.State.NOT_REVIEWED) - .annotate(num_unreviewed_textanswers=Count("contributions__textanswer_set")) - .order_by("vote_end_date", "-num_unreviewed_textanswers") - .all() + # Evaluations where the grading process is finished should be shown first, need to be sorted in Python + return sorted( + ( + semester.evaluations.exclude(pk__in=excluded) + .exclude(state=Evaluation.State.PUBLISHED) + .exclude(vote_end_date__gte=exclude_date) + .exclude(can_publish_text_results=False) + .filter(contributions__textanswer_set__state=TextAnswer.State.NOT_REVIEWED) + .annotate(num_unreviewed_textanswers=Count("contributions__textanswer_set")) + ), + key=lambda e: (-e.grading_process_is_finished, e.vote_end_date, -e.num_unreviewed_textanswers), ) From 4506f9401646e1b48fd91151117e0d5f432f2f4a Mon Sep 17 00:00:00 2001 From: KoKonuts Date: Thu, 31 Mar 2022 22:53:33 +0200 Subject: [PATCH 3/6] Reformat through precommit --- evap/staff/tools.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/evap/staff/tools.py b/evap/staff/tools.py index 8fd38e1ee9..8728374108 100644 --- a/evap/staff/tools.py +++ b/evap/staff/tools.py @@ -338,11 +338,11 @@ def find_unreviewed_evaluations(semester, excluded): return sorted( ( semester.evaluations.exclude(pk__in=excluded) - .exclude(state=Evaluation.State.PUBLISHED) - .exclude(vote_end_date__gte=exclude_date) - .exclude(can_publish_text_results=False) - .filter(contributions__textanswer_set__state=TextAnswer.State.NOT_REVIEWED) - .annotate(num_unreviewed_textanswers=Count("contributions__textanswer_set")) + .exclude(state=Evaluation.State.PUBLISHED) + .exclude(vote_end_date__gte=exclude_date) + .exclude(can_publish_text_results=False) + .filter(contributions__textanswer_set__state=TextAnswer.State.NOT_REVIEWED) + .annotate(num_unreviewed_textanswers=Count("contributions__textanswer_set")) ), key=lambda e: (-e.grading_process_is_finished, e.vote_end_date, -e.num_unreviewed_textanswers), ) From 2ac59e74fcf9f4f518d9566a54a9a8dafa472849 Mon Sep 17 00:00:00 2001 From: KoKonuts Date: Wed, 6 Apr 2022 11:36:09 +0200 Subject: [PATCH 4/6] Revert " Prioritize evaluations with finished grading for review" This reverts commit d88c2ecc1ef4bc0f55ca6279c96f6ad24905b1d9. --- evap/staff/views.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/evap/staff/views.py b/evap/staff/views.py index 8d02f1ae1a..977ea9050e 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -1491,13 +1491,7 @@ def evaluation_textanswers(request, semester_id, evaluation_id): request.session["review-visited"] = visited sections = evaluation_sections + contributor_sections - # Evaluations where the grading process is finished should be shown first, need to be sorted in Python - template_data.update( - dict( - sections=sections, - next_evaluations=sorted(next_evaluations, key=lambda e: e.grading_process_is_finished, reverse=True), - ) - ) + template_data.update(dict(sections=sections, next_evaluations=next_evaluations)) return render(request, "staff_evaluation_textanswers_quick.html", template_data) template_data.update(dict(evaluation_sections=evaluation_sections, contributor_sections=contributor_sections)) From cfef5f66ff8829281f253004f1a8eb29f856ee2c Mon Sep 17 00:00:00 2001 From: KoKonuts <89521080+PonderKoKo@users.noreply.github.com> Date: Thu, 7 Apr 2022 15:00:56 +0200 Subject: [PATCH 5/6] Rewrite adding textanswers in test_suggested_evaluation_ordering Co-authored-by: Richard Ebeling --- evap/staff/tests/test_views.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 1d3c0c8061..ada2c3531f 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -2293,18 +2293,9 @@ def test_suggested_evaluation_ordering(self): _quantity=2, ) - for i, evaluation in enumerate(evaluations): - evaluation.general_contribution.questionnaires.set([baker.make(Questionnaire, type=Questionnaire.Type.TOP)]) - question = baker.make(Question, type=Question.TEXT) - contribution = baker.make( - Contribution, - evaluation=evaluation, - contributor=baker.make(UserProfile), - questionnaires=[question.questionnaire], - ) - baker.make(TextAnswer, contribution=contribution, question=question, answer=self.answer) - if i == 1: - baker.make(TextAnswer, contribution=contribution, question=question, answer=self.answer) + for evaluation, answer_count in zip(evaluations, [1, 2]): + contribution = baker.make(Contribution, evaluation=evaluation, _fill_optional=["contributor"]) + baker.make(TextAnswer, contribution=contribution, question__type=Question.TEXT, _quantity=answer_count) url = f"/staff/semester/{self.semester.pk}/evaluation/{self.evaluation2.pk}/textanswers" From 299f1b2f81d7f76d41ca62976e144b0af77335ae Mon Sep 17 00:00:00 2001 From: KoKonuts Date: Thu, 14 Apr 2022 21:26:04 +0200 Subject: [PATCH 6/6] Use assertIn for test_suggested_evaluation_ordering --- evap/staff/tests/test_views.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index 1d3c0c8061..12c07e7ee0 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -2311,24 +2311,27 @@ def test_suggested_evaluation_ordering(self): with run_in_staff_mode(self): # Since Evaluation 1 has an extra text answer, it should be first page = self.app.get(url, user=self.manager) - self.assertTrue( - f'data-evaluation="{evaluations[1].pk}"' in str(page.html.select("span[data-next-evaluation-index]")[0]) + self.assertIn( + f'data-evaluation="{evaluations[1].pk}"', + str(page.html.select_one("span[data-next-evaluation-index]")), ) # Since Evaluation 0 has an earlier end date, it should now be first evaluations[0].vote_end_date = datetime.date.today() - datetime.timedelta(days=4) evaluations[0].save() page = self.app.get(url, user=self.manager) - self.assertTrue( - f'data-evaluation="{evaluations[0].pk}"' in str(page.html.select("span[data-next-evaluation-index]")[0]) + self.assertIn( + f'data-evaluation="{evaluations[0].pk}"', + str(page.html.select_one("span[data-next-evaluation-index]")), ) # Since the grading process for Evaluation 1 is finished, it should be first evaluations[1].wait_for_grade_upload_before_publishing = False evaluations[1].save() page = self.app.get(url, user=self.manager) - self.assertTrue( - f'data-evaluation="{evaluations[1].pk}"' in str(page.html.select("span[data-next-evaluation-index]")[0]) + self.assertIn( + f'data-evaluation="{evaluations[1].pk}"', + str(page.html.select_one("span[data-next-evaluation-index]")), ) def test_num_queries_is_constant(self):