@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
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
import { isNone } from '@ember/utils';
|
|
6
|
+
|
|
7
|
+
export default class TableCellDropdownActionItemComponent extends Component {
|
|
8
|
+
@service abilities;
|
|
9
|
+
@tracked permissionRequired;
|
|
10
|
+
@tracked doesntHavePermissions = false;
|
|
11
|
+
@tracked disabled = false;
|
|
12
|
+
@tracked visible = true;
|
|
13
|
+
|
|
14
|
+
constructor(owner, { columnAction = {}, row = {}, disabled = false, permission = null }) {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this.permissionRequired = columnAction.permission ?? permission;
|
|
17
|
+
this.disabled = this.disabledCheck(columnAction, this.permissionRequired, disabled);
|
|
18
|
+
this.visible = (columnAction.visible ?? true) && this.visibilityCheck(columnAction, row);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@action onClick(columnAction, row, dd) {
|
|
22
|
+
if (this.disabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeof dd?.actions?.close === 'function') {
|
|
27
|
+
dd.actions.close();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (typeof columnAction?.fn === 'function') {
|
|
31
|
+
columnAction.fn(row);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
disabledCheck(columnAction, permission, defaultValue = false) {
|
|
36
|
+
let disabled = columnAction.disabled ?? defaultValue;
|
|
37
|
+
if (!disabled) {
|
|
38
|
+
disabled = permission && this.abilities.cannot(permission);
|
|
39
|
+
this.doesntHavePermissions = disabled;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return disabled;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
visibilityCheck(columnAction, context) {
|
|
46
|
+
const isVisible = columnAction.isVisible;
|
|
47
|
+
|
|
48
|
+
if (isNone(context) || !isVisible) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (typeof isVisible === 'boolean') {
|
|
53
|
+
return isVisible;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (typeof isVisible === 'function') {
|
|
57
|
+
return isVisible(context);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<div class="cell-dropdown-button overflow-visible {{@column.wrapperClass}}" {{did-insert this.setupComponent}} ...attributes>
|
|
2
|
+
<DropdownButton
|
|
3
|
+
@icon={{@column.ddButtonIcon}}
|
|
4
|
+
@iconPrefix={{@column.ddButtonIconPrefix}}
|
|
5
|
+
@text={{this.buttonText}}
|
|
6
|
+
@size="xs"
|
|
7
|
+
@horizontalPosition="left"
|
|
8
|
+
@calculatePosition={{this.calculatePosition}}
|
|
9
|
+
@renderInPlace={{true}}
|
|
10
|
+
@onOpen={{this.onOpen}}
|
|
11
|
+
@onClose={{this.onClose}}
|
|
12
|
+
as |dd|
|
|
13
|
+
>
|
|
14
|
+
<div class="next-dd-menu next-dd-menu-table-dd mt-0i {{@column.ddMenuWrapperClass}}" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
|
|
15
|
+
{{#if @column.ddMenuLabel}}
|
|
16
|
+
<div class="next-dd-menu-label-container px-1">
|
|
17
|
+
<div class="next-dd-menu-label {{@column.ddMenuLabelClass}}">
|
|
18
|
+
{{@column.ddMenuLabel}}
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="next-dd-menu-seperator"></div>
|
|
22
|
+
{{/if}}
|
|
23
|
+
{{#each @column.actions as |columnAction|}}
|
|
24
|
+
<Table::Cell::Dropdown::ActionItem @columnAction={{columnAction}} @row={{@row}} @column={{@column}} @dd={{dd}} />
|
|
25
|
+
{{/each}}
|
|
26
|
+
</div>
|
|
27
|
+
</DropdownButton>
|
|
28
|
+
</div>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action, computed } from '@ember/object';
|
|
4
|
+
|
|
5
|
+
export default class TableCellDropdownComponent extends Component {
|
|
6
|
+
@tracked tableCellNode;
|
|
7
|
+
defaultButtonText = 'Actions';
|
|
8
|
+
|
|
9
|
+
@computed('args.column.ddButtonText', 'defaultButtonText') get buttonText() {
|
|
10
|
+
const { ddButtonText } = this.args.column;
|
|
11
|
+
|
|
12
|
+
if (ddButtonText === undefined) {
|
|
13
|
+
return this.defaultButtonText;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (ddButtonText === false) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return ddButtonText;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@action setupComponent(dropdownWrapperNode) {
|
|
24
|
+
const tableCellNode = this.getOwnerTableCell(dropdownWrapperNode);
|
|
25
|
+
|
|
26
|
+
if (tableCellNode) {
|
|
27
|
+
tableCellNode.style.overflow = 'visible';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.tableCellNode = tableCellNode;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@action onOpen() {
|
|
34
|
+
if (!this.tableCellNode) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const currentZIndex = Number.parseInt(this.tableCellNode.style.zIndex, 10) || 0;
|
|
39
|
+
this.tableCellNode.style.zIndex = currentZIndex + 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@action onClose() {
|
|
43
|
+
if (!this.tableCellNode) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const currentZIndex = Number.parseInt(this.tableCellNode.style.zIndex, 10) || 1;
|
|
48
|
+
this.tableCellNode.style.zIndex = currentZIndex - 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@action getOwnerTableCell(dropdownWrapperNode) {
|
|
52
|
+
while (dropdownWrapperNode) {
|
|
53
|
+
dropdownWrapperNode = dropdownWrapperNode.parentNode;
|
|
54
|
+
|
|
55
|
+
if (dropdownWrapperNode?.tagName?.toLowerCase() === 'td') {
|
|
56
|
+
return dropdownWrapperNode;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@action onDropdownItemClick(columnAction, row, dd) {
|
|
64
|
+
if (typeof dd?.actions?.close === 'function') {
|
|
65
|
+
dd.actions.close();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (typeof columnAction?.fn === 'function') {
|
|
69
|
+
columnAction.fn(row);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@action calculatePosition(trigger, content) {
|
|
74
|
+
if (typeof this.args.column?.calculatePosition === 'function') {
|
|
75
|
+
return this.args.column.calculatePosition(trigger, content);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
79
|
+
const contentRect = content?.getBoundingClientRect?.();
|
|
80
|
+
const contentWidth = contentRect?.width || 224;
|
|
81
|
+
|
|
82
|
+
const style = {
|
|
83
|
+
position: 'fixed',
|
|
84
|
+
marginTop: '0px',
|
|
85
|
+
left: `${triggerRect.left - contentWidth - 3}px`,
|
|
86
|
+
top: `${triggerRect.top}px`,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return { style };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<div class="px-4 py-3" ...attributes>
|
|
2
|
+
<div class="flex flex-1 flex-row items-start justify-between gap-4">
|
|
3
|
+
<div class="flex min-w-0 flex-row items-start gap-3">
|
|
4
|
+
<div class="relative flex flex-shrink-0 items-start justify-start">
|
|
5
|
+
<Image
|
|
6
|
+
src={{this.imageUrl}}
|
|
7
|
+
@fallbackSrc={{config "defaultValues.vendorImage"}}
|
|
8
|
+
alt={{this.name}}
|
|
9
|
+
height="48"
|
|
10
|
+
width="48"
|
|
11
|
+
class="h-14 w-14 rounded-md border border-gray-200 object-cover shadow-sm dark:border-gray-700"
|
|
12
|
+
/>
|
|
13
|
+
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
|
|
14
|
+
<InputInfo @text={{this.name}} />
|
|
15
|
+
</Attach::Tooltip>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="flex min-w-0 flex-col">
|
|
18
|
+
<div class="flex min-w-0 flex-wrap items-center gap-2">
|
|
19
|
+
<h1 class="truncate text-base font-semibold leading-5 text-gray-900 dark:text-gray-100">{{this.name}}</h1>
|
|
20
|
+
<Badge @status={{this.status}} @size="xs">{{smart-humanize this.status}}</Badge>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="mt-1 flex max-w-2xl flex-wrap items-center gap-1.5">
|
|
24
|
+
{{#if this.businessId}}
|
|
25
|
+
<span class="inline-flex max-w-[12rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
26
|
+
<FaIcon @icon="id-card" class="text-gray-400 dark:text-gray-300" />
|
|
27
|
+
<span class="truncate">{{this.businessId}}</span>
|
|
28
|
+
</span>
|
|
29
|
+
{{/if}}
|
|
30
|
+
{{#if this.type}}
|
|
31
|
+
<span class="inline-flex max-w-[10rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
32
|
+
<FaIcon @icon="building" class="text-gray-400 dark:text-gray-300" />
|
|
33
|
+
<span class="truncate">{{smart-humanize this.type}}</span>
|
|
34
|
+
</span>
|
|
35
|
+
{{/if}}
|
|
36
|
+
{{#if this.email}}
|
|
37
|
+
<span class="inline-flex max-w-[14rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
38
|
+
<FaIcon @icon="envelope" class="text-gray-400 dark:text-gray-300" />
|
|
39
|
+
<span class="truncate">{{this.email}}</span>
|
|
40
|
+
</span>
|
|
41
|
+
{{/if}}
|
|
42
|
+
{{#if this.phone}}
|
|
43
|
+
<span class="inline-flex max-w-[10rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
44
|
+
<FaIcon @icon="phone" class="text-gray-400 dark:text-gray-300" />
|
|
45
|
+
<span class="truncate">{{this.phone}}</span>
|
|
46
|
+
</span>
|
|
47
|
+
{{/if}}
|
|
48
|
+
{{#if this.country}}
|
|
49
|
+
<span class="inline-flex max-w-[10rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
50
|
+
<FaIcon @icon="globe" class="text-gray-400 dark:text-gray-300" />
|
|
51
|
+
<span class="truncate"><CountryName @country={{this.country}} @showFlag={{true}} /></span>
|
|
52
|
+
</span>
|
|
53
|
+
{{/if}}
|
|
54
|
+
{{#if this.address}}
|
|
55
|
+
<span class="inline-flex max-w-[16rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
56
|
+
<FaIcon @icon="location-dot" class="text-gray-400 dark:text-gray-300" />
|
|
57
|
+
<span class="truncate">{{this.address}}</span>
|
|
58
|
+
</span>
|
|
59
|
+
{{/if}}
|
|
60
|
+
{{#if this.website}}
|
|
61
|
+
<span class="inline-flex max-w-[14rem] items-center gap-1 truncate rounded-md bg-gray-100 px-1.5 py-0.5 text-[11px] font-medium leading-4 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
|
62
|
+
<FaIcon @icon="link" class="text-gray-400 dark:text-gray-300" />
|
|
63
|
+
<span class="truncate">{{this.website}}</span>
|
|
64
|
+
</span>
|
|
65
|
+
{{/if}}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="next-view-header-right flex-shrink-0">
|
|
70
|
+
<Layout::Resource::Panel::HeaderActions
|
|
71
|
+
@resource={{@resource}}
|
|
72
|
+
@saveTask={{@saveTask}}
|
|
73
|
+
@saveOptions={{@saveOptions}}
|
|
74
|
+
@saveDisabled={{@saveDisabled}}
|
|
75
|
+
@pojoResource={{@pojoResource}}
|
|
76
|
+
@authSchema={{@authSchema}}
|
|
77
|
+
@actionButtons={{@actionButtons}}
|
|
78
|
+
@onPressCancel={{@onPressCancel}}
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { get } from '@ember/object';
|
|
3
|
+
|
|
4
|
+
export default class VendorPanelHeaderComponent extends Component {
|
|
5
|
+
get resource() {
|
|
6
|
+
return this.args.resource;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
get imageUrl() {
|
|
10
|
+
return get(this.resource, 'photo_url') ?? get(this.resource, 'logo_url');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get name() {
|
|
14
|
+
return get(this.resource, 'name') ?? get(this.resource, 'displayName') ?? get(this.resource, 'business_id') ?? get(this.resource, 'public_id') ?? '-';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get status() {
|
|
18
|
+
return get(this.resource, 'status') ?? 'active';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get businessId() {
|
|
22
|
+
return get(this.resource, 'business_id') ?? get(this.resource, 'internal_id') ?? get(this.resource, 'public_id');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get type() {
|
|
26
|
+
return get(this.resource, 'type');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get email() {
|
|
30
|
+
return get(this.resource, 'email');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get phone() {
|
|
34
|
+
return get(this.resource, 'phone');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get country() {
|
|
38
|
+
return get(this.resource, 'country');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get address() {
|
|
42
|
+
return get(this.resource, 'address_street') ?? get(this.resource, 'address');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get website() {
|
|
46
|
+
return get(this.resource, 'website_url');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -7,17 +7,27 @@ export default class ConnectivityDevicesIndexDetailsVehicleController extends Co
|
|
|
7
7
|
@service deviceActions;
|
|
8
8
|
@service hostRouter;
|
|
9
9
|
@service intl;
|
|
10
|
+
@service mapManager;
|
|
11
|
+
@service vehicleActions;
|
|
10
12
|
|
|
11
13
|
@tracked queryParams = [];
|
|
12
14
|
|
|
13
15
|
get device() {
|
|
14
|
-
return this.model;
|
|
16
|
+
return this.model?.device ?? this.model;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
get vehicle() {
|
|
18
20
|
return this.device?.attachable;
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
get positions() {
|
|
24
|
+
return Array.from(this.model?.positions ?? []);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get hasPositions() {
|
|
28
|
+
return this.positions.length > 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
get vehicleName() {
|
|
22
32
|
return this.device?.attached_to_name ?? this.vehicle?.displayName ?? this.vehicle?.display_name ?? this.vehicle?.name;
|
|
23
33
|
}
|
|
@@ -58,6 +68,14 @@ export default class ConnectivityDevicesIndexDetailsVehicleController extends Co
|
|
|
58
68
|
return Boolean(this.vehicleName || this.device?.attachable_uuid);
|
|
59
69
|
}
|
|
60
70
|
|
|
71
|
+
get canOpenVehicle() {
|
|
72
|
+
return Boolean(this.vehicle?.id);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get canLocateVehicle() {
|
|
76
|
+
return Boolean(this.vehicle?.id && (this.vehicle?.location || this.vehicle?.last_position || this.hasPositions));
|
|
77
|
+
}
|
|
78
|
+
|
|
61
79
|
@action attachToVehicle() {
|
|
62
80
|
return this.deviceActions.attachToVehicle(this.device, { callback: () => this.hostRouter.refresh() });
|
|
63
81
|
}
|
|
@@ -71,4 +89,34 @@ export default class ConnectivityDevicesIndexDetailsVehicleController extends Co
|
|
|
71
89
|
return this.hostRouter.transitionTo('console.fleet-ops.management.vehicles.index.details', this.vehicle);
|
|
72
90
|
}
|
|
73
91
|
}
|
|
92
|
+
|
|
93
|
+
@action openVehiclePositions() {
|
|
94
|
+
if (this.vehicle?.id) {
|
|
95
|
+
return this.hostRouter.transitionTo('console.fleet-ops.management.vehicles.index.details.positions', this.vehicle);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@action async locateVehicle() {
|
|
100
|
+
if (!this.vehicle?.id) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await this.transitionToLiveMap();
|
|
105
|
+
await this.mapManager.waitForMap({ timeoutMs: 8000 });
|
|
106
|
+
|
|
107
|
+
this.mapManager.focusResource(this.vehicle, 16, {
|
|
108
|
+
paddingBottomRight: [300, 200],
|
|
109
|
+
moveend: () => {
|
|
110
|
+
this.vehicleActions.panel?.view?.(this.vehicle, { closeOnTransition: true });
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async transitionToLiveMap() {
|
|
116
|
+
try {
|
|
117
|
+
await this.hostRouter.transitionTo('console.fleet-ops.operations.orders.index', { queryParams: { layout: 'map' } });
|
|
118
|
+
} catch (_) {
|
|
119
|
+
// Keep locate actions usable even if the current transition is already in-flight.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
74
122
|
}
|