Skip to content

refactor(sort): route alphabetical sorts through a shared comparator - #1169

Merged
JamieRuderman merged 5 commits into
mainfrom
refactor/shared-alpha-sort
Aug 3, 2026
Merged

refactor(sort): route alphabetical sorts through a shared comparator#1169
JamieRuderman merged 5 commits into
mainfrom
refactor/shared-alpha-sort

Conversation

@JamieRuderman

Copy link
Copy Markdown
Member

Stacked on #1167 — review that one first. GitHub will retarget this to main automatically when #1167 merges.

"Alphabetical" meant four different things across the UI. There were ~14 hand-rolled comparators in 12 files, in four flavors:

  • bare localeCompare (case-sensitive) — Tags, selectedHelper, selectors/tags
  • localeCompare with { sensitivity: 'base' }selectors/contacts
  • toLowerCase() with </>connections, search, SortServices, FilterDrawer, OrganizationSelect, OrganizationSelectList, NetworksPage
  • raw >/< on unnormalized strings — SharedUsersLists

Plus alphaEmailSort copy-pasted verbatim into OrganizationMemberList and OrganizationGuestList.

Changes

helpers/utilHelper.ts gains one shared comparator pair backed by a single Intl.Collator:

  • alphaSort(a, b) — for strings (emails, nodeName, nested fields)
  • byName(a, b) — for the common { name } object case, so most call sites become .sort(byName)

Every site above now routes through it, and the two private nameSorts plus both alphaEmailSort copies are deleted. Net -38/+43 lines across 15 files.

Behavior changes

This deliberately makes previously-inconsistent sorts agree, so some orderings shift:

  • numeric: true everywheredevice2 now sorts before device10 instead of after. This is the main visible change and the reason for the collator.
  • sensitivity: 'base' — case and accents no longer split otherwise-equal names. The toLowerCase() sites were already effectively case-insensitive; the bare-localeCompare sites (tags, device selection) change.
  • Two-way comparators now return 0 on equal. OrganizationSelect, OrganizationSelectList, FilterDrawer, and NetworksPage used ? 1 : -1, which never returns 0 and gives an unstable order for equal names. They're now stable.
  • SortServices ZTOA is byName(b, a) rather than a separately hand-written reversed comparator.

Testing

tsc --noEmit passes. Verified by grep that no localeCompare, toLowerCase() comparison, or raw name/email comparator remains in frontend/src. Not exercised in the running app — the sorts are visual, so a click through tags, networks, org member lists, and the service sort menu is worth doing before merge.

Base automatically changed from fix/sort-scripting-device-selection to main August 3, 2026 19:34
@JamieRuderman

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

dispatch.ui.set({ selected: sortSelectedIds(nextSelected, visibleDevices), selectionAnchor: deviceId })

P2 Badge Synchronize selections when the device sort changes

If the user selects multiple devices and then changes the sort in FilterDrawer, the fetched visibleDevices reorder but sortSelectedIds is not called because no selection click occurs, so state.ui.selected retains the previous order. ScriptRunPage maps selectedIds directly into resolvedDevices and submits that same array as form.deviceIds, meaning the displayed and submitted device order no longer matches the list sort this change promises to follow; derive the ordered selection when the list order changes rather than only inside handleSelect.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@JamieRuderman
JamieRuderman merged commit cd30caf into main Aug 3, 2026
6 checks passed
@JamieRuderman
JamieRuderman deleted the refactor/shared-alpha-sort branch August 3, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant