@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
@@ -1,62 +1,122 @@
1
1
  import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
2
3
  import { inject as service } from '@ember/service';
3
4
  import { action } from '@ember/object';
5
+ import contextComponentCallback from '../utils/context-component-callback';
6
+ import applyContextComponentArguments from '../utils/apply-context-component-arguments';
4
7
 
5
8
  export default class VehicleFormPanelComponent extends Component {
9
+ /**
10
+ * @service store
11
+ */
6
12
  @service store;
13
+
14
+ /**
15
+ * @service notifications
16
+ */
7
17
  @service notifications;
18
+
19
+ /**
20
+ * @service hostRouter
21
+ */
8
22
  @service hostRouter;
23
+
24
+ /**
25
+ * @service loader
26
+ */
9
27
  @service loader;
28
+
29
+ /**
30
+ * @service contextPanel
31
+ */
10
32
  @service contextPanel;
11
33
 
34
+ /**
35
+ * Overlay context.
36
+ * @type {any}
37
+ */
38
+ @tracked context;
39
+
40
+ /**
41
+ * Indicates whether the component is in a loading state.
42
+ * @type {boolean}
43
+ */
44
+ @tracked isLoading = false;
45
+
46
+ /**
47
+ * Constructs the component and applies initial state.
48
+ */
12
49
  constructor() {
13
50
  super(...arguments);
14
51
  this.vehicle = this.args.vehicle;
15
- this.applyDynamicArguments();
52
+ applyContextComponentArguments(this);
16
53
  }
17
54
 
18
- applyDynamicArguments() {
19
- // Apply context if available
20
- if (this.args.context) {
21
- this.vehicle = this.args.context;
22
- }
23
-
24
- // Apply dynamic arguments if available
25
- if (this.args.dynamicArgs) {
26
- const keys = Object.keys(this.args.dynamicArgs);
27
-
28
- keys.forEach((key) => {
29
- this[key] = this.args.dynamicArgs[key];
30
- });
31
- }
55
+ /**
56
+ * Sets the overlay context.
57
+ *
58
+ * @action
59
+ * @param {OverlayContextObject} overlayContext
60
+ */
61
+ @action setOverlayContext(overlayContext) {
62
+ this.context = overlayContext;
63
+ contextComponentCallback(this, 'onLoad', ...arguments);
32
64
  }
33
65
 
66
+ /**
67
+ * Saves the vehicle changes.
68
+ *
69
+ * @action
70
+ * @returns {Promise<any>}
71
+ */
34
72
  @action save() {
35
- const { onAfterSave } = this.args;
36
73
  const { vehicle } = this;
37
74
 
38
- this.loader.showLoader('.overlay-inner-content', 'Saving vehicle...');
75
+ this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving vehicle...', preserveTargetPosition: true });
76
+ this.isLoading = true;
77
+
78
+ contextComponentCallback(this, 'onBeforeSave', vehicle);
39
79
 
40
80
  try {
41
81
  return vehicle
42
82
  .save()
43
83
  .then((vehicle) => {
44
84
  this.notifications.success(`Vehicle (${vehicle.displayName}) saved successfully.`);
45
-
46
- if (typeof onAfterSave === 'function') {
47
- onAfterSave(vehicle);
48
- }
85
+ contextComponentCallback(this, 'onAfterSave', vehicle);
86
+ })
87
+ .catch((error) => {
88
+ this.notifications.serverError(error);
49
89
  })
50
- .catch(this.notifications.serverError)
51
90
  .finally(() => {
52
- this.loader.removeLoader();
91
+ this.loader.removeLoader('.next-content-overlay-panel-container ');
92
+ this.isLoading = false;
53
93
  });
54
94
  } catch (error) {
55
- this.loader.removeLoader();
95
+ this.loader.removeLoader('.next-content-overlay-panel-container ');
96
+ this.isLoading = false;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * View the details of the vehicle.
102
+ *
103
+ * @action
104
+ */
105
+ @action onViewDetails() {
106
+ const isActionOverrided = contextComponentCallback(this, 'onViewDetails', this.vehicle);
107
+
108
+ if (!isActionOverrided) {
109
+ this.contextPanel.focus(this.vehicle, 'viewing');
56
110
  }
57
111
  }
58
112
 
59
- @action viewDetails() {
60
- this.contextPanel.focus(this.vehicle, 'viewing');
113
+ /**
114
+ * Handles cancel button press.
115
+ *
116
+ * @action
117
+ * @returns {any}
118
+ */
119
+ @action onPressCancel() {
120
+ return contextComponentCallback(this, 'onPressCancel', this.vehicle);
61
121
  }
62
122
  }
@@ -1,11 +1,11 @@
1
- <Overlay @position="right" @noBackdrop={{true}} @fullHeight={{true}} @isResizable={{or this.isResizable @isResizable}} @width={{or this.width @width "600px"}}>
1
+ <Overlay @onLoad={{this.setOverlayContext}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @isResizable={{or this.isResizable @isResizable}} @width={{or this.width @width "600px"}}>
2
2
  <Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]">
3
3
  <div class="flex flex-row items-center justify-between w-full mb-4">
4
4
  <div class="flex flex-1 space-x-2">
5
- <Button @type="default" @icon="pen" @helpText="Edit vehicle" @onClick={{this.editVehicle}} />
5
+ <Button @type="default" @icon="pen" @helpText="Edit vehicle" @onClick={{this.onEdit}} />
6
6
  </div>
7
7
  <div class="flex flex-1 justify-end">
8
- <Button @type="default" @icon="times" @helpText="Close vehicle details" @onClick={{@onPressCancel}} />
8
+ <Button @type="default" @icon="times" @helpText="Close vehicle details" @onClick={{this.onPressCancel}} />
9
9
  </div>
10
10
  </div>
11
11
  <div class="flex flex-row justify-between w-full">
@@ -44,7 +44,7 @@
44
44
  <div class="ui-tabs mt-4">
45
45
  <nav>
46
46
  {{#each this.tabs as |tab|}}
47
- <a href="javascript:;" class="ui-tab {{if (eq this.currentTab tab.slug) 'active' }}" {{on "click" (fn this.changeTab tab.slug)}}>
47
+ <a href="javascript:;" class="ui-tab {{if (eq this.tab.slug tab.slug) 'active' }}" {{on "click" (fn this.onTabChanged tab.slug)}}>
48
48
  <FaIcon @icon={{tab.icon}} class="mr-1" />
49
49
  <span>{{tab.title}}</span>
50
50
  </a>
@@ -52,7 +52,7 @@
52
52
  </nav>
53
53
  </div>
54
54
  </div>
55
- <div class="tab-content tab-{{this.currentTab}}">
55
+ <div class="tab-content tab-{{this.tab.slug}}">
56
56
  {{component this.tab.component vehicle=this.vehicle tabOptions=this.tab params=this.tab.componentParams}}
57
57
  </div>
58
58
  </Overlay::Body>
@@ -1,22 +1,82 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
- import { action, computed } from '@ember/object';
3
+ import { action } from '@ember/object';
4
4
  import { inject as service } from '@ember/service';
5
5
  import { isArray } from '@ember/array';
6
6
  import VehiclePanelDetailComponent from './vehicle-panel/details';
7
+ import contextComponentCallback from '../utils/context-component-callback';
8
+ import applyContextComponentArguments from '../utils/apply-context-component-arguments';
7
9
 
10
+ /**
11
+ * Represents the vehicle panel component, handling vehicle information display and editing.
12
+ *
13
+ * @class VehiclePanelComponent
14
+ * @extends Component
15
+ */
8
16
  export default class VehiclePanelComponent extends Component {
17
+ /**
18
+ * Service for fetching data.
19
+ *
20
+ * @type {Service}
21
+ */
9
22
  @service fetch;
23
+
24
+ /**
25
+ * Service for managing modals.
26
+ *
27
+ * @type {Service}
28
+ */
10
29
  @service modalsManager;
30
+
31
+ /**
32
+ * Universe service for managing global data and settings.
33
+ *
34
+ * @type {Service}
35
+ */
11
36
  @service universe;
37
+
38
+ /**
39
+ * Ember data store service.
40
+ *
41
+ * @type {Service}
42
+ */
12
43
  @service store;
44
+
45
+ /**
46
+ * Service for managing routing within the host app.
47
+ *
48
+ * @type {Service}
49
+ */
13
50
  @service hostRouter;
51
+
52
+ /**
53
+ * Service for managing the context panel.
54
+ *
55
+ * @type {Service}
56
+ */
14
57
  @service contextPanel;
15
- @tracked currentTab;
16
- @tracked devices = [];
17
- @tracked deviceApi = {};
58
+
59
+ /**
60
+ * The current active tab.
61
+ *
62
+ * @type {Object}
63
+ * @tracked
64
+ */
65
+ @tracked tab;
66
+
67
+ /**
68
+ * The vehicle being displayed or edited.
69
+ *
70
+ * @type {VehicleModel}
71
+ * @tracked
72
+ */
18
73
  @tracked vehicle;
19
74
 
75
+ /**
76
+ * Returns the array of tabs available for the panel.
77
+ *
78
+ * @type {Array}
79
+ */
20
80
  get tabs() {
21
81
  const registeredTabs = this.universe.getMenuItemsFromRegistry('component:vehicle-panel');
22
82
  // this.universe._createMenuItem('Tracking', null, { icon: 'satellite-dish', component: VehiclePanelTrackingComponent }),
@@ -29,46 +89,79 @@ export default class VehiclePanelComponent extends Component {
29
89
  return defaultTabs;
30
90
  }
31
91
 
32
- @computed('currentTab', 'tabs') get tab() {
33
- if (this.currentTab) {
34
- return this.tabs.find(({ slug }) => slug === this.currentTab);
35
- }
36
-
37
- return null;
38
- }
39
-
92
+ /**
93
+ * Initializes the vehicle panel component.
94
+ */
40
95
  constructor() {
41
96
  super(...arguments);
42
97
  this.vehicle = this.args.vehicle;
43
- this.changeTab(this.args.tab);
44
- this.applyDynamicArguments();
98
+ this.tab = this.getTabUsingSlug(this.args.tab);
99
+ applyContextComponentArguments(this);
45
100
  }
46
101
 
47
- applyDynamicArguments() {
48
- // Apply context if available
49
- if (this.args.context) {
50
- this.vehicle = this.args.context;
51
- }
102
+ /**
103
+ * Sets the overlay context.
104
+ *
105
+ * @action
106
+ * @param {OverlayContextObject} overlayContext
107
+ */
108
+ @action setOverlayContext(overlayContext) {
109
+ this.context = overlayContext;
110
+ contextComponentCallback(this, 'onLoad', ...arguments);
111
+ }
52
112
 
53
- // Apply dynamic arguments if available
54
- if (this.args.dynamicArgs) {
55
- const keys = Object.keys(this.args.dynamicArgs);
113
+ /**
114
+ * Handles changing the active tab.
115
+ *
116
+ * @method
117
+ * @param {String} tab - The new tab to switch to.
118
+ * @action
119
+ */
120
+ @action onTabChanged(tab) {
121
+ this.tab = this.getTabUsingSlug(tab);
122
+ contextComponentCallback(this, 'onTabChanged', tab);
123
+ }
124
+
125
+ /**
126
+ * Handles edit action for the vehicle.
127
+ *
128
+ * @method
129
+ * @action
130
+ */
131
+ @action onEdit() {
132
+ const isActionOverrided = contextComponentCallback(this, 'onEdit', this.vehicle);
56
133
 
57
- keys.forEach((key) => {
58
- this[key] = this.args.dynamicArgs[key];
134
+ if (!isActionOverrided) {
135
+ this.contextPanel.focus(this.vehicle, 'editing', {
136
+ onAfterSave: () => {
137
+ this.contextPanel.clear();
138
+ },
59
139
  });
60
140
  }
61
141
  }
62
142
 
63
- @action async changeTab(tab = 'details') {
64
- this.currentTab = tab;
143
+ /**
144
+ * Handles the cancel action.
145
+ *
146
+ * @method
147
+ * @action
148
+ * @returns {Boolean} Indicates whether the cancel action was overridden.
149
+ */
150
+ @action onPressCancel() {
151
+ return contextComponentCallback(this, 'onPressCancel', this.vehicle);
152
+ }
65
153
 
66
- if (typeof this.args.onTabChanged === 'function') {
67
- this.args.onTabChanged(tab);
154
+ /**
155
+ * Finds and returns a tab based on its slug.
156
+ *
157
+ * @param {String} tabSlug - The slug of the tab.
158
+ * @returns {Object|null} The found tab or null.
159
+ */
160
+ getTabUsingSlug(tabSlug) {
161
+ if (tabSlug) {
162
+ return this.tabs.find(({ slug }) => slug === tabSlug);
68
163
  }
69
- }
70
164
 
71
- @action editVehicle() {
72
- this.contextPanel.focus(this.vehicle, 'editing');
165
+ return this.tabs[0];
73
166
  }
74
167
  }
@@ -1,8 +1,61 @@
1
1
  import Controller from '@ember/controller';
2
+ import { tracked } from '@glimmer/tracking';
2
3
  import { action } from '@ember/object';
3
4
 
5
+ /**
6
+ * Controller for managing the details view within the "Management -> Drivers -> Index" route.
7
+ *
8
+ * @class ManagementDriversIndexDetailsController
9
+ * @extends Controller
10
+ */
4
11
  export default class ManagementDriverIndexDetailsController extends Controller {
12
+ /**
13
+ * The currently active view tab ('details' by default).
14
+ *
15
+ * @type {String}
16
+ * @tracked
17
+ */
18
+ @tracked view = 'details';
19
+
20
+ /**
21
+ * An array of query parameters to be serialized in the URL.
22
+ *
23
+ * @type {String[]}
24
+ * @tracked
25
+ */
26
+ @tracked queryParams = ['view'];
27
+
28
+ /**
29
+ * Transitions back to the "management.drivers.index" route.
30
+ *
31
+ * @method
32
+ * @action
33
+ * @returns {Transition} The transition object representing the route change.
34
+ */
5
35
  @action transitionBack() {
6
36
  return this.transitionToRoute('management.drivers.index');
7
37
  }
38
+
39
+ /**
40
+ * Transitions to the edit view for a specific vehicle.
41
+ *
42
+ * @method
43
+ * @param {DriverModel} driver - The vehicle to be edited.
44
+ * @action
45
+ * @returns {Transition} The transition object representing the route change.
46
+ */
47
+ @action onEdit(driver) {
48
+ return this.transitionToRoute('management.drivers.index.edit', driver);
49
+ }
50
+
51
+ /**
52
+ * Updates the active view tab.
53
+ *
54
+ * @method
55
+ * @param {String} tab - The name of the tab to activate.
56
+ * @action
57
+ */
58
+ @action onTabChanged(tab) {
59
+ this.view = tab;
60
+ }
8
61
  }
@@ -5,76 +5,107 @@ import { action } from '@ember/object';
5
5
 
6
6
  export default class ManagementDriversIndexEditController extends Controller {
7
7
  /**
8
- * True if updating service rate.
8
+ * Inject the `hostRouter` service
9
9
  *
10
- * @var {Boolean}
10
+ * @memberof ManagementDriversIndexEditController
11
11
  */
12
- @tracked isUpdatingDriver = false;
12
+ @service hostRouter;
13
+
13
14
  /**
14
- * Inject the `loader` service
15
+ * Inject the `hostRouter` service
15
16
  *
16
- * @var {Service}
17
+ * @memberof ManagementDriversIndexEditController
17
18
  */
18
- @service loader;
19
+ @service modalsManager;
20
+
19
21
  /**
20
- * Inject the `notifications` service
22
+ * The overlay component context.
21
23
  *
22
- * @var {Service}
24
+ * @memberof ManagementDriversIndexEditController
23
25
  */
24
- @service notifications;
26
+ @tracked overlay;
27
+
25
28
  /**
26
- * Inject the `hostRouter` service
29
+ * When exiting the overlay.
27
30
  *
28
- * @var {Service}
31
+ * @return {Transition}
32
+ * @memberof ManagementDriversIndexEditController
29
33
  */
30
- @service hostRouter;
34
+ @action transitionBack(driver) {
35
+ // check if driver record has been edited and prompt for confirmation
36
+ if (driver.hasDirtyAttributes) {
37
+ return this.confirmContinueWithUnsavedChanges(driver, {
38
+ confirm: () => {
39
+ driver.rollbackAttributes();
40
+ return this.transitionToRoute('management.drivers.index');
41
+ },
42
+ });
43
+ }
44
+
45
+ return this.transitionToRoute('management.drivers.index');
46
+ }
47
+
31
48
  /**
32
- * Inject the `currentUser` service
49
+ * Set the overlay component context object.
33
50
  *
34
- * @var {Service}
51
+ * @param {OverlayContext} overlay
52
+ * @memberof ManagementDriversIndexEditController
35
53
  */
36
- @service store;
54
+ @action setOverlayContext(overlay) {
55
+ this.overlay = overlay;
56
+ }
57
+
37
58
  /**
38
- * Updates the drivers to server
59
+ * When driver details button is clicked in overlay.
39
60
  *
40
- * @void
61
+ * @param {VehicleModel} driver
62
+ * @return {Promise}
63
+ * @memberof ManagementDriversIndexEditController
41
64
  */
42
- @action updateDriver() {
43
- const { driver } = this;
65
+ @action onViewDetails(driver) {
66
+ // check if driver record has been edited and prompt for confirmation
67
+ if (driver.hasDirtyAttributes) {
68
+ return this.confirmContinueWithUnsavedChanges(driver);
69
+ }
44
70
 
45
- this.isUpdatingDriver = true;
46
- this.loader.showLoader('.overlay-inner-content', 'Updating driver...');
71
+ return this.transitionToRoute('management.drivers.index.details', driver);
72
+ }
47
73
 
48
- try {
49
- return driver
50
- .save()
51
- .then((driver) => {
52
- return this.transitionToRoute('management.drivers.index').then(() => {
53
- this.notifications.success(`Driver '${driver.name}' updated`);
54
- this.resetForm();
55
- this.hostRouter.refresh();
56
- });
57
- })
58
- .catch(this.notifications.serverError)
59
- .finally(() => {
60
- this.isUpdatingDriver = false;
61
- this.loader.removeLoader();
62
- });
63
- } catch (error) {
64
- this.isUpdatingDriver = false;
65
- this.loader.removeLoader();
74
+ /**
75
+ * Trigger a route refresh and focus the new driver created.
76
+ *
77
+ * @param {VehicleModel} driver
78
+ * @return {Promise}
79
+ * @memberof ManagementDriversIndexEditController
80
+ */
81
+ @action onAfterSave(driver) {
82
+ if (this.overlay) {
83
+ this.overlay.close();
66
84
  }
67
- }
68
85
 
69
- @action transitionBack() {
70
- return this.transitionToRoute('management.drivers.index');
86
+ this.hostRouter.refresh();
87
+ return this.transitionToRoute('management.drivers.index.details', driver);
71
88
  }
89
+
72
90
  /**
73
- * Resets the driver form
91
+ * Prompts the user to confirm if they wish to continue with unsaved changes.
74
92
  *
75
- * @void
93
+ * @method
94
+ * @param {VehicleModel} driver - The driver object with unsaved changes.
95
+ * @param {Object} [options={}] - Additional options for configuring the modal.
96
+ * @returns {Promise} A promise that resolves when the user confirms, and transitions to a new route.
97
+ * @memberof ManagementDriversIndexEditController
76
98
  */
77
- @action resetForm() {
78
- this.driver = this.store.createRecord('driver');
99
+ confirmContinueWithUnsavedChanges(driver, options = {}) {
100
+ return this.modalsManager.confirm({
101
+ title: 'Continue Without Saving?',
102
+ body: 'Unsaved changes to this driver will be lost. Click continue to proceed.',
103
+ acceptButtonText: 'Continue without saving',
104
+ confirm: () => {
105
+ driver.rollbackAttributes();
106
+ return this.transitionToRoute('management.drivers.index.details', driver);
107
+ },
108
+ ...options,
109
+ });
79
110
  }
80
111
  }