@fleetbase/fleetops-engine 0.3.2 → 0.3.4
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/visibility-controls.js +1 -0
- package/addon/components/contact-form-panel.hbs +28 -6
- package/addon/components/driver-form-panel.hbs +10 -0
- package/addon/components/driver-form-panel.js +51 -0
- package/addon/components/driver-panel/details.hbs +1 -5
- package/addon/components/driver-panel.hbs +21 -3
- package/addon/components/fleet-form-panel.hbs +60 -6
- package/addon/components/fleet-panel/details.hbs +1 -1
- package/addon/components/fuel-report-form-panel.hbs +84 -8
- package/addon/components/fuel-report-form-panel.js +6 -0
- package/addon/components/fuel-report-panel/details.hbs +4 -0
- package/addon/components/issue-form-panel.hbs +99 -11
- package/addon/components/issue-form-panel.js +5 -13
- package/addon/components/layout/fleet-ops-sidebar.js +10 -1
- package/addon/components/live-map-drawer/driver-listing.hbs +6 -0
- package/addon/components/live-map-drawer/driver-listing.js +240 -0
- package/addon/components/live-map-drawer/place-listing.hbs +6 -0
- package/addon/components/live-map-drawer/place-listing.js +204 -0
- package/addon/components/live-map-drawer/vehicle-listing.hbs +6 -0
- package/addon/components/live-map-drawer/vehicle-listing.js +216 -0
- package/addon/components/live-map-drawer.hbs +17 -0
- package/addon/components/live-map-drawer.js +104 -0
- package/addon/components/live-map.hbs +5 -1
- package/addon/components/live-map.js +107 -15
- package/addon/components/map-container/toolbar.hbs +6 -0
- package/addon/components/modals/driver-assign-vehicle.hbs +2 -11
- package/addon/components/modals/driver-assign-vendor.hbs +1 -9
- package/addon/components/modals/fuel-report-details.hbs +4 -0
- package/addon/components/modals/order-event.hbs +1 -1
- package/addon/components/order/schedule-card.hbs +35 -7
- package/addon/components/order/schedule-card.js +163 -6
- package/addon/components/place-form-panel.hbs +14 -7
- package/addon/components/place-form-panel.js +71 -0
- package/addon/components/place-panel/details.hbs +11 -21
- package/addon/components/vehicle-form-panel.hbs +67 -7
- package/addon/components/vehicle-form-panel.js +37 -0
- package/addon/components/vehicle-panel/details.hbs +9 -5
- package/addon/components/vehicle-panel.hbs +18 -4
- package/addon/components/vendor-form-panel/create-form.hbs +72 -11
- package/addon/components/vendor-form-panel/edit-form.hbs +1 -1
- package/addon/components/vendor-form-panel.hbs +70 -30
- package/addon/components/vendor-form-panel.js +4 -40
- package/addon/components/vendor-panel/details.hbs +2 -2
- package/addon/components/vendor-panel.hbs +16 -2
- package/addon/controllers/management/contacts/index.js +42 -3
- package/addon/controllers/management/fleets/index.js +12 -23
- package/addon/controllers/management/fuel-reports/index/new.js +1 -1
- package/addon/controllers/management/fuel-reports/index.js +73 -20
- package/addon/controllers/management/issues/index/new.js +2 -2
- package/addon/controllers/management/issues/index.js +65 -45
- package/addon/controllers/management/places/index.js +59 -18
- package/addon/controllers/management/vehicles/index.js +67 -8
- package/addon/controllers/management/vendors/index.js +63 -8
- package/addon/controllers/operations/orders/index.js +70 -15
- package/addon/controllers/operations/scheduler/index.js +45 -30
- package/addon/routes/management/contacts/index.js +8 -0
- package/addon/routes/management/fleets/index.js +8 -2
- package/addon/routes/management/fuel-reports/index.js +6 -0
- package/addon/routes/management/issues/index.js +9 -1
- package/addon/routes/management/places/index.js +11 -1
- package/addon/routes/management/vehicles/index.js +3 -3
- package/addon/routes/management/vendors/index.js +8 -0
- package/addon/routes/operations/scheduler/index.js +26 -1
- package/addon/styles/fleetops-engine.css +28 -0
- package/addon/templates/operations/orders/index.hbs +2 -2
- package/addon/templates/operations/scheduler/index.hbs +33 -9
- package/addon/utils/create-full-calendar-event-from-order.js +8 -0
- package/addon/utils/get-issue-categories.js +30 -0
- package/addon/utils/get-issue-types.js +3 -0
- package/addon/utils/get-vendor-status-options.js +3 -0
- package/addon/utils/get-vendor-type-options.js +41 -0
- package/app/components/live-map-drawer/driver-listing.js +1 -0
- package/app/components/live-map-drawer/place-listing.js +1 -0
- package/app/components/live-map-drawer/vehicle-listing.js +1 -0
- package/app/components/live-map-drawer.js +1 -0
- package/app/utils/create-full-calendar-event-from-order.js +1 -0
- package/app/utils/get-issue-categories.js +1 -0
- package/app/utils/get-issue-types.js +1 -0
- package/app/utils/get-vendor-categories.js +1 -0
- package/app/utils/get-vendor-status-options.js +1 -0
- package/app/utils/get-vendor-type-options.js +1 -0
- package/app/utils/get-vendor-types.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/migrations/2023_11_09_041807_add_status_column_to_fuel_reports_table.php +32 -0
- package/server/migrations/2023_11_15_062814_add_comments_column_and_resolved_at_column_to_vehicle_device_events_table.php +33 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -2
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +5 -13
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +1 -3
- package/server/src/Http/Filter/ContactFilter.php +10 -0
- package/server/src/Http/Filter/FleetFilter.php +8 -6
- package/server/src/Http/Filter/FuelReportFilter.php +51 -0
- package/server/src/Http/Filter/IssueFilter.php +61 -5
- package/server/src/Http/Filter/PlaceFilter.php +48 -6
- package/server/src/Http/Filter/VehicleFilter.php +21 -6
- package/server/src/Http/Filter/VendorFilter.php +11 -8
- package/server/src/Http/Middleware/TransformLocationMiddleware.php +1 -1
- package/server/src/Http/Resources/Internal/v1/IntegratedVendorFacilitator.php +17 -18
- package/server/src/Http/Resources/v1/Contact.php +16 -19
- package/server/src/Http/Resources/v1/CurrentJob.php +13 -16
- package/server/src/Http/Resources/v1/Driver.php +59 -57
- package/server/src/Http/Resources/v1/Entity.php +30 -33
- package/server/src/Http/Resources/v1/FuelReport.php +16 -14
- package/server/src/Http/Resources/v1/Order.php +1 -1
- package/server/src/Http/Resources/v1/Payload.php +21 -24
- package/server/src/Http/Resources/v1/Place.php +27 -30
- package/server/src/Http/Resources/v1/Proof.php +13 -16
- package/server/src/Http/Resources/v1/PurchaseRate.php +14 -17
- package/server/src/Http/Resources/v1/ServiceArea.php +13 -16
- package/server/src/Http/Resources/v1/ServiceQuote.php +15 -18
- package/server/src/Http/Resources/v1/ServiceRate.php +33 -36
- package/server/src/Http/Resources/v1/ServiceRateFee.php +14 -17
- package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +9 -12
- package/server/src/Http/Resources/v1/TrackingNumber.php +18 -21
- package/server/src/Http/Resources/v1/TrackingStatus.php +18 -21
- package/server/src/Http/Resources/v1/Vehicle.php +31 -34
- package/server/src/Http/Resources/v1/VehicleDevice.php +23 -25
- package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +38 -32
- package/server/src/Http/Resources/v1/Vendor.php +31 -26
- package/server/src/Http/Resources/v1/Zone.php +14 -17
- package/server/src/Models/Driver.php +7 -1
- package/server/src/Models/FuelReport.php +2 -1
- package/server/src/Models/IntegratedVendor.php +6 -1
- package/server/src/Models/Order.php +24 -2
- package/server/src/Models/Place.php +2 -2
- package/server/src/Models/VehicleDevice.php +1 -1
- package/server/src/Models/VehicleDeviceEvent.php +2 -1
- package/server/src/Models/Vendor.php +1 -1
- package/server/src/Observers/DriverObserver.php +15 -0
- package/server/src/Observers/FleetObserver.php +19 -0
- package/server/src/Providers/FleetOpsServiceProvider.php +1 -0
- package/addon/components/full-calendar/draggable.js +0 -1
- package/addon/components/full-calendar.js +0 -1
- package/app/components/full-calendar/draggable.js +0 -1
- package/app/components/full-calendar.js +0 -1
|
@@ -1,17 +1,174 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
2
3
|
import { action } from '@ember/object';
|
|
4
|
+
import { isBlank } from '@ember/utils';
|
|
5
|
+
import { inject as service } from '@ember/service';
|
|
3
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Component representing the schedule card of an order.
|
|
9
|
+
* @extends Component
|
|
10
|
+
* @memberof OrderScheduleCardComponent
|
|
11
|
+
*/
|
|
4
12
|
export default class OrderScheduleCardComponent extends Component {
|
|
5
|
-
|
|
6
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Service for managing the context panel.
|
|
15
|
+
* @service
|
|
16
|
+
* @memberof OrderScheduleCardComponent
|
|
17
|
+
*/
|
|
18
|
+
@service contextPanel;
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Service for managing modals.
|
|
22
|
+
* @service
|
|
23
|
+
* @memberof OrderScheduleCardComponent
|
|
24
|
+
*/
|
|
25
|
+
@service modalsManager;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Service for managing notifications.
|
|
29
|
+
* @service
|
|
30
|
+
* @memberof OrderScheduleCardComponent
|
|
31
|
+
*/
|
|
32
|
+
@service notifications;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Indicates if a driver is currently being assigned.
|
|
36
|
+
* @tracked
|
|
37
|
+
* @memberof OrderScheduleCardComponent
|
|
38
|
+
*/
|
|
39
|
+
@tracked isAssigningDriver;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Constructor for OrderScheduleCardComponent.
|
|
43
|
+
* @param {Object} owner - The owner of the component.
|
|
44
|
+
* @param {Object} args - Arguments passed to the component, including the order.
|
|
45
|
+
*/
|
|
46
|
+
constructor(owner, { order }) {
|
|
47
|
+
super(...arguments);
|
|
48
|
+
this.loadDriverFromOrder(order);
|
|
49
|
+
this.loadPayloadFromOrder(order);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Action to handle driver click events.
|
|
54
|
+
* @action
|
|
55
|
+
* @param {DriverModel} driver - The clicked driver object.
|
|
56
|
+
* @memberof OrderScheduleCardComponent
|
|
57
|
+
*/
|
|
58
|
+
@action onClickDriver(driver) {
|
|
59
|
+
this.contextPanel.focus(driver);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Action to handle vehicle click events.
|
|
64
|
+
* @action
|
|
65
|
+
* @param {VehicleModel} vehicle - The clicked vehicle object.
|
|
66
|
+
* @memberof OrderScheduleCardComponent
|
|
67
|
+
*/
|
|
68
|
+
@action onClickVehicle(vehicle) {
|
|
69
|
+
this.contextPanel.focus(vehicle);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Action to start the process of assigning a driver.
|
|
74
|
+
* @action
|
|
75
|
+
* @memberof OrderScheduleCardComponent
|
|
76
|
+
*/
|
|
77
|
+
@action startAssignDriver() {
|
|
78
|
+
this.isAssigningDriver = true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Action to assign a driver to an order.
|
|
83
|
+
* @action
|
|
84
|
+
* @param {DriverModel} driver - The driver to be assigned.
|
|
85
|
+
* @memberof OrderScheduleCardComponent
|
|
86
|
+
*/
|
|
87
|
+
@action assignDriver(driver) {
|
|
88
|
+
const order = this.args.order;
|
|
89
|
+
|
|
90
|
+
if (isBlank(driver)) {
|
|
91
|
+
return this.modalsManager.confirm({
|
|
92
|
+
title: 'Unassign Driver?',
|
|
93
|
+
body: `You are about to unassign the driver for Order ${order.public_id}. Click continue to confirm removal of driver.`,
|
|
94
|
+
acceptButtonText: 'Continue and unassign driver',
|
|
95
|
+
confirm: () => {
|
|
96
|
+
order.setProperties({
|
|
97
|
+
driver_assigned: null,
|
|
98
|
+
driver_assigned_uuid: null,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return order
|
|
102
|
+
.save()
|
|
103
|
+
.catch((error) => {
|
|
104
|
+
this.notifications.serverError(error);
|
|
105
|
+
})
|
|
106
|
+
.finally(() => {
|
|
107
|
+
this.isAssigningDriver = false;
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
decline: (modal) => {
|
|
111
|
+
this.isAssigningDriver = false;
|
|
112
|
+
modal.done();
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return this.modalsManager.confirm({
|
|
118
|
+
title: 'Assign New Driver?',
|
|
119
|
+
body: `You are about to assign a new driver (${driver.name}) to Order ${order.public_id}. Click continue to confirm driver.`,
|
|
120
|
+
acceptButtonText: 'Continue and assign driver',
|
|
121
|
+
confirm: () => {
|
|
122
|
+
order.set('driver_assigned_uuid', driver.id);
|
|
123
|
+
return order
|
|
124
|
+
.save()
|
|
125
|
+
.catch((error) => {
|
|
126
|
+
this.notifications.serverError(error);
|
|
127
|
+
})
|
|
128
|
+
.finally(() => {
|
|
129
|
+
this.isAssigningDriver = false;
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
decline: (modal) => {
|
|
133
|
+
this.isAssigningDriver = false;
|
|
134
|
+
modal.done();
|
|
135
|
+
},
|
|
136
|
+
});
|
|
10
137
|
}
|
|
11
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Action triggered when the title of an order is clicked.
|
|
141
|
+
* @action
|
|
142
|
+
* @param {OrderModel} order - The order associated with the clicked title.
|
|
143
|
+
* @memberof OrderScheduleCardComponent
|
|
144
|
+
*/
|
|
12
145
|
@action onTitleClick(order) {
|
|
13
|
-
|
|
14
|
-
|
|
146
|
+
const { onTitleClick } = this.args;
|
|
147
|
+
|
|
148
|
+
if (typeof onTitleClick === 'function') {
|
|
149
|
+
onTitleClick(order);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Loads the driver information from the order.
|
|
155
|
+
* @param {OrderModel} order - The order to load the driver from.
|
|
156
|
+
* @memberof OrderScheduleCardComponent
|
|
157
|
+
*/
|
|
158
|
+
loadDriverFromOrder(order) {
|
|
159
|
+
if (order && typeof order.loadDriver === 'function') {
|
|
160
|
+
order.loadDriver();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Loads the payload information from the order.
|
|
166
|
+
* @param {OrderModel} order - The order to load the payload from.
|
|
167
|
+
* @memberof OrderScheduleCardComponent
|
|
168
|
+
*/
|
|
169
|
+
loadPayloadFromOrder(order) {
|
|
170
|
+
if (order && typeof order.loadPayload === 'function') {
|
|
171
|
+
order.loadPayload();
|
|
15
172
|
}
|
|
16
173
|
}
|
|
17
174
|
}
|
|
@@ -6,7 +6,13 @@
|
|
|
6
6
|
@isResizeble={{or this.isResizable @isResizable}}
|
|
7
7
|
@width={{or this.width @width "600px"}}
|
|
8
8
|
>
|
|
9
|
-
<Overlay::Header
|
|
9
|
+
<Overlay::Header
|
|
10
|
+
@title={{if this.place.public_id this.place.name "New Place"}}
|
|
11
|
+
@status={{this.place.public_id}}
|
|
12
|
+
@hideStatusDot={{true}}
|
|
13
|
+
@createdAt={{this.place.createdAt}}
|
|
14
|
+
@titleWrapperClass="leading-5"
|
|
15
|
+
>
|
|
10
16
|
<div class="flex flex-1 justify-end">
|
|
11
17
|
<Button @icon={{if this.place.id "save" "check"}} @type="primary" @text={{if this.place.id "Save Place" "Create Place"}} @onClick={{this.save}} @wrapperClass="mr-2" />
|
|
12
18
|
<Button @type="default" @icon="times" @helpText={{if this.place.id "Cancel edit place" "Cancel new place"}} @onClick={{this.onPressCancel}} />
|
|
@@ -15,9 +21,11 @@
|
|
|
15
21
|
|
|
16
22
|
<Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
|
|
17
23
|
<div class="grid grid-cols-3 gap-1 text-xs dark:text-gray-100">
|
|
18
|
-
<InputGroup @name="Name" @
|
|
24
|
+
<InputGroup @name="Name" @wrapperClass="col-span-2">
|
|
25
|
+
<Input @value={{this.place.name}} @type="text" class="w-full form-input" placeholder="Name" />
|
|
26
|
+
</InputGroup>
|
|
19
27
|
<InputGroup @name="Street 1" @value={{this.place.street1}} @wrapperClass="col-span-3">
|
|
20
|
-
<AutocompleteInput @value={{this.place.street1}} @fetchUrl="places/lookup" @onSelect={{this.
|
|
28
|
+
<AutocompleteInput @value={{this.place.street1}} @fetchUrl="places/lookup" @onSelect={{this.onAutocomplete}} placeholder="Street 1" class="w-full" as |result|>
|
|
21
29
|
{{result.address}}
|
|
22
30
|
</AutocompleteInput>
|
|
23
31
|
</InputGroup>
|
|
@@ -29,14 +37,14 @@
|
|
|
29
37
|
<InputGroup @name="City" @autocomplete="nope" @value={{this.place.city}} />
|
|
30
38
|
<InputGroup @name="State" @autocomplete="nope" @value={{this.place.province}} />
|
|
31
39
|
<InputGroup @name="Country" @wrapperClass="col-span-2">
|
|
32
|
-
<CountrySelect class="w-full form-input form-select form-datalist" @value={{this.place.country}} @onChange={{this.place.country}} placeholder="Country" />
|
|
40
|
+
<CountrySelect class="w-full form-input form-select form-datalist" @value={{this.place.country}} @onChange={{fn (mut this.place.country)}} placeholder="Country" />
|
|
33
41
|
</InputGroup>
|
|
34
42
|
<InputGroup @name="Coordinates" @wrapperClass="col-span-2">
|
|
35
43
|
<CoordinatesInput
|
|
36
44
|
@value={{this.place.location}}
|
|
37
45
|
@onChange={{this.updatePlaceCoordinates}}
|
|
38
|
-
@onGeocode={{this.
|
|
39
|
-
@onUpdatedFromMap={{this.
|
|
46
|
+
@onGeocode={{this.onAutocomplete}}
|
|
47
|
+
@onUpdatedFromMap={{this.onReverseGeocode}}
|
|
40
48
|
@onInit={{this.setCoordinatesInput}}
|
|
41
49
|
/>
|
|
42
50
|
</InputGroup>
|
|
@@ -44,7 +52,6 @@
|
|
|
44
52
|
<InputGroup @name="Phone">
|
|
45
53
|
<PhoneInput @value={{this.place.phone}} @autocomplete="nope" @onInput={{this.phone}} class="form-input w-full" />
|
|
46
54
|
</InputGroup>
|
|
47
|
-
<InputGroup @name="Email" @autocomplete="nope" @value={{this.place.email}} />
|
|
48
55
|
</div>
|
|
49
56
|
</Overlay::Body>
|
|
50
57
|
</Overlay>
|
|
@@ -2,6 +2,8 @@ import Component from '@glimmer/component';
|
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
3
|
import { inject as service } from '@ember/service';
|
|
4
4
|
import { action } from '@ember/object';
|
|
5
|
+
import { isBlank } from '@ember/utils';
|
|
6
|
+
import Point from '@fleetbase/fleetops-data/utils/geojson/point';
|
|
5
7
|
import contextComponentCallback from '../utils/context-component-callback';
|
|
6
8
|
import applyContextComponentArguments from '../utils/apply-context-component-arguments';
|
|
7
9
|
|
|
@@ -48,6 +50,12 @@ export default class PlaceFormPanelComponent extends Component {
|
|
|
48
50
|
*/
|
|
49
51
|
@tracked isLoading = false;
|
|
50
52
|
|
|
53
|
+
/**
|
|
54
|
+
* The coordinates input component instance.
|
|
55
|
+
* @type {CoordinateInputComponent}
|
|
56
|
+
*/
|
|
57
|
+
@tracked coordinatesInputComponent;
|
|
58
|
+
|
|
51
59
|
/**
|
|
52
60
|
* All possible place types
|
|
53
61
|
*
|
|
@@ -131,4 +139,67 @@ export default class PlaceFormPanelComponent extends Component {
|
|
|
131
139
|
@action onPressCancel() {
|
|
132
140
|
return contextComponentCallback(this, 'onPressCancel', this.place);
|
|
133
141
|
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Handles the selection from an autocomplete. Updates the place properties with the selected data.
|
|
145
|
+
* If a coordinates input component is present, updates its coordinates too.
|
|
146
|
+
*
|
|
147
|
+
* @action
|
|
148
|
+
* @param {Object} selected - The selected item from the autocomplete.
|
|
149
|
+
* @param {Object} selected.location - The location data of the selected item.
|
|
150
|
+
* @memberof PlaceFormPanelComponent
|
|
151
|
+
*/
|
|
152
|
+
@action onAutocomplete(selected) {
|
|
153
|
+
this.place.setProperties({ ...selected });
|
|
154
|
+
|
|
155
|
+
if (this.coordinatesInputComponent) {
|
|
156
|
+
this.coordinatesInputComponent.updateCoordinates(selected.location);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Performs reverse geocoding given latitude and longitude. Updates place properties with the geocoding result.
|
|
162
|
+
*
|
|
163
|
+
* @action
|
|
164
|
+
* @param {Object} coordinates - The latitude and longitude coordinates.
|
|
165
|
+
* @param {number} coordinates.latitude - Latitude value.
|
|
166
|
+
* @param {number} coordinates.longitude - Longitude value.
|
|
167
|
+
* @returns {Promise} A promise that resolves with the reverse geocoding result.
|
|
168
|
+
* @memberof PlaceFormPanelComponent
|
|
169
|
+
*/
|
|
170
|
+
@action onReverseGeocode({ latitude, longitude }) {
|
|
171
|
+
return this.fetch.get('geocoder/reverse', { coordinates: [latitude, longitude].join(','), single: true }).then((result) => {
|
|
172
|
+
if (isBlank(result)) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this.place.setProperties({ ...result });
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Sets the coordinates input component.
|
|
182
|
+
*
|
|
183
|
+
* @action
|
|
184
|
+
* @param {Object} coordinatesInputComponent - The coordinates input component to be set.
|
|
185
|
+
* @memberof PlaceFormPanelComponent
|
|
186
|
+
*/
|
|
187
|
+
@action setCoordinatesInput(coordinatesInputComponent) {
|
|
188
|
+
this.coordinatesInputComponent = coordinatesInputComponent;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Updates the place coordinates with the given latitude and longitude.
|
|
193
|
+
*
|
|
194
|
+
* @action
|
|
195
|
+
* @param {Object} coordinates - The latitude and longitude coordinates.
|
|
196
|
+
* @param {number} coordinates.latitude - Latitude value.
|
|
197
|
+
* @param {number} coordinates.longitude - Longitude value.
|
|
198
|
+
* @memberof PlaceFormPanelComponent
|
|
199
|
+
*/
|
|
200
|
+
@action updatePlaceCoordinates({ latitude, longitude }) {
|
|
201
|
+
const location = new Point(longitude, latitude);
|
|
202
|
+
|
|
203
|
+
this.place.setProperties({ location });
|
|
204
|
+
}
|
|
134
205
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
<div class="p-4 space-y-4">
|
|
2
|
-
<ContentPanel @title="Map" @open={{
|
|
3
|
-
<LeafletMap class="w-full h-48 rounded-b-md shadow-md" @lat={{@place.latitude}} @lng={{@place.longitude}} @zoom={{17}} as |layers|>
|
|
2
|
+
<ContentPanel @title="Map" @open={{false}}>
|
|
3
|
+
<LeafletMap class="w-full h-48 rounded-b-md shadow-md" @lat={{@place.latitude}} @lng={{@place.longitude}} @zoom={{17}} @zoomControl={{false}} as |layers|>
|
|
4
4
|
<layers.tile @url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png" />
|
|
5
|
-
<layers.marker
|
|
5
|
+
<layers.marker
|
|
6
|
+
@id={{@place.id}}
|
|
7
|
+
@icon={{icon iconUrl="/engines-dist/images/building-marker.png" iconSize=(array 16 16)}}
|
|
8
|
+
@location={{point-to-coordinates @place.location}}
|
|
9
|
+
@riseOnHover={{true}}
|
|
10
|
+
@title={{@place.address}}
|
|
11
|
+
@alt={{@place.address}}
|
|
12
|
+
as |marker|
|
|
13
|
+
>
|
|
6
14
|
<marker.popup>
|
|
7
15
|
<div>{{@place.address}}</div>
|
|
8
16
|
<div>{{format-point @place.location}}</div>
|
|
@@ -60,24 +68,6 @@
|
|
|
60
68
|
<div class="field-value">{{n-a @place.phone}}</div>
|
|
61
69
|
</div>
|
|
62
70
|
|
|
63
|
-
<div class="field-info-container">
|
|
64
|
-
<div class="field-name">Email</div>
|
|
65
|
-
<div class="field-value">{{n-a @place.email}}</div>
|
|
66
|
-
</div>
|
|
67
|
-
|
|
68
|
-
<div class="field-info-container">
|
|
69
|
-
<div class="field-name">Vendor</div>
|
|
70
|
-
<div class="field-value">
|
|
71
|
-
{{#if @place.vendor_uuid}}
|
|
72
|
-
<a href="javascript:;" {{on "click" @place.viewVendor}}>
|
|
73
|
-
{{@place.vendor_name}}
|
|
74
|
-
</a>
|
|
75
|
-
{{else}}
|
|
76
|
-
{{@place.vendor_name}}
|
|
77
|
-
{{/if}}
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
71
|
<div class="field-info-container col-span-3">
|
|
82
72
|
<div class="field-name">
|
|
83
73
|
Coordinates
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
<Overlay
|
|
1
|
+
<Overlay
|
|
2
|
+
@onLoad={{this.setOverlayContext}}
|
|
3
|
+
@position="right"
|
|
4
|
+
@noBackdrop={{true}}
|
|
5
|
+
@fullHeight={{true}}
|
|
6
|
+
@isResizeble={{or this.isResizable @isResizable}}
|
|
7
|
+
@width={{or this.width @width "600px"}}
|
|
8
|
+
>
|
|
2
9
|
<Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]">
|
|
3
10
|
<div class="flex flex-row items-center justify-between w-full mb-4">
|
|
4
11
|
<div class="flex flex-1 space-x-2">
|
|
@@ -8,9 +15,21 @@
|
|
|
8
15
|
</div>
|
|
9
16
|
<div class="flex flex-1 justify-end">
|
|
10
17
|
<div class="mr-2">
|
|
11
|
-
<Button
|
|
18
|
+
<Button
|
|
19
|
+
@icon={{if this.vehicle.id "save" "check"}}
|
|
20
|
+
@type="primary"
|
|
21
|
+
@text={{if this.vehicle.id "Save Vehicle" "Create Vehicle"}}
|
|
22
|
+
@onClick={{this.save}}
|
|
23
|
+
@isLoading={{this.isLoading}}
|
|
24
|
+
/>
|
|
12
25
|
</div>
|
|
13
|
-
<Button
|
|
26
|
+
<Button
|
|
27
|
+
@type="default"
|
|
28
|
+
@icon="times"
|
|
29
|
+
@helpText={{if this.vehicle.id "Cancel edit vehicle" "Cancel new vehicle"}}
|
|
30
|
+
@onClick={{this.onPressCancel}}
|
|
31
|
+
@disabled={{this.isLoading}}
|
|
32
|
+
/>
|
|
14
33
|
</div>
|
|
15
34
|
</div>
|
|
16
35
|
<div class="flex flex-row justify-between w-full">
|
|
@@ -23,7 +42,15 @@
|
|
|
23
42
|
<InputInfo @text="Upload new photo" />
|
|
24
43
|
</Attach::Tooltip>
|
|
25
44
|
<div class="upload-avatar-button-wrapper rounded-lg">
|
|
26
|
-
<UploadButton
|
|
45
|
+
<UploadButton
|
|
46
|
+
@name="photos"
|
|
47
|
+
@accept="image/*"
|
|
48
|
+
@onFileAdded={{this.onUploadNewPhoto}}
|
|
49
|
+
@icon="upload"
|
|
50
|
+
@hideButtonText={{true}}
|
|
51
|
+
@labelClass="upload-avatar-label-overlay"
|
|
52
|
+
class="w-12 btn-reset"
|
|
53
|
+
/>
|
|
27
54
|
</div>
|
|
28
55
|
</div>
|
|
29
56
|
</div>
|
|
@@ -88,18 +115,43 @@
|
|
|
88
115
|
</InputGroup>
|
|
89
116
|
|
|
90
117
|
<InputGroup @name="Driver Assigned">
|
|
91
|
-
<ModelSelect
|
|
118
|
+
<ModelSelect
|
|
119
|
+
@modelName="driver"
|
|
120
|
+
@selectedModel={{this.vehicle.driver}}
|
|
121
|
+
@placeholder="Select Driver"
|
|
122
|
+
@triggerClass="form-select form-input"
|
|
123
|
+
@infiniteScroll={{false}}
|
|
124
|
+
@renderInPlace={{true}}
|
|
125
|
+
@onChange={{fn (mut this.vehicle.driver)}}
|
|
126
|
+
as |model|
|
|
127
|
+
>
|
|
92
128
|
{{model.name}}
|
|
93
129
|
</ModelSelect>
|
|
94
130
|
</InputGroup>
|
|
95
131
|
|
|
96
132
|
<InputGroup @name="Status">
|
|
97
133
|
<div class="fleetbase-model-select fleetbase-power-select ember-model-select">
|
|
98
|
-
<PowerSelect
|
|
134
|
+
<PowerSelect
|
|
135
|
+
@options={{this.vehicleStatusOptions}}
|
|
136
|
+
@selected={{this.vehicle.status}}
|
|
137
|
+
@onChange={{fn (mut this.vehicle.status)}}
|
|
138
|
+
@placeholder="Select vehicle status"
|
|
139
|
+
@triggerClass="form-select form-input"
|
|
140
|
+
as |status|
|
|
141
|
+
>
|
|
99
142
|
{{smart-humanize status}}
|
|
100
143
|
</PowerSelect>
|
|
101
144
|
</div>
|
|
102
145
|
</InputGroup>
|
|
146
|
+
<InputGroup @name="Coordinates" @wrapperClass="col-span-2">
|
|
147
|
+
<CoordinatesInput
|
|
148
|
+
@value={{this.vehicle.location}}
|
|
149
|
+
@onChange={{this.onCoordinatesChanged}}
|
|
150
|
+
@onGeocode={{this.onAutocomplete}}
|
|
151
|
+
@onUpdatedFromMap={{this.onCoordinatesChanged}}
|
|
152
|
+
@onInit={{this.setCoordinatesInput}}
|
|
153
|
+
/>
|
|
154
|
+
</InputGroup>
|
|
103
155
|
</div>
|
|
104
156
|
</ContentPanel>
|
|
105
157
|
|
|
@@ -107,7 +159,15 @@
|
|
|
107
159
|
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:gap-2">
|
|
108
160
|
<div class="input-group mb-2">
|
|
109
161
|
<InputLabel @labelText="Select map avatar" @helpText="Select an avatar to be used for rendering on maps when using geolocation tracking features." />
|
|
110
|
-
<FetchSelect
|
|
162
|
+
<FetchSelect
|
|
163
|
+
@wrapperClass="w-60"
|
|
164
|
+
@placeholder="Select avatar"
|
|
165
|
+
@endpoint="vehicles/avatars"
|
|
166
|
+
@selected={{this.vehicle.avatar_url}}
|
|
167
|
+
@optionValue="value"
|
|
168
|
+
@onChange={{fn (mut this.vehicle.avatar_url)}}
|
|
169
|
+
as |option|
|
|
170
|
+
>
|
|
111
171
|
{{titleize (humanize option.key)}}
|
|
112
172
|
</FetchSelect>
|
|
113
173
|
</div>
|
|
@@ -4,6 +4,7 @@ import { inject as service } from '@ember/service';
|
|
|
4
4
|
import { action } from '@ember/object';
|
|
5
5
|
import contextComponentCallback from '../utils/context-component-callback';
|
|
6
6
|
import applyContextComponentArguments from '../utils/apply-context-component-arguments';
|
|
7
|
+
import Point from '@fleetbase/fleetops-data/utils/geojson/point';
|
|
7
8
|
|
|
8
9
|
export default class VehicleFormPanelComponent extends Component {
|
|
9
10
|
/**
|
|
@@ -160,4 +161,40 @@ export default class VehicleFormPanelComponent extends Component {
|
|
|
160
161
|
@action onPressCancel() {
|
|
161
162
|
return contextComponentCallback(this, 'onPressCancel', this.vehicle);
|
|
162
163
|
}
|
|
164
|
+
|
|
165
|
+
@action onAutocomplete({ location }) {
|
|
166
|
+
if (location) {
|
|
167
|
+
this.vehicle.setProperties({ location });
|
|
168
|
+
|
|
169
|
+
if (this.coordinatesInputComponent) {
|
|
170
|
+
this.coordinatesInputComponent.updateCoordinates(location);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Sets the coordinates input component.
|
|
177
|
+
*
|
|
178
|
+
* @action
|
|
179
|
+
* @param {Object} coordinatesInputComponent - The coordinates input component to be set.
|
|
180
|
+
* @memberof PlaceFormPanelComponent
|
|
181
|
+
*/
|
|
182
|
+
@action setCoordinatesInput(coordinatesInputComponent) {
|
|
183
|
+
this.coordinatesInputComponent = coordinatesInputComponent;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Updates the Vehicle coordinates with the given latitude and longitude.
|
|
188
|
+
*
|
|
189
|
+
* @action
|
|
190
|
+
* @param {Object} coordinates - The latitude and longitude coordinates.
|
|
191
|
+
* @param {number} coordinates.latitude - Latitude value.
|
|
192
|
+
* @param {number} coordinates.longitude - Longitude value.
|
|
193
|
+
* @memberof PlaceFormPanelComponent
|
|
194
|
+
*/
|
|
195
|
+
@action onCoordinatesChanged({ latitude, longitude }) {
|
|
196
|
+
const location = new Point(longitude, latitude);
|
|
197
|
+
|
|
198
|
+
this.vehicle.setProperties({ location });
|
|
199
|
+
}
|
|
163
200
|
}
|
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
<div class="field-name">Name</div>
|
|
6
6
|
<div class="field-value">{{n-a @vehicle.display_name}}</div>
|
|
7
7
|
</div>
|
|
8
|
-
<div class="field-info-container">
|
|
9
|
-
<div class="field-name">Internal ID</div>
|
|
10
|
-
<div class="field-value">{{n-a @vehicle.internal_id}}</div>
|
|
11
|
-
</div>
|
|
12
8
|
<div class="field-info-container">
|
|
13
9
|
<div class="field-name">Plate Number</div>
|
|
14
10
|
<div class="field-value">{{n-a @vehicle.plate_number}}</div>
|
|
@@ -19,7 +15,7 @@
|
|
|
19
15
|
</div>
|
|
20
16
|
<div class="field-info-container">
|
|
21
17
|
<div class="field-name">Make</div>
|
|
22
|
-
<div class="field-value">{{n-a @vehicle.
|
|
18
|
+
<div class="field-value">{{n-a @vehicle.make}}</div>
|
|
23
19
|
</div>
|
|
24
20
|
<div class="field-info-container">
|
|
25
21
|
<div class="field-name">Model</div>
|
|
@@ -29,6 +25,14 @@
|
|
|
29
25
|
<div class="field-name">Year</div>
|
|
30
26
|
<div class="field-value">{{n-a @vehicle.year}}</div>
|
|
31
27
|
</div>
|
|
28
|
+
<div class="field-info-container col-span-3">
|
|
29
|
+
<div class="field-name">
|
|
30
|
+
Coordinates
|
|
31
|
+
</div>
|
|
32
|
+
<div class="field-value">
|
|
33
|
+
{{point-coordinates @vehicle.location}}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
32
36
|
</div>
|
|
33
37
|
</ContentPanel>
|
|
34
38
|
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
<Overlay
|
|
1
|
+
<Overlay
|
|
2
|
+
@onLoad={{this.setOverlayContext}}
|
|
3
|
+
@position="right"
|
|
4
|
+
@noBackdrop={{true}}
|
|
5
|
+
@fullHeight={{true}}
|
|
6
|
+
@isResizable={{or this.isResizable @isResizable}}
|
|
7
|
+
@width={{or this.width @width "600px"}}
|
|
8
|
+
>
|
|
2
9
|
<Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]">
|
|
3
10
|
<div class="flex flex-row items-center justify-between w-full mb-4">
|
|
4
11
|
<div class="flex flex-1 space-x-2">
|
|
@@ -13,7 +20,14 @@
|
|
|
13
20
|
<div class="flex flex-row">
|
|
14
21
|
<div class="w-14">
|
|
15
22
|
<div class="w-12 h-12 flex items-center justify-start rounded-lg">
|
|
16
|
-
<Image
|
|
23
|
+
<Image
|
|
24
|
+
src={{this.vehicle.photo_url}}
|
|
25
|
+
@fallbackSrc={{config "defaultValues.vehicleImage"}}
|
|
26
|
+
alt={{this.vehicle.name}}
|
|
27
|
+
height="48"
|
|
28
|
+
width="48"
|
|
29
|
+
class="h-12 w-12 rounded-lg shadow-sm"
|
|
30
|
+
/>
|
|
17
31
|
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
|
|
18
32
|
<InputInfo @text={{this.vehicle.displayName}} />
|
|
19
33
|
</Attach::Tooltip>
|
|
@@ -29,7 +43,7 @@
|
|
|
29
43
|
{{else}}
|
|
30
44
|
<div class="flex flex-row items-center">
|
|
31
45
|
<span class="text-sm dark:text-gray-500 text-gray-700 mr-3">No driver assigned</span>
|
|
32
|
-
{{
|
|
46
|
+
{{! <Button @icon="user-plus" @size="xs" @helpText="Assign a driver to vehicle" /> }}
|
|
33
47
|
</div>
|
|
34
48
|
{{/if}}
|
|
35
49
|
</div>
|
|
@@ -46,7 +60,7 @@
|
|
|
46
60
|
<div class="ui-tabs mt-4">
|
|
47
61
|
<nav>
|
|
48
62
|
{{#each this.tabs as |tab|}}
|
|
49
|
-
<a href="javascript:;" class="ui-tab {{if (eq this.tab.slug tab.slug) 'active'
|
|
63
|
+
<a href="javascript:;" class="ui-tab {{if (eq this.tab.slug tab.slug) 'active'}}" {{on "click" (fn this.onTabChanged tab.slug)}}>
|
|
50
64
|
<FaIcon @icon={{tab.icon}} class="mr-1" />
|
|
51
65
|
<span>{{tab.title}}</span>
|
|
52
66
|
</a>
|