diff --git a/Docs/Schemas/LayoutConfigJson.schema.json b/Docs/Schemas/LayoutConfigJson.schema.json index 5932671e8..4078fbd26 100644 --- a/Docs/Schemas/LayoutConfigJson.schema.json +++ b/Docs/Schemas/LayoutConfigJson.schema.json @@ -6,14 +6,11 @@ "description": "question: What is the id of this layout?\n\nThe id is a unique string to identify the theme\n\nIt should be\n- in english\n- describe the theme in a single word (or a few words)\n- all lowercase and with only [a-z] or underscores (_)\n\nThis is used as hashtag in the changeset message, which will read something like \"Adding data with #mapcomplete for theme #\"\n\nOn official themes, it'll become the name of the page, e.g.\n'cyclestreets' which become 'cyclestreets.html'\n\ntype: id\ngroup: basic", "type": "string" }, - "credits": { - "description": "Who helped to create this theme and should be attributed?", + "title": { + "description": "question: What is the title of this theme?\n\nThe human-readable title, as shown in the welcome message and the index page\ngroup: basic", "anyOf": [ { - "type": "array", - "items": { - "type": "string" - } + "$ref": "#/definitions/Record" }, { "type": "string" @@ -27,8 +24,8 @@ "type": "string" } }, - "title": { - "description": "question: What is the title of this theme?\n\nThe human-readable title, as shown in the welcome message and the index page\ngroup: basic", + "description": { + "description": "question: How would you describe this theme?\nThe description, as shown in the welcome message and the more-screen\ngroup: basic", "anyOf": [ { "$ref": "#/definitions/Record" @@ -49,17 +46,6 @@ } ] }, - "description": { - "description": "question: How would you describe this theme?\nThe description, as shown in the welcome message and the more-screen\ngroup: basic", - "anyOf": [ - { - "$ref": "#/definitions/Record" - }, - { - "type": "string" - } - ] - }, "descriptionTail": { "description": "A part of the description, shown under the login-button.\ngroup: hidden", "anyOf": [ @@ -79,6 +65,10 @@ "description": "question: What image should be used as social image preview?\nThis is included as og:image-tag on official themes.\n\nSee https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit for more information\nifunset: use the default social image of mapcomplete (or generate one based on the icon)\nType: image\ngroup: basic", "type": "string" }, + "extraLink": { + "description": "question: should an extra help button be shown in certain circumstances?\nAdds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\n\nFor example {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]},\n\ngroup: advanced\nifunset: show a link to open MapComplete full screen if used in an iframe", + "$ref": "#/definitions/default" + }, "startZoom": { "description": "question: At what zoomlevel should this theme open?\nDefault location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used\nifunset: Use the default startzoom (0)\ntype: float\ngroup: start_location", "type": "number" @@ -91,44 +81,27 @@ "description": "question: At what start longitude should this theme open?\nDefault location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used\nifunset: Use 0 as start longitude\ntype: float\ngroup: start_location", "type": "number" }, - "widenFactor": { - "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\n\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3", - "type": "number" - }, - "overpassMaxZoom": { - "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used.", - "type": "number" - }, - "osmApiTileSize": { - "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here\nDefault: overpassMaxZoom + 1", - "type": "number" - }, - "overrideAll": { - "description": "An override applied on all layers of the theme.\n\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\n\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\n\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\n\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer", - "$ref": "#/definitions/Partial" - }, "defaultBackgroundId": { "description": "The id of the default background. BY default: vanilla OSM", "type": "string" }, - "tileLayerSources": { - "description": "Define some (overlay) slippy map tilesources", - "type": "array", - "items": { - "allOf": [ - { - "$ref": "#/definitions/RasterLayerProperties" - }, - { - "type": "object", - "properties": { - "defaultState": { - "type": "boolean" - } - } + "credits": { + "description": "Who helped to create this theme and should be attributed?", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" } - ] - } + }, + { + "type": "string" + } + ] + }, + "hideFromOverview": { + "description": "If set to true, this layout will not be shown in the overview with more themes", + "type": "boolean" }, "layers": { "description": "question: What layers should this map show?\ntype: layer[]\ntypes: hidden | layer | hidden\ngroup: layers\nsuggestions: return Array.from(layers.keys()).map(key => ({if: \"value=\"+key, then: key+\" - \"+layers.get(key).description}))\nEvery layer contains a description of which feature to display - the overpassTags which are queried.\nInstead of running one query for every layer, the query is fused.\n\nAfterwards, every layer is given the list of features.\nEvery layer takes away the features that match with them*, and give the leftovers to the next layers.\n\nThis implies that the _order_ of the layers is important in the case of features with the same tags;\nas the later layers might never receive their feature.\n\n*layers can also remove 'leftover'-features if the leftovers overlap with a feature in the layer itself\n\nNote that builtin layers can be reused. Either put in the name of the layer to reuse, or use {builtin: \"layername\", override: ...}\n\nThe 'override'-object will be copied over the original values of the layer, which allows to change certain aspects of the layer\n\nFor example: If you would like to use layer nature reserves, but only from a specific operator (eg. Natuurpunt) you would use the following in your theme:\n\n```\n\"layer\": {\n \"builtin\": \"nature_reserve\",\n \"override\": {\"source\":\n {\"osmTags\": {\n \"+and\":[\"operator=Natuurpunt\"]\n }\n }\n }\n}\n```\n\nIt's also possible to load multiple layers at once, for example, if you would like for both drinking water and benches to start at the zoomlevel at 12, you would use the following:\n\n```\n\"layer\": {\n \"builtin\": [\"benches\", \"drinking_water\"],\n \"override\": {\"minzoom\": 12}\n}\n```", @@ -176,14 +149,33 @@ ] } }, + "overrideAll": { + "description": "An override applied on all layers of the theme.\n\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\n\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\n\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\n\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer", + "$ref": "#/definitions/Partial" + }, + "tileLayerSources": { + "description": "Define some (overlay) slippy map tilesources", + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/definitions/RasterLayerProperties" + }, + { + "type": "object", + "properties": { + "defaultState": { + "type": "boolean" + } + } + } + ] + } + }, "customCss": { "description": "The URL of a custom CSS stylesheet to modify the layout\ngroup: advanced", "type": "string" }, - "hideFromOverview": { - "description": "If set to true, this layout will not be shown in the overview with more themes", - "type": "boolean" - }, "lockLocation": { "description": "If set to true, the basemap will not scroll outside of the area visible on initial zoom.\nIf set to [[lon, lat], [lon, lat]], the map will not scroll outside of those bounds.\nOff by default, which will enable panning to the entire world", "anyOf": [ @@ -231,10 +223,6 @@ } ] }, - "extraLink": { - "description": "question: should an extra help button be shown in certain circumstances?\nAdds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\n\nFor example {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]},\n\ngroup: advanced\nifunset: show a link to open MapComplete full screen if used in an iframe", - "$ref": "#/definitions/default" - }, "enableUserBadge": { "description": "question: Should a user be able to login with OpenStreetMap?\n\nIf not logged in, will not show the login buttons and hide all the editable elements.\nAs such, MapComplete will become read-only and a purely visualisation tool.\n\nifunset: Enable the possiblity to login with OpenStreetMap (default)\niffalse: Do not enable to login with OpenStreetMap, have a read-only view of MapComplete.\niftrue: Enable the possiblity to login with OpenStreetMap\ngroup: feature_switches", "type": "boolean" @@ -294,6 +282,18 @@ "description": "question: After how much seconds should the overpass-query stop?\nIf a query takes too long, the overpass-server will abort.\nOnce can set the amount of time before overpass gives up here.\nifunset: use the default amount of 30 seconds as timeout\ntype: pnat\ngroup: advanced", "type": "number" }, + "widenFactor": { + "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\n\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3", + "type": "number" + }, + "overpassMaxZoom": { + "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used.", + "type": "number" + }, + "osmApiTileSize": { + "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here\nDefault: overpassMaxZoom + 1", + "type": "number" + }, "enableNodeDatabase": { "description": "Enables tracking of all nodes when data is loaded.\nThis is useful for the 'ImportWay' and 'ConflateWay'-buttons who need this database.\n\nNote: this flag will be automatically set and can thus be ignored.\ngroup: hidden", "type": "boolean" @@ -1718,15 +1718,15 @@ ], "additionalProperties": false }, - "Partial": { - "type": "object", - "additionalProperties": false - }, - "RasterLayerProperties": { + "default": { "type": "object", "properties": { - "name": { - "description": "The name of the imagery source", + "icon": { + "description": "question: What icon should be shown in the link button?\nifunset: do not show an icon\ntype: icon", + "type": "string" + }, + "text": { + "description": "question: What text should be shown in the link icon?\n\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\nifunset: do not show a text", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1736,52 +1736,30 @@ } ] }, - "isOverlay": { + "href": { + "description": "question: if clicked, what webpage should open?\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\ntype: url", + "type": "string" + }, + "newTab": { + "description": "question: Should the link open in a new tab?\niftrue: Open in a new tab\niffalse: do not open in a new tab\nifunset: do not open in a new tab", "type": "boolean" }, - "id": { - "type": "string" - }, - "url": { - "type": "string" - }, - "category": { - "type": "string" - }, - "type": { - "type": "string" - }, - "attribution": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "text": { - "type": "string" - }, - "html": { - "type": "string" - }, - "required": { - "type": "boolean" - } + "requirements": { + "description": "question: When should the extra button be shown?\nsuggestions: return [{if: \"value=iframe\", then: \"When shown in an iframe\"}, {if: \"value=no-iframe\", then: \"When shown as stand-alone webpage\"}, {if: \"value=welcome-message\", then: \"When the welcome messages are enabled\"}, {if: \"value=iframe\", then: \"When the welcome messages are disabled\"}]", + "type": "array", + "items": { + "enum": [ + "iframe", + "no-iframe", + "no-welcome-message", + "welcome-message" + ], + "type": "string" } - }, - "min_zoom": { - "type": "number" - }, - "max_zoom": { - "type": "number" - }, - "best": { - "type": "boolean" } }, "required": [ - "id", - "name", - "url" + "href" ], "additionalProperties": false }, @@ -2581,15 +2559,15 @@ }, "additionalProperties": false }, - "default": { + "Partial": { + "type": "object", + "additionalProperties": false + }, + "RasterLayerProperties": { "type": "object", "properties": { - "icon": { - "description": "question: What icon should be shown in the link button?\nifunset: do not show an icon\ntype: icon", - "type": "string" - }, - "text": { - "description": "question: What text should be shown in the link icon?\n\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\nifunset: do not show a text", + "name": { + "description": "The name of the imagery source", "anyOf": [ { "$ref": "#/definitions/Record" @@ -2599,30 +2577,52 @@ } ] }, - "href": { - "description": "question: if clicked, what webpage should open?\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\ntype: url", - "type": "string" - }, - "newTab": { - "description": "question: Should the link open in a new tab?\niftrue: Open in a new tab\niffalse: do not open in a new tab\nifunset: do not open in a new tab", + "isOverlay": { "type": "boolean" }, - "requirements": { - "description": "question: When should the extra button be shown?\nsuggestions: return [{if: \"value=iframe\", then: \"When shown in an iframe\"}, {if: \"value=no-iframe\", then: \"When shown as stand-alone webpage\"}, {if: \"value=welcome-message\", then: \"When the welcome messages are enabled\"}, {if: \"value=iframe\", then: \"When the welcome messages are disabled\"}]", - "type": "array", - "items": { - "enum": [ - "iframe", - "no-iframe", - "no-welcome-message", - "welcome-message" - ], - "type": "string" + "id": { + "type": "string" + }, + "url": { + "type": "string" + }, + "category": { + "type": "string" + }, + "type": { + "type": "string" + }, + "attribution": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "text": { + "type": "string" + }, + "html": { + "type": "string" + }, + "required": { + "type": "boolean" + } } + }, + "min_zoom": { + "type": "number" + }, + "max_zoom": { + "type": "number" + }, + "best": { + "type": "boolean" } }, "required": [ - "href" + "id", + "name", + "url" ], "additionalProperties": false } diff --git a/Docs/Schemas/LayoutConfigJsonJSC.ts b/Docs/Schemas/LayoutConfigJsonJSC.ts index 244a561c5..052ddf813 100644 --- a/Docs/Schemas/LayoutConfigJsonJSC.ts +++ b/Docs/Schemas/LayoutConfigJsonJSC.ts @@ -6,14 +6,11 @@ export default { "description": "question: What is the id of this layout?\n\nThe id is a unique string to identify the theme\n\nIt should be\n- in english\n- describe the theme in a single word (or a few words)\n- all lowercase and with only [a-z] or underscores (_)\n\nThis is used as hashtag in the changeset message, which will read something like \"Adding data with #mapcomplete for theme #\"\n\nOn official themes, it'll become the name of the page, e.g.\n'cyclestreets' which become 'cyclestreets.html'\n\ntype: id\ngroup: basic", "type": "string" }, - "credits": { - "description": "Who helped to create this theme and should be attributed?", + "title": { + "description": "question: What is the title of this theme?\n\nThe human-readable title, as shown in the welcome message and the index page\ngroup: basic", "anyOf": [ { - "type": "array", - "items": { - "type": "string" - } + "$ref": "#/definitions/Record" }, { "type": "string" @@ -27,8 +24,8 @@ export default { "type": "string" } }, - "title": { - "description": "question: What is the title of this theme?\n\nThe human-readable title, as shown in the welcome message and the index page\ngroup: basic", + "description": { + "description": "question: How would you describe this theme?\nThe description, as shown in the welcome message and the more-screen\ngroup: basic", "anyOf": [ { "$ref": "#/definitions/Record" @@ -49,17 +46,6 @@ export default { } ] }, - "description": { - "description": "question: How would you describe this theme?\nThe description, as shown in the welcome message and the more-screen\ngroup: basic", - "anyOf": [ - { - "$ref": "#/definitions/Record" - }, - { - "type": "string" - } - ] - }, "descriptionTail": { "description": "A part of the description, shown under the login-button.\ngroup: hidden", "anyOf": [ @@ -79,6 +65,10 @@ export default { "description": "question: What image should be used as social image preview?\nThis is included as og:image-tag on official themes.\n\nSee https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit for more information\nifunset: use the default social image of mapcomplete (or generate one based on the icon)\nType: image\ngroup: basic", "type": "string" }, + "extraLink": { + "description": "question: should an extra help button be shown in certain circumstances?\nAdds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\n\nFor example {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]},\n\ngroup: advanced\nifunset: show a link to open MapComplete full screen if used in an iframe", + "$ref": "#/definitions/default" + }, "startZoom": { "description": "question: At what zoomlevel should this theme open?\nDefault location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used\nifunset: Use the default startzoom (0)\ntype: float\ngroup: start_location", "type": "number" @@ -91,44 +81,27 @@ export default { "description": "question: At what start longitude should this theme open?\nDefault location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used\nifunset: Use 0 as start longitude\ntype: float\ngroup: start_location", "type": "number" }, - "widenFactor": { - "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\n\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3", - "type": "number" - }, - "overpassMaxZoom": { - "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used.", - "type": "number" - }, - "osmApiTileSize": { - "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here\nDefault: overpassMaxZoom + 1", - "type": "number" - }, - "overrideAll": { - "description": "An override applied on all layers of the theme.\n\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\n\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\n\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\n\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer", - "$ref": "#/definitions/Partial" - }, "defaultBackgroundId": { "description": "The id of the default background. BY default: vanilla OSM", "type": "string" }, - "tileLayerSources": { - "description": "Define some (overlay) slippy map tilesources", - "type": "array", - "items": { - "allOf": [ - { - "$ref": "#/definitions/RasterLayerProperties" - }, - { - "type": "object", - "properties": { - "defaultState": { - "type": "boolean" - } - } + "credits": { + "description": "Who helped to create this theme and should be attributed?", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" } - ] - } + }, + { + "type": "string" + } + ] + }, + "hideFromOverview": { + "description": "If set to true, this layout will not be shown in the overview with more themes", + "type": "boolean" }, "layers": { "description": "question: What layers should this map show?\ntype: layer[]\ntypes: hidden | layer | hidden\ngroup: layers\nsuggestions: return Array.from(layers.keys()).map(key => ({if: \"value=\"+key, then: key+\" - \"+layers.get(key).description}))\nEvery layer contains a description of which feature to display - the overpassTags which are queried.\nInstead of running one query for every layer, the query is fused.\n\nAfterwards, every layer is given the list of features.\nEvery layer takes away the features that match with them*, and give the leftovers to the next layers.\n\nThis implies that the _order_ of the layers is important in the case of features with the same tags;\nas the later layers might never receive their feature.\n\n*layers can also remove 'leftover'-features if the leftovers overlap with a feature in the layer itself\n\nNote that builtin layers can be reused. Either put in the name of the layer to reuse, or use {builtin: \"layername\", override: ...}\n\nThe 'override'-object will be copied over the original values of the layer, which allows to change certain aspects of the layer\n\nFor example: If you would like to use layer nature reserves, but only from a specific operator (eg. Natuurpunt) you would use the following in your theme:\n\n```\n\"layer\": {\n \"builtin\": \"nature_reserve\",\n \"override\": {\"source\":\n {\"osmTags\": {\n \"+and\":[\"operator=Natuurpunt\"]\n }\n }\n }\n}\n```\n\nIt's also possible to load multiple layers at once, for example, if you would like for both drinking water and benches to start at the zoomlevel at 12, you would use the following:\n\n```\n\"layer\": {\n \"builtin\": [\"benches\", \"drinking_water\"],\n \"override\": {\"minzoom\": 12}\n}\n```", @@ -176,14 +149,33 @@ export default { ] } }, + "overrideAll": { + "description": "An override applied on all layers of the theme.\n\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\n\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\n\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\n\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer", + "$ref": "#/definitions/Partial" + }, + "tileLayerSources": { + "description": "Define some (overlay) slippy map tilesources", + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/definitions/RasterLayerProperties" + }, + { + "type": "object", + "properties": { + "defaultState": { + "type": "boolean" + } + } + } + ] + } + }, "customCss": { "description": "The URL of a custom CSS stylesheet to modify the layout\ngroup: advanced", "type": "string" }, - "hideFromOverview": { - "description": "If set to true, this layout will not be shown in the overview with more themes", - "type": "boolean" - }, "lockLocation": { "description": "If set to true, the basemap will not scroll outside of the area visible on initial zoom.\nIf set to [[lon, lat], [lon, lat]], the map will not scroll outside of those bounds.\nOff by default, which will enable panning to the entire world", "anyOf": [ @@ -231,10 +223,6 @@ export default { } ] }, - "extraLink": { - "description": "question: should an extra help button be shown in certain circumstances?\nAdds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\n\nFor example {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]},\n\ngroup: advanced\nifunset: show a link to open MapComplete full screen if used in an iframe", - "$ref": "#/definitions/default" - }, "enableUserBadge": { "description": "question: Should a user be able to login with OpenStreetMap?\n\nIf not logged in, will not show the login buttons and hide all the editable elements.\nAs such, MapComplete will become read-only and a purely visualisation tool.\n\nifunset: Enable the possiblity to login with OpenStreetMap (default)\niffalse: Do not enable to login with OpenStreetMap, have a read-only view of MapComplete.\niftrue: Enable the possiblity to login with OpenStreetMap\ngroup: feature_switches", "type": "boolean" @@ -294,6 +282,18 @@ export default { "description": "question: After how much seconds should the overpass-query stop?\nIf a query takes too long, the overpass-server will abort.\nOnce can set the amount of time before overpass gives up here.\nifunset: use the default amount of 30 seconds as timeout\ntype: pnat\ngroup: advanced", "type": "number" }, + "widenFactor": { + "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\n\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3", + "type": "number" + }, + "overpassMaxZoom": { + "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used.", + "type": "number" + }, + "osmApiTileSize": { + "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here\nDefault: overpassMaxZoom + 1", + "type": "number" + }, "enableNodeDatabase": { "description": "Enables tracking of all nodes when data is loaded.\nThis is useful for the 'ImportWay' and 'ConflateWay'-buttons who need this database.\n\nNote: this flag will be automatically set and can thus be ignored.\ngroup: hidden", "type": "boolean" @@ -1698,14 +1698,15 @@ export default { "appliesToKey" ] }, - "Partial": { - "type": "object" - }, - "RasterLayerProperties": { + "default": { "type": "object", "properties": { - "name": { - "description": "The name of the imagery source", + "icon": { + "description": "question: What icon should be shown in the link button?\nifunset: do not show an icon\ntype: icon", + "type": "string" + }, + "text": { + "description": "question: What text should be shown in the link icon?\n\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\nifunset: do not show a text", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1715,52 +1716,30 @@ export default { } ] }, - "isOverlay": { + "href": { + "description": "question: if clicked, what webpage should open?\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\ntype: url", + "type": "string" + }, + "newTab": { + "description": "question: Should the link open in a new tab?\niftrue: Open in a new tab\niffalse: do not open in a new tab\nifunset: do not open in a new tab", "type": "boolean" }, - "id": { - "type": "string" - }, - "url": { - "type": "string" - }, - "category": { - "type": "string" - }, - "type": { - "type": "string" - }, - "attribution": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "text": { - "type": "string" - }, - "html": { - "type": "string" - }, - "required": { - "type": "boolean" - } + "requirements": { + "description": "question: When should the extra button be shown?\nsuggestions: return [{if: \"value=iframe\", then: \"When shown in an iframe\"}, {if: \"value=no-iframe\", then: \"When shown as stand-alone webpage\"}, {if: \"value=welcome-message\", then: \"When the welcome messages are enabled\"}, {if: \"value=iframe\", then: \"When the welcome messages are disabled\"}]", + "type": "array", + "items": { + "enum": [ + "iframe", + "no-iframe", + "no-welcome-message", + "welcome-message" + ], + "type": "string" } - }, - "min_zoom": { - "type": "number" - }, - "max_zoom": { - "type": "number" - }, - "best": { - "type": "boolean" } }, "required": [ - "id", - "name", - "url" + "href" ] }, "LayerConfigJson": { @@ -2557,15 +2536,14 @@ export default { } } }, - "default": { + "Partial": { + "type": "object" + }, + "RasterLayerProperties": { "type": "object", "properties": { - "icon": { - "description": "question: What icon should be shown in the link button?\nifunset: do not show an icon\ntype: icon", - "type": "string" - }, - "text": { - "description": "question: What text should be shown in the link icon?\n\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\nifunset: do not show a text", + "name": { + "description": "The name of the imagery source", "anyOf": [ { "$ref": "#/definitions/Record" @@ -2575,30 +2553,52 @@ export default { } ] }, - "href": { - "description": "question: if clicked, what webpage should open?\nNote that {lat},{lon},{zoom}, {language} and {theme} will be replaced\n\ntype: url", - "type": "string" - }, - "newTab": { - "description": "question: Should the link open in a new tab?\niftrue: Open in a new tab\niffalse: do not open in a new tab\nifunset: do not open in a new tab", + "isOverlay": { "type": "boolean" }, - "requirements": { - "description": "question: When should the extra button be shown?\nsuggestions: return [{if: \"value=iframe\", then: \"When shown in an iframe\"}, {if: \"value=no-iframe\", then: \"When shown as stand-alone webpage\"}, {if: \"value=welcome-message\", then: \"When the welcome messages are enabled\"}, {if: \"value=iframe\", then: \"When the welcome messages are disabled\"}]", - "type": "array", - "items": { - "enum": [ - "iframe", - "no-iframe", - "no-welcome-message", - "welcome-message" - ], - "type": "string" + "id": { + "type": "string" + }, + "url": { + "type": "string" + }, + "category": { + "type": "string" + }, + "type": { + "type": "string" + }, + "attribution": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "text": { + "type": "string" + }, + "html": { + "type": "string" + }, + "required": { + "type": "boolean" + } } + }, + "min_zoom": { + "type": "number" + }, + "max_zoom": { + "type": "number" + }, + "best": { + "type": "boolean" } }, "required": [ - "href" + "id", + "name", + "url" ] } }, diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index 367508160..7694ffa79 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -28,6 +28,9 @@ import { ExtraFunctions } from "../src/Logic/ExtraFunctions" import { QuestionableTagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" import LayerConfig from "../src/Models/ThemeConfig/LayerConfig" import PointRenderingConfig from "../src/Models/ThemeConfig/PointRenderingConfig" + +import { ConfigMeta } from "../src/UI/Studio/configMeta" + // This scripts scans 'src/assets/layers/*.json' for layer definition files and 'src/assets/themes/*.json' for theme definition files. // It spits out an overview of those to be used to load them @@ -256,6 +259,7 @@ class LayerOverviewUtils extends Script { if (!existsSync(LayerOverviewUtils.themePath)) { mkdirSync(LayerOverviewUtils.themePath) } + writeFileSync( `${LayerOverviewUtils.themePath}${theme.id}.json`, JSON.stringify(theme, null, " "), diff --git a/scripts/lint.ts b/scripts/lint.ts index 9a960dba3..06db62a47 100644 --- a/scripts/lint.ts +++ b/scripts/lint.ts @@ -8,12 +8,22 @@ import Translations from "../src/UI/i18n/Translations" import { Translation } from "../src/UI/i18n/Translation" import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" import { ConversionContext } from "../src/Models/ThemeConfig/Conversion/Conversion" +import themeconfig from "../src/assets/schemas/layoutconfigmeta.json" +import layerconfig from "../src/assets/schemas/layerconfigmeta.json" + +import { Utils } from "../src/Utils" +import { ConfigMeta } from "../src/UI/Studio/configMeta" /* * This script reads all theme and layer files and reformats them inplace * Use with caution, make a commit beforehand! */ - +const themeAttributesOrder = Utils.Dedup( + (themeconfig).filter((c) => c.path.length === 1).map((c) => c.path[0]) +) +const layerAttributesOrder = Utils.Dedup( + (layerconfig).filter((c) => c.path.length === 1).map((c) => c.path[0]) +) const t: Translation = Translations.t.general.add.addNew t.OnEveryLanguage((txt, ln) => { console.log(ln, txt) @@ -31,6 +41,19 @@ const articles = { pt_BR : 'uma',//*/ } +function reorder(object: object, order: string[]) { + const allKeys = new Set(Object.keys(object)) + const copy = {} + for (const key of order) { + copy[key] = object[key] + allKeys.delete(key) + } + for (const key of allKeys) { + copy[key] = object[key] + } + return copy +} + function addArticleToPresets(layerConfig: { presets?: { title: any }[] }) { /* if(layerConfig.presets === undefined){ @@ -73,7 +96,8 @@ for (const layerFile of layerFiles) { ) ) addArticleToPresets(fixed) - writeFileSync(layerFile.path, JSON.stringify(fixed, null, " ") + "\n") + const reordered = reorder(fixed, layerAttributesOrder) + writeFileSync(layerFile.path, JSON.stringify(reordered, null, " ") + "\n") } catch (e) { console.error("COULD NOT LINT LAYER" + layerFile.path + ":\n\t" + e) } @@ -93,9 +117,10 @@ for (const themeFile of themeFiles) { } // extractInlineLayer(fixed) const endsWithNewline = themeFile.raw.at(-1) === "\n" + const ordered = reorder(fixed, themeAttributesOrder) writeFileSync( themeFile.path, - JSON.stringify(fixed, null, " ") + (endsWithNewline ? "\n" : "") + JSON.stringify(ordered, null, " ") + (endsWithNewline ? "\n" : "") ) } catch (e) { console.error("COULD NOT LINT THEME" + themeFile.path + ":\n\t" + e) diff --git a/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts b/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts index 7560b5f38..780985e60 100644 --- a/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts +++ b/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts @@ -145,7 +145,6 @@ export class UpdateLegacyLayer extends DesugaringStep< } if (config["mapRendering"]) { - console.log("MapRendering is", config["mapRendering"], json.id) const pointRenderings: PointRenderingConfigJson[] = [] const lineRenderings: LineRenderingConfigJson[] = [] for (const mapRenderingElement of config["mapRendering"]) { @@ -205,7 +204,6 @@ export class UpdateLegacyLayer extends DesugaringStep< typeof rendering[key]["render"] === "string" && Object.keys(rendering[key]).length === 1 ) { - console.log("Rewrite: ", rendering[key]) rendering[key] = rendering[key]["render"] } } @@ -220,7 +218,6 @@ export class UpdateLegacyLayer extends DesugaringStep< typeof rendering[key]["render"] === "string" && Object.keys(rendering[key]).length === 1 ) { - console.log("Rewrite: ", rendering[key]) rendering[key] = rendering[key]["render"] } } @@ -263,13 +260,16 @@ class UpdateLegacyTheme extends DesugaringStep { delete oldThemeConfig["language"] delete oldThemeConfig["version"] + if (oldThemeConfig.startLat === 0) { + delete oldThemeConfig.startLat + } + if (oldThemeConfig.startLon === 0) { + delete oldThemeConfig.startLon + } + if (oldThemeConfig.startZoom <= 2) { + delete oldThemeConfig.startZoom + } if (oldThemeConfig["maintainer"] !== undefined) { - console.log( - "Maintainer: ", - oldThemeConfig["maintainer"], - "credits: ", - oldThemeConfig["credits"] - ) if (oldThemeConfig.credits === undefined) { oldThemeConfig["credits"] = oldThemeConfig["maintainer"] delete oldThemeConfig["maintainer"] diff --git a/src/Models/ThemeConfig/Json/LayoutConfigJson.ts b/src/Models/ThemeConfig/Json/LayoutConfigJson.ts index 1beedb702..f7369f5b0 100644 --- a/src/Models/ThemeConfig/Json/LayoutConfigJson.ts +++ b/src/Models/ThemeConfig/Json/LayoutConfigJson.ts @@ -38,11 +38,12 @@ export interface LayoutConfigJson { id: string /** + * question: What is the title of this theme? * - * Who helped to create this theme and should be attributed? + * The human-readable title, as shown in the welcome message and the index page + * group: basic */ - credits?: string | string[] - + title: Translatable /** * Only used in 'generateLayerOverview': if present, every translation will be checked to make sure it is fully translated. * @@ -51,12 +52,12 @@ export interface LayoutConfigJson { mustHaveLanguage?: string[] /** - * question: What is the title of this theme? - * - * The human-readable title, as shown in the welcome message and the index page + * question: How would you describe this theme? + * The description, as shown in the welcome message and the more-screen * group: basic + * */ - title: Translatable + description: Translatable /** * A short description, showed as social description and in the 'more theme'-buttons. @@ -65,14 +66,6 @@ export interface LayoutConfigJson { */ shortDescription?: Translatable - /** - * question: How would you describe this theme? - * The description, as shown in the welcome message and the more-screen - * group: basic - * - */ - description: Translatable - /** * A part of the description, shown under the login-button. * group: hidden @@ -103,6 +96,18 @@ export interface LayoutConfigJson { */ socialImage?: string + /** + * question: should an extra help button be shown in certain circumstances? + * Adds an additional button on the top-left of the application. + * This can link to an arbitrary location. + * + * For example {icon: "./assets/svg/pop-out.svg", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: ["iframe","no-welcome-message]}, + * + * group: advanced + * ifunset: show a link to open MapComplete full screen if used in an iframe + */ + extraLink?: ExtraLinkConfigJson + /** * question: At what zoomlevel should this theme open? * Default location and zoom to start. @@ -130,71 +135,21 @@ export interface LayoutConfigJson { * group: start_location */ startLon: number - - /** - * When a query is run, the data within bounds of the visible map is loaded. - * However, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data. - * For this, the bounds are widened in order to make a small pan still within bounds of the loaded data. - * - * IF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3 - */ - widenFactor?: number - /** - * At low zoom levels, overpass is used to query features. - * At high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile. - * The overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used. - */ - overpassMaxZoom?: 17 | number - - /** - * When the OSM-api is used to fetch features, it does so in a tiled fashion. - * These tiles are using a ceratin zoom level, that can be controlled here - * Default: overpassMaxZoom + 1 - */ - osmApiTileSize?: number - - /** - * An override applied on all layers of the theme. - * - * E.g.: if there are two layers defined: - * ``` - * "layers":[ - * {"title": ..., "tagRenderings": [...], "osmSource":{"tags": ...}}, - * {"title", ..., "tagRenderings", [...], "osmSource":{"tags" ...}} - * ] - * ``` - * - * and overrideAll is specified: - * ``` - * "overrideAll": { - * "osmSource":{"geoJsonSource":"xyz"} - * } - * then the result will be that all the layers will have these properties applied and result in: - * "layers":[ - * {"title": ..., "tagRenderings": [...], "osmSource":{"tags": ..., "geoJsonSource":"xyz"}}, - * {"title", ..., "tagRenderings", [...], "osmSource":{"tags" ..., "geoJsonSource":"xyz"}} - * ] - * ``` - * - * If the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example - * - * "overrideAll": { - * "+tagRenderings": [ { ... some tagrendering ... }] - * } - * - * In the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer - */ - overrideAll?: Partial - /** * The id of the default background. BY default: vanilla OSM */ defaultBackgroundId?: string /** - * Define some (overlay) slippy map tilesources + * + * Who helped to create this theme and should be attributed? */ - tileLayerSources?: (RasterLayerProperties & { defaultState?: true | boolean })[] + credits?: string | string[] + + /** + * If set to true, this layout will not be shown in the overview with more themes + */ + hideFromOverview?: boolean /** * question: What layers should this map show? @@ -253,16 +208,48 @@ export interface LayoutConfigJson { hideTagRenderingsWithLabels?: string[] } )[] + /** + * An override applied on all layers of the theme. + * + * E.g.: if there are two layers defined: + * ``` + * "layers":[ + * {"title": ..., "tagRenderings": [...], "osmSource":{"tags": ...}}, + * {"title", ..., "tagRenderings", [...], "osmSource":{"tags" ...}} + * ] + * ``` + * + * and overrideAll is specified: + * ``` + * "overrideAll": { + * "osmSource":{"geoJsonSource":"xyz"} + * } + * then the result will be that all the layers will have these properties applied and result in: + * "layers":[ + * {"title": ..., "tagRenderings": [...], "osmSource":{"tags": ..., "geoJsonSource":"xyz"}}, + * {"title", ..., "tagRenderings", [...], "osmSource":{"tags" ..., "geoJsonSource":"xyz"}} + * ] + * ``` + * + * If the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example + * + * "overrideAll": { + * "+tagRenderings": [ { ... some tagrendering ... }] + * } + * + * In the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer + */ + overrideAll?: Partial + /** + * Define some (overlay) slippy map tilesources + */ + tileLayerSources?: (RasterLayerProperties & { defaultState?: true | boolean })[] /** * The URL of a custom CSS stylesheet to modify the layout * group: advanced */ customCss?: string - /** - * If set to true, this layout will not be shown in the overview with more themes - */ - hideFromOverview?: boolean /** * If set to true, the basemap will not scroll outside of the area visible on initial zoom. @@ -271,18 +258,6 @@ export interface LayoutConfigJson { */ lockLocation?: [[number, number], [number, number]] | number[][] - /** - * question: should an extra help button be shown in certain circumstances? - * Adds an additional button on the top-left of the application. - * This can link to an arbitrary location. - * - * For example {icon: "./assets/svg/pop-out.svg", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: ["iframe","no-welcome-message]}, - * - * group: advanced - * ifunset: show a link to open MapComplete full screen if used in an iframe - */ - extraLink?: ExtraLinkConfigJson - /** * question: Should a user be able to login with OpenStreetMap? * @@ -430,6 +405,28 @@ export interface LayoutConfigJson { */ overpassTimeout?: number + /** + * When a query is run, the data within bounds of the visible map is loaded. + * However, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data. + * For this, the bounds are widened in order to make a small pan still within bounds of the loaded data. + * + * IF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3 + */ + widenFactor?: number + /** + * At low zoom levels, overpass is used to query features. + * At high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile. + * The overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used. + */ + overpassMaxZoom?: 17 | number + + /** + * When the OSM-api is used to fetch features, it does so in a tiled fashion. + * These tiles are using a ceratin zoom level, that can be controlled here + * Default: overpassMaxZoom + 1 + */ + osmApiTileSize?: number + /** * Enables tracking of all nodes when data is loaded. * This is useful for the 'ImportWay' and 'ConflateWay'-buttons who need this database. diff --git a/src/assets/schemas/layerconfigmeta.json b/src/assets/schemas/layerconfigmeta.json index c3f90bc50..897eb3f0c 100644 --- a/src/assets/schemas/layerconfigmeta.json +++ b/src/assets/schemas/layerconfigmeta.json @@ -10073,6 +10073,10 @@ "if": "value=hydrant", "then": "hydrant - Map layer to show fire hydrants." }, + { + "if": "value=ice_cream", + "then": "ice_cream - A place where ice cream is sold over the counter" + }, { "if": "value=icons", "then": "icons - A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI" @@ -10221,6 +10225,10 @@ "if": "value=recycling", "then": "recycling - A layer with recycling containers and centres" }, + { + "if": "value=route_marker", + "then": "route_marker - Route markers are small markers often found along official hiking/cycling/riding/skiing routes to indicate the direction of the route." + }, { "if": "value=school", "then": "school - Schools giving primary and secondary education and post-secondary, non-tertiary education. Note that this level of education does not imply an age of the pupiles" diff --git a/src/assets/schemas/layoutconfigmeta.json b/src/assets/schemas/layoutconfigmeta.json index 3886d6ea2..d92e2cd93 100644 --- a/src/assets/schemas/layoutconfigmeta.json +++ b/src/assets/schemas/layoutconfigmeta.json @@ -19,34 +19,6 @@ "type": "string", "description": "The id is a unique string to identify the theme\nIt should be\n- in english\n- describe the theme in a single word (or a few words)\n- all lowercase and with only [a-z] or underscores (_)\nThis is used as hashtag in the changeset message, which will read something like \"Adding data with #mapcomplete for theme #\"\nOn official themes, it'll become the name of the page, e.g.\n'cyclestreets' which become 'cyclestreets.html'" }, - { - "path": [ - "credits" - ], - "required": false, - "hints": {}, - "type": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ], - "description": "Who helped to create this theme and should be attributed?" - }, - { - "path": [ - "mustHaveLanguage" - ], - "required": false, - "hints": {}, - "type": "array", - "description": "Only used in 'generateLayerOverview': if present, every translation will be checked to make sure it is fully translated.\nThis must be a list of two-letter, lowercase codes which identifies the language, e.g. \"en\", \"nl\", ..." - }, { "path": [ "title" @@ -68,21 +40,12 @@ }, { "path": [ - "shortDescription" + "mustHaveLanguage" ], "required": false, - "hints": { - "group": "hidden" - }, - "type": [ - { - "$ref": "#/definitions/Record" - }, - { - "type": "string" - } - ], - "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used" + "hints": {}, + "type": "array", + "description": "Only used in 'generateLayerOverview': if present, every translation will be checked to make sure it is fully translated.\nThis must be a list of two-letter, lowercase codes which identifies the language, e.g. \"en\", \"nl\", ..." }, { "path": [ @@ -103,6 +66,24 @@ ], "description": "The description, as shown in the welcome message and the more-screen" }, + { + "path": [ + "shortDescription" + ], + "required": false, + "hints": { + "group": "hidden" + }, + "type": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ], + "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used" + }, { "path": [ "descriptionTail" @@ -148,6 +129,111 @@ "type": "string", "description": "This is included as og:image-tag on official themes.\nSee https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit for more information" }, + { + "path": [ + "extraLink" + ], + "required": false, + "hints": { + "group": "advanced", + "question": "should an extra help button be shown in certain circumstances?", + "ifunset": "show a link to open MapComplete full screen if used in an iframe" + }, + "type": "object", + "description": "Adds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\nFor example {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]}," + }, + { + "path": [ + "extraLink", + "icon" + ], + "required": false, + "hints": { + "typehint": "icon", + "question": "What icon should be shown in the link button?", + "ifunset": "do not show an icon" + }, + "type": "string", + "description": "" + }, + { + "path": [ + "extraLink", + "text" + ], + "required": false, + "hints": { + "question": "What text should be shown in the link icon?", + "ifunset": "do not show a text" + }, + "type": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ], + "description": "Note that {lat},{lon},{zoom}, {language} and {theme} will be replaced" + }, + { + "path": [ + "extraLink", + "href" + ], + "required": true, + "hints": { + "typehint": "url", + "question": "if clicked, what webpage should open?" + }, + "type": "string", + "description": "Note that {lat},{lon},{zoom}, {language} and {theme} will be replaced" + }, + { + "path": [ + "extraLink", + "newTab" + ], + "required": false, + "hints": { + "question": "Should the link open in a new tab?", + "iftrue": "Open in a new tab", + "iffalse": "do not open in a new tab", + "ifunset": "do not open in a new tab" + }, + "type": "boolean", + "description": "" + }, + { + "path": [ + "extraLink", + "requirements" + ], + "required": false, + "hints": { + "question": "When should the extra button be shown?", + "suggestions": [ + { + "if": "value=iframe", + "then": "When shown in an iframe" + }, + { + "if": "value=no-iframe", + "then": "When shown as stand-alone webpage" + }, + { + "if": "value=welcome-message", + "then": "When the welcome messages are enabled" + }, + { + "if": "value=iframe", + "then": "When the welcome messages are disabled" + } + ] + }, + "type": "array", + "description": "" + }, { "path": [ "startZoom" @@ -190,44 +276,6 @@ "type": "number", "description": "Default location and zoom to start.\nNote that this is barely used. Once the user has visited mapcomplete at least once, the previous location of the user will be used" }, - { - "path": [ - "widenFactor" - ], - "required": false, - "hints": {}, - "type": "number", - "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3" - }, - { - "path": [ - "overpassMaxZoom" - ], - "required": false, - "hints": {}, - "type": "number", - "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used." - }, - { - "path": [ - "osmApiTileSize" - ], - "required": false, - "hints": { - "default": "overpassMaxZoom + 1" - }, - "type": "number", - "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here" - }, - { - "path": [ - "overrideAll" - ], - "required": false, - "hints": {}, - "type": "object", - "description": "An override applied on all layers of the theme.\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer" - }, { "path": [ "defaultBackgroundId" @@ -239,29 +287,31 @@ }, { "path": [ - "tileLayerSources" + "credits" ], "required": false, "hints": {}, - "type": "array", - "description": "Define some (overlay) slippy map tilesources" - }, - { - "path": [ - "tileLayerSources", - "name" - ], - "required": true, - "hints": {}, "type": [ { - "$ref": "#/definitions/Record" + "type": "array", + "items": { + "type": "string" + } }, { "type": "string" } ], - "description": "The name of the imagery source" + "description": "Who helped to create this theme and should be attributed?" + }, + { + "path": [ + "hideFromOverview" + ], + "required": false, + "hints": {}, + "type": "boolean", + "description": "If set to true, this layout will not be shown in the overview with more themes" }, { "path": [ @@ -530,6 +580,10 @@ "if": "value=hydrant", "then": "hydrant - Map layer to show fire hydrants." }, + { + "if": "value=ice_cream", + "then": "ice_cream - A place where ice cream is sold over the counter" + }, { "if": "value=icons", "then": "icons - A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI" @@ -678,6 +732,10 @@ "if": "value=recycling", "then": "recycling - A layer with recycling containers and centres" }, + { + "if": "value=route_marker", + "then": "route_marker - Route markers are small markers often found along official hiking/cycling/riding/skiing routes to indicate the direction of the route." + }, { "if": "value=school", "then": "school - Schools giving primary and secondary education and post-secondary, non-tertiary education. Note that this level of education does not imply an age of the pupiles" @@ -12109,6 +12167,10 @@ "if": "value=hydrant", "then": "hydrant - Map layer to show fire hydrants." }, + { + "if": "value=ice_cream", + "then": "ice_cream - A place where ice cream is sold over the counter" + }, { "if": "value=icons", "then": "icons - A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI" @@ -12257,6 +12319,10 @@ "if": "value=recycling", "then": "recycling - A layer with recycling containers and centres" }, + { + "if": "value=route_marker", + "then": "route_marker - Route markers are small markers often found along official hiking/cycling/riding/skiing routes to indicate the direction of the route." + }, { "if": "value=school", "then": "school - Schools giving primary and secondary education and post-secondary, non-tertiary education. Note that this level of education does not imply an age of the pupiles" @@ -28998,6 +29064,10 @@ "if": "value=hydrant", "then": "hydrant - Map layer to show fire hydrants." }, + { + "if": "value=ice_cream", + "then": "ice_cream - A place where ice cream is sold over the counter" + }, { "if": "value=icons", "then": "icons - A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI" @@ -29146,6 +29216,10 @@ "if": "value=recycling", "then": "recycling - A layer with recycling containers and centres" }, + { + "if": "value=route_marker", + "then": "route_marker - Route markers are small markers often found along official hiking/cycling/riding/skiing routes to indicate the direction of the route." + }, { "if": "value=school", "then": "school - Schools giving primary and secondary education and post-secondary, non-tertiary education. Note that this level of education does not imply an age of the pupiles" @@ -35394,6 +35468,41 @@ "type": "array", "description": "TagRenderings with any of these labels will be removed from the layer.\nNote that the 'id' and 'group' are considered labels too" }, + { + "path": [ + "overrideAll" + ], + "required": false, + "hints": {}, + "type": "object", + "description": "An override applied on all layers of the theme.\nE.g.: if there are two layers defined:\n```\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ...}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ...}}\n]\n```\nand overrideAll is specified:\n```\n\"overrideAll\": {\n \"osmSource\":{\"geoJsonSource\":\"xyz\"}\n}\nthen the result will be that all the layers will have these properties applied and result in:\n\"layers\":[\n {\"title\": ..., \"tagRenderings\": [...], \"osmSource\":{\"tags\": ..., \"geoJsonSource\":\"xyz\"}},\n {\"title\", ..., \"tagRenderings\", [...], \"osmSource\":{\"tags\" ..., \"geoJsonSource\":\"xyz\"}}\n]\n```\nIf the overrideAll contains a list where the keys starts with a plus, the values will be appended (instead of discarding the old list), for example\n\"overrideAll\": {\n \"+tagRenderings\": [ { ... some tagrendering ... }]\n}\nIn the above scenario, `sometagrendering` will be added at the beginning of the tagrenderings of every layer" + }, + { + "path": [ + "tileLayerSources" + ], + "required": false, + "hints": {}, + "type": "array", + "description": "Define some (overlay) slippy map tilesources" + }, + { + "path": [ + "tileLayerSources", + "name" + ], + "required": true, + "hints": {}, + "type": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ], + "description": "The name of the imagery source" + }, { "path": [ "customCss" @@ -35405,15 +35514,6 @@ "type": "string", "description": "The URL of a custom CSS stylesheet to modify the layout" }, - { - "path": [ - "hideFromOverview" - ], - "required": false, - "hints": {}, - "type": "boolean", - "description": "If set to true, this layout will not be shown in the overview with more themes" - }, { "path": [ "lockLocation" @@ -35466,111 +35566,6 @@ ], "description": "If set to true, the basemap will not scroll outside of the area visible on initial zoom.\nIf set to [[lon, lat], [lon, lat]], the map will not scroll outside of those bounds.\nOff by default, which will enable panning to the entire world" }, - { - "path": [ - "extraLink" - ], - "required": false, - "hints": { - "group": "advanced", - "question": "should an extra help button be shown in certain circumstances?", - "ifunset": "show a link to open MapComplete full screen if used in an iframe" - }, - "type": "object", - "description": "Adds an additional button on the top-left of the application.\nThis can link to an arbitrary location.\nFor example {icon: \"./assets/svg/pop-out.svg\", href: 'https://mapcomplete.org/{theme}.html?lat={lat}&lon={lon}&z={zoom}, requirements: [\"iframe\",\"no-welcome-message]}," - }, - { - "path": [ - "extraLink", - "icon" - ], - "required": false, - "hints": { - "typehint": "icon", - "question": "What icon should be shown in the link button?", - "ifunset": "do not show an icon" - }, - "type": "string", - "description": "" - }, - { - "path": [ - "extraLink", - "text" - ], - "required": false, - "hints": { - "question": "What text should be shown in the link icon?", - "ifunset": "do not show a text" - }, - "type": [ - { - "$ref": "#/definitions/Record" - }, - { - "type": "string" - } - ], - "description": "Note that {lat},{lon},{zoom}, {language} and {theme} will be replaced" - }, - { - "path": [ - "extraLink", - "href" - ], - "required": true, - "hints": { - "typehint": "url", - "question": "if clicked, what webpage should open?" - }, - "type": "string", - "description": "Note that {lat},{lon},{zoom}, {language} and {theme} will be replaced" - }, - { - "path": [ - "extraLink", - "newTab" - ], - "required": false, - "hints": { - "question": "Should the link open in a new tab?", - "iftrue": "Open in a new tab", - "iffalse": "do not open in a new tab", - "ifunset": "do not open in a new tab" - }, - "type": "boolean", - "description": "" - }, - { - "path": [ - "extraLink", - "requirements" - ], - "required": false, - "hints": { - "question": "When should the extra button be shown?", - "suggestions": [ - { - "if": "value=iframe", - "then": "When shown in an iframe" - }, - { - "if": "value=no-iframe", - "then": "When shown as stand-alone webpage" - }, - { - "if": "value=welcome-message", - "then": "When the welcome messages are enabled" - }, - { - "if": "value=iframe", - "then": "When the welcome messages are disabled" - } - ] - }, - "type": "array", - "description": "" - }, { "path": [ "enableUserBadge" @@ -35778,6 +35773,35 @@ "type": "number", "description": "If a query takes too long, the overpass-server will abort.\nOnce can set the amount of time before overpass gives up here." }, + { + "path": [ + "widenFactor" + ], + "required": false, + "hints": {}, + "type": "number", + "description": "When a query is run, the data within bounds of the visible map is loaded.\nHowever, users tend to pan and zoom a lot. It is pretty annoying if every single pan means a reloading of the data.\nFor this, the bounds are widened in order to make a small pan still within bounds of the loaded data.\nIF widenfactor is 1, this feature is disabled. A recommended value is between 1 and 3" + }, + { + "path": [ + "overpassMaxZoom" + ], + "required": false, + "hints": {}, + "type": "number", + "description": "At low zoom levels, overpass is used to query features.\nAt high zoom level, the OSM api is used to fetch one or more BBOX aligning with a slippy tile.\nThe overpassMaxZoom controls the flipoverpoint: if the zoom is this or lower, overpass is used." + }, + { + "path": [ + "osmApiTileSize" + ], + "required": false, + "hints": { + "default": "overpassMaxZoom + 1" + }, + "type": "number", + "description": "When the OSM-api is used to fetch features, it does so in a tiled fashion.\nThese tiles are using a ceratin zoom level, that can be controlled here" + }, { "path": [ "enableNodeDatabase"