@fleetbase/fleetops-engine
Version:
Fleet & Transport Management Extension for Fleetbase
295 lines (265 loc) • 10.4 kB
JavaScript
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { task } from 'ember-concurrency';
import fleetOpsOptions from '../../../../utils/fleet-ops-options';
export default class ConnectivityTelematicsDetailsSensorsController extends Controller {
sensorActions;
deviceActions;
hostRouter;
intl;
queryParams = ['page', 'limit', 'sort', 'query', 'status', 'type', 'device_uuid', 'last_reading_at'];
telematic;
page = 1;
limit;
sort = '-updated_at';
query;
status;
type;
device_uuid;
last_reading_at;
get sensors() {
return Array.from(this.model ?? []);
}
get activeSensorsCount() {
return this.sensors.filter((sensor) => sensor.is_active || sensor.status === 'active' || sensor.status === 'online').length;
}
get sensorsWithReadingsCount() {
return this.sensors.filter((sensor) => sensor.last_value || sensor.last_reading_at).length;
}
get deviceCount() {
return new Set(this.sensors.map((sensor) => sensor.device_uuid).filter(Boolean)).size;
}
get hasActiveFilters() {
return Boolean(this.query || this.status || this.type || this.device_uuid || this.last_reading_at);
}
get hasSensors() {
return this.sensors.length > 0;
}
get hasSyncedDevices() {
const meta = this.telematic?.meta ?? {};
return Number(meta.last_sync_total ?? meta.device_count ?? 0) > 0;
}
get hasSyncRun() {
const meta = this.telematic?.meta ?? {};
return Boolean(meta.last_sync_started_at || meta.last_sync_completed_at || meta.last_sync_job_id || meta.last_sync_result || meta.last_sync_total);
}
get emptyStateVariant() {
if (this.hasSensors) {
return null;
}
if (this.hasActiveFilters) {
return 'filtered_empty';
}
if (!this.hasSyncedDevices && !this.hasSyncRun) {
return 'not_synced';
}
return 'empty';
}
get emptyStateContent() {
switch (this.emptyStateVariant) {
case 'filtered_empty':
return {
tone: 'info',
icon: 'filter',
title: 'No sensors match these filters',
message: 'Clear the current search and filters to return to the full sensor inventory.',
primaryText: 'Clear filters',
primaryIcon: 'filter',
primaryAction: this.clearFilters,
};
case 'not_synced':
return {
tone: 'warning',
icon: 'satellite-dish',
title: 'Sync devices before reviewing sensors',
message: 'Sensor inventory depends on synced devices and provider telemetry ingestion.',
primaryText: 'Go to Devices',
primaryIcon: 'microchip',
primaryAction: this.goToDevices,
};
case 'empty':
return {
tone: 'info',
icon: 'gauge-high',
title: 'No sensors reported yet',
message: 'Devices are synced, but this provider has not reported sensor inventory or webhook sensor data yet.',
primaryText: 'Refresh',
primaryIcon: 'refresh',
primaryAction: this.refresh,
secondaryText: 'View Devices',
secondaryIcon: 'microchip',
secondaryAction: this.goToDevices,
note: 'Some providers expose sensors only after live telemetry, fuel, or diagnostic events are ingested.',
};
default:
return null;
}
}
get metrics() {
return [
{ label: 'Sensors', value: this.model?.meta?.total ?? this.sensors.length, icon: 'gauge-high', accentClass: 'fleetops-connectivity-kpi-accent-blue' },
{ label: 'Active', value: this.activeSensorsCount, icon: 'signal', accentClass: 'fleetops-connectivity-kpi-accent-green' },
{ label: 'Reporting values', value: this.sensorsWithReadingsCount, icon: 'chart-line', accentClass: 'fleetops-connectivity-kpi-accent-amber' },
{ label: 'Parent devices', value: this.deviceCount, icon: 'microchip', accentClass: 'fleetops-connectivity-kpi-accent-blue' },
];
}
get actionButtons() {
return [
{
icon: 'refresh',
size: 'sm',
onClick: this.refresh,
helpText: this.intl.t('common.refresh'),
wrapperClass: 'fleetops-telematics-action-button',
isLoading: this.refreshTask.isRunning,
disabled: this.refreshTask.isRunning,
},
{
icon: 'microchip',
text: 'View Devices',
size: 'sm',
onClick: this.goToDevices,
wrapperClass: 'fleetops-telematics-action-button',
},
];
}
bulkActions = [];
get columns() {
return [
{
sticky: true,
label: this.intl.t('column.name'),
valuePath: 'name',
cellComponent: 'table/cell/anchor',
action: this.sensorActions.transition.view,
permission: 'fleet-ops view sensor',
resizable: true,
sortable: true,
filterable: true,
filterParam: 'query',
filterComponent: 'filter/string',
},
{
label: 'Type',
valuePath: 'type',
resizable: true,
sortable: true,
filterable: true,
filterParam: 'type',
filterComponent: 'filter/multi-option',
filterOptions: fleetOpsOptions('sensorTypes'),
filterOptionLabel: 'label',
filterOptionValue: 'value',
},
{
label: 'Device',
valuePath: 'device.displayName',
cellComponent: 'table/cell/anchor',
action: this.deviceActions.transition.view,
permission: 'fleet-ops view device',
resizable: true,
sortable: true,
filterable: true,
filterComponent: 'filter/model',
filterComponentPlaceholder: 'Select device',
filterParam: 'device_uuid',
model: 'device',
modelNamePath: 'displayName',
query: { telematic_uuid: this.telematic?.id },
},
{
label: 'Value',
valuePath: 'last_value',
resizable: true,
sortable: true,
},
{
label: 'Unit',
valuePath: 'unit',
resizable: true,
sortable: true,
},
{
label: this.intl.t('column.status'),
valuePath: 'status',
cellComponent: 'table/cell/status',
resizable: true,
sortable: true,
filterable: true,
filterComponent: 'filter/multi-option',
filterOptions: fleetOpsOptions('sensorStatuses'),
filterOptionLabel: 'label',
filterOptionValue: 'value',
},
{
label: 'Last Reading',
valuePath: 'lastReadingAt',
sortParam: 'last_reading_at',
resizable: true,
sortable: true,
filterable: true,
filterParam: 'last_reading_at',
filterComponent: 'filter/date',
},
{
label: '',
cellComponent: 'table/cell/dropdown',
ddButtonText: false,
ddButtonIcon: 'ellipsis-h',
ddButtonIconPrefix: 'fas',
ddMenuLabel: this.intl.t('common.resource-actions', { resource: this.intl.t('resource.sensor') }),
cellClassNames: 'overflow-visible align-middle',
wrapperClass: 'flex items-center justify-end mx-2',
sticky: 'right',
width: 60,
actions: [
{
label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.sensor') }),
fn: this.sensorActions.transition.view,
permission: 'fleet-ops view sensor',
},
{
label: 'Open parent device',
fn: this.openParentDevice,
permission: 'fleet-ops view device',
},
],
sortable: false,
filterable: false,
resizable: false,
searchable: false,
},
];
}
refresh() {
if (this.refreshTask.isRunning) {
return;
}
return this.refreshTask.perform();
}
clearFilters() {
this.query = null;
this.status = null;
this.type = null;
this.device_uuid = null;
this.last_reading_at = null;
this.page = 1;
}
goToDevices() {
return this.hostRouter.transitionTo('console.fleet-ops.connectivity.telematics.details.devices', this.telematic);
}
openParentDevice(sensor) {
const device = sensor.device;
if (device?.id) {
return this.deviceActions.transition.view(device);
}
return this.hostRouter.transitionTo('console.fleet-ops.connectivity.telematics.details.devices', this.telematic, {
queryParams: { device_id: sensor.device_uuid },
});
}
*refreshTask() {
yield this.hostRouter.refresh();
}
}