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-09-08 21:40:48 +02:00
)
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
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-09-08 21:40:48 +02:00
)
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-09-08 21:40:48 +02:00
)
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
2022-09-08 21:40:48 +02:00
)
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-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
2022-09-08 21:40:48 +02:00
)
2022-01-26 21:40:38 +01:00
) ,
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" )
2022-09-08 21:40:48 +02:00
)
) ,
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
}
}