Skip to content
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
3,738 changes: 1,869 additions & 1,869 deletions evap/development/fixtures/test_data.json

Large diffs are not rendered by default.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just put this in one migration. Semantically, this is one operation.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Generated by Django 6.0.4 on 2026-04-13 20:21

from django.db import migrations, models


def rename_private_and_public_to_keep(apps, schema_editor): # pylint: disable=unused-argument
TextAnswer = apps.get_model("evaluation", "TextAnswer")
TextAnswer.objects.filter(review_decision="PR").update(review_decision="KE")
TextAnswer.objects.filter(review_decision="PU").update(review_decision="KE")


def reverse(apps, schema_editor): # pylint: disable=unused-argument
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call it rename_keep_to_public?

TextAnswer = apps.get_model("evaluation", "TextAnswer")
TextAnswer.objects.filter(review_decision="KE").update(review_decision="PU")


class Migration(migrations.Migration):
dependencies = [
("evaluation", "0163_migrate_cms_links"),
]

operations = [
migrations.RemoveConstraint(
model_name="textanswer",
name="TextAnswer_review_decision_choices",
),
migrations.AlterField(
model_name="textanswer",
name="review_decision",
field=models.CharField(
choices=[("KE", "keep"), ("DE", "deleted"), ("UN", "undecided")],
default="UN",
max_length=2,
verbose_name="review decision for the answer",
),
),
migrations.AddConstraint(
model_name="textanswer",
constraint=models.CheckConstraint(
condition=models.Q(("review_decision__in", ["KE", "DE", "UN"])),
name="TextAnswer_review_decision_choices",
),
),
migrations.RunPython(rename_private_and_public_to_keep, reverse_code=reverse),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to have this RunPython before the AddConstraint above?

]
21 changes: 3 additions & 18 deletions evap/evaluation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1628,8 +1628,7 @@ class ReviewDecision(models.TextChoices):
When publishing evaluation results, this answer should be ...
"""

PUBLIC = "PU", _("public")
PRIVATE = "PR", _("private") # This answer should only be displayed to the contributor the question was about
KEEP = "KE", _("keep")
DELETED = "DE", _("deleted")

UNDECIDED = "UN", _("undecided")
Expand Down Expand Up @@ -1660,22 +1659,8 @@ def will_be_deleted(self):
return self.review_decision == self.ReviewDecision.DELETED

@property
def will_be_private(self):
return self.review_decision == self.ReviewDecision.PRIVATE

@property
def will_be_public(self):
return self.review_decision == self.ReviewDecision.PUBLIC

# Once evaluation results are published, the review decision is executed
# and thus, an answer _is_ private or _is_ public from that point on.
@property
def is_public(self):
return self.will_be_public

@property
def is_private(self):
return self.will_be_private
def will_be_kept(self):
return self.review_decision == self.ReviewDecision.KEEP

@property
def is_reviewed(self):
Expand Down
15 changes: 7 additions & 8 deletions evap/evaluation/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,21 +381,20 @@ def test_textanswers_to_delete_get_deleted_on_publish(self):
assignment__question__type=QuestionType.TEXT,
assignment__questionnaire=questionnaire,
contribution=evaluation.general_contribution,
answer=iter(["deleted", "public", "private"]),
answer=iter(["deleted", "keep"]),
review_decision=iter(
[
TextAnswer.ReviewDecision.DELETED,
TextAnswer.ReviewDecision.PUBLIC,
TextAnswer.ReviewDecision.PRIVATE,
TextAnswer.ReviewDecision.KEEP,
]
),
_quantity=3,
_quantity=2,
_bulk_create=True,
)

self.assertEqual(evaluation.textanswer_set.count(), 3)
evaluation.publish()
self.assertEqual(evaluation.textanswer_set.count(), 2)
evaluation.publish()
self.assertEqual(evaluation.textanswer_set.count(), 1)
self.assertFalse(TextAnswer.objects.filter(answer="deleted").exists())

def test_original_textanswers_get_deleted_on_publish(self):
Expand All @@ -417,7 +416,7 @@ def test_original_textanswers_get_deleted_on_publish(self):
contribution=evaluation.general_contribution,
answer="published answer",
original_answer="original answer",
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)

self.assertEqual(evaluation.textanswer_set.count(), 1)
Expand Down Expand Up @@ -548,7 +547,7 @@ def test_textanswer_review_state(self):
evaluation.TextAnswerReviewState.REVIEW_URGENT, # grades were uploaded
)

textanswer.review_decision = TextAnswer.ReviewDecision.PUBLIC
textanswer.review_decision = TextAnswer.ReviewDecision.KEEP
textanswer.save()
del evaluation.num_reviewed_textanswers # reset cached_property cache

Expand Down
18 changes: 9 additions & 9 deletions evap/results/fixtures/minimal_test_data_results.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
"contribution": 1,
"answer": ".general_orig_published.",
"original_answer": null,
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -285,7 +285,7 @@
"contribution": 1,
"answer": ".general_changed_published.",
"original_answer": ".general_orig_published_changed.",
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -297,7 +297,7 @@
"contribution": 3,
"answer": ".contributor_orig_published.",
"original_answer": null,
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -309,7 +309,7 @@
"contribution": 3,
"answer": ".contributor_orig_private.",
"original_answer": null,
"review_decision": "PR",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -321,7 +321,7 @@
"contribution": 6,
"answer": ".responsible_contributor_orig_published.",
"original_answer": null,
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -345,7 +345,7 @@
"contribution": 6,
"answer": ".responsible_contributor_changed_published.",
"original_answer": ".responsible_contributor_orig_published_changed.",
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -357,7 +357,7 @@
"contribution": 6,
"answer": ".responsible_contributor_orig_private.",
"original_answer": null,
"review_decision": "PR",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -381,7 +381,7 @@
"contribution": 6,
"answer": ".responsible_contributor_additional_orig_published.",
"original_answer": null,
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand All @@ -405,7 +405,7 @@
"contribution": 1,
"answer": ".general_additional_orig_published.",
"original_answer": null,
"review_decision": "PU",
"review_decision": "KE",
"is_flagged": false
}
},
Expand Down
3 changes: 0 additions & 3 deletions evap/results/templates/textanswer_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
<ul>
{% for answer in question_result.answers %}
<li>
{% if answer.is_private %}
<span data-bs-toggle="tooltip" data-bs-placement="left" class="fas fa-circle-info d-print-none" title="{% translate 'This answer is only visible to you. Other contributors and your delegates cannot see it.' %}"></span>
{% endif %}
{{ answer.answer|linebreaksbr }}
</li>
{% endfor %}
Expand Down
2 changes: 1 addition & 1 deletion evap/results/tests/test_exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ def test_text_answer_export(self):
assignment=iter(assignments[idx] for idx in [0, 1, 2, 2, 0]),
contribution__evaluation=evaluation,
contribution__questionnaires=iter(assignments[idx].questionnaire for idx in [0, 1, 2, 2, 0]),
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
_quantity=5,
)

Expand Down
12 changes: 6 additions & 6 deletions evap/results/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,37 +536,37 @@ def setUpTestData(cls):
TextAnswer,
assignment=cls.assignment,
contribution=cls.general_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)
cls.responsible1_textanswer = baker.make(
TextAnswer,
assignment=cls.assignment,
contribution=cls.responsible1_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)
cls.responsible1_additional_textanswer = baker.make(
TextAnswer,
assignment=cls.assignment_likert,
contribution=cls.responsible1_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)
cls.responsible2_textanswer = baker.make(
TextAnswer,
assignment=cls.assignment,
contribution=cls.responsible2_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)
cls.contributor_own_textanswer = baker.make(
TextAnswer,
assignment=cls.assignment,
contribution=cls.contributor_own_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)
cls.contributor_general_textanswer = baker.make(
TextAnswer,
assignment=cls.assignment,
contribution=cls.contributor_general_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)

def test_text_answer_visible_to_non_contributing_responsible(self):
Expand Down
6 changes: 2 additions & 4 deletions evap/results/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def _get_results_impl(evaluation: Evaluation, *, refetch_related_objects: bool =
((textanswer.contribution_id, textanswer.assignment_id), textanswer)
for contribution in evaluation.contributions.all()
for textanswer in contribution.textanswer_set.all()
if textanswer.review_decision in [TextAnswer.ReviewDecision.PRIVATE, TextAnswer.ReviewDecision.PUBLIC]
if textanswer.review_decision == TextAnswer.ReviewDecision.KEEP
)

racs_per_contribution_assignment: dict[tuple[int, int], list[RatingAnswerCounter]] = unordered_groupby(
Expand Down Expand Up @@ -483,7 +483,7 @@ def can_textanswer_be_seen_by( # noqa: PLR0911,PLR0912
view_general_results: ViewGeneralResults,
view_contributor_results: ViewContributorResults,
) -> bool:
assert textanswer.review_decision in [TextAnswer.ReviewDecision.PRIVATE, TextAnswer.ReviewDecision.PUBLIC]
assert textanswer.review_decision == TextAnswer.ReviewDecision.KEEP
contributor = textanswer.contribution.contributor

# NOTE: when changing this behavior, make sure all changes are also reflected in results.tools.textanswers_visible_to
Expand All @@ -509,8 +509,6 @@ def can_textanswer_be_seen_by( # noqa: PLR0911,PLR0912
case ViewContributorResults.FULL:
if user.is_reviewer:
return True
if textanswer.is_private:
return user == contributor
return contributor in represented_users

return False
4 changes: 1 addition & 3 deletions evap/staff/templates/staff_evaluation_textanswers_quick.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,8 @@ <h5 class="modal-title" id="hotkeys-modal-title">Hotkeys</h5>
data-id="{{ answer.id }}"
{% if contributor %} data-contribution="yes"{% endif %}
{% if answer.is_reviewed %}
{% if answer.will_be_public %}
{% if answer.will_be_kept %}
data-review="publish"
{% elif answer.will_be_private %}
data-review="make_private"
{% else %}
data-review="delete"
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@
<input type="hidden" name="answer_id" value="{{ answer.id }}" />

<div class="btn-group btn-group-sm outline-fix" role="group">
<input type="radio" class="btn-check" name="action" value="publish" id="{{ answer.id }}-radio-publish" autocomplete="off" {% if answer.will_be_public %}checked{% endif %}>
<input type="radio" class="btn-check" name="action" value="publish" id="{{ answer.id }}-radio-publish" autocomplete="off" {% if answer.will_be_kept %}checked{% endif %}>
<label class="btn btn-outline-primary" for="{{ answer.id }}-radio-publish">{% translate 'Publish' %}</label>

<input type="radio" class="btn-check" name="action" value="make_private" id="{{ answer.id }}-radio-private" autocomplete="off" {% if answer.will_be_private %}checked{% endif %} {% if not contributor %}disabled{% endif %}>
<label class="btn btn-outline-primary" for="{{ answer.id }}-radio-private">{% translate 'Private' %}</label>

<input type="radio" class="btn-check" name="action" value="unreview" id="{{ answer.id }}-radio-undecided" autocomplete="off" {% if not answer.is_reviewed %}checked{% endif %}>
<label class="btn btn-outline-primary" for="{{ answer.id }}-radio-undecided">{% translate 'Undecided' %}</label>

Expand Down
15 changes: 7 additions & 8 deletions evap/staff/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ def test_success_with_data(self):
baker.make(
TextAnswer,
contribution=evaluation.general_contribution,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)

self.instance.archive()
Expand Down Expand Up @@ -2858,7 +2858,7 @@ def setUpTestData(cls):
contribution=contribution,
assignment=assignment,
answer=cls.reviewed_answer,
review_decision=TextAnswer.ReviewDecision.PUBLIC,
review_decision=TextAnswer.ReviewDecision.KEEP,
)

cls.evaluation2 = baker.make(
Expand Down Expand Up @@ -3839,10 +3839,9 @@ def test_review_actions(self):
let_user_vote_for_evaluation(self.student2, self.evaluation)

# now reviewing should work
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.PUBLIC)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.KEEP)
self.assert_transition("delete", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.DELETED)
self.assert_transition("make_private", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.PRIVATE)
self.assert_transition("unreview", TextAnswer.ReviewDecision.PUBLIC, TextAnswer.ReviewDecision.UNDECIDED)
self.assert_transition("unreview", TextAnswer.ReviewDecision.KEEP, TextAnswer.ReviewDecision.UNDECIDED)

# textanswer_edit action should not change the state, but give a link to edit page
response = self.assert_transition(
Expand Down Expand Up @@ -3871,7 +3870,7 @@ def test_finishing_review_updates_results(self):
self.assertEqual(len(textresult.answers), 0)

textanswer = self.evaluation.unreviewed_textanswer_set[0]
textanswer.review_decision = TextAnswer.ReviewDecision.PUBLIC
textanswer.review_decision = TextAnswer.ReviewDecision.KEEP
textanswer.save()
self.evaluation.end_review()
self.evaluation.save()
Expand All @@ -3884,13 +3883,13 @@ def test_finishing_review_updates_results(self):

def test_published(self):
let_user_vote_for_evaluation(self.student2, self.evaluation)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.PUBLIC)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.KEEP)
Evaluation.objects.filter(id=self.evaluation.id).update(state=Evaluation.State.PUBLISHED)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, status=403)

def test_archived(self):
let_user_vote_for_evaluation(self.student2, self.evaluation)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.PUBLIC)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, TextAnswer.ReviewDecision.KEEP)
Semester.objects.filter(id=self.evaluation.course.semester.id).update(results_are_archived=True)
self.assert_transition("publish", TextAnswer.ReviewDecision.UNDECIDED, status=403)

Expand Down
3 changes: 1 addition & 2 deletions evap/staff/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1744,8 +1744,7 @@ def evaluation_textanswers_update_publish(request):
return redirect("staff:evaluation_textanswer_edit", answer.pk)

review_decision_for_action = {
"publish": TextAnswer.ReviewDecision.PUBLIC,
"make_private": TextAnswer.ReviewDecision.PRIVATE,
"publish": TextAnswer.ReviewDecision.KEEP,
"delete": TextAnswer.ReviewDecision.DELETED,
"unreview": TextAnswer.ReviewDecision.UNDECIDED,
}
Expand Down