diff --git a/addon/components/activity-form-panel.hbs b/addon/components/activity-form-panel.hbs index c6e5cb51..93e67fc8 100644 --- a/addon/components/activity-form-panel.hbs +++ b/addon/components/activity-form-panel.hbs @@ -1,7 +1,7 @@
-
diff --git a/addon/components/activity-form-panel.js b/addon/components/activity-form-panel.js index 55e79225..1c3f20c8 100644 --- a/addon/components/activity-form-panel.js +++ b/addon/components/activity-form-panel.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; import { underscore, capitalize, w } from '@ember/string'; +import { task } from 'ember-concurrency'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; @@ -42,14 +43,14 @@ export default class ActivityFormPanelComponent extends Component { } /** - * Action method to save the activity. It triggers an optional onSave callback + * Task to save the activity. It triggers an optional onSave callback * with the current state of the activity. - * @action + * @task */ - @action save() { + @task *save() { contextComponentCallback(this, 'onSave', this.customEntity); if (typeof this.onSave === 'function') { - this.onSave(this.activity); + yield this.onSave(this.activity); } } diff --git a/addon/components/cell/driver-name.hbs b/addon/components/cell/driver-name.hbs index ab61be45..e7b24fb0 100644 --- a/addon/components/cell/driver-name.hbs +++ b/addon/components/cell/driver-name.hbs @@ -1,8 +1,19 @@ {{#if this.driver}}
{{this.driver.name}} - + {{get-default-value this.driver.name}} + {{#if @row.vehicle_assigned}} +
+ + {{n-a @row.vehicle_assigned.display_name}} +
+ {{else if this.driver.vehicle}} +
+ + {{n-a this.driver.vehicle_name}} +
+ {{/if}}
diff --git a/addon/components/cell/vehicle-name.hbs b/addon/components/cell/vehicle-name.hbs new file mode 100644 index 00000000..c448a41a --- /dev/null +++ b/addon/components/cell/vehicle-name.hbs @@ -0,0 +1,17 @@ +
+ {{this.altText}} + + + {{#if (has-block)}} + {{yield}} + {{else}} + + {{n-a @value}} + + {{/if}} + + + {{#if @column.showOnlineIndicator}} + + {{/if}} +
\ No newline at end of file diff --git a/addon/components/cell/vehicle-name.js b/addon/components/cell/vehicle-name.js new file mode 100644 index 00000000..6cad6218 --- /dev/null +++ b/addon/components/cell/vehicle-name.js @@ -0,0 +1,3 @@ +import TableCellMediaNameComponent from '@fleetbase/ember-ui/components/table/cell/media-name'; + +export default class CellVehicleNameComponent extends TableCellMediaNameComponent {} diff --git a/addon/components/contact-form-panel.hbs b/addon/components/contact-form-panel.hbs index 553cb7e0..cd6802f5 100644 --- a/addon/components/contact-form-panel.hbs +++ b/addon/components/contact-form-panel.hbs @@ -18,7 +18,7 @@
-
diff --git a/addon/components/contact-form-panel.js b/addon/components/contact-form-panel.js index f2874d64..5cfdc4e6 100644 --- a/addon/components/contact-form-panel.js +++ b/addon/components/contact-form-panel.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; +import { task } from 'ember-concurrency'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; @@ -10,6 +11,7 @@ export default class ContactFormPanelComponent extends Component { * @service store */ @service store; + /** * @service intl */ @@ -35,11 +37,6 @@ export default class ContactFormPanelComponent extends Component { */ @service hostRouter; - /** - * @service loader - */ - @service loader; - /** * @service contextPanel */ @@ -51,12 +48,6 @@ export default class ContactFormPanelComponent extends Component { */ @tracked context; - /** - * Indicates whether the component is in a loading state. - * @type {boolean} - */ - @tracked isLoading = false; - /** * All possible contact types. * @@ -92,37 +83,23 @@ export default class ContactFormPanelComponent extends Component { } /** - * Saves the contact changes. + * Task to save contact. * - * @action - * @returns {Promise} + * @return {void} + * @memberof ContactFormPanelComponent */ - @action save() { - const { contact } = this; - - this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving contact...', preserveTargetPosition: true }); - this.isLoading = true; - - contextComponentCallback(this, 'onBeforeSave', contact); + @task *save() { + contextComponentCallback(this, 'onBeforeSave', this.contact); try { - return contact - .save() - .then((contact) => { - this.notifications.success(this.intl.t('fleet-ops.component.contact-form-panel.success-message', { contactName: contact.name })); - contextComponentCallback(this, 'onAfterSave', contact); - }) - .catch((error) => { - this.notifications.serverError(error); - }) - .finally(() => { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; - }); + this.contact = yield this.contact.save(); } catch (error) { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; + this.notifications.serverError(error); + return; } + + this.notifications.success(this.intl.t('fleet-ops.component.contact-form-panel.success-message', { contactName: this.contact.name })); + contextComponentCallback(this, 'onAfterSave', this.contact); } /** diff --git a/addon/components/contact-panel/details.hbs b/addon/components/contact-panel/details.hbs index c70aa1c7..364fbd51 100644 --- a/addon/components/contact-panel/details.hbs +++ b/addon/components/contact-panel/details.hbs @@ -2,34 +2,34 @@
-
+
{{t "fleet-ops.component.contact-panel.details.web-url"}}
{{n-a @contact.name}}
-
+
{{t "fleet-ops.common.title"}}
{{n-a @contact.title}}
-
+
{{t "fleet-ops.common.internal-id"}}
{{n-a @contact.internal_id}}
-
+
{{t "fleet-ops.common.email"}}
{{n-a @contact.email}}
-
+
{{t "fleet-ops.common.email"}}
{{n-a @contact.phone}}
-
+
{{t "fleet-ops.common.type"}}
-
+
{{@contact.type}}
diff --git a/addon/components/custom-field-form-panel.js b/addon/components/custom-field-form-panel.js index c3ec5819..8cda001e 100644 --- a/addon/components/custom-field-form-panel.js +++ b/addon/components/custom-field-form-panel.js @@ -63,17 +63,19 @@ export default class CustomFieldFormPanelComponent extends Component { * @task */ @task *save() { - yield this.customField - .save() - .then((customField) => { - if (typeof this.onCustomFieldSaved === 'function') { - this.onCustomFieldSaved(customField); - } - contextComponentCallback(this, 'onCustomFieldSaved', customField); - }) - .catch((error) => { - this.notifications.serverError(error); - }); + contextComponentCallback(this, 'onBeforeCustomFieldSaved', this.customField); + + try { + this.customField = yield this.customField.save(); + } catch (error) { + this.notifications.serverError(error); + return; + } + + if (typeof this.onCustomFieldSaved === 'function') { + this.onCustomFieldSaved(this.customField); + } + contextComponentCallback(this, 'onCustomFieldSaved', this.customField); } /** diff --git a/addon/components/driver-form-panel.hbs b/addon/components/driver-form-panel.hbs index 0541a614..f57e2f05 100644 --- a/addon/components/driver-form-panel.hbs +++ b/addon/components/driver-form-panel.hbs @@ -8,7 +8,7 @@
-
@@ -54,7 +54,7 @@
- + {{if this.driver.online "Online" "Offline"}}
diff --git a/addon/components/driver-form-panel.js b/addon/components/driver-form-panel.js index 1c2cea4d..6276806b 100644 --- a/addon/components/driver-form-panel.js +++ b/addon/components/driver-form-panel.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; +import { task } from 'ember-concurrency'; import Point from '@fleetbase/fleetops-data/utils/geojson/point'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; @@ -37,11 +38,6 @@ export default class DriverFormPanelComponent extends Component { */ @service hostRouter; - /** - * @service loader - */ - @service loader; - /** * @service contextPanel */ @@ -64,12 +60,6 @@ export default class DriverFormPanelComponent extends Component { */ @tracked driverStatusOptions = ['active', 'pending']; - /** - * Indicates whether the component is in a loading state. - * @type {boolean} - */ - @tracked isLoading = false; - /** * The coordinates input component instance. * @type {CoordinateInputComponent} @@ -151,32 +141,23 @@ export default class DriverFormPanelComponent extends Component { } /** - * Saves the driver changes. + * Task to save driver. * - * @action - * @returns {Promise} + * @return {void} + * @memberof DriverFormPanelComponent */ - @action save() { - const { driver } = this; + @task *save() { + contextComponentCallback(this, 'onBeforeSave', this.driver); - this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving driver...', preserveTargetPosition: true }); - this.isLoading = true; - - contextComponentCallback(this, 'onBeforeSave', driver); + try { + this.driver = yield this.driver.save(); + } catch (error) { + this.notifications.serverError(error); + return; + } - return driver - .save() - .then((driver) => { - this.notifications.success(this.intl.t('fleet-ops.component.driver-form-panel.success-message', { driverName: driver.name })); - contextComponentCallback(this, 'onAfterSave', driver); - }) - .catch((error) => { - this.notifications.serverError(error); - }) - .finally(() => { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; - }); + this.notifications.success(this.intl.t('fleet-ops.component.driver-form-panel.success-message', { driverName: this.driver.name })); + contextComponentCallback(this, 'onAfterSave', this.driver); } /** diff --git a/addon/components/driver-onboard-settings.js b/addon/components/driver-onboard-settings.js index 1c7408b5..4023cfc4 100644 --- a/addon/components/driver-onboard-settings.js +++ b/addon/components/driver-onboard-settings.js @@ -7,6 +7,7 @@ import { task } from 'ember-concurrency-decorators'; export default class DriverOnboardSettingsComponent extends Component { @service fetch; @service currentUser; + @service notifications; @tracked companyId; @tracked driverOnboardSettingsLoaded = false; @tracked driverOnboardSettings = {}; @@ -37,8 +38,18 @@ export default class DriverOnboardSettingsComponent extends Component { @task *saveDriverOnboardSettings() { const { driverOnboardSettings } = this; - const driverOnboardSettingsResponse = yield this.fetch.post('fleet-ops/settings/driver-onboard-settings', { driverOnboardSettings }); - if (driverOnboardSettings?.enableDriverOnboardFromApp == false) this.driverOnboardSettings = driverOnboardSettingsResponse?.driverOnboardSettings; + let driverOnboardSettingsResponse; + + try { + driverOnboardSettingsResponse = yield this.fetch.post('fleet-ops/settings/driver-onboard-settings', { driverOnboardSettings }); + } catch (error) { + this.notifications.serverError(error); + return; + } + + if (driverOnboardSettingsResponse && driverOnboardSettings && driverOnboardSettings.enableDriverOnboardFromApp == false) { + this.driverOnboardSettings = driverOnboardSettingsResponse.driverOnboardSettings; + } } @task *getDriverOnboardSettings() { diff --git a/addon/components/driver-panel.hbs b/addon/components/driver-panel.hbs index 18c9e0cc..a5038a95 100644 --- a/addon/components/driver-panel.hbs +++ b/addon/components/driver-panel.hbs @@ -59,7 +59,7 @@
- + {{if this.driver.online "Online" "Offline"}}
diff --git a/addon/components/driver-panel.js b/addon/components/driver-panel.js index 6bba5901..653e248e 100644 --- a/addon/components/driver-panel.js +++ b/addon/components/driver-panel.js @@ -4,6 +4,7 @@ import { action } from '@ember/object'; import { inject as service } from '@ember/service'; import { isArray } from '@ember/array'; import DriverPanelDetailComponent from './driver-panel/details'; +import DriverPanelOrdersComponent from './driver-panel/orders'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; @@ -74,8 +75,10 @@ export default class DriverPanelComponent extends Component { get tabs() { const registeredTabs = this.universe.getMenuItemsFromRegistry('component:driver-panel'); // this.universe._createMenuItem('Tracking', null, { icon: 'satellite-dish', component: DriverPanelTrackingComponent }), - const defaultTabs = [this.universe._createMenuItem('Details', null, { icon: 'circle-info', component: DriverPanelDetailComponent })]; - + const defaultTabs = [ + this.universe._createMenuItem('Details', null, { icon: 'circle-info', component: DriverPanelDetailComponent }), + this.universe._createMenuItem('Orders', null, { icon: 'bars-progress', component: DriverPanelOrdersComponent }), + ]; if (isArray(registeredTabs)) { return [...defaultTabs, ...registeredTabs]; } diff --git a/addon/components/driver-panel/details.hbs b/addon/components/driver-panel/details.hbs index bf559292..e0bc4962 100644 --- a/addon/components/driver-panel/details.hbs +++ b/addon/components/driver-panel/details.hbs @@ -6,11 +6,11 @@
{{t "fleet-ops.common.name"}}
{{n-a @driver.name}}
-
+
{{t "fleet-ops.common.email"}}
{{n-a @driver.email}}
-
+
{{t "fleet-ops.common.phone"}}
{{n-a @driver.phone}}
@@ -18,23 +18,23 @@
-
+
{{t "fleet-ops.common.id"}}
{{n-a @driver.public_id}}
-
+
{{t "fleet-ops.common.internal-id"}}
{{n-a @driver.internal_id}}
-
+
{{t "fleet-ops.common.driver-license"}}
{{n-a @driver.drivers_license_number}}
-
+
{{t "fleet-ops.common.city"}}
{{n-a @driver.city}}
-
+
{{t "fleet-ops.common.country"}}
diff --git a/addon/components/driver-panel/orders.hbs b/addon/components/driver-panel/orders.hbs new file mode 100644 index 00000000..d34b3c72 --- /dev/null +++ b/addon/components/driver-panel/orders.hbs @@ -0,0 +1,122 @@ + + {{#unless this.queryOrders.isIdle}} +
+ +
+ {{/unless}} +
+ + +
+ {{#each this.orders as |order|}} +
+
+
+
+ + + +
+
+
{{order.public_id}}
+
{{order.createdAt}}
+
+
+
+ + {{n-a (humanize order.type)}} +
+
+
+
+
+ {{#if order.isMultipleDropoffOrder}} +
{{pluralize (t "fleet-ops.operations.orders.index.view.customer")}}
+
+ {{#each order.payload.waypoints as |waypoint|}} +
+ {{waypoint.customer.name}} +
{{waypoint.customer.name}}
+ + +
{{n-a waypoint.customer.name "No Customer"}}
+ {{#if waypoint.customer}} +
{{n-a waypoint.customer.phone "No Phone"}}
+ {{/if}} +
+
+
+ {{/each}} +
+ {{else}} +
{{t "fleet-ops.operations.orders.index.view.customer"}}
+
+
+ {{order.customer.name}} +
+
+
{{n-a order.customer.name "No Customer"}}
+ {{#if order.customer}} +
{{n-a order.customer.phone "No Phone"}}
+ {{/if}} +
+
+ {{/if}} +
+
+
{{t "fleet-ops.operations.orders.index.view.facilitator"}}
+
+
+ {{order.facilitator.name}} +
+
+
{{n-a order.facilitator.name "No Facilitator"}}
+ {{#if order.facilitator}} +
{{n-a order.facilitator.phone "No Phone"}}
+ {{/if}} +
+
+
+
+
+ {{t "fleet-ops.operations.orders.index.view.vehicle-assigned"}} +
+ +
+
+
{{t "fleet-ops.operations.orders.index.view.tracking-number"}}
+
{{n-a order.tracking_number.tracking_number}}
+
+
+
{{t "fleet-ops.common.internal-id"}}
+
{{n-a order.internal_id}}
+
+ {{#if order.pod_required}} +
+
{{t "fleet-ops.operations.orders.index.view.proof-of-delivery"}}
+
{{n-a (smart-humanize order.pod_method)}}
+
+ {{/if}} +
+
{{t "fleet-ops.operations.orders.index.view.date-started"}}
+
{{n-a order.startedAt}}
+
+
+ +
+
+
+
+ {{/each}} +
+ +
\ No newline at end of file diff --git a/addon/components/driver-panel/orders.js b/addon/components/driver-panel/orders.js new file mode 100644 index 00000000..aed42cac --- /dev/null +++ b/addon/components/driver-panel/orders.js @@ -0,0 +1,44 @@ +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { inject as service } from '@ember/service'; +import { action, computed } from '@ember/object'; +import { task } from 'ember-concurrency-decorators'; + +export default class CustomerOrderHistoryComponent extends Component { + @service store; + @service fetch; + @service intl; + @service hostRouter; + @tracked orders = []; + @tracked driver; + + @computed('args.title') get title() { + return this.args.title ?? this.intl.t('fleetops.component.widget.orders.widget-title'); + } + + constructor() { + super(...arguments); + this.driver = this.args.driver; + this.queryOrders.perform(); + } + + @task *queryOrders(params = {}) { + try { + this.orders = yield this.store.query('order', { + driver_assigned_uuid: this.driver.id, + sort: '-created_at', + ...params, + }); + } catch (error) { + this.notifications.serverError('error', error); + } + } + + @action search(event) { + this.queryOrders.perform({ query: event.target.value ?? '' }); + } + + @action async viewOrder(order) { + this.hostRouter.transitionTo('console.fleet-ops.operations.orders.index.view', order); + } +} diff --git a/addon/components/edit-order-route-panel.js b/addon/components/edit-order-route-panel.js index 7d09a0d4..81e6e201 100644 --- a/addon/components/edit-order-route-panel.js +++ b/addon/components/edit-order-route-panel.js @@ -88,11 +88,17 @@ export default class EditOrderRoutePanelComponent extends Component { contextComponentCallback(this, 'onLoad', ...arguments); } + /** + * Task to save order route. + * + * @return {void} + * @memberof EditOrderRoutePanelComponent + */ @task *save() { const { payload } = this.order; - yield this.fetch - .patch( + try { + this.order = yield this.fetch.patch( `orders/route/${this.order.id}`, { pickup: payload.pickup, @@ -104,14 +110,14 @@ export default class EditOrderRoutePanelComponent extends Component { normalizeToEmberData: true, normalizeModelType: 'order', } - ) - .then((order) => { - this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.view.update-success', { orderId: order.public_id })); - contextComponentCallback(this, 'onAfterSave', order); - }) - .catch((error) => { - this.notifications.serverError(error); - }); + ); + } catch (error) { + this.notifications.serverError(error); + return; + } + + this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.view.update-success', { orderId: this.order.public_id })); + contextComponentCallback(this, 'onAfterSave', this.order); } _serializeWaypoints(waypoints = []) { diff --git a/addon/components/entity-field-editing-settings.hbs b/addon/components/entity-field-editing-settings.hbs index 05c43ecf..042cb00e 100644 --- a/addon/components/entity-field-editing-settings.hbs +++ b/addon/components/entity-field-editing-settings.hbs @@ -54,7 +54,7 @@
{{#if orderConfigEntityEditingSettings.is_editable}} -
+
{{#let (get (get this.entityEditingSettings this.selectedOrderConfig.id) "editable_entity_fields") as |editableEntityFields|}} {{#each this.entityFields as |entityField|}}
diff --git a/addon/components/fleet-form-panel.hbs b/addon/components/fleet-form-panel.hbs index 6868c94f..312389ff 100644 --- a/addon/components/fleet-form-panel.hbs +++ b/addon/components/fleet-form-panel.hbs @@ -17,7 +17,7 @@ @titleWrapperClass="leading-5" >
-
diff --git a/addon/components/place-form-panel.js b/addon/components/place-form-panel.js index b18e5dcc..e18ff209 100644 --- a/addon/components/place-form-panel.js +++ b/addon/components/place-form-panel.js @@ -3,6 +3,7 @@ import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; import { isBlank } from '@ember/utils'; +import { task } from 'ember-concurrency'; import Point from '@fleetbase/fleetops-data/utils/geojson/point'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; @@ -33,11 +34,6 @@ export default class PlaceFormPanelComponent extends Component { */ @service hostRouter; - /** - * @service loader - */ - @service loader; - /** * @service contextPanel */ @@ -49,12 +45,6 @@ export default class PlaceFormPanelComponent extends Component { */ @tracked context; - /** - * Indicates whether the component is in a loading state. - * @type {boolean} - */ - @tracked isLoading = false; - /** * The coordinates input component instance. * @type {CoordinateInputComponent} @@ -89,37 +79,23 @@ export default class PlaceFormPanelComponent extends Component { } /** - * Saves the place changes. + * Task to save place. * - * @action - * @returns {Promise} + * @return {void} + * @memberof PlaceFormPanelComponent */ - @action save() { - const { place } = this; - - this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving place...', preserveTargetPosition: true }); - this.isLoading = true; - - contextComponentCallback(this, 'onBeforeSave', place); + @task *save() { + contextComponentCallback(this, 'onBeforeSave', this.place); try { - return place - .save() - .then((place) => { - this.notifications.success(this.intl.t('fleet-ops.component.place-form-panel.success-message', { placeAddress: place.address })); - contextComponentCallback(this, 'onAfterSave', place); - }) - .catch((error) => { - this.notifications.serverError(error); - }) - .finally(() => { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; - }); + this.place = yield this.place.save(); } catch (error) { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; + this.notifications.serverError(error); + return; } + + this.notifications.success(this.intl.t('fleet-ops.component.place-form-panel.success-message', { placeAddress: this.place.address })); + contextComponentCallback(this, 'onAfterSave', this.place); } /** diff --git a/addon/components/place-panel/details.hbs b/addon/components/place-panel/details.hbs index d98d8243..f5d8ba50 100644 --- a/addon/components/place-panel/details.hbs +++ b/addon/components/place-panel/details.hbs @@ -31,39 +31,39 @@
{{n-a @place.street1}}
-
+
{{t "fleet-ops.common.neighborhood"}}
{{n-a @place.neighborhood}}
-
+
{{t "fleet-ops.common.building"}}
{{n-a @place.building}}
-
+
{{t "fleet-ops.common.security-access-code"}}
{{n-a @place.security_access_code}}
-
+
{{t "fleet-ops.common.city"}}
{{n-a @place.city}}
-
+
{{t "fleet-ops.common.state"}}
{{n-a @place.province}}
-
+
{{t "fleet-ops.common.country"}}
-
+
{{t "fleet-ops.common.phone"}}
{{n-a @place.phone}}
diff --git a/addon/components/route-list.hbs b/addon/components/route-list.hbs index 38c0f5f8..bdb42b93 100644 --- a/addon/components/route-list.hbs +++ b/addon/components/route-list.hbs @@ -1,47 +1,70 @@
- {{#if @order.payload.firstWaypoint}} -
-
-
1
-
-
- + {{#if @order.isMultipleDropoffOrder}} + {{#if @order.payload.firstWaypoint}} +
+
+
1
+
+
+ +
-
- {{/if}} + {{/if}} - {{#if (gt @order.payload.waypoints.length 2)}} - - {{#unless this.isWaypointsCollapsed}} - {{#each @order.payload.middleWaypoints as |waypoint index|}} -
-
-
{{add index 2}}
-
-
- + {{#if (gt @order.payload.waypoints.length 2)}} + + {{#unless this.isWaypointsCollapsed}} + {{#each @order.payload.middleWaypoints as |waypoint index|}} +
+
+
{{add index 2}}
+
+
+ +
+
+ {{/each}} + {{/unless}} + {{/if}} - {{#if @order.payload.lastWaypoint}} -
-
-
{{add @order.payload.middleWaypoints.length 2}}
+ {{#if @order.payload.lastWaypoint}} +
+
+
{{add @order.payload.middleWaypoints.length 2}}
+
+
+ +
-
- + {{/if}} + {{else}} + {{#if @order.payload.pickup}} +
+
+
1
+
+
+ +
+
+ {{/if}} + {{#if @order.payload.dropoff}} +
+
+
2
+
+
+ +
-
+ {{/if}} {{/if}}
\ No newline at end of file diff --git a/addon/components/vehicle-form-panel.hbs b/addon/components/vehicle-form-panel.hbs index 50b7c1ed..31bf0c0b 100644 --- a/addon/components/vehicle-form-panel.hbs +++ b/addon/components/vehicle-form-panel.hbs @@ -8,7 +8,7 @@
-
diff --git a/addon/components/vehicle-form-panel.js b/addon/components/vehicle-form-panel.js index 2c033c39..0a30ccb1 100644 --- a/addon/components/vehicle-form-panel.js +++ b/addon/components/vehicle-form-panel.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; +import { task } from 'ember-concurrency'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; import Point from '@fleetbase/fleetops-data/utils/geojson/point'; @@ -37,11 +38,6 @@ export default class VehicleFormPanelComponent extends Component { */ @service hostRouter; - /** - * @service loader - */ - @service loader; - /** * @service contextPanel */ @@ -53,12 +49,6 @@ export default class VehicleFormPanelComponent extends Component { */ @tracked context; - /** - * Indicates whether the component is in a loading state. - * @type {boolean} - */ - @tracked isLoading = false; - /** * Status options for vehicles. * @type {Array} @@ -113,37 +103,23 @@ export default class VehicleFormPanelComponent extends Component { } /** - * Saves the vehicle changes. + * Task to save vehicle. * - * @action - * @returns {Promise} + * @return {void} + * @memberof VehicleFormPanelComponent */ - @action save() { - const { vehicle } = this; - - this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving vehicle...', preserveTargetPosition: true }); - this.isLoading = true; - - contextComponentCallback(this, 'onBeforeSave', vehicle); + @task *save() { + contextComponentCallback(this, 'onBeforeSave', this.vehicle); try { - return vehicle - .save() - .then((vehicle) => { - this.notifications.success(this.intl.t('fleet-ops.component.vehicle-form-panel.success-message', { vehicleName: vehicle.displayName })); - contextComponentCallback(this, 'onAfterSave', vehicle); - }) - .catch((error) => { - this.notifications.serverError(error); - }) - .finally(() => { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; - }); + this.vehicle = yield this.vehicle.save(); } catch (error) { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; + this.notifications.serverError(error); + return; } + + this.notifications.success(this.intl.t('fleet-ops.component.vehicle-form-panel.success-message', { vehicleName: this.vehicle.displayName })); + contextComponentCallback(this, 'onAfterSave', this.vehicle); } /** diff --git a/addon/components/vehicle-panel/details.hbs b/addon/components/vehicle-panel/details.hbs index cda573b4..17fd3b61 100644 --- a/addon/components/vehicle-panel/details.hbs +++ b/addon/components/vehicle-panel/details.hbs @@ -1,27 +1,27 @@
-
+
{{t "fleet-ops.common.name"}}
{{n-a @vehicle.display_name}}
-
+
{{t "fleet-ops.common.plate-number"}}
{{n-a @vehicle.plate_number}}
-
+
{{t "fleet-ops.common.vin-number"}}
{{n-a @vehicle.vin}}
-
+
{{t "fleet-ops.common.make"}}
{{n-a @vehicle.make}}
-
+
{{t "fleet-ops.common.model"}}
{{n-a @vehicle.model}}
-
+
{{t "fleet-ops.common.year"}}
{{n-a @vehicle.year}}
diff --git a/addon/components/vendor-form-panel.hbs b/addon/components/vendor-form-panel.hbs index c75f3fd5..c4dce935 100644 --- a/addon/components/vendor-form-panel.hbs +++ b/addon/components/vendor-form-panel.hbs @@ -1,14 +1,4 @@ - +
@@ -18,7 +8,7 @@
-
@@ -33,15 +23,7 @@
- +
@@ -73,19 +55,9 @@ {{#if this.isEditing}} - + {{else}} - + {{/if}} diff --git a/addon/components/vendor-form-panel.js b/addon/components/vendor-form-panel.js index 9c6dcaae..510675b7 100644 --- a/addon/components/vendor-form-panel.js +++ b/addon/components/vendor-form-panel.js @@ -2,6 +2,7 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; +import { task } from 'ember-concurrency'; import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback'; import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments'; import getVendorTypeOptions from '../utils/get-vendor-type-options'; @@ -38,11 +39,6 @@ export default class VendorFormPanelComponent extends Component { */ @service hostRouter; - /** - * @service loader - */ - @service loader; - /** * @service contextPanel */ @@ -54,12 +50,6 @@ export default class VendorFormPanelComponent extends Component { */ @tracked context; - /** - * Indicates whether the component is in a loading state. - * @type {boolean} - */ - @tracked isLoading = false; - /** * The users vendor instance. * @type {VendorModel|IntegratedVendorModel} @@ -102,37 +92,23 @@ export default class VendorFormPanelComponent extends Component { } /** - * Saves the vendor changes. + * Task to save vendor. * - * @action - * @returns {Promise} + * @return {void} + * @memberof VendorFormPanelComponent */ - @action save() { - const { vendor } = this; - - this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving vendor...', preserveTargetPosition: true }); - this.isLoading = true; - - contextComponentCallback(this, 'onBeforeSave', vendor); + @task *save() { + contextComponentCallback(this, 'onBeforeSave', this.vendor); try { - return vendor - .save() - .then((vendor) => { - this.notifications.success(this.intl.t('fleet-ops.component.vendor-form-panel.success-message', { vendorName: vendor.displayName })); - contextComponentCallback(this, 'onAfterSave', vendor); - }) - .catch((error) => { - this.notifications.serverError(error); - }) - .finally(() => { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; - }); + this.vendor = yield this.vendor.save(); } catch (error) { - this.loader.removeLoader('.next-content-overlay-panel-container '); - this.isLoading = false; + this.notifications.serverError(error); + return; } + + this.notifications.success(this.intl.t('fleet-ops.component.vendor-form-panel.success-message', { vendorName: this.vendor.name })); + contextComponentCallback(this, 'onAfterSave', this.vendor); } /** diff --git a/addon/components/vendor-form-panel/create-form.hbs b/addon/components/vendor-form-panel/create-form.hbs index 0b56d9b6..740d7838 100644 --- a/addon/components/vendor-form-panel/create-form.hbs +++ b/addon/components/vendor-form-panel/create-form.hbs @@ -2,14 +2,7 @@
- + {{vendorType.label}}
@@ -17,14 +10,7 @@ {{#if (eq this.selectedVendorType.value "integrated-vendor")}}
- +
{{integratedVendor.code}}

{{integratedVendor.name}}

@@ -45,33 +31,17 @@ {{#each this.selectedIntegratedVendor.credential_params as |param|}} - + {{/each}} {{#each this.selectedIntegratedVendor.option_params as |param|}} {{#if param.options}} - {{else}} - + {{/if}} {{/each}} @@ -88,18 +58,9 @@
{{#if this.showAdvancedOptions}}
- - - + + +
{{/if}} @@ -112,32 +73,20 @@ - + + +
- + {{smart-humanize type}}
- + {{smart-humanize status}}
@@ -151,16 +100,7 @@
- +
{{n-a model.address}}
{{model.public_id}} diff --git a/addon/components/vendor-form-panel/create-form.js b/addon/components/vendor-form-panel/create-form.js index 7608bcd5..1218b2ab 100644 --- a/addon/components/vendor-form-panel/create-form.js +++ b/addon/components/vendor-form-panel/create-form.js @@ -143,7 +143,7 @@ export default class VendorFormPanelCreateFormComponent extends Component { return this.contextPanel.focus(place, 'editing', { onAfterSave: (place) => { - this.vendor.place = place; + this.selectVendorAddress(place); this.contextPanel.clear(); }, }); diff --git a/addon/components/vendor-form-panel/edit-form.hbs b/addon/components/vendor-form-panel/edit-form.hbs index c7ba528c..4d18ed38 100644 --- a/addon/components/vendor-form-panel/edit-form.hbs +++ b/addon/components/vendor-form-panel/edit-form.hbs @@ -58,7 +58,9 @@ {{else}} - + + + diff --git a/addon/components/vendor-form-panel/edit-form.js b/addon/components/vendor-form-panel/edit-form.js index 334dff8a..fc52c394 100644 --- a/addon/components/vendor-form-panel/edit-form.js +++ b/addon/components/vendor-form-panel/edit-form.js @@ -47,6 +47,11 @@ export default class VendorFormPanelEditFormComponent extends Component { place = this.store.createRecord('place'); } - return this.contextPanel.focus(place); + return this.contextPanel.focus(place, 'editing', { + onAfterSave: (place) => { + this.selectVendorAddress(place); + this.contextPanel.clear(); + }, + }); } } diff --git a/addon/components/vendor-panel/details.hbs b/addon/components/vendor-panel/details.hbs index 56511fb3..e58bfca6 100644 --- a/addon/components/vendor-panel/details.hbs +++ b/addon/components/vendor-panel/details.hbs @@ -10,21 +10,21 @@
-
+
{{t "fleet-ops.common.sandbox"}}
{{if this.vendor.sandbox "Yes" "No"}}
-
+
{{t "fleet-ops.common.host"}}
{{n-a this.vendor.host}}
-
+
{{t "fleet-ops.common.namespace"}}
{{n-a this.vendor.namespace}}
{{#if (is-object this.vendor.options)}} {{#each-in this.vendor.options as |key value|}} -
+
{{smart-humanize key}}
{{n-a value}}
@@ -33,34 +33,34 @@
{{else}}
-
+
{{t "fleet-ops.common.name"}}
{{n-a this.vendor.name}}
-
+
{{t "fleet-ops.common.email"}}
{{n-a this.vendor.email}}
-
+
{{t "fleet-ops.common.phone"}}
{{n-a this.vendor.phone}}
-
+
{{t "fleet-ops.common.website-url"}}
{{n-a this.vendor.website_url}}
-
+
{{t "fleet-ops.common.country"}}
-
+
{{t "fleet-ops.common.status"}}
diff --git a/addon/controllers/operations/orders/index.js b/addon/controllers/operations/orders/index.js index 57c78a6e..8f0af035 100644 --- a/addon/controllers/operations/orders/index.js +++ b/addon/controllers/operations/orders/index.js @@ -96,6 +96,7 @@ export default class OperationsOrdersIndexController extends BaseController { 'facilitator', 'customer', 'driver', + 'vehicle', 'pickup', 'dropoff', 'created_by', @@ -184,6 +185,13 @@ export default class OperationsOrdersIndexController extends BaseController { */ @tracked driver; + /** + * The filterable param `vehicle` + * + * @var {String} + */ + @tracked vehicle; + /** * The filterable param `payload` * @@ -326,7 +334,7 @@ export default class OperationsOrdersIndexController extends BaseController { { label: this.intl.t('fleet-ops.common.id'), valuePath: 'public_id', - width: '150px', + width: '140px', cellComponent: 'table/cell/link-to', route: 'operations.orders.index.view', onLinkClick: this.viewOrder, @@ -339,6 +347,7 @@ export default class OperationsOrdersIndexController extends BaseController { label: this.intl.t('fleet-ops.common.internal-id'), valuePath: 'internal_id', width: '125px', + hidden: true, resizable: true, sortable: true, filterable: true, @@ -356,32 +365,18 @@ export default class OperationsOrdersIndexController extends BaseController { filterComponent: 'filter/string', }, { - label: this.intl.t('fleet-ops.operations.orders.index.customer'), - valuePath: 'customer.name', - cellComponent: 'table/cell/base', - width: '125px', - resizable: true, - sortable: true, - hidden: true, - filterable: true, - filterComponent: 'filter/model', - filterComponentPlaceholder: 'Select order customer', - filterParam: 'customer', - model: 'customer', - }, - { - label: this.intl.t('fleet-ops.operations.orders.index.facilitator'), - valuePath: 'facilitator.name', - cellComponent: 'table/cell/base', - width: '125px', + label: this.intl.t('fleet-ops.operations.orders.index.driver-assigned'), + cellComponent: 'cell/driver-name', + valuePath: 'driver_assigned', + modelPath: 'driver_assigned', + width: '210px', resizable: true, - hidden: true, sortable: true, filterable: true, filterComponent: 'filter/model', - filterComponentPlaceholder: 'Select order facilitator', - filterParam: 'facilitator', - model: 'vendor', + filterComponentPlaceholder: 'Select driver for order', + filterParam: 'driver', + model: 'driver', }, { label: this.intl.t('fleet-ops.operations.orders.index.pickup'), @@ -412,6 +407,50 @@ export default class OperationsOrdersIndexController extends BaseController { modelNamePath: 'address', model: 'place', }, + { + label: this.intl.t('fleet-ops.operations.orders.index.customer'), + valuePath: 'customer.name', + cellComponent: 'table/cell/base', + width: '125px', + resizable: true, + sortable: true, + hidden: false, + filterable: true, + filterComponent: 'filter/model', + filterComponentPlaceholder: 'Select order customer', + filterParam: 'customer', + model: 'customer', + }, + { + label: this.intl.t('fleet-ops.operations.orders.index.vehicle-assigned'), + cellComponent: 'cell/vehicle-name', + valuePath: 'vehicle_assigned.display_name', + modelPath: 'vehicle_assigned', + showOnlineIndicator: true, + width: '170px', + hidden: true, + resizable: true, + sortable: true, + filterable: true, + filterComponent: 'filter/model', + filterComponentPlaceholder: 'Select vehicle for order', + filterParam: 'vehicle', + model: 'vehicle', + }, + { + label: this.intl.t('fleet-ops.operations.orders.index.facilitator'), + valuePath: 'facilitator.name', + cellComponent: 'table/cell/base', + width: '125px', + resizable: true, + hidden: true, + sortable: true, + filterable: true, + filterComponent: 'filter/model', + filterComponentPlaceholder: 'Select order facilitator', + filterParam: 'facilitator', + model: 'vendor', + }, { label: this.intl.t('fleet-ops.operations.orders.index.scheduled-at'), valuePath: 'scheduledAt', @@ -450,20 +489,6 @@ export default class OperationsOrdersIndexController extends BaseController { filterable: true, filterComponent: 'filter/string', }, - { - label: this.intl.t('fleet-ops.operations.orders.index.driver-assigned'), - cellComponent: 'table/cell/driver-name', - valuePath: 'driver_assigned', - modelPath: 'driver_assigned', - width: '170px', - resizable: true, - sortable: true, - filterable: true, - filterComponent: 'filter/model', - filterComponentPlaceholder: 'Select driver for order', - filterParam: 'driver', - model: 'driver', - }, { label: this.intl.t('fleet-ops.common.type'), valuePath: 'type', @@ -645,6 +670,13 @@ export default class OperationsOrdersIndexController extends BaseController { this.query = value; } + /** + * Reload layout view. + */ + @action reload() { + return this.hostRouter.refresh(); + } + /** * Hides all elements on the live map. * @action diff --git a/addon/controllers/operations/orders/index/new.js b/addon/controllers/operations/orders/index/new.js index c043decd..4a87f30e 100644 --- a/addon/controllers/operations/orders/index/new.js +++ b/addon/controllers/operations/orders/index/new.js @@ -122,6 +122,7 @@ export default class OperationsOrdersIndexNewController extends BaseController { */ @tracked payload = this.store.createRecord('payload'); @tracked driversQuery = {}; + @tracked vehiclesQuery = {}; @tracked meta = []; @tracked entities = []; @tracked waypoints = []; @@ -296,7 +297,7 @@ export default class OperationsOrdersIndexNewController extends BaseController { this.previewRoute(false); this.loader.showLoader('body', { loadingMessage: 'Creating Order...' }); - const { order, groupedMetaFields, payload, entities, waypoints, isMultipleDropoffOrder } = this; + const { order, groupedMetaFields, payload, entities, waypoints } = this; const route = this.leafletOptimizedRoute ? this.getOptimizedRoute() : this.getRoute(); // set service quote if applicable @@ -305,14 +306,7 @@ export default class OperationsOrdersIndexNewController extends BaseController { } try { - order - .serializeMeta() - .serializeMetaFromGroupedFields(groupedMetaFields) - .setPayload(payload) - .setRoute(route) - .get('payload') - .setWaypoints(waypoints, isMultipleDropoffOrder) - .setEntities(entities); + order.serializeMeta().serializeMetaFromGroupedFields(groupedMetaFields).setPayload(payload).setRoute(route).get('payload').setWaypoints(waypoints).setEntities(entities); } catch (error) { this.notifications.serverError(error); this.loader.removeLoader(); @@ -353,15 +347,8 @@ export default class OperationsOrdersIndexNewController extends BaseController { // trigger event that fleet-ops created an order this.universe.trigger('fleet-ops.order.created', order); - // get engine route prefix - let engineMountPoint = this.universe.getEngineMountPoint('@fleetbase/fleetops-engine'); - - if (!engineMountPoint.endsWith('.')) { - engineMountPoint = engineMountPoint + '.'; - } - // transition to order view - return this.hostRouter.transitionTo(`${engineMountPoint}operations.orders.index.view`, order).then(() => { + return this.hostRouter.transitionTo(`console.fleet-ops.operations.orders.index.view`, order).then(() => { this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.new.success-message', { orderId: order.public_id })); this.loader.removeLoader(); this.resetForm(); @@ -557,11 +544,19 @@ export default class OperationsOrdersIndexNewController extends BaseController { @action createPlace() { const place = this.store.createRecord('place'); - this.contextPanel.focus(place, 'editing'); + this.contextPanel.focus(place, 'editing', { + onAfterSave: () => { + this.contextPanel.clear(); + }, + }); } @action editPlace(place) { - this.contextPanel.focus(place, 'editing'); + this.contextPanel.focus(place, 'editing', { + onAfterSave: () => { + this.contextPanel.clear(); + }, + }); } @action async getQuotes(service) { @@ -1196,7 +1191,11 @@ export default class OperationsOrdersIndexNewController extends BaseController { @action setOrderCustomer(model) { this.order.set('customer', model); - // this.order.set('customer_type', `fleet-ops:${model.customer_type}`); + } + + @action setWaypointCustomer(waypoint, model) { + waypoint.set('customer', model); + waypoint.set('customer_type', `fleet-ops:${model.customer_type}`); } @action selectIntegratedServiceType(key) { @@ -1207,6 +1206,14 @@ export default class OperationsOrdersIndexNewController extends BaseController { } } + @action async selectDriver(driver) { + this.order.set('driver_assigned', driver); + if (driver && driver.vehicle) { + const vehicle = await driver.vehicle; + this.order.set('vehicle_assigned', vehicle); + } + } + @action addCustomField() { let label, value; diff --git a/addon/controllers/operations/orders/index/view.js b/addon/controllers/operations/orders/index/view.js index cd596557..5c8de1fc 100644 --- a/addon/controllers/operations/orders/index/view.js +++ b/addon/controllers/operations/orders/index/view.js @@ -197,10 +197,8 @@ export default class OperationsOrdersIndexViewController extends BaseController // create groups this.model.payload.waypoints.forEach((waypoint) => { const destinationId = waypoint.id; - if (destinationId) { const entities = this.model.payload.entities.filter((entity) => entity.destination_uuid === destinationId); - if (entities.length === 0) { return; } @@ -506,11 +504,20 @@ export default class OperationsOrdersIndexViewController extends BaseController }, setDriver: (driver) => { order.set('driver_assigned', driver); + if (driver && driver.vehicle) { + order.set('vehicle_assigned', driver.vehicle); + } if (!driver) { order.set('driver_assigned_uuid', null); } }, + setVehicle: (vehicle) => { + order.set('vehicle_assigned', vehicle); + if (!vehicle) { + order.set('vehicle_assigned_uuid', null); + } + }, scheduleOrder: (dateInstance) => { order.scheduled_at = dateInstance.toDate(); }, diff --git a/addon/controllers/settings/navigator-app.js b/addon/controllers/settings/navigator-app.js new file mode 100644 index 00000000..47f77da2 --- /dev/null +++ b/addon/controllers/settings/navigator-app.js @@ -0,0 +1,3 @@ +import Controller from '@ember/controller'; + +export default class SettingsNavigatorAppController extends Controller {} diff --git a/addon/templates/operations/orders/index.hbs b/addon/templates/operations/orders/index.hbs index a09e2159..dd433a2a 100644 --- a/addon/templates/operations/orders/index.hbs +++ b/addon/templates/operations/orders/index.hbs @@ -21,6 +21,7 @@ {{#if this.isTableLayout}} +