2021-03-24 01:25:57 +01:00
import SimpleMetaTagger from "./SimpleMetaTagger" ;
2021-12-05 02:06:14 +01:00
import { ExtraFuncParams , ExtraFunctions } from "./ExtraFunctions" ;
2021-08-07 23:11:34 +02:00
import LayerConfig from "../Models/ThemeConfig/LayerConfig" ;
2021-09-26 17:36:39 +02:00
import State from "../State" ;
2021-04-22 13:30:00 +02:00
2020-10-19 12:08:42 +02:00
/ * *
* Metatagging adds various tags to the elements , e . g . lat , lon , surface area , . . .
*
* All metatags start with an underscore
* /
export default class MetaTagging {
2021-09-09 00:05:51 +02:00
private static errorPrintCount = 0 ;
private static readonly stopErrorOutputAt = 10 ;
2021-03-24 01:25:57 +01:00
/ * *
2021-09-21 02:10:42 +02:00
* This method ( re ) calculates all metatags and calculated tags on every given object .
* The given features should be part of the given layer
2021-11-07 16:34:51 +01:00
*
2021-10-27 20:19:45 +02:00
* Returns true if at least one feature has changed properties
2021-03-24 01:25:57 +01:00
* /
2021-09-22 05:02:09 +02:00
public static addMetatags ( features : { feature : any ; freshness : Date } [ ] ,
2021-09-26 17:36:39 +02:00
params : ExtraFuncParams ,
layer : LayerConfig ,
options ? : {
includeDates? : true | boolean ,
includeNonDates? : true | boolean
2021-10-27 20:19:45 +02:00
} ) : boolean {
2021-07-26 20:21:05 +02:00
if ( features === undefined || features . length === 0 ) {
2021-06-21 03:13:49 +02:00
return ;
}
2020-10-30 00:56:46 +01:00
2021-09-22 05:02:09 +02:00
2021-10-10 23:38:09 +02:00
const metatagsToApply : SimpleMetaTagger [ ] = [ ]
for ( const metatag of SimpleMetaTagger . metatags ) {
if ( metatag . includesDates ) {
if ( options . includeDates ? ? true ) {
metatagsToApply . push ( metatag )
}
} else {
if ( options . includeNonDates ? ? true ) {
metatagsToApply . push ( metatag )
2021-09-22 05:02:09 +02:00
}
2020-10-30 00:56:46 +01:00
}
2021-10-10 23:38:09 +02:00
}
2020-10-30 00:56:46 +01:00
2021-09-26 17:36:39 +02:00
// The calculated functions - per layer - which add the new keys
2021-09-21 02:10:42 +02:00
const layerFuncs = this . createRetaggingFunc ( layer )
2021-05-13 12:40:19 +02:00
2021-10-27 20:19:45 +02:00
let atLeastOneFeatureChanged = false ;
2020-10-30 00:56:46 +01:00
2021-09-26 17:36:39 +02:00
for ( let i = 0 ; i < features . length ; i ++ ) {
2021-10-10 23:38:09 +02:00
const ff = features [ i ] ;
const feature = ff . feature
const freshness = ff . freshness
let somethingChanged = false
for ( const metatag of metatagsToApply ) {
try {
if ( ! metatag . keys . some ( key = > feature . properties [ key ] === undefined ) ) {
// All keys are already defined, we probably already ran this one
continue
}
2021-11-07 16:34:51 +01:00
if ( metatag . isLazy ) {
2021-10-10 23:38:09 +02:00
somethingChanged = true ;
2021-11-07 16:34:51 +01:00
2021-10-12 02:12:45 +02:00
metatag . applyMetaTagsOnFeature ( feature , freshness , layer )
2021-11-07 16:34:51 +01:00
} else {
2021-10-12 02:12:45 +02:00
const newValueAdded = metatag . applyMetaTagsOnFeature ( feature , freshness , layer )
2021-10-04 00:18:08 +02:00
/ * N o t e t h a t t h e e x p r e s s i o n :
* ` somethingChanged = newValueAdded || metatag.applyMetaTagsOnFeature(feature, freshness) `
* Is WRONG
*
* IF something changed is ` true ` due to an earlier run , it will short - circuit and _not_ evaluate the right hand of the OR ,
* thus not running an update !
* /
somethingChanged = newValueAdded || somethingChanged
2021-09-26 17:36:39 +02:00
}
2021-10-10 23:38:09 +02:00
} catch ( e ) {
console . error ( "Could not calculate metatag for " , metatag . keys . join ( "," ) , ":" , e , e . stack )
2021-06-20 03:09:26 +02:00
}
}
2020-10-30 00:56:46 +01:00
2021-10-10 23:38:09 +02:00
if ( layerFuncs !== undefined ) {
try {
layerFuncs ( params , feature )
} catch ( e ) {
console . error ( e )
}
somethingChanged = true
}
2021-09-26 17:36:39 +02:00
2021-10-10 23:38:09 +02:00
if ( somethingChanged ) {
State . state ? . allElements ? . getEventSourceById ( feature . properties . id ) ? . ping ( )
2021-10-27 20:19:45 +02:00
atLeastOneFeatureChanged = true
2021-10-10 23:38:09 +02:00
}
2020-10-30 00:56:46 +01:00
}
2021-10-27 20:19:45 +02:00
return atLeastOneFeatureChanged
2021-10-10 23:38:09 +02:00
}
2021-03-22 02:45:22 +01:00
2021-12-05 05:20:33 +01:00
public static createFunctionsForFeature ( layerId : string , calculatedTags : [ string , string ] [ ] ) : ( ( feature : any ) = > void ) [ ] {
2021-10-10 23:38:09 +02:00
const functions : ( ( feature : any ) = > void ) [ ] = [ ] ;
2021-03-24 01:25:57 +01:00
for ( const entry of calculatedTags ) {
const key = entry [ 0 ]
const code = entry [ 1 ] ;
if ( code === undefined ) {
continue ;
2021-03-22 01:04:25 +01:00
}
2021-09-21 02:10:42 +02:00
2021-03-24 01:25:57 +01:00
const func = new Function ( "feat" , "return " + code + ";" ) ;
2021-03-22 01:04:25 +01:00
2021-10-10 23:38:09 +02:00
const f = ( feature : any ) = > {
delete feature . properties [ key ]
2021-09-09 00:05:51 +02:00
2021-10-10 23:38:09 +02:00
Object . defineProperty ( feature . properties , key , {
configurable : true ,
enumerable : false , // By setting this as not enumerable, the localTileSaver will _not_ calculate this
get : function ( ) {
try {
// Lazyness for the win!
let result = func ( feature ) ;
if ( result === "" ) {
result === undefined
}
if ( result !== undefined && typeof result !== "string" ) {
// Make sure it is a string!
result = JSON . stringify ( result ) ;
}
delete feature . properties [ key ]
feature . properties [ key ] = result ;
return result ;
} catch ( e ) {
if ( MetaTagging . errorPrintCount < MetaTagging . stopErrorOutputAt ) {
2021-12-05 05:20:33 +01:00
console . warn ( "Could not calculate a calculated tag for key " + key + " defined by " + code + " (in layer" + layerId + ") due to \n" + e + "\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features" , e , e . stack )
2021-10-10 23:38:09 +02:00
MetaTagging . errorPrintCount ++ ;
if ( MetaTagging . errorPrintCount == MetaTagging . stopErrorOutputAt ) {
console . error ( "Got " , MetaTagging . stopErrorOutputAt , " errors calculating this metatagging - stopping output now" )
}
2021-06-21 03:13:49 +02:00
}
}
2021-11-07 16:34:51 +01:00
}
} )
2021-05-13 12:40:19 +02:00
2021-05-10 23:51:03 +02:00
}
2021-11-07 16:34:51 +01:00
2021-10-10 23:38:09 +02:00
functions . push ( f )
2021-02-20 03:29:55 +01:00
}
2021-10-10 23:38:09 +02:00
return functions ;
}
private static createRetaggingFunc ( layer : LayerConfig ) :
( ( params : ExtraFuncParams , feature : any ) = > void ) {
const calculatedTags : [ string , string ] [ ] = layer . calculatedTags ;
if ( calculatedTags === undefined || calculatedTags . length === 0 ) {
return undefined ;
}
2021-09-21 02:10:42 +02:00
return ( params : ExtraFuncParams , feature ) = > {
2021-03-24 01:25:57 +01:00
const tags = feature . properties
if ( tags === undefined ) {
return ;
2020-11-11 16:23:49 +01:00
}
2021-03-22 02:45:22 +01:00
2021-03-26 03:24:58 +01:00
try {
2021-12-05 05:20:33 +01:00
const functions = MetaTagging . createFunctionsForFeature ( layer . id , calculatedTags )
2021-10-10 23:38:09 +02:00
2021-12-05 02:06:14 +01:00
ExtraFunctions . FullPatchFeature ( params , feature ) ;
2021-03-26 03:24:58 +01:00
for ( const f of functions ) {
2021-10-10 23:38:09 +02:00
f ( feature ) ;
2021-03-24 01:25:57 +01:00
}
2021-10-10 23:38:09 +02:00
State . state ? . allElements ? . getEventSourceById ( feature . properties . id ) ? . ping ( ) ;
2021-03-26 03:24:58 +01:00
} catch ( e ) {
2021-10-10 23:38:09 +02:00
console . error ( "Invalid syntax in calculated tags or some other error: " , e )
2021-03-24 01:25:57 +01:00
}
2021-03-22 01:04:25 +01:00
}
}
2021-03-25 15:19:44 +01:00
2020-10-19 12:08:42 +02:00
}