@fleetbase/fleetops-engine 0.4.12 → 0.4.14
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/avatar-management.hbs +78 -0
- package/addon/components/admin/avatar-management.js +191 -0
- package/addon/components/avatar-picker.hbs +15 -0
- package/addon/components/avatar-picker.js +57 -0
- package/addon/components/driver-form-panel.hbs +12 -13
- package/addon/components/driver-panel/details.hbs +7 -7
- package/addon/components/edit-order-route-panel.hbs +9 -69
- package/addon/components/edit-order-route-panel.js +78 -27
- package/addon/components/fleet-listing-panel.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar/driver-listing.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.hbs +2 -1
- package/addon/components/live-map.js +0 -1
- package/addon/components/order/schedule-card.hbs +29 -17
- package/addon/components/order/schedule-card.js +1 -1
- package/addon/components/place-form-panel.hbs +35 -51
- package/addon/components/place-panel/details.hbs +10 -14
- package/addon/components/place-panel.hbs +2 -12
- package/addon/components/vehicle-form-panel.hbs +11 -80
- package/addon/components/vehicle-form-panel.js +33 -0
- package/addon/controllers/management/places/index.js +29 -21
- package/addon/controllers/operations/orders/index/view.js +10 -10
- package/addon/controllers/operations/scheduler/index.js +7 -4
- package/addon/engine.js +7 -1
- package/addon/styles/fleetops-engine.css +94 -0
- package/addon/templates/management/places/index.hbs +1 -1
- package/addon/templates/operations/scheduler/index.hbs +5 -4
- package/addon/utils/create-full-calendar-event-from-order.js +23 -1
- package/app/components/admin/avatar-management.js +1 -0
- package/app/components/avatar-picker.js +1 -0
- package/composer.json +2 -2
- package/config/environment.js +2 -0
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/migrations/2023_09_14_074512_update_vehicles_table.php +2 -2
- package/server/migrations/2023_09_14_074619_create_vehicle_devices_table.php +2 -2
- package/server/migrations/2023_09_26_071205_add_online_column_to_vehicles_table.php +2 -2
- package/server/migrations/2023_09_26_083957_create_fleet_vehicles_table.php +2 -2
- package/server/migrations/2023_09_27_023757_add_column_to_fleets_table.php +2 -2
- package/server/migrations/2023_10_05_074811_update_vehicle.php +2 -2
- package/server/migrations/2023_10_25_093014_create_vehicle_device_events_table.php +2 -2
- package/server/migrations/2023_11_03_072503_refactor_issues_table_columns.php +2 -2
- package/server/migrations/2023_11_06_040645_refactor_fuel_reports_table.php +2 -2
- package/server/migrations/2023_11_09_041807_add_status_column_to_fuel_reports_table.php +2 -2
- package/server/migrations/2023_11_15_062814_add_comments_column_and_resolved_at_column_to_vehicle_device_events_table.php +2 -2
- package/server/migrations/2023_11_17_053001_add_category_uuid_to_entities_table.php +2 -2
- package/server/migrations/2023_11_28_074244_add_supplier_uuid_column_to_entities_table.php +2 -2
- package/server/migrations/{2023_12_14_100209_add_meta_column_on_driver_table.php → 2023_12_14_100209_add_meta_column_on_driver_table copy.php } +10 -4
- package/server/migrations/2024_02_18_100209_add_avatar_url_columns_table.php +54 -0
- package/server/src/Expansions/UserExpansion.php +1 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +7 -1
- package/server/src/Http/Controllers/Api/v1/PlaceController.php +11 -2
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +15 -8
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +46 -0
- package/server/src/Http/Controllers/Internal/v1/PlaceController.php +12 -0
- package/server/src/Http/Resources/v1/Driver.php +6 -4
- package/server/src/Http/Resources/v1/Order.php +2 -1
- package/server/src/Http/Resources/v1/Payload.php +8 -4
- package/server/src/Http/Resources/v1/Place.php +2 -0
- package/server/src/Http/Resources/v1/Vehicle.php +1 -0
- package/server/src/Models/Driver.php +76 -0
- package/server/src/Models/Payload.php +49 -3
- package/server/src/Models/Place.php +71 -0
- package/server/src/Models/Vehicle.php +44 -20
- package/server/src/Notifications/OrderAssigned.php +2 -0
- package/server/src/routes.php +3 -0
- package/translations/en-us.yaml +16 -4
|
@@ -3,6 +3,7 @@ import { tracked } from '@glimmer/tracking';
|
|
|
3
3
|
import { action } from '@ember/object';
|
|
4
4
|
import { inject as service } from '@ember/service';
|
|
5
5
|
import { isArray } from '@ember/array';
|
|
6
|
+
import { task } from 'ember-concurrency-decorators';
|
|
6
7
|
import contextComponentCallback from '../utils/context-component-callback';
|
|
7
8
|
import applyContextComponentArguments from '../utils/apply-context-component-arguments';
|
|
8
9
|
import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
|
|
@@ -87,26 +88,50 @@ export default class EditOrderRoutePanelComponent extends Component {
|
|
|
87
88
|
contextComponentCallback(this, 'onLoad', ...arguments);
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
});
|
|
91
|
+
@task *save() {
|
|
92
|
+
const { payload } = this.order;
|
|
93
|
+
|
|
94
|
+
yield this.fetch
|
|
95
|
+
.patch(
|
|
96
|
+
`orders/route/${this.order.id}`,
|
|
97
|
+
{
|
|
98
|
+
pickup: payload.pickup,
|
|
99
|
+
dropoff: payload.dropoff,
|
|
100
|
+
return: payload.return,
|
|
101
|
+
waypoints: this._serializeWaypoints(payload.waypoints),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
normalizeToEmberData: true,
|
|
105
|
+
normalizeModelType: 'order',
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
.then((order) => {
|
|
109
|
+
this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.view.update-success', { orderId: order.public_id }));
|
|
110
|
+
contextComponentCallback(this, 'onAfterSave', order);
|
|
111
|
+
})
|
|
112
|
+
.catch((error) => {
|
|
113
|
+
this.notifications.serverError(error);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
_serializeWaypoints(waypoints = []) {
|
|
118
|
+
if (!waypoints) {
|
|
119
|
+
return [];
|
|
109
120
|
}
|
|
121
|
+
|
|
122
|
+
waypoints = typeof waypoints.toArray === 'function' ? waypoints.toArray() : Array.from(waypoints);
|
|
123
|
+
return waypoints.map((waypoint) => {
|
|
124
|
+
const json = waypoint.serialize();
|
|
125
|
+
// if place is serialized just send it back
|
|
126
|
+
if (json.place) {
|
|
127
|
+
return json;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// set id for place_uuid
|
|
131
|
+
json.place_uuid = waypoint.place ? waypoint.place.id : waypoint.place_uuid;
|
|
132
|
+
|
|
133
|
+
return json;
|
|
134
|
+
});
|
|
110
135
|
}
|
|
111
136
|
|
|
112
137
|
/**
|
|
@@ -147,26 +172,50 @@ export default class EditOrderRoutePanelComponent extends Component {
|
|
|
147
172
|
}
|
|
148
173
|
|
|
149
174
|
this.order.payload.setProperties({
|
|
175
|
+
pickup: null,
|
|
176
|
+
dropoff: null,
|
|
177
|
+
return: null,
|
|
150
178
|
pickup_uuid: null,
|
|
151
179
|
dropoff_uuid: null,
|
|
180
|
+
return_uuid: null,
|
|
152
181
|
});
|
|
153
182
|
} else {
|
|
154
|
-
|
|
155
|
-
this.order.payload.waypoints.
|
|
183
|
+
// get pickup from payload waypoints if available
|
|
184
|
+
const waypoints = typeof this.order.payload.waypoints.toArray === 'function' ? this.order.payload.waypoints.toArray() : Array.from(this.order.payload.waypoints);
|
|
185
|
+
|
|
186
|
+
if (waypoints[0]) {
|
|
187
|
+
const pickup = this.createPlaceFromWaypoint(waypoints[0]);
|
|
188
|
+
this.order.payload.set('pickup', pickup);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (waypoints[1]) {
|
|
192
|
+
const dropoff = this.createPlaceFromWaypoint(waypoints[1]);
|
|
193
|
+
this.order.payload.set('dropoff', dropoff);
|
|
194
|
+
}
|
|
156
195
|
|
|
157
196
|
this.order.payload.setProperties({
|
|
158
|
-
|
|
159
|
-
dropoff_uuid: null,
|
|
160
|
-
pickup: null,
|
|
161
|
-
dropoff: null,
|
|
197
|
+
waypoints: [],
|
|
162
198
|
});
|
|
163
199
|
}
|
|
164
200
|
|
|
201
|
+
// this.isMultiDrop = isMultiDrop;
|
|
165
202
|
contextComponentCallback(this, 'onRouteChanged');
|
|
166
203
|
}
|
|
167
204
|
|
|
205
|
+
createPlaceFromWaypoint(waypoint) {
|
|
206
|
+
const json = waypoint.serialize();
|
|
207
|
+
return this.store.createRecord('place', json);
|
|
208
|
+
}
|
|
209
|
+
|
|
168
210
|
addWaypointFromExistingPlace(place) {
|
|
169
|
-
const
|
|
211
|
+
const json = place.serialize();
|
|
212
|
+
const waypoint = this.store.createRecord('waypoint', {
|
|
213
|
+
uuid: place.id,
|
|
214
|
+
place_uuid: place.id,
|
|
215
|
+
location: place.location,
|
|
216
|
+
place,
|
|
217
|
+
...json,
|
|
218
|
+
});
|
|
170
219
|
this.order.payload.waypoints.pushObject(waypoint);
|
|
171
220
|
|
|
172
221
|
// fire callback
|
|
@@ -196,11 +245,13 @@ export default class EditOrderRoutePanelComponent extends Component {
|
|
|
196
245
|
return;
|
|
197
246
|
}
|
|
198
247
|
|
|
248
|
+
const json = place.serialize();
|
|
199
249
|
this.order.payload.waypoints.objectAt(index).setProperties({
|
|
200
|
-
|
|
250
|
+
uuid: place.id,
|
|
201
251
|
place_uuid: place.id,
|
|
202
252
|
location: place.location,
|
|
203
253
|
place,
|
|
254
|
+
...json,
|
|
204
255
|
});
|
|
205
256
|
|
|
206
257
|
// fire callback waypoint place selected
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
<FleetListingPanel @fleet={{subFleet}} @onVehicleClicked={{this.onVehicleClicked}} @depth={{add @depth 1}} @itemDropdownButton={{@itemDropdownButton}} @itemDropdownButtonActions={{@itemDropdownButtonActions}} />
|
|
4
4
|
{{/each}}
|
|
5
5
|
{{#each this.fleet.vehicles as |vehicle|}}
|
|
6
|
-
<Layout::Sidebar::Item @icon="circle" @iconSize="2xs" @iconClass={{if vehicle.online "text-green-500" "text-yellow-200"}} @onClick={{fn this.onVehicleClicked vehicle}} @rightSideComponent={{@itemRightSideComponent}} @rightSideComponentContext={{@itemRightSideComponentContext}} @rightSideStatus={{@itemRightSideStatus}} @rightSideStatusText={{@itemRightSideStatusText}} @hideRightSideStatusDot={{@itemHideRightSideStatusDot}} @rightSideStatusClass={{@itemRightSideStatusClass}} @disableRightSideStatusHumanize={{@itemDisableRightSideStatusHumanize}} @dropdownButton={{@itemDropdownButton}} @dropdownButtonActions={{@itemDropdownButtonActions}} @dropdownContext={{vehicle}} @dropdownButtonIcon={{@itemDropdownButtonIcon}} @dropdownButtonIconPrefix={{@itemDropdownButtonIconPrefix}} @dropdownButtonText={{@itemDropdownButtonText}} @dropdownButtonCalculatePosition={{@itemDropdownButtonCalculatePosition}} @
|
|
6
|
+
<Layout::Sidebar::Item @icon="circle" @iconSize="2xs" @iconClass={{if vehicle.online "text-green-500" "text-yellow-200"}} @onClick={{fn this.onVehicleClicked vehicle}} @rightSideComponent={{@itemRightSideComponent}} @rightSideComponentContext={{@itemRightSideComponentContext}} @rightSideStatus={{@itemRightSideStatus}} @rightSideStatusText={{@itemRightSideStatusText}} @hideRightSideStatusDot={{@itemHideRightSideStatusDot}} @rightSideStatusClass={{@itemRightSideStatusClass}} @disableRightSideStatusHumanize={{@itemDisableRightSideStatusHumanize}} @dropdownButton={{@itemDropdownButton}} @dropdownButtonActions={{@itemDropdownButtonActions}} @dropdownContext={{vehicle}} @dropdownButtonIcon={{@itemDropdownButtonIcon}} @dropdownButtonIconPrefix={{@itemDropdownButtonIconPrefix}} @dropdownButtonText={{@itemDropdownButtonText}} @dropdownButtonCalculatePosition={{@itemDropdownButtonCalculatePosition}} @dropdownButtonMenuLabel={{vehicle.displayName}} @dropdownButtonWrapperClass={{@itemDropdownButtonWrapperClass}} @dropdownButtonTriggerClass={{@itemDropdownButtonTriggerClass}} @registerDropdownButtonAPI={{@itemRegisterDropdownButtonAPI}} @dropdownButtonRenderInPlace={{false}}>{{vehicle.displayName}}</Layout::Sidebar::Item>
|
|
7
7
|
{{/each}}
|
|
8
8
|
</Layout::Sidebar::Panel>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<Layout::Sidebar::Panel @open={{true}} @title={{@title}} @titleIcon={{@icon}} @hideCaret={{true}} @toggleOnCaretOnly={{true}} @onClickPanelTitle={{this.transitionToRoute}} @wrapperClass="next-driver-listing">
|
|
2
2
|
{{#each this.drivers as |driver|}}
|
|
3
|
-
<Layout::Sidebar::Item @icon="circle" @iconSize="2xs" @iconClass={{if driver.online "text-green-500" "text-yellow-200"}} @onClick={{fn this.onDriverClicked driver}} class="driver-nav-item" @dropdownButton={{true}} @dropdownButtonActions={{this.dropdownButtonActions}} @dropdownContext={{driver}} @dropdownButtonIcon={{@itemDropdownButtonIcon}} @dropdownButtonIconPrefix={{@itemDropdownButtonIconPrefix}} @dropdownButtonText={{@itemDropdownButtonText}} @dropdownButtonCalculatePosition={{@itemDropdownButtonCalculatePosition}} @dropdownButtonRenderInPlace={{
|
|
3
|
+
<Layout::Sidebar::Item @icon="circle" @iconSize="2xs" @iconClass={{if driver.online "text-green-500" "text-yellow-200"}} @onClick={{fn this.onDriverClicked driver}} class="driver-nav-item" @dropdownButton={{true}} @dropdownButtonActions={{this.dropdownButtonActions}} @dropdownContext={{driver}} @dropdownButtonIcon={{@itemDropdownButtonIcon}} @dropdownButtonIconPrefix={{@itemDropdownButtonIconPrefix}} @dropdownButtonText={{@itemDropdownButtonText}} @dropdownButtonCalculatePosition={{@itemDropdownButtonCalculatePosition}} @dropdownButtonRenderInPlace={{false}} @dropdownButtonMenuLabel={{driver.name}} @dropdownButtonWrapperClass={{@itemDropdownButtonWrapperClass}} @dropdownButtonTriggerClass={{@itemDropdownButtonTriggerClass}} @dropdownHorizontalPosition="left" @registerDropdownButtonAPI={{@itemRegisterDropdownButtonAPI}} @rightSideComponent={{@itemRightSideComponent}} @rightSideComponentContext={{@itemRightSideComponentContext}} @rightSideStatus={{@itemRightSideStatus}} @rightSideStatusText={{@itemRightSideStatusText}} @hideRightSideStatusDot={{@itemHideRightSideStatusDot}} @rightSideStatusClass={{@itemRightSideStatusClass}} @disableRightSideStatusHumanize={{@itemDisableRightSideStatusHumanize}}>{{driver.name}}</Layout::Sidebar::Item>
|
|
4
4
|
{{/each}}
|
|
5
5
|
</Layout::Sidebar::Panel>
|
|
@@ -393,7 +393,6 @@ export default class LiveMapComponent extends Component {
|
|
|
393
393
|
|
|
394
394
|
// trigger that initial coordinates is set to livemap component
|
|
395
395
|
this.universe.trigger('fleet-ops.live-map.has_coordinates', { latitude: this.latitude, longitude: this.longitude });
|
|
396
|
-
return [this.latitude, this.longitude];
|
|
397
396
|
}
|
|
398
397
|
|
|
399
398
|
/**
|
|
@@ -7,25 +7,31 @@
|
|
|
7
7
|
</a>
|
|
8
8
|
<div class="{{@contentClass}} card-content bg-white dark:bg-gray-900 text-sm space-y-2">
|
|
9
9
|
<div class="flex items-center justify-between">
|
|
10
|
-
<div>
|
|
11
|
-
<
|
|
10
|
+
<div class="flex flex-row items-center leading-5">
|
|
11
|
+
<div class="w-4">
|
|
12
|
+
<FaIcon @icon="clock" @size="xs" />
|
|
13
|
+
</div>
|
|
12
14
|
<span class="font-semibold">{{t "fleet-ops.component.order.schedule-card.date"}}</span>
|
|
13
15
|
</div>
|
|
14
16
|
<span class={{unless @order.scheduled_at "dark:text-gray-600 text-gray-400"}}>{{n-a @order.scheduledAt "Not Scheduled"}}</span>
|
|
15
17
|
</div>
|
|
16
18
|
<div class="flex items-center justify-between">
|
|
17
|
-
<div>
|
|
18
|
-
<
|
|
19
|
+
<div class="flex flex-row items-center leading-5">
|
|
20
|
+
<div class="w-4">
|
|
21
|
+
<FaIcon @icon="calendar" @size="xs" />
|
|
22
|
+
</div>
|
|
19
23
|
<span class="font-semibold">Date created</span>
|
|
20
24
|
</div>
|
|
21
25
|
<span>{{n-a @order.createdAtWithTime}}</span>
|
|
22
26
|
</div>
|
|
23
27
|
<div class="flex items-center justify-between">
|
|
24
28
|
<div class="flex flex-row items-center">
|
|
25
|
-
<
|
|
29
|
+
<div class="w-4">
|
|
30
|
+
<FaIcon @icon="id-card-alt" @size="xs" />
|
|
31
|
+
</div>
|
|
26
32
|
<span class="font-semibold">{{t "fleet-ops.component.order.schedule-card.driver-assigned"}}</span>
|
|
27
|
-
<div class="ml-
|
|
28
|
-
<a href="javascript:;" class="text-blue-400 hover:opacity-75" {{on "click" this.startAssignDriver}}>
|
|
33
|
+
<div class="ml-1">
|
|
34
|
+
<a href="javascript:;" class="text-blue-400 text-xs hover:opacity-75" {{on "click" this.startAssignDriver}}>
|
|
29
35
|
<FaIcon @icon="edit" @size="xs" />
|
|
30
36
|
</a>
|
|
31
37
|
</div>
|
|
@@ -33,14 +39,9 @@
|
|
|
33
39
|
<div>
|
|
34
40
|
{{#if this.isAssigningDriver}}
|
|
35
41
|
<ModelSelect @modelName="driver" @selectedModel={{@order.driver_assigned}} @placeholder={{t "fleet-ops.component.order.schedule-card.select-driver"}} @triggerClass="form-select form-input form-input-sm w-48" @infiniteScroll={{false}} @renderInPlace={{true}} @allowClear={{true}} @disabled={{@model.isLoading}} @onChange={{this.assignDriver}} as |model|>
|
|
36
|
-
<div class="flex items-center">
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
</div>
|
|
40
|
-
<div class="flex-1 flex flex-row truncate text-xs">
|
|
41
|
-
<span class="uppercase mr-1.5 text-xs">{{model.name}}</span>
|
|
42
|
-
<span class="uppercase text-xs">{{model.phone}}</span>
|
|
43
|
-
</div>
|
|
42
|
+
<div class="flex flex-row items-center truncate uppercase">
|
|
43
|
+
<span class="uppercase mr-1.5">{{model.name}}</span>
|
|
44
|
+
<span class="uppercase">{{model.phone}}</span>
|
|
44
45
|
</div>
|
|
45
46
|
</ModelSelect>
|
|
46
47
|
{{else}}
|
|
@@ -49,12 +50,23 @@
|
|
|
49
50
|
</div>
|
|
50
51
|
</div>
|
|
51
52
|
<div class="flex items-center justify-between">
|
|
52
|
-
<div class="flex flex-row items-center">
|
|
53
|
-
<
|
|
53
|
+
<div class="flex flex-row items-center leading-5">
|
|
54
|
+
<div class="w-4">
|
|
55
|
+
<FaIcon @icon="car" @size="xs" />
|
|
56
|
+
</div>
|
|
54
57
|
<span class="font-semibold">{{t "fleet-ops.component.order.schedule-card.vehicle-assigned"}}</span>
|
|
55
58
|
</div>
|
|
56
59
|
<a href="javascript:;" disabled={{not @order.driver_assigned.vehicle}} class={{unless @order.driver_assigned.vehicle_uuid "dark:text-gray-600 text-gray-400"}} {{on "click" (fn this.onClickVehicle @order.driver_assigned.vehicle)}}>{{n-a @order.driver_assigned.vehicle_name (t "fleet-ops.component.order.schedule-card.no-vehicle")}}</a>
|
|
57
60
|
</div>
|
|
61
|
+
<div class="flex items-center justify-between">
|
|
62
|
+
<div class="flex flex-row items-center leading-5">
|
|
63
|
+
<div class="w-4">
|
|
64
|
+
<FaIcon @icon="location-dot" @size="xs" />
|
|
65
|
+
</div>
|
|
66
|
+
<span class="font-semibold">{{t "fleet-ops.component.order.schedule-card.destination"}}</span>
|
|
67
|
+
</div>
|
|
68
|
+
<span>{{n-a @order.pickupName}}</span>
|
|
69
|
+
</div>
|
|
58
70
|
{{!-- <div class="z-20 relative">
|
|
59
71
|
<RouteList @order={{@order}} />
|
|
60
72
|
</div> --}}
|
|
@@ -1,61 +1,45 @@
|
|
|
1
|
-
<Overlay
|
|
2
|
-
@
|
|
3
|
-
@onOpen={{this.onOpen}}
|
|
4
|
-
@onClose={{this.onClose}}
|
|
5
|
-
@onToggle={{this.onToggle}}
|
|
6
|
-
@position="right"
|
|
7
|
-
@noBackdrop={{true}}
|
|
8
|
-
@fullHeight={{true}}
|
|
9
|
-
@isResizeble={{or this.isResizable @isResizable}}
|
|
10
|
-
@width={{or this.width @width "570px"}}
|
|
11
|
-
>
|
|
12
|
-
<Overlay::Header
|
|
13
|
-
@title={{if this.place.public_id this.place.name (t "fleet-ops.component.place-form-panel.place") }}
|
|
14
|
-
@status={{this.place.public_id}}
|
|
15
|
-
@hideStatusDot={{true}}
|
|
16
|
-
@createdAt={{this.place.createdAt}}
|
|
17
|
-
@titleWrapperClass="leading-5"
|
|
18
|
-
>
|
|
1
|
+
<Overlay @onLoad={{this.setOverlayContext}} @onOpen={{this.onOpen}} @onClose={{this.onClose}} @onToggle={{this.onToggle}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @isResizeble={{true}} @width="570px" @overlayClass="place-form-panel">
|
|
2
|
+
<Overlay::Header @title={{if this.place.public_id this.place.address (t "fleet-ops.component.place-form-panel.place")}} @status={{this.place.public_id}} @hideStatusDot={{true}} @titleWrapperClass="flex-col leading-5">
|
|
19
3
|
<div class="flex flex-1 justify-end">
|
|
20
|
-
<Button @icon={{if this.place.id "save" "check"}} @type="primary" @text={{if this.place.id (t "fleet-ops.component.place-form-panel.save-place")(t "fleet-ops.component.place-form-panel.create-place")
|
|
4
|
+
<Button @icon={{if this.place.id "save" "check"}} @type="primary" @text={{if this.place.id (t "fleet-ops.component.place-form-panel.save-place") (t "fleet-ops.component.place-form-panel.create-place")}} @onClick={{this.save}} @wrapperClass="mr-2" />
|
|
21
5
|
<Button @type="default" @icon="times" @helpText={{if this.place.id (t "fleet-ops.component.place-form-panel.cancel-edit-place")(t "fleet-ops.component.place-form-panel.cancel-new-place") }} @onClick={{this.onPressCancel}} />
|
|
22
6
|
</div>
|
|
23
7
|
</Overlay::Header>
|
|
24
8
|
|
|
25
9
|
<Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
|
|
26
|
-
<div class="
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
{{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
@value={{this.place.location}}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@
|
|
52
|
-
|
|
53
|
-
</
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
</InputGroup>
|
|
10
|
+
<div class="flex-1 space-y-4">
|
|
11
|
+
<div class="grid grid-cols-3 gap-1 text-xs dark:text-gray-100">
|
|
12
|
+
<InputGroup @name={{t "fleet-ops.common.name"}} @wrapperClass="col-span-2">
|
|
13
|
+
<Input @value={{this.place.name}} @type="text" class="w-full form-input" placeholder={{t "fleet-ops.common.name"}} />
|
|
14
|
+
</InputGroup>
|
|
15
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.street-1"}} @value={{this.place.street1}} @wrapperClass="col-span-3">
|
|
16
|
+
<AutocompleteInput @value={{this.place.street1}} @fetchUrl="places/lookup" @onSelect={{this.onAutocomplete}} placeholder={{t "fleet-ops.component.place-form-panel.street-1"}} class="w-full" as |result|>
|
|
17
|
+
{{result.address}}
|
|
18
|
+
</AutocompleteInput>
|
|
19
|
+
</InputGroup>
|
|
20
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.street-2"}} @autocomplete="nope" @value={{this.place.street2}} @wrapperClass="col-span-3" />
|
|
21
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.neighborhood"}} @autocomplete="nope" @value={{this.place.neighborhood}} />
|
|
22
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.building"}} @autocomplete="nope" @value={{this.place.building}} />
|
|
23
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.security-code"}} @autocomplete="nope" @value={{this.place.security_access_code}} />
|
|
24
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.postal-code"}} @autocomplete="nope" @value={{this.place.postal_code}} />
|
|
25
|
+
<InputGroup @name={{t "fleet-ops.common.city"}} @autocomplete="nope" @value={{this.place.city}} />
|
|
26
|
+
<InputGroup @name={{t "fleet-ops.component.place-form-panel.state"}} @autocomplete="nope" @value={{this.place.province}} />
|
|
27
|
+
<InputGroup @name={{t "fleet-ops.common.country"}} @wrapperClass="col-span-2">
|
|
28
|
+
<CountrySelect class="w-full form-input form-select form-datalist" @value={{this.place.country}} @onChange={{fn (mut this.place.country)}} placeholder={{t "fleet-ops.common.country"}} />
|
|
29
|
+
</InputGroup>
|
|
30
|
+
<InputGroup @name={{t "fleet-ops.common.coordinates"}} @wrapperClass="col-span-2">
|
|
31
|
+
<CoordinatesInput @value={{this.place.location}} @onChange={{this.updatePlaceCoordinates}} @onGeocode={{this.onAutocomplete}} @onUpdatedFromMap={{this.onReverseGeocode}} @onInit={{this.setCoordinatesInput}} />
|
|
32
|
+
</InputGroup>
|
|
33
|
+
<div class="col-span-1"></div>
|
|
34
|
+
<InputGroup @name={{t "fleet-ops.common.phone"}}>
|
|
35
|
+
<PhoneInput @value={{this.place.phone}} @autocomplete="nope" @onInput={{this.phone}} class="form-input w-full" />
|
|
36
|
+
</InputGroup>
|
|
37
|
+
</div>
|
|
38
|
+
<ContentPanel @title={{t "fleet-ops.component.avatar-picker.avatar"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
39
|
+
<AvatarPicker @model={{this.place}} @defaultAvatar={{config "defaultValues.placeAvatar"}} />
|
|
40
|
+
</ContentPanel>
|
|
58
41
|
</div>
|
|
42
|
+
|
|
59
43
|
<Spacer @height="300px" />
|
|
60
44
|
</Overlay::Body>
|
|
61
45
|
</Overlay>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div class="p-4 space-y-4">
|
|
2
|
-
<ContentPanel @title="Map" @open={{
|
|
2
|
+
<ContentPanel @title="Map" @open={{true}}>
|
|
3
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
5
|
<layers.marker
|
|
@@ -23,58 +23,54 @@
|
|
|
23
23
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-2 text-xs dark:text-gray-100">
|
|
24
24
|
<div class="field-info-container col-span-3">
|
|
25
25
|
<div class="field-name">{{t "fleet-ops.common.name"}}</div>
|
|
26
|
-
<div class="field-value">{{n-a @place.name}}</div>
|
|
26
|
+
<div class="field-value uppercase">{{n-a @place.name}}</div>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
29
|
<div class="field-info-container col-span-3">
|
|
30
30
|
<div class="field-name">{{t "fleet-ops.common.street"}}</div>
|
|
31
|
-
<div class="field-value">{{n-a @place.street1}}</div>
|
|
31
|
+
<div class="field-value uppercase">{{n-a @place.street1}}</div>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
34
|
<div class="field-info-container">
|
|
35
35
|
<div class="field-name">{{t "fleet-ops.common.neighborhood"}}</div>
|
|
36
|
-
<div class="field-value">{{n-a @place.neighborhood}}</div>
|
|
36
|
+
<div class="field-value uppercase">{{n-a @place.neighborhood}}</div>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
39
|
<div class="field-info-container">
|
|
40
40
|
<div class="field-name">{{t "fleet-ops.common.building"}}</div>
|
|
41
|
-
<div class="field-value">{{n-a @place.building}}</div>
|
|
41
|
+
<div class="field-value uppercase">{{n-a @place.building}}</div>
|
|
42
42
|
</div>
|
|
43
43
|
|
|
44
44
|
<div class="field-info-container">
|
|
45
45
|
<div class="field-name">{{t "fleet-ops.common.security-access-code"}}</div>
|
|
46
|
-
<div class="field-value">{{n-a @place.security_access_code}}</div>
|
|
46
|
+
<div class="field-value uppercase">{{n-a @place.security_access_code}}</div>
|
|
47
47
|
</div>
|
|
48
48
|
|
|
49
49
|
<div class="field-info-container">
|
|
50
50
|
<div class="field-name">{{t "fleet-ops.common.city"}}</div>
|
|
51
|
-
<div class="field-value">{{n-a @place.city}}</div>
|
|
51
|
+
<div class="field-value uppercase">{{n-a @place.city}}</div>
|
|
52
52
|
</div>
|
|
53
53
|
|
|
54
54
|
<div class="field-info-container">
|
|
55
55
|
<div class="field-name">{{t "fleet-ops.common.state"}}</div>
|
|
56
|
-
<div class="field-value">{{n-a @place.province}}</div>
|
|
56
|
+
<div class="field-value uppercase">{{n-a @place.province}}</div>
|
|
57
57
|
</div>
|
|
58
58
|
|
|
59
59
|
<div class="field-info-container">
|
|
60
60
|
<div class="field-name">{{t "fleet-ops.common.country"}}</div>
|
|
61
|
-
<div class="field-value">
|
|
61
|
+
<div class="field-value uppercase">
|
|
62
62
|
<CountryName @country={{@place.country}} @showFlag={{true}} />
|
|
63
63
|
</div>
|
|
64
64
|
</div>
|
|
65
65
|
|
|
66
66
|
<div class="field-info-container">
|
|
67
67
|
<div class="field-name">{{t "fleet-ops.common.phone"}}</div>
|
|
68
|
-
<div class="field-value">{{n-a @place.phone}}</div>
|
|
68
|
+
<div class="field-value uppercase">{{n-a @place.phone}}</div>
|
|
69
69
|
</div>
|
|
70
70
|
|
|
71
71
|
<div class="field-info-container col-span-3">
|
|
72
72
|
<div class="field-name">
|
|
73
73
|
{{t "fleet-ops.common.coordinates"}}
|
|
74
|
-
{{!-- <a href="javascript:;" class="block ml-3" {{on "click" @place.viewPlaceOnMap}}>
|
|
75
|
-
<FaIcon @icon="map" class="mr-1" />
|
|
76
|
-
View on map
|
|
77
|
-
</a> --}}
|
|
78
74
|
</div>
|
|
79
75
|
<div class="field-value">
|
|
80
76
|
{{point-coordinates @place.location}}
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
<Overlay
|
|
2
|
-
@
|
|
3
|
-
@onOpen={{this.onOpen}}
|
|
4
|
-
@onClose={{this.onClose}}
|
|
5
|
-
@onToggle={{this.onToggle}}
|
|
6
|
-
@position="right"
|
|
7
|
-
@noBackdrop={{true}}
|
|
8
|
-
@fullHeight={{true}}
|
|
9
|
-
@isResizable={{or this.isResizable @isResizable}}
|
|
10
|
-
@width={{or this.width @width "570px"}}
|
|
11
|
-
>
|
|
12
|
-
<Overlay::Header @title={{this.place.name}} @status={{this.place.public_id}} @hideStatusDot={{true}} @createdAt={{this.place.createdAt}}>
|
|
1
|
+
<Overlay @onLoad={{this.setOverlayContext}} @onOpen={{this.onOpen}} @onClose={{this.onClose}} @onToggle={{this.onToggle}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @isResizable={{true}} @width="570px" @overlayClass="place-panel">
|
|
2
|
+
<Overlay::Header @title={{this.place.address}} @status={{this.place.public_id}} @hideStatusDot={{true}}>
|
|
13
3
|
<Button @type="default" @icon="pen" @helpText={{t "fleet-ops.component.place-panel.edit-place"}} @onClick={{this.onEdit}} @wrapperClass="mr-2" />
|
|
14
4
|
<Button @type="default" @icon="times" @helpText={{if this.place.id (t "fleet-ops.component.place-panel.cancel-edit-place")(t "fleet-ops.component.place-panel.cancel-new-place") }} @onClick={{this.onPressCancel}} />
|
|
15
5
|
</Overlay::Header>
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
<Overlay
|
|
2
|
-
@onLoad={{this.setOverlayContext}}
|
|
3
|
-
@onOpen={{this.onOpen}}
|
|
4
|
-
@onClose={{this.onClose}}
|
|
5
|
-
@onToggle={{this.onToggle}}
|
|
6
|
-
@position="right"
|
|
7
|
-
@noBackdrop={{true}}
|
|
8
|
-
@fullHeight={{true}}
|
|
9
|
-
@isResizeble={{or this.isResizable @isResizable}}
|
|
10
|
-
@width={{or this.width @width "570px"}}
|
|
11
|
-
>
|
|
1
|
+
<Overlay @onLoad={{this.setOverlayContext}} @onOpen={{this.onOpen}} @onClose={{this.onClose}} @onToggle={{this.onToggle}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @isResizeble={{or this.isResizable @isResizable}} @width={{or this.width @width "570px"}}>
|
|
12
2
|
<Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]">
|
|
13
3
|
<div class="flex flex-row items-center justify-between w-full mb-4">
|
|
14
4
|
<div class="flex flex-1 space-x-2">
|
|
@@ -18,21 +8,9 @@
|
|
|
18
8
|
</div>
|
|
19
9
|
<div class="flex flex-1 justify-end">
|
|
20
10
|
<div class="mr-2">
|
|
21
|
-
<Button
|
|
22
|
-
@icon={{if this.vehicle.id "save" "check"}}
|
|
23
|
-
@type="primary"
|
|
24
|
-
@text={{if this.vehicle.id (t "fleet-ops.component.vehicle-form-panel.save-vehicle")(t "fleet-ops.component.vehicle-form-panel.create-vehicle") }}
|
|
25
|
-
@onClick={{this.save}}
|
|
26
|
-
@isLoading={{this.isLoading}}
|
|
27
|
-
/>
|
|
11
|
+
<Button @icon={{if this.vehicle.id "save" "check"}} @type="primary" @text={{if this.vehicle.id (t "fleet-ops.component.vehicle-form-panel.save-vehicle") (t "fleet-ops.component.vehicle-form-panel.create-vehicle")}} @onClick={{this.save}} @isLoading={{this.isLoading}} />
|
|
28
12
|
</div>
|
|
29
|
-
<Button
|
|
30
|
-
@type="default"
|
|
31
|
-
@icon="times"
|
|
32
|
-
@helpText={{if this.vehicle.id (t "fleet-ops.component.vehicle-form-panel.cancel-edit-vehicle")(t "fleet-ops.component.vehicle-form-panel.cancel-new-vehicle") }}
|
|
33
|
-
@onClick={{this.onPressCancel}}
|
|
34
|
-
@disabled={{this.isLoading}}
|
|
35
|
-
/>
|
|
13
|
+
<Button @type="default" @icon="times" @helpText={{if this.vehicle.id (t "fleet-ops.component.vehicle-form-panel.cancel-edit-vehicle") (t "fleet-ops.component.vehicle-form-panel.cancel-new-vehicle")}} @onClick={{this.onPressCancel}} @disabled={{this.isLoading}} />
|
|
36
14
|
</div>
|
|
37
15
|
</div>
|
|
38
16
|
<div class="flex flex-row justify-between w-full">
|
|
@@ -45,15 +23,7 @@
|
|
|
45
23
|
<InputInfo @text={{t "fleet-ops.component.vehicle-form-panel.upload-photo"}} />
|
|
46
24
|
</Attach::Tooltip>
|
|
47
25
|
<div class="upload-avatar-button-wrapper rounded-lg">
|
|
48
|
-
<UploadButton
|
|
49
|
-
@name={{t "fleet-ops.common.photos"}}
|
|
50
|
-
@accept="image/*"
|
|
51
|
-
@onFileAdded={{this.onUploadNewPhoto}}
|
|
52
|
-
@icon="upload"
|
|
53
|
-
@hideButtonText={{true}}
|
|
54
|
-
@labelClass="upload-avatar-label-overlay"
|
|
55
|
-
class="w-12 btn-reset"
|
|
56
|
-
/>
|
|
26
|
+
<UploadButton @name={{t "fleet-ops.common.photos"}} @accept="image/*" @onFileAdded={{this.onUploadNewPhoto}} @icon="upload" @hideButtonText={{true}} @labelClass="upload-avatar-label-overlay" class="w-12 btn-reset" />
|
|
57
27
|
</div>
|
|
58
28
|
</div>
|
|
59
29
|
</div>
|
|
@@ -118,68 +88,29 @@
|
|
|
118
88
|
</InputGroup>
|
|
119
89
|
|
|
120
90
|
<InputGroup @name={{t "fleet-ops.component.vehicle-form-panel.driver-assigned"}}>
|
|
121
|
-
<ModelSelect
|
|
122
|
-
@modelName="driver"
|
|
123
|
-
@selectedModel={{this.vehicle.driver}}
|
|
124
|
-
@placeholder={{t "fleet-ops.component.vehicle-form-panel.select-driver"}}
|
|
125
|
-
@triggerClass="form-select form-input"
|
|
126
|
-
@infiniteScroll={{false}}
|
|
127
|
-
@renderInPlace={{true}}
|
|
128
|
-
@onChange={{fn (mut this.vehicle.driver)}}
|
|
129
|
-
as |model|
|
|
130
|
-
>
|
|
91
|
+
<ModelSelect @modelName="driver" @selectedModel={{this.vehicle.driver}} @placeholder={{t "fleet-ops.component.vehicle-form-panel.select-driver"}} @triggerClass="form-select form-input" @infiniteScroll={{false}} @renderInPlace={{true}} @onChange={{fn (mut this.vehicle.driver)}} as |model|>
|
|
131
92
|
{{model.name}}
|
|
132
93
|
</ModelSelect>
|
|
133
94
|
</InputGroup>
|
|
134
95
|
|
|
135
96
|
<InputGroup @name={{t "fleet-ops.common.status"}}>
|
|
136
97
|
<div class="fleetbase-model-select fleetbase-power-select ember-model-select">
|
|
137
|
-
<PowerSelect
|
|
138
|
-
@options={{this.vehicleStatusOptions}}
|
|
139
|
-
@selected={{this.vehicle.status}}
|
|
140
|
-
@onChange={{fn (mut this.vehicle.status)}}
|
|
141
|
-
@placeholder={{t "fleet-ops.component.vehicle-form-panel.select-vehicle"}}
|
|
142
|
-
@triggerClass="form-select form-input"
|
|
143
|
-
as |status|
|
|
144
|
-
>
|
|
98
|
+
<PowerSelect @options={{this.vehicleStatusOptions}} @selected={{this.vehicle.status}} @onChange={{fn (mut this.vehicle.status)}} @placeholder={{t "fleet-ops.component.vehicle-form-panel.select-vehicle"}} @triggerClass="form-select form-input" as |status|>
|
|
145
99
|
{{smart-humanize status}}
|
|
146
100
|
</PowerSelect>
|
|
147
101
|
</div>
|
|
148
102
|
</InputGroup>
|
|
149
103
|
<InputGroup @name={{t "fleet-ops.common.coordinates"}} @wrapperClass="col-span-2">
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
@onChange={{this.onCoordinatesChanged}}
|
|
153
|
-
@onGeocode={{this.onAutocomplete}}
|
|
154
|
-
@onUpdatedFromMap={{this.onCoordinatesChanged}}
|
|
155
|
-
@onInit={{this.setCoordinatesInput}}
|
|
156
|
-
/>
|
|
157
|
-
</InputGroup>
|
|
104
|
+
<CoordinatesInput @value={{this.vehicle.location}} @onChange={{this.onCoordinatesChanged}} @onGeocode={{this.onAutocomplete}} @onUpdatedFromMap={{this.onCoordinatesChanged}} @onInit={{this.setCoordinatesInput}} />
|
|
105
|
+
</InputGroup>
|
|
158
106
|
</div>
|
|
159
107
|
</ContentPanel>
|
|
160
108
|
|
|
161
|
-
<ContentPanel @title={{t "fleet-ops.component.
|
|
162
|
-
<
|
|
163
|
-
<div class="input-group mb-2">
|
|
164
|
-
<InputLabel @labelText={{t "fleet-ops.component.vehicle-form-panel.select-map-avatar"}} @helpText={{t "fleet-ops.component.vehicle-form-panel.select-avatar-rendering"}} />
|
|
165
|
-
<FetchSelect
|
|
166
|
-
@wrapperClass="w-60"
|
|
167
|
-
@placeholder={{t "fleet-ops.component.vehicle-form-panel.select-avatar"}}
|
|
168
|
-
@endpoint="vehicles/avatars"
|
|
169
|
-
@selected={{this.vehicle.avatar_url}}
|
|
170
|
-
@optionValue="value"
|
|
171
|
-
@onChange={{fn (mut this.vehicle.avatar_url)}}
|
|
172
|
-
as |option|
|
|
173
|
-
>
|
|
174
|
-
{{titleize (humanize option.key)}}
|
|
175
|
-
</FetchSelect>
|
|
176
|
-
</div>
|
|
177
|
-
<div>
|
|
178
|
-
<img alt={{this.vehicle.displayName}} src={{this.vehicle.avatar_url}} class="w-24 h-24" />
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
109
|
+
<ContentPanel @title={{t "fleet-ops.component.avatar-picker.avatar"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
110
|
+
<AvatarPicker @model={{this.vehicle}} @defaultAvatar={{config "defaultValues.vehicleAvatar"}} />
|
|
181
111
|
</ContentPanel>
|
|
182
112
|
</div>
|
|
113
|
+
|
|
183
114
|
<Spacer @height="300px" />
|
|
184
115
|
</Overlay::Body>
|
|
185
116
|
</Overlay>
|