import Vue from 'vue'
import { getQueryStringValue } from '@/utils/querystring'
import { getClientLogoAsBase64 } from '@/services/auth-service'
import {
saveSettingsParamLocally,
saveSettingsParamRemotely,
getSettingsParamFromRemote,
} from '@/services/settings-service.js'
import i18n, { isValidLocaleCode } from '@/i18n'
import storage from '@/plugins/vue-local-storage.js'
import {
getUserParameters,
getUserParametersAsObject,
} from '@/services/user-service.js'
//Dummy promise to resolve when a sync is requested but there is already a sync in progress
let hasSyncFromCachePromise = null
let cacheBlacklist = ['osmLayers']
function newState() {
return {
//Used to PATCH settings parameters (thanks to ids)
userParameters: [],
hasSyncFromCache: false,
clientLogoBase64: '',
//Language will be decided during login action (default to fr)
applicationLanguage: '',
//Cartography
//-- Predefined views
//---- Default predefined view
defaultMapPredefinedView: null,
//-- Carto
//---- Default zoom level
defaultMapZoomLevel: null,
//---- Zones
//------ Client zones
areClientZonesEnabledOnTheMap: false,
//------ Client zone types
enabledClientZones: [],
clientBasemapItems: [],
naturalGeocodingProvider: 'osm',
//Base maps
//Selected Leaflet base map
wmsItem: {},
googleLayers: [],
areOSMLayersDisabled: false,
osmLayers: [],
userBaseLayer: null,
//location
autorefreshTimeInterval: 2,
//User parameters (user client-side / database setting)
userMaxMapPredefinedViewsCount: 999, //database name: maxvue
//Events (client/user client-side setting)
isAggregateEventGroupRoundEnabled: false,
isAggregateEventGroupBinEnabled: false,
}
}
/**
*
* @param {*} countryCode
* @returns
*/
export function getComputedLanguageCodeFromCountryCode(countryCode) {
let countryCodeNormalized = (countryCode || '').toString().toLowerCase()
return isValidLocaleCode(countryCodeNormalized) ? countryCodeNormalized : ''
}
/**
* @namespace Stores
* @category Stores
* @module settings-store
* */
const SettingsStore = {
namespaced: true,
state: newState(),
getters: {
getParameter: (state) => (name) => state[name],
/**
* Retrieves the first available basemapId
* API requires a valid client basemapId but use custom layers/basemaps (Google/OSM).
**/
getValidBasemapId: (state) =>
(state.clientBasemapItems.find((c) => !!c.id) || {}).id || '',
},
mutations: {
setParameters(state, data) {
Object.assign(state, data)
},
resetStore(state) {
state = {
...state,
...newState(),
}
},
},
actions: {
resetStore({ commit }) {
commit('resetStore')
},
/**
* Some settings are stored in the server. This will check and overwrite client cache.
* @function syncFromServer
* @memberof SettingsStore
*/
async syncFromServer({ commit, rootGetters, state, dispatch }) {
let googleLayersString =
(await Vue.$auth.getClientParameter('GeoredV3GoogleMap')) ||
(!Vue.$env.isProduction() &&
getQueryStringValue('GeoredV3GoogleMap')) ||
''
const currentUserLogin = rootGetters['auth/loginName']
let userParameters = Object.freeze(
await getUserParameters(currentUserLogin)
)
/*console.log('syncFromServer::userParameters', {
userParameters: userParameters,
})*/
//Clear current
commit('setParameters', {
clientLogoBase64: '',
})
let newState = {
userParameters,
clientLogoBase64: await getClientLogoAsBase64('default'),
//The language choice at login view has priority over the client language
applicationLanguage:
state.applicationLanguage ||
getComputedLanguageCodeFromCountryCode(
rootGetters['auth/clientCountry']
) ||
'fr',
//Google basemaps
googleLayers:
state.googleLayers.length > 0
? state.googleLayers
: googleLayersString.split(',').filter((str) => !!str),
//OSM layer/s is/are enabled by default but it can be diasble for certain clients
areOSMLayersDisabled: await Vue.$mapService.areOSMLayersDisabled(),
osmLayers: await Vue.$mapService.getOSMLayers(),
//Retrieve user parameters and merge them into state (userMaxMapPredefinedViewsCount, defaultMapZoomLevel, userBaseLayer)
...(await getUserParametersAsObject(
currentUserLogin,
state.userParameters
)),
//Retrieve other parameters from online persistance (defaultMapPredefinedView)
...(await getSettingsParamFromRemote()),
}
commit('setParameters', newState)
dispatch('saveParameters')
/*console.log('settings::syncFromServer', {
newState: {
...newState,
},
})*/
},
/**
* Retrieves settings from client-side cache. Call it before requesting parameters.
* This should be called during app bootstrap
* @param {Boolean} options.once Retrieves just once (default: true)
*/
async syncFromCache({ commit, state, rootGetters }, options = {}) {
if (options.once === undefined) {
options.once = true
}
const { once } = options
if (once && state.hasSyncFromCache) {
return hasSyncFromCachePromise
}
let resolve = null
hasSyncFromCachePromise = new Promise((r) => {
resolve = r
})
let defaultState = newState()
let keyPart = '_' + rootGetters['auth/loginNameClientIdEncoded']
let data = {}
let keys = await storage.keys()
let cachedState = {}
await Promise.all(
Object.keys(state)
.filter((stateKey) => !cacheBlacklist.includes(stateKey))
.map((stateKey) => {
return (async () => {
let includesKey =
keys.findIndex((key) => key.includes(stateKey)) !== -1
//Hot-fix: Old version adds a '}' at the end of the cache key (bug)
let value = includesKey
? (await storage.getItem(stateKey + keyPart)) ||
(await storage.getItem(stateKey + keyPart + '}'))
: null
cachedState[stateKey] = value
data[stateKey] = value !== null ? value : defaultState[stateKey]
})()
})
)
data.hasSyncFromCache = true
commit('setParameters', data)
/*console.log('settings::syncFromCache', {
cachedState,
})*/
resolve()
},
setParameter({ commit }, { name, value }) {
commit('setParameters', {
[name]: value,
})
},
async setParameterAndSave({ dispatch }, { name, value }) {
await dispatch('setParameter', { name, value })
await dispatch('saveParameter', name)
},
/**
* Persist a single parameter from state
*/
async saveParameter({ state, rootGetters }, parameterName) {
if (state[parameterName] !== undefined) {
if (rootGetters['auth/isLogged']) {
await saveSettingsParamRemotely(
parameterName,
state[parameterName],
rootGetters['auth/isLoginAs'],
state.userParameters
)
await saveSettingsParamLocally(
getCacheKey(
parameterName,
rootGetters['auth/loginNameClientIdEncoded']
),
state[parameterName]
)
}
}
},
/**
* Persist Vuex settings into client-side cache
*/
async saveParameters({ state, rootGetters }) {
await Promise.all(
Object.keys(state).map((stateKey) => {
return (async () => {
if (rootGetters['auth/isLogged']) {
await saveSettingsParamRemotely(
stateKey,
state[stateKey],
rootGetters['auth/isLoginAs'],
state.userParameters
)
await saveSettingsParamLocally(
getCacheKey(
stateKey,
rootGetters['auth/loginNameClientIdEncoded']
),
state[stateKey]
)
}
})()
})
)
},
},
}
function getCacheKey(stateKey = '', segregationKey = '') {
return `${stateKey}_${segregationKey}`
}
export default SettingsStore
Source