refactor: consolidate duplicated helpers and envelope types #121

Merged
David merged 1 commit from refactor/mapps-140-consolidate-helpers into main 2026-06-13 13:38:04 +02:00
Owner

One canonical implementation per concept, removing the copy-paste drift seedbed flagged in the too-many-cooks audit.

Move urlencoding_minimal to src/utils/url.rs and import it in all five former copies (company_picker, contacts, audit_log, knowledge_base, contracts).

Add one shared client decode envelope crate::utils::Paginated<T> (with #[serde(default)] meta) and delete the divergent per-page / per-module re-declarations: modules/audit::Paginated, modules/sla::SlaPaginated, and the generic Paginated<T> in dashboard, projects, time, assets, knowledge_base, tickets, contracts, and billing, plus the named PaginatedTickets. data uses default = "Vec::new" so the envelope stays generic over non-Default row types.

Add UserRole::parse_role(&str) -> UserRole as the single canonical role parser and route the auth_callback site through it, dropping its partial inline match that omitted super_admin/dispatcher/sales.

Change AuthContext::has_role (and use_require_role) to take UserRole instead of a stringly comparison, matching AuthState::has_role.

Rename the three domain-specific humanize_status functions to humanize_ticket_status, humanize_tenant_status, and humanize_contract_status so they no longer share a name that invites drift.

Extract ticket_status_badge(&str) -> BadgeVariant into components::table and route the dashboard, ticket-list, and portal ticket tables through it; the canonical mapping includes the closed arm the divergent copies missed.

Remove the private CompanyAddress in contacts in favor of the module Address, restoring access to its formatted/is_empty helpers.

Define default_true once in crate::utils and point every #[serde(default = "...")] at it, deleting the five model-local copies and the onboarding copy.

Add month_name to crate::utils::datetime and import it in the calendar and timesheet pages.

Add a real PortalUserMenu (avatar dropdown with Account Settings + Logout) to PortalLayout, which previously showed a bare icon with no way to sign out.

#MAPPS-140

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

One canonical implementation per concept, removing the copy-paste drift seedbed flagged in the too-many-cooks audit. Move `urlencoding_minimal` to `src/utils/url.rs` and import it in all five former copies (company_picker, contacts, audit_log, knowledge_base, contracts). Add one shared client decode envelope `crate::utils::Paginated<T>` (with `#[serde(default)]` meta) and delete the divergent per-page / per-module re-declarations: `modules/audit::Paginated`, `modules/sla::SlaPaginated`, and the generic `Paginated<T>` in dashboard, projects, time, assets, knowledge_base, tickets, contracts, and billing, plus the named `PaginatedTickets`. `data` uses `default = "Vec::new"` so the envelope stays generic over non-`Default` row types. Add `UserRole::parse_role(&str) -> UserRole` as the single canonical role parser and route the `auth_callback` site through it, dropping its partial inline match that omitted super_admin/dispatcher/sales. Change `AuthContext::has_role` (and `use_require_role`) to take `UserRole` instead of a stringly comparison, matching `AuthState::has_role`. Rename the three domain-specific `humanize_status` functions to `humanize_ticket_status`, `humanize_tenant_status`, and `humanize_contract_status` so they no longer share a name that invites drift. Extract `ticket_status_badge(&str) -> BadgeVariant` into `components::table` and route the dashboard, ticket-list, and portal ticket tables through it; the canonical mapping includes the `closed` arm the divergent copies missed. Remove the private `CompanyAddress` in `contacts` in favor of the module `Address`, restoring access to its `formatted`/`is_empty` helpers. Define `default_true` once in `crate::utils` and point every `#[serde(default = "...")]` at it, deleting the five model-local copies and the onboarding copy. Add `month_name` to `crate::utils::datetime` and import it in the calendar and timesheet pages. Add a real `PortalUserMenu` (avatar dropdown with Account Settings + Logout) to `PortalLayout`, which previously showed a bare icon with no way to sign out. #MAPPS-140 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
refactor: consolidate duplicated helpers and envelope types
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 2m1s
Create release / Create release from merged PR (pull_request) Has been skipped
ab903b6082
One canonical implementation per concept, removing the copy-paste drift seedbed flagged in the too-many-cooks audit.

Move `urlencoding_minimal` to `src/utils/url.rs` and import it in all five former copies (company_picker, contacts, audit_log, knowledge_base, contracts).

Add one shared client decode envelope `crate::utils::Paginated<T>` (with `#[serde(default)]` meta) and delete the divergent per-page / per-module re-declarations: `modules/audit::Paginated`, `modules/sla::SlaPaginated`, and the generic `Paginated<T>` in dashboard, projects, time, assets, knowledge_base, tickets, contracts, and billing, plus the named `PaginatedTickets`. `data` uses `default = "Vec::new"` so the envelope stays generic over non-`Default` row types.

Add `UserRole::parse_role(&str) -> UserRole` as the single canonical role parser and route the `auth_callback` site through it, dropping its partial inline match that omitted super_admin/dispatcher/sales.

Change `AuthContext::has_role` (and `use_require_role`) to take `UserRole` instead of a stringly comparison, matching `AuthState::has_role`.

Rename the three domain-specific `humanize_status` functions to `humanize_ticket_status`, `humanize_tenant_status`, and `humanize_contract_status` so they no longer share a name that invites drift.

Extract `ticket_status_badge(&str) -> BadgeVariant` into `components::table` and route the dashboard, ticket-list, and portal ticket tables through it; the canonical mapping includes the `closed` arm the divergent copies missed.

Remove the private `CompanyAddress` in `contacts` in favor of the module `Address`, restoring access to its `formatted`/`is_empty` helpers.

Define `default_true` once in `crate::utils` and point every `#[serde(default = "...")]` at it, deleting the five model-local copies and the onboarding copy.

Add `month_name` to `crate::utils::datetime` and import it in the calendar and timesheet pages.

Add a real `PortalUserMenu` (avatar dropdown with Account Settings + Logout) to `PortalLayout`, which previously showed a bare icon with no way to sign out.

#MAPPS-140

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
David merged commit fb2747f7d7 into main 2026-06-13 13:38:04 +02:00
David deleted branch refactor/mapps-140-consolidate-helpers 2026-06-13 13:38:04 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
psa-systems/mokosh-apps!121
No description provided.