Skip to content

Commit cee393e

Browse files
authored
Change codelist sort order on user pages #3003
2 parents c6f1701 + 07cc480 commit cee393e

2 files changed

Lines changed: 105 additions & 10 deletions

File tree

opencodelists/tests/views/test_user.py

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ def test_user_codelists(
6969
for version in codelist["versions"]
7070
if version.is_draft
7171
] == [
72-
codelist.versions.first().id,
7372
organisation_codelist.versions.first().id,
73+
codelist.versions.first().id,
7474
]
7575

7676
# make org codelist under-review
@@ -144,3 +144,89 @@ def test_user_codelists(
144144
org_codelist_version_id,
145145
user_codelist_version_id,
146146
]
147+
148+
149+
def test_user_codelists_sort_user_first(
150+
client,
151+
user,
152+
organisation,
153+
codelist_from_scratch,
154+
user_codelist_from_scratch,
155+
):
156+
# Give both codelists the same name (case-insensitive), one user-owned and one org-owned
157+
update_codelist(
158+
codelist=user_codelist_from_scratch,
159+
owner=user,
160+
name="alpha list",
161+
slug="alpha-list-user",
162+
description=user_codelist_from_scratch.description,
163+
methodology=user_codelist_from_scratch.methodology,
164+
references={},
165+
signoffs={},
166+
)
167+
update_codelist(
168+
codelist=codelist_from_scratch,
169+
owner=organisation,
170+
name="ALPHA LIST",
171+
slug="alpha-list-org",
172+
description=codelist_from_scratch.description,
173+
methodology=codelist_from_scratch.methodology,
174+
references={},
175+
signoffs={},
176+
)
177+
178+
client.force_login(user)
179+
response = client.get(reverse("user", args=(user.username,)))
180+
181+
matching_codelists = [
182+
codelist["codelist"]
183+
for codelist in response.context["all_codelists"]
184+
if codelist["codelist"].name.casefold() == "alpha list"
185+
]
186+
assert [codelist.owner for codelist in matching_codelists] == [user, organisation]
187+
188+
189+
def test_published_codelists_sorted_same_as_all_codelists(
190+
client,
191+
user,
192+
user_codelist,
193+
user_codelist_from_scratch,
194+
):
195+
update_codelist(
196+
codelist=user_codelist,
197+
owner=user,
198+
name="zeta list",
199+
slug="zeta-list",
200+
description=user_codelist.description,
201+
methodology=user_codelist.methodology,
202+
references={},
203+
signoffs={},
204+
)
205+
update_codelist(
206+
codelist=user_codelist_from_scratch,
207+
owner=user,
208+
name="ALPHA LIST",
209+
slug="alpha-list",
210+
description=user_codelist_from_scratch.description,
211+
methodology=user_codelist_from_scratch.methodology,
212+
references={},
213+
signoffs={},
214+
)
215+
save_for_review(draft=user_codelist_from_scratch.versions.first())
216+
publish_version(version=user_codelist_from_scratch.versions.last())
217+
218+
client.force_login(user)
219+
response = client.get(reverse("user", args=(user.username,)))
220+
221+
codelist_ids = {user_codelist.id, user_codelist_from_scratch.id}
222+
all_codelist_ids = [
223+
codelist["codelist"].id
224+
for codelist in response.context["all_codelists"]
225+
if codelist["codelist"].id in codelist_ids
226+
]
227+
published_codelist_ids = [
228+
version.codelist.id
229+
for version in response.context["published_codelists"]
230+
if version.codelist.id in codelist_ids
231+
]
232+
assert published_codelist_ids == all_codelist_ids

opencodelists/views/user.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1+
from datetime import datetime
2+
13
from django.shortcuts import get_object_or_404, render
24

3-
from codelists.models import Status
5+
from codelists.models import Codelist, Status
46

57
from ..models import User
68

79

810
def user(request, username):
911
user = get_object_or_404(User, username=username)
1012

13+
def codelist_sort_key(codelist: Codelist) -> tuple[str, bool, str, datetime]:
14+
"""
15+
We sort by name, then owner, then date (all case-insensitive where applicable),
16+
while making sure the current user's codelists appear before organisation ones
17+
when names are the same.
18+
"""
19+
return (
20+
codelist.name.casefold(),
21+
codelist.owner != user,
22+
str(codelist.owner).casefold(),
23+
codelist.updated_at,
24+
)
25+
1126
# Find all of the codelists owned (in their current version) by this user with at least one published version.
1227
owned_codelists = user.codelists.filter(
1328
versions__status=Status.PUBLISHED
@@ -38,11 +53,7 @@ def user(request, username):
3853
else []
3954
),
4055
}
41-
for codelist in sorted(
42-
codelists_to_display, key=lambda x: (x.owner != user, str(x.owner), x.name)
43-
)
44-
# We sort first by owner, then by name - but making sure that the current user's
45-
# codelists always come first
56+
for codelist in sorted(codelists_to_display, key=codelist_sort_key)
4657
# We can't use a queryset order_by (where versions_under_review/drafts are querysets of CodelistVersion
4758
# instances), as a codelist can have multiple versions and multiple handles, and this results in duplicates
4859
# in the returned queryset. See https://code.djangoproject.com/ticket/18165
@@ -52,10 +63,8 @@ def user(request, username):
5263
"user": user,
5364
"published_codelists": [
5465
codelist.latest_published_version()
55-
for codelist in owned_codelists.order_by("handles__name")
66+
for codelist in sorted(owned_codelists, key=codelist_sort_key)
5667
],
57-
# note that name is a property on a codelist, not an attribute, and it comes from the current handle.
58-
# If we want to order codelists or versions by codelist name, we actually need to order them by handle name.
5968
"all_codelists": all_codelists,
6069
}
6170

0 commit comments

Comments
 (0)