2021-04-10 03:50:44 +02:00
import * as known_themes from "../assets/generated/known_layers_and_themes.json"
2021-08-07 23:11:34 +02:00
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" ;
2021-09-28 17:30:48 +02:00
import LayerConfig from "../Models/ThemeConfig/LayerConfig" ;
2021-11-08 02:36:01 +01:00
import BaseUIElement from "../UI/BaseUIElement" ;
import Combine from "../UI/Base/Combine" ;
import Title from "../UI/Base/Title" ;
import List from "../UI/Base/List" ;
2021-12-05 02:06:14 +01:00
import DependencyCalculator from "../Models/ThemeConfig/DependencyCalculator" ;
2021-12-21 18:35:31 +01:00
import Constants from "../Models/Constants" ;
import { Utils } from "../Utils" ;
2022-01-14 19:34:00 +01:00
import Link from "../UI/Base/Link" ;
2022-01-18 20:18:12 +01:00
import { LayoutConfigJson } from "../Models/ThemeConfig/Json/LayoutConfigJson" ;
2022-07-11 09:14:26 +02:00
import { LayerConfigJson } from "../Models/ThemeConfig/Json/LayerConfigJson" ;
2021-07-03 22:00:36 +02:00
2020-07-05 18:59:47 +02:00
export class AllKnownLayouts {
2021-04-10 03:50:44 +02:00
public static allKnownLayouts : Map < string , LayoutConfig > = AllKnownLayouts . AllLayouts ( ) ;
public static layoutsList : LayoutConfig [ ] = AllKnownLayouts . GenerateOrderedList ( AllKnownLayouts . allKnownLayouts ) ;
2022-01-26 21:40:38 +01:00
// Must be below the list...
private static sharedLayers : Map < string , LayerConfig > = AllKnownLayouts . getSharedLayers ( ) ;
2021-04-10 03:50:44 +02:00
2022-05-21 01:02:03 +02:00
public static AllPublicLayers ( options ? : {
includeInlineLayers :true | boolean
2022-07-12 10:23:45 +02:00
} ) : LayerConfig [ ] {
2021-11-07 16:34:51 +01:00
const allLayers : LayerConfig [ ] = [ ]
2021-09-28 17:30:48 +02:00
const seendIds = new Set < string > ( )
2022-04-28 00:26:19 +02:00
AllKnownLayouts . sharedLayers . forEach ( ( layer , key ) = > {
seendIds . add ( key )
allLayers . push ( layer )
} )
2022-05-21 01:02:03 +02:00
if ( options ? . includeInlineLayers ? ? true ) {
const publicLayouts = AllKnownLayouts . layoutsList . filter ( l = > ! l . hideFromOverview )
for ( const layout of publicLayouts ) {
if ( layout . hideFromOverview ) {
2021-09-28 17:30:48 +02:00
continue
}
2022-05-21 01:02:03 +02:00
for ( const layer of layout . layers ) {
if ( seendIds . has ( layer . id ) ) {
continue
}
seendIds . add ( layer . id )
allLayers . push ( layer )
}
2021-09-28 17:30:48 +02:00
2022-05-21 01:02:03 +02:00
}
2021-09-28 17:30:48 +02:00
}
2022-05-21 01:02:03 +02:00
2021-09-28 17:30:48 +02:00
return allLayers
}
2022-01-26 21:40:38 +01:00
2022-05-21 01:50:55 +02:00
/ * *
* Returns all themes which use the given layer , reverse sorted by minzoom . This sort maximizes the chances that the layer is prominently featured on the first theme
* /
2022-05-21 01:02:03 +02:00
public static themesUsingLayer ( id : string , publicOnly = true ) : LayoutConfig [ ] {
2022-05-21 01:50:55 +02:00
const themes = AllKnownLayouts . layoutsList
. filter ( l = > ! ( publicOnly && l . hideFromOverview ) && l . id !== "personal" )
. map ( theme = > ( { theme , minzoom : theme.layers.find ( layer = > layer . id === id ) ? . minzoom } ) )
. filter ( obj = > obj . minzoom !== undefined )
themes . sort ( ( th0 , th1 ) = > th1 . minzoom - th0 . minzoom )
return themes . map ( th = > th . theme ) ;
2022-05-21 01:02:03 +02:00
}
2022-04-06 16:12:01 +02:00
/ * *
* Generates documentation for the layers .
* Inline layers are included ( if the theme is public )
* @param callback
* @constructor
* /
public static GenOverviewsForSingleLayer ( callback : ( layer : LayerConfig , element : BaseUIElement , inlineSource : string ) = > void ) : void {
2022-01-15 02:55:52 +01:00
const allLayers : LayerConfig [ ] = Array . from ( AllKnownLayouts . sharedLayers . values ( ) )
. filter ( layer = > Constants . priviliged_layers . indexOf ( layer . id ) < 0 )
2022-01-14 19:34:00 +01:00
const builtinLayerIds : Set < string > = new Set < string > ( )
allLayers . forEach ( l = > builtinLayerIds . add ( l . id ) )
2022-04-06 16:12:01 +02:00
const inlineLayers = new Map < string , string > ( ) ;
for ( const layout of Array . from ( AllKnownLayouts . allKnownLayouts . values ( ) ) ) {
if ( layout . hideFromOverview ) {
continue
}
for ( const layer of layout . layers ) {
if ( Constants . priviliged_layers . indexOf ( layer . id ) >= 0 ) {
continue
}
if ( builtinLayerIds . has ( layer . id ) ) {
continue
}
2022-05-21 01:02:03 +02:00
if ( layer . source . geojsonSource !== undefined ) {
2022-04-06 16:12:01 +02:00
// Not an OSM-source
continue
}
allLayers . push ( layer )
builtinLayerIds . add ( layer . id )
inlineLayers . set ( layer . id , layout . id )
}
}
2022-01-14 19:34:00 +01:00
const themesPerLayer = new Map < string , string [ ] > ( )
for ( const layout of Array . from ( AllKnownLayouts . allKnownLayouts . values ( ) ) ) {
if ( layout . hideFromOverview ) {
continue
}
for ( const layer of layout . layers ) {
if ( ! builtinLayerIds . has ( layer . id ) ) {
2022-04-06 16:12:01 +02:00
// This is an inline layer
2022-01-14 19:34:00 +01:00
continue
}
if ( ! themesPerLayer . has ( layer . id ) ) {
themesPerLayer . set ( layer . id , [ ] )
}
themesPerLayer . get ( layer . id ) . push ( layout . id )
}
}
// Determine the cross-dependencies
2022-01-26 21:40:38 +01:00
const layerIsNeededBy : Map < string , string [ ] > = new Map < string , string [ ] > ( )
2022-01-14 19:34:00 +01:00
for ( const layer of allLayers ) {
for ( const dep of DependencyCalculator . getLayerDependencies ( layer ) ) {
const dependency = dep . neededLayer
2022-01-26 21:40:38 +01:00
if ( ! layerIsNeededBy . has ( dependency ) ) {
2022-01-14 19:34:00 +01:00
layerIsNeededBy . set ( dependency , [ ] )
}
layerIsNeededBy . get ( dependency ) . push ( layer . id )
}
}
2022-01-15 02:55:52 +01:00
allLayers . forEach ( ( layer ) = > {
2022-01-26 21:40:38 +01:00
const element = layer . GenerateDocumentation ( themesPerLayer . get ( layer . id ) , layerIsNeededBy , DependencyCalculator . getLayerDependencies ( layer ) )
2022-04-06 16:12:01 +02:00
callback ( layer , element , inlineLayers . get ( layer . id ) )
2022-01-14 19:34:00 +01:00
} )
}
2021-11-07 16:34:51 +01:00
2022-04-06 16:12:01 +02:00
/ * *
* Generates the documentation for the layers overview page
* @constructor
* /
2021-11-08 02:36:01 +01:00
public static GenLayerOverviewText ( ) : BaseUIElement {
2021-12-21 18:35:31 +01:00
for ( const id of Constants . priviliged_layers ) {
if ( ! AllKnownLayouts . sharedLayers . has ( id ) ) {
2021-11-08 02:36:01 +01:00
throw "Priviliged layer definition not found: " + id
}
}
2021-12-04 21:44:18 +01:00
2021-12-21 18:35:31 +01:00
const allLayers : LayerConfig [ ] = Array . from ( AllKnownLayouts . sharedLayers . values ( ) )
. filter ( layer = > Constants . priviliged_layers . indexOf ( layer . id ) < 0 )
2021-12-04 21:44:18 +01:00
const builtinLayerIds : Set < string > = new Set < string > ( )
allLayers . forEach ( l = > builtinLayerIds . add ( l . id ) )
2021-11-08 02:36:01 +01:00
const themesPerLayer = new Map < string , string [ ] > ( )
for ( const layout of Array . from ( AllKnownLayouts . allKnownLayouts . values ( ) ) ) {
for ( const layer of layout . layers ) {
2021-12-04 21:44:18 +01:00
if ( ! builtinLayerIds . has ( layer . id ) ) {
continue
}
2021-11-08 02:36:01 +01:00
if ( ! themesPerLayer . has ( layer . id ) ) {
themesPerLayer . set ( layer . id , [ ] )
}
themesPerLayer . get ( layer . id ) . push ( layout . id )
}
}
2021-12-05 02:06:14 +01:00
// Determine the cross-dependencies
2022-01-26 21:40:38 +01:00
const layerIsNeededBy : Map < string , string [ ] > = new Map < string , string [ ] > ( )
2021-12-05 02:06:14 +01:00
for ( const layer of allLayers ) {
for ( const dep of DependencyCalculator . getLayerDependencies ( layer ) ) {
const dependency = dep . neededLayer
2022-01-26 21:40:38 +01:00
if ( ! layerIsNeededBy . has ( dependency ) ) {
2021-12-05 02:06:14 +01:00
layerIsNeededBy . set ( dependency , [ ] )
}
layerIsNeededBy . get ( dependency ) . push ( layer . id )
}
2022-01-26 21:40:38 +01:00
2021-12-05 02:06:14 +01:00
}
2022-01-26 21:40:38 +01:00
2021-11-08 02:36:01 +01:00
return new Combine ( [
new Title ( "Special and other useful layers" , 1 ) ,
"MapComplete has a few data layers available in the theme which have special properties through builtin-hooks. Furthermore, there are some normal layers (which are built from normal Theme-config files) but are so general that they get a mention here." ,
new Title ( "Priviliged layers" , 1 ) ,
2021-12-21 18:35:31 +01:00
new List ( Constants . priviliged_layers . map ( id = > "[" + id + "](#" + id + ")" ) ) ,
. . . Constants . priviliged_layers
. map ( id = > AllKnownLayouts . sharedLayers . get ( id ) )
2022-01-26 21:40:38 +01:00
. map ( ( l ) = > l . GenerateDocumentation ( themesPerLayer . get ( l . id ) , layerIsNeededBy , DependencyCalculator . getLayerDependencies ( l ) , Constants . added_by_default . indexOf ( l . id ) >= 0 , Constants . no_include . indexOf ( l . id ) < 0 ) ) ,
2021-12-04 21:44:18 +01:00
new Title ( "Normal layers" , 1 ) ,
2022-01-14 19:34:00 +01:00
"The following layers are included in MapComplete:" ,
2022-01-26 21:40:38 +01:00
new List ( Array . from ( AllKnownLayouts . sharedLayers . keys ( ) ) . map ( id = > new Link ( id , "./Layers/" + id + ".md" ) ) )
2021-11-08 02:36:01 +01:00
] )
}
2022-05-21 01:02:03 +02:00
public static GenerateDocumentationForTheme ( theme : LayoutConfig ) : BaseUIElement {
return new Combine ( [
new Title ( new Combine ( [ theme . title , "(" , theme . id + ")" ] ) , 2 ) ,
theme . description ,
"This theme contains the following layers:" ,
new List ( theme . layers . map ( l = > l . id ) ) ,
"Available languages:" ,
new List ( theme . language )
] )
}
2022-07-11 09:14:26 +02:00
public static getSharedLayers ( ) : Map < string , LayerConfig > {
2022-01-26 21:40:38 +01:00
const sharedLayers = new Map < string , LayerConfig > ( ) ;
2022-07-11 09:14:26 +02:00
for ( const layer of known_themes [ "layers" ] ) {
2022-01-26 21:40:38 +01:00
try {
// @ts-ignore
const parsed = new LayerConfig ( layer , "shared_layers" )
sharedLayers . set ( layer . id , parsed ) ;
} catch ( e ) {
if ( ! Utils . runningFromConsole ) {
console . error ( "CRITICAL: Could not parse a layer configuration!" , layer . id , " due to" , e )
}
}
}
return sharedLayers ;
}
2022-07-11 09:14:26 +02:00
public static getSharedLayersConfigs ( ) : Map < string , LayerConfigJson > {
const sharedLayers = new Map < string , LayerConfigJson > ( ) ;
for ( const layer of known_themes [ "layers" ] ) {
// @ts-ignore
sharedLayers . set ( layer . id , layer ) ;
}
return sharedLayers ;
}
2021-04-10 03:50:44 +02:00
private static GenerateOrderedList ( allKnownLayouts : Map < string , LayoutConfig > ) : LayoutConfig [ ] {
const list = [ ]
2022-01-15 02:55:52 +01:00
allKnownLayouts . forEach ( ( layout ) = > {
2021-12-21 18:35:31 +01:00
list . push ( layout )
2021-04-10 03:50:44 +02:00
} )
return list ;
}
2020-11-11 16:23:49 +01:00
private static AllLayouts ( ) : Map < string , LayoutConfig > {
2021-04-10 03:50:44 +02:00
const dict : Map < string , LayoutConfig > = new Map ( ) ;
2022-07-11 09:14:26 +02:00
for ( const layoutConfigJson of known_themes [ "themes" ] ) {
2022-04-06 16:12:01 +02:00
const layout = new LayoutConfig ( < LayoutConfigJson > layoutConfigJson , true )
2022-01-26 21:40:38 +01:00
dict . set ( layout . id , layout )
for ( let i = 0 ; i < layout . layers . length ; i ++ ) {
let layer = layout . layers [ i ] ;
if ( typeof ( layer ) === "string" ) {
layer = AllKnownLayouts . sharedLayers . get ( layer ) ;
layout . layers [ i ] = layer
if ( layer === undefined ) {
console . log ( "Defined layers are " , AllKnownLayouts . sharedLayers . keys ( ) )
throw ` Layer ${ layer } was not found or defined - probably a type was made `
}
}
}
2020-07-25 01:07:02 +02:00
}
2021-04-10 03:50:44 +02:00
return dict ;
2020-07-05 18:59:47 +02:00
}
2020-07-15 15:55:08 +02:00
2020-07-05 18:59:47 +02:00
}