-
Notifications
You must be signed in to change notification settings - Fork 146
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
Customizable evaluation results filters #2232
base: main
Are you sure you want to change the base?
Conversation
0127464
to
ca11745
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- looks good, most parts work as expected
- tests not reviewed yet
9bd5cea
to
8aaee00
Compare
e77a156
to
73c3a65
Compare
…py müssen wir uns nochmal anschauen, da failed noch ein test
…est_tools zusammengeführt, jetzt alles clean
…aber jetzt geht wieder
made the can_see_general_textanswers and the contributor counterpart also consider the represtened users
make difference between remove_textanswers_that_the_user_must_not_see and can_textanswer_be_seen_by clearer for the future
when users cannot or should not click specific textanswer buttons (because it does not make sense) they should still be there for consistency but should be disabled
Co-authored-by: Yannik <[email protected]>
implemented smaller changes that were quested in PR. - removed comments - itereated over enums directly - changed the name in this itereation from con_view to contributor_view (same for gen_view) - correclty formatted HTML comment - made things that should be in one line to be in one line - implemented variables for reused expected answers (on method and instance level) in test_views.py Co-authored-by: Yannik <[email protected]>
showing a tooltip with title is not possible since the tag has the disabled class and therefore does not accept any mouse events. Also: formatted code. Co-authored-by: Yannik <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some last comments from me :)
Removed tooltip from individual buttons and added a big one on label of the results button groups, since it is not simply possible to show a tooltip on a disabled button. Co-authored-by: Yannik <[email protected]>
Test seems to be deleted by accident. Added it again.
should (maybe?) be a lil faster. But was recommend so here.
This uses the db to check if one of the represented users is a responsible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nice, want have.
(After changing these little things)
I just realised that when I use the contributor and go in a contribution where I dont have general_textanswers rights but can edit change the contributor settings that the value for the view_general_results parameter is not set correctly. Why is that? @janno42 |
removed tooltips and changed some labels
Probably because you don't set the value and in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks mostly good
<div class="col-auto"> | ||
<div class="btn-switch btn-switch-light my-auto d-print-none"> | ||
<div class="btn-switch-label">{% translate 'View' %}</div> | ||
<div class="btn-switch btn-group"> | ||
{% if user.is_staff and view == 'export' or is_contributor %} | ||
<a | ||
href="{% if is_contributor %}{% url 'results:evaluation_detail' evaluation.course.semester.id evaluation.id %}?view=export{% endif %}" | ||
role="button" | ||
class="btn btn-sm btn-light{% if view == 'export' %} active{% endif %}" | ||
data-bs-toggle="tooltip" | ||
data-bs-placement="bottom" | ||
title="{% blocktranslate %}Shows filtered view meant for personal export. Other contributors' results and private answers are hidden.{% endblocktranslate %}" | ||
> | ||
{% translate 'Export' context 'view mode' %} | ||
</a> | ||
|
||
{% endif %} | ||
<a | ||
href="{% url 'results:evaluation_detail' evaluation.course.semester.id evaluation.id %}?view=full" | ||
role="button" | ||
class="btn btn-sm btn-light{% if view == 'full' %} active{% endif %}" | ||
data-bs-toggle="tooltip" | ||
data-bs-placement="bottom" | ||
title="{% translate 'Shows all results available for you.' %}" | ||
> | ||
{% translate 'Full' %} | ||
</a> | ||
{% if not evaluation.can_publish_rating_results %} | ||
<button | ||
type="button" | ||
disabled | ||
class="btn btn-sm btn-light" | ||
data-bs-toggle="tooltip" | ||
data-bs-placement="bottom" | ||
title="{% blocktranslate %}The results of this evaluation have not been published because it didn't get enough votes.{% endblocktranslate %}" | ||
> | ||
{% if evaluation.course.is_private %} | ||
{% translate 'Participant' %} | ||
{% else %} | ||
{% translate 'Public' %} | ||
{% endif %} | ||
</button> | ||
{% else %} | ||
<a | ||
href="{% url 'results:evaluation_detail' evaluation.course.semester.id evaluation.id %}?view=public" | ||
role="button" | ||
class="btn btn-sm btn-light{% if view == 'public' %} active{% endif %}" | ||
data-bs-toggle="tooltip" | ||
data-bs-placement="bottom" | ||
title=" | ||
{% if evaluation.course.is_private %} | ||
{% translate 'Shows results available for the participants.' %}" | ||
> | ||
{% translate 'Participant' %} | ||
{% else %} | ||
{% translate 'Shows results available for everyone logged in.' %}" | ||
> | ||
{% translate 'Public' %} | ||
{% endif %} | ||
</a> | ||
{% endif %} | ||
<div class="row"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second line is indented too far here
@@ -21,7 +21,7 @@ | |||
{% if evaluation.state != evaluation.State.PUBLISHED %} | |||
<div class="alert alert-warning">{% translate 'This is a preview. The results have not been published yet.' %}</div> | |||
{% endif %} | |||
|
|||
{# manager is automatically a reviewer (so these are all groups that can see the buttons) #} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{# manager is automatically a reviewer (so these are all groups that can see the buttons) #} |
page_with_ratings_general_get_parameter = self.app.get( | ||
self.url + "?view_contributor_results=ratings", user=self.manager | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean this?
page_with_ratings_general_get_parameter = self.app.get( | |
self.url + "?view_contributor_results=ratings", user=self.manager | |
) | |
page_with_ratings_contributor_get_parameter = self.app.get( | |
self.url + "?view_contributor_results=ratings", user=self.manager | |
) |
self.assertNotIn(".responsible_contributor_orig_notreviewed.", page) | ||
self.assertIn(".responsible_contributor_additional_orig_published.", page) | ||
self.assertNotIn(".responsible_contributor_additional_orig_hidden.", page) | ||
def helper_test_general(self, user, view_general_results, expected_visible_textanswers): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can refactor this to merge the two helper_test_*
methods:
from itertools import product
def check_with_view(
self,
user,
all_textanswers,
expected_visible_textanswers,
general=ViewGeneralResults,
contributor=ViewContributorResults,
):
textanswers_not_in = list(set(all_textanswers) - set(expected_visible_textanswers))
for general_view, contributor_view in product(general, contributor):
page = self.app.get(
f"/results/semester/1/evaluation/1?view_general_results={general_view.value}&view_contributor_results={contributor_view.value}",
user=user,
)
for answer in expected_visible_textanswers:
self.assertIn(answer, page)
for answer in textanswers_not_in:
self.assertNotIn(answer, page)
The above checks all combinations of the given general
and contributor
views, and the arguments each default to checking all variants. You can still have helper_test_general
and helper_test_contributor
, but let them use check_with_view
so that their logic is not duplicated. Maybe this would even be a way to shorten some parts like the following?
self.helper_test_general(user, ViewGeneralResults.FULL, [])
self.helper_test_general(user, ViewGeneralResults.RATINGS, [])
self.helper_test_contributor(user, ViewContributorResults.FULL, [])
self.helper_test_contributor(user, ViewContributorResults.RATINGS, [])
self.helper_test_contributor(user, ViewContributorResults.PERSONAL, [])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular, the case "person sees nothing" seems to be checked a couple of times
self.helper_test_contributor(user, ViewContributorResults.RATINGS, []) | ||
self.helper_test_contributor(user, ViewContributorResults.PERSONAL, []) | ||
|
||
user = "[email protected]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just assign this once at the beginning of the function
if view_contributor_results == ViewContributorResults.RATINGS: | ||
return False | ||
if user.is_reviewer: | ||
return True | ||
if ( | ||
view_contributor_results == ViewContributorResults.PERSONAL or textanswer.is_private | ||
): # private textanswers should only be seen by the contributor and reviewer | ||
return contributor == user | ||
if view_contributor_results == ViewContributorResults.FULL: | ||
# users can see textanswers if the contributor is one of their represented users (which includes the user itself) | ||
if contributor in represented_users: | ||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this a bit hard to understand, how do you feel about the following?
if view_contributor_results == ViewContributorResults.RATINGS: | |
return False | |
if user.is_reviewer: | |
return True | |
if ( | |
view_contributor_results == ViewContributorResults.PERSONAL or textanswer.is_private | |
): # private textanswers should only be seen by the contributor and reviewer | |
return contributor == user | |
if view_contributor_results == ViewContributorResults.FULL: | |
# users can see textanswers if the contributor is one of their represented users (which includes the user itself) | |
if contributor in represented_users: | |
return True | |
match view_contributor_results: | |
case ViewContributorResults.RATINGS: | |
return False | |
case ViewContributorResults.PERSONAL: | |
return user.is_reviewer or contributor == user | |
case ViewContributorResults.FULL: | |
if user.is_reviewer: | |
return True | |
if textanswer.is_private: | |
return user == contributor | |
return contributor in represented_users |
|
||
if textanswer.is_private: | ||
return contributor == user | ||
|
||
# NOTE: when changing this behavior, make sure all changes are also reflected in results.tools.textanswers_visible_to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So just to make sure: We checked that textanswers_visible_to
does not need any changes?
try: | ||
view_contributor_results = ViewContributorResults( | ||
request.GET.get("view_contributor_results", ViewContributorResults.FULL) | ||
) | ||
except ValueError as e: | ||
raise BadRequest from e | ||
|
||
try: | ||
view_general_results = ViewGeneralResults( | ||
request.GET.get( | ||
"view_general_results", | ||
ViewGeneralResults.FULL, | ||
) | ||
) | ||
except ValueError as e: | ||
raise BadRequest from e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can merge these two, and also the contributor
one below:
try: | |
view_contributor_results = ViewContributorResults( | |
request.GET.get("view_contributor_results", ViewContributorResults.FULL) | |
) | |
except ValueError as e: | |
raise BadRequest from e | |
try: | |
view_general_results = ViewGeneralResults( | |
request.GET.get( | |
"view_general_results", | |
ViewGeneralResults.FULL, | |
) | |
) | |
except ValueError as e: | |
raise BadRequest from e | |
try: | |
view_general_results = ViewGeneralResults(request.GET.get("view_general_results", ViewGeneralResults.FULL)) | |
view_contributor_results = ViewContributorResults( | |
request.GET.get("view_contributor_results", ViewContributorResults.FULL) | |
) | |
contributor = get_object_or_404(UserProfile, pk=request.GET.get("contributor_id", request.user.id)) | |
except ValueError as e: | |
raise BadRequest from e |
represented_users = [view_as_user] | ||
if view != "export": | ||
represented_users += list(view_as_user.represented_users.all()) | ||
# redirect to non-public view if there is none because the results have not been published | ||
if not evaluation.can_publish_rating_results and view == "public": | ||
view = "full" | ||
represented_users += list(view_as_user.represented_users.all()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two lines can just be represented_users = [view_as_user, *view_as_user.represented_users.all()]
if evaluation.is_user_contributor(view_as_user): | ||
contributor_personal = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just write contributor_personal = evaluation.is_user_contributor(view_as_user)
from the start
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: contributor_textanswers = view_as_user.is_reviewer or evaluation.user_is_contributor(view_as_user)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and for the third one:
contributor_textanswers = view_as_user.is_reviewer or evaluation.user_is_contributor(view_as_user)
contributor_personal = evaluation.is_user_contributor(view_as_user)
user_represents_responsible = any(user in represented_users for user in evaluation.course.responsibles.all())
user_represents_general_visibilty_contributor = any(
evaluation.is_user_contributor(user)
and evaluation.contributions.filter(
contributor=user,
textanswer_visibility=Contribution.TextAnswerVisibility.GENERAL_TEXTANSWERS,
).exists()
for user in represented_users
)
general_textanswers = (
view_as_user.is_reviewer or user_represents_responsible or user_represents_general_visibilty_contributor
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix #1786