Studio: small improvements after selftesting, icons reusing HeroIcons can now be colored as well

This commit is contained in:
Pieter Vander Vennet 2024-01-12 23:19:31 +01:00
parent 003430131b
commit 8f036f6045
45 changed files with 10960 additions and 288 deletions

View file

@ -121,6 +121,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -117,6 +117,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -2,7 +2,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -174,6 +174,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -2,7 +2,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -170,6 +170,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -85,7 +85,7 @@
]
},
"calculatedTags": {
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\nNot found... * \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"type": "array",
"items": {
"type": "string"
@ -136,14 +136,26 @@
"type": "boolean"
},
"titleIcons": {
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]\ngroup: infobox",
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nUse `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons\n\nType: icon[]\ngroup: infobox",
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
"allOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
]
},
{
"type": "string"
@ -253,7 +265,7 @@
}
},
"tagRenderings": {
"description": "question: Edit this attribute showing piece/question\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"description": "question: Edit this way this attributed is displayed or queried\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"type": "array",
"items": {
"anyOf": [
@ -370,7 +382,14 @@
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/default_2"
"anyOf": [
{
"$ref": "#/definitions/default_2"
},
{
"$ref": "#/definitions/Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>"
}
]
}
},
"syncSelection": {
@ -518,6 +537,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -561,7 +584,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -850,6 +873,20 @@
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [
@ -1242,6 +1279,17 @@
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1457,6 +1505,17 @@
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1597,33 +1656,71 @@
"sourceString"
]
},
"subexpand": {
"$ref": "#/definitions/Record<string,string[]>"
},
"renderings": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
},
{
"type": "array",
"items": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
}
}
]
}
},
"required": [
@ -1784,6 +1881,10 @@
"description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given",
"type": "object",
"properties": {
"quantity": {
"description": "What is quantified? E.g. 'speed', 'length' (including width, diameter, ...), 'electric tension', 'electric current', 'duration'",
"type": "string"
},
"appliesToKey": {
"description": "Every key from this list will be normalized.\n\nTo render the value properly (with a human readable denomination), use `{canonical(<key>)}`",
"type": "array",
@ -1808,10 +1909,13 @@
}
},
"required": [
"applicableUnits",
"appliesToKey"
"applicableUnits"
],
"additionalProperties": false
},
"Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>": {
"type": "object",
"additionalProperties": false
}
},
"$schema": "http://json-schema.org/draft-07/schema#",

View file

@ -85,7 +85,7 @@ export default {
]
},
"calculatedTags": {
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\nNot found... * \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"type": "array",
"items": {
"type": "string"
@ -136,14 +136,26 @@ export default {
"type": "boolean"
},
"titleIcons": {
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]\ngroup: infobox",
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nUse `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons\n\nType: icon[]\ngroup: infobox",
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
"allOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
]
},
{
"type": "string"
@ -253,7 +265,7 @@ export default {
}
},
"tagRenderings": {
"description": "question: Edit this attribute showing piece/question\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"description": "question: Edit this way this attributed is displayed or queried\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"type": "array",
"items": {
"anyOf": [
@ -370,7 +382,14 @@ export default {
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/default_2"
"anyOf": [
{
"$ref": "#/definitions/default_2"
},
{
"$ref": "#/definitions/Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>"
}
]
}
},
"syncSelection": {
@ -514,6 +533,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -555,7 +578,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -841,6 +864,20 @@ export default {
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [
@ -1229,6 +1266,17 @@ export default {
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1443,6 +1491,17 @@ export default {
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1582,33 +1641,71 @@ export default {
"sourceString"
]
},
"subexpand": {
"$ref": "#/definitions/Record<string,string[]>"
},
"renderings": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
},
{
"type": "array",
"items": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
}
}
]
}
},
"required": [
@ -1765,6 +1862,10 @@ export default {
"description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given",
"type": "object",
"properties": {
"quantity": {
"description": "What is quantified? E.g. 'speed', 'length' (including width, diameter, ...), 'electric tension', 'electric current', 'duration'",
"type": "string"
},
"appliesToKey": {
"description": "Every key from this list will be normalized.\n\nTo render the value properly (with a human readable denomination), use `{canonical(<key>)}`",
"type": "array",
@ -1789,9 +1890,11 @@ export default {
}
},
"required": [
"applicableUnits",
"appliesToKey"
"applicableUnits"
]
},
"Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>": {
"type": "object"
}
},
"$schema": "http://json-schema.org/draft-07/schema#"

View file

@ -427,6 +427,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -470,7 +474,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -759,6 +763,20 @@
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [
@ -1151,6 +1169,17 @@
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1366,6 +1395,17 @@
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1506,33 +1546,71 @@
"sourceString"
]
},
"subexpand": {
"$ref": "#/definitions/Record<string,string[]>"
},
"renderings": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
},
{
"type": "array",
"items": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
}
}
]
}
},
"required": [
@ -1693,6 +1771,10 @@
"description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given",
"type": "object",
"properties": {
"quantity": {
"description": "What is quantified? E.g. 'speed', 'length' (including width, diameter, ...), 'electric tension', 'electric current', 'duration'",
"type": "string"
},
"appliesToKey": {
"description": "Every key from this list will be normalized.\n\nTo render the value properly (with a human readable denomination), use `{canonical(<key>)}`",
"type": "array",
@ -1717,11 +1799,14 @@
}
},
"required": [
"applicableUnits",
"appliesToKey"
"applicableUnits"
],
"additionalProperties": false
},
"Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>": {
"type": "object",
"additionalProperties": false
},
"default": {
"type": "object",
"properties": {
@ -1854,7 +1939,7 @@
]
},
"calculatedTags": {
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\nNot found... * \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"type": "array",
"items": {
"type": "string"
@ -1905,14 +1990,26 @@
"type": "boolean"
},
"titleIcons": {
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]\ngroup: infobox",
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nUse `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons\n\nType: icon[]\ngroup: infobox",
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
"allOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
]
},
{
"type": "string"
@ -2022,7 +2119,7 @@
}
},
"tagRenderings": {
"description": "question: Edit this attribute showing piece/question\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"description": "question: Edit this way this attributed is displayed or queried\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"type": "array",
"items": {
"anyOf": [
@ -2139,7 +2236,14 @@
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/default_2"
"anyOf": [
{
"$ref": "#/definitions/default_2"
},
{
"$ref": "#/definitions/Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>"
}
]
}
},
"syncSelection": {
@ -2254,7 +2358,7 @@
]
},
"calculatedTags": {
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\nNot found... * \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"type": "array",
"items": {
"type": "string"
@ -2305,14 +2409,26 @@
"type": "boolean"
},
"titleIcons": {
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]\ngroup: infobox",
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nUse `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons\n\nType: icon[]\ngroup: infobox",
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
"allOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
]
},
{
"type": "string"
@ -2422,7 +2538,7 @@
}
},
"tagRenderings": {
"description": "question: Edit this attribute showing piece/question\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"description": "question: Edit this way this attributed is displayed or queried\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"type": "array",
"items": {
"anyOf": [
@ -2539,7 +2655,14 @@
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/default_2"
"anyOf": [
{
"$ref": "#/definitions/default_2"
},
{
"$ref": "#/definitions/Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>"
}
]
}
},
"syncSelection": {

View file

@ -423,6 +423,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -464,7 +468,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -750,6 +754,20 @@ export default {
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [
@ -1138,6 +1156,17 @@ export default {
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1352,6 +1381,17 @@ export default {
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -1491,33 +1531,71 @@ export default {
"sourceString"
]
},
"subexpand": {
"$ref": "#/definitions/Record<string,string[]>"
},
"renderings": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
},
{
"type": "array",
"items": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/QuestionableTagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"builtin": {
"type": "string"
},
"override": {
"$ref": "#/definitions/Partial<QuestionableTagRenderingConfigJson>"
}
},
"required": [
"builtin",
"override"
]
},
{
"type": "string"
}
]
}
}
}
]
}
},
"required": [
@ -1674,6 +1752,10 @@ export default {
"description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given",
"type": "object",
"properties": {
"quantity": {
"description": "What is quantified? E.g. 'speed', 'length' (including width, diameter, ...), 'electric tension', 'electric current', 'duration'",
"type": "string"
},
"appliesToKey": {
"description": "Every key from this list will be normalized.\n\nTo render the value properly (with a human readable denomination), use `{canonical(<key>)}`",
"type": "array",
@ -1698,10 +1780,12 @@ export default {
}
},
"required": [
"applicableUnits",
"appliesToKey"
"applicableUnits"
]
},
"Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>": {
"type": "object"
},
"default": {
"type": "object",
"properties": {
@ -1833,7 +1917,7 @@ export default {
]
},
"calculatedTags": {
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\nNot found... * \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"type": "array",
"items": {
"type": "string"
@ -1884,14 +1968,26 @@ export default {
"type": "boolean"
},
"titleIcons": {
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]\ngroup: infobox",
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nUse `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons\n\nType: icon[]\ngroup: infobox",
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
"allOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
]
},
{
"type": "string"
@ -2001,7 +2097,7 @@ export default {
}
},
"tagRenderings": {
"description": "question: Edit this attribute showing piece/question\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"description": "question: Edit this way this attributed is displayed or queried\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"type": "array",
"items": {
"anyOf": [
@ -2118,7 +2214,14 @@ export default {
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/default_2"
"anyOf": [
{
"$ref": "#/definitions/default_2"
},
{
"$ref": "#/definitions/Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>"
}
]
}
},
"syncSelection": {
@ -2232,7 +2335,7 @@ export default {
]
},
"calculatedTags": {
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\nNot found... * \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to <a>Docs/CalculatedTags.md</a> for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]\n\nSee the full documentation on [https://github.com/pietervdvn/MapComplete/blob/master/Docs/CalculatedTags.md]\n\ngroup: expert\nquestion: What extra attributes should be calculated with javascript?",
"type": "array",
"items": {
"type": "string"
@ -2283,14 +2386,26 @@ export default {
"type": "boolean"
},
"titleIcons": {
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]\ngroup: infobox",
"description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nUse `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons\n\nType: icon[]\ngroup: infobox",
"anyOf": [
{
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
"allOf": [
{
"$ref": "#/definitions/TagRenderingConfigJson"
},
{
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
}
]
},
{
"type": "string"
@ -2400,7 +2515,7 @@ export default {
}
},
"tagRenderings": {
"description": "question: Edit this attribute showing piece/question\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"description": "question: Edit this way this attributed is displayed or queried\n\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together\n\ntype: tagrendering[]\ngroup: tagrenderings",
"type": "array",
"items": {
"anyOf": [
@ -2517,7 +2632,14 @@ export default {
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/default_2"
"anyOf": [
{
"$ref": "#/definitions/default_2"
},
{
"$ref": "#/definitions/Record<string,string|{quantity:string;denominations:string[];canonical?:string|undefined;}>"
}
]
}
},
"syncSelection": {

View file

@ -186,6 +186,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -229,7 +233,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"

View file

@ -182,6 +182,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -223,7 +227,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"

View file

@ -57,6 +57,20 @@
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [
@ -226,6 +240,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -269,7 +287,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"

View file

@ -57,6 +57,20 @@ export default {
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [
@ -222,6 +236,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -263,7 +281,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"

View file

@ -131,6 +131,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -127,6 +127,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -287,6 +287,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -330,7 +334,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"

View file

@ -283,6 +283,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -324,7 +328,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"

View file

@ -97,6 +97,17 @@
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -333,6 +344,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -376,7 +391,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -665,6 +680,20 @@
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [

View file

@ -97,6 +97,17 @@ export default {
}
]
},
"editButtonAriaLabel": {
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time.",
"anyOf": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
]
},
"labels": {
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
"type": "array",
@ -329,6 +340,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -370,7 +385,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -656,6 +671,20 @@ export default {
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [

View file

@ -24,8 +24,21 @@
"sourceString"
]
},
"subexpand": {
"$ref": "#/definitions/Record<string,string[]>"
},
"renderings": {
"$ref": "#/definitions/T"
"anyOf": [
{
"$ref": "#/definitions/T"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/T"
}
}
]
}
},
"required": [
@ -153,6 +166,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -196,7 +213,7 @@
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -485,6 +502,20 @@
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [

View file

@ -24,8 +24,21 @@ export default {
"sourceString"
]
},
"subexpand": {
"$ref": "#/definitions/Record<string,string[]>"
},
"renderings": {
"$ref": "#/definitions/T"
"anyOf": [
{
"$ref": "#/definitions/T"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/T"
}
}
]
}
},
"required": [
@ -149,6 +162,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [
@ -190,7 +207,7 @@ export default {
"type": "object",
"properties": {
"icon": {
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return [\"pin\",\"square\",\"circle\",\"checkmark\",\"clock\",\"close\",\"crosshair\",\"help\",\"home\",\"invalid\",\"location\",\"location_empty\",\"location_locked\",\"note\",\"resolved\",\"ring\",\"scissors\",\"teardrop\",\"teardrop_with_hole_green\",\"triangle\"].map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"description": "question: What icon should be used?\ntype: icon\nsuggestions: return Constants.defaultPinIcons.map(i => ({if: \"value=\"+i, then: i, icon: i}))",
"anyOf": [
{
"$ref": "#/definitions/MinimalTagRenderingConfigJson"
@ -476,6 +493,20 @@ export default {
}
]
},
"alsoShowIf": {
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags.",
"anyOf": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
]
},
"ifnot": {
"description": "question: What tags should be applied if this mapping is _not_ chosen?\n\nOnly applicable if 'multiAnswer' is set.\nThis is for situations such as:\n`accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.\nThis can be done with `ifnot`\nNote that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.\nIf this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`\n\nifunset: Do not apply a tag if a different mapping is chosen.",
"anyOf": [

View file

@ -2,6 +2,10 @@
"description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given",
"type": "object",
"properties": {
"quantity": {
"description": "What is quantified? E.g. 'speed', 'length' (including width, diameter, ...), 'electric tension', 'electric current', 'duration'",
"type": "string"
},
"appliesToKey": {
"description": "Every key from this list will be normalized.\n\nTo render the value properly (with a human readable denomination), use `{canonical(<key>)}`",
"type": "array",
@ -26,8 +30,7 @@
}
},
"required": [
"applicableUnits",
"appliesToKey"
"applicableUnits"
],
"definitions": {
"TagConfigJson": {
@ -150,6 +153,10 @@
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -2,6 +2,10 @@ export default {
"description": "In some cases, a value is represented in a certain unit (such as meters for heigt/distance/..., km/h for speed, ...)\n\nSometimes, multiple denominations are possible (e.g. km/h vs mile/h; megawatt vs kilowatt vs gigawatt for power generators, ...)\n\nThis brings in some troubles, as there are multiple ways to write it (no denomitation, 'm' vs 'meter' 'metre', ...)\n\nNot only do we want to write consistent data to OSM, we also want to present this consistently to the user.\nThis is handled by defining units.\n\n# Rendering\n\nTo render a value with long (human) denomination, use {canonical(key)}\n\n# Usage\n\nFirst of all, you define which keys have units applied, for example:\n\n```\nunits: [\n appliesTo: [\"maxspeed\", \"maxspeed:hgv\", \"maxspeed:bus\"]\n applicableUnits: [\n ...\n ]\n]\n```\n\nApplicableUnits defines which is the canonical extension, how it is presented to the user, ...:\n\n```\napplicableUnits: [\n{\n canonicalDenomination: \"km/h\",\n alternativeDenomination: [\"km/u\", \"kmh\", \"kph\"]\n default: true,\n human: {\n en: \"kilometer/hour\",\n nl: \"kilometer/uur\"\n },\n humanShort: {\n en: \"km/h\",\n nl: \"km/u\"\n }\n},\n{\n canoncialDenomination: \"mph\",\n ... similar for miles an hour ...\n}\n]\n```\n\n\nIf this is defined, then every key which the denominations apply to (`maxspeed`, `maxspeed:hgv` and `maxspeed:bus`) will be rewritten at the metatagging stage:\nevery value will be parsed and the canonical extension will be added add presented to the other parts of the code.\n\nAlso, if a freeform text field is used, an extra dropdown with applicable denominations will be given",
"type": "object",
"properties": {
"quantity": {
"description": "What is quantified? E.g. 'speed', 'length' (including width, diameter, ...), 'electric tension', 'electric current', 'duration'",
"type": "string"
},
"appliesToKey": {
"description": "Every key from this list will be normalized.\n\nTo render the value properly (with a human readable denomination), use `{canonical(<key>)}`",
"type": "array",
@ -26,8 +30,7 @@ export default {
}
},
"required": [
"applicableUnits",
"appliesToKey"
"applicableUnits"
],
"definitions": {
"TagConfigJson": {
@ -146,6 +149,10 @@ export default {
"prefix": {
"description": "If set, then the canonical value will be prefixed instead, e.g. for '€'\nNote that if all values use 'prefix', the dropdown might move to before the text field",
"type": "boolean"
},
"addSpace": {
"description": "If set, add a space between the quantity and the denomination.\n\nE.g.: `50 mph` instad of `50mph`",
"type": "boolean"
}
},
"required": [

View file

@ -777,6 +777,10 @@ video {
float: left;
}
.m-8 {
margin: 2rem;
}
.m-4 {
margin: 1rem;
}
@ -789,10 +793,6 @@ video {
margin: 0px;
}
.m-8 {
margin: 2rem;
}
.m-2 {
margin: 0.5rem;
}
@ -1071,14 +1071,14 @@ video {
height: 6rem;
}
.h-screen {
height: 100vh;
}
.h-full {
height: 100%;
}
.h-screen {
height: 100vh;
}
.h-32 {
height: 8rem;
}
@ -1106,6 +1106,10 @@ video {
height: fit-content;
}
.h-16 {
height: 4rem;
}
.h-0 {
height: 0px;
}
@ -1134,10 +1138,6 @@ video {
height: 1.25rem;
}
.h-16 {
height: 4rem;
}
.h-48 {
height: 12rem;
}
@ -1202,6 +1202,10 @@ video {
width: 1.5rem;
}
.w-16 {
width: 4rem;
}
.w-screen {
width: 100vw;
}
@ -1236,10 +1240,6 @@ video {
width: 2.75rem;
}
.w-16 {
width: 4rem;
}
.w-64 {
width: 16rem;
}
@ -1931,11 +1931,6 @@ video {
line-height: 1.75rem;
}
.text-5xl {
font-size: 3rem;
line-height: 1;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
@ -1956,6 +1951,11 @@ video {
line-height: 2.5rem;
}
.text-5xl {
font-size: 3rem;
line-height: 1;
}
.font-extrabold {
font-weight: 800;
}
@ -2039,11 +2039,6 @@ video {
letter-spacing: -0.025em;
}
.text-red-500 {
--tw-text-opacity: 1;
color: rgb(239 68 68 / var(--tw-text-opacity));
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
@ -2250,6 +2245,9 @@ video {
--catch-detail-foregroundcolor: white;
--catch-detail-color-contrast: #fb3afb;
--image-carousel-height: 350px;
/** Technical value, used by icon.svelte
*/
--svg-color: #000000;
}
/***********************************************************************\
@ -2795,6 +2793,10 @@ a.link-underline {
overflow: visible !important;
}
svg.apply-fill path {
fill: var(--svg-color)
}
.compass_arrow {
width: calc( 2.5rem - 1px ) ;
height: calc( 2.5rem - 1px )

View file

@ -6,6 +6,7 @@ import { Utils } from "../src/Utils"
import Validators from "../src/UI/InputElement/Validators"
import { AllKnownLayouts } from "../src/Customizations/AllKnownLayouts"
import { AllSharedLayers } from "../src/Customizations/AllSharedLayers"
import Constants from "../src/Models/Constants"
const metainfo = {
type: "One of the inputValidator types",
@ -199,11 +200,12 @@ function extractHintsFrom(
if (hints["suggestions"]) {
const suggestions = hints["suggestions"]
const f = new Function("{ layers, themes, validators }", suggestions)
const f = new Function("{ layers, themes, validators, Constants }", suggestions)
hints["suggestions"] = f({
layers: AllSharedLayers.sharedLayers,
themes: AllKnownLayouts.allKnownLayouts,
validators: Validators,
Constants: Constants
})
}
return hints

View file

@ -114,27 +114,42 @@ export default class Constants {
* These are the values that are allowed to use as 'backdrop' icon for a map pin
*/
private static readonly _defaultPinIcons = [
"pin",
"square",
"circle",
"none",
"pin",
"person",
"plus",
"ring",
"star",
"teardrop",
"triangle",
"checkmark",
"clock",
"close",
"crosshair",
"help",
"home",
"invalid",
"location",
"location_empty",
"location_locked",
"note",
"resolved",
"ring",
"scissors",
"teardrop",
"teardrop_with_hole_green",
"triangle",
"brick_wall_square",
"brick_wall_round",
"gps_arrow",
"checkmark",
"help",
"clock",
"invalid",
"close",
"invalid",
"heart",
"heart_outline",
"confirm",
"direction",
"not_found",
"mastodon",
"party",
"addSmall",
] as const
public static readonly defaultPinIcons: string[] = <any>Constants._defaultPinIcons

View file

@ -24,6 +24,7 @@ import { ConversionContext } from "./ConversionContext"
import * as eli from "../../../assets/editor-layer-index.json"
import { AvailableRasterLayers } from "../../RasterLayers"
import Back from "../../../assets/svg/Back.svelte"
import PointRenderingConfigJson from "../Json/PointRenderingConfigJson"
class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
private readonly _languages: string[]
@ -1012,6 +1013,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
*/
private readonly _path: string
private readonly _studioValidations: boolean
private readonly _validatePointRendering = new ValidatePointRendering()
constructor(path: string, isBuiltin, doesImageExist, studioValidations) {
super("Runs various checks against common mistakes for a layer", [], "PrevalidateLayer")
@ -1101,6 +1103,8 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
context.enter("pointRendering").err("There are no pointRenderings at all...")
}
json.pointRendering?.forEach((pr,i) => this._validatePointRendering.convert(pr, context.enters("pointeRendering", i)))
if (json["mapRendering"]) {
context.enter("mapRendering").err("This layer has a legacy 'mapRendering'")
}
@ -1405,13 +1409,40 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
}
}
class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJson> {
constructor() {
super("Various checks for pointRenderings", [], "ValidatePOintRendering")
}
convert(json: PointRenderingConfigJson, context: ConversionContext): PointRenderingConfigJson {
if (json.marker === undefined && json.label === undefined) {
context.err(`A point rendering should define at least an marker or a label`)
}
if (json["markers"]) {
context.enter("markers").err(`Detected a field 'markerS' in pointRendering. It is written as a singular case`)
}
if (json.marker && !Array.isArray(json.marker)) {
context.enter("marker").err(
"The marker in a pointRendering should be an array"
)
}
if (json.location.length == 0) {
context.enter("location").err (
"A pointRendering should have at least one 'location' to defined where it should be rendered. "
)
}
return json
}
}
export class ValidateLayer extends Conversion<
LayerConfigJson,
{ parsed: LayerConfig; raw: LayerConfigJson }
> {
private readonly _skipDefaultLayers: boolean
private readonly _prevalidation: PrevalidateLayer
constructor(
path: string,
isBuiltin: boolean,

View file

@ -506,7 +506,7 @@ export interface LayerConfigJson {
* If the way is part of a relation, MapComplete will attempt to update this relation as well
* question: Should the contributor be able to split ways using this layer?
* iftrue: enable the 'split-roads'-component
* iffalse: don't enable the split-roads componenet
* iffalse: don't enable the split-roads component
* ifunset: don't enable the split-roads component
* group: editing
*/

View file

@ -5,7 +5,7 @@ export interface IconConfigJson {
/**
* question: What icon should be used?
* type: icon
* suggestions: return ["pin","square","circle","checkmark","clock","close","crosshair","help","home","invalid","location","location_empty","location_locked","note","resolved","ring","scissors","teardrop","teardrop_with_hole_green","triangle"].map(i => ({if: "value="+i, then: i, icon: i}))
* suggestions: return Constants.defaultPinIcons.map(i => ({if: "value="+i, then: i, icon: i}))
*/
icon: string | MinimalTagRenderingConfigJson | { builtin: string; override: any }
/**

View file

@ -79,23 +79,7 @@ export default class PointRenderingConfig extends WithContextLoader {
}
})
if (json.marker === undefined && json.label === undefined) {
throw `At ${context}: A point rendering should define at least an marker or a label`
}
if (json["markers"]) {
throw `At ${context}.markers: detected a field 'markerS' in pointRendering. It is written as a singular case`
}
if (json.marker && !Array.isArray(json.marker)) {
throw `At ${context}.marker: the marker in a pointRendering should be an array`
}
if (this.location.size == 0) {
throw (
"A pointRendering should have at least one 'location' to defined where it should be rendered. (At " +
context +
".location)"
)
}
this.marker = (json.marker ?? []).map((m) => new IconConfig(<any>m))
if (json.css !== undefined) {
this.cssDef = this.tr("css", undefined)

View file

@ -371,20 +371,9 @@ export default class TagRenderingConfig {
let iconClass = commonSize
if (!!mapping.icon) {
if (typeof mapping.icon === "string" && mapping.icon !== "") {
let stripped = mapping.icon
if (stripped.endsWith(".svg")) {
stripped = stripped.substring(0, stripped.length - 4)
}
if (Constants.defaultPinIcons.indexOf(stripped) >= 0) {
icon = "./assets/svg/" + mapping.icon
if (!icon.endsWith(".svg")) {
icon += ".svg"
}
} else {
icon = mapping.icon
}
icon = mapping.icon.trim()
} else if (mapping.icon["path"]) {
icon = mapping.icon["path"]
icon = mapping.icon["path"].trim()
iconClass = mapping.icon["class"] ?? iconClass
}
}

View file

@ -1,7 +1,7 @@
<script lang="ts">
/**
* A mapcontrol button which allows the user to select a different background.
* Even though the componenet is very small, it gets it's own class as it is often reused
* Even though the component is very small, it gets it's own class as it is often reused
*/
import { Square3Stack3dIcon } from "@babeard/svelte-heroicons/solid"
import type { SpecialVisualizationState } from "../SpecialVisualization"

View file

@ -13,7 +13,7 @@
let iconItem = icon.icon?.GetRenderValue($tags)?.Subs($tags)?.txt
$: iconItem = icon.icon?.GetRenderValue($tags)?.Subs($tags)?.txt
let color = icon.color?.GetRenderValue(tags)?.txt ?? "#000000"
let color = icon.color?.GetRenderValue($tags)?.txt ?? "#000000"
$: color = icon.color?.GetRenderValue($tags)?.txt ?? "#000000"
</script>

View file

@ -1,46 +1,47 @@
<script lang="ts">
import Pin from "../../assets/svg/Pin.svelte"
import Square from "../../assets/svg/Square.svelte"
import Circle from "../../assets/svg/Circle.svelte"
import Checkmark from "../../assets/svg/Checkmark.svelte"
import Clock from "../../assets/svg/Clock.svelte"
import Close from "../../assets/svg/Close.svelte"
import Crosshair from "../../assets/svg/Crosshair.svelte"
import Help from "../../assets/svg/Help.svelte"
import Home from "../../assets/svg/Home.svelte"
import Invalid from "../../assets/svg/Invalid.svelte"
import Location from "../../assets/svg/Location.svelte"
import Location_empty from "../../assets/svg/Location_empty.svelte"
import Location_locked from "../../assets/svg/Location_locked.svelte"
import Note from "../../assets/svg/Note.svelte"
import Resolved from "../../assets/svg/Resolved.svelte"
import Ring from "../../assets/svg/Ring.svelte"
import Scissors from "../../assets/svg/Scissors.svelte"
import Teardrop from "../../assets/svg/Teardrop.svelte"
import Teardrop_with_hole_green from "../../assets/svg/Teardrop_with_hole_green.svelte"
import Triangle from "../../assets/svg/Triangle.svelte"
import Brick_wall_square from "../../assets/svg/Brick_wall_square.svelte"
import Brick_wall_round from "../../assets/svg/Brick_wall_round.svelte"
import Gps_arrow from "../../assets/svg/Gps_arrow.svelte"
import { HeartIcon } from "@babeard/svelte-heroicons/solid"
import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline"
import Confirm from "../../assets/svg/Confirm.svelte"
import Not_found from "../../assets/svg/Not_found.svelte"
import { twMerge } from "tailwind-merge"
import Direction_gradient from "../../assets/svg/Direction_gradient.svelte"
import Mastodon from "../../assets/svg/Mastodon.svelte"
import Party from "../../assets/svg/Party.svelte"
import AddSmall from "../../assets/svg/AddSmall.svelte"
import Pin from "../../assets/svg/Pin.svelte"
import Square from "../../assets/svg/Square.svelte"
import Circle from "../../assets/svg/Circle.svelte"
import Checkmark from "../../assets/svg/Checkmark.svelte"
import Clock from "../../assets/svg/Clock.svelte"
import Close from "../../assets/svg/Close.svelte"
import Crosshair from "../../assets/svg/Crosshair.svelte"
import Help from "../../assets/svg/Help.svelte"
import Home from "../../assets/svg/Home.svelte"
import Invalid from "../../assets/svg/Invalid.svelte"
import Location from "../../assets/svg/Location.svelte"
import Location_empty from "../../assets/svg/Location_empty.svelte"
import Location_locked from "../../assets/svg/Location_locked.svelte"
import Note from "../../assets/svg/Note.svelte"
import Resolved from "../../assets/svg/Resolved.svelte"
import Ring from "../../assets/svg/Ring.svelte"
import Scissors from "../../assets/svg/Scissors.svelte"
import Teardrop from "../../assets/svg/Teardrop.svelte"
import Teardrop_with_hole_green from "../../assets/svg/Teardrop_with_hole_green.svelte"
import Triangle from "../../assets/svg/Triangle.svelte"
import Brick_wall_square from "../../assets/svg/Brick_wall_square.svelte"
import Brick_wall_round from "../../assets/svg/Brick_wall_round.svelte"
import Gps_arrow from "../../assets/svg/Gps_arrow.svelte"
import { HeartIcon } from "@babeard/svelte-heroicons/solid"
import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline"
import Confirm from "../../assets/svg/Confirm.svelte"
import Not_found from "../../assets/svg/Not_found.svelte"
import { twMerge } from "tailwind-merge"
import Direction_gradient from "../../assets/svg/Direction_gradient.svelte"
import Mastodon from "../../assets/svg/Mastodon.svelte"
import Party from "../../assets/svg/Party.svelte"
import AddSmall from "../../assets/svg/AddSmall.svelte"
/**
* Renders a single icon.
*
* Icons -placed on top of each other- form a 'Marker' together
*/
/**
* Renders a single icon.
*
* Icons -placed on top of each other- form a 'Marker' together
*/
export let icon: string | undefined
export let color: string | undefined = undefined
export let clss: string | undefined = undefined
export let icon: string | undefined
export let color: string | undefined = undefined
export let clss: string | undefined = undefined
</script>
{#if icon}
@ -99,9 +100,9 @@
{:else if icon === "invalid"}
<Invalid {color} class={clss} />
{:else if icon === "heart"}
<HeartIcon class={clss} />
<HeartIcon style="--svg-color: {color}" class={twMerge(clss,"apply-fill")} />
{:else if icon === "heart_outline"}
<HeartOutlineIcon class={clss} />
<HeartOutlineIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
{:else if icon === "confirm"}
<Confirm class={clss} {color} />
{:else if icon === "direction"}
@ -118,3 +119,4 @@
<img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" alt="" />
{/if}
{/if}

View file

@ -27,7 +27,7 @@
/**
* Indicates if this tagRendering currently shows the attribute or asks the question to _change_ the property
*/
export let editMode = !config.IsKnown(tags.data) // || showQuestionIfUnknown;
export let editMode = !config.IsKnown(tags.data)
if (tags) {
onDestroy(
tags.addCallbackD((tags) => {

View file

@ -159,7 +159,7 @@
}
}
function onSave() {
function onSave(e) {
if (selectedTags === undefined) {
return
}

View file

@ -41,7 +41,6 @@
<TagRenderingEditable
{config}
selectedElement={undefined}
showQuestionIfUnknown={true}
{state}
{tags}
/>

View file

@ -117,7 +117,6 @@
selectedElement={state.exampleFeature}
{config}
editingEnabled={new ImmutableStore(true)}
showQuestionIfUnknown={true}
{state}
{tags}
/>

View file

@ -187,7 +187,6 @@
editMode={startInEditMode}
{config}
selectedElement={undefined}
showQuestionIfUnknown={true}
{state}
{tags}
/>

View file

@ -215,7 +215,6 @@
<TagRenderingEditable
{config}
selectedElement={undefined}
showQuestionIfUnknown={!schema.hints?.ifunset}
{state}
{tags}
/>

View file

@ -139,7 +139,6 @@
<TagRenderingEditable
config={configBuiltin}
selectedElement={undefined}
showQuestionIfUnknown={true}
{state}
{tags}
/>

View file

@ -1,16 +1,7 @@
<script lang="ts">
// Testing grounds
import Motion from "../Sensors/Motion"
import { Store, Stores } from "../Logic/UIEventSource"
let maxAcc = Motion.singleton.maxAcc
let shaken = Motion.singleton.lastShakeEvent
let recentlyShaken = Stores.Chronic(250).mapD(
(now) => now.getTime() - 3000 < shaken.data?.getTime()
)
import Icon from "./Map/Icon.svelte"
</script>
Acc: {$maxAcc}
{#if $recentlyShaken}
<div class="text-5xl text-red-500">SHAKEN</div>
{/if}
<Icon clss="h-16 w-16" icon="heart" color="#ff0000"/>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -225,6 +225,94 @@
],
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation"
},
{
"path": [
"mappings",
"alsoShowIf"
],
"required": false,
"hints": {},
"type": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"$ref": "#/definitions/{or:TagConfigJson[];}"
},
{
"type": "string"
}
],
"description": "Also show this 'then'-option if the feature matches these tags.\nIdeal for outdated tags."
},
{
"path": [
"mappings",
"alsoShowIf",
"and"
],
"required": false,
"hints": {
"typehint": "tag"
},
"type": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"type": "object",
"properties": {
"or": {
"type": "array",
"items": {
"$ref": "#/definitions/TagConfigJson"
}
}
},
"required": [
"or"
]
},
{
"type": "string"
}
],
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation"
},
{
"path": [
"mappings",
"alsoShowIf",
"or"
],
"required": false,
"hints": {
"typehint": "tag"
},
"type": [
{
"$ref": "#/definitions/{and:TagConfigJson[];}"
},
{
"type": "object",
"properties": {
"or": {
"type": "array",
"items": {
"$ref": "#/definitions/TagConfigJson"
}
}
},
"required": [
"or"
]
},
{
"type": "string"
}
],
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation"
},
{
"path": [
"mappings",
@ -565,6 +653,10 @@
{
"if": "value=id",
"then": "<b>id</b> Checks for valid identifiers for layers, will automatically replace spaces and uppercase"
},
{
"if": "value=slope",
"then": "<b>slope</b> Validates that the slope is a valid number.The accompanying input element uses the gyroscope and the compass to determine the correct incline. The sign of the incline will be set automatically. The bearing of the way is compared to the bearing of the compass, as such, the device knows if it is measuring in the forward or backward direction."
}
]
},
@ -775,6 +867,22 @@
],
"description": "This hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like"
},
{
"path": [
"editButtonAriaLabel"
],
"required": false,
"hints": {},
"type": [
{
"$ref": "#/definitions/Record<string,string>"
},
{
"type": "string"
}
],
"description": "When using a screenreader and selecting the 'edit' button, the current rendered value is read aloud in normal circumstances.\nIn some rare cases, this is not desirable. For example, if the rendered value is a link to a website, this link can be selected (and will be read aloud).\nIf the user presses _tab_ again, they'll select the button and have the link read aloud a second time."
},
{
"path": [
"labels"

View file

@ -53,6 +53,9 @@
--image-carousel-height: 350px;
/** Technical value, used by icon.svelte
*/
--svg-color: #000000;
}
/***********************************************************************\
@ -612,6 +615,10 @@ a.link-underline {
overflow: visible !important;
}
svg.apply-fill path {
fill: var(--svg-color)
}
.compass_arrow {
width: calc( 2.5rem - 1px ) ;
height: calc( 2.5rem - 1px )