All updates
QAFrontend

Smoother Move-to-Processing assignment, sidebar/page stability fixes, and consistent column sorting

PR #919pixbox-supportMar 29, 2026 · 23:01 UTC
QAMar 29, 2026

Executive summary

A batch of three fixes promoted to QA across the Mail, Admin, and Vendor portals. When a user moves an unassigned mail item to Processing, the system now automatically prompts them to assign an owner and completes the move in one step. Separately, several pages were hardened against an intermittent load-time crash, and table column sorting now behaves consistently (ascending, descending, then back to unsorted) across all grids.

Why this was needed

Three independent problems were addressed. (1) Moving a single mail item to Processing failed silently with only an error toast when the item had no assigned owner — unlike the bulk action, which already guided users to assign someone. (2) Navigation menus and several pages built their icons at module-load time, which could trigger a render crash (React.createElement is not a function) during server-side rendering on page load. (3) Some grid columns that the table library treated as numeric skipped the "clear sort" step, so users could only toggle ascending/descending and never return to the default order.

Client / user impact

  • Mail operators: "Move to Processing" from a row action or the sidebar now opens the Assign User modal for unassigned mail, assigns the owner, and completes the transition together — matching the bulk experience and removing a dead-end error.
  • All portal users: Fewer intermittent blank-page or crash-on-load incidents across Admin, Vendor, and Mail navigation and several screens.
  • Anyone using data tables: Clicking a column header reliably cycles unsorted → ascending → descending → unsorted, so the original order can always be restored.

Technical scope

  • Assign-user flow (apps/mail/.../MailContents.tsx): Added an onError handler to the single-mail handleStatusChange. It detects an assignment-required error via three paths mirrored from the bulk handler (error code === ASSIGNMENT_REQUIRED, string details, or message substring match), then opens the existing BulkAssignUserModal and stores the failed item id + target status so assignment and the status transition complete in one call. Existing error toasts are not duplicated.
  • SSR hardening: Replaced module-level JSX icons (e.g. icon: <Shield />) with component references (Icon: Shield + iconClassName) so JSX is only created inside render functions. Touched constants and consumers across Admin (admin-nav, administration/page, AdminSidebar, AdminNavGroup, AdminNavItem), Mail (constants/index, confirmation-propmt, ActivityLogTab, app-sidebar.utils), and Vendor (vendor-nav, VendorSidebar).
  • Sort reset (apps/mail/.../data-grid.tsx): Set sortDescFirst: false and enableSortingRemoval: true at the table level to force a consistent none→asc→desc→none cycle for every column.

Risk & mitigation

Low overall. The icon refactor is broad (13 files) but mechanical — it changes how icons are constructed, not which icons appear, so the main risk is a missed icon rendering blank; visual checks of all navigation menus and dialogs cover this. The sort-cycle change applies to every DataGrid column, including any previously relying on descending-first behavior. The assign-user error handling reuses the already-proven bulk path, limiting new logic.

QA validation focus

  • From a mail row action and from the sidebar, move an unassigned mail to Processing: the Assign User modal should open, and assigning a user should complete the move automatically.
  • Move an already-assigned mail: it should transition with no modal.
  • Confirm bulk "Move to Processing" still behaves as before, and that no duplicate error toasts appear.
  • Load Admin, Vendor, and Mail pages (especially navigation sidebars, the administration page, confirmation dialogs, and the activity log) and verify all icons render with no crash or blank screen.
  • On data grids (including the Notes column on /batches), click a header three times and confirm the cycle ascending → descending → unsorted.