@lipagas/fleetops-engine
Version:
Fleet & Transport Management Extension for Fleetbase
174 lines (154 loc) • 5.96 kB
JavaScript
import Service, { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { isBlank } from '@ember/utils';
import { isArray } from '@ember/array';
import getWithDefault from '@lipagas/ember-core/utils/get-with-default';
/**
* Service for managing and retrieving user location data.
* It interacts with various sources to provide the most accurate location information.
*
* @extends Service
*/
export default class LocationService extends Service {
/**
* Default latitude used when location data is unavailable.
* @type {number}
* @static
*/
static DEFAULT_LATITUDE = 1.369;
/**
* Default longitude used when location data is unavailable.
* @type {number}
* @static
*/
static DEFAULT_LONGITUDE = 103.8864;
/**
* Service for accessing the current user's data.
* @type {CurrentUserService}
*/
currentUser;
/**
* A service for managing application-wide events and states.
* @type {UniverseService}
*/
universe;
/**
* Service for making HTTP requests, with support for caching responses.
* @type {FetchService}
*/
fetch;
/**
* Current latitude of the user.
* @type {number}
*/
latitude = this.DEFAULT_LATITUDE;
/**
* Current longitude of the user.
* @type {number}
*/
longitude = this.DEFAULT_LONGITUDE;
/**
* Flag indicating whether the user's location has been located.
* @type {boolean}
*/
located = false;
/**
* Retrieves the current latitude.
* @returns {number} The current latitude.
*/
getLatitude() {
return this.latitude;
}
/**
* Retrieves the current longitude.
* @returns {number} The current longitude.
*/
getLongitude() {
return this.longitude;
}
/**
* 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.
*/
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 await this.getUserLocationFromNavigator();
}
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] = validCoordinates.coordinates;
this.updateLocation({ latitude, longitude });
return { latitude, longitude };
}
}
return await this.getUserLocationFromWhois();
} catch (error) {
return await this.getUserLocationFromWhois();
}
}
/**
* Retrieves the user's location using the browser's navigator geolocation API.
* 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.
*/
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();
}
} else {
return await this.getUserLocationFromWhois();
}
}
/**
* 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');
const coordinates = {
latitude: getWithDefault(whois, 'latitude', this.DEFAULT_LATITUDE),
longitude: getWithDefault(whois, 'longitude', this.DEFAULT_LONGITUDE),
};
this.updateLocation(coordinates);
return coordinates;
}
/**
* 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;
this.longitude = longitude;
this.located = true;
this.universe.trigger('user.located', { latitude, longitude });
}
}