@fleetbase/fleetops-engine 0.6.20 → 0.6.22
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/custom-entity/form.hbs +14 -14
- package/addon/components/device/card.hbs +1 -0
- package/addon/components/device/card.js +3 -0
- package/addon/components/device/details.hbs +92 -43
- package/addon/components/device/form.hbs +108 -60
- package/addon/components/device/form.js +36 -8
- package/addon/components/device/manager.hbs +29 -0
- package/addon/components/device/manager.js +95 -0
- package/addon/components/device/panel-header.hbs +32 -0
- package/addon/components/device/panel-header.js +3 -0
- package/addon/components/device/pill.hbs +16 -0
- package/addon/components/device/pill.js +3 -0
- package/addon/components/driver/details.hbs +4 -0
- package/addon/components/driver/details.js +19 -1
- package/addon/components/driver/form.hbs +14 -3
- package/addon/components/driver/form.js +49 -47
- package/addon/components/driver/pill.hbs +17 -0
- package/addon/components/driver/pill.js +3 -0
- package/addon/components/entity/form.hbs +7 -5
- package/addon/components/layout/fleet-ops-sidebar.js +12 -12
- package/addon/components/map/drawer/device-event-listing.hbs +64 -0
- package/addon/components/map/drawer/device-event-listing.js +181 -0
- package/addon/components/map/drawer/position-listing.hbs +100 -0
- package/addon/components/map/drawer/position-listing.js +455 -0
- package/addon/components/map/drawer.js +2 -0
- package/addon/components/map/leaflet-live-map.hbs +7 -2
- package/addon/components/modals/attach-device.hbs +18 -0
- package/addon/components/modals/attach-device.js +3 -0
- package/addon/components/order/details/detail.hbs +2 -54
- package/addon/components/order/details/detail.js +1 -0
- package/addon/components/order/details/payload.hbs +6 -4
- package/addon/components/order/details/payload.js +2 -0
- package/addon/components/order/pill.hbs +34 -0
- package/addon/components/order/pill.js +3 -0
- package/addon/components/order-config-manager/custom-fields.js +1 -1
- package/addon/components/positions-replay.hbs +339 -0
- package/addon/components/positions-replay.js +409 -0
- package/addon/components/sensor/details.hbs +64 -38
- package/addon/components/sensor/form.hbs +112 -63
- package/addon/components/sensor/form.js +36 -24
- package/addon/components/sensor/panel-header.hbs +32 -0
- package/addon/components/sensor/panel-header.js +3 -0
- package/addon/components/telematic/details.hbs +40 -16
- package/addon/components/telematic/form.hbs +63 -64
- package/addon/components/telematic/form.js +73 -4
- package/addon/components/vehicle/card.hbs +2 -2
- package/addon/components/vehicle/details.hbs +4 -0
- package/addon/components/vehicle/details.js +19 -1
- package/addon/components/vehicle/form.hbs +4 -0
- package/addon/components/vehicle/pill.hbs +34 -0
- package/addon/components/vehicle/pill.js +3 -0
- package/addon/controllers/analytics/reports/index/edit.js +1 -1
- package/addon/controllers/connectivity/devices/index/details.js +22 -1
- package/addon/controllers/connectivity/devices/index/edit.js +66 -1
- package/addon/controllers/connectivity/devices/index.js +51 -9
- package/addon/controllers/connectivity/events/index.js +65 -16
- package/addon/controllers/connectivity/sensors/index/details.js +22 -1
- package/addon/controllers/connectivity/sensors/index/edit.js +66 -1
- package/addon/controllers/connectivity/sensors/index.js +66 -6
- package/addon/controllers/connectivity/telematics/index/details.js +22 -1
- package/addon/controllers/connectivity/telematics/index/edit.js +66 -1
- package/addon/controllers/connectivity/telematics/index.js +20 -11
- package/addon/controllers/management/fleets/index/details.js +26 -21
- package/addon/controllers/management/fleets/index/edit.js +9 -6
- package/addon/controllers/management/vehicles/index/details.js +26 -13
- package/addon/controllers/settings/custom-fields.js +6 -0
- package/addon/helpers/get-fleet-ops-option-label.js +11 -0
- package/addon/routes/connectivity/devices/index/details.js +27 -1
- package/addon/routes/connectivity/devices/index/edit.js +27 -1
- package/addon/routes/connectivity/sensors/index/details.js +27 -1
- package/addon/routes/connectivity/sensors/index/edit.js +27 -1
- package/addon/routes/connectivity/telematics/index/details.js +27 -1
- package/addon/routes/connectivity/telematics/index/edit.js +27 -1
- package/addon/routes/management/drivers/index/details/positions.js +3 -0
- package/addon/routes/management/vehicles/index/details/positions.js +3 -0
- package/addon/routes.js +4 -0
- package/addon/services/movement-tracker.js +81 -30
- package/addon/services/position-playback.js +486 -0
- package/addon/services/resource-metadata.js +46 -0
- package/addon/styles/fleetops-engine.css +157 -0
- package/addon/templates/connectivity/devices/index/details/index.hbs +2 -2
- package/addon/templates/connectivity/devices/index/details.hbs +15 -2
- package/addon/templates/connectivity/devices/index/edit.hbs +1 -1
- package/addon/templates/connectivity/events/index.hbs +1 -1
- package/addon/templates/connectivity/sensors/index/details/index.hbs +2 -2
- package/addon/templates/connectivity/sensors/index/details.hbs +15 -2
- package/addon/templates/connectivity/sensors/index/edit.hbs +1 -1
- package/addon/templates/connectivity/telematics/index/details/index.hbs +2 -2
- package/addon/templates/connectivity/telematics/index/details.hbs +14 -2
- package/addon/templates/connectivity/telematics/index/edit.hbs +1 -1
- package/addon/templates/management/drivers/index/details/positions.hbs +2 -0
- package/addon/templates/management/vehicles/index/details/devices.hbs +1 -2
- package/addon/templates/management/vehicles/index/details/positions.hbs +1 -0
- package/addon/utils/fleet-ops-options.js +95 -0
- package/app/components/device/card.js +1 -0
- package/app/components/device/manager.js +1 -0
- package/app/components/device/panel-header.js +1 -0
- package/app/components/device/pill.js +1 -0
- package/app/components/driver/pill.js +1 -0
- package/app/components/map/drawer/device-event-listing.js +1 -0
- package/app/components/map/drawer/position-listing.js +1 -0
- package/app/components/modals/attach-device.js +1 -0
- package/app/components/order/pill.js +1 -0
- package/app/components/positions-replay.js +1 -0
- package/app/components/sensor/panel-header.js +1 -0
- package/app/components/vehicle/pill.js +1 -0
- package/app/helpers/get-fleet-ops-option-label.js +1 -0
- package/app/routes/management/drivers/index/details/positions.js +1 -0
- package/app/routes/management/vehicles/index/details/positions.js +1 -0
- package/app/services/position-playback.js +1 -0
- package/app/services/resource-metadata.js +1 -0
- package/app/templates/management/drivers/index/details/positions.js +1 -0
- package/app/templates/management/vehicles/index/details/positions.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/config/telematics.php +111 -0
- package/server/migrations/2025_10_27_000001_add_telematics_integration_fields.php +70 -0
- package/server/migrations/2025_10_27_171322_fix_device_column_names.php +107 -0
- package/server/migrations/2025_10_27_203023_add_company_uuid_to_device_events_table.php +28 -0
- package/server/src/Console/Commands/ReplayVehicleLocations.php +225 -0
- package/server/src/Contracts/TelematicProviderDescriptor.php +72 -0
- package/server/src/Contracts/TelematicProviderInterface.php +119 -0
- package/server/src/Exceptions/TelematicProviderException.php +14 -0
- package/server/src/Exceptions/TelematicRateLimitExceededException.php +12 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +24 -14
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +27 -7
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +22 -0
- package/server/src/Http/Controllers/Internal/v1/PositionController.php +240 -0
- package/server/src/Http/Controllers/Internal/v1/SensorController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/TelematicController.php +141 -0
- package/server/src/Http/Controllers/TelematicWebhookController.php +169 -0
- package/server/src/Http/Filter/DeviceEventFilter.php +68 -0
- package/server/src/Http/Filter/PositionFilter.php +35 -0
- package/server/src/Http/Resources/v1/Position.php +44 -0
- package/server/src/Jobs/ReplayPositions.php +64 -0
- package/server/src/Jobs/SendPositionReplay.php +65 -0
- package/server/src/Jobs/SyncTelematicDevicesJob.php +106 -0
- package/server/src/Jobs/TestTelematicConnectionJob.php +102 -0
- package/server/src/Models/Asset.php +10 -8
- package/server/src/Models/Device.php +79 -12
- package/server/src/Models/DeviceEvent.php +33 -3
- package/server/src/Models/Driver.php +28 -1
- package/server/src/Models/Maintenance.php +15 -12
- package/server/src/Models/Part.php +2 -0
- package/server/src/Models/Payload.php +0 -1
- package/server/src/Models/Place.php +4 -1
- package/server/src/Models/Position.php +27 -17
- package/server/src/Models/Sensor.php +78 -13
- package/server/src/Models/Telematic.php +116 -6
- package/server/src/Models/TrackingNumber.php +3 -1
- package/server/src/Models/Vehicle.php +8 -11
- package/server/src/Models/WorkOrder.php +8 -5
- package/server/src/Providers/FleetOpsServiceProvider.php +2 -0
- package/server/src/Support/Telematics/Providers/AbstractProvider.php +151 -0
- package/server/src/Support/Telematics/Providers/FlespiProvider.php +182 -0
- package/server/src/Support/Telematics/Providers/GeotabProvider.php +181 -0
- package/server/src/Support/Telematics/Providers/SamsaraProvider.php +177 -0
- package/server/src/Support/Telematics/TelematicProviderRegistry.php +147 -0
- package/server/src/Support/Telematics/TelematicService.php +223 -0
- package/server/src/Support/Utils.php +1 -1
- package/server/src/routes.php +24 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<div class="form-wrapper" ...attributes>
|
|
2
|
-
<ContentPanel @title={{t "custom-entity.
|
|
2
|
+
<ContentPanel @title={{t "custom-entity.fields.details"}} @open={{true}} @wrapperClass="bordered-top">
|
|
3
3
|
<div class="space-y-2">
|
|
4
|
-
<InputGroup @name={{t "custom-entity.
|
|
5
|
-
<InputGroup @name={{t "custom-entity.
|
|
6
|
-
<InputGroup @name={{t "custom-entity.
|
|
4
|
+
<InputGroup @name={{t "custom-entity.fields.name"}} @value={{@resource.name}} />
|
|
5
|
+
<InputGroup @name={{t "custom-entity.fields.description"}} @value={{@resource.description}} />
|
|
6
|
+
<InputGroup @name={{t "custom-entity.fields.type"}} @value={{@resource.type}} {{on "input" this.setCustomEntityType}} />
|
|
7
7
|
</div>
|
|
8
8
|
</ContentPanel>
|
|
9
|
-
<ContentPanel @title={{t "custom-entity.
|
|
9
|
+
<ContentPanel @title={{t "custom-entity.fields.entity-image"}} @open={{true}} @wrapperClass="bordered-top">
|
|
10
10
|
<div class="w-32 flex flex-col items-center">
|
|
11
11
|
<Image src={{@resource.photo_url}} alt={{@resource.name}} height="128" width="128" class="h-32 w-32 rounded-md" />
|
|
12
12
|
<UploadButton
|
|
@@ -19,32 +19,32 @@
|
|
|
19
19
|
/>
|
|
20
20
|
</div>
|
|
21
21
|
</ContentPanel>
|
|
22
|
-
<ContentPanel @title={{t "custom-entity.
|
|
22
|
+
<ContentPanel @title={{t "custom-entity.fields.measurements"}} @open={{true}} @wrapperClass="bordered-top">
|
|
23
23
|
<div class="grid grid-cols-2 gap-2">
|
|
24
24
|
<InputGroup
|
|
25
|
-
@name={{t "custom-entity.
|
|
26
|
-
@helpText={{t "custom-entity.
|
|
25
|
+
@name={{t "custom-entity.fields.length"}}
|
|
26
|
+
@helpText={{t "custom-entity.fields.length-text"}}
|
|
27
27
|
@wrapperClass="mb-2"
|
|
28
28
|
>
|
|
29
29
|
<UnitInput class="w-full" @value={{@resource.length}} @unit={{@resource.dimensions_unit}} @canSelectUnit={{true}} @onUnitChange={{this.updateCustomEntityDimensionsUnit}} />
|
|
30
30
|
</InputGroup>
|
|
31
31
|
<InputGroup
|
|
32
|
-
@name={{t "custom-entity.
|
|
33
|
-
@helpText={{t "custom-entity.
|
|
32
|
+
@name={{t "custom-entity.fields.width"}}
|
|
33
|
+
@helpText={{t "custom-entity.fields.width-text"}}
|
|
34
34
|
@wrapperClass="mb-2"
|
|
35
35
|
>
|
|
36
36
|
<UnitInput class="w-full" @value={{@resource.width}} @unit={{@resource.dimensions_unit}} @canSelectUnit={{true}} @onUnitChange={{this.updateCustomEntityDimensionsUnit}} />
|
|
37
37
|
</InputGroup>
|
|
38
38
|
<InputGroup
|
|
39
|
-
@name={{t "custom-entity.
|
|
40
|
-
@helpText={{t "custom-entity.
|
|
39
|
+
@name={{t "custom-entity.fields.height"}}
|
|
40
|
+
@helpText={{t "custom-entity.fields.height-text"}}
|
|
41
41
|
@wrapperClass="mb-2"
|
|
42
42
|
>
|
|
43
43
|
<UnitInput class="w-full" @value={{@resource.height}} @unit={{@resource.dimensions_unit}} @canSelectUnit={{true}} @onUnitChange={{this.updateCustomEntityDimensionsUnit}} />
|
|
44
44
|
</InputGroup>
|
|
45
45
|
<InputGroup
|
|
46
|
-
@name={{t "custom-entity.
|
|
47
|
-
@helpText={{t "custom-entity.
|
|
46
|
+
@name={{t "custom-entity.fields.weight"}}
|
|
47
|
+
@helpText={{t "custom-entity.fields.weight-text"}}
|
|
48
48
|
@wrapperClass="mb-2"
|
|
49
49
|
>
|
|
50
50
|
<UnitInput
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{yield}}
|
|
@@ -1,14 +1,44 @@
|
|
|
1
1
|
<div class="details-wrapper" ...attributes>
|
|
2
|
-
<ContentPanel @title=
|
|
2
|
+
<ContentPanel @title="Integration" @open={{true}} @wrapperClass="bordered-top">
|
|
3
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
|
4
|
+
<div class="field-info-container lg:col-span-3">
|
|
5
|
+
<div class="field-name">{{t "device.fields.telematic"}}</div>
|
|
6
|
+
<div class="field-value">
|
|
7
|
+
{{#if @resource.telematic}}
|
|
8
|
+
<div class="flex flex-row space-x-2 text-sm">
|
|
9
|
+
<div class="pt-1.5">
|
|
10
|
+
<Image src={{@resource.telematic.provider_descriptor.icon}} class="w-5 h-5" />
|
|
11
|
+
</div>
|
|
12
|
+
<div>
|
|
13
|
+
<div class="font-semibold">{{@resource.telematic.provider_descriptor.label}}</div>
|
|
14
|
+
<div class="text-xs text-gray-400 dark:text-gray-500">
|
|
15
|
+
{{n-a @resource.telematic.provider_descriptor.description}}
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
{{else}}
|
|
20
|
+
{{n-a null}}
|
|
21
|
+
{{/if}}
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div class="field-info-container">
|
|
26
|
+
<div class="field-name">{{t "device.fields.data-frequency"}}</div>
|
|
27
|
+
<div class="field-value">{{n-a @resource.data_frequency}}</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</ContentPanel>
|
|
31
|
+
|
|
32
|
+
<ContentPanel @title="Identity" @open={{true}} @wrapperClass="bordered-top">
|
|
3
33
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
|
4
34
|
<div class="field-info-container">
|
|
5
35
|
<div class="field-name">{{t "device.fields.device-name"}}</div>
|
|
6
|
-
<div class="field-value">{{n-a @resource.
|
|
36
|
+
<div class="field-value">{{n-a @resource.name}}</div>
|
|
7
37
|
</div>
|
|
8
38
|
|
|
9
39
|
<div class="field-info-container">
|
|
10
40
|
<div class="field-name">{{t "device.fields.device-type"}}</div>
|
|
11
|
-
<div class="field-value">{{
|
|
41
|
+
<div class="field-value">{{n-a (get-fleet-ops-option-label "deviceTypes" @resource.type)}}</div>
|
|
12
42
|
</div>
|
|
13
43
|
|
|
14
44
|
<div class="field-info-container">
|
|
@@ -17,13 +47,22 @@
|
|
|
17
47
|
</div>
|
|
18
48
|
|
|
19
49
|
<div class="field-info-container">
|
|
20
|
-
<div class="field-name">
|
|
21
|
-
<div class="field-value">{{n-a @resource.
|
|
50
|
+
<div class="field-name">Internal ID</div>
|
|
51
|
+
<div class="field-value">{{n-a @resource.internal_id}}</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</ContentPanel>
|
|
55
|
+
|
|
56
|
+
<ContentPanel @title="Hardware" @open={{true}} @wrapperClass="bordered-top">
|
|
57
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
|
58
|
+
<div class="field-info-container">
|
|
59
|
+
<div class="field-name">{{t "device.fields.device-provider"}}</div>
|
|
60
|
+
<div class="field-value">{{n-a (titleize @resource.provider)}}</div>
|
|
22
61
|
</div>
|
|
23
62
|
|
|
24
63
|
<div class="field-info-container">
|
|
25
|
-
<div class="field-name">{{t "device.fields.model"}}</div>
|
|
26
|
-
<div class="field-value">{{n-a @resource.
|
|
64
|
+
<div class="field-name">{{t "device.fields.device-model"}}</div>
|
|
65
|
+
<div class="field-value">{{n-a @resource.model}}</div>
|
|
27
66
|
</div>
|
|
28
67
|
|
|
29
68
|
<div class="field-info-container">
|
|
@@ -31,70 +70,80 @@
|
|
|
31
70
|
<div class="field-value">{{n-a @resource.manufacturer}}</div>
|
|
32
71
|
</div>
|
|
33
72
|
|
|
34
|
-
<div class="field-info-container">
|
|
73
|
+
<div class="field-info-container lg:col-span-3">
|
|
35
74
|
<div class="field-name">{{t "device.fields.serial-number"}}</div>
|
|
36
75
|
<div class="field-value">{{n-a @resource.serial_number}}</div>
|
|
37
76
|
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</ContentPanel>
|
|
38
79
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<div class="field-info-container">
|
|
45
|
-
<div class="field-name">{{t "device.fields.status"}}</div>
|
|
46
|
-
<div class="field-value">
|
|
47
|
-
<Badge @status={{@resource.status}}>{{smart-humanize @resource.status}}</Badge>
|
|
48
|
-
</div>
|
|
80
|
+
<ContentPanel @title="Installation & Maintenance" @open={{true}} @wrapperClass="bordered-top">
|
|
81
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
|
82
|
+
<div class="field-info-container lg:col-span-2">
|
|
83
|
+
<div class="field-name">{{t "device.fields.device-location"}}</div>
|
|
84
|
+
<div class="field-value">{{n-a @resource.location}}</div>
|
|
49
85
|
</div>
|
|
50
86
|
|
|
51
87
|
<div class="field-info-container">
|
|
52
88
|
<div class="field-name">{{t "device.fields.installation-date"}}</div>
|
|
53
|
-
<div class="field-value">{{format-date @resource.installation_date}}</div>
|
|
89
|
+
<div class="field-value">{{or (format-date @resource.installation_date) "-"}}</div>
|
|
54
90
|
</div>
|
|
55
91
|
|
|
56
92
|
<div class="field-info-container">
|
|
57
|
-
<div class="field-name">{{t "device.fields.last-maintenance"}}</div>
|
|
58
|
-
<div class="field-value">{{format-date @resource.last_maintenance_date}}</div>
|
|
93
|
+
<div class="field-name">{{t "device.fields.last-maintenance-date"}}</div>
|
|
94
|
+
<div class="field-value">{{or (format-date @resource.last_maintenance_date) "-"}}</div>
|
|
59
95
|
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</ContentPanel>
|
|
60
98
|
|
|
99
|
+
<ContentPanel @title="Connectivity" @open={{true}} @wrapperClass="bordered-top">
|
|
100
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
|
61
101
|
<div class="field-info-container">
|
|
62
|
-
<div class="field-name">{{t "
|
|
63
|
-
<div class="field-value">
|
|
102
|
+
<div class="field-name">{{t "common.online"}}</div>
|
|
103
|
+
<div class="field-value">
|
|
104
|
+
{{#if @resource.is_online}}
|
|
105
|
+
<Badge @status="online">{{t "common.online"}}</Badge>
|
|
106
|
+
{{else}}
|
|
107
|
+
<Badge @status="offline">{{t "common.offline"}}</Badge>
|
|
108
|
+
{{/if}}
|
|
109
|
+
</div>
|
|
64
110
|
</div>
|
|
65
111
|
|
|
66
112
|
<div class="field-info-container">
|
|
67
|
-
<div class="field-name">{{t "
|
|
68
|
-
<div class="field-value">{{
|
|
113
|
+
<div class="field-name">{{t "common.last-seen-at"}}</div>
|
|
114
|
+
<div class="field-value">{{or (format-date @resource.last_online_at) "-"}}</div>
|
|
69
115
|
</div>
|
|
70
116
|
|
|
71
|
-
|
|
72
|
-
<div class="field-
|
|
73
|
-
|
|
74
|
-
|
|
117
|
+
{{#if @resource.signal_strength}}
|
|
118
|
+
<div class="field-info-container">
|
|
119
|
+
<div class="field-name">{{t "device.fields.signal-strength"}}</div>
|
|
120
|
+
<div class="field-value">{{n-a @resource.signal_strength}}</div>
|
|
121
|
+
</div>
|
|
122
|
+
{{/if}}
|
|
123
|
+
</div>
|
|
124
|
+
</ContentPanel>
|
|
75
125
|
|
|
126
|
+
<ContentPanel @title="Warranty & Status" @open={{true}} @wrapperClass="bordered-top">
|
|
127
|
+
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
|
|
76
128
|
<div class="field-info-container">
|
|
77
|
-
<div class="field-name">{{t "device.fields.
|
|
129
|
+
<div class="field-name">{{t "device.fields.status"}}</div>
|
|
78
130
|
<div class="field-value">
|
|
79
|
-
{{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<Badge @status="danger">{{t "device.fields.offline"}}</Badge>
|
|
83
|
-
{{/if}}
|
|
131
|
+
<Badge @status={{@resource.status}}>
|
|
132
|
+
{{smart-humanize @resource.status}}
|
|
133
|
+
</Badge>
|
|
84
134
|
</div>
|
|
85
135
|
</div>
|
|
86
136
|
|
|
87
|
-
<div class="field-info-container">
|
|
88
|
-
<div class="field-name">{{t "device.fields.
|
|
89
|
-
<div class="field-value">{{n-a @resource.
|
|
137
|
+
<div class="field-info-container lg:col-span-2">
|
|
138
|
+
<div class="field-name">{{t "device.fields.warranty"}}</div>
|
|
139
|
+
<div class="field-value">{{n-a @resource.warranty.name}}</div>
|
|
90
140
|
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</ContentPanel>
|
|
91
143
|
|
|
144
|
+
<ContentPanel @title="Notes" @open={{true}} @wrapperClass="bordered-top">
|
|
145
|
+
<div class="grid grid-cols-1 lg:grid-cols-1 gap-2">
|
|
92
146
|
<div class="field-info-container">
|
|
93
|
-
<div class="field-name">{{t "device.fields.last-online"}}</div>
|
|
94
|
-
<div class="field-value">{{format-date @resource.last_online_at}}</div>
|
|
95
|
-
</div>
|
|
96
|
-
|
|
97
|
-
<div class="field-info-container col-span-3">
|
|
98
147
|
<div class="field-name">{{t "device.fields.notes"}}</div>
|
|
99
148
|
<div class="field-value">{{n-a @resource.notes}}</div>
|
|
100
149
|
</div>
|
|
@@ -1,45 +1,109 @@
|
|
|
1
1
|
<div class="form-wrapper" ...attributes>
|
|
2
|
-
<ContentPanel @title=
|
|
2
|
+
<ContentPanel @title="Integration" @open={{true}} @wrapperClass="bordered-top">
|
|
3
3
|
<div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-2 no-input-group-padding text-xs">
|
|
4
|
-
<InputGroup @name={{t "device.fields.
|
|
5
|
-
<
|
|
6
|
-
@
|
|
7
|
-
@
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
<InputGroup @name={{t "device.fields.telematic"}}>
|
|
5
|
+
<ModelSelect
|
|
6
|
+
@modelName="telematic"
|
|
7
|
+
@selectedModel={{@resource.telematic}}
|
|
8
|
+
@placeholder={{t "device.fields.telematic-placeholder"}}
|
|
9
|
+
@triggerClass="form-select form-input"
|
|
10
|
+
@infiniteScroll={{false}}
|
|
11
|
+
@renderInPlace={{true}}
|
|
12
|
+
@onChange={{this.selectTelematic}}
|
|
13
|
+
@disabled={{cannot-write @resource}}
|
|
14
|
+
as |model|
|
|
15
|
+
>
|
|
16
|
+
<div class="space-x-2 text-sm">
|
|
17
|
+
<div class="inline-block align-top">
|
|
18
|
+
<div class="hide-from-trigger h-1.5 w-full" />
|
|
19
|
+
<Image src={{model.provider_descriptor.icon}} class="w-5 h-5" />
|
|
20
|
+
</div>
|
|
21
|
+
<div class="inline-block">
|
|
22
|
+
<div class="font-semibold normalize-in-trigger">{{or model.name model.public_id}}</div>
|
|
23
|
+
<div class="hide-from-trigger">{{n-a model.provider_descriptor.label (titleize model.provider)}}</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</ModelSelect>
|
|
12
27
|
</InputGroup>
|
|
13
28
|
|
|
14
29
|
<InputGroup @name={{t "device.fields.device-type"}}>
|
|
15
30
|
<div class="fleetbase-model-select fleetbase-power-select ember-model-select">
|
|
16
31
|
<PowerSelect
|
|
17
|
-
@options={{
|
|
18
|
-
@selected={{@resource.
|
|
19
|
-
@onChange={{
|
|
20
|
-
@placeholder={{t "
|
|
32
|
+
@options={{get-fleet-ops-options "deviceTypes"}}
|
|
33
|
+
@selected={{find-by "value" @resource.type (get-fleet-ops-options "deviceTypes")}}
|
|
34
|
+
@onChange={{set-model-attr @resource "type"}}
|
|
35
|
+
@placeholder={{t "common.select-field" field=(t "common.type")}}
|
|
21
36
|
@triggerClass="form-select form-input"
|
|
22
37
|
@disabled={{cannot-write @resource}}
|
|
23
|
-
as |
|
|
38
|
+
as |option|
|
|
24
39
|
>
|
|
25
|
-
|
|
40
|
+
<div class="text-sm">
|
|
41
|
+
<div class="font-semibold normalize-in-trigger">{{option.label}}</div>
|
|
42
|
+
<div class="hide-from-trigger">{{option.description}}</div>
|
|
43
|
+
</div>
|
|
26
44
|
</PowerSelect>
|
|
27
45
|
</div>
|
|
28
46
|
</InputGroup>
|
|
29
47
|
|
|
30
|
-
<InputGroup @name={{t "device.fields.
|
|
48
|
+
<InputGroup @name={{t "device.fields.data-frequency"}}>
|
|
31
49
|
<Input
|
|
32
|
-
@value={{@resource.
|
|
50
|
+
@value={{@resource.data_frequency}}
|
|
33
51
|
@type="text"
|
|
34
52
|
class="w-full form-input"
|
|
35
|
-
placeholder={{t "device.fields.
|
|
53
|
+
placeholder={{t "device.fields.data-frequency-placeholder"}}
|
|
36
54
|
disabled={{cannot-write @resource}}
|
|
37
55
|
/>
|
|
38
56
|
</InputGroup>
|
|
57
|
+
</div>
|
|
58
|
+
</ContentPanel>
|
|
39
59
|
|
|
60
|
+
<ContentPanel @title="Identity" @open={{true}} @wrapperClass="bordered-top">
|
|
61
|
+
<div class="flex flex-row space-x-3 mb-3">
|
|
62
|
+
<div class="flex items-center justify-start rounded-full">
|
|
63
|
+
<Image src={{@resource.photo_url}} alt={{@resource.name}} height="48" width="48" class="h-14 w-14 rounded-full shadow-sm" />
|
|
64
|
+
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
|
|
65
|
+
<InputInfo @text={{t "common.upload-new-photo"}} />
|
|
66
|
+
</Attach::Tooltip>
|
|
67
|
+
</div>
|
|
68
|
+
<div>
|
|
69
|
+
<UploadButton
|
|
70
|
+
@name={{t "common.photos"}}
|
|
71
|
+
@accept="image/*"
|
|
72
|
+
@onFileAdded={{perform this.handlePhotoUpload}}
|
|
73
|
+
@icon="upload"
|
|
74
|
+
@size="xs"
|
|
75
|
+
@buttonText={{t "common.upload-image"}}
|
|
76
|
+
@disabled={{cannot-write @resource}}
|
|
77
|
+
/>
|
|
78
|
+
<div class="px-1">
|
|
79
|
+
<span class="text-gray-300 dark:text-gray-600 text-xs">{{t "common.upload-image-supported"}}</span>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
<div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-2 no-input-group-padding text-xs">
|
|
84
|
+
<InputGroup @name={{t "device.fields.device-name"}}>
|
|
85
|
+
<Input
|
|
86
|
+
@value={{@resource.name}}
|
|
87
|
+
@type="text"
|
|
88
|
+
class="w-full form-input"
|
|
89
|
+
placeholder={{t "device.fields.device-name-placeholder"}}
|
|
90
|
+
disabled={{cannot-write @resource}}
|
|
91
|
+
/>
|
|
92
|
+
</InputGroup>
|
|
93
|
+
|
|
94
|
+
<InputGroup @name={{t "device.fields.device-id"}}>
|
|
95
|
+
<Input @value={{@resource.device_id}} @type="text" class="w-full form-input" placeholder={{t "device.fields.device-id-placeholder"}} disabled={{cannot-write @resource}} />
|
|
96
|
+
</InputGroup>
|
|
97
|
+
|
|
98
|
+
<InputGroup @name="Internal ID" @value={{@resource.internal_id}} disabled={{cannot-write @resource}} />
|
|
99
|
+
</div>
|
|
100
|
+
</ContentPanel>
|
|
101
|
+
|
|
102
|
+
<ContentPanel @title="Hardware" @open={{true}} @wrapperClass="bordered-top">
|
|
103
|
+
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3 lg:gap-2 no-input-group-padding text-xs">
|
|
40
104
|
<InputGroup @name={{t "device.fields.device-provider"}}>
|
|
41
105
|
<Input
|
|
42
|
-
@value={{@resource.
|
|
106
|
+
@value={{@resource.provider}}
|
|
43
107
|
@type="text"
|
|
44
108
|
class="w-full form-input"
|
|
45
109
|
placeholder={{t "device.fields.device-provider-placeholder"}}
|
|
@@ -49,7 +113,7 @@
|
|
|
49
113
|
|
|
50
114
|
<InputGroup @name={{t "device.fields.device-model"}}>
|
|
51
115
|
<Input
|
|
52
|
-
@value={{@resource.
|
|
116
|
+
@value={{@resource.model}}
|
|
53
117
|
@type="text"
|
|
54
118
|
class="w-full form-input"
|
|
55
119
|
placeholder={{t "device.fields.device-model-placeholder"}}
|
|
@@ -67,7 +131,7 @@
|
|
|
67
131
|
/>
|
|
68
132
|
</InputGroup>
|
|
69
133
|
|
|
70
|
-
<InputGroup @name={{t "device.fields.serial-number"}}>
|
|
134
|
+
<InputGroup @name={{t "device.fields.serial-number"}} @wrapperClass="lg:col-span-3">
|
|
71
135
|
<Input
|
|
72
136
|
@value={{@resource.serial_number}}
|
|
73
137
|
@type="text"
|
|
@@ -76,10 +140,14 @@
|
|
|
76
140
|
disabled={{cannot-write @resource}}
|
|
77
141
|
/>
|
|
78
142
|
</InputGroup>
|
|
143
|
+
</div>
|
|
144
|
+
</ContentPanel>
|
|
79
145
|
|
|
80
|
-
|
|
146
|
+
<ContentPanel @title="Installation & Maintenance" @open={{true}} @wrapperClass="bordered-top">
|
|
147
|
+
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3 lg:gap-2 no-input-group-padding text-xs">
|
|
148
|
+
<InputGroup @name={{t "device.fields.device-location"}} @wrapperClass="lg:col-span-2">
|
|
81
149
|
<Input
|
|
82
|
-
@value={{@resource.
|
|
150
|
+
@value={{@resource.location}}
|
|
83
151
|
@type="text"
|
|
84
152
|
class="w-full form-input"
|
|
85
153
|
placeholder={{t "device.fields.device-location-placeholder"}}
|
|
@@ -106,50 +174,30 @@
|
|
|
106
174
|
class="w-full form-input"
|
|
107
175
|
/>
|
|
108
176
|
</InputGroup>
|
|
177
|
+
</div>
|
|
178
|
+
</ContentPanel>
|
|
109
179
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@value={{@resource.data_frequency}}
|
|
113
|
-
@type="text"
|
|
114
|
-
class="w-full form-input"
|
|
115
|
-
placeholder={{t "device.fields.data-frequency-placeholder"}}
|
|
116
|
-
disabled={{cannot-write @resource}}
|
|
117
|
-
/>
|
|
118
|
-
</InputGroup>
|
|
119
|
-
|
|
180
|
+
<ContentPanel @title="Warranty & Status" @open={{true}} @wrapperClass="bordered-top">
|
|
181
|
+
<div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-2 no-input-group-padding text-xs">
|
|
120
182
|
<InputGroup @name={{t "device.fields.status"}}>
|
|
121
183
|
<div class="fleetbase-model-select fleetbase-power-select ember-model-select">
|
|
122
184
|
<PowerSelect
|
|
123
|
-
@options={{
|
|
124
|
-
@selected={{@resource.status}}
|
|
125
|
-
@onChange={{
|
|
126
|
-
@placeholder={{t "
|
|
185
|
+
@options={{get-fleet-ops-options "deviceStatuses"}}
|
|
186
|
+
@selected={{find-by "value" @resource.status (get-fleet-ops-options "deviceStatuses")}}
|
|
187
|
+
@onChange={{set-model-attr @resource "status"}}
|
|
188
|
+
@placeholder={{t "common.select-field" field=(t "common.status")}}
|
|
127
189
|
@triggerClass="form-select form-input"
|
|
128
190
|
@disabled={{cannot-write @resource}}
|
|
129
|
-
as |
|
|
191
|
+
as |option|
|
|
130
192
|
>
|
|
131
|
-
|
|
193
|
+
<div class="text-sm">
|
|
194
|
+
<div class="font-semibold normalize-in-trigger">{{option.label}}</div>
|
|
195
|
+
<div class="hide-from-trigger">{{option.description}}</div>
|
|
196
|
+
</div>
|
|
132
197
|
</PowerSelect>
|
|
133
198
|
</div>
|
|
134
199
|
</InputGroup>
|
|
135
200
|
|
|
136
|
-
<InputGroup @name={{t "device.fields.telematic"}}>
|
|
137
|
-
<ModelSelect
|
|
138
|
-
@modelName="telematic"
|
|
139
|
-
@selectedModel={{@resource.telematic}}
|
|
140
|
-
@placeholder={{t "device.fields.telematic-placeholder"}}
|
|
141
|
-
@triggerClass="form-select form-input"
|
|
142
|
-
@infiniteScroll={{false}}
|
|
143
|
-
@renderInPlace={{true}}
|
|
144
|
-
@onChange={{fn (mut @resource.telematic)}}
|
|
145
|
-
@onChangeId={{fn (mut @resource.telematic_uuid)}}
|
|
146
|
-
@disabled={{cannot-write @resource}}
|
|
147
|
-
as |model|
|
|
148
|
-
>
|
|
149
|
-
{{model.name}}
|
|
150
|
-
</ModelSelect>
|
|
151
|
-
</InputGroup>
|
|
152
|
-
|
|
153
201
|
<InputGroup @name={{t "device.fields.warranty"}}>
|
|
154
202
|
<ModelSelect
|
|
155
203
|
@modelName="warranty"
|
|
@@ -168,7 +216,11 @@
|
|
|
168
216
|
{{model.provider}}
|
|
169
217
|
</ModelSelect>
|
|
170
218
|
</InputGroup>
|
|
219
|
+
</div>
|
|
220
|
+
</ContentPanel>
|
|
171
221
|
|
|
222
|
+
<ContentPanel @title="Notes" @open={{true}} @wrapperClass="bordered-top">
|
|
223
|
+
<div class="grid grid-cols-1 gap-2 no-input-group-padding text-xs">
|
|
172
224
|
<InputGroup @name={{t "device.fields.notes"}} @wrapperClass="col-span-2">
|
|
173
225
|
<Textarea
|
|
174
226
|
@value={{@resource.notes}}
|
|
@@ -179,10 +231,6 @@
|
|
|
179
231
|
rows={{4}}
|
|
180
232
|
/>
|
|
181
233
|
</InputGroup>
|
|
182
|
-
|
|
183
|
-
<RegistryYield @registry="fleet-ops:component:device:form:details" as |RegistryComponent|>
|
|
184
|
-
<RegistryComponent @resource={{@resource}} @controller={{@controller}} @permission={{get-write-permission @resource}} />
|
|
185
|
-
</RegistryYield>
|
|
186
234
|
</div>
|
|
187
235
|
</ContentPanel>
|
|
188
236
|
|
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
|
+
import { action } from '@ember/object';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { task } from 'ember-concurrency';
|
|
2
5
|
|
|
3
6
|
export default class DeviceFormComponent extends Component {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
deviceTypeOptions = ['dashcam', 'obd', 'blackbox', 'tablet', 'tracker', 'sensor'];
|
|
7
|
+
@service fetch;
|
|
8
|
+
@service currentUser;
|
|
9
|
+
@service notifications;
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
@action selectTelematic(telematic) {
|
|
12
|
+
this.args.resource.setProperties({
|
|
13
|
+
telematic,
|
|
14
|
+
telematic_uuid: telematic.id,
|
|
15
|
+
provider: telematic.provider,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@task *handlePhotoUpload(file) {
|
|
20
|
+
try {
|
|
21
|
+
yield this.fetch.uploadFile.perform(
|
|
22
|
+
file,
|
|
23
|
+
{
|
|
24
|
+
path: `uploads/${this.currentUser.companyId}/devices/${this.args.resource.id}`,
|
|
25
|
+
subject_uuid: this.args.resource.id,
|
|
26
|
+
subject_type: 'fleet-ops:device',
|
|
27
|
+
type: 'device_photo',
|
|
28
|
+
},
|
|
29
|
+
(uploadedFile) => {
|
|
30
|
+
this.args.resource.setProperties({
|
|
31
|
+
photo_uuid: uploadedFile.id,
|
|
32
|
+
photo_url: uploadedFile.url,
|
|
33
|
+
photo: uploadedFile,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
this.notifications.error('Unable to upload photo: ' + err.message);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
13
41
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<div class="fleetops-device-manager" ...attributes>
|
|
2
|
+
<div class="flex flex-row items-center justify-between mb-4 px-3 pt-2">
|
|
3
|
+
<div></div>
|
|
4
|
+
<div>
|
|
5
|
+
<Button @icon="plus" @text="Attach device" @onClick={{this.addDevice}} @disabled={{not @resource}} />
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
<div>
|
|
9
|
+
{{#each this.devices as |device|}}
|
|
10
|
+
<div class="flex flex-row justify-between px-3 py-4 border-t border-gray-200 dark:border-gray-700">
|
|
11
|
+
<Device::Pill @device={{device}} />
|
|
12
|
+
<div>
|
|
13
|
+
<Button @type="danger" @icon="times" @text="Detach" @size="xs" @onClick={{fn this.removeDevice device}} />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
{{else}}
|
|
17
|
+
<div class="empty-state bg-white dark:bg-gray-800 rounded-lg shadow-sm p-12 text-center">
|
|
18
|
+
<FaIcon @icon="hard-drive" @size="2x" class="text-gray-400 mb-2" />
|
|
19
|
+
<h3 class="text-base font-semibold text-gray-700 dark:text-gray-300">
|
|
20
|
+
No Devices Attached
|
|
21
|
+
</h3>
|
|
22
|
+
<p class="text-sm text-gray-500 dark:text-gray-400">
|
|
23
|
+
Click Attach device above to start receiving telematic data for this
|
|
24
|
+
{{get-model-name @resource}}
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
{{/each}}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|