🐛 Fix sorting for accented teams and organizations (#12505)

* 🐛 Fix sorting for accented teams and organizations

* 📎 Code review
This commit is contained in:
María Valderrama 2026-10-21 15:12:41 +02:00 committed by GitHub
parent d8862c759b
commit 338d009c1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 3 deletions

View File

@ -69,6 +69,18 @@
(nil? (dm/get-in team [:organization :id]))
(contains? #{"unlimited" "enterprise"} (get-subscription-type (:subscription team)))))
(def ^:private combining-marks-re (js/RegExp. "\\p{M}" "gu"))
(defn- name-sort-key
"Key that sorts `label` alphabetically regardless of case and
accents: NFD splits an accented letter into its base letter plus a
combining mark, and dropping the marks makes \"Ábaco\" sort like
\"abaco\" instead of after \"z\"."
[label]
(-> (.normalize label "NFD")
(str/replace combining-marks-re "")
(str/lower)))
(defn sort-organization-teams
"Orders the teams of a single organization for the dropdown's second
column: alphabetical, with the organization's default team
@ -76,7 +88,7 @@
`:is-default` and an explicit `false` into one comparator value."
[teams]
(sort-by (juxt (fn [team] (boolean (:is-default team)))
(fn [team] (str/lower (:name team ""))))
(fn [team] (name-sort-key (:name team ""))))
teams))
(defn sort-all-teams
@ -89,7 +101,7 @@
(sort-all-teams teams team-display-name))
([teams display-name]
(sort-by (juxt (fn [team] (boolean (:is-default team)))
(comp str/lower display-name))
(comp name-sort-key display-name))
teams)))
(defn teams-for-organization
@ -113,7 +125,7 @@
stable."
[organizations]
(sort-by (juxt (fn [organization] (if (nil? (:id organization)) 1 0))
(fn [organization] (str/lower (:name organization "")))
(fn [organization] (name-sort-key (:name organization "")))
:id)
organizations))

View File

@ -46,6 +46,26 @@
(t/is (= ["org-a" "org-b" "org-c" nil]
(map :id (dts/sort-organizations organizations))))))
(t/deftest names-starting-with-an-accented-letter-sort-as-the-plain-letter
;; A code-point comparison would push "Ábaco", "Órbita" and "Ámbar"
;; after "z"; accented letters must sort like their base letter.
(let [organizations [{:id "org-1" :name "OrgA"}
nil
{:id "org-2" :name "Órbita"}
{:id "org-3" :name "beta"}
{:id "org-4" :name "Ábaco"}]
teams [{:id "t1" :name "zeta"}
{:id "t2" :name "Personal projects" :is-default true}
{:id "t3" :name "apricot"}
{:id "t4" :name "Ámbar"}]
display-name (fn [team] (if (:is-default team) "Personal projects" (:name team)))]
(t/is (= ["Ábaco" "beta" "Órbita" "OrgA" nil]
(map :name (dts/sort-organizations organizations))))
(t/is (= ["Ámbar" "apricot" "zeta" "Personal projects"]
(map :name (dts/sort-organization-teams teams))))
(t/is (= ["Ámbar" "apricot" "zeta" "Personal projects"]
(map :name (dts/sort-all-teams teams display-name))))))
(t/deftest closed-control-line-2-matrix
(t/testing "profile with organizations, destination has an organization"
(t/is (= "Org A"