@fleetbase/fleetops-engine 0.2.9 → 0.3.1

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 (70) hide show
  1. package/addon/components/context-panel.hbs +1 -1
  2. package/addon/components/driver-card-mini.js +34 -13
  3. package/addon/components/driver-form-panel.hbs +3 -3
  4. package/addon/components/driver-form-panel.js +87 -29
  5. package/addon/components/driver-panel.hbs +5 -5
  6. package/addon/components/driver-panel.js +118 -31
  7. package/addon/components/live-map.js +221 -10
  8. package/addon/components/map-container/toolbar/visibility-control-panel.hbs +66 -0
  9. package/addon/components/map-container/toolbar/visibility-control-panel.js +74 -0
  10. package/addon/components/map-container/toolbar/zones-panel.hbs +10 -10
  11. package/addon/components/map-container/toolbar/zones-panel.js +90 -61
  12. package/addon/components/map-container/toolbar.hbs +12 -7
  13. package/addon/components/modals/vehicle-form.hbs +35 -35
  14. package/addon/components/vehicle-form-panel.hbs +6 -7
  15. package/addon/components/vehicle-form-panel.js +86 -26
  16. package/addon/components/vehicle-panel.hbs +5 -5
  17. package/addon/components/vehicle-panel.js +124 -31
  18. package/addon/controllers/management/drivers/index/details.js +53 -0
  19. package/addon/controllers/management/drivers/index/edit.js +77 -46
  20. package/addon/controllers/management/drivers/index/new.js +39 -79
  21. package/addon/controllers/management/drivers/index.js +17 -221
  22. package/addon/controllers/management/fleets/index/edit.js +1 -1
  23. package/addon/controllers/management/fleets/index/new.js +1 -1
  24. package/addon/controllers/management/fuel-reports/index.js +2 -2
  25. package/addon/controllers/management/vehicles/index/details.js +49 -0
  26. package/addon/controllers/management/vehicles/index/edit.js +104 -1
  27. package/addon/controllers/management/vehicles/index/new.js +71 -0
  28. package/addon/controllers/operations/orders/index/new.js +1 -1
  29. package/addon/controllers/operations/orders/index/view.js +17 -7
  30. package/addon/controllers/operations/orders/index.js +109 -48
  31. package/addon/controllers/operations/service-rates/index/edit.js +1 -1
  32. package/addon/controllers/operations/service-rates/index/new.js +1 -1
  33. package/addon/helpers/is-visibility-control-visible.js +18 -0
  34. package/addon/routes/application.js +1 -1
  35. package/addon/routes/home.js +1 -1
  36. package/addon/routes/management/drivers/index/details.js +5 -0
  37. package/addon/routes/operations/service-rates/index.js +1 -1
  38. package/addon/routes/operations/zones/index.js +1 -1
  39. package/addon/services/context-panel.js +81 -14
  40. package/addon/templates/management/drivers/index/details.hbs +1 -1
  41. package/addon/templates/management/drivers/index/edit.hbs +1 -1
  42. package/addon/templates/management/drivers/index/new.hbs +1 -1
  43. package/addon/templates/management/vehicles/index/details.hbs +1 -1
  44. package/addon/templates/management/vehicles/index/edit.hbs +1 -1
  45. package/addon/templates/management/vehicles/index/new.hbs +1 -1
  46. package/addon/templates/operations/orders/index/view.hbs +2 -2
  47. package/addon/templates/operations/orders/index.hbs +1 -1
  48. package/addon/utils/apply-context-component-arguments.js +31 -0
  49. package/addon/utils/context-component-callback.js +16 -0
  50. package/app/components/map-container/toolbar/visibility-control-panel.js +1 -0
  51. package/app/helpers/is-visibility-control-visible.js +1 -0
  52. package/app/utils/apply-context-component-arguments.js +1 -0
  53. package/app/utils/context-component-callback.js +1 -0
  54. package/composer.json +2 -2
  55. package/extension.json +1 -1
  56. package/package.json +3 -3
  57. package/server/migrations/2023_09_14_074512_update_vehicles_table.php +89 -88
  58. package/server/migrations/2023_10_25_093014_create_vehicle_device_events_table.php +56 -0
  59. package/server/src/Http/Resources/v1/Vehicle.php +1 -0
  60. package/server/src/Models/Fleet.php +2 -0
  61. package/server/src/Models/VehicleDevice.php +17 -3
  62. package/server/src/Models/VehicleDeviceEvent.php +90 -0
  63. package/server/src/Notifications/OrderAssigned.php +21 -0
  64. package/server/src/Notifications/OrderCanceled.php +21 -0
  65. package/server/src/Notifications/OrderDispatchFailed.php +21 -0
  66. package/server/src/Notifications/OrderDispatched.php +21 -0
  67. package/server/src/Notifications/OrderPing.php +21 -0
  68. package/server/src/Notifications/OrderSplit.php +32 -5
  69. package/server/src/Providers/FleetOpsServiceProvider.php +22 -0
  70. package/server/src/Providers/NotificationServiceProvider.php +43 -0
@@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action, set } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
- import { dasherize, camelize } from '@ember/string';
6
+ import { dasherize, camelize, classify } from '@ember/string';
7
7
  import { singularize } from 'ember-inflector';
8
8
  import { alias } from '@ember/object/computed';
9
9
  import { later } from '@ember/runloop';
@@ -106,120 +106,155 @@ export default class LiveMapComponent extends Component {
106
106
  /**
107
107
  * An array of routes.
108
108
  * @type {Array}
109
+ * @memberof LiveMapComponent
109
110
  */
110
111
  @tracked routes = [];
111
112
 
112
113
  /**
113
114
  * An array of drivers.
114
115
  * @type {Array}
116
+ * @memberof LiveMapComponent
115
117
  */
116
118
  @tracked drivers = [];
117
119
 
118
120
  /**
119
121
  * An array of vehicles.
120
122
  * @type {Array}
123
+ * @memberof LiveMapComponent
121
124
  */
122
125
  @tracked vehicles = [];
123
126
 
124
127
  /**
125
128
  * An array of places.
126
129
  * @type {Array}
130
+ * @memberof LiveMapComponent
127
131
  */
128
132
  @tracked places = [];
129
133
 
130
134
  /**
131
135
  * An array of channels.
132
136
  * @type {Array}
137
+ * @memberof LiveMapComponent
133
138
  */
134
139
  @tracked channels = [];
135
140
 
136
141
  /**
137
142
  * Indicates if data is loading.
138
143
  * @type {boolean}
144
+ * @memberof LiveMapComponent
139
145
  */
140
146
  @tracked isLoading = true;
141
147
 
142
148
  /**
143
149
  * Indicates if the component is ready.
144
150
  * @type {boolean}
151
+ * @memberof LiveMapComponent
145
152
  */
146
153
  @tracked isReady = false;
147
154
 
148
155
  /**
149
156
  * Controls for visibility.
150
157
  * @type {Object}
158
+ * @memberof LiveMapComponent
151
159
  */
152
- @tracked visibilityControls = {};
160
+ @tracked visibilityControls = {
161
+ vehicles: true,
162
+ onlineVehicles: true,
163
+ offlineVehicles: true,
164
+ drivers: true,
165
+ onlineDrivers: true,
166
+ offlineDrivers: true,
167
+ places: true,
168
+ };
153
169
 
154
170
  /**
155
171
  * An array of active service areas.
156
172
  * @type {Array}
173
+ * @memberof LiveMapComponent
157
174
  */
158
175
  @tracked activeServiceAreas = [];
159
176
 
160
177
  /**
161
178
  * An array of editable map layers.
162
179
  * @type {Array}
180
+ * @memberof LiveMapComponent
163
181
  */
164
182
  @tracked editableLayers = [];
165
183
 
166
184
  /**
167
185
  * The Leaflet map instance.
168
186
  * @type {Object}
187
+ * @memberof LiveMapComponent
169
188
  */
170
189
  @tracked leafletMap;
171
190
 
172
191
  /**
173
192
  * The map's zoom level.
174
193
  * @type {number}
194
+ * @memberof LiveMapComponent
175
195
  */
176
196
  @tracked zoom = 12;
177
197
 
178
198
  /**
179
199
  * The feature group for drawing on the map.
180
200
  * @type {Object}
201
+ * @memberof LiveMapComponent
181
202
  */
182
203
  @tracked drawFeatureGroup;
183
204
 
184
205
  /**
185
206
  * The draw control for the map.
186
207
  * @type {Object}
208
+ * @memberof LiveMapComponent
187
209
  */
188
210
  @tracked drawControl;
189
211
 
190
212
  /**
191
213
  * The URL for the map's tile source.
192
214
  * @type {string}
215
+ * @memberof LiveMapComponent
193
216
  */
194
217
  @tracked tileSourceUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
195
218
 
196
219
  /**
197
220
  * The latitude for the map view.
198
221
  * @type {number}
222
+ * @memberof LiveMapComponent
199
223
  */
200
224
  @tracked latitude = DEFAULT_LATITUDE;
201
225
 
202
226
  /**
203
227
  * The longitude for the map view.
204
228
  * @type {number}
229
+ * @memberof LiveMapComponent
205
230
  */
206
231
  @tracked longitude = DEFAULT_LONGITUDE;
207
232
 
208
233
  /**
209
234
  * Indicates if coordinate setting should be skipped.
210
235
  * @type {boolean}
236
+ * @memberof LiveMapComponent
211
237
  */
212
238
  @tracked skipSetCoordinates = false;
213
239
 
240
+ /**
241
+ * Cache for storing original state of resource arrays.
242
+ * @type {Object.<string, Array>}
243
+ * @memberof LiveMapComponent
244
+ */
245
+ originalResources = {};
246
+
214
247
  /**
215
248
  * The user's latitude from the currentUser.
216
249
  * @type {number}
250
+ * @memberof LiveMapComponent
217
251
  */
218
252
  @alias('currentUser.latitude') userLatitude;
219
253
 
220
254
  /**
221
255
  * The user's longitude from the currentUser.
222
256
  * @type {number}
257
+ * @memberof LiveMapComponent
223
258
  */
224
259
  @alias('currentUser.longitude') userLongitude;
225
260
 
@@ -419,6 +454,8 @@ export default class LiveMapComponent extends Component {
419
454
  this.triggerAction(callbackFnName);
420
455
  this.createVisibilityControl(internalName);
421
456
  this[internalName] = data;
457
+ // cache as resource
458
+ this.cacheOriginalResources(internalName);
422
459
 
423
460
  if (typeof options.onLoaded === 'function') {
424
461
  options.onLoaded(data);
@@ -477,7 +514,7 @@ export default class LiveMapComponent extends Component {
477
514
  */
478
515
  hide(name) {
479
516
  if (isArray(name)) {
480
- return name.forEach(this.hide);
517
+ return name.forEach(this.hide.bind(this));
481
518
  }
482
519
 
483
520
  this.createVisibilityControl(name, false);
@@ -491,22 +528,180 @@ export default class LiveMapComponent extends Component {
491
528
  */
492
529
  show(name) {
493
530
  if (isArray(name)) {
494
- return name.forEach(this.show);
531
+ return name.forEach(this.show.bind(this));
495
532
  }
496
533
 
497
534
  this.createVisibilityControl(name, true);
498
535
  }
499
536
 
537
+ /**
538
+ * Toggles the visibility of a control by its name.
539
+ * Calls `hide()` if the control is currently visible, and `show()` otherwise.
540
+ *
541
+ * @param {string} name - The name of the control to toggle.
542
+ * @memberof LiveMapComponent
543
+ */
544
+ toggleVisibility(name) {
545
+ if (this.isVisible(name)) {
546
+ this.hide(name);
547
+ } else {
548
+ this.show(name);
549
+ }
550
+ }
551
+
500
552
  /**
501
553
  * Check if a specific element or feature is currently visible based on its name.
502
554
  *
503
555
  * @param {string} name - The name of the element or feature to check visibility for.
504
556
  * @returns {boolean} Returns `true` if the element or feature is currently visible, `false` otherwise.
557
+ * @memberof LiveMapComponent
505
558
  */
506
559
  isVisible(name) {
507
560
  return this.visibilityControls[name] === true;
508
561
  }
509
562
 
563
+ /**
564
+ * Caches the original state of a resource array.
565
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
566
+ * @memberof LiveMapComponent
567
+ */
568
+ cacheOriginalResources(name) {
569
+ if (!this.originalResources[name]) {
570
+ this.originalResources[name] = [...this[name]];
571
+ }
572
+ }
573
+
574
+ /**
575
+ * Retrieves the original resources array for a given name.
576
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
577
+ * @returns {Array} - The original array of resources; an empty array if not set.
578
+ * @memberof LiveMapComponent
579
+ */
580
+ getOriginalResources(name) {
581
+ if (isArray(this.originalResources[name])) {
582
+ return this.originalResources[name];
583
+ }
584
+
585
+ return [];
586
+ }
587
+
588
+ /**
589
+ * Shows all online and offline resources for a given name.
590
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
591
+ * @memberof LiveMapComponent
592
+ */
593
+ showAllOnlineOffline(name) {
594
+ this.show(name);
595
+ this.showOnline(name);
596
+ this.showOffline(name);
597
+ }
598
+
599
+ /**
600
+ * Hides all online and offline resources for a given name.
601
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
602
+ * @memberof LiveMapComponent
603
+ */
604
+ hideAllOnlineOffline(name) {
605
+ this.hide(name);
606
+ this.hideOnline(name);
607
+ this.hideOffline(name);
608
+ }
609
+
610
+ /**
611
+ * Toggles the visibility of all online and offline resources for a given name.
612
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
613
+ * @memberof LiveMapComponent
614
+ */
615
+ toggleAllOnlineOffline(name) {
616
+ if (this.isVisible(name)) {
617
+ this.hideAllOnlineOffline(name);
618
+ } else {
619
+ this.showAllOnlineOffline(name);
620
+ }
621
+ }
622
+
623
+ /**
624
+ * Toggles the visibility of online resources for a given array.
625
+ * @method toggleOnline
626
+ * @param {string} name - The name of the resource array (e.g., 'vehicles', 'drivers').
627
+ * @memberof LiveMapComponent
628
+ */
629
+ toggleOnline(name) {
630
+ const visibilityControlName = `online${classify(name)}`;
631
+
632
+ if (this.isVisible(visibilityControlName)) {
633
+ this.hideOnline(name);
634
+ } else {
635
+ this.showOnline(name);
636
+ }
637
+ }
638
+
639
+ /**
640
+ * Toggles the visibility of offline resources for a given array.
641
+ * @method toggleOffline
642
+ * @param {string} name - The name of the resource array (e.g., 'vehicles', 'drivers').
643
+ * @memberof LiveMapComponent
644
+ */
645
+ toggleOffline(name) {
646
+ const visibilityControlName = `offline${classify(name)}`;
647
+
648
+ if (this.isVisible(visibilityControlName)) {
649
+ this.hideOffline(name);
650
+ } else {
651
+ this.showOffline(name);
652
+ }
653
+ }
654
+
655
+ /**
656
+ * Hides online resources from a given array and updates it.
657
+ * @method hideOnline
658
+ * @param {string} name - The name of the resource array (e.g., 'vehicles', 'drivers').
659
+ * @memberof LiveMapComponent
660
+ */
661
+ hideOnline(name) {
662
+ this[name] = this.getOriginalResources(name).filter((resource) => !resource.online);
663
+
664
+ // track with visibility controls
665
+ this.createVisibilityControl(`online${classify(name)}`, false);
666
+ }
667
+
668
+ /**
669
+ * Shows online resources from a given array and updates it.
670
+ * @method showOnline
671
+ * @param {string} name - The name of the resource array (e.g., 'vehicles', 'drivers').
672
+ * @memberof LiveMapComponent
673
+ */
674
+ showOnline(name) {
675
+ this[name] = this.getOriginalResources(name).filter((resource) => resource.online);
676
+
677
+ // track with visibility controls
678
+ this.createVisibilityControl(`online${classify(name)}`, true);
679
+ }
680
+
681
+ /**
682
+ * Hides offline resources from a specified array.
683
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
684
+ * @memberof LiveMapComponent
685
+ */
686
+ hideOffline(name) {
687
+ this[name] = this.getOriginalResources(name).filter((resource) => resource.online);
688
+
689
+ // track with visibility controls
690
+ this.createVisibilityControl(`offline${classify(name)}`, false);
691
+ }
692
+
693
+ /**
694
+ * Shows offline resources from a specified array.
695
+ * @param {string} name - Name of the resource array (e.g., 'vehicles', 'drivers').
696
+ * @memberof LiveMapComponent
697
+ */
698
+ showOffline(name) {
699
+ this[name] = this.getOriginalResources(name).filter((resource) => !resource.online);
700
+
701
+ // track with visibility controls
702
+ this.createVisibilityControl(`offline${classify(name)}`, true);
703
+ }
704
+
510
705
  /**
511
706
  * Toggles the context menu item for enabling/disabling draw controls.
512
707
  *
@@ -514,6 +709,7 @@ export default class LiveMapComponent extends Component {
514
709
  * @param {string} [options.onText='Hide draw controls...'] - Text to display when enabling draw controls.
515
710
  * @param {string} [options.offText='Enable draw controls...'] - Text to display when disabling draw controls.
516
711
  * @param {string} [options.callback=function] - Callback function to trigger after toggle.
712
+ * @memberof LiveMapComponent
517
713
  */
518
714
  toggleDrawControlContextMenuItem(options = {}) {
519
715
  const toggle = !this.isVisible('drawControls');
@@ -537,6 +733,7 @@ export default class LiveMapComponent extends Component {
537
733
  * Removes a specific service area from the context menu.
538
734
  *
539
735
  * @param {Object} serviceArea - The service area to be removed from the context menu.
736
+ * @memberof LiveMapComponent
540
737
  */
541
738
  removeServiceAreaFromContextMenu(serviceArea) {
542
739
  this.leafletContextmenuManager.removeItemFromContextMenu('map', `Focus Service Area: ${serviceArea.name}`);
@@ -547,6 +744,7 @@ export default class LiveMapComponent extends Component {
547
744
  *
548
745
  * @param {string} id - The ID of the Leaflet layer to retrieve.
549
746
  * @returns {Object|null} The found Leaflet layer or `null` if not found.
747
+ * @memberof LiveMapComponent
550
748
  */
551
749
  getLeafletLayerById(id) {
552
750
  return this.leafletMapManager.getLeafletLayerById(this.leafletMap, id);
@@ -557,6 +755,7 @@ export default class LiveMapComponent extends Component {
557
755
  *
558
756
  * @param {Function} callback - A callback function that defines the condition for finding the layer.
559
757
  * @returns {Object|null} The found Leaflet layer or `null` if not found.
758
+ * @memberof LiveMapComponent
560
759
  */
561
760
  findLeafletLayer(callback) {
562
761
  return this.leafletMapManager.findLeafletLayer(this.leafletMap, callback);
@@ -1183,7 +1382,7 @@ export default class LiveMapComponent extends Component {
1183
1382
  // Add Service Area Context Menu Items
1184
1383
  const serviceAreas = this.serviceAreas.getFromCache();
1185
1384
 
1186
- if (isArray(serviceAreas)) {
1385
+ if (isArray(serviceAreas) && serviceAreas.length) {
1187
1386
  contextmenuItems.pushObject({
1188
1387
  separator: true,
1189
1388
  });
@@ -1227,7 +1426,7 @@ export default class LiveMapComponent extends Component {
1227
1426
  * @memberof LiveMapComponent
1228
1427
  */
1229
1428
  @action createDriverContextMenu(driver, layer) {
1230
- const contextmenuItems = [
1429
+ let contextmenuItems = [
1231
1430
  {
1232
1431
  separator: true,
1233
1432
  },
@@ -1258,7 +1457,13 @@ export default class LiveMapComponent extends Component {
1258
1457
  return {
1259
1458
  text: menuItem.title,
1260
1459
  callback: () => {
1261
- return menuItem.onClick(driver, layer, menuItem);
1460
+ const callbackContext = {
1461
+ driver,
1462
+ layer,
1463
+ contextmenuService: this.leafletContextmenuManager,
1464
+ menuItem,
1465
+ };
1466
+ return menuItem.onClick(callbackContext);
1262
1467
  },
1263
1468
  };
1264
1469
  }),
@@ -1309,7 +1514,13 @@ export default class LiveMapComponent extends Component {
1309
1514
  return {
1310
1515
  text: menuItem.title,
1311
1516
  callback: () => {
1312
- return menuItem.onClick(vehicle, layer, menuItem);
1517
+ const callbackContext = {
1518
+ vehicle,
1519
+ layer,
1520
+ contextmenuService: this.leafletContextmenuManager,
1521
+ menuItem,
1522
+ };
1523
+ return menuItem.onClick(callbackContext);
1313
1524
  },
1314
1525
  };
1315
1526
  }),
@@ -1333,7 +1544,7 @@ export default class LiveMapComponent extends Component {
1333
1544
  * @memberof LiveMapComponent
1334
1545
  */
1335
1546
  @action createZoneContextMenu(zone, layer) {
1336
- const contextmenuItems = [
1547
+ let contextmenuItems = [
1337
1548
  {
1338
1549
  separator: true,
1339
1550
  },
@@ -1373,7 +1584,7 @@ export default class LiveMapComponent extends Component {
1373
1584
  * @memberof LiveMapComponent
1374
1585
  */
1375
1586
  @action createServiceAreaContextMenu(serviceArea, layer) {
1376
- const contextmenuItems = [
1587
+ let contextmenuItems = [
1377
1588
  {
1378
1589
  separator: true,
1379
1590
  },
@@ -0,0 +1,66 @@
1
+ <div class="next-dd-menu overflow-visible">
2
+ <div class="px-1">
3
+ <div class="text-sm flex flex-row items-center px-3 py-0.5 rounded-md my-1 text-gray-800 dark:text-gray-300">
4
+ Visibility Controls
5
+ </div>
6
+ </div>
7
+ <div class="next-dd-menu-seperator"></div>
8
+ <div class="px-1">
9
+ <a href="javascript:;" class="next-dd-item flex-row items-center justify-between relative" {{on "click" (fn this.triggerCallback "toggleVisibility" "places")}}>
10
+ <div class="flex flex-row items-center">
11
+ <div class="w-6">
12
+ <FaIcon @icon="building" />
13
+ </div>
14
+ <span>
15
+ {{#if (is-visibility-control-visible this.liveMap "places")}}
16
+ Hide all places...
17
+ {{else}}
18
+ Show all places...
19
+ {{/if}}
20
+ </span>
21
+ </div>
22
+ <div>
23
+ <Badge @status="info" @hideStatusDot={{true}} @spanClass="rounded-full -mr-2">{{this.liveMap.originalResources.places.length}}</Badge>
24
+ </div>
25
+ </a>
26
+ <BasicDropdownHover @horizontalPosition="right" @calculatePosition={{this.calculatePosition}} @renderInPlace={{true}} as |dd|>
27
+ <dd.Trigger class="next-dd-item flex-row items-center justify-between relative {{if dd.isOpen 'active'}}">
28
+ <div class="flex flex-row items-center">
29
+ <div class="w-6">
30
+ <FaIcon @icon="car" />
31
+ </div>
32
+ <span>Vehicles</span>
33
+ </div>
34
+ <div>
35
+ <Badge @status="info" @hideStatusDot={{true}} @spanClass="rounded-full -mr-2">{{this.liveMap.originalResources.vehicles.length}}</Badge>
36
+ </div>
37
+ </dd.Trigger>
38
+ <dd.Content>
39
+ <div class="next-dd-menu">
40
+ <div class="px-1">
41
+ <div class="text-sm flex flex-row items-center px-3 py-0.5 rounded-md my-1 text-gray-800 dark:text-gray-300 truncate">
42
+ <FaIcon @icon="binoculars" class="mr-2" />
43
+ <span>Vehicle Visibility Controls...</span>
44
+ </div>
45
+ </div>
46
+ <div class="next-dd-menu-seperator"></div>
47
+ <div class="px-1">
48
+ <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.triggerCallback "toggleAllOnlineOffline" "vehicles")}}>
49
+ {{#if (is-visibility-control-visible this.liveMap "vehicles")}}
50
+ Hide all vehicles...
51
+ {{else}}
52
+ Show all vehicles...
53
+ {{/if}}
54
+ </a>
55
+ <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.triggerCallback "showOnline" "vehicles")}}>
56
+ Only show online vehicles...
57
+ </a>
58
+ <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.triggerCallback "showOffline" "vehicles")}}>
59
+ Only show offline vehicles...
60
+ </a>
61
+ </div>
62
+ </div>
63
+ </dd.Content>
64
+ </BasicDropdownHover>
65
+ </div>
66
+ </div>
@@ -0,0 +1,74 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+ import { classify } from '@ember/string';
5
+ import { calculateInPlacePosition } from 'ember-basic-dropdown/utils/calculate-position';
6
+
7
+ /**
8
+ * @class MapContainerToolbarVisibilityControlPanelComponent
9
+ * @extends {Component}
10
+ * @memberof @fleetbase/fleetops-engine
11
+ */
12
+ export default class MapContainerToolbarVisibilityControlPanelComponent extends Component {
13
+ /**
14
+ * Reference to the map instance.
15
+ * @type {L.Map}
16
+ * @memberof MapContainerToolbarZonesPanelComponent
17
+ */
18
+ @tracked map;
19
+
20
+ /**
21
+ * Reference to the live map component instance.
22
+ * @type {LiveMapComponent}
23
+ * @memberof MapContainerToolbarZonesPanelComponent
24
+ */
25
+ @tracked liveMap;
26
+
27
+ /**
28
+ * Class constructor.
29
+ * @memberof MapContainerToolbarZonesPanelComponent
30
+ */
31
+ constructor() {
32
+ super(...arguments);
33
+ this.map = this.args.map;
34
+ this.liveMap = this.args.liveMap;
35
+ }
36
+
37
+ /**
38
+ * Calculate position for dropdown.
39
+ * @param {Element} trigger The triggering element
40
+ * @returns {Object} Position style object
41
+ * @memberof MapContainerToolbarZonesPanelComponent
42
+ */
43
+ @action calculatePosition(trigger) {
44
+ const position = calculateInPlacePosition(...arguments);
45
+ const rect = trigger.getBoundingClientRect();
46
+
47
+ position.style.top = '-0.5rem';
48
+ position.style.left = `calc(${rect.width}px + 0.75rem)`;
49
+
50
+ return position;
51
+ }
52
+
53
+ /**
54
+ * Generic callback trigger function.
55
+ * @param {string} callbackFn Callback function name
56
+ * @param {...any} params Parameters for the callback function
57
+ * @memberof MapContainerToolbarZonesPanelComponent
58
+ */
59
+ @action triggerCallback(callbackFn, ...params) {
60
+ const tryInvoke = (context, fnName) => {
61
+ if (context && typeof context[fnName] === 'function') {
62
+ context[fnName](...params);
63
+ }
64
+ };
65
+
66
+ tryInvoke(this, callbackFn);
67
+ tryInvoke(this.args, callbackFn);
68
+ tryInvoke(this.liveMap, callbackFn);
69
+
70
+ // Additional check for event callback function in args
71
+ const eventCallbackFn = `on${classify(callbackFn)}`;
72
+ tryInvoke(this.args, eventCallbackFn);
73
+ }
74
+ }
@@ -1,4 +1,4 @@
1
- <div class="next-dd-menu overflow-visible" {{did-insert this.setupZonesPanel}}>
1
+ <div class="next-dd-menu overflow-visible">
2
2
  <div class="px-1">
3
3
  <div class="text-sm flex flex-row items-center px-3 py-0.5 rounded-md my-1 text-gray-800 dark:text-gray-300">
4
4
  Service Areas
@@ -6,9 +6,9 @@
6
6
  </div>
7
7
  <div class="next-dd-menu-seperator"></div>
8
8
  <div class="px-1">
9
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.serviceAreaAction "createServiceArea" @dd)}}>Create new service area...</a>
10
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.liveMapAction "focusAllServiceAreas" @dd)}}>Show all service areas</a>
11
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.liveMapAction "blurAllServiceAreas" @dd)}}>Hide all service areas</a>
9
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn @dd this.triggerCallback "createServiceArea")}}>Create new service area...</a>
10
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn @dd this.triggerCallback "focusAllServiceAreas")}}>Show all service areas</a>
11
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn @dd this.triggerCallback "blurAllServiceAreas")}}>Hide all service areas</a>
12
12
  {{#each this.serviceAreaRecords as |serviceArea|}}
13
13
  <BasicDropdownHover @horizontalPosition="right" @calculatePosition={{this.calculatePosition}} @renderInPlace={{true}} as |dd|>
14
14
  <dd.Trigger class="next-dd-item {{if dd.isOpen 'active'}}">
@@ -25,13 +25,13 @@
25
25
  </div>
26
26
  <div class="next-dd-menu-seperator"></div>
27
27
  <div class="px-1">
28
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.liveMapAction "focusServiceArea" dd serviceArea)}}>Focus {{serviceArea.name}}...</a>
29
- {{#if (eq serviceArea this.activeServiceArea)}}
30
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.liveMapAction "blurServiceArea" dd serviceArea)}}>Blur service area...</a>
28
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.triggerCallback "focusServiceArea" serviceArea)}}>Focus {{serviceArea.name}}...</a>
29
+ {{#if (eq serviceArea this.liveMap.activeServiceArea)}}
30
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.triggerCallback "blurServiceArea" serviceArea)}}>Blur service area...</a>
31
31
  {{/if}}
32
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.serviceAreaAction "createZone" dd serviceArea)}}>Create zone inside...</a>
33
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.serviceAreaAction "editServiceAreaDetails" dd serviceArea)}}>Edit {{serviceArea.name}}...</a>
34
- <a href="javascript:;" class="next-dd-item" {{on "click" (fn this.serviceAreaAction "deleteServiceArea" dd serviceArea)}}>Delete {{serviceArea.name}}...</a>
32
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.triggerCallback "createZone" serviceArea)}}>Create zone inside...</a>
33
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.triggerCallback "editServiceAreaDetails" serviceArea)}}>Edit {{serviceArea.name}}...</a>
34
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.triggerCallback "deleteServiceArea" serviceArea)}}>Delete {{serviceArea.name}}...</a>
35
35
  </div>
36
36
  </div>
37
37
  </dd.Content>