Skip to content

feat(tracking-page): organization settings for the customer tracking page - #355

Open
roncodes wants to merge 2 commits into
mainfrom
feature/tracking-page-settings
Open

roncodes wants to merge 2 commits into
mainfrom
feature/tracking-page-settings

Conversation

@roncodes

@roncodes roncodes commented Oct 6, 2026

Copy link
Copy Markdown
Member

PR 2 of the customer tracking pages refactor. It adds the settings backend for a company's tracking page. The settings screen (PR 4) and the public pages (PRs 3 and 5) read this config.

What's stored

Company setting tracking-page, always sanitized to a fixed shape by TrackingPageConfig::sanitize():

Group Keys (defaults)
org_page enabled (off), slug (company name, slugified)
generic_page allowed (on)
links target: auto | org | generic (auto)
branding display_name, logo_uuid, accent (#1F5FA8 or the instance default), accent_dark, support_phone, support_email, website, powered_by (on), theme (system | light), default_locale, locales (all 10)
access public_status (on), channels.sms/email (on), session_hours (24, range 1–168), account_sign_in (on), account_upsell (on)
visibility map, driver_name, vehicle, items, pod_photo, pod_signature, report_problem (on); item_prices, instructions_edit (off); driver_contact (company)

Instance-wide defaults for the generic page are stored in the system setting fleet-ops.tracking-page (generic_page.enabled and branding fallbacks).

Privacy rules are deliberately not settings: the map and driver hide after delivery, and the driver shows only while en route to the viewer's stops.

Endpoints (fleet-ops/settings/…)

  • GET / POST tracking-page-settings: the config, plus the read-back the screen needs:
    • slug_validation;
    • accent_ink and accent_contrast;
    • sms_available: Twilio counts only with credentials, because getAvailableProviders() always reports it;
    • customer_portal_installed;
    • the admin defaults.
  • POST tracking-page-settings/validate-slug: the live check while typing.
  • GET / POST admin-tracking-page-settings: admin only.

Permissions: update tracking-page-settings for save and the slug check, and view tracking-page-settings for read. They come from a new resource in the FleetOps auth schema.

Slugs

  • 3 to 40 lowercase letters, digits and single hyphens, with a reserved list (track, admin, api, customer-portal, …).
  • A saved valid slug is indexed at fleet-ops.tracking-page-slugs.{slug} → company uuid, so the public page resolves a company in one read rather than scanning every company's settings. Changing the slug frees the old index entry, but only if it still points at this company.
  • An enabled organization page refuses an invalid, reserved or taken slug with 422. While the page is disabled, the slug is saved but not indexed.

Tests

TrackingPageSettingsTest covers:

  • defaults, sanitizing of every field type, and fallbacks;
  • admin defaults;
  • slug rules and slugify;
  • contrast and ink;
  • the read-back facts;
  • slug indexing and freeing;
  • refusals for taken, reserved and invalid slugs;
  • the live check;
  • admin save and read.

The two seams that read the live environment (the SMS provider list and installed extensions) are marked @codeCoverageIgnore; tests replace them.

Depends on nothing. Plan: https://claude.ai/artifact/6Cd4e5QYiraFM3vjoakbyM

…page

Add the settings backend for the customer tracking page refactor (PR 2):

- TrackingPageConfig: the company config's shape, defaults and sanitizing
  (pages, branding, access, what verified visitors see), instance defaults
  for the generic page, slug rules with a reserved list, and accent contrast
  helpers (ink colour and WCAG ratio).
- SettingController: get/save tracking-page-settings, a live slug check, and
  admin defaults. Saved slugs are indexed in fleet-ops.tracking-page-slugs.*
  so the public page resolves a company in one read; an enabled organization
  page refuses an invalid, reserved or taken slug. The read-back includes the
  slug status, the accent's ink and contrast, whether SMS is configured
  (Twilio counts only with credentials), and whether the customer portal is
  installed.
- Routes under settings/, and a tracking-page-settings permission resource.
filter_var(null, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) returns
false, not null, so every unset toggle (generic page allowed, powered by, the
visibility defaults) came out false instead of its default.
@codecov

codecov Bot commented Oct 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (9ba5d0d) to head (cab38a6).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##                main      #355    +/-   ##
============================================
  Coverage     100.00%   100.00%            
- Complexity     12379     12452    +73     
============================================
  Files            600       601     +1     
  Lines          46496     46696   +200     
============================================
+ Hits           46496     46696   +200     
Flag Coverage Δ
backend 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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