UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

194 lines (193 loc) 8.61 kB
import GroupLayer from '../../models/layers/grouplayer'; import Layer from '../../models/layers/layer'; import LZString from 'lz-string'; import LayerManager from '../layers/layermanager'; import StateManager from '../state/statemanager'; import ComponentManager from '../state/componentManager'; import ThemeLayer from '../../models/layers/themelayer'; import { isTimeAwareLayer } from '../../models/layers/timeawarelayer'; import ErrorManager from '../error/errormanager'; import DrawingFeature, { DrawingState } from '../../components/drawing/drawingFeature'; class StateDeserializer { constructor() { Object.defineProperty(this, "stateManager", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "layerManager", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "componentManager", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.stateManager = StateManager.getInstance(); this.layerManager = LayerManager.getInstance(); this.componentManager = ComponentManager.getInstance(); } get state() { return this.stateManager.state; } deserializeAndSetState(compressedState) { // First: clear the current layers list for (const layer of this.stateManager.state.layers.layersList) { this.layerManager.toggle(layer, 'off'); } this.state.layers.layersList = []; const stringState = LZString.decompressFromBase64(compressedState); const sharedState = JSON.parse(stringState); this.state.projection = sharedState.m.p; this.state.position.center = sharedState.p.c; this.state.position.resolution = sharedState.p.r; this.state.treeview.advanced = Boolean(sharedState.t.a); this.state.globe.display = sharedState.g.d; // Set basemap if any if (sharedState.b) { const basemap = Object.values(this.state.basemaps).find((b) => b.id === sharedState.b.i); if (basemap) { if (basemap.projection) { this.state.projection = basemap.projection; } this.state.activeBasemap = basemap; } else { // TODO REG : Add infobox ? console.warn(`Cannot find basemap with id ${sharedState.b.i} in the available basemaps`); } } // Set all layers const deserializedLayers = this.getDeserializedLayerTree(sharedState.l); for (const deserializedLayer of deserializedLayers) { this.state.layers.layersList.push(deserializedLayer); } // Set drawn features this.deserializeDrawingFeatures(sharedState.f); } getDeserializedLayerTree(sharedLayers) { const layersList = []; for (const sharedLayer of sharedLayers) { const layer = this.findBaseLayerById(sharedLayer.i); if (layer) { this.deserializeLayer(layer, sharedLayer); layersList.push(layer); } else { console.warn(`Cannot find layer with id ${sharedLayer.i} in the available layers`); } } return layersList; } deserializeLayer(originalLayer, sharedLayer) { originalLayer.order = sharedLayer.o; originalLayer.isDefaultChecked = Boolean(sharedLayer.c); if (originalLayer instanceof GroupLayer || originalLayer instanceof ThemeLayer) { originalLayer.isExpanded = Boolean(sharedLayer.e); // Manage children this.removeUnnecessaryChilds(originalLayer, sharedLayer); this.checkUnknownLayers(sharedLayer, originalLayer); } else if (originalLayer instanceof Layer && this.layerManager.isLayerWithLegend(originalLayer)) { originalLayer.isLegendExpanded = Boolean(sharedLayer.e); } if (isTimeAwareLayer(originalLayer)) { originalLayer.timeRestriction = sharedLayer.t; } } checkUnknownLayers(sharedLayer, originalLayer) { // If some layers are present in the shared state but cannot be found in the current list of available layers // It probably means that the layers are private ones or that the layer has been delete. // Add an infobox for this. for (const sharedChild of sharedLayer.z) { const originalChild = originalLayer.children.find((c) => c.id == sharedChild.i); if (!originalChild) { ErrorManager.getInstance().pushMessage('unknown-layers-cannot-be-added', 'Some layer could not be added to the layer-tree. This is either because you do not have the rights for it, or because this layer does not exist anymore.', 'warning'); } } } removeUnnecessaryChilds(originalLayer, sharedLayer) { let reorder = false; for (let i = originalLayer.children.length - 1; i >= 0; i--) { const child = originalLayer.children[i]; const serializedChild = sharedLayer.z.find((l) => l.i == child.id); if (serializedChild) { this.deserializeLayer(child, serializedChild); } else { // This child exists in the original layer, but not in the shared state. // => If it is present in the x list, it was explicitely removed // And we can remove it from the current object const explicitlyRemoved = sharedLayer.x.find((id) => id == child.id); if (explicitlyRemoved) { originalLayer.children.splice(i, 1); console.debug(`Layer ${child.name} was removed from initial state`); } else { // Otherwise it is a new layer. We do not remove it // But we have to set the right order for it. // In this case we have to reorder all the layers at this level // In order to keep the order defined in the initial group console.debug(`Layer ${child.name} will be added to the treeview because it is new`); console.debug(`Layer ${originalLayer.name} needs a reorering of its children`); reorder = true; } } } if (reorder) { console.debug(`Reordering childs for layer ${originalLayer.name}`); let order = 1; for (const child of originalLayer.children) { child.order = order++; } } } findBaseLayerById(layerId) { for (const theme of Object.values(this.state.themes._allThemes)) { const layer = this.findLayerRecursive(theme, layerId); if (layer) { return layer; } } return null; } findLayerRecursive(layer, layerId) { if (layer.id === layerId) { // When deserializing the layer, we clone it, // otherwise the following operation will also // affect the layer referenced in other themes const foundLayer = layer.clone(); return foundLayer; } // Else, we call recursively on the children if (layer instanceof GroupLayer || layer instanceof ThemeLayer) { for (const childLayer of layer.children) { const foundChild = this.findLayerRecursive(childLayer, layerId); if (foundChild) { return foundChild; } } } return null; } deserializeDrawingFeatures(serializedFeatures) { if (serializedFeatures) { if (this.state.extendedState.drawing) { // First, delete existing drawing features in the state before adding new ones. // This will trigger removal of the ol features in the map. const drawingState = this.state.extendedState.drawing; drawingState.features.splice(0, drawingState.features.length); } else { this.state.extendedState.drawing = new DrawingState(); } serializedFeatures.forEach((f) => DrawingFeature.deserialize(f)); } } } export default StateDeserializer;