@fleetbase/fleetops-engine 0.6.54 → 0.6.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/components/admin/routing-settings.hbs +2 -1
- package/addon/components/cell/attached-vehicle.hbs +10 -0
- package/addon/components/cell/attached-vehicle.js +58 -0
- package/addon/components/cell/device-identity.hbs +24 -0
- package/addon/components/cell/device-identity.js +129 -0
- package/addon/components/cell/driver-identity.hbs +33 -0
- package/addon/components/cell/driver-identity.js +143 -0
- package/addon/components/cell/equipment-identity.hbs +5 -0
- package/addon/components/cell/equipment-identity.js +48 -0
- package/addon/components/cell/part-identity.hbs +5 -0
- package/addon/components/cell/part-identity.js +63 -0
- package/addon/components/cell/telematic-device.hbs +38 -0
- package/addon/components/cell/telematic-device.js +44 -0
- package/addon/components/cell/telematic-provider.hbs +33 -16
- package/addon/components/cell/telematic-provider.js +50 -8
- package/addon/components/cell/vehicle-identity.hbs +33 -0
- package/addon/components/cell/vehicle-identity.js +138 -0
- package/addon/components/device/form.hbs +2 -2
- package/addon/components/device/form.js +7 -0
- package/addon/components/device/panel-header.hbs +45 -20
- package/addon/components/device/panel-header.js +49 -1
- package/addon/components/device/panel-tabs/events.hbs +30 -0
- package/addon/components/device/panel-tabs/events.js +128 -0
- package/addon/components/device/panel-tabs/sensors.hbs +30 -0
- package/addon/components/device/panel-tabs/sensors.js +93 -0
- package/addon/components/device/panel-tabs/vehicle.hbs +68 -0
- package/addon/components/device/panel-tabs/vehicle.js +90 -0
- package/addon/components/equipment/form.js +8 -1
- package/addon/components/layout/fleet-ops-sidebar.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +8 -0
- package/addon/components/map/drawer/device-event-listing.js +2 -0
- package/addon/components/map/drawer/driver-listing.js +2 -0
- package/addon/components/map/drawer/place-listing.js +2 -0
- package/addon/components/map/drawer/position-listing.hbs +11 -6
- package/addon/components/map/drawer/position-listing.js +17 -4
- package/addon/components/map/drawer/vehicle-listing.js +2 -0
- package/addon/components/sensor/panel-header.hbs +47 -15
- package/addon/components/sensor/panel-header.js +59 -1
- package/addon/components/table/cell/dropdown/action-item.hbs +31 -0
- package/addon/components/table/cell/dropdown/action-item.js +62 -0
- package/addon/components/table/cell/dropdown.hbs +28 -0
- package/addon/components/table/cell/dropdown.js +91 -0
- package/addon/components/vendor/panel-header.hbs +82 -0
- package/addon/components/vendor/panel-header.js +48 -0
- package/addon/controllers/connectivity/devices/index/details/vehicle.js +49 -1
- package/addon/controllers/connectivity/devices/index.js +144 -129
- package/addon/controllers/connectivity/events/details.js +3 -0
- package/addon/controllers/connectivity/events/index.js +187 -11
- package/addon/controllers/connectivity/sensors/index.js +156 -14
- package/addon/controllers/connectivity/telematics/details/devices.js +126 -134
- package/addon/controllers/maintenance/equipment/index.js +1 -2
- package/addon/controllers/maintenance/parts/index.js +1 -2
- package/addon/controllers/management/drivers/index.js +82 -42
- package/addon/controllers/management/fuel-reports/index.js +63 -4
- package/addon/controllers/management/issues/index.js +63 -4
- package/addon/controllers/management/vehicles/index.js +33 -6
- package/addon/routes/connectivity/devices/index/details/vehicle.js +24 -2
- package/addon/routes/connectivity/devices/index.js +7 -0
- package/addon/routes/connectivity/events/details.js +3 -0
- package/addon/routes/connectivity/events/index.js +6 -2
- package/addon/routes/connectivity/sensors/index.js +7 -2
- package/addon/routes/connectivity/telematics/details/devices.js +2 -0
- package/addon/services/device-actions.js +30 -0
- package/addon/services/device-event-actions.js +1 -1
- package/addon/services/equipment-actions.js +1 -0
- package/addon/services/sensor-actions.js +3 -0
- package/addon/services/service-rate-actions.js +39 -1
- package/addon/services/vehicle-actions.js +24 -12
- package/addon/services/vendor-actions.js +3 -0
- package/addon/styles/fleetops-engine.css +8 -0
- package/addon/templates/connectivity/devices/index/details/vehicle.hbs +64 -1
- package/addon/templates/management/vendors/index/details.hbs +2 -2
- package/addon/templates/settings/notifications.hbs +2 -1
- package/addon/templates/settings/routing.hbs +1 -0
- package/addon/utils/device-table-columns.js +288 -0
- package/addon/utils/identity-cell-resource.js +20 -0
- package/addon/utils/map-drawer-dropdown-position.js +47 -0
- package/addon/utils/trackable-option.js +93 -0
- package/app/components/cell/attached-vehicle.js +1 -0
- package/app/components/cell/device-identity.js +1 -0
- package/app/components/cell/driver-identity.js +1 -0
- package/app/components/cell/equipment-identity.js +1 -0
- package/app/components/cell/part-identity.js +1 -0
- package/app/components/cell/telematic-device.js +1 -0
- package/app/components/cell/vehicle-identity.js +1 -0
- package/app/components/device/panel-tabs/events.hbs +30 -0
- package/app/components/device/panel-tabs/events.js +128 -0
- package/app/components/device/panel-tabs/sensors.hbs +30 -0
- package/app/components/device/panel-tabs/sensors.js +93 -0
- package/app/components/device/panel-tabs/vehicle.hbs +68 -0
- package/app/components/device/panel-tabs/vehicle.js +90 -0
- package/app/components/table/cell/dropdown/action-item.js +1 -0
- package/app/components/table/cell/dropdown.js +1 -0
- package/app/components/vendor/panel-header.js +1 -0
- package/app/controllers/connectivity/events/{index/details.js → details.js} +1 -1
- package/app/routes/connectivity/events/{index/details.js → details.js} +1 -1
- package/app/templates/connectivity/events/{index/details.js → details.js} +1 -1
- package/app/utils/map-drawer-dropdown-position.js +1 -0
- package/app/utils/trackable-option.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/src/Console/Commands/SyncTelematics.php +4 -4
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +18 -1
- package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/ServiceRateController.php +82 -13
- package/server/src/Http/Filter/DeviceEventFilter.php +21 -0
- package/server/src/Http/Filter/DeviceFilter.php +24 -1
- package/server/src/Http/Resources/v1/Index/Vehicle.php +19 -0
- package/server/src/Models/Device.php +2 -0
- package/server/src/Models/DeviceEvent.php +81 -0
- package/server/src/Models/Equipment.php +55 -0
- package/server/src/Support/Telematics/Providers/AfaqyProvider.php +1 -0
- package/server/src/Support/Telematics/Providers/FlespiProvider.php +89 -15
- package/server/src/Support/Telematics/Providers/GeotabProvider.php +123 -35
- package/server/src/Support/Telematics/Providers/SafeeProvider.php +26 -2
- package/server/src/Support/Telematics/Providers/SamsaraProvider.php +122 -14
- package/server/src/routes.php +0 -1
- package/server/tests/DeviceFilterTest.php +9 -0
- package/server/tests/DriverVehicleStatusDefaultTest.php +19 -2
- package/server/tests/EquipmentAssignmentMorphTypeTest.php +35 -0
- package/server/tests/ServiceRateRouteValidationTest.php +101 -0
- package/server/tests/TelematicsHardeningTest.php +238 -7
- package/addon/controllers/connectivity/events/index/details.js +0 -3
- package/addon/routes/connectivity/events/index/details.js +0 -3
- /package/addon/templates/connectivity/events/{index/details.hbs → details.hbs} +0 -0
|
@@ -1,21 +1,84 @@
|
|
|
1
1
|
import Controller from '@ember/controller';
|
|
2
|
+
import { action, get } from '@ember/object';
|
|
2
3
|
import { inject as service } from '@ember/service';
|
|
3
4
|
import { tracked } from '@glimmer/tracking';
|
|
4
5
|
import fleetOpsOptions from '../../../utils/fleet-ops-options';
|
|
5
6
|
|
|
7
|
+
function sensorTelematic(sensor) {
|
|
8
|
+
const telematic = get(sensor, 'telematic');
|
|
9
|
+
|
|
10
|
+
if (telematic) {
|
|
11
|
+
return telematic;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const id = get(sensor, 'telematic_uuid');
|
|
15
|
+
const name = get(sensor, 'telematic_name');
|
|
16
|
+
const provider = get(sensor, 'provider');
|
|
17
|
+
|
|
18
|
+
if (!id && !name && !provider) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
id,
|
|
24
|
+
name: name ?? provider,
|
|
25
|
+
provider,
|
|
26
|
+
provider_descriptor: get(sensor, 'provider_descriptor'),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sensorDevice(sensor) {
|
|
31
|
+
const device = get(sensor, 'device');
|
|
32
|
+
|
|
33
|
+
if (device) {
|
|
34
|
+
return device;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const id = get(sensor, 'device_uuid');
|
|
38
|
+
const deviceId = get(sensor, 'device_id') ?? get(sensor, 'provider_device_id') ?? get(sensor, 'ident');
|
|
39
|
+
const name = get(sensor, 'device_name') ?? deviceId;
|
|
40
|
+
const imei = get(sensor, 'device_imei') ?? get(sensor, 'imei') ?? get(sensor, 'ident');
|
|
41
|
+
|
|
42
|
+
if (!id && !name && !imei && !deviceId) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
id,
|
|
48
|
+
displayName: name,
|
|
49
|
+
name,
|
|
50
|
+
imei,
|
|
51
|
+
device_id: deviceId,
|
|
52
|
+
ident: get(sensor, 'ident'),
|
|
53
|
+
serial_number: get(sensor, 'device_serial_number'),
|
|
54
|
+
connection_status: get(sensor, 'device_connection_status'),
|
|
55
|
+
status: get(sensor, 'device_status'),
|
|
56
|
+
photo_url: get(sensor, 'device_photo_url') ?? get(sensor, 'photo_url'),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
6
60
|
export default class ConnectivitySensorsIndexController extends Controller {
|
|
7
61
|
@service sensorActions;
|
|
8
62
|
@service deviceActions;
|
|
9
63
|
@service telematicActions;
|
|
10
64
|
@service intl;
|
|
65
|
+
@service store;
|
|
11
66
|
|
|
12
67
|
/** query params */
|
|
13
|
-
@tracked queryParams = ['
|
|
68
|
+
@tracked queryParams = ['page', 'limit', 'sort', 'query', 'telematic', 'device', 'type', 'status', 'serial_number', 'imei', 'last_reading_at', 'created_at', 'updated_at'];
|
|
14
69
|
@tracked page = 1;
|
|
15
70
|
@tracked limit;
|
|
16
71
|
@tracked sort = '-created_at';
|
|
17
|
-
@tracked
|
|
18
|
-
@tracked
|
|
72
|
+
@tracked query;
|
|
73
|
+
@tracked telematic;
|
|
74
|
+
@tracked device;
|
|
75
|
+
@tracked type;
|
|
76
|
+
@tracked status;
|
|
77
|
+
@tracked serial_number;
|
|
78
|
+
@tracked imei;
|
|
79
|
+
@tracked last_reading_at;
|
|
80
|
+
@tracked created_at;
|
|
81
|
+
@tracked updated_at;
|
|
19
82
|
|
|
20
83
|
/** action buttons */
|
|
21
84
|
@tracked actionButtons = [
|
|
@@ -67,14 +130,16 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
67
130
|
resizable: true,
|
|
68
131
|
sortable: true,
|
|
69
132
|
filterable: true,
|
|
70
|
-
filterParam: '
|
|
133
|
+
filterParam: 'query',
|
|
71
134
|
filterComponent: 'filter/string',
|
|
72
135
|
},
|
|
73
136
|
{
|
|
74
137
|
label: 'Telematic',
|
|
75
138
|
valuePath: 'telematic.provider',
|
|
76
|
-
cellComponent: '
|
|
77
|
-
|
|
139
|
+
cellComponent: 'cell/telematic-provider',
|
|
140
|
+
resourcePath: sensorTelematic,
|
|
141
|
+
compact: true,
|
|
142
|
+
action: this.openTelematic,
|
|
78
143
|
permission: 'fleet-ops view telematic',
|
|
79
144
|
resizable: true,
|
|
80
145
|
sortable: true,
|
|
@@ -87,8 +152,10 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
87
152
|
{
|
|
88
153
|
label: 'Device',
|
|
89
154
|
valuePath: 'device.displayName',
|
|
90
|
-
cellComponent: '
|
|
91
|
-
|
|
155
|
+
cellComponent: 'cell/device-identity',
|
|
156
|
+
resourcePath: sensorDevice,
|
|
157
|
+
showStatus: false,
|
|
158
|
+
action: this.openDevice,
|
|
92
159
|
permission: 'fleet-ops view device',
|
|
93
160
|
resizable: true,
|
|
94
161
|
sortable: true,
|
|
@@ -97,10 +164,14 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
97
164
|
filterComponentPlaceholder: 'Select device',
|
|
98
165
|
filterParam: 'device',
|
|
99
166
|
model: 'device',
|
|
167
|
+
modelNamePath: 'displayName',
|
|
168
|
+
query: this.telematic ? { telematic_uuid: this.telematic } : undefined,
|
|
100
169
|
},
|
|
101
170
|
{
|
|
102
171
|
label: 'Type',
|
|
103
172
|
valuePath: 'type',
|
|
173
|
+
cellComponent: 'table/cell/base',
|
|
174
|
+
humanize: true,
|
|
104
175
|
resizable: true,
|
|
105
176
|
sortable: true,
|
|
106
177
|
filterable: true,
|
|
@@ -109,13 +180,16 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
109
180
|
filterOptions: fleetOpsOptions('sensorTypes'),
|
|
110
181
|
},
|
|
111
182
|
{
|
|
112
|
-
label: '
|
|
113
|
-
valuePath: '
|
|
183
|
+
label: 'Last Value',
|
|
184
|
+
valuePath: 'last_value',
|
|
185
|
+
resizable: true,
|
|
186
|
+
sortable: true,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
label: 'Unit',
|
|
190
|
+
valuePath: 'unit',
|
|
114
191
|
resizable: true,
|
|
115
192
|
sortable: true,
|
|
116
|
-
filterable: true,
|
|
117
|
-
filterParam: 'serial_number',
|
|
118
|
-
filterComponent: 'filter/string',
|
|
119
193
|
},
|
|
120
194
|
{
|
|
121
195
|
label: this.intl.t('column.status'),
|
|
@@ -127,6 +201,41 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
127
201
|
filterComponent: 'filter/multi-option',
|
|
128
202
|
filterOptions: fleetOpsOptions('sensorStatuses'),
|
|
129
203
|
},
|
|
204
|
+
{
|
|
205
|
+
label: 'Threshold',
|
|
206
|
+
valuePath: 'threshold_status',
|
|
207
|
+
cellComponent: 'table/cell/status',
|
|
208
|
+
resizable: true,
|
|
209
|
+
sortable: true,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
label: 'Serial Number',
|
|
213
|
+
valuePath: 'serial_number',
|
|
214
|
+
resizable: true,
|
|
215
|
+
sortable: true,
|
|
216
|
+
filterable: true,
|
|
217
|
+
filterParam: 'serial_number',
|
|
218
|
+
filterComponent: 'filter/string',
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
label: 'IMEI',
|
|
222
|
+
valuePath: 'imei',
|
|
223
|
+
resizable: true,
|
|
224
|
+
sortable: true,
|
|
225
|
+
filterable: true,
|
|
226
|
+
filterParam: 'imei',
|
|
227
|
+
filterComponent: 'filter/string',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
label: 'Last Reading',
|
|
231
|
+
valuePath: 'lastReadingAt',
|
|
232
|
+
sortParam: 'last_reading_at',
|
|
233
|
+
resizable: true,
|
|
234
|
+
sortable: true,
|
|
235
|
+
filterable: true,
|
|
236
|
+
filterParam: 'last_reading_at',
|
|
237
|
+
filterComponent: 'filter/date',
|
|
238
|
+
},
|
|
130
239
|
{
|
|
131
240
|
label: this.intl.t('column.created-at'),
|
|
132
241
|
valuePath: 'createdAt',
|
|
@@ -134,6 +243,7 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
134
243
|
resizable: true,
|
|
135
244
|
sortable: true,
|
|
136
245
|
filterable: true,
|
|
246
|
+
filterParam: 'created_at',
|
|
137
247
|
filterComponent: 'filter/date',
|
|
138
248
|
},
|
|
139
249
|
{
|
|
@@ -144,9 +254,9 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
144
254
|
sortable: true,
|
|
145
255
|
hidden: true,
|
|
146
256
|
filterable: true,
|
|
257
|
+
filterParam: 'updated_at',
|
|
147
258
|
filterComponent: 'filter/date',
|
|
148
259
|
},
|
|
149
|
-
|
|
150
260
|
{
|
|
151
261
|
label: '',
|
|
152
262
|
cellComponent: 'table/cell/dropdown',
|
|
@@ -184,4 +294,36 @@ export default class ConnectivitySensorsIndexController extends Controller {
|
|
|
184
294
|
searchable: false,
|
|
185
295
|
},
|
|
186
296
|
];
|
|
297
|
+
|
|
298
|
+
async resolveDevice(device) {
|
|
299
|
+
if (!device?.id) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const cachedDevice = this.store.peekRecord('device', device.id);
|
|
304
|
+
|
|
305
|
+
if (cachedDevice) {
|
|
306
|
+
return cachedDevice;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
try {
|
|
310
|
+
return await this.store.findRecord('device', device.id);
|
|
311
|
+
} catch (_) {
|
|
312
|
+
return device;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@action async openDevice(device) {
|
|
317
|
+
const resolvedDevice = await this.resolveDevice(device);
|
|
318
|
+
|
|
319
|
+
if (resolvedDevice?.id) {
|
|
320
|
+
return this.deviceActions.panel.view(resolvedDevice);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
@action openTelematic(telematic) {
|
|
325
|
+
if (telematic?.id) {
|
|
326
|
+
return this.telematicActions.transition.view(telematic);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
187
329
|
}
|
|
@@ -3,24 +3,36 @@ import { action } from '@ember/object';
|
|
|
3
3
|
import { inject as service } from '@ember/service';
|
|
4
4
|
import { tracked } from '@glimmer/tracking';
|
|
5
5
|
import { task } from 'ember-concurrency';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
{ label: 'Online', value: 'online' },
|
|
9
|
-
{ label: 'Recently Offline', value: 'recently_offline' },
|
|
10
|
-
{ label: 'Offline', value: 'offline' },
|
|
11
|
-
{ label: 'Long Offline', value: 'long_offline' },
|
|
12
|
-
{ label: 'Never Connected', value: 'never_connected' },
|
|
13
|
-
];
|
|
6
|
+
import buildDeviceTableColumns from '../../../../utils/device-table-columns';
|
|
7
|
+
import fleetOpsOptions from '../../../../utils/fleet-ops-options';
|
|
14
8
|
|
|
15
9
|
export default class ConnectivityTelematicsDetailsDevicesController extends Controller {
|
|
16
10
|
@service deviceActions;
|
|
17
11
|
@service fetch;
|
|
18
12
|
@service hostRouter;
|
|
19
13
|
@service intl;
|
|
14
|
+
@service mapManager;
|
|
20
15
|
@service modalsManager;
|
|
21
16
|
@service notifications;
|
|
22
|
-
|
|
23
|
-
@
|
|
17
|
+
@service store;
|
|
18
|
+
@service vehicleActions;
|
|
19
|
+
|
|
20
|
+
@tracked queryParams = [
|
|
21
|
+
'page',
|
|
22
|
+
'limit',
|
|
23
|
+
'sort',
|
|
24
|
+
'query',
|
|
25
|
+
'status',
|
|
26
|
+
'provider',
|
|
27
|
+
'attachment_state',
|
|
28
|
+
'vehicle',
|
|
29
|
+
'connection_status',
|
|
30
|
+
'device_id',
|
|
31
|
+
'type',
|
|
32
|
+
'serial_number',
|
|
33
|
+
'last_online_at',
|
|
34
|
+
'updated_at',
|
|
35
|
+
];
|
|
24
36
|
@tracked telematic;
|
|
25
37
|
@tracked page = 1;
|
|
26
38
|
@tracked limit;
|
|
@@ -32,6 +44,8 @@ export default class ConnectivityTelematicsDetailsDevicesController extends Cont
|
|
|
32
44
|
@tracked vehicle;
|
|
33
45
|
@tracked connection_status;
|
|
34
46
|
@tracked device_id;
|
|
47
|
+
@tracked type;
|
|
48
|
+
@tracked serial_number;
|
|
35
49
|
@tracked last_online_at;
|
|
36
50
|
@tracked updated_at;
|
|
37
51
|
|
|
@@ -57,7 +71,17 @@ export default class ConnectivityTelematicsDetailsDevicesController extends Cont
|
|
|
57
71
|
|
|
58
72
|
get hasActiveFilters() {
|
|
59
73
|
return Boolean(
|
|
60
|
-
this.query ||
|
|
74
|
+
this.query ||
|
|
75
|
+
this.status ||
|
|
76
|
+
this.provider ||
|
|
77
|
+
this.attachment_state ||
|
|
78
|
+
this.vehicle ||
|
|
79
|
+
this.connection_status ||
|
|
80
|
+
this.device_id ||
|
|
81
|
+
this.type ||
|
|
82
|
+
this.serial_number ||
|
|
83
|
+
this.last_online_at ||
|
|
84
|
+
this.updated_at
|
|
61
85
|
);
|
|
62
86
|
}
|
|
63
87
|
|
|
@@ -194,130 +218,16 @@ export default class ConnectivityTelematicsDetailsDevicesController extends Cont
|
|
|
194
218
|
|
|
195
219
|
@tracked bulkActions = [];
|
|
196
220
|
|
|
221
|
+
get deviceTypeOptions() {
|
|
222
|
+
return fleetOpsOptions('deviceTypes');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
get deviceStatusOptions() {
|
|
226
|
+
return fleetOpsOptions('deviceStatuses');
|
|
227
|
+
}
|
|
228
|
+
|
|
197
229
|
get columns() {
|
|
198
|
-
return
|
|
199
|
-
{
|
|
200
|
-
sticky: true,
|
|
201
|
-
label: this.intl.t('column.name'),
|
|
202
|
-
valuePath: 'displayName',
|
|
203
|
-
cellComponent: 'table/cell/anchor',
|
|
204
|
-
action: this.deviceActions.transition.view,
|
|
205
|
-
permission: 'fleet-ops view device',
|
|
206
|
-
resizable: true,
|
|
207
|
-
sortable: true,
|
|
208
|
-
filterable: true,
|
|
209
|
-
filterParam: 'query',
|
|
210
|
-
filterComponent: 'filter/string',
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
label: 'Provider ID',
|
|
214
|
-
valuePath: 'device_id',
|
|
215
|
-
resizable: true,
|
|
216
|
-
sortable: true,
|
|
217
|
-
filterable: true,
|
|
218
|
-
filterParam: 'device_id',
|
|
219
|
-
filterComponent: 'filter/string',
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
label: 'Vehicle',
|
|
223
|
-
valuePath: 'attached_to_name',
|
|
224
|
-
resizable: true,
|
|
225
|
-
sortable: true,
|
|
226
|
-
filterable: true,
|
|
227
|
-
filterParam: 'vehicle',
|
|
228
|
-
filterComponent: 'filter/model',
|
|
229
|
-
filterComponentPlaceholder: 'Select vehicle',
|
|
230
|
-
model: 'vehicle',
|
|
231
|
-
modelNamePath: 'displayName',
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
label: 'Connection',
|
|
235
|
-
valuePath: 'connection_status',
|
|
236
|
-
cellComponent: 'table/cell/status',
|
|
237
|
-
resizable: true,
|
|
238
|
-
sortable: true,
|
|
239
|
-
filterable: true,
|
|
240
|
-
filterParam: 'connection_status',
|
|
241
|
-
filterComponent: 'filter/multi-option',
|
|
242
|
-
filterOptions: connectionStatusOptions,
|
|
243
|
-
filterOptionLabel: 'label',
|
|
244
|
-
filterOptionValue: 'value',
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
label: 'Last Seen',
|
|
248
|
-
valuePath: 'lastOnlineAt',
|
|
249
|
-
sortParam: 'last_online_at',
|
|
250
|
-
resizable: true,
|
|
251
|
-
sortable: true,
|
|
252
|
-
filterable: true,
|
|
253
|
-
filterParam: 'last_online_at',
|
|
254
|
-
filterComponent: 'filter/date',
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
label: 'Attachment',
|
|
258
|
-
valuePath: 'attachable_uuid',
|
|
259
|
-
hidden: true,
|
|
260
|
-
resizable: true,
|
|
261
|
-
sortable: false,
|
|
262
|
-
filterable: true,
|
|
263
|
-
filterParam: 'attachment_state',
|
|
264
|
-
filterComponent: 'filter/select',
|
|
265
|
-
filterOptions: [
|
|
266
|
-
{ label: 'Attached', value: 'attached' },
|
|
267
|
-
{ label: 'Unattached', value: 'unattached' },
|
|
268
|
-
],
|
|
269
|
-
filterOptionLabel: 'label',
|
|
270
|
-
filterOptionValue: 'value',
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
label: this.intl.t('column.updated-at'),
|
|
274
|
-
valuePath: 'updatedAt',
|
|
275
|
-
sortParam: 'updated_at',
|
|
276
|
-
resizable: true,
|
|
277
|
-
sortable: true,
|
|
278
|
-
hidden: true,
|
|
279
|
-
filterable: true,
|
|
280
|
-
filterComponent: 'filter/date',
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
label: '',
|
|
284
|
-
cellComponent: 'table/cell/dropdown',
|
|
285
|
-
ddButtonText: false,
|
|
286
|
-
ddButtonIcon: 'ellipsis-h',
|
|
287
|
-
ddButtonIconPrefix: 'fas',
|
|
288
|
-
ddMenuLabel: this.intl.t('common.resource-actions', { resource: this.intl.t('resource.device') }),
|
|
289
|
-
cellClassNames: 'overflow-visible align-middle',
|
|
290
|
-
wrapperClass: 'flex items-center justify-end mx-2',
|
|
291
|
-
sticky: 'right',
|
|
292
|
-
width: 60,
|
|
293
|
-
actions: [
|
|
294
|
-
{
|
|
295
|
-
label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.device') }),
|
|
296
|
-
fn: this.deviceActions.transition.view,
|
|
297
|
-
permission: 'fleet-ops view device',
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.device') }),
|
|
301
|
-
fn: this.deviceActions.transition.edit,
|
|
302
|
-
permission: 'fleet-ops update device',
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
label: 'Attach or change vehicle',
|
|
306
|
-
fn: this.openAttachDeviceModal,
|
|
307
|
-
permission: 'fleet-ops update device',
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
label: 'Review recent events',
|
|
311
|
-
fn: this.openDeviceEvents,
|
|
312
|
-
permission: 'fleet-ops view device-event',
|
|
313
|
-
},
|
|
314
|
-
],
|
|
315
|
-
sortable: false,
|
|
316
|
-
filterable: false,
|
|
317
|
-
resizable: false,
|
|
318
|
-
searchable: false,
|
|
319
|
-
},
|
|
320
|
-
];
|
|
230
|
+
return buildDeviceTableColumns(this, { showProvider: false, deviceActionMode: 'panel', showDeviceStatus: false });
|
|
321
231
|
}
|
|
322
232
|
|
|
323
233
|
@action refresh() {
|
|
@@ -336,6 +246,8 @@ export default class ConnectivityTelematicsDetailsDevicesController extends Cont
|
|
|
336
246
|
this.vehicle = null;
|
|
337
247
|
this.connection_status = null;
|
|
338
248
|
this.device_id = null;
|
|
249
|
+
this.type = null;
|
|
250
|
+
this.serial_number = null;
|
|
339
251
|
this.last_online_at = null;
|
|
340
252
|
this.updated_at = null;
|
|
341
253
|
this.page = 1;
|
|
@@ -358,6 +270,86 @@ export default class ConnectivityTelematicsDetailsDevicesController extends Cont
|
|
|
358
270
|
});
|
|
359
271
|
}
|
|
360
272
|
|
|
273
|
+
@action hasAttachedVehicle(device) {
|
|
274
|
+
return Boolean(device?.attachable_uuid && this.isVehicleAttachment(device));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@action async viewAttachedVehicle(device) {
|
|
278
|
+
const vehicle = await this.resolveAttachedVehicle(device);
|
|
279
|
+
|
|
280
|
+
if (!vehicle) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return this.vehicleActions.panel.view(vehicle);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@action async locateAttachedVehicle(device) {
|
|
288
|
+
const vehicle = await this.resolveAttachedVehicle(device);
|
|
289
|
+
|
|
290
|
+
if (!vehicle) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
await this.transitionToLiveMap();
|
|
295
|
+
await this.mapManager.waitForMap({ timeoutMs: 8000 });
|
|
296
|
+
|
|
297
|
+
this.mapManager.focusResource(vehicle, 16, {
|
|
298
|
+
paddingBottomRight: [300, 200],
|
|
299
|
+
moveend: () => {
|
|
300
|
+
this.vehicleActions.panel.view(vehicle, { closeOnTransition: true });
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async transitionToLiveMap() {
|
|
306
|
+
try {
|
|
307
|
+
await this.hostRouter.transitionTo('console.fleet-ops.operations.orders.index', { queryParams: { layout: 'map' } });
|
|
308
|
+
} catch (_) {
|
|
309
|
+
// Keep locate actions usable even if the current transition is already in-flight.
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
isVehicleAttachment(device) {
|
|
314
|
+
const attachableType = `${device?.attachable_type ?? ''}`.toLowerCase();
|
|
315
|
+
|
|
316
|
+
return !attachableType || attachableType.includes('vehicle');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async resolveAttachedVehicle(device) {
|
|
320
|
+
if (!device?.attachable_uuid) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (!this.isVehicleAttachment(device)) {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const attachable = device.attachable;
|
|
329
|
+
|
|
330
|
+
if (attachable && typeof attachable.then !== 'function') {
|
|
331
|
+
return attachable;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (attachable && typeof attachable.then === 'function') {
|
|
335
|
+
return await attachable;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const cachedVehicle = this.store.peekRecord('vehicle', device.attachable_uuid);
|
|
339
|
+
|
|
340
|
+
if (cachedVehicle) {
|
|
341
|
+
return cachedVehicle;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
return await this.store.findRecord('vehicle', device.attachable_uuid);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
this.notifications.serverError(error);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
|
|
361
353
|
@action openDeviceEvents(device) {
|
|
362
354
|
return this.hostRouter.transitionTo('console.fleet-ops.connectivity.telematics.details.events', this.telematic, {
|
|
363
355
|
queryParams: { device_uuid: device.id },
|
|
@@ -61,8 +61,7 @@ export default class MaintenanceEquipmentIndexController extends Controller {
|
|
|
61
61
|
{
|
|
62
62
|
label: this.intl.t('column.name'),
|
|
63
63
|
valuePath: 'name',
|
|
64
|
-
cellComponent: '
|
|
65
|
-
cellClassNames: 'uppercase',
|
|
64
|
+
cellComponent: 'cell/equipment-identity',
|
|
66
65
|
action: this.equipmentActions.transition.view,
|
|
67
66
|
permission: 'fleet-ops view equipment',
|
|
68
67
|
resizable: true,
|
|
@@ -61,8 +61,7 @@ export default class MaintenancePartsIndexController extends Controller {
|
|
|
61
61
|
{
|
|
62
62
|
label: this.intl.t('column.name'),
|
|
63
63
|
valuePath: 'name',
|
|
64
|
-
cellComponent: '
|
|
65
|
-
cellClassNames: 'uppercase',
|
|
64
|
+
cellComponent: 'cell/part-identity',
|
|
66
65
|
action: this.partActions.transition.view,
|
|
67
66
|
permission: 'fleet-ops view part',
|
|
68
67
|
resizable: true,
|