Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8acbf62
fix(assets): serve leaflet marker icons from the leaflet package
janni1288 Aug 8, 2026
4fe9895
Merge branch 'fleetbase:main' into fix/leaflet-marker-icons
janni1288 Aug 18, 2026
8867fd3
chore: regenerate pnpm-lock.yaml for leaflet dependency
janni1288 Aug 19, 2026
5f9375d
feat(driver): add driver card component
janni1288 Aug 20, 2026
bb32eaf
feat(drivers): persist card/table layout preference
janni1288 Aug 20, 2026
cc00087
feat(drivers): add card view layout toggle to drivers index
janni1288 Aug 20, 2026
676cf46
feat(api): publish the order config flow's graph so consumers can seq…
roncodes Aug 22, 2026
f7e394d
fix(api): stop PUT /v1/vehicles/{id} silently discarding the odometer
roncodes Aug 22, 2026
1f0c5ff
fix(api): scope issue and fuel-report lists by driver_uuid, not silen…
roncodes Aug 22, 2026
e62a3c3
test(vehicles): move the odometer contract onto the controller that o…
roncodes Aug 23, 2026
2c943b9
test(filters): cover the vehicle_uuid alias on both driver-scoped fil…
roncodes Aug 23, 2026
b27d47d
test(order-config): update the flow contract for the published graph …
roncodes Aug 23, 2026
461db31
fix(drivers): restore changeLayout as an action and satisfy prettier
roncodes Aug 23, 2026
40eb65c
chore(release): bump to v0.6.61 and write the release notes
roncodes Aug 23, 2026
ade56e5
chore: drop a node_modules symlink committed by accident
roncodes Aug 23, 2026
4f6a78b
chore: drop a node_modules symlink committed by accident
roncodes Aug 23, 2026
e2370ca
chore: ignore a node_modules symlink, not just the directory
roncodes Aug 23, 2026
cf20a07
Merge pull request #300 from fleetbase/feat/public-order-config-flow-…
roncodes Aug 23, 2026
1a3b388
Merge pull request #302 from fleetbase/fix/driver-scoped-filter-aliases
roncodes Aug 23, 2026
81dcea2
Merge pull request #301 from fleetbase/fix/vehicle-update-drops-odometer
roncodes Aug 23, 2026
2c3cbf3
fix(security): a driver's password can no longer be set by a general …
roncodes Aug 23, 2026
8dc555b
feat(api): driver-facing manifests — read, run, and re-sequence a route
roncodes Aug 23, 2026
96267e0
test: cover the manifest controller, and make its logic testable
roncodes Aug 23, 2026
b421dd7
test: cover the driver password endpoints, and drop the foundation de…
roncodes Aug 23, 2026
38ec9b3
perf: order stops by geometry, not four hundred routing calls
roncodes Aug 23, 2026
ddcdba2
test: reach the real password helpers, not only the probe's stand-ins
roncodes Aug 23, 2026
68601b3
fix: remove a line no test could reach, and apply the formatter
roncodes Aug 23, 2026
a5a4f1c
feat(map): configurable Leaflet tile provider + keyless OpenStreetMap…
roncodes Aug 27, 2026
4eb74f9
test(map): cover leaflet tile url sanitization in setting controller
roncodes Aug 28, 2026
eecdc72
Merge pull request #306 from fleetbase/feature/leaflet-tile-provider-…
roncodes Aug 28, 2026
e4119c3
fix: a password given at driver creation is now actually kept
roncodes Aug 31, 2026
0f4112c
fix: read the password column the driver's user relation leaves out
roncodes Aug 31, 2026
680a490
Merge pull request #304 from fleetbase/fix/driver-password-change-req…
roncodes Aug 31, 2026
abbbcc2
Merge pull request #305 from fleetbase/feat/driver-manifest-api
roncodes Aug 31, 2026
4d83063
fix(drivers): polish driver card layout
roncodes Aug 31, 2026
068be38
Merge pull request #299 from janni1288/feat/drivers-card-view
roncodes Aug 31, 2026
196ac5f
fix place editing for geocoded order stops
roncodes Aug 31, 2026
a764a68
Merge pull request #307 from fleetbase/feature/fix-unsaved-geocoded-p…
roncodes Aug 31, 2026
853b9aa
ci avoid duplicate release branch runs
roncodes Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ember.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Ember.js CI

on:
push:
branches: [ main, 'dev-v*' ]
branches: [ main ]
tags:
- 'v*'
pull_request:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/postman.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ name: API Contract (Postman)

on:
push:
branches: [main, 'dev-v*']
branches: [main]
pull_request:
branches: [main, 'dev-v*']
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: PHP CI

on:
push:
branches: [ main, 'dev-v*' ]
branches: [ main ]
tags:
- 'v*'
pull_request:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/declarations/

# dependencies
/node_modules/
/node_modules
/scripts/node_modules/

# misc
Expand Down
2 changes: 2 additions & 0 deletions .template-lintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ module.exports = {
'link-href-attributes': 'off',
'require-input-label': 'off',
'no-array-prototype-extensions': 'off',
// `leaflet-tile-url` is a zero-argument helper resolving the configured tile provider
'no-implicit-this': { allow: ['leaflet-tile-url'] },
},
};
29 changes: 9 additions & 20 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
> v0.6.60 ~ "Closes an authentication bypass, and clears a run of API 500s"
> v0.6.61 ~ "A grid view for drivers, a sequenceable order flow, and two silent API no-ops closed"

---
## Highlights
A security fix and a broad sweep of public API defects surfaced by running the official Postman collection against a live stack. Several endpoints answered `500` where a `404` or `422` belonged, and a few were unreachable entirely.
Two API defects in this release were silent: both answered `200` and neither did what the caller asked. A vehicle odometer update was discarded, and a driver-scoped list came back unscoped. Alongside them, the order config flow now publishes enough of its shape to be sequenced, and Drivers Management gains a card layout.

---
## Security
- **Closed a verify-code authentication bypass in the driver flow.** Please upgrade.
- The non-production verification-code bypass is now scoped to explicitly designated review accounts, so a bypass code alone is not enough — the identity has to be on the allowlist too.
## Features
- **Drivers Management has a card view.** A layout toggle switches the index between the table and a card grid, and the choice is remembered across visits.
- **The order config flow publishes its graph.** `activities`, `sequence` and `logic` now ride along with each activity, so a consumer can order the flow and offer a next step instead of rendering an unordered set. Transitions are normalised to a list of codes regardless of which of the two stored shapes a flow was authored in.

---
## Bug Fixes
- **Driver `register-device` was unreachable on both driver routes.** Laravel never injects a class-typed parameter that declares a default, so the injected request was always null.
- **Geofence driver history asked for a UUID the API never issues.** It now resolves the driver by the public id callers actually hold.
- **`/from-qr` returned a 500**, and the QR code's content is now published in debug mode so the flow can be exercised.
- **Fuel reports could not be created without a location**, and could not be updated.
- **A sensor could not be created at all** — `last_position` had no default.
- **Customer signup with a place failed** — the Place location now defaults.
- Unknown onboard organization answers `404` instead of `500`.
- Duplicate part SKU and fuel transaction answer `422` instead of `500`.
- Restored the vehicle maintenance schedule workflows.
- **`PUT /v1/vehicles/{id}` silently discarded the odometer.** The field is fillable on the model but was missing from the controller's input projection, so a driver app recording mileage received a `200` and a correct-looking body while the reading was dropped. `odometer` and `odometer_unit` are now accepted and validated.
- **Issue and fuel-report lists scoped by `driver_uuid` came back scoped by nothing.** The base filter silently ignores a query parameter it cannot match to a method, so the filter was dropped and the response was narrowed only by company — every driver's records, with no sign the request had been narrowed at all. `driver_uuid`, `driver_assigned` and `vehicle_uuid` are now recognised on both filters.
- **Leaflet marker icons are served from the leaflet package** rather than resolving to a broken URL.

---
## Testing
- Coverage restored to 100% across the QR, geofence, driver auth, customer request and navigator changes.

---
## Continuous Integration
- The server, Ember and Postman workflows now run on `dev-v*` release branches.
- The contract run tests this branch's API code rather than the published package.
- Coverage held at 100% across the vehicle input projection, both driver-scoped filters, and the order config flow projection.

---
## Need help?
Expand Down
6 changes: 1 addition & 5 deletions addon/components/ai/route-preview-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,7 @@ export default class AiRoutePreviewMapComponent extends Component {
get tileUrl() {
const theme = document.body?.dataset?.theme;

if (theme === 'dark') {
return 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';
}

return 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
return this.mapSettings.getLeafletTileUrl(theme === 'dark' ? 'dark' : 'light');
}

get emptyText() {
Expand Down
3 changes: 2 additions & 1 deletion addon/components/customer/orders.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { debug } from '@ember/debug';
import { task, timeout } from 'ember-concurrency';
import { Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
import engineService from '@fleetbase/ember-core/decorators/engine-service';
import { DEFAULT_LEAFLET_TILE_URL } from '../../utils/leaflet-tile-url';
import registerComponent from '@fleetbase/ember-core/utils/register-component';
import OrderProgressCardComponent from '../order-progress-card';
import DisplayPlaceComponent from '../display-place';
Expand Down Expand Up @@ -38,7 +39,7 @@ export default class CustomerOrdersComponent extends Component {
@tracked longitude;
@tracked route;
@tracked query;
@tracked tileSourceUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
@tracked tileSourceUrl = DEFAULT_LEAFLET_TILE_URL;
@tracked scheduledAt;
@tracked deliveryInstructions = {};

Expand Down
49 changes: 49 additions & 0 deletions addon/components/driver/card.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<Layout::Resource::Card ...attributes as |Card|>
<Card.header class="{{@headerClass}}">
<RegistryYield @registry="fleet-ops:component:driver:card:header:start" as |RegistryComponent|>
<RegistryComponent @order={{@resource}} @resource={{@resource}} />
</RegistryYield>
<div class="flex items-center w-full min-w-0">
<div class="font-semibold flex-1 truncate" data-test-driver-name>{{or @resource.name @resource.display_name}}</div>
<FaIcon @icon="circle" @size="xs" class="ml-2 flex-none {{if @resource.online 'text-green-500' 'text-gray-400'}}" data-test-driver-online-indicator />
</div>
<div class="text-gray-400 dark:text-gray-500 text-sm w-full truncate">{{n-a @resource.phone @resource.public_id}}</div>
{{#if (has-block "header")}}
{{yield to="header"}}
{{/if}}
<RegistryYield @registry="fleet-ops:component:driver:card:header:end" as |RegistryComponent|>
<RegistryComponent @order={{@resource}} @resource={{@resource}} />
</RegistryYield>
</Card.header>
<Card.body class="{{@bodyClass}} h-40 overflow-hidden">
<Image src={{avatar-url @resource.photo_url}} @fallbackSrc={{this.fallbackImage}} class="block w-full h-full object-cover rounded-none" data-test-driver-photo />
{{#if (has-block "body")}}
{{yield to="body"}}
{{/if}}
</Card.body>
<Card.footer class={{@footerClass}}>
<RegistryYield @registry="fleet-ops:component:driver:card:footer:start" as |RegistryComponent|>
<RegistryComponent @order={{@resource}} @resource={{@resource}} />
</RegistryYield>
<div class="flex flex-row items-center justify-between w-full">
<Badge @status={{or this.statusValue "default"}} @size="xs" data-test-driver-status-badge>{{this.statusLabel}}</Badge>
<div class="flex flex-row items-center space-x-1">
<Button @icon="eye" @size="xs" @onClick={{fn this.driverActions.transition.view @resource}} />
<Button @icon="pencil" @size="xs" @onClick={{fn this.driverActions.transition.edit @resource}} />
<Button @icon="trash" @size="xs" @type="danger" @onClick={{fn this.driverActions.delete @resource}} />
</div>
</div>
<RegistryYield @registry="fleet-ops:component:driver:card:footer:end" as |RegistryComponent|>
<RegistryComponent @order={{@resource}} @resource={{@resource}} />
</RegistryYield>
{{#if (has-block "footer")}}
{{yield to="footer"}}
{{/if}}
<div class="mt-1.5 w-full">
<div class="text-gray-400 dark:text-gray-500 text-xs truncate">
<FaIcon @icon="car" @prefix="fas" class="mr-1" />{{n-a this.assignedVehicleLabel}}
</div>
<div class="text-gray-400 dark:text-gray-500 text-xs">Last Modified: {{@resource.updatedAt}}</div>
</div>
</Card.footer>
</Layout::Resource::Card>
30 changes: 30 additions & 0 deletions addon/components/driver/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import config from 'ember-get-config';

export default class DriverCardComponent extends Component {
@service driverActions;

get resource() {
return this.args.resource;
}

get fallbackImage() {
return config?.defaultValues?.driverImage;
}

get statusValue() {
return get(this.resource, 'status') ?? '';
}

get statusLabel() {
return this.statusValue || '-';
}

get assignedVehicleLabel() {
const driver = this.resource;

return get(driver, 'vehicle_assigned.display_name') ?? get(driver, 'vehicle.display_name') ?? get(driver, 'vehicle_name');
}
}
23 changes: 4 additions & 19 deletions addon/components/map/leaflet-live-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export default class MapLeafletLiveMapComponent extends Component {
@tracked latitude = this.location.getLatitude();
@tracked longitude = this.location.getLongitude();
@tracked contextmenuItems = [];
@tracked tileUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
@tracked theme = 'light';
@tracked routes = [];
@tracked drivers = [];
Expand All @@ -57,6 +56,10 @@ export default class MapLeafletLiveMapComponent extends Component {
@tracked leafletPluginsReady = hasLeafletPluginsReady();
_viewportReloadLocks = new Set();

get tileUrl() {
return this.mapSettings.getLeafletTileUrl(this.theme);
}

constructor() {
super(...arguments);

Expand Down Expand Up @@ -888,22 +891,4 @@ export default class MapLeafletLiveMapComponent extends Component {
// Fallback to default Singapore longitude
return 103.8864;
}

#changeTileSource(source) {
switch (source) {
case 'dark':
this.theme = 'dark';
this.tileUrl = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';
break;
case 'custom':
this.theme = 'custom';
this.tileUrl = source.startsWith('https://') ? source : 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
break;
case 'light':
default:
this.theme = 'light';
this.tileUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
break;
}
}
}
2 changes: 1 addition & 1 deletion addon/components/modals/place-details.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="flex">
<div class="w-48 mb-6 mr-6">
<LeafletMap class="w-full h-48 mb-2 rounded-md shadow-md" @lat={{@options.place.latitude}} @lng={{@options.place.longitude}} @zoom={{12}} as |layers|>
<layers.tile @url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png" />
<layers.tile @url={{leaflet-tile-url}} />

<layers.marker @location={{@options.place.coordinates}} />
</LeafletMap>
Expand Down
2 changes: 1 addition & 1 deletion addon/components/modals/point-map.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
<div class="fleetbase-leaflet-map-container">
<LeafletMap class="map-height-base" @lat={{@options.latitude}} @lng={{@options.longitude}} @zoom={{12}} as |layers|>
<layers.tile @url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png" />
<layers.tile @url={{leaflet-tile-url}} />

<layers.marker @icon={{@options.icon}} @location={{point-to-coordinates @options.location}} @riseOnHover={{true}} as |marker|>
<marker.popup @maxWidth="500" @minWidth="180">
Expand Down
3 changes: 2 additions & 1 deletion addon/components/orchestrator-workbench.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default class OrchestratorWorkbenchComponent extends Component {
@service modalsManager;
@service location;
@service mapManager;
@service mapSettings;
@service routeEngine;
@service('order-allocation') allocationService;

Expand Down Expand Up @@ -661,7 +662,7 @@ export default class OrchestratorWorkbenchComponent extends Component {

get tileSourceUrl() {
const isDark = document.documentElement.classList.contains('dark');
return isDark ? 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png' : 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png';
return this.mapSettings.getLeafletTileUrl(isDark ? 'dark' : 'light');
}

// ── Computed helpers ──────────────────────────────────────────────────────
Expand Down
3 changes: 2 additions & 1 deletion addon/components/order-tracking-lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { task } from 'ember-concurrency';
import { OSRMv1, Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
import engineService from '@fleetbase/ember-core/decorators/engine-service';
import { DEFAULT_LEAFLET_TILE_URL } from '../utils/leaflet-tile-url';

export default class OrderTrackingLookupComponent extends Component {
@service urlSearchParams;
Expand All @@ -28,7 +29,7 @@ export default class OrderTrackingLookupComponent extends Component {
@tracked latitude;
@tracked longitude;
@tracked route;
@tracked tileSourceUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
@tracked tileSourceUrl = DEFAULT_LEAFLET_TILE_URL;

constructor() {
super(...arguments);
Expand Down
3 changes: 3 additions & 0 deletions addon/components/order/form/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { action, get } from '@ember/object';
import { task } from 'ember-concurrency';
import { colorForId, routeColorForStatus, routeStyleForStatus } from '../../../utils/route-colors';
import { buildRoutePointMarkerPresentation, buildRoutePointsFromPayload, describeRoutePoint } from '../../../utils/route-visualization';
import preparePlaceForSave from '../../../utils/prepare-place-for-save';

const ORDER_ROUTE_PREVIEW_PADDING_BOTTOM_RIGHT = [420, 0];
const ORDER_ROUTE_PREVIEW_MAX_ZOOM_TWO_POINTS = 13;
Expand Down Expand Up @@ -153,6 +154,7 @@ export default class OrderFormRouteComponent extends Component {
@action setWaypointPlace(index, place) {
if (!this.args.resource.payload.waypoints[index]) return;

place = preparePlaceForSave(this.store, place);
this.args.resource.payload.waypoints[index].place = place;
this.args.resource.payload.waypoints[index]?.setProperties({
street1: place.street1,
Expand Down Expand Up @@ -186,6 +188,7 @@ export default class OrderFormRouteComponent extends Component {
}

@action setPayloadPlace(prop, place) {
place = preparePlaceForSave(this.store, place);
this.args.resource.payload[prop] = place;
this.previewRoute();
this.requestServiceQuoteRefresh(`route.${prop}.changed`);
Expand Down
2 changes: 1 addition & 1 deletion addon/components/place/details.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
@zoomControl={{false}}
as |layers|
>
<layers.tile @url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png" />
<layers.tile @url={{leaflet-tile-url}} />
<layers.marker
@id={{@resource.id}}
@icon={{icon iconUrl=(or @resource.avatar_url "/engines-dist/images/building-marker.png") iconSize=(array 40 40)}}
Expand Down
5 changes: 4 additions & 1 deletion addon/components/positions-replay.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class PositionsReplayComponent extends Component {
@service positionPlayback;
@service notifications;
@service location;
@service mapSettings;

/** Component ID */
id = guidFor(this);
Expand All @@ -29,7 +30,9 @@ export default class PositionsReplayComponent extends Component {
@tracked latitude = this.args.resource.latitude || this.location.getLatitude();
@tracked longitude = this.args.resource.longitude || this.location.getLongitude();
@tracked zoom = 14;
@tracked tileUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
get tileUrl() {
return this.mapSettings.getLeafletTileUrl('light');
}

/** Computed properties - read state from service */
get isReplaying() {
Expand Down
2 changes: 1 addition & 1 deletion addon/components/service-area/details.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@zoomControl={{false}}
as |layers|
>
<layers.tile @url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png" />
<layers.tile @url={{leaflet-tile-url}} />
<layers.polygon
@id={{@resource.id}}
@record={{@resource}}
Expand Down
14 changes: 7 additions & 7 deletions addon/components/widget/live-fleet.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,11 @@ import { task } from 'ember-concurrency';
import { renderCompleted, waitForInsertedAndSized } from '@fleetbase/ember-ui/utils/dom';
import LeafletTrackingMarkerComponent from '../leaflet-tracking-marker';
import ensureLeafletDrawEditNamespace from '../../utils/leaflet-draw-namespace-guard';
import { DEFAULT_LEAFLET_TILE_ATTRIBUTION } from '../../utils/leaflet-tile-url';

const DEFAULT_CENTER = [1.31, 103.85];
const DEFAULT_ZOOM = 11;
// Match the rest of fleetops' Leaflet maps (light Carto basemap), which keeps the
// dashboard styling consistent with the operational live map. Falls back gracefully
// in dark mode via the next-leaflet-container-map theming.
const TILE_URL = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
const TILE_URL_DARK = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png';
const TILE_ATTRIBUTION = '&copy; OpenStreetMap contributors &copy; CARTO';
const TILE_ATTRIBUTION = DEFAULT_LEAFLET_TILE_ATTRIBUTION;
const RECONCILE_INTERVAL_MS = 5 * 60_000;

/**
Expand All @@ -30,6 +26,7 @@ export default class WidgetLiveFleetComponent extends Component {
@service fetch;
@service socket;
@service currentUser;
@service mapSettings;

@tracked data = null;
@tracked error = null;
Expand All @@ -38,7 +35,7 @@ export default class WidgetLiveFleetComponent extends Component {

get tileUrl() {
const isDark = typeof document !== 'undefined' && document.documentElement?.dataset?.theme === 'dark';
return isDark ? TILE_URL_DARK : TILE_URL;
return this.mapSettings.getLeafletTileUrl(isDark ? 'dark' : 'light');
}

socketChannel = null;
Expand Down Expand Up @@ -78,6 +75,9 @@ export default class WidgetLiveFleetComponent extends Component {
this.#ensureTrackingMarkerRegistered();
this.#patchLeafletDrawInitHook();
this.#resetMapDeferred();
// Widgets can render before the fleetops engine boots, so make sure the
// company's map settings (custom tile provider URL) are loaded.
this.mapSettings.load();
this.load.perform();
this.subscribe();
this.reconcileTimer = setInterval(() => this.load.perform(), RECONCILE_INTERVAL_MS);
Expand Down
Loading
Loading