@fleetbase/fleetops-engine 0.4.2 → 0.4.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/edit-order-route-panel.hbs +182 -0
- package/addon/components/edit-order-route-panel.js +265 -0
- package/addon/components/fleet-panel.js +3 -3
- package/addon/components/map-container/toolbar.hbs +2 -2
- package/addon/components/modals/order-route-form.hbs +1 -1
- package/addon/controllers/operations/orders/index/new.js +73 -36
- package/addon/controllers/operations/orders/index/view.js +131 -126
- package/addon/routes/operations/orders/index/view.js +1 -1
- package/addon/services/context-panel.js +6 -0
- package/addon/styles/fleetops-engine.css +5 -0
- package/addon/templates/operations/orders/index/new.hbs +390 -58
- package/addon/templates/operations/orders/index/view.hbs +135 -105
- package/addon/templates/operations/service-rates/index/new.hbs +3 -1
- package/composer.json +2 -2
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/src/Http/Controllers/Api/v1/DriverController.php +59 -20
- package/server/src/Http/Controllers/Api/v1/OrderController.php +2 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +16 -3
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +11 -0
- package/server/src/Http/Resources/v1/Order.php +3 -0
- package/server/src/Http/Resources/v1/PurchaseRate.php +2 -1
- package/server/src/Http/Resources/v1/ServiceQuote.php +1 -0
- package/server/src/Http/Resources/v1/ServiceQuoteItem.php +29 -0
- package/server/src/Models/Driver.php +1 -1
- package/server/src/Models/Order.php +16 -0
- package/server/src/Models/Place.php +2 -2
- package/server/src/Observers/DriverObserver.php +6 -1
- package/server/src/routes.php +1 -0
- package/translations/en-us.yaml +9 -2
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
<Overlay @position="right" @noBackdrop={{true}} @width="
|
|
2
|
-
<Overlay::Header
|
|
3
|
-
@overlay={{overlay}}
|
|
4
|
-
@title={{@model.public_id}}
|
|
5
|
-
@status={{@model.status}}
|
|
6
|
-
@dispatched={{@model.dispatched}}
|
|
7
|
-
@createdAt={{@model.createdAt}}
|
|
8
|
-
@onPressCancel={{this.transitionBack}}
|
|
9
|
-
>
|
|
1
|
+
<Overlay @position="right" @noBackdrop={{true}} @width="550px" @fullHeight={{true}} @isResizable={{true}} @onLoad={{this.setupInterface}} as |overlay|>
|
|
2
|
+
<Overlay::Header @overlay={{overlay}} @title={{@model.public_id}} @status={{@model.status}} @dispatched={{@model.dispatched}} @createdAt={{@model.createdAt}} @onPressCancel={{this.transitionBack}}>
|
|
10
3
|
{{#if @model.canBeDispatched}}
|
|
11
4
|
<Button @type="primary" @icon="paper-plane" @text={{t "fleet-ops.operations.orders.index.view.dispatch"}} class="mr-2" @onClick={{fn this.dispatchOrder @model}} />
|
|
12
5
|
{{/if}}
|
|
@@ -87,15 +80,8 @@
|
|
|
87
80
|
</DropdownButton>
|
|
88
81
|
</Overlay::Header>
|
|
89
82
|
|
|
90
|
-
<Overlay::Body @wrapperClass="new-order-overlay-body"
|
|
91
|
-
<ContentPanel
|
|
92
|
-
@title={{t "fleet-ops.operations.orders.index.view.activity"}}
|
|
93
|
-
@open={{true}}
|
|
94
|
-
@pad={{false}}
|
|
95
|
-
@isLoading={{not this.loadOrderRelations.isIdle}}
|
|
96
|
-
@panelBodyWrapperClass="px-0 py-4"
|
|
97
|
-
@panelBodyClass="bg-white dark:bg-gray-800"
|
|
98
|
-
>
|
|
83
|
+
<Overlay::Body @wrapperClass="new-order-overlay-body">
|
|
84
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.activity"}} @open={{true}} @pad={{false}} @isLoading={{not this.loadOrderRelations.isIdle}} @panelBodyWrapperClass="px-0 py-4" @panelBodyClass="bg-white dark:bg-gray-800">
|
|
99
85
|
{{#if @model.tracking_statuses}}
|
|
100
86
|
<Timeline @activity={{@model.tracking_statuses}} @arrowClass="bg-gray-600 border border-gray-900 shadow-md" as |TimelineItem|>
|
|
101
87
|
<TimelineItem @activeStatus={{@model.status}} as |trackingStatus|>
|
|
@@ -135,12 +121,7 @@
|
|
|
135
121
|
<div class="field-name">{{t "fleet-ops.operations.orders.index.view.customer"}}</div>
|
|
136
122
|
<div class="flex flex-row">
|
|
137
123
|
<div>
|
|
138
|
-
<Image
|
|
139
|
-
src={{avatar-url @model.customer.photo_url}}
|
|
140
|
-
@fallbackSrc={{config "defaultValues.contactImage"}}
|
|
141
|
-
class="w-8 h-8 rounded-md shadow-sm mr-2"
|
|
142
|
-
alt={{@model.customer.name}}
|
|
143
|
-
/>
|
|
124
|
+
<Image src={{avatar-url @model.customer.photo_url}} @fallbackSrc={{config "defaultValues.contactImage"}} class="w-8 h-8 rounded-md shadow-sm mr-2" alt={{@model.customer.name}} />
|
|
144
125
|
</div>
|
|
145
126
|
<div>
|
|
146
127
|
<div class="field-value">{{n-a @model.customer.name "No Customer"}}</div>
|
|
@@ -155,12 +136,7 @@
|
|
|
155
136
|
{{#if @model.facilitator.isIntegratedVendor}}
|
|
156
137
|
<div class="flex flex-row">
|
|
157
138
|
<div>
|
|
158
|
-
<Image
|
|
159
|
-
src={{avatar-url @model.facilitator.photo_url}}
|
|
160
|
-
@fallbackSrc={{config "defaultValues.contactImage"}}
|
|
161
|
-
class="w-8 h-8 rounded-md border border-gray-200 dark:border-gray-900 shadow-sm mr-2"
|
|
162
|
-
alt={{@model.facilitator.name}}
|
|
163
|
-
/>
|
|
139
|
+
<Image src={{avatar-url @model.facilitator.photo_url}} @fallbackSrc={{config "defaultValues.contactImage"}} class="w-8 h-8 rounded-md border border-gray-200 dark:border-gray-900 shadow-sm mr-2" alt={{@model.facilitator.name}} />
|
|
164
140
|
</div>
|
|
165
141
|
<div>
|
|
166
142
|
<div class="field-value">{{n-a @model.facilitator.name}}</div>
|
|
@@ -177,14 +153,7 @@
|
|
|
177
153
|
<div>
|
|
178
154
|
<a href="javascript:;" class="flex flex-row" {{on "click" (fn this.focusOrderAssignedDriver @model)}}>
|
|
179
155
|
<div>
|
|
180
|
-
<Image
|
|
181
|
-
src={{avatar-url @model.driver_assigned.photo_url}}
|
|
182
|
-
@fallbackSrc={{config "defaultValues.driverImage"}}
|
|
183
|
-
width="32"
|
|
184
|
-
height="32"
|
|
185
|
-
class="w-8 h-8 rounded-md shadow-sm mr-3 lg:mr-2"
|
|
186
|
-
alt={{@model.driver_assigned.name}}
|
|
187
|
-
/>
|
|
156
|
+
<Image src={{avatar-url @model.driver_assigned.photo_url}} @fallbackSrc={{config "defaultValues.driverImage"}} width="32" height="32" class="w-8 h-8 rounded-md shadow-sm mr-3 lg:mr-2" alt={{@model.driver_assigned.name}} />
|
|
188
157
|
</div>
|
|
189
158
|
<div class="field-value">
|
|
190
159
|
<div>{{n-a @model.driver_assigned.name "No Driver"}}</div>
|
|
@@ -194,13 +163,7 @@
|
|
|
194
163
|
</div>
|
|
195
164
|
</a>
|
|
196
165
|
<div class="mt-1">
|
|
197
|
-
<Button
|
|
198
|
-
@size="xs"
|
|
199
|
-
@type="default"
|
|
200
|
-
@icon="edit"
|
|
201
|
-
@text={{if @model.has_driver_assigned (t "fleet-ops.operations.orders.index.view.change-driver") (t "fleet-ops.operations.orders.index.view.assign-driver")}}
|
|
202
|
-
@onClick={{fn this.assignDriver @model}}
|
|
203
|
-
/>
|
|
166
|
+
<Button @size="xs" @type="default" @icon="edit" @text={{if @model.has_driver_assigned (t "fleet-ops.operations.orders.index.view.change-driver") (t "fleet-ops.operations.orders.index.view.assign-driver")}} @onClick={{fn this.assignDriver @model}} />
|
|
204
167
|
</div>
|
|
205
168
|
</div>
|
|
206
169
|
</div>
|
|
@@ -239,25 +202,56 @@
|
|
|
239
202
|
</div>
|
|
240
203
|
</ContentPanel>
|
|
241
204
|
|
|
205
|
+
{{#if @model.purchase_rate}}
|
|
206
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.purchase-rate-panel-title"}} @open={{true}} @pad={{false}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
207
|
+
<div class="order-view-purchase-rate-table-wrapper next-table-wrapper h-auto table-fluid rounded-b-md">
|
|
208
|
+
<table id="order-view-purchase-rate-table" class="table table-fixed flex-1">
|
|
209
|
+
<thead>
|
|
210
|
+
<tr>
|
|
211
|
+
<th class="text-left">{{t "fleet-ops.operations.orders.index.new.breakdown"}}</th>
|
|
212
|
+
<th>
|
|
213
|
+
<div class="flex flex-row items-center justify-end">{{@model.purchase_rate.service_quote.currency}}</div>
|
|
214
|
+
</th>
|
|
215
|
+
</tr>
|
|
216
|
+
</thead>
|
|
217
|
+
<tbody>
|
|
218
|
+
{{#each @model.purchase_rate.service_quote.items as |item|}}
|
|
219
|
+
<tr>
|
|
220
|
+
<td>
|
|
221
|
+
<span class="font-semibold">{{smart-humanize item.details}}</span>
|
|
222
|
+
</td>
|
|
223
|
+
<td>
|
|
224
|
+
<div class="flex flex-row items-center justify-end">{{format-currency item.amount @model.purchase_rate.service_quote.currency}}</div>
|
|
225
|
+
</td>
|
|
226
|
+
</tr>
|
|
227
|
+
{{/each}}
|
|
228
|
+
<tr class="border-b-0">
|
|
229
|
+
<td class="border-b-0">
|
|
230
|
+
<span class="font-semibold">{{t "fleet-ops.common.total"}}</span>
|
|
231
|
+
</td>
|
|
232
|
+
<td class="border-b-0">
|
|
233
|
+
<div class="flex flex-row items-center justify-end">{{format-currency @model.purchase_rate.service_quote.amount @model.purchase_rate.service_quote.currency}}</div>
|
|
234
|
+
</td>
|
|
235
|
+
</tr>
|
|
236
|
+
</tbody>
|
|
237
|
+
</table>
|
|
238
|
+
</div>
|
|
239
|
+
</ContentPanel>
|
|
240
|
+
{{/if}}
|
|
241
|
+
|
|
242
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.notes-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
243
|
+
<p class="text-gray-700 dark:text-gray-300 leading-5 text-sm">{{n-a @model.notes}}</p>
|
|
244
|
+
</ContentPanel>
|
|
245
|
+
|
|
242
246
|
{{#if @model.isIntegratedVendorOrder}}
|
|
243
|
-
<ContentPanel
|
|
244
|
-
@title={{concat @model.facilitator.name (t "fleet-ops.operations.orders.index.view.order-details-title")}}
|
|
245
|
-
@open={{true}}
|
|
246
|
-
@pad={{true}}
|
|
247
|
-
@panelBodyClass="bg-white dark:bg-gray-800"
|
|
248
|
-
>
|
|
247
|
+
<ContentPanel @title={{concat @model.facilitator.name (t "fleet-ops.operations.orders.index.view.order-details-title")}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
249
248
|
<IntegratedOrderDetails @integratedVendor={{@model.facilitator}} @details={{@model.meta.integrated_vendor_order}} />
|
|
250
249
|
</ContentPanel>
|
|
251
250
|
{{/if}}
|
|
252
251
|
|
|
253
252
|
{{#if @model.order_config}}
|
|
254
253
|
{{#each @model.groupedMetaFields as |group|}}
|
|
255
|
-
<ContentPanel
|
|
256
|
-
@title={{if group.value (humanize group.value) (t "fleet-ops.operations.orders.index.view.additional-details-title")}}
|
|
257
|
-
@open={{true}}
|
|
258
|
-
@pad={{true}}
|
|
259
|
-
@panelBodyClass="bg-white dark:bg-gray-800"
|
|
260
|
-
>
|
|
254
|
+
<ContentPanel @title={{if group.value (humanize group.value) (t "fleet-ops.operations.orders.index.view.additional-details-title")}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
261
255
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 lg:gap-2">
|
|
262
256
|
{{#each group.items as |metaField|}}
|
|
263
257
|
<div class="field-info-container space-y-2">
|
|
@@ -273,14 +267,7 @@
|
|
|
273
267
|
{{/if}}
|
|
274
268
|
|
|
275
269
|
{{#if @model.tracking_number}}
|
|
276
|
-
<ContentPanel
|
|
277
|
-
@title={{t "fleet-ops.operations.orders.index.view.tracking"}}
|
|
278
|
-
@prefixTitleRight={{@model.tracking}}
|
|
279
|
-
@isLoading={{not this.loadOrderRelations.isIdle}}
|
|
280
|
-
@open={{true}}
|
|
281
|
-
@pad={{true}}
|
|
282
|
-
@panelBodyClass="bg-white dark:bg-gray-800"
|
|
283
|
-
>
|
|
270
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.tracking"}} @prefixTitleRight={{@model.tracking}} @isLoading={{not this.loadOrderRelations.isIdle}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
284
271
|
<div class="mb-4 flex justify-end">
|
|
285
272
|
<Button @size="xs" @type="default" @icon="barcode" @text="Get Order Label" @onClick={{fn this.viewOrderLabel @model}} />
|
|
286
273
|
</div>
|
|
@@ -295,7 +282,7 @@
|
|
|
295
282
|
</ContentPanel>
|
|
296
283
|
{{/if}}
|
|
297
284
|
|
|
298
|
-
<ContentPanel @title="
|
|
285
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.route-panel-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @actionButtons={{this.routePanelButtons}}>
|
|
299
286
|
{{#if @model.payload.isMultiDrop}}
|
|
300
287
|
<div>
|
|
301
288
|
<RouteList @order={{@model}} />
|
|
@@ -319,14 +306,7 @@
|
|
|
319
306
|
</ContentPanel>
|
|
320
307
|
|
|
321
308
|
{{#if @model.isStorefrontOrder}}
|
|
322
|
-
<ContentPanel
|
|
323
|
-
@title={{t "fleet-ops.operations.orders.index.view.order-summary"}}
|
|
324
|
-
@prefixTitleRight={{if @model.payload.cod_amount "Cash" ""}}
|
|
325
|
-
@prefixTitleRightClass="text-green-400"
|
|
326
|
-
@open={{true}}
|
|
327
|
-
@pad={{true}}
|
|
328
|
-
@panelBodyClass="bg-white dark:bg-gray-800"
|
|
329
|
-
>
|
|
309
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.order-summary"}} @prefixTitleRight={{if @model.payload.cod_amount "Cash" ""}} @prefixTitleRightClass="text-green-400" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
330
310
|
<div class="flex flex-col space-y-4 p-2 overflow-hidden">
|
|
331
311
|
{{#each @model.payload.entities as |entity|}}
|
|
332
312
|
<div class="flex flex-1">
|
|
@@ -399,7 +379,7 @@
|
|
|
399
379
|
</ContentPanel>
|
|
400
380
|
{{/if}}
|
|
401
381
|
|
|
402
|
-
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.payload"}} @open={{
|
|
382
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.payload"}} @open={{gt @model.payload.entities.length 0}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
403
383
|
{{#if this.isMultiDropOrder}}
|
|
404
384
|
<div class="space-y-2">
|
|
405
385
|
{{#each this.entitiesByDestination as |group|}}
|
|
@@ -419,15 +399,7 @@
|
|
|
419
399
|
<Badge @status={{group.waypoint.status_code}} />
|
|
420
400
|
</div>
|
|
421
401
|
<div class="flex items-start">
|
|
422
|
-
<DropdownButton
|
|
423
|
-
@triggerClass="mr-2"
|
|
424
|
-
@iconClass="icon-text-height"
|
|
425
|
-
@buttonSize="sm"
|
|
426
|
-
@icon="ellipsis-h"
|
|
427
|
-
@iconPrefix="fas"
|
|
428
|
-
@contentClass="dropdown-menu"
|
|
429
|
-
as |dd|
|
|
430
|
-
>
|
|
402
|
+
<DropdownButton @triggerClass="mr-2" @iconClass="icon-text-height" @buttonSize="sm" @icon="ellipsis-h" @iconPrefix="fas" @contentClass="dropdown-menu" as |dd|>
|
|
431
403
|
<div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
|
|
432
404
|
<div class="px-1">
|
|
433
405
|
<div class="text-sm flex flex-row items-center px-3 py-1 rounded-md my-1 text-gray-300">
|
|
@@ -445,13 +417,7 @@
|
|
|
445
417
|
</div>
|
|
446
418
|
</div>
|
|
447
419
|
</DropdownButton>
|
|
448
|
-
<Button
|
|
449
|
-
@icon="plus"
|
|
450
|
-
@iconPrefix="fas"
|
|
451
|
-
@text={{t "fleet-ops.operations.orders.index.view.add-item-button"}}
|
|
452
|
-
@size="sm"
|
|
453
|
-
@onClick={{fn this.addEntity group.waypoint}}
|
|
454
|
-
/>
|
|
420
|
+
<Button @icon="plus" @iconPrefix="fas" @text={{t "fleet-ops.operations.orders.index.view.add-item-button"}} @size="sm" @onClick={{fn this.addEntity group.waypoint}} />
|
|
455
421
|
</div>
|
|
456
422
|
</div>
|
|
457
423
|
</div>
|
|
@@ -469,12 +435,7 @@
|
|
|
469
435
|
<div class="dark:text-gray-100 truncate mb-2">
|
|
470
436
|
{{entity.tracking}}
|
|
471
437
|
</div>
|
|
472
|
-
<Button
|
|
473
|
-
@icon="pencil"
|
|
474
|
-
@text={{t "fleet-ops.operations.orders.index.view.edit-item-button"}}
|
|
475
|
-
@size="xs"
|
|
476
|
-
@onClick={{fn this.editEntity entity}}
|
|
477
|
-
/>
|
|
438
|
+
<Button @icon="pencil" @text={{t "fleet-ops.operations.orders.index.view.edit-item-button"}} @size="xs" @onClick={{fn this.editEntity entity}} />
|
|
478
439
|
</div>
|
|
479
440
|
<div class="absolute top-0 right-0 p-2">
|
|
480
441
|
<Button @icon="times" @iconPrefix="fas" @type="danger" @size="xs" @onClick={{fn this.removeEntity entity}} />
|
|
@@ -504,14 +465,7 @@
|
|
|
504
465
|
<Button @icon="pencil" @text={{t "fleet-ops.operations.orders.index.view.edit-item-button"}} @size="sm" @onClick={{fn this.editEntity entity}} />
|
|
505
466
|
</div>
|
|
506
467
|
<div class="absolute top-0 right-0 p-2">
|
|
507
|
-
<Button
|
|
508
|
-
@icon="times"
|
|
509
|
-
@iconPrefix="fas"
|
|
510
|
-
@type="danger"
|
|
511
|
-
@size="xs"
|
|
512
|
-
@onClick={{fn this.removeEntity entity}}
|
|
513
|
-
@wrapperClass={{if (eq index 0) "invisible"}}
|
|
514
|
-
/>
|
|
468
|
+
<Button @icon="times" @iconPrefix="fas" @type="danger" @size="xs" @onClick={{fn this.removeEntity entity}} @wrapperClass={{if (eq index 0) "invisible"}} />
|
|
515
469
|
</div>
|
|
516
470
|
</div>
|
|
517
471
|
</div>
|
|
@@ -519,5 +473,81 @@
|
|
|
519
473
|
</div>
|
|
520
474
|
{{/if}}
|
|
521
475
|
</ContentPanel>
|
|
476
|
+
|
|
477
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.documents-panel-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
|
|
478
|
+
<div class="space-y-4">
|
|
479
|
+
{{#if this.isUploading}}
|
|
480
|
+
<div
|
|
481
|
+
class="dropzone w-full rounded-lg px-4 py-8 bg-gray-50 dark:bg-gray-900 bg-opacity-25 text-gray-900 dark:text-white text-center flex flex-col items-center justify-center border-2 border-dashed border-gray-200 dark:border-indigo-500"
|
|
482
|
+
>
|
|
483
|
+
<div class="flex items-center justify-center py-5">
|
|
484
|
+
<Spinner class="text-sm dar:text-gray-100" @loadingMessage={{t "fleet-ops.common.uploading"}} />
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
{{else}}
|
|
488
|
+
{{#let (file-queue name="files" onFileAdded=this.queueFile accept=(join "," this.acceptedFileTypes)) as |queue|}}
|
|
489
|
+
<FileDropzone @queue={{queue}} class="dropzone file-dropzone" as |dropzone|>
|
|
490
|
+
{{#if dropzone.active}}
|
|
491
|
+
{{#if dropzone.valid}}
|
|
492
|
+
{{t "component.dropzone.drop-to-upload"}}
|
|
493
|
+
{{else}}
|
|
494
|
+
{{t "component.dropzone.invalid"}}
|
|
495
|
+
{{/if}}
|
|
496
|
+
{{else if queue.files.length}}
|
|
497
|
+
<div class="my-2">
|
|
498
|
+
<FaIcon @icon="folder-open" class="text-indigo-500 mr-2" />
|
|
499
|
+
{{t "component.dropzone.files-ready-for-upload" numOfFiles=(pluralize queue.files.length (t "component.dropzone.file"))}}
|
|
500
|
+
</div>
|
|
501
|
+
<div class="my-2">({{queue.progress}}%)</div>
|
|
502
|
+
{{else}}
|
|
503
|
+
<h4 class="font-semibold">
|
|
504
|
+
<FaIcon @icon="folder-open" @size="lg" class="text-indigo-500 mr-2" />
|
|
505
|
+
{{t "component.dropzone.upload-documents-files"}}
|
|
506
|
+
</h4>
|
|
507
|
+
<div>
|
|
508
|
+
{{#if dropzone.supported}}
|
|
509
|
+
<p class="text-sm my-5">{{t "component.dropzone.dropzone-supported-files"}}</p>
|
|
510
|
+
{{/if}}
|
|
511
|
+
<FileUpload @name="files" @for="files" @accept={{join "," this.acceptedFileTypes}} @multiple={{true}} @onFileAdded={{this.queueFile}}>
|
|
512
|
+
<a tabindex={{0}} class="btn btn-magic cursor-pointer ml-1">{{t "component.dropzone.or-select-button-text"}}</a>
|
|
513
|
+
</FileUpload>
|
|
514
|
+
</div>
|
|
515
|
+
{{/if}}
|
|
516
|
+
</FileDropzone>
|
|
517
|
+
{{/let}}
|
|
518
|
+
{{#if this.uploadQueue}}
|
|
519
|
+
<div class="mx-4">
|
|
520
|
+
<div class="flex items-center justify-between mb-4">
|
|
521
|
+
<span class="leading-6 dark:text-gray-100">{{t "component.dropzone.upload-queue"}}</span>
|
|
522
|
+
</div>
|
|
523
|
+
<div class="space-y-2 mb-4">
|
|
524
|
+
{{#each this.uploadQueue as |file|}}
|
|
525
|
+
<div class="flex items-center justify-between bg-blue-100 border border-blue-800 dark:border-blue-800 py-1.5 shadow-sm rounded-lg px-4">
|
|
526
|
+
<div class="text-xs text-blue-900 truncate">{{truncate-filename file.name 50}}</div>
|
|
527
|
+
<div class="flex items-center text-sm">
|
|
528
|
+
<Spinner class="text-blue-900 mr-2" />
|
|
529
|
+
<span class="font-bold text-blue-900">{{round file.progress}}%</span>
|
|
530
|
+
</div>
|
|
531
|
+
</div>
|
|
532
|
+
{{/each}}
|
|
533
|
+
</div>
|
|
534
|
+
</div>
|
|
535
|
+
{{/if}}
|
|
536
|
+
<div>
|
|
537
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-2 md:gap-4">
|
|
538
|
+
{{#each @model.files as |file|}}
|
|
539
|
+
<File @file={{file}} @onDelete={{this.removeFile}} />
|
|
540
|
+
{{/each}}
|
|
541
|
+
</div>
|
|
542
|
+
</div>
|
|
543
|
+
{{/if}}
|
|
544
|
+
</div>
|
|
545
|
+
</ContentPanel>
|
|
546
|
+
|
|
547
|
+
<ContentPanel @title={{t "fleet-ops.operations.orders.index.view.comments-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @wrapperClass="mb-20">
|
|
548
|
+
<CommentThread @subject={{@model}} @subjectType="fleet-ops:order" />
|
|
549
|
+
</ContentPanel>
|
|
550
|
+
|
|
551
|
+
<Spacer @height="300px" />
|
|
522
552
|
</Overlay::Body>
|
|
523
553
|
</Overlay>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
{{/if}}
|
|
8
8
|
</Overlay::Header>
|
|
9
9
|
|
|
10
|
-
<Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4"
|
|
10
|
+
<Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4">
|
|
11
11
|
<div>
|
|
12
12
|
<div class="grid grid-cols-2 gap-2">
|
|
13
13
|
<div class="input-group">
|
|
@@ -302,5 +302,7 @@
|
|
|
302
302
|
</div>
|
|
303
303
|
{{/if}}
|
|
304
304
|
</ContentPanel>
|
|
305
|
+
|
|
306
|
+
<Spacer @height="300px" />
|
|
305
307
|
</Overlay::Body>
|
|
306
308
|
</Overlay>
|
package/composer.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fleetbase/fleetops-api",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fleetbase-extension",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"require": {
|
|
24
24
|
"php": "^7.4|^8.0",
|
|
25
|
-
"fleetbase/core-api": "^1.3.
|
|
25
|
+
"fleetbase/core-api": "^1.3.13",
|
|
26
26
|
"barryvdh/laravel-dompdf": "^2.0",
|
|
27
27
|
"brick/geo": "0.7.2",
|
|
28
28
|
"cknow/laravel-money": "^7.1",
|
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetbase/fleetops-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@babel/core": "^7.23.2",
|
|
46
46
|
"@fleetbase/ember-core": "^0.2.1",
|
|
47
|
-
"@fleetbase/ember-ui": "^0.2.
|
|
48
|
-
"@fleetbase/fleetops-data": "^0.1.
|
|
47
|
+
"@fleetbase/ember-ui": "^0.2.10",
|
|
48
|
+
"@fleetbase/fleetops-data": "^0.1.8",
|
|
49
49
|
"@fleetbase/leaflet-routing-machine": "^3.2.16",
|
|
50
50
|
"@fortawesome/ember-fontawesome": "^0.4.1",
|
|
51
51
|
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
|
@@ -376,7 +376,7 @@ class DriverController extends Controller
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
// Get the user's company for this driver profile
|
|
379
|
-
$company =
|
|
379
|
+
$company = static::getDriverCompanyFromUser($user);
|
|
380
380
|
|
|
381
381
|
// Get driver record
|
|
382
382
|
$driver = Driver::where(
|
|
@@ -414,7 +414,7 @@ class DriverController extends Controller
|
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
// Get the user's company for this driver profile
|
|
417
|
-
$company =
|
|
417
|
+
$company = static::getDriverCompanyFromUser($user);
|
|
418
418
|
|
|
419
419
|
// generate verification token
|
|
420
420
|
try {
|
|
@@ -464,7 +464,7 @@ class DriverController extends Controller
|
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
// Get the user's company for this driver profile
|
|
467
|
-
$company =
|
|
467
|
+
$company = static::getDriverCompanyFromUser($user);
|
|
468
468
|
|
|
469
469
|
// get driver record
|
|
470
470
|
$driver = Driver::where(
|
|
@@ -488,19 +488,33 @@ class DriverController extends Controller
|
|
|
488
488
|
}
|
|
489
489
|
|
|
490
490
|
/**
|
|
491
|
-
*
|
|
491
|
+
* Gets the current organization/company for the driver
|
|
492
|
+
*
|
|
493
|
+
* @param string $id
|
|
494
|
+
* @param \Illuminate\Http\Request $request
|
|
495
|
+
* @return \Fleetbase\Http\Resources\Organization
|
|
492
496
|
*/
|
|
493
|
-
public
|
|
497
|
+
public function currentOrganization(string $id, Request $request)
|
|
494
498
|
{
|
|
495
|
-
|
|
496
|
-
$
|
|
499
|
+
try {
|
|
500
|
+
$driver = Driver::findRecordOrFail($id);
|
|
501
|
+
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
|
|
502
|
+
return response()->apiError('Driver resource not found.', 404);
|
|
497
503
|
}
|
|
498
504
|
|
|
499
|
-
|
|
500
|
-
|
|
505
|
+
// Get the driver user account
|
|
506
|
+
$user = $driver->getUser();
|
|
507
|
+
if (!$user) {
|
|
508
|
+
return response()->apiError('Driver has not user account.');
|
|
501
509
|
}
|
|
502
510
|
|
|
503
|
-
|
|
511
|
+
// Get the user account company
|
|
512
|
+
$company = Flow::getCompanySessionForUser($user);
|
|
513
|
+
if (!$company) {
|
|
514
|
+
return response()->apiError('No company found for this driver.');
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return new Organization($company);
|
|
504
518
|
}
|
|
505
519
|
|
|
506
520
|
/**
|
|
@@ -548,23 +562,26 @@ class DriverController extends Controller
|
|
|
548
562
|
);
|
|
549
563
|
}
|
|
550
564
|
|
|
551
|
-
//
|
|
565
|
+
// Get the next organization
|
|
552
566
|
$company = Company::where('public_id', $nextOrganization)->first();
|
|
553
567
|
|
|
554
568
|
if ($company->uuid === $driver->user->company_uuid) {
|
|
555
|
-
return response()->
|
|
556
|
-
'error' => 'Driver is already on this organizations session',
|
|
557
|
-
]);
|
|
569
|
+
return response()->apiError('Driver is already on this organizations session.');
|
|
558
570
|
}
|
|
559
571
|
|
|
560
572
|
if (!CompanyUser::where(['user_uuid' => $driver->user_uuid, 'company_uuid' => $company->uuid])->exists()) {
|
|
561
|
-
return response()->
|
|
562
|
-
|
|
563
|
-
|
|
573
|
+
return response()->apiError('You do not belong to this organization');
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// Get the driver user account
|
|
577
|
+
$user = $driver->getUser();
|
|
578
|
+
if (!$user) {
|
|
579
|
+
return response()->apiError('Driver has not user account.');
|
|
564
580
|
}
|
|
565
581
|
|
|
566
|
-
|
|
567
|
-
|
|
582
|
+
// Assign user to company and update their session
|
|
583
|
+
$user->assignCompany($company);
|
|
584
|
+
Auth::setSession($user);
|
|
568
585
|
|
|
569
586
|
return new Organization($company);
|
|
570
587
|
}
|
|
@@ -700,7 +717,13 @@ class DriverController extends Controller
|
|
|
700
717
|
return response()->json($route);
|
|
701
718
|
}
|
|
702
719
|
|
|
703
|
-
|
|
720
|
+
/**
|
|
721
|
+
* Get the drivers current company using their user account.
|
|
722
|
+
*
|
|
723
|
+
* @param \Fleetbase\Models\User $user
|
|
724
|
+
* @return \Fleetbase\Models\Company|null
|
|
725
|
+
*/
|
|
726
|
+
private static function getDriverCompanyFromUser(User $user): ?Company
|
|
704
727
|
{
|
|
705
728
|
// company defaults to null
|
|
706
729
|
$company = null;
|
|
@@ -719,4 +742,20 @@ class DriverController extends Controller
|
|
|
719
742
|
|
|
720
743
|
return $company;
|
|
721
744
|
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Patches phone number with international code.
|
|
748
|
+
*/
|
|
749
|
+
private static function phone(string $phone = null): string
|
|
750
|
+
{
|
|
751
|
+
if ($phone === null) {
|
|
752
|
+
$phone = request()->input('phone');
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
if (!Str::startsWith($phone, '+')) {
|
|
756
|
+
$phone = '+' . $phone;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
return $phone;
|
|
760
|
+
}
|
|
722
761
|
}
|
|
@@ -422,6 +422,8 @@ class OrderController extends Controller
|
|
|
422
422
|
public function query(Request $request)
|
|
423
423
|
{
|
|
424
424
|
$results = Order::queryWithRequest($request, function (&$query, $request) {
|
|
425
|
+
$query->where('company_uuid', session('company'));
|
|
426
|
+
|
|
425
427
|
if ($request->has('payload')) {
|
|
426
428
|
$query->whereHas('payload', function ($q) use ($request) {
|
|
427
429
|
$q->where('public_id', $request->input('payload'));
|
|
@@ -94,8 +94,9 @@ class DriverController extends FleetOpsController
|
|
|
94
94
|
->filter()
|
|
95
95
|
->toArray();
|
|
96
96
|
|
|
97
|
-
//
|
|
98
|
-
$
|
|
97
|
+
// Get current session company
|
|
98
|
+
$company = Auth::getCompany();
|
|
99
|
+
$input['company_uuid'] = session('company', $company->uuid);
|
|
99
100
|
$input['user_uuid'] = $existingUser->uuid;
|
|
100
101
|
$input['slug'] = $existingUser->slug;
|
|
101
102
|
|
|
@@ -107,6 +108,18 @@ class DriverController extends FleetOpsController
|
|
|
107
108
|
// create the profile
|
|
108
109
|
$driverProfile = Driver::create($input);
|
|
109
110
|
|
|
111
|
+
// Assign user to company
|
|
112
|
+
if ($company) {
|
|
113
|
+
$existingUser->assignCompany($company);
|
|
114
|
+
|
|
115
|
+
// create company user
|
|
116
|
+
CompanyUser::create([
|
|
117
|
+
'user_uuid' => $existingUser->uuid,
|
|
118
|
+
'company_uuid' => $company->uuid,
|
|
119
|
+
'status' => $isOrganizationMember ? 'active' : 'pending'
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
|
|
110
123
|
if (!$isOrganizationMember) {
|
|
111
124
|
// send invitation to user
|
|
112
125
|
$invitation = Invite::create([
|
|
@@ -159,7 +172,7 @@ class DriverController extends FleetOpsController
|
|
|
159
172
|
|
|
160
173
|
// Get current session company
|
|
161
174
|
$company = Auth::getCompany();
|
|
162
|
-
$userInput['company_uuid'] =
|
|
175
|
+
$userInput['company_uuid'] = session('company', $company->uuid);
|
|
163
176
|
|
|
164
177
|
// Create user account
|
|
165
178
|
$user = User::create($userInput);
|
|
@@ -82,6 +82,7 @@ class OrderController extends FleetOpsController
|
|
|
82
82
|
$payload = Utils::get($input, 'payload');
|
|
83
83
|
$waypoints = Utils::get($input, 'payload.waypoints');
|
|
84
84
|
$entities = Utils::get($input, 'payload.entities');
|
|
85
|
+
$uploads = Utils::get($input, 'files', []);
|
|
85
86
|
|
|
86
87
|
// save order route & payload with request input
|
|
87
88
|
$order
|
|
@@ -91,6 +92,16 @@ class OrderController extends FleetOpsController
|
|
|
91
92
|
->insertWaypoints($waypoints)
|
|
92
93
|
->insertEntities($entities);
|
|
93
94
|
|
|
95
|
+
// If order creation includes files assosciate each to this order
|
|
96
|
+
if ($uploads) {
|
|
97
|
+
$ids = collect($uploads)->pluck('uuid');
|
|
98
|
+
$files = File::whereIn('uuid', $ids)->get();
|
|
99
|
+
|
|
100
|
+
foreach ($files as $file) {
|
|
101
|
+
$file->setKey($order);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
94
105
|
// if it's integrated vendor order apply to meta
|
|
95
106
|
if ($isIntegratedVendorOrder) {
|
|
96
107
|
$order->updateMeta(
|
|
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Http\Resources\v1;
|
|
|
4
4
|
|
|
5
5
|
use Fleetbase\FleetOps\Support\Utils;
|
|
6
6
|
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
7
|
+
use Fleetbase\Http\Resources\Comment;
|
|
7
8
|
use Fleetbase\Support\Http;
|
|
8
9
|
use Fleetbase\Support\Resolve;
|
|
9
10
|
|
|
@@ -43,6 +44,8 @@ class Order extends FleetbaseResource
|
|
|
43
44
|
'driver_assigned' => new Driver($this->driverAssigned()->without(['jobs', 'currentJob'])->first()),
|
|
44
45
|
'tracking_number' => new TrackingNumber($this->trackingNumber),
|
|
45
46
|
'tracking_statuses' => $this->whenLoaded('trackingStatuses', TrackingStatus::collection($this->trackingStatuses)),
|
|
47
|
+
'comments' => $this->when(Http::isInternalRequest(), Comment::collection($this->comments)),
|
|
48
|
+
'files' => $this->when(Http::isInternalRequest(), $this->files),
|
|
46
49
|
'purchase_rate' => new PurchaseRate($this->purchaseRate),
|
|
47
50
|
'notes' => $this->notes,
|
|
48
51
|
'type' => $this->type,
|