Ensure lexical sort for org names (#1958)
Fixes #1955 Orgs list endpoint sorting now works as follows: - Default org is always sorted first - Name sorting now works on a lowercased version of the org names to ensure lexical sorting The lodash `sortBy` resorting of orgs in the "All Organizations" dropdown list in the nav bar has also been removed so that the backend sorting is applied instead. Tests have been updated accordingly.
This commit is contained in:
parent
8c0321bdea
commit
a02f7a6826
@ -204,7 +204,10 @@ class OrgOps:
|
||||
if not user.is_superuser:
|
||||
query[f"users.{user.id}"] = {"$gte": role.value}
|
||||
|
||||
aggregate: List[Dict[str, Any]] = [{"$match": query}]
|
||||
aggregate: List[Dict[str, Any]] = [
|
||||
{"$match": query},
|
||||
{"$set": {"nameLower": {"$toLower": "$name"}}},
|
||||
]
|
||||
|
||||
# Ensure default org is always first, then sort on sort_by if set
|
||||
sort_query = {"default": -1}
|
||||
@ -216,9 +219,13 @@ class OrgOps:
|
||||
if sort_direction not in (1, -1):
|
||||
raise HTTPException(status_code=400, detail="invalid_sort_direction")
|
||||
|
||||
# Do lexical sort of names
|
||||
if sort_by == "name":
|
||||
sort_by = "nameLower"
|
||||
|
||||
sort_query[sort_by] = sort_direction
|
||||
|
||||
aggregate.extend([{"$sort": sort_query}])
|
||||
aggregate.extend([{"$sort": sort_query}, {"$unset": ["nameLower"]}])
|
||||
|
||||
aggregate.extend(
|
||||
[
|
||||
|
@ -688,7 +688,7 @@ def test_sort_orgs(admin_auth_headers):
|
||||
r = requests.post(
|
||||
f"{API_PREFIX}/orgs/create",
|
||||
headers=admin_auth_headers,
|
||||
json={"name": "mno", "slug": "mno"},
|
||||
json={"name": "Mno", "slug": "mno"},
|
||||
)
|
||||
assert r.status_code == 200
|
||||
|
||||
@ -701,6 +701,7 @@ def test_sort_orgs(admin_auth_headers):
|
||||
|
||||
# Check default sorting
|
||||
# Default org should come first, followed by alphabetical sorting ascending
|
||||
# Ensure org names are sorted lexically, not by character code
|
||||
r = requests.get(f"{API_PREFIX}/orgs", headers=admin_auth_headers)
|
||||
data = r.json()
|
||||
orgs = data["items"]
|
||||
@ -711,9 +712,10 @@ def test_sort_orgs(admin_auth_headers):
|
||||
last_name = None
|
||||
for org in other_orgs:
|
||||
org_name = org["name"]
|
||||
org_name_lower = org_name.lower()
|
||||
if last_name:
|
||||
assert org_name > last_name
|
||||
last_name = org_name
|
||||
assert org_name_lower > last_name
|
||||
last_name = org_name_lower
|
||||
|
||||
# Sort by name descending, ensure default org still first
|
||||
r = requests.get(
|
||||
@ -728,6 +730,7 @@ def test_sort_orgs(admin_auth_headers):
|
||||
last_name = None
|
||||
for org in other_orgs:
|
||||
org_name = org["name"]
|
||||
org_name_lower = org_name.lower()
|
||||
if last_name:
|
||||
assert org_name < last_name
|
||||
last_name = org_name
|
||||
assert org_name_lower < last_name
|
||||
last_name = org_name_lower
|
||||
|
@ -4,7 +4,6 @@ import { nothing, render, type TemplateResult } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
import { when } from "lit/directives/when.js";
|
||||
import sortBy from "lodash/fp/sortBy";
|
||||
|
||||
import "broadcastchannel-polyfill";
|
||||
import "./utils/polyfills";
|
||||
@ -355,8 +354,6 @@ export class App extends LiteElement {
|
||||
const orgs = this.appState.userInfo?.orgs;
|
||||
if (!orgs || orgs.length < 2 || !this.appState.userInfo) return;
|
||||
|
||||
const sortedOrgs = sortBy<UserOrg>("name")(orgs);
|
||||
|
||||
const selectedOption = this.appState.orgSlug
|
||||
? orgs.find(({ slug }) => slug === this.appState.orgSlug)
|
||||
: { slug: "", name: msg("All Organizations") };
|
||||
@ -401,7 +398,7 @@ export class App extends LiteElement {
|
||||
<sl-divider></sl-divider>
|
||||
`,
|
||||
)}
|
||||
${sortedOrgs.map(
|
||||
${orgs.map(
|
||||
(org) => html`
|
||||
<sl-menu-item
|
||||
type="checkbox"
|
||||
|
Loading…
Reference in New Issue
Block a user