Add possibility to add external geojson
This commit is contained in:
parent
d7c1f38d26
commit
f0765df5ed
10 changed files with 98 additions and 11 deletions
|
@ -127,7 +127,7 @@ export default class LayerConfig {
|
||||||
* A string is interpreted as a name to call
|
* A string is interpreted as a name to call
|
||||||
* @param tagRenderings
|
* @param tagRenderings
|
||||||
*/
|
*/
|
||||||
function trs(tagRenderings?: (string | TagRenderingConfigJson)[]) {
|
function trs(tagRenderings?: (string | TagRenderingConfigJson)[], readOnly = false) {
|
||||||
if (tagRenderings === undefined) {
|
if (tagRenderings === undefined) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,10 @@ export default class LayerConfig {
|
||||||
if (typeof renderingJson === "string") {
|
if (typeof renderingJson === "string") {
|
||||||
|
|
||||||
if (renderingJson === "questions") {
|
if (renderingJson === "questions") {
|
||||||
|
if(readOnly){
|
||||||
|
throw `A tagrendering has a question, but asking a question does not make sense here: is it a title icon or a geojson-layer? ${context}`
|
||||||
|
}
|
||||||
|
|
||||||
return new TagRenderingConfig("questions", undefined)
|
return new TagRenderingConfig("questions", undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +155,7 @@ export default class LayerConfig {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tagRenderings = trs(json.tagRenderings);
|
this.tagRenderings = trs(json.tagRenderings, this.source.geojsonSource !== undefined);
|
||||||
|
|
||||||
|
|
||||||
const titleIcons = [];
|
const titleIcons = [];
|
||||||
|
@ -164,7 +168,7 @@ export default class LayerConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.titleIcons = trs(titleIcons);
|
this.titleIcons = trs(titleIcons, true);
|
||||||
|
|
||||||
|
|
||||||
this.title = tr("title", undefined);
|
this.title = tr("title", undefined);
|
||||||
|
|
|
@ -394,7 +394,7 @@ export class InitUiElements {
|
||||||
features.forEach(feature => {
|
features.forEach(feature => {
|
||||||
State.state.allElements.addOrGetElement(feature);
|
State.state.allElements.addOrGetElement(feature);
|
||||||
|
|
||||||
if (Hash.hash.data === feature.properties.id.replace("/", "_")) {
|
if (Hash.hash.data === feature.properties.id) {
|
||||||
State.state.selectedElement.setData(feature);
|
State.state.selectedElement.setData(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,10 @@ export default class UpdateFromOverpass implements FeatureSource {
|
||||||
if (layer.doNotDownload) {
|
if (layer.doNotDownload) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(layer.source.geojsonSource !== undefined){
|
||||||
|
// Not our responsibility to download this layer!
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if data for this layer has already been loaded
|
// Check if data for this layer has already been loaded
|
||||||
|
|
|
@ -11,6 +11,7 @@ import LayerConfig from "../../Customizations/JSON/LayerConfig";
|
||||||
import LocalStorageSource from "./LocalStorageSource";
|
import LocalStorageSource from "./LocalStorageSource";
|
||||||
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
|
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
|
||||||
import Loc from "../../Models/Loc";
|
import Loc from "../../Models/Loc";
|
||||||
|
import GeoJsonSource from "./GeoJsonSource";
|
||||||
|
|
||||||
export default class FeaturePipeline implements FeatureSource {
|
export default class FeaturePipeline implements FeatureSource {
|
||||||
|
|
||||||
|
@ -30,6 +31,15 @@ export default class FeaturePipeline implements FeatureSource {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const geojsonSources: GeoJsonSource [] = []
|
||||||
|
for (const flayer of flayers.data) {
|
||||||
|
const sourceUrl = flayer.layerDef.source.geojsonSource
|
||||||
|
if (sourceUrl !== undefined) {
|
||||||
|
geojsonSources.push(new WayHandlingApplyingFeatureSource(flayers,
|
||||||
|
new GeoJsonSource(flayer.layerDef.id, sourceUrl)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const amendedLocalStorageSource =
|
const amendedLocalStorageSource =
|
||||||
new RememberingSource(
|
new RememberingSource(
|
||||||
new WayHandlingApplyingFeatureSource(flayers,
|
new WayHandlingApplyingFeatureSource(flayers,
|
||||||
|
@ -37,11 +47,12 @@ export default class FeaturePipeline implements FeatureSource {
|
||||||
));
|
));
|
||||||
|
|
||||||
newPoints = new FeatureDuplicatorPerLayer(flayers, newPoints);
|
newPoints = new FeatureDuplicatorPerLayer(flayers, newPoints);
|
||||||
|
|
||||||
const merged = new FeatureSourceMerger([
|
const merged = new FeatureSourceMerger([
|
||||||
amendedOverpassSource,
|
amendedOverpassSource,
|
||||||
amendedLocalStorageSource,
|
amendedLocalStorageSource,
|
||||||
newPoints
|
newPoints,
|
||||||
|
...geojsonSources
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const source =
|
const source =
|
||||||
|
|
|
@ -22,7 +22,6 @@ export default class FeatureSourceMerger implements FeatureSource {
|
||||||
let all = {}; // Mapping 'id' -> {feature, freshness}
|
let all = {}; // Mapping 'id' -> {feature, freshness}
|
||||||
for (const source of this._sources) {
|
for (const source of this._sources) {
|
||||||
if(source?.features?.data === undefined){
|
if(source?.features?.data === undefined){
|
||||||
console.log("Not defined");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const f of source.features.data) {
|
for (const f of source.features.data) {
|
||||||
|
|
52
Logic/FeatureSource/GeoJsonSource.ts
Normal file
52
Logic/FeatureSource/GeoJsonSource.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import FeatureSource from "./FeatureSource";
|
||||||
|
import {UIEventSource} from "../UIEventSource";
|
||||||
|
import * as $ from "jquery";
|
||||||
|
import {Layer} from "leaflet";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a geojson file somewhere and passes it along
|
||||||
|
*/
|
||||||
|
export default class GeoJsonSource implements FeatureSource {
|
||||||
|
features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||||
|
|
||||||
|
constructor(layerId: string, url: string, onFail: ((errorMsg: any) => void) = undefined) {
|
||||||
|
if (onFail === undefined) {
|
||||||
|
onFail = errorMsg => {
|
||||||
|
console.warn(`Could not load geojson layer from`, url, "due to", errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>(undefined)
|
||||||
|
const eventSource = this.features;
|
||||||
|
$.getJSON(url, function (json, status) {
|
||||||
|
if (status !== "success") {
|
||||||
|
console.log("Fetching geojson failed failed")
|
||||||
|
onFail(status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.elements === [] && json.remarks.indexOf("runtime error") > 0) {
|
||||||
|
console.log("Timeout or other runtime error");
|
||||||
|
onFail("Runtime error (timeout)")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const time = new Date();
|
||||||
|
const features: { feature: any, freshness: Date } [] = []
|
||||||
|
let i = 0;
|
||||||
|
for (const feature of json.features) {
|
||||||
|
if (feature.properties.id === undefined) {
|
||||||
|
feature.properties.id = url + "/" + i;
|
||||||
|
feature.id = url + "/" + i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
feature._matching_layer_id = layerId;
|
||||||
|
features.push({feature: feature, freshness: time})
|
||||||
|
}
|
||||||
|
console.log("Loaded features are", features)
|
||||||
|
eventSource.setData(features)
|
||||||
|
|
||||||
|
}).fail(onFail)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -44,6 +44,7 @@ export class Overpass {
|
||||||
if (status !== "success") {
|
if (status !== "success") {
|
||||||
console.log("Query failed")
|
console.log("Query failed")
|
||||||
onFail(status);
|
onFail(status);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.elements === [] && json.remarks.indexOf("runtime error") > 0) {
|
if (json.elements === [] && json.remarks.indexOf("runtime error") > 0) {
|
||||||
|
|
|
@ -110,7 +110,7 @@ export default class ShowDataLayer {
|
||||||
private postProcessFeature(feature, leafletLayer: L.Layer) {
|
private postProcessFeature(feature, leafletLayer: L.Layer) {
|
||||||
const layer: LayerConfig = this._layerDict[feature._matching_layer_id];
|
const layer: LayerConfig = this._layerDict[feature._matching_layer_id];
|
||||||
if(layer === undefined){
|
if(layer === undefined){
|
||||||
console.warn("No layer found for object (probably a now disabled layer)", feature)
|
console.warn("No layer found for object (probably a now disabled layer)", feature, this._layerDict)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (layer.title === undefined && (layer.tagRenderings ?? []).length === 0) {
|
if (layer.title === undefined && (layer.tagRenderings ?? []).length === 0) {
|
||||||
|
|
|
@ -62,7 +62,8 @@
|
||||||
"if": "id~=-",
|
"if": "id~=-",
|
||||||
"then": "<span class='alert'>Uploading...</alert>"
|
"then": "<span class='alert'>Uploading...</alert>"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"condition": "id~(node|way|relation)/[0-9]*"
|
||||||
},
|
},
|
||||||
"sharelink": {
|
"sharelink": {
|
||||||
"render": "{share_link()}"
|
"render": "{share_link()}"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"maintainer": "MapComplete",
|
"maintainer": "MapComplete",
|
||||||
"icon": "./assets/layers/play_forest/icon.svg",
|
"icon": "./assets/layers/play_forest/icon.svg",
|
||||||
"hideFromOverview": true,
|
"hideFromOverview": true,
|
||||||
"lockLocation": true,
|
"lockLocation": false,
|
||||||
"version": "0",
|
"version": "0",
|
||||||
"startLat": 51.17174,
|
"startLat": 51.17174,
|
||||||
"startLon": 4.449462,
|
"startLon": 4.449462,
|
||||||
|
@ -23,13 +23,28 @@
|
||||||
"widenFactor": 0.05,
|
"widenFactor": 0.05,
|
||||||
"socialImage": "",
|
"socialImage": "",
|
||||||
"defaultBackgroundId": "CartoDB.Positron",
|
"defaultBackgroundId": "CartoDB.Positron",
|
||||||
"layers": [
|
"layersX": [
|
||||||
"play_forest",
|
"play_forest",
|
||||||
"playground",
|
"playground",
|
||||||
"sport_pitch",
|
"sport_pitch",
|
||||||
"slow_roads",
|
"slow_roads",
|
||||||
"grass_in_parks",
|
"grass_in_parks",
|
||||||
"village_green"
|
"village_green"
|
||||||
|
],
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
"source": {
|
||||||
|
"osmTags": "country~*",
|
||||||
|
"geoJsonSource": "https://pietervdvn.github.io/latlon2country/15.10774.14922.json"
|
||||||
|
},
|
||||||
|
"maxOverlapPercentage": 0,
|
||||||
|
"name": "test",
|
||||||
|
"title": "Test",
|
||||||
|
"minzoom": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
"roamingRenderings": []
|
"roamingRenderings": []
|
||||||
}
|
}
|
Loading…
Reference in a new issue