UNPKG

@fleetbase/fleetops-engine

Version:

Fleet & Transport Management Extension for Fleetbase

417 lines (397 loc) 19.5 kB
import { MenuItem, Widget, ExtensionComponent } from '@fleetbase/ember-core/contracts'; export default { setupExtension(app, universe) { const menuService = universe.getService('menu'); const registryService = universe.getService('registry'); const widgetService = universe.getService('widget'); // Register header navigation menuService.registerHeaderMenuItem('Fleet-Ops', 'console.fleet-ops', { icon: 'route', priority: 0, description: 'Dispatch, fleet management, driver tracking, and logistics operations.', shortcuts: [ { title: 'Orders', description: 'Create, dispatch, and track delivery orders in real time.', icon: 'boxes-stacked', route: 'console.fleet-ops.operations.orders', }, { title: 'Places', description: 'Manage saved locations, addresses, and points of interest.', icon: 'location-dot', route: 'console.fleet-ops.management.places', }, { title: 'Drivers', description: 'Manage driver profiles, assignments, and live locations.', icon: 'id-card', route: 'console.fleet-ops.management.drivers', }, { title: 'Vehicles', description: 'View and manage your vehicle fleet and telematics.', icon: 'truck', route: 'console.fleet-ops.management.vehicles', }, { title: 'Fleets', description: 'Organise drivers and vehicles into operational fleets.', icon: 'layer-group', route: 'console.fleet-ops.management.fleets', }, { title: 'Service Rates', description: 'Configure pricing rules and service rate cards.', icon: 'tags', route: 'console.fleet-ops.operations.service-rates', }, { title: 'Devices', description: 'Manage connected telematics devices and their sensor data.', icon: 'microchip', route: 'console.fleet-ops.connectivity.devices', }, { title: 'Reports', description: 'Generate and review operational analytics reports.', icon: 'chart-bar', route: 'console.fleet-ops.analytics.reports', }, { title: 'Orchestrator', description: 'Intelligently allocate and dispatch orders to available drivers.', icon: 'diagram-project', route: 'console.fleet-ops.operations.orchestrator', }, ], }); // Register admin sections menuService.registerAdminMenuPanel( 'Fleet-Ops Config', [ new MenuItem({ title: 'Routing', icon: 'route', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'admin/routing-settings'), }), new MenuItem({ title: 'Map', icon: 'map', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'admin/map-settings'), }), new MenuItem({ title: 'Navigator App', icon: 'location-arrow', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'admin/navigator-app'), }), ], { slug: 'fleet-ops', } ); // Register track order button menuService.registerMenuItem( 'auth:login', new MenuItem({ title: 'Track Order', route: 'virtual', slug: 'track-order', icon: 'barcode', type: 'link', wrapperClass: 'btn-block py-1 border dark:border-gray-700 border-gray-200 hover:opacity-50', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'order-tracking-lookup'), onClick: (menuItem) => { universe.transitionMenuItem('virtual', menuItem); }, }) ); // Register widgets this.registerWidgets(widgetService); // Create registries this.createRegistries(registryService); registryService.registerRenderableComponent('ai:action-preview:fleet-ops.create_order', new ExtensionComponent('@fleetbase/fleetops-engine', 'ai/create-order-preview')); // // Register console home guidance // this.registerHomeComponents(registryService); // Setup customer portal const isCustomerPortalInstalled = universe.extensionManager.isInstalled('@fleetbase/customer-portal-engine'); if (isCustomerPortalInstalled) { universe.whenEngineLoaded('@fleetbase/customer-portal-engine', () => { universe.extensionManager.ensureEngineLoaded('@fleetbase/fleetops-engine'); }); } }, registerWidgets(widgetService) { const widgets = [ // Legacy monolithic 13-tile widget — kept registered for one release as // users have it pinned to existing dashboards. The new KPI tile widgets // below supersede it. Scheduled for removal in the next major. new Widget({ id: 'fleet-ops-key-metrics-widget', name: 'Fleet-Ops Metrics (Legacy)', description: 'DEPRECATED — replaced by individual KPI tile widgets. Will be removed in the next major release.', icon: 'truck', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/fleet-ops-key-metrics'), grid_options: { w: 12, h: 8, minW: 8, minH: 6 }, category: 'Legacy', default: false, }), // Small KPI tile widgets — S-tier, each wraps <Widget::KpiTile> with a // fixed slug pointing at GET /fleet-ops/metrics/{slug}. new Widget({ id: 'fleet-ops-kpi-earnings-widget', name: 'Earnings (30d)', description: 'Total earnings over the last 30 days with trend.', icon: 'sack-dollar', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/kpi-earnings'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'KPI Tiles', default: true, }), new Widget({ id: 'fleet-ops-kpi-aov-widget', name: 'Avg Order Value (30d)', description: 'Average revenue per completed order with trend.', icon: 'receipt', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/kpi-aov'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'KPI Tiles', default: true, }), new Widget({ id: 'fleet-ops-kpi-distance-widget', name: 'Distance Travelled (30d)', description: 'Total kilometres delivered over the last 30 days.', icon: 'route', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/kpi-distance'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'KPI Tiles', default: false, }), new Widget({ id: 'fleet-ops-kpi-active-orders-widget', name: 'Active Orders', description: 'Live count of orders currently in flight.', icon: 'bolt', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/kpi-active-orders'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'KPI Tiles', default: true, }), new Widget({ id: 'fleet-ops-kpi-drivers-online-widget', name: 'Drivers Online', description: 'Live count of drivers currently active on a job.', icon: 'id-card', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/kpi-drivers-online'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'KPI Tiles', default: true, }), new Widget({ id: 'fleet-ops-kpi-open-issues-widget', name: 'Open Issues', description: 'Pending issues across the fleet (lower is better).', icon: 'triangle-exclamation', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/kpi-open-issues'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'KPI Tiles', default: false, }), // Analytics widgets — composed visualizations powered by /fleet-ops/analytics/*. new Widget({ id: 'fleet-ops-operations-pulse-widget', name: 'Operations Pulse', description: 'Live operational snapshot with day-over-day deltas.', icon: 'wave-pulse', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/operations-pulse'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: false, }), new Widget({ id: 'fleet-ops-live-fleet-widget', name: 'Live Fleet Map', description: 'Real-time driver positions and active routes.', icon: 'map-location-dot', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/live-fleet'), grid_options: { w: 8, h: 11, minW: 8, minH: 8 }, category: 'Maps', default: true, }), new Widget({ id: 'fleet-ops-revenue-trend-widget', name: 'Revenue Trend', description: 'Revenue over time with period comparison.', icon: 'chart-line', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/revenue-trend'), grid_options: { w: 4, h: 11, minW: 4, minH: 8 }, category: 'Analytics', default: true, }), new Widget({ id: 'fleet-ops-orders-by-status-widget', name: 'Order Volume by Status', description: 'Daily stacked bars of order counts by status.', icon: 'chart-column', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/orders-by-status'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: false, }), new Widget({ id: 'fleet-ops-on-time-delivery-widget', name: 'On-Time Delivery', description: 'Percentage of deliveries completed within the SLA window.', icon: 'clock', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/on-time-delivery'), grid_options: { w: 3, h: 4, minW: 3, minH: 4 }, category: 'Analytics', default: false, }), new Widget({ id: 'fleet-ops-top-drivers-widget', name: 'Top Drivers', description: 'Driver leaderboard sortable by orders, on-time %, or distance.', icon: 'medal', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/top-drivers'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: true, }), new Widget({ id: 'fleet-ops-fuel-efficiency-widget', name: 'Fuel Cost & Efficiency', description: 'Weekly fuel cost and cost-per-km trend.', icon: 'gas-pump', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/fuel-efficiency'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: false, }), new Widget({ id: 'fleet-ops-fuel-providers-widget', name: 'Fuel Integrations', description: 'Provider spend, unmatched transactions, and sync health.', icon: 'gas-pump', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/fuel-providers'), grid_options: { w: 4, h: 5, minW: 4, minH: 5 }, category: 'Analytics', default: false, }), new Widget({ id: 'fleet-ops-issues-insights-widget', name: 'Issues Insights', description: 'Open/resolved issues, category breakdown, and average resolution time.', icon: 'triangle-exclamation', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/issues-insights'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: false, }), new Widget({ id: 'fleet-ops-maintenance-overview-widget', name: 'Maintenance Overview', description: 'Overdue, scheduled, and YTD maintenance spend.', icon: 'wrench', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/maintenance-overview'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: true, }), new Widget({ id: 'fleet-ops-geofence-violations-widget', name: 'Geofence Violations', description: 'Dwell-time outliers and geofence event hotspots.', icon: 'location-crosshairs', component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/geofence-violations'), grid_options: { w: 6, h: 6, minW: 5, minH: 5 }, category: 'Analytics', default: false, }), ]; const defaultWidgets = widgets .filter((widget) => (typeof widget.isDefault === 'function' ? widget.isDefault() : widget.default === true)) .map((widget) => { const definition = typeof widget.toObject === 'function' ? widget.toObject() : widget; return { ...definition, widgetId: definition.widgetId ?? definition.id, }; }); widgetService.registerWidgets('dashboard', widgets); if (typeof widgetService.registerDashboard === 'function') { widgetService.registerDashboard('fleet-ops'); } widgetService.registerWidgets('fleet-ops', widgets); if (typeof widgetService.registerDefaultWidgets === 'function') { widgetService.registerDefaultWidgets('fleet-ops', defaultWidgets); } }, registerHomeComponents(registryService) { registryService.registerRenderableComponent('console:home:before-dashboard', new ExtensionComponent('@fleetbase/fleetops-engine', 'home/getting-started-guidance')); }, createRegistries(registryService) { registryService.createRegistries([ 'engine:fleet-ops', 'fleet-ops:component:map:drawer', 'fleet-ops:component:vehicle:details', 'fleet-ops:component:driver:details', 'fleet-ops:component:order-config-manager', 'fleet-ops:component:contact:form', 'fleet-ops:component:contact:form:details', 'fleet-ops:component:customer:form', 'fleet-ops:component:customer:form:details', 'fleet-ops:component:driver:form', 'fleet-ops:component:driver:form:details', 'fleet-ops:component:fleet:form', 'fleet-ops:component:fleet:form:details', 'fleet-ops:component:place:form', 'fleet-ops:component:place:form:details', 'fleet-ops:component:vehicle:form', 'fleet-ops:component:vehicle:form:details', 'fleet-ops:component:vehicle:form:after-details', 'fleet-ops:component:vehicle:form:start', 'fleet-ops:component:vehicle:form:end', 'fleet-ops:component:vehicle:card:header:start', 'fleet-ops:component:vehicle:card:header:end', 'fleet-ops:component:vehicle:card:footer:start', 'fleet-ops:component:vehicle:card:footer:end', 'fleet-ops:component:vendor:form:edit', 'fleet-ops:component:vendor:form:edit:details', 'fleet-ops:component:vendor:form:create', 'fleet-ops:component:vendor:form:create:details', 'fleet-ops:component:issue:form', 'fleet-ops:component:issue:form:details', 'fleet-ops:component:fuel-report:form', 'fleet-ops:component:fuel-report:form:details', 'fleet-ops:component:maintenance:form', 'fleet-ops:component:maintenance:form:details', 'fleet-ops:component:maintenance:details', 'fleet-ops:component:work-order:form', 'fleet-ops:component:work-order:form:details', 'fleet-ops:component:work-order:details', 'fleet-ops:component:equipment:form', 'fleet-ops:component:equipment:form:details', 'fleet-ops:component:equipment:details', 'fleet-ops:component:part:form', 'fleet-ops:component:part:form:details', 'fleet-ops:component:part:details', 'fleet-ops:contextmenu:vehicle', 'fleet-ops:contextmenu:driver', 'fleet-ops:component:order:details', 'fleet-ops:component:order:form', 'fleet-ops:component:order:form:start', 'fleet-ops:component:order:form:end', 'fleet-ops:component:order:form:details', 'fleet-ops:component:order:form:details:start', 'fleet-ops:component:order:form:details:end', 'fleet-ops:component:order:form:details:after-details', 'fleet-ops:component:order:form:payload:entity', 'fleet-ops:component:order:form:payload:entity:form', 'fleet-ops:template:settings:routing', 'fleet-ops:template:settings:orchestrator', 'fleet-ops:component:admin:routing-settings', ]); }, };