forked from MapComplete/MapComplete
Fix #287
This commit is contained in:
parent
da7c9951c0
commit
99a6321cc9
2 changed files with 77 additions and 27 deletions
|
@ -5,7 +5,6 @@ import List from "../UI/Base/List"
|
||||||
import Title from "../UI/Base/Title"
|
import Title from "../UI/Base/Title"
|
||||||
import { BBox } from "./BBox"
|
import { BBox } from "./BBox"
|
||||||
import { Feature, Geometry, MultiPolygon, Polygon } from "geojson"
|
import { Feature, Geometry, MultiPolygon, Polygon } from "geojson"
|
||||||
import { GeoJSONFeature } from "maplibre-gl"
|
|
||||||
|
|
||||||
export interface ExtraFuncParams {
|
export interface ExtraFuncParams {
|
||||||
/**
|
/**
|
||||||
|
@ -508,9 +507,9 @@ export class ExtraFunctions {
|
||||||
public static constructHelpers(
|
public static constructHelpers(
|
||||||
params: ExtraFuncParams
|
params: ExtraFuncParams
|
||||||
): Record<ExtraFuncType, (feature: Feature) => Function> {
|
): Record<ExtraFuncType, (feature: Feature) => Function> {
|
||||||
const record: Record<string, (feature: GeoJSONFeature) => Function> = {}
|
const record: Record<string, (feature: Feature) => Function> = {}
|
||||||
for (const f of ExtraFunctions.allFuncs) {
|
for (const f of ExtraFunctions.allFuncs) {
|
||||||
if (this.types.indexOf(<any>f._name) < 0) {
|
if ((<readonly string[]> this.types).indexOf(f._name) < 0) {
|
||||||
throw "Invalid extraFunc-type: " + f._name
|
throw "Invalid extraFunc-type: " + f._name
|
||||||
}
|
}
|
||||||
record[f._name] = (feat) => f._f(params, feat)
|
record[f._name] = (feat) => f._f(params, feat)
|
||||||
|
|
|
@ -9,11 +9,14 @@ import { IndexedFeatureSource } from "./FeatureSource/FeatureSource"
|
||||||
import OsmObjectDownloader from "./Osm/OsmObjectDownloader"
|
import OsmObjectDownloader from "./Osm/OsmObjectDownloader"
|
||||||
import { Utils } from "../Utils"
|
import { Utils } from "../Utils"
|
||||||
import { Store, UIEventSource } from "./UIEventSource"
|
import { Store, UIEventSource } from "./UIEventSource"
|
||||||
|
import { selectDefault } from "../Utils/selectDefault"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ...
|
* Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ...
|
||||||
*
|
*
|
||||||
* All metatags start with an underscore
|
* All metatags start with an underscore.
|
||||||
|
*
|
||||||
|
* Will apply the metatags as soon as they are passed in
|
||||||
*/
|
*/
|
||||||
export default class MetaTagging {
|
export default class MetaTagging {
|
||||||
private static errorPrintCount = 0
|
private static errorPrintCount = 0
|
||||||
|
@ -23,6 +26,18 @@ export default class MetaTagging {
|
||||||
string,
|
string,
|
||||||
((feature: Feature, propertiesStore: UIEventSource<any>) => void)[]
|
((feature: Feature, propertiesStore: UIEventSource<any>) => void)[]
|
||||||
>()
|
>()
|
||||||
|
private state: {
|
||||||
|
readonly selectedElement: Store<Feature>;
|
||||||
|
readonly layout: LayoutConfig;
|
||||||
|
readonly osmObjectDownloader: OsmObjectDownloader;
|
||||||
|
readonly perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>;
|
||||||
|
readonly indexedFeatures: IndexedFeatureSource;
|
||||||
|
readonly featureProperties: FeaturePropertiesStore
|
||||||
|
}
|
||||||
|
private params: {
|
||||||
|
getFeatureById: (id) => Feature;
|
||||||
|
getFeaturesWithin: (layerId, bbox) => (Feature[][] | [Feature[]])
|
||||||
|
}
|
||||||
|
|
||||||
constructor(state: {
|
constructor(state: {
|
||||||
readonly selectedElement: Store<Feature>
|
readonly selectedElement: Store<Feature>
|
||||||
|
@ -32,7 +47,8 @@ export default class MetaTagging {
|
||||||
readonly indexedFeatures: IndexedFeatureSource
|
readonly indexedFeatures: IndexedFeatureSource
|
||||||
readonly featureProperties: FeaturePropertiesStore
|
readonly featureProperties: FeaturePropertiesStore
|
||||||
}) {
|
}) {
|
||||||
const params = MetaTagging.createExtraFuncParams(state)
|
this.state = state
|
||||||
|
const params = this.params = MetaTagging.createExtraFuncParams(state)
|
||||||
for (const layer of state.layout.layers) {
|
for (const layer of state.layout.layers) {
|
||||||
if (layer.source === null) {
|
if (layer.source === null) {
|
||||||
continue
|
continue
|
||||||
|
@ -61,21 +77,55 @@ export default class MetaTagging {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
state.selectedElement.addCallbackAndRunD((feature) => {
|
// Force update the tags of the currently selected element
|
||||||
const layer = state.layout.getMatchingLayer(feature.properties)
|
state.selectedElement.addCallbackAndRunD(feature => {
|
||||||
// Force update the tags of the currently selected element
|
this.updateCurrentSelectedElement()
|
||||||
MetaTagging.addMetatags(
|
let lastUpdateMoment = new Date()
|
||||||
[feature],
|
const tags = state?.featureProperties?.getStore(feature.properties.id)
|
||||||
params,
|
console.log("Binding an updater to", feature)
|
||||||
layer,
|
tags?.addCallbackD(() => {
|
||||||
state.layout,
|
console.log("Received an update!")
|
||||||
state.osmObjectDownloader,
|
if(feature !== state.selectedElement.data){
|
||||||
state.featureProperties,
|
return true // Unregister, we are not the selected element anymore
|
||||||
{
|
|
||||||
evaluateStrict: true,
|
|
||||||
}
|
}
|
||||||
)
|
if(new Date().getTime() - lastUpdateMoment.getTime() < 250){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastUpdateMoment = new Date()
|
||||||
|
window.requestIdleCallback(() => {
|
||||||
|
this.updateCurrentSelectedElement()
|
||||||
|
lastUpdateMoment = new Date()
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers an update of the calculated tags of the selected element
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private updateCurrentSelectedElement() {
|
||||||
|
const feature = this.state.selectedElement.data
|
||||||
|
if (!feature) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const state = this.state
|
||||||
|
const layer = state.layout.getMatchingLayer(feature.properties)
|
||||||
|
// Force update if the tags of the element changed
|
||||||
|
MetaTagging.addMetatags(
|
||||||
|
[feature],
|
||||||
|
this.params,
|
||||||
|
layer,
|
||||||
|
state.layout,
|
||||||
|
state.osmObjectDownloader,
|
||||||
|
state.featureProperties,
|
||||||
|
{
|
||||||
|
evaluateStrict: true
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
|
@ -142,7 +192,7 @@ export default class MetaTagging {
|
||||||
const feature = features[i]
|
const feature = features[i]
|
||||||
const tags = featurePropertiesStores?.getStore(feature.properties.id)
|
const tags = featurePropertiesStores?.getStore(feature.properties.id)
|
||||||
let somethingChanged = false
|
let somethingChanged = false
|
||||||
let definedTags = new Set(Object.getOwnPropertyNames(feature.properties))
|
const definedTags = new Set(Object.getOwnPropertyNames(feature.properties))
|
||||||
|
|
||||||
for (const metatag of metatagsToApply) {
|
for (const metatag of metatagsToApply) {
|
||||||
try {
|
try {
|
||||||
|
@ -161,6 +211,7 @@ export default class MetaTagging {
|
||||||
metatag.applyMetaTagsOnFeature(feature, layer, tags, state)
|
metatag.applyMetaTagsOnFeature(feature, layer, tags, state)
|
||||||
if (options?.evaluateStrict) {
|
if (options?.evaluateStrict) {
|
||||||
for (const key of metatag.keys) {
|
for (const key of metatag.keys) {
|
||||||
|
// Important: we _have_ to evaluate this as this might trigger a calculation
|
||||||
const evaluated = feature.properties[key]
|
const evaluated = feature.properties[key]
|
||||||
if (evaluated !== undefined) {
|
if (evaluated !== undefined) {
|
||||||
strictlyEvaluated++
|
strictlyEvaluated++
|
||||||
|
@ -211,6 +262,7 @@ export default class MetaTagging {
|
||||||
atLeastOneFeatureChanged = true
|
atLeastOneFeatureChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.debug("Strictly evaluated ", strictlyEvaluated, " values") // Do not remove this
|
||||||
return atLeastOneFeatureChanged
|
return atLeastOneFeatureChanged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,12 +280,12 @@ export default class MetaTagging {
|
||||||
})
|
})
|
||||||
return feats
|
return feats
|
||||||
}
|
}
|
||||||
if(!state.perLayer.get(layerId)){
|
if (!state.perLayer.get(layerId)) {
|
||||||
// This layer is not loaded
|
// This layer is not loaded
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return [state.perLayer.get(layerId).GetFeaturesWithin(bbox)]
|
return [state.perLayer.get(layerId).GetFeaturesWithin(bbox)]
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,8 +330,8 @@ export default class MetaTagging {
|
||||||
if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) {
|
if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"Could not calculate a " +
|
"Could not calculate a " +
|
||||||
(isStrict ? "strict " : "") +
|
(isStrict ? "strict " : "") +
|
||||||
"calculated tag for key",
|
"calculated tag for key",
|
||||||
key,
|
key,
|
||||||
"for feature",
|
"for feature",
|
||||||
feat.properties.id,
|
feat.properties.id,
|
||||||
|
@ -287,9 +339,9 @@ export default class MetaTagging {
|
||||||
code,
|
code,
|
||||||
"(in layer",
|
"(in layer",
|
||||||
layerId +
|
layerId +
|
||||||
") due to \n" +
|
") due to \n" +
|
||||||
e +
|
e +
|
||||||
"\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features",
|
"\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features",
|
||||||
e,
|
e,
|
||||||
e.stack,
|
e.stack,
|
||||||
{ feat }
|
{ feat }
|
||||||
|
@ -328,7 +380,6 @@ export default class MetaTagging {
|
||||||
|
|
||||||
const funcName = "metaTaggging_for_" + id
|
const funcName = "metaTaggging_for_" + id
|
||||||
if (typeof MetaTagging.metataggingObject[funcName] !== "function") {
|
if (typeof MetaTagging.metataggingObject[funcName] !== "function") {
|
||||||
console.log(MetaTagging.metataggingObject)
|
|
||||||
throw (
|
throw (
|
||||||
"Error: metatagging-object for this theme does not have an entry at " +
|
"Error: metatagging-object for this theme does not have an entry at " +
|
||||||
funcName +
|
funcName +
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue