Repository navigation
Resource identity system: pills, one-line identity cells, hover summaries and select options - #324
Conversation
One descriptor per resource: how it is titled and identified (never by UUID), its photo or icon tile, its online flag and status with the tone map the old identity cells carried, the badges an identity cell shows on its line, the details a select option lists, the facts a hover summary shows, and how it opens: the action service's context panel where one exists, a route transition for inspections and fuel integrations, the entity modal, or nothing for warranties, manifests and recurring schedules. All 67 fleetops-data models are covered: 34 first-class resources, 16 sub-records that delegate opening to their parent (or do not open), 13 polymorphic subtypes registered as aliases of their concrete resource, and the attachable, facilitator and maintenance-subject bases, which resolve the concrete descriptor from the record or its *_type attribute and delegate. Parts and work orders hydrate their fitted asset and linked schedule lazily, on hover only. The engine instance-initializer registers them through the resource-registry service ember-ui 0.4.1 provides, so no ember-ui module is imported; a host on an older ember-ui has no such service and the identity components fall back to text.
…t option Template-only wrappers over the ember-ui bases, one set per descriptor key: <key>/pill and <key>/summary, cell/<key>-identity and select-option/<key>, plus the attachable, facilitator and maintenance-subject dispatchers, which resolve the concrete resource through their descriptor. The existing vehicle, driver, trailer, device, equipment, order and inspection-submission pills keep their named arguments but now render through Resource::Pill, so they open the record and show its summary on hover; the vehicle tooltip and the order QR body live in the summaries. The vehicle, driver, device, equipment and part identity cells drop their JS: their tone maps moved into the descriptors. select-option/user and the select-option base are gone because ember-ui provides them.
driverActions.panel.view took the argument as a record, so a table cell that only had a driver_name stub, or a proxy from an async relation, opened a panel with nothing in it. Resolve thenables and loadResource() stubs first, as vehicleActions and trailerActions already do.
Every related-record column now renders the resource's identity cell: vehicles (driver, vendor), drivers (vehicle, vendor), trailers (name as a trailer, towing vehicle, vendor), fleets (service area, parent fleet, vendor, zone), fuel reports (reporter, driver, vehicle), fuel transactions (vehicle, fuel report), issues (reporter, assignee, driver, vehicle), contacts, customers and vendors (address as its place), orders (payload, driver, vehicle, customer, facilitator, pickup, dropoff, created and updated by), service rates (service area, zone), connectivity events, sensors and telematics (device, provider), the device table columns (device, attached asset, provider), inspection submissions (form, vehicle, driver), maintenances (asset, performed by), schedules (subject, default assignee), work orders (target, assignee), payments (service quote, order, customer) and the map drawer listings (driver, current job, vehicle). Rows that only carry a *_name build an identity stub with buildIdentityStub, which keeps UUIDs out of identifier fields and shares one in-flight load per row, and read async relations through relation-value so a promise proxy never passes for a record. Columns drop the compact, showStatus and showStatusBadge keys the new cell ignores, and the vehicles and trailers vendor columns open the vendor panel instead of calling a viewVendor that never existed. The four multi-model filters use ember-ui's filter/model-multiple.
The work order carries only schedule_uuid and the model has no relation to it, so the "Linked Schedule" field never rendered. Peek the store for the schedule, then fetch it, and keep it on the component.
The panel header fell back to attachable_uuid when nothing else named the asset, which put a UUID in the chip.
A part carries asset_type and asset_uuid with no relation, so the field could only echo asset_name. Resolve the type through the resource registry and fetch the record, so the field can show the asset's pill.
Every detail field that names another record renders that record's pill, which opens it and shows its summary on hover: vehicle (driver, and a new attached-trailer field), driver (vendor, assigned vehicle), fuel report (reporter, driver, vehicle), order (customer and facilitator, which are polymorphic), trailer (category, towing vehicle, vendor, warranty), work order (target, assignee, linked schedule), maintenance (asset, performed by, work order), maintenance schedule (subject, default assignee), equipment (equipped to, warranty), part (fitted to, vendor, warranty), sensor (device, warranty), device (warranty), device event (device, provider), fleet (service area, zone), service rate (order config, zones and service areas), inspection submission (form, submitted by), warranty (vendor), the device vehicle tab (driver, device), and the fuel transaction and connectivity event templates. The vehicle and driver panel headers had anchors styled as links with no click handler; they are pills now, as are the sensor, device and work order header chips. Sensor details showed the device's raw name instead of its display name. Async relations are read through resource-relation so a promise proxy never renders as a record. Inside clickable cards (vehicle and trailer cards, inspection history, fleet listings) a nested click target is not allowed, so those show the compact select-option row instead.
modals/place-assign-vendor wrote the selected vendor record into vendor_uuid, so saving the place sent an object where the API expects an id. Use ModelSelect's onChangeId. The picker also renders the vendor select-option.
All 128 ModelSelect pickers and the eight record-backed PowerSelects now render each option through select-option/<key> and show the compact variant in the closed trigger, the way modals/inspection-link already did. Polymorphic pickers (equipment, maintenance, maintenance schedule, part and work order forms, attach telematic device) resolve the option component from the chosen model name with resource-component and fall back to the label text, so the trigger updates when the type changes. The six modals that rendered a pill or an order card as the option use the select-option too, and the position drawer's trackable wrapper dispatches on its model name. Along the way: the order form's vehicle picker passed the driver query (and a this.driversQuery that the template-only modal never had), and two vehicle pickers set <Image @src>, which ember-ui's Image ignores; both render the vehicle select-option now. The hide-from-trigger and normalize-in-trigger classes are gone from every converted picker.
The select-option base and select-option/user, the pill hover style and the select-option styles moved into ember-ui 0.4.1; filter/multi-model is ember-ui's filter/model-multiple; cell/driver-name, cell/vehicle-name and cell/telematic-provider are replaced by identity cells; and cell/attached-vehicle and cell/telematic-device had no callers left. A grep for each name finds no remaining reference.
Every fact a FleetOps descriptor lists names its label with a resource-summary.facts.<key> translation key; the summary falls back to a humanized key when the host has no translation.
A unit test walks all 67 fleetops-data model names through the registry and checks each descriptor tolerates an empty record and never returns a UUID as an identifier; the instance-initializer test counts the 53 descriptors it registers. The identity-cell test now asserts one line: plate and driver on the vehicle line, the vehicle badge on the driver line, no status text, and the click chain stopping propagation. A parameterised render test mounts the pill, summary, identity cell and select option of every key, plus the Order::Pill @order regression. The identity-columns test drops the compact, showStatus and assignedVehicleLabel expectations and checks stubs carry no UUID. These tests are not run by the FleetOps CI, which only lints and builds; they need ember-ui 0.4.1 in node_modules to import the registry.
|
CI verdict: the Ember.js CI build (lint + build) passed on the first run even though the published |
The base branch rewrote the fuel transaction review page and the fuel provider transactions controller now derives its columns from the parent controller. Keep the upstream versions and reapply the identity work on top: the parent controller's vehicle and fuel report identity columns survive the merge, and the rewritten review page shows the vehicle, order and fuel report as pills beside their match buttons.
The picker switches between vehicles and orders, so it resolves the select-option from the model name like the other polymorphic pickers.
The vehicles index built a column whose action was vendorActions.panel.view, but the controller never injected vendorActions, so opening the route threw "Cannot read properties of undefined (reading 'panel')" while rendering the table. The store was read the same way.
…te-fns Inline badges next to an identity cell now come only from the driver, vehicle and trailer descriptors; places, contacts, devices and the rest render just their name. The descriptor dates (licence expiry, position and schedule identifiers) go through the console's date-fns formatter instead of the browser locale, which had produced Arabic digits and a garbled expiry.
The .driver-card hover colours were written for the dark orchestrator workbench; the drivers index card shares the class, so hovering it in light mode painted a dark slab. Light mode gets gray-100/gray-300 and the dark pair is scoped to the dark theme.
The column had no resourcePath, so the identity cell fell back to the row and showed the device's own name and icon under "Telematic Provider". It now resolves the loaded telematic, or a stub that loads it.
The vehicle, order and fuel report pills received a bare relation that is usually not loaded, so they rendered a fallback title with no link and no summary. The controller now hands them the loaded record or an identity stub that carries the transaction's name and loads the record on hover or click.
These three tables still used table/cell/media-name; they now use the vendor, contact and customer identity cells like every other index.
…e driver pill - vendor/pill and vendor/summary wrappers existed for integrated vendors only, so an order whose facilitator is a plain vendor threw "Attempted to resolve vendor/pill" and crashed the details view. - The hidden Trailers and Devices columns on vehicles and trailers rendered "[object Array]" once shown; they now use cell/resource-list, one pill per related record. - Contact and customer popovers showed raw type strings such as "customer-fleet-ops:contact"; they now read "Customer" or "Contact". - The vehicle details driver pill received a bare belongs-to proxy; it now gets the loaded relation so an unassigned driver renders static.
They were written with the previous commit but a vendor/ ignore rule kept them out of the index; force-added so vendor/pill resolves.
…ell, titleize column labels - The trailer, inspection and long-offline badge rules leave the engine stylesheet; ember-ui's palette now owns every Fleet-Ops status. - cell/resource-list pills draw a 1.25rem circle with the name centred beside it and a hover box that stays inside the cell. - Column labels read in title case: Device Attached, Driver Assigned, Trailer Attached, the trailer columns and Attached Asset.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## release/v0.6.66 #324 +/- ##
====================================================
Coverage 100.00% 100.00%
- Complexity 10774 11073 +299
====================================================
Files 565 576 +11
Lines 41545 42186 +641
====================================================
+ Hits 41545 42186 +641
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Adopts the resource identity system from
@fleetbase/ember-uiv0.4.1 across FleetOps: every place a record references another record now shows that resource's pill, one-line identity cell, hover summary or select option.Depends on fleetbase/ember-ui#175 (v0.4.1) being published. Until the
@fleetbase/ember-uirange is bumped this branch builds but the new components resolve to nothing at runtime; the engine's instance-initializer looks upservice:resource-registryand does nothing when it is absent, and no ember-ui module is imported. CI on this branch is expected to fail on the build until the range is bumped; the verdict is reported below.What changed
Descriptors (
addon/utils/resource-descriptors/{assets,people,connectivity,maintenance,operations,fuel,sub-records,polymorphic}.js, registered byinstance-initializers/register-fleetops-resource-descriptors) — all 67 fleetops-data models: 34 first-class resources with a full descriptor, 16 sub-records with a degraded one (icon tile, dot only with a status, a few facts, opening delegated to the parent or nothing), 13 polymorphic subtypes as aliases of their concrete resource, and theattachable,facilitatorandmaintenance-subjectbases as dispatchers that resolve the concrete descriptor from the record or its*_type. Parts hydrate their fitted asset and work orders their linked schedule on hover only. Fact labels are translated underresource-summary.facts.*.Wrappers —
<key>/pill,<key>/summary,cell/<key>-identityandselect-option/<key>for every key, as template-only files over the ember-ui bases. The existing vehicle, driver, trailer, device, equipment, order and inspection-submission pills keep their named arguments; the vehicle tooltip and the order QR body now live in the summaries (the tracking-number descriptor's image is the QR). The identity cells drop their JS and tone maps.Tables — 56 related-record columns render identity cells (vehicles, drivers, trailers incl. towing vehicle, fleets, fuel reports, fuel transactions, issues, contacts/customers/vendors address, orders, service rates, connectivity events/sensors/telematics,
device-table-columns, inspection submissions, maintenances, schedules, work orders, payments, map drawer listings, fuel provider transactions). Rows with only a*_namegetbuildIdentityStub(utils/identity-cell-resource.js): no UUID in identifier fields, one in-flight load per row. Async relations are read through the localutils/relation-value.js. The fourfilter/multi-modelcolumns arefilter/model-multiple; the 38filter/modelcolumns pick up option rendering from ember-ui.Details — every detail field naming a related record renders its pill (vehicle, driver, fuel report, order, trailer, work order, maintenance, schedule, equipment, part, sensor, device, device event, fleet, service rate, inspection submission, warranty, the device vehicle tab, fuel transaction and connectivity event templates). Inside clickable cards (vehicle and trailer cards, inspection history, fleet listings) the compact select option is used instead, since a nested click target is not allowed.
Pickers — all 128
ModelSelects and the 8 record-backedPowerSelects renderselect-option/<key>with the compact variant in the trigger; the 9 polymorphic pickers resolve it from the chosen model name with a text fallback. Audit output (record pickers without@selectedItemComponent):That one selects
{ label, type }notifiable descriptors, not records, so it is left as is.hide-from-trigger/normalize-in-triggerremain only in enum pickers (19 files).Deleted — the
select-optionbase andselect-option/user, the.select-option*and.fleetbase-pill > a[href]CSS,filter/multi-modeland its CSS,cell/driver-name,cell/vehicle-name,cell/telematic-provider, and the unusedcell/attached-vehicleandcell/telematic-device.Bugs fixed (one commit each)
driverActions.panel.viewignored promise proxies andloadResource()stubsvendorActions.viewVendorthat never existed (in the tables commit)order.photo_url(in the tables commit)sensor/detailsshoweddevice.nameinstead ofdisplayName(in the details commit)order/pillread@resource.*when invoked with@order<Image @src>inmodals/order-formandorder/form/details(in the pickers commit)modals/place-assign-vendorwrote a record intovendor_uuidattachable_uuidas the asset nameRemoved cell API
compact,showStatusBadgeandshowStatuson identity-cell columns are accepted and ignored; the dot carries the status and there is never a status badge.assignedVehicleLabelis gone (the descriptor supplies the badge).Listed, not fixed
order/kanban-card,order/schedule-card(which also nests anchors inside an anchor),widget/live-fleet, the operations monitor sidebar,positions-replay,global-search,customer/orders, the orchestrator panels andmap/leaflet-live-map.warranty/detailssubject stays text: the model hassubject_type/subject_uuidbut no relation.table/cell/anchor,table/cell/media-name) and the drivers fleetslink-list.Tests
Not run here: the FleetOps CI only lints and builds, and the tests import the registry from ember-ui 0.4.1. Added:
tests/unit/utils/resource-descriptors-test.js(all 67 model names resolve, aliases,fleet-ops:*and PHP class strings, every descriptor tolerates{}, no UUID identifiers),tests/unit/instance-initializers/register-fleetops-resource-descriptors-test.js, a rewrittentests/integration/components/cell/resource-identities-test.js(one-line assertions, click chain, self-suppression),tests/integration/components/resource-wrappers-test.js(all four wrappers of every key,Order::Pill @orderregression), and an updatedidentity-columns-test.js(no removed keys, stubs without UUIDs).Verification
eslint .,ember-template-lint .,normalize-rgba-alpha --check && stylelint,fleetbase-intl-lint: all exit 0.cell/driver-name,cell/vehicle-name,cell/attached-vehicle,cell/telematic-device,cell/telematic-provider,filter/multi-model,resource/detail-linkorconfig.defaultValues.*Imagereferences;Resource::*andTable::Cell::Identityare invoked only from the wrapper files; the remainingtable/cell/anchorcolumns are own-row name columns.Manual test plan
driver_namestill open the driver.activity-logpopover can still be entered; existingResourceIdentityusers in other engines are unchanged.