Skip to content

Commit

Permalink
Merge pull request #553 from geoadmin/feat_load_geojson_data_in_store
Browse files Browse the repository at this point in the history
Load GeoJSON data on addLayer in a store plugin
  • Loading branch information
pakb authored Dec 4, 2023
2 parents 74c127c + f115896 commit 53e6538
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 23 deletions.
8 changes: 6 additions & 2 deletions src/api/layers/GeoAdminGeoJsonLayer.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ export default class GeoAdminGeoJsonLayer extends GeoAdminLayer {
* @param {boolean} visible If the layer should be shown on the map
* @param {LayerAttribution[]} attributions Description of the data owner(s) for this layer
* @param geoJsonUrl The URL to use when requesting the GeoJSON data (the true GeoJSON per
* say...)
* se...)
* @param styleUrl The URL to use to request the styling to apply to the data
*/
constructor(name, id, opacity, visible, attributions, geoJsonUrl, styleUrl) {
super(name, LayerTypes.GEOJSON, id, id, opacity, visible, attributions)
this.geoJsonUrl = geoJsonUrl
this.styleUrl = styleUrl

this.isLoading = true
this.geoJsonData = null
this.geoJsonStyle = null
}

getURL() {
getURL(_epsgNumber, _timestamp) {
return this.geoJsonUrl
}
}
34 changes: 18 additions & 16 deletions src/modules/map/components/openlayers/utils/styleFromLiterals.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function getOlStyleForPoint(options, shape) {
},
}
// deep copy to preserve the original object
const style = Object.assign({}, shapes[shape], options)
const style = { ...shapes[shape], ...options }
return new RegularShape(style)
}
}
Expand All @@ -53,15 +53,22 @@ function getOlBasicStyles(options) {
} else if (type === 'fill') {
olStyles[type] = new Fill(style)
} else if (type === 'text') {
style.stroke = new Stroke(style.stroke)
style.fill = new Fill(style.fill)
let backgroundFill
if (style.backgroundFill) {
style.backgroundFill = new Fill(style.backgroundFill)
backgroundFill = new Fill(style.backgroundFill)
}
let backgroundStroke
if (style.backgroundStroke) {
style.backgroundStroke = new Stroke(style.backgroundStroke)
backgroundStroke = new Stroke(style.backgroundStroke)
}
olStyles[type] = new Text(style)
olStyles[type] = new Text({
...style,
// replacing/overwriting literals (strings) that must be converted to objects
stroke: new Stroke(style.stroke),
fill: new Fill(style.fill),
backgroundFill,
backgroundStroke,
})
}
})
return olStyles
Expand Down Expand Up @@ -173,13 +180,11 @@ OlStyleForPropertyValue.prototype.initialize_ = function (properties) {
imageRotationProperty: properties.rotation,
}
} else if (this.type === 'unique') {
for (let i = 0; i < properties.values.length; i++) {
const value = properties.values[i]
for (const value of properties.values) {
this.pushOrInitialize_(value.geomType, value.value, getStyleSpec(value))
}
} else if (this.type === 'range') {
for (let i = 0; i < properties.ranges.length; i++) {
const range = properties.ranges[i]
for (const range of properties.ranges) {
const key = range.range.toString()
this.pushOrInitialize_(range.geomType, key, getStyleSpec(range))
}
Expand Down Expand Up @@ -212,12 +217,9 @@ OlStyleForPropertyValue.prototype.findOlStyleInRange_ = function (value, geomTyp
}

OlStyleForPropertyValue.prototype.getOlStyleForResolution_ = function (olStyles, resolution) {
for (let i = 0; i < olStyles.length; i++) {
const style = olStyles[i]
if (style.minResolution <= resolution && style.maxResolution > resolution) {
return olStyles[i]
}
}
return olStyles.find(
(style) => style.minResolution <= resolution && style.maxResolution > resolution
)
}

OlStyleForPropertyValue.prototype.log_ = function (value, id) {
Expand Down
4 changes: 3 additions & 1 deletion src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import from2Dto3Dplugin from '@/store/plugins/2d-to-3d-management.plugin'
import loadGeojsonStyleAndData from '@/store/plugins/load-geojson-style-and-data.plugin'
import reprojectSelectedFeaturesOnProjectionChangePlugin from '@/store/plugins/reproject-selected-features-on-projection-change.plugin'
import { createStore } from 'vuex'
import app from './modules/app.store'
Expand All @@ -16,6 +17,7 @@ import topics from './modules/topics.store'
import ui from './modules/ui.store'
import appReadinessPlugin from './plugins/app-readiness.plugin'
import clickOnMapManagementPlugin from './plugins/click-on-map-management.plugin'
import loadExternalLayerAttributes from './plugins/external-layers.plugin'
import geolocationManagementPlugin from './plugins/geolocation-management.plugin'
import loadLayersConfigOnLangChange from './plugins/load-layersconfig-on-lang-change'
import loadingBarManagementPlugin from './plugins/loading-bar-management.plugin'
Expand All @@ -24,7 +26,6 @@ import redoSearchOnLangChange from './plugins/redo-search-on-lang-change.plugin'
import screenSizeManagementPlugin from './plugins/screen-size-management.plugin'
import syncCameraLonLatZoom from './plugins/sync-camera-lonlatzoom'
import topicChangeManagementPlugin from './plugins/topic-change-management.plugin'
import loadExternalLayerAttributes from './plugins/external-layers.plugin'

export default createStore({
strict: true,
Expand All @@ -43,6 +44,7 @@ export default createStore({
reprojectSelectedFeaturesOnProjectionChangePlugin,
from2Dto3Dplugin,
loadExternalLayerAttributes,
loadGeojsonStyleAndData,
],
modules: {
app,
Expand Down
2 changes: 1 addition & 1 deletion src/store/modules/layers.store.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ const mutations = {
}
state.activeLayers.push(layer)
},
updateLayer(state, { layer: layer }) {
updateLayer(state, layer) {
Object.assign(getActiveLayerById(state, layer.getID()), layer)
},
removeLayerWithId(state, layerId) {
Expand Down
6 changes: 3 additions & 3 deletions src/store/plugins/external-layers.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* external resources like the GetCapabilities endpoint of the external layer
*/

import ExternalGroupOfLayers from '@/api/layers/ExternalGroupOfLayers.class'
import ExternalLayer from '@/api/layers/ExternalLayer.class'
import ExternalWMSLayer from '@/api/layers/ExternalWMSLayer.class'
import ExternalWMTSLayer from '@/api/layers/ExternalWMTSLayer.class'
import ExternalGroupOfLayers from '@/api/layers/ExternalGroupOfLayers.class'
import log from '@/utils/logging'
import { readWmsCapabilities, readWmtsCapabilities } from '@/api/layers/layers-external.api'
import log from '@/utils/logging'

/**
* Load External layers attributes (title, abstract, extent, attributions, ...) on layer added
Expand Down Expand Up @@ -50,7 +50,7 @@ async function updateExternalLayer(store, externalLayer, projection) {
}

updatedExternalLayer.isLoading = false
store.commit('updateLayer', { layer: updatedExternalLayer })
store.dispatch('updateLayer', updatedExternalLayer)
} catch (error) {
log.error(`Failed to update external layer: ${error}`)
}
Expand Down
61 changes: 61 additions & 0 deletions src/store/plugins/load-geojson-style-and-data.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Listen to the `addLayer` mutation, and if a GeoJSON is added without data/style defined, we load
* it here
*/

import GeoAdminGeoJsonLayer from '@/api/layers/GeoAdminGeoJsonLayer.class'
import log from '@/utils/logging'
import axios from 'axios'

async function load(url) {
try {
return await axios.get(url)
} catch (error) {
log.error(`Error while loading URL ${url}`, error)
throw error
}
}

/**
* @param {Vuex.Store} store
* @param {GeoAdminGeoJsonLayer} geoJsonLayer
* @returns {Promise<void>}
*/
async function loadDataAndStyle(store, geoJsonLayer) {
try {
const { data: style } = await load(geoJsonLayer.styleUrl)
const { data } = await load(geoJsonLayer.geoJsonUrl)
// as the layer comes from the store (99.9% chances), we copy it before altering it
// (otherwise, Vuex raises an error)
const layerCopy = geoJsonLayer.clone()
layerCopy.geoJsonData = data
layerCopy.geoJsonStyle = style
layerCopy.isLoading = false
store.dispatch('updateLayer', layerCopy)
} catch (error) {
log.error(
`Error while fetching GeoJSON data/style for layer ${geoJsonLayer?.getID()}`,
error
)
throw error
}
}

/**
* Load GeoJSON data and style whenever a GeoJSON layer is added (or does nothing if the layer was
* already processed/loaded)
*
* @param {Vuex.Store} store
*/
export default function loadGeojsonStyleAndData(store) {
store.subscribe((mutation) => {
if (
mutation.type === 'addLayer' &&
mutation.payload.layer instanceof GeoAdminGeoJsonLayer &&
mutation.payload.layer.isLoading
) {
log.debug(`Loading data/style for added GeoJSON layer`, mutation.payload.layer)
loadDataAndStyle(store, mutation.payload.layer)
}
})
}

0 comments on commit 53e6538

Please sign in to comment.