@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.
Files changed (137) hide show
  1. package/addon/components/admin/visibility-controls.js +1 -0
  2. package/addon/components/contact-form-panel.hbs +28 -6
  3. package/addon/components/driver-form-panel.hbs +10 -0
  4. package/addon/components/driver-form-panel.js +51 -0
  5. package/addon/components/driver-panel/details.hbs +1 -5
  6. package/addon/components/driver-panel.hbs +21 -3
  7. package/addon/components/fleet-form-panel.hbs +60 -6
  8. package/addon/components/fleet-panel/details.hbs +1 -1
  9. package/addon/components/fuel-report-form-panel.hbs +84 -8
  10. package/addon/components/fuel-report-form-panel.js +6 -0
  11. package/addon/components/fuel-report-panel/details.hbs +4 -0
  12. package/addon/components/issue-form-panel.hbs +99 -11
  13. package/addon/components/issue-form-panel.js +5 -13
  14. package/addon/components/layout/fleet-ops-sidebar.js +10 -1
  15. package/addon/components/live-map-drawer/driver-listing.hbs +6 -0
  16. package/addon/components/live-map-drawer/driver-listing.js +240 -0
  17. package/addon/components/live-map-drawer/place-listing.hbs +6 -0
  18. package/addon/components/live-map-drawer/place-listing.js +204 -0
  19. package/addon/components/live-map-drawer/vehicle-listing.hbs +6 -0
  20. package/addon/components/live-map-drawer/vehicle-listing.js +216 -0
  21. package/addon/components/live-map-drawer.hbs +17 -0
  22. package/addon/components/live-map-drawer.js +104 -0
  23. package/addon/components/live-map.hbs +5 -1
  24. package/addon/components/live-map.js +107 -15
  25. package/addon/components/map-container/toolbar.hbs +6 -0
  26. package/addon/components/modals/driver-assign-vehicle.hbs +2 -11
  27. package/addon/components/modals/driver-assign-vendor.hbs +1 -9
  28. package/addon/components/modals/fuel-report-details.hbs +4 -0
  29. package/addon/components/modals/order-event.hbs +1 -1
  30. package/addon/components/order/schedule-card.hbs +35 -7
  31. package/addon/components/order/schedule-card.js +163 -6
  32. package/addon/components/place-form-panel.hbs +14 -7
  33. package/addon/components/place-form-panel.js +71 -0
  34. package/addon/components/place-panel/details.hbs +11 -21
  35. package/addon/components/vehicle-form-panel.hbs +67 -7
  36. package/addon/components/vehicle-form-panel.js +37 -0
  37. package/addon/components/vehicle-panel/details.hbs +9 -5
  38. package/addon/components/vehicle-panel.hbs +18 -4
  39. package/addon/components/vendor-form-panel/create-form.hbs +72 -11
  40. package/addon/components/vendor-form-panel/edit-form.hbs +1 -1
  41. package/addon/components/vendor-form-panel.hbs +70 -30
  42. package/addon/components/vendor-form-panel.js +4 -40
  43. package/addon/components/vendor-panel/details.hbs +2 -2
  44. package/addon/components/vendor-panel.hbs +16 -2
  45. package/addon/controllers/management/contacts/index.js +42 -3
  46. package/addon/controllers/management/fleets/index.js +12 -23
  47. package/addon/controllers/management/fuel-reports/index/new.js +1 -1
  48. package/addon/controllers/management/fuel-reports/index.js +73 -20
  49. package/addon/controllers/management/issues/index/new.js +2 -2
  50. package/addon/controllers/management/issues/index.js +65 -45
  51. package/addon/controllers/management/places/index.js +59 -18
  52. package/addon/controllers/management/vehicles/index.js +67 -8
  53. package/addon/controllers/management/vendors/index.js +63 -8
  54. package/addon/controllers/operations/orders/index.js +70 -15
  55. package/addon/controllers/operations/scheduler/index.js +45 -30
  56. package/addon/routes/management/contacts/index.js +8 -0
  57. package/addon/routes/management/fleets/index.js +8 -2
  58. package/addon/routes/management/fuel-reports/index.js +6 -0
  59. package/addon/routes/management/issues/index.js +9 -1
  60. package/addon/routes/management/places/index.js +11 -1
  61. package/addon/routes/management/vehicles/index.js +3 -3
  62. package/addon/routes/management/vendors/index.js +8 -0
  63. package/addon/routes/operations/scheduler/index.js +26 -1
  64. package/addon/styles/fleetops-engine.css +28 -0
  65. package/addon/templates/operations/orders/index.hbs +2 -2
  66. package/addon/templates/operations/scheduler/index.hbs +33 -9
  67. package/addon/utils/create-full-calendar-event-from-order.js +8 -0
  68. package/addon/utils/get-issue-categories.js +30 -0
  69. package/addon/utils/get-issue-types.js +3 -0
  70. package/addon/utils/get-vendor-status-options.js +3 -0
  71. package/addon/utils/get-vendor-type-options.js +41 -0
  72. package/app/components/live-map-drawer/driver-listing.js +1 -0
  73. package/app/components/live-map-drawer/place-listing.js +1 -0
  74. package/app/components/live-map-drawer/vehicle-listing.js +1 -0
  75. package/app/components/live-map-drawer.js +1 -0
  76. package/app/utils/create-full-calendar-event-from-order.js +1 -0
  77. package/app/utils/get-issue-categories.js +1 -0
  78. package/app/utils/get-issue-types.js +1 -0
  79. package/app/utils/get-vendor-categories.js +1 -0
  80. package/app/utils/get-vendor-status-options.js +1 -0
  81. package/app/utils/get-vendor-type-options.js +1 -0
  82. package/app/utils/get-vendor-types.js +1 -0
  83. package/composer.json +1 -1
  84. package/extension.json +1 -1
  85. package/package.json +4 -4
  86. package/server/migrations/2023_11_09_041807_add_status_column_to_fuel_reports_table.php +32 -0
  87. package/server/migrations/2023_11_15_062814_add_comments_column_and_resolved_at_column_to_vehicle_device_events_table.php +33 -0
  88. package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -2
  89. package/server/src/Http/Controllers/Api/v1/VehicleController.php +2 -2
  90. package/server/src/Http/Controllers/Internal/v1/DriverController.php +5 -13
  91. package/server/src/Http/Controllers/Internal/v1/OrderController.php +1 -3
  92. package/server/src/Http/Filter/ContactFilter.php +10 -0
  93. package/server/src/Http/Filter/FleetFilter.php +8 -6
  94. package/server/src/Http/Filter/FuelReportFilter.php +51 -0
  95. package/server/src/Http/Filter/IssueFilter.php +61 -5
  96. package/server/src/Http/Filter/PlaceFilter.php +48 -6
  97. package/server/src/Http/Filter/VehicleFilter.php +21 -6
  98. package/server/src/Http/Filter/VendorFilter.php +11 -8
  99. package/server/src/Http/Middleware/TransformLocationMiddleware.php +1 -1
  100. package/server/src/Http/Resources/Internal/v1/IntegratedVendorFacilitator.php +17 -18
  101. package/server/src/Http/Resources/v1/Contact.php +16 -19
  102. package/server/src/Http/Resources/v1/CurrentJob.php +13 -16
  103. package/server/src/Http/Resources/v1/Driver.php +59 -57
  104. package/server/src/Http/Resources/v1/Entity.php +30 -33
  105. package/server/src/Http/Resources/v1/FuelReport.php +16 -14
  106. package/server/src/Http/Resources/v1/Order.php +1 -1
  107. package/server/src/Http/Resources/v1/Payload.php +21 -24
  108. package/server/src/Http/Resources/v1/Place.php +27 -30
  109. package/server/src/Http/Resources/v1/Proof.php +13 -16
  110. package/server/src/Http/Resources/v1/PurchaseRate.php +14 -17
  111. package/server/src/Http/Resources/v1/ServiceArea.php +13 -16
  112. package/server/src/Http/Resources/v1/ServiceQuote.php +15 -18
  113. package/server/src/Http/Resources/v1/ServiceRate.php +33 -36
  114. package/server/src/Http/Resources/v1/ServiceRateFee.php +14 -17
  115. package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +9 -12
  116. package/server/src/Http/Resources/v1/TrackingNumber.php +18 -21
  117. package/server/src/Http/Resources/v1/TrackingStatus.php +18 -21
  118. package/server/src/Http/Resources/v1/Vehicle.php +31 -34
  119. package/server/src/Http/Resources/v1/VehicleDevice.php +23 -25
  120. package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +38 -32
  121. package/server/src/Http/Resources/v1/Vendor.php +31 -26
  122. package/server/src/Http/Resources/v1/Zone.php +14 -17
  123. package/server/src/Models/Driver.php +7 -1
  124. package/server/src/Models/FuelReport.php +2 -1
  125. package/server/src/Models/IntegratedVendor.php +6 -1
  126. package/server/src/Models/Order.php +24 -2
  127. package/server/src/Models/Place.php +2 -2
  128. package/server/src/Models/VehicleDevice.php +1 -1
  129. package/server/src/Models/VehicleDeviceEvent.php +2 -1
  130. package/server/src/Models/Vendor.php +1 -1
  131. package/server/src/Observers/DriverObserver.php +15 -0
  132. package/server/src/Observers/FleetObserver.php +19 -0
  133. package/server/src/Providers/FleetOpsServiceProvider.php +1 -0
  134. package/addon/components/full-calendar/draggable.js +0 -1
  135. package/addon/components/full-calendar.js +0 -1
  136. package/app/components/full-calendar/draggable.js +0 -1
  137. package/app/components/full-calendar.js +0 -1
@@ -5,7 +5,7 @@ import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
6
  import { timeout } from 'ember-concurrency';
7
7
  import { task } from 'ember-concurrency-decorators';
8
-
8
+ import getVendorStatusOptions from '../../../utils/get-vendor-status-options';
9
9
  export default class ManagementVendorsIndexController extends Controller {
10
10
  /**
11
11
  * Inject the `management.places.index` controller
@@ -68,7 +68,7 @@ export default class ManagementVendorsIndexController extends Controller {
68
68
  *
69
69
  * @var {Array}
70
70
  */
71
- queryParams = ['page', 'limit', 'sort', 'query', 'public_id', 'internal_id', 'created_by', 'updated_by', 'status'];
71
+ queryParams = ['page', 'limit', 'sort', 'query', 'public_id', 'internal_id', 'created_by', 'updated_by', 'status', 'name', 'email', 'phone', 'type', 'country', 'address', 'website_url'];
72
72
 
73
73
  /**
74
74
  * The current page of data being viewed
@@ -112,6 +112,48 @@ export default class ManagementVendorsIndexController extends Controller {
112
112
  */
113
113
  @tracked status;
114
114
 
115
+ /**
116
+ * The filterable param `type`
117
+ *
118
+ * @var {Array|String}
119
+ */
120
+ @tracked type;
121
+
122
+ /**
123
+ * The filterable param `name`
124
+ *
125
+ * @var {String}
126
+ */
127
+ @tracked name;
128
+
129
+ /**
130
+ * The filterable param `website_url`
131
+ *
132
+ * @var {String}
133
+ */
134
+ @tracked website_url;
135
+
136
+ /**
137
+ * The filterable param `phone`
138
+ *
139
+ * @var {String}
140
+ */
141
+ @tracked phone;
142
+
143
+ /**
144
+ * The filterable param `email`
145
+ *
146
+ * @var {String}
147
+ */
148
+ @tracked email;
149
+
150
+ /**
151
+ * The filterable param `country`
152
+ *
153
+ * @var {String}
154
+ */
155
+ @tracked country;
156
+
115
157
  /**
116
158
  * Rows for the table
117
159
  *
@@ -168,6 +210,17 @@ export default class ManagementVendorsIndexController extends Controller {
168
210
  filterable: true,
169
211
  filterComponent: 'filter/string',
170
212
  },
213
+ {
214
+ label: 'Website URL',
215
+ valuePath: 'website_url',
216
+ cellComponent: 'click-to-copy',
217
+ width: '80px',
218
+ resizable: true,
219
+ sortable: true,
220
+ hidden: true,
221
+ filterable: true,
222
+ filterComponent: 'filter/string',
223
+ },
171
224
  {
172
225
  label: 'Phone',
173
226
  valuePath: 'phone',
@@ -194,11 +247,13 @@ export default class ManagementVendorsIndexController extends Controller {
194
247
  {
195
248
  label: 'Type',
196
249
  valuePath: 'type',
197
- cellComponent: 'table/cell/status',
198
- width: '120px',
250
+ cellComponent: 'table/cell/anchor',
251
+ action: this.viewVendorPlace,
252
+ width: '150px',
199
253
  resizable: true,
200
254
  sortable: true,
201
255
  filterable: true,
256
+ filterParam: 'type',
202
257
  filterComponent: 'filter/string',
203
258
  },
204
259
  {
@@ -206,12 +261,12 @@ export default class ManagementVendorsIndexController extends Controller {
206
261
  valuePath: 'country',
207
262
  cellComponent: 'table/cell/base',
208
263
  cellClassNames: 'uppercase',
209
- width: '130px',
264
+ width: '120px',
210
265
  resizable: true,
211
266
  sortable: true,
212
- hidden: true,
213
267
  filterable: true,
214
- filterComponent: 'filter/string',
268
+ filterComponent: 'filter/country',
269
+ filterParam: 'country',
215
270
  },
216
271
  {
217
272
  label: 'Created At',
@@ -243,7 +298,7 @@ export default class ManagementVendorsIndexController extends Controller {
243
298
  sortable: true,
244
299
  filterable: true,
245
300
  filterComponent: 'filter/multi-option',
246
- filterOptions: this.statusOptions,
301
+ filterOptions: getVendorStatusOptions(),
247
302
  },
248
303
  {
249
304
  label: '',
@@ -1,4 +1,4 @@
1
- import Controller, { inject as controller } from '@ember/controller';
1
+ import Controller from '@ember/controller';
2
2
  import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
@@ -9,20 +9,6 @@ import { timeout } from 'ember-concurrency';
9
9
  import { task } from 'ember-concurrency-decorators';
10
10
 
11
11
  export default class OperationsOrdersIndexController extends Controller {
12
- /**
13
- * Injection of the `ManagementDriversIndexController` controller
14
- *
15
- * @memberof OperationsOrdersIndexController
16
- */
17
- @controller('management.drivers.index') driversController;
18
-
19
- /**
20
- * Injection of the `ManagementFleetIndexController` controller
21
- *
22
- * @memberof OperationsOrdersIndexController
23
- */
24
- @controller('management.fleets.index') fleetController;
25
-
26
12
  /**
27
13
  * Inject the `currentUser` service
28
14
  *
@@ -110,6 +96,8 @@ export default class OperationsOrdersIndexController extends Controller {
110
96
  'status',
111
97
  'type',
112
98
  'layout',
99
+ 'drawerOpen',
100
+ 'drawerTab',
113
101
  ];
114
102
 
115
103
  /**
@@ -266,6 +254,13 @@ export default class OperationsOrdersIndexController extends Controller {
266
254
  */
267
255
  @tracked leafletMap;
268
256
 
257
+ /**
258
+ * Reference to the drawer context API.
259
+ *
260
+ * @type {Object}
261
+ */
262
+ @tracked drawer;
263
+
269
264
  /**
270
265
  * Current layout type (e.g., 'map', 'table', 'kanban', 'analytics')
271
266
  *
@@ -273,6 +268,20 @@ export default class OperationsOrdersIndexController extends Controller {
273
268
  */
274
269
  @tracked layout = 'map';
275
270
 
271
+ /**
272
+ * Decides if scope drawer is open.
273
+ *
274
+ * @type {Boolean}
275
+ */
276
+ @tracked drawerOpen = 0;
277
+
278
+ /**
279
+ * The drawer tab that is active.
280
+ *
281
+ * @type {Boolean}
282
+ */
283
+ @tracked drawerTab;
284
+
276
285
  /**
277
286
  * Flag to determine if the layout is 'map'
278
287
  *
@@ -722,6 +731,52 @@ export default class OperationsOrdersIndexController extends Controller {
722
731
  this.liveMap = liveMap;
723
732
  }
724
733
 
734
+ /**
735
+ * Sets the drawer component context api.
736
+ *
737
+ * @param {Object} drawerApi
738
+ * @memberof OperationsOrdersIndexController
739
+ */
740
+ @action setDrawerContext(drawerApi) {
741
+ this.drawer = drawerApi;
742
+ }
743
+
744
+ /**
745
+ * Toggles the LiveMap drawer component.
746
+ *
747
+ * @memberof OperationsOrdersIndexController
748
+ */
749
+ @action onPressLiveMapDrawerToggle() {
750
+ if (this.drawer) {
751
+ this.drawer.toggleMinimize({
752
+ onToggle: (drawerApi) => {
753
+ this.drawerOpen = drawerApi.isMinimized ? 0 : 1;
754
+ },
755
+ });
756
+ }
757
+ }
758
+
759
+ /**
760
+ * Handles the resize end event for the `<LiveMapDrawer />` component.
761
+ *
762
+ * @params {Object} event
763
+ * @params {Object.drawerPanelNode|HTMLElement}
764
+ * @memberof OperationsOrdersIndexController
765
+ */
766
+ @action onDrawerResizeEnd({ drawerPanelNode }) {
767
+ const rect = drawerPanelNode.getBoundingClientRect();
768
+
769
+ if (rect.height === 0) {
770
+ this.drawerOpen = 0;
771
+ } else if (rect.height > 1) {
772
+ this.drawerOpen = 1;
773
+ }
774
+ }
775
+
776
+ @action onDrawerTabChanged(tabName) {
777
+ this.drawerTab = tabName;
778
+ }
779
+
725
780
  /**
726
781
  * Exports all orders.
727
782
  * @action
@@ -1,31 +1,26 @@
1
1
  import Controller from '@ember/controller';
2
+ import { tracked } from '@glimmer/tracking';
2
3
  import { inject as service } from '@ember/service';
3
- import { computed, action } from '@ember/object';
4
+ import { action } from '@ember/object';
4
5
  import { format, isValid as isValidDate } from 'date-fns';
6
+ import createFullCalendarEventFromOrder from '../../../utils/create-full-calendar-event-from-order';
5
7
 
6
8
  export default class OperationsSchedulerIndexController extends Controller {
7
9
  @service modalsManager;
8
10
  @service notifications;
9
-
10
- @computed('model.@each.scheduled_at') get scheduledOrders() {
11
- return this.model.filter((order) => isValidDate(order.scheduled_at));
12
- }
13
-
14
- @computed('model.@each.scheduled_at') get unscheduledOrders() {
15
- return this.model.filter((order) => !order.scheduled_at);
16
- }
17
-
18
- @computed('scheduledOrders.@each.scheduled_at') get events() {
19
- return this.scheduledOrders.map((order) => ({
20
- id: order.id,
21
- title: `${order.scheduledAtTime} - ${order.public_id}`,
22
- start: order.scheduled_at,
23
- allDay: true,
24
- }));
11
+ @service store;
12
+ @service hostRouter;
13
+ @tracked scheduledOrders = [];
14
+ @tracked unscheduledOrders = [];
15
+ @tracked events = [];
16
+
17
+ @action setCalendarApi(calendar) {
18
+ this.calendar = calendar;
25
19
  }
26
20
 
27
- @action viewEvent(order, eventClickInfo) {
28
- const { event } = eventClickInfo;
21
+ @action viewEvent(order) {
22
+ // get the event from the calendar
23
+ let event = this.calendar.getEventById(order.id);
29
24
 
30
25
  this.modalsManager.show('modals/order-event', {
31
26
  title: `Scheduling for ${order.public_id}`,
@@ -34,7 +29,7 @@ export default class OperationsSchedulerIndexController extends Controller {
34
29
  hideDeclineButton: true,
35
30
  order,
36
31
  reschedule: (date) => {
37
- if (typeof date?.toDate === 'function') {
32
+ if (date && typeof date.toDate === 'function') {
38
33
  date = date.toDate();
39
34
  }
40
35
 
@@ -51,15 +46,27 @@ export default class OperationsSchedulerIndexController extends Controller {
51
46
  }
52
47
 
53
48
  return order.save().then((order) => {
54
- this.notifications.success(`'${order.public_id}' has been updated.`);
49
+ // remove event from calendar
50
+ if (event) {
51
+ event.remove();
52
+ }
55
53
 
56
- // update event props
57
- event?.setProp('title', order.eventTitle);
54
+ if (order.scheduled_at) {
55
+ // notify order has been scheduled
56
+ this.notifications.success(`Order '${order.public_id}' has been scheduled at ${order.scheduledAt}.`);
57
+ // add event to calendar
58
+ event = this.calendar.addEvent(createFullCalendarEventFromOrder(order));
59
+ } else {
60
+ this.notifications.info(`Order '${order.public_id}' has been unscheduled.`);
61
+ }
58
62
 
59
- // remove event from calendar if unscheduled
60
- if (!order.scheduled_at || !isValidDate(order.scheduled_at)) {
61
- event.remove();
63
+ // update event props
64
+ if (event && typeof event.setProp === 'function') {
65
+ event.setProp('title', order.eventTitle);
62
66
  }
67
+
68
+ // refresh route
69
+ this.hostRouter.refresh();
63
70
  });
64
71
  },
65
72
  });
@@ -80,7 +87,9 @@ export default class OperationsSchedulerIndexController extends Controller {
80
87
  const order = this.store.peekRecord('order', data.id);
81
88
 
82
89
  order.set('scheduled_at', date);
83
- order.save();
90
+ return order.save().then(() => {
91
+ this.hostRouter.refresh();
92
+ });
84
93
  }
85
94
 
86
95
  @action receivedEvent(eventReceivedInfo) {
@@ -88,7 +97,9 @@ export default class OperationsSchedulerIndexController extends Controller {
88
97
  const order = this.store.peekRecord('order', event.id);
89
98
 
90
99
  // update event props
91
- event?.setProp('title', order.eventTitle);
100
+ if (typeof event.setProp === 'function') {
101
+ event.setProp('title', order.eventTitle);
102
+ }
92
103
  }
93
104
 
94
105
  @action rescheduleEventFromDrag(eventDropInfo) {
@@ -102,9 +113,13 @@ export default class OperationsSchedulerIndexController extends Controller {
102
113
 
103
114
  // set and save order props
104
115
  order.set('scheduled_at', isValidDate(newDate) ? newDate : start);
105
- order.save();
116
+ order.save().then(() => {
117
+ this.hostRouter.refresh();
118
+ });
106
119
 
107
120
  // update event props
108
- event?.setProp('title', order.eventTitle);
121
+ if (typeof event.setProp === 'function') {
122
+ event.setProp('title', order.eventTitle);
123
+ }
109
124
  }
110
125
  }
@@ -15,6 +15,14 @@ export default class ManagementContactsIndexRoute extends Route {
15
15
  sort: { refreshModel: true },
16
16
  query: { refreshModel: true },
17
17
  status: { refreshModel: true },
18
+ name: { refreshModel: true },
19
+ title: { refreshModel: true },
20
+ phone: { refreshModel: true },
21
+ email: { refreshModel: true },
22
+ type: { refreshModel: true },
23
+ internal_id: { refreshModel: true },
24
+ createdAt: { refreshModel: true },
25
+ updatedAt: { refreshModel: true },
18
26
  };
19
27
 
20
28
  model(params) {
@@ -15,11 +15,17 @@ export default class ManagementFleetsIndexRoute extends Route {
15
15
  sort: { refreshModel: true },
16
16
  query: { refreshModel: true },
17
17
  status: { refreshModel: true },
18
- internal_id: { refreshModel: true },
18
+ public_id: { refreshModel: true },
19
19
  zone: { refreshModel: true },
20
20
  service_area: { refreshModel: true },
21
- parent_fleet: { refreshModel: true },
21
+ parent_fleet_uuid: { refreshModel: true },
22
22
  task: { refreshModel: true },
23
+ name: { refreshModel: true },
24
+ vendor: { refreshModel: true },
25
+ drivers_count: { refreshModel: true },
26
+ drivers_online_count: { refreshModel: true },
27
+ createdAt: { refreshModel: true },
28
+ updatedAt: { refreshModel: true },
23
29
  };
24
30
 
25
31
  model(params) {
@@ -15,8 +15,14 @@ export default class ManagementFuelReportsIndexRoute extends Route {
15
15
  sort: { refreshModel: true },
16
16
  query: { refreshModel: true },
17
17
  vehicle: { refreshModel: true },
18
+ reporter: { refreshModel: true },
18
19
  driver: { refreshModel: true },
19
20
  status: { refreshModel: true },
21
+ createdAt: { refreshModel: true },
22
+ updatedAt: { refreshModel: true },
23
+ public_id: { refreshModel: true },
24
+ volume: { refreshModel: true },
25
+ odometer: { refreshModel: true },
20
26
  };
21
27
 
22
28
  model(params) {
@@ -14,8 +14,16 @@ export default class ManagementIssuesIndexRoute extends Route {
14
14
  limit: { refreshModel: true },
15
15
  sort: { refreshModel: true },
16
16
  query: { refreshModel: true },
17
- country: { refreshModel: true },
17
+ priority: { refreshModel: true },
18
18
  status: { refreshModel: true },
19
+ vehicle: { refreshModel: true },
20
+ driver: { refreshModel: true },
21
+ assignee: { refreshModel: true },
22
+ reporter: { refreshModel: true },
23
+ type: { refreshModel: true },
24
+ category: { refreshModel: true },
25
+ updatedAt: { refreshModel: true },
26
+ createdAt: { refreshModel: true },
19
27
  };
20
28
 
21
29
  model(params) {
@@ -15,9 +15,19 @@ export default class ManagementPlacesIndexRoute extends Route {
15
15
  sort: { refreshModel: true },
16
16
  query: { refreshModel: true },
17
17
  country: { refreshModel: true },
18
+ name: { refreshModel: true },
19
+ address: { refreshModel: true },
20
+ public_id: { refreshModel: true },
21
+ city: { refreshModel: true },
22
+ phone: { refreshModel: true },
23
+ neighborhood: { refreshModel: true },
24
+ postal_code: { refreshModel: true },
25
+ state: { refreshModel: true },
26
+ createdAt: { refreshModel: true },
27
+ updatedAt: { refreshModel: true },
18
28
  };
19
29
 
20
30
  model(params) {
21
- return this.store.query('place', { params });
31
+ return this.store.query('place', { ...params });
22
32
  }
23
33
  }
@@ -10,14 +10,14 @@ export default class ManagementVehiclesIndexRoute extends Route {
10
10
  sort: { refreshModel: true },
11
11
  query: { refreshModel: true },
12
12
  status: { refreshModel: true },
13
- name: { refreshModel: true },
13
+ display_name: { refreshModel: true },
14
14
  public_id: { refreshModel: true },
15
15
  vin: { refreshModel: true },
16
16
  plate_number: { refreshModel: true },
17
- vehicle_make: { refreshModel: true },
18
- vehicle_model: { refreshModel: true },
17
+ model: { refreshModel: true },
19
18
  year: { refreshModel: true },
20
19
  country: { refreshModel: true },
20
+ make: { refreshModel: true },
21
21
  fleet: { refreshModel: true },
22
22
  vendor: { refreshModel: true },
23
23
  driver: { refreshModel: true },
@@ -16,6 +16,14 @@ export default class ManagementVendorsIndexRoute extends Route {
16
16
  query: { refreshModel: true },
17
17
  country: { refreshModel: true },
18
18
  status: { refreshModel: true },
19
+ name: { refreshModel: true },
20
+ email: { refreshModel: true },
21
+ address: { refreshModel: true },
22
+ phone: { refreshModel: true },
23
+ type: { refreshModel: true },
24
+ createdAt: { refreshModel: true },
25
+ updatedAt: { refreshModel: true },
26
+ website_url: { refreshModel: true },
19
27
  };
20
28
 
21
29
  model(params) {
@@ -1,10 +1,35 @@
1
1
  import Route from '@ember/routing/route';
2
2
  import { inject as service } from '@ember/service';
3
+ import { isValid as isValidDate } from 'date-fns';
4
+ import { isNone } from '@ember/utils';
5
+ import createFullCalendarEventFromOrder from '../../../utils/create-full-calendar-event-from-order';
6
+
7
+ const getUnscheduledOrder = (order) => {
8
+ return isNone(order.scheduled_at);
9
+ };
10
+
11
+ const getScheduledOrder = (order) => {
12
+ return isValidDate(order.scheduled_at);
13
+ };
3
14
 
4
15
  export default class OperationsSchedulerIndexRoute extends Route {
5
16
  @service store;
6
17
 
7
18
  model() {
8
- return this.store.query('order', { status: 'created', with: ['payload'] });
19
+ return this.store.query('order', { status: 'created', with: ['payload', 'driverAssigned.vehicle'] });
20
+ }
21
+
22
+ setupController(controller, model) {
23
+ // get orders
24
+ const orders = model.toArray();
25
+
26
+ // set unscheduled orders
27
+ controller.unscheduledOrders = orders.filter(getUnscheduledOrder);
28
+
29
+ // set scheduled orders
30
+ controller.scheduledOrders = orders.filter(getScheduledOrder);
31
+
32
+ // create events from scheduledOrders
33
+ controller.events = controller.scheduledOrders.map(createFullCalendarEventFromOrder);
9
34
  }
10
35
  }
@@ -0,0 +1,28 @@
1
+ .scheduler-left-sidebar {
2
+ border-right: 1px rgba(229, 231, 235, 1) solid;
3
+ height: 100vh;
4
+ overflow-y: scroll;
5
+ }
6
+
7
+ body[data-theme="dark"] .scheduler-left-sidebar {
8
+ border-right: 1px rgba(55, 65, 81, 1) solid;
9
+ }
10
+
11
+ .scheduler-left-sidebar > .next-content-panel-wrapper > .next-content-panel-container > .next-content-panel > .next-content-panel-header.next-content-panel-is-closed {
12
+ border-bottom-left-radius: 0;
13
+ border-bottom-right-radius: 0;
14
+ }
15
+ .scheduler-left-sidebar > .next-content-panel-wrapper > .next-content-panel-container > .next-content-panel > .next-content-panel-header {
16
+ border-top-left-radius: 0;
17
+ border-top-right-radius: 0;
18
+ border-top: 0;
19
+ border-left: 0;
20
+ border-right: 0;
21
+ }
22
+
23
+ .scheduler-left-sidebar > .next-content-panel-wrapper > .next-content-panel-container > .next-content-panel > .next-content-panel-body {
24
+ border-left: 0;
25
+ border-right: 0;
26
+ border-bottom-left-radius: 0;
27
+ border-bottom-right-radius: 0;
28
+ }
@@ -13,9 +13,9 @@
13
13
  {{#if this.isMapLayout}}
14
14
  <MapContainer @layout={{this.layout}} @onReady={{this.onMapContainerReady}}>
15
15
  <GlobalSearch @visible={{this.isSearchVisible}} @onPressOrder={{this.viewOrder}} />
16
- <MapContainer::Toolbar @activeOrdersCount={{this.activeOrdersCount}} @liveMap={{this.liveMap}} @map={{this.leafletMap}} @onPressViewOrders={{this.toggleOrdersPanel}} @onPressSearch={{this.toggleSearch}} @onPressCreateOrder={{this.createOrder}} @onPressCreateDriver={{this.driversController.createDriver}} @onPressDriverProfile={{this.driversController.viewDriver}} />
16
+ <MapContainer::Toolbar @activeOrdersCount={{this.activeOrdersCount}} @liveMap={{this.liveMap}} @map={{this.leafletMap}} @onPressViewOrders={{this.toggleOrdersPanel}} @onPressSearch={{this.toggleSearch}} @onPressCreateOrder={{this.createOrder}} @onPressLiveMapDrawerToggle={{this.onPressLiveMapDrawerToggle}} />
17
17
  <OrderListOverlay @noBackdrop={{true}} @fullHeight={{true}} @outView={{not this.isOrdersPanelVisible}} @width={{if (media 'isMobile') "100%" "338px"}} @onPressCancel={{this.hideOrdersPanel}} @onPressCreateOrder={{this.createOrder}} @onPressViewOrder={{this.viewOrder}} @onPressCreateFleet={{this.fleetController.createFleet}} @onPressManageFleet={{this.fleetController.viewFleet}} @onPressCancelOrders={{this.bulkCancelOrders}} @onPressDeleteOrders={{this.bulkDeleteOrders}} />
18
- <LiveMap id="leafletMap" class="next-leaflet-container-map" @lat={{1.3521}} @lng={{103.8198}} @zoom={{12}} @zoomControl={{false}} @onLoad={{this.setMapReference}} {{set-container-dimensions}} />
18
+ <LiveMap id="leafletMap" class="next-leaflet-container-map" @lat={{1.3521}} @lng={{103.8198}} @zoom={{12}} @zoomControl={{false}} @onLoad={{this.setMapReference}} @onDrawerReady={{this.setDrawerContext}} @isDrawerMinimized={{not this.drawerOpen}} @onDrawerResizeEnd={{this.onDrawerResizeEnd}} @onDrawerTabChanged={{this.onDrawerTabChanged}} @drawerTab={{this.drawerTab}} {{set-container-dimensions}} />
19
19
  </MapContainer>
20
20
  {{/if}}
21
21
 
@@ -1,10 +1,18 @@
1
1
  <Layout::Section::Header @title="Scheduler" />
2
2
 
3
- {{!-- <div>
4
- <div class="p-6">
5
- <div class="grid grid-cols-3 gap-4">
6
- <div class="space-y-4">
7
- <ContentPanel @title="Unscheduled Orders" @titleStatuRight={{this.unscheduledOrders.length}} @titleStatuRightClass="info-status-badge" @hideStatusDot={{true}} @open={{this.unscheduledOrders.length}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
3
+ <Layout::Section::Body class="overflow-y-scroll h-screen">
4
+ <div class="h-screen">
5
+ <div class="grid grid-cols-1 lg:grid-cols-3">
6
+ <div class="scheduler-left-sidebar">
7
+ <ContentPanel
8
+ @title="Unscheduled Orders"
9
+ @titleStatuRight={{this.unscheduledOrders.length}}
10
+ @titleStatuRightClass="info-status-badge"
11
+ @hideStatusDot={{true}}
12
+ @open={{true}}
13
+ @pad={{true}}
14
+ @panelBodyClass="bg-white dark:bg-gray-900"
15
+ >
8
16
  <div class="space-y-4">
9
17
  {{#each this.unscheduledOrders as |order|}}
10
18
  <FullCalendar::Draggable @eventData={{json-hash id=order.id title=order.eventTitle allDay=true}}>
@@ -13,7 +21,15 @@
13
21
  {{/each}}
14
22
  </div>
15
23
  </ContentPanel>
16
- <ContentPanel @title="Scheduled Orders" @titleStatuRight={{this.scheduledOrders.length}} @titleStatusRightClass="info-status-badge" @hideStatusDot={{true}} @open={{this.scheduledOrders.length}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
24
+ <ContentPanel
25
+ @title="Scheduled Orders"
26
+ @titleStatuRight={{this.scheduledOrders.length}}
27
+ @titleStatusRightClass="info-status-badge"
28
+ @hideStatusDot={{true}}
29
+ @open={{true}}
30
+ @pad={{true}}
31
+ @panelBodyClass="bg-white dark:bg-gray-900"
32
+ >
17
33
  <div class="space-y-4">
18
34
  {{#each this.scheduledOrders as |order|}}
19
35
  <Order::ScheduleCard @order={{order}} @titleClass="cursor-pointer" @onTitleClick={{fn this.viewEvent order}} />
@@ -22,9 +38,17 @@
22
38
  </ContentPanel>
23
39
  </div>
24
40
 
25
- <div class="col-span-2">
26
- <FullCalendar @events={{this.events}} @onDrop={{this.scheduleEventFromDrop}} @onEventReceive={{this.receivedEvent}} @onEventDrop={{this.rescheduleEventFromDrag}} @onEventClick={{this.viewOrderAsEvent}} />
41
+ <div class="col-span-2 p-4">
42
+ <FullCalendar
43
+ @events={{this.events}}
44
+ @editable={{true}}
45
+ @onDrop={{this.scheduleEventFromDrop}}
46
+ @onEventReceive={{this.receivedEvent}}
47
+ @onEventDrop={{this.rescheduleEventFromDrag}}
48
+ @onEventClick={{this.viewOrderAsEvent}}
49
+ @onInit={{this.setCalendarApi}}
50
+ />
27
51
  </div>
28
52
  </div>
29
53
  </div>
30
- </div> --}}
54
+ </Layout::Section::Body>
@@ -0,0 +1,8 @@
1
+ export default function createFullCalendarEventFromOrder(order) {
2
+ return {
3
+ id: order.id,
4
+ title: `${order.scheduledAtTime} - ${order.public_id}`,
5
+ start: order.scheduled_at,
6
+ allDay: true,
7
+ };
8
+ }