Skip to content

Commit

Permalink
Merge pull request #90 from fleetbase/dev-v0.4.19
Browse files Browse the repository at this point in the history
v0.4.19
  • Loading branch information
roncodes authored Mar 13, 2024
2 parents b0d5547 + 3f4a0df commit 7a90049
Show file tree
Hide file tree
Showing 23 changed files with 474 additions and 148 deletions.
19 changes: 19 additions & 0 deletions addon/components/activity-form-panel.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@
<span class="dark:text-gray-100 text-sm ml-2">{{t "fleet-ops.component.activity-form-panel.completes-order"}}</span>
</Toggle>
</InputGroup>
<InputGroup @helpText={{t "fleet-ops.component.activity-form-panel.require-pod-help-text"}}>
<Toggle @isToggled={{this.activity.require_pod}} @onToggle={{fn (mut this.activity.require_pod)}} @helpText={{t "fleet-ops.component.activity-form-panel.require-pod-help-text"}}>
<span class="dark:text-gray-100 text-sm mx-2">{{t "fleet-ops.component.activity-form-panel.require-pod"}}</span>
</Toggle>
</InputGroup>
{{#if this.activity.require_pod}}
<InputGroup @name={{t "fleet-ops.component.activity-form-panel.select-pod-method"}}>
<select class="form-select w-full has--placeholder" {{on "change" this.setProofOfDeliveryMethod}}>
<option selected disabled>
{{t "fleet-ops.component.activity-form-panel.pod-method-placeholder"}}
</option>
{{#each this.podOptions as |podOption|}}
<option value={{podOption}} selected={{eq this.activity.pod_method podOption}}>
{{smart-humanize podOption}}
</option>
{{/each}}
</select>
</InputGroup>
{{/if}}
<ActivityLogicBuilder @activity={{this.activity}} @onChange={{this.updateActivityLogic}} class="mb-4" />
<ActivityEventSelector @activity={{this.activity}} @onChange={{this.updateActivityEvents}} />
<Spacer @height="300px" />
Expand Down
18 changes: 18 additions & 0 deletions addon/components/activity-form-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export default class ActivityFormPanelComponent extends Component {
*/
@tracked targetActivity;

/**
* Proof of delivery options.
*
* @memberof ActivityFormPanelComponent
*/
@tracked podOptions = ['scan', 'signature', 'photo'];

/**
* Constructor for ActivityFormPanelComponent.
* Applies context component arguments upon instantiation.
Expand All @@ -46,6 +53,17 @@ export default class ActivityFormPanelComponent extends Component {
}
}

/**
* Sets the proof of delivery method to be used for this activity.
*
* @param {Event} event
* @memberof ActivityFormPanelComponent
*/
@action setProofOfDeliveryMethod(event) {
const value = event.target.value;
this.activity.set('pod_method', value);
}

/**
* Action method to set the activity code. It uses the underscore function to format
* the code and updates the status by capitalizing each word.
Expand Down
21 changes: 14 additions & 7 deletions addon/components/live-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ export default class LiveMapComponent extends Component {
this.tileSourceUrl = 'https://{s}.tile.jawg.io/jawg-matrix/{z}/{x}/{y}{r}.png?access-token=';
}

this.ready();
this.setupComponent();
}

Expand Down Expand Up @@ -332,7 +331,6 @@ export default class LiveMapComponent extends Component {
})
.finally(() => {
this.listen();
this.ready();
});
}

Expand Down Expand Up @@ -386,14 +384,23 @@ export default class LiveMapComponent extends Component {
* if available, or null if the function is skipped.
*/
async setInitialCoordinates() {
const { latitude, longitude } = await this.location.getUserLocation();
try {
const { latitude, longitude } = await this.location.getUserLocation();

this.latitude = latitude || this.location.DEFAULT_LATITUDE;
this.longitude = longitude || this.location.DEFAULT_LONGITUDE;
} catch (error) {
this.latitude = this.location.DEFAULT_LATITUDE;
this.longitude = this.location.DEFAULT_LONGITUDE;
}

this.latitude = latitude;
this.longitude = longitude;
this.ready();

// trigger that initial coordinates is set to livemap component
this.universe.trigger('fleet-ops.live-map.has_coordinates', { latitude: this.latitude, longitude: this.longitude });
// Trigger that initial coordinates are set to live map component
this.universe.trigger('fleet-ops.live-map.has_coordinates', {
latitude: this.latitude,
longitude: this.longitude,
});
}

/**
Expand Down
5 changes: 5 additions & 0 deletions addon/controllers/operations/orders/index/new.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,11 @@ export default class OperationsOrdersIndexNewController extends BaseController {
params.facilitator = this.order.facilitator.public_id;
}

// filter by order config type
if (this.orderConfig) {
params.service_type = this.orderConfig.key;
}

if (shouldCheck) {
try {
serviceRates = await this.fetch.get(`service-rates/for-route`, params);
Expand Down
25 changes: 23 additions & 2 deletions addon/controllers/operations/service-rates/index/new.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ export default class OperationsServiceRatesIndexNewController extends BaseContro
@tracked serviceRate = this.store.createRecord('service-rate', { per_meter_unit: 'm' });

/**
* Different service types available, based on order type.
* Available order configs.
*
* @var {Array}
*/
@tracked serviceTypes = [];
@tracked orderConfigs = [];

/**
* Service areas.
Expand All @@ -75,6 +75,13 @@ export default class OperationsServiceRatesIndexNewController extends BaseContro
*/
@tracked isCreatingServiceRate = false;

/**
* The current selected order config.
*
* @var {OrderConfigModel|null}
*/
@tracked orderConfig;

/**
* True if updating service rate.
*
Expand Down Expand Up @@ -279,6 +286,20 @@ export default class OperationsServiceRatesIndexNewController extends BaseContro
});
}

@action setConfig(event) {
const orderConfigId = event.target.value;
if (!orderConfigId) {
return;
}

const orderConfig = this.store.peekRecord('order-config', orderConfigId);
if (orderConfig) {
this.orderConfig = orderConfig;
this.serviceRate.set('order_config_uuid', orderConfig.id);
this.serviceRate.set('service_type', orderConfig.key);
}
}

/**
* Adds a per drop-off rate fee
*/
Expand Down
19 changes: 14 additions & 5 deletions addon/routes/operations/service-rates/index/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,20 @@ export default class OperationsServiceRatesIndexEditRoute extends Route {
@service currentUser;
@service notifications;

/**
* Re-use the new service rate form template.
*
* @memberof OperationsServiceRatesIndexEditRoute
*/
templateName = 'operations.service-rates.index.new';

/**
* Handle any async error.
*
* @param {*} error
* @return {*}
* @memberof OperationsServiceRatesIndexEditRoute
*/
@action error(error) {
this.notifications.serverError(error);
return this.transitionTo('operations.service-rates.index');
Expand All @@ -33,10 +45,7 @@ export default class OperationsServiceRatesIndexEditRoute extends Route {
controller.parcelFees = model.parcel_fees;
}

const serviceTypes = await this.currentUser.getInstalledOrderConfigs();
const serviceAreas = await this.store.findAll('service-area');

controller.serviceTypes = serviceTypes;
controller.serviceAreas = serviceAreas;
controller.orderConfigs = await this.store.findAll('order-config');
controller.serviceAreas = await this.store.findAll('service-area');
}
}
8 changes: 2 additions & 6 deletions addon/routes/operations/service-rates/index/new.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@ import { inject as service } from '@ember/service';

export default class OperationsServiceRatesIndexNewRoute extends Route {
@service store;
@service currentUser;

async setupController(controller) {
const serviceTypes = await this.currentUser.getInstalledOrderConfigs();
const serviceAreas = await this.store.findAll('service-area');

controller.serviceTypes = serviceTypes;
controller.serviceAreas = serviceAreas;
controller.orderConfigs = await this.store.findAll('order-config');
controller.serviceAreas = await this.store.findAll('service-area');
}
}
98 changes: 54 additions & 44 deletions addon/services/location.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,66 +78,74 @@ export default class LocationService extends Service {
}

/**
* Attempts to fetch the user's location from various sources.
* Uses cached data, navigator geolocation, or WHOIS data as fallbacks.
* Attempts to fetch the user's location from various sources including cached data,
* navigator geolocation, or WHOIS data. It first tries to get the cached coordinates.
* If not available or outdated, it tries the browser's geolocation API.
* As a fallback, it uses WHOIS data associated with the user's account.
*
* @returns {Promise<Object>} A promise that resolves to an object containing latitude and longitude.
*/
getUserLocation() {
return this.fetch.cachedGet('fleet-ops/live/coordinates', {}, { expirationInterval: 1, expirationIntervalUnit: 'hour' }).then((coordinates) => {
async getUserLocation() {
// If the location has already been located, return the existing coordinates
if (this.located) {
return { latitude: this.latitude, longitude: this.longitude };
}

try {
const coordinates = await this.fetch.cachedGet('fleet-ops/live/coordinates', {}, { expirationInterval: 1, expirationIntervalUnit: 'hour' });

if (isBlank(coordinates)) {
return this.getUserLocationFromNavigator().then((navigatorCoordinates) => {
this.updateLocation(navigatorCoordinates);
return navigatorCoordinates;
});
return await this.getUserLocationFromNavigator();
}

if (isArray(coordinates)) {
const validCoordinates = coordinates.filter((point) => point.coordinates[0] !== 0);
if (isArray(coordinates) && coordinates.length > 0) {
// Ensure the coordinates array contains valid data
const validCoordinates = coordinates.find((point) => point.coordinates[0] !== 0 && point.coordinates[1] !== 0);
if (validCoordinates) {
const [longitude, latitude] = getWithDefault(validCoordinates, '0.coordinates', [0, 0]);
const userCoordinates = {
latitude,
longitude,
};

this.updateLocation(userCoordinates);
return userCoordinates;
const [longitude, latitude] = validCoordinates.coordinates;
this.updateLocation({ latitude, longitude });
return { latitude, longitude };
}
}

return this.getUserLocationFromWhois();
});
return await this.getUserLocationFromWhois();
} catch (error) {
return await this.getUserLocationFromWhois();
}
}

/**
* Retrieves the user's location using the browser's navigator geolocation API.
* @returns {Promise<Object>} A promise that resolves to geolocation coordinates.
* It creates a promise that resolves with the geolocation if successful,
* or with WHOIS data as a fallback in case of failure or absence of navigator geolocation.
*
* @returns {Promise<Object>} A promise that resolves to geolocation coordinates or WHOIS data.
*/
getUserLocationFromNavigator() {
return new Promise((resolve) => {
// eslint-disable-next-line no-undef
if (window.navigator && window.navigator.geolocation) {
// eslint-disable-next-line no-undef
return navigator.geolocation.getCurrentPosition(
({ coords }) => {
this.updateLocation(coords);
return resolve(coords);
},
() => {
// If failed use user whois
return resolve(this.getUserLocationFromWhois());
}
);
async getUserLocationFromNavigator() {
if (window.navigator && window.navigator.geolocation) {
try {
const position = await new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, {
enableHighAccuracy: true,
timeout: 600,
});
});
const { latitude, longitude } = position.coords;
this.updateLocation({ latitude, longitude });
return { latitude, longitude };
} catch (error) {
return await this.getUserLocationFromWhois();
}

// default to whois lookup coordinates
return resolve(this.getUserLocationFromWhois());
});
} else {
return await this.getUserLocationFromWhois();
}
}

/**
* Retrieves the user's location based on WHOIS data associated with the user's account.
* @returns {Object} An object containing latitude and longitude from WHOIS data.
* Retrieves the user's location based on WHOIS data associated with their account.
* Defaults to predefined coordinates if WHOIS data is not available.
*
* @returns {Object} An object containing latitude and longitude from WHOIS data or default values.
*/
getUserLocationFromWhois() {
const whois = this.currentUser.getOption('whois');
Expand All @@ -151,8 +159,10 @@ export default class LocationService extends Service {
}

/**
* Updates the service's tracked properties with the new location data and triggers an event.
* @param {Object} coordinates - An object containing the latitude and longitude.
* Updates the service's tracked properties with the new location data.
* Triggers an event to notify other parts of the application that the user's location has been updated.
*
* @param {Object} coordinates - An object containing the latitude and longitude to be set.
*/
updateLocation({ latitude, longitude }) {
this.latitude = latitude;
Expand Down
11 changes: 10 additions & 1 deletion addon/templates/operations/service-rates/index/new.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,16 @@

<div class="input-group">
<InputLabel @labelText={{t "fleet-ops.operations.service-rates.index.new.service-order-label"}} @helpText={{t "fleet-ops.operations.service-rates.index.new.service-order-help-text"}} />
<Select class="w-full" @options={{this.serviceTypes}} @value={{this.serviceRate.service_type}} @optionLabel="name" @optionValue="key" @onSelect={{fn (mut this.serviceRate.service_type)}} @placeholder={{t "fleet-ops.operations.service-rates.index.new.service-order-placeholder"}} />
<select class="form-select w-full has--placeholder" {{on "change" this.setConfig}}>
<option selected disabled>
{{t "fleet-ops.operations.service-rates.index.new.service-order-placeholder"}}
</option>
{{#each this.orderConfigs as |orderConfig|}}
<option value={{orderConfig.id}} selected={{eq orderConfig.id this.serviceRate.order_config_uuid}}>
{{orderConfig.name}}
</option>
{{/each}}
</select>
</div>

<div class="input-group">
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fleetbase/fleetops-api",
"version": "0.4.18",
"version": "0.4.19",
"description": "Fleet & Transport Management Extension for Fleetbase",
"keywords": [
"fleetbase-extension",
Expand Down
2 changes: 1 addition & 1 deletion extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Fleet-Ops",
"version": "0.4.18",
"version": "0.4.19",
"description": "Fleet & Transport Management Extension for Fleetbase",
"repository": "https://github.com/fleetbase/fleetops",
"license": "MIT",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/fleetops-engine",
"version": "0.4.18",
"version": "0.4.19",
"description": "Fleet & Transport Management Extension for Fleetbase",
"fleetbase": {
"route": "fleet-ops"
Expand Down Expand Up @@ -44,7 +44,7 @@
"@babel/core": "^7.23.2",
"@fleetbase/ember-core": "^0.2.6",
"@fleetbase/ember-ui": "^0.2.11",
"@fleetbase/fleetops-data": "^0.1.13",
"@fleetbase/fleetops-data": "^0.1.14",
"@fleetbase/leaflet-routing-machine": "^3.2.16",
"@fortawesome/ember-fontawesome": "^0.4.1",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
Expand Down
Loading

0 comments on commit 7a90049

Please sign in to comment.