diff --git a/Docs/Schemas/LayerConfigJson.schema.json b/Docs/Schemas/LayerConfigJson.schema.json index d81d9085d..a0a0d808e 100644 --- a/Docs/Schemas/LayerConfigJson.schema.json +++ b/Docs/Schemas/LayerConfigJson.schema.json @@ -576,6 +576,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -639,7 +663,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -696,10 +720,10 @@ "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -710,7 +734,7 @@ ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -734,7 +758,7 @@ ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -751,7 +775,7 @@ ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -765,18 +789,18 @@ ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -790,7 +814,7 @@ ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, @@ -1114,7 +1138,6 @@ "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1133,10 +1156,11 @@ "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1155,7 +1179,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1168,7 +1192,7 @@ ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1179,7 +1203,7 @@ ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1233,6 +1257,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -1286,7 +1334,6 @@ "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1305,10 +1352,11 @@ "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1327,7 +1375,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1340,7 +1388,7 @@ ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1351,7 +1399,7 @@ ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1405,6 +1453,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ diff --git a/Docs/Schemas/LayerConfigJsonJSC.ts b/Docs/Schemas/LayerConfigJsonJSC.ts index 9ba937b91..54375a114 100644 --- a/Docs/Schemas/LayerConfigJsonJSC.ts +++ b/Docs/Schemas/LayerConfigJsonJSC.ts @@ -571,6 +571,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -634,7 +658,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -689,10 +713,10 @@ export default { "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -703,7 +727,7 @@ export default { ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -727,7 +751,7 @@ export default { ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -744,7 +768,7 @@ export default { ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -758,18 +782,18 @@ export default { ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -783,7 +807,7 @@ export default { ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, @@ -1102,7 +1126,6 @@ export default { "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1121,10 +1144,11 @@ export default { "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1143,7 +1167,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1156,7 +1180,7 @@ export default { ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1167,7 +1191,7 @@ export default { ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1221,6 +1245,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -1273,7 +1321,6 @@ export default { "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1292,10 +1339,11 @@ export default { "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1314,7 +1362,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1327,7 +1375,7 @@ export default { ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1338,7 +1386,7 @@ export default { ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1392,6 +1440,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ diff --git a/Docs/Schemas/LayoutConfigJson.schema.json b/Docs/Schemas/LayoutConfigJson.schema.json index cc8881dab..51f89ba18 100644 --- a/Docs/Schemas/LayoutConfigJson.schema.json +++ b/Docs/Schemas/LayoutConfigJson.schema.json @@ -473,6 +473,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -536,7 +560,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -593,10 +617,10 @@ "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -607,7 +631,7 @@ ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -631,7 +655,7 @@ ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -648,7 +672,7 @@ ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -662,18 +686,18 @@ ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -687,7 +711,7 @@ ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, @@ -1011,7 +1035,6 @@ "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1030,10 +1053,11 @@ "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1052,7 +1076,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1065,7 +1089,7 @@ ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1076,7 +1100,7 @@ ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1130,6 +1154,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -1183,7 +1231,6 @@ "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1202,10 +1249,11 @@ "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1224,7 +1272,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1237,7 +1285,7 @@ ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1248,7 +1296,7 @@ ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1302,6 +1350,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ diff --git a/Docs/Schemas/LayoutConfigJsonJSC.ts b/Docs/Schemas/LayoutConfigJsonJSC.ts index f4c8998b2..51ff7f2a6 100644 --- a/Docs/Schemas/LayoutConfigJsonJSC.ts +++ b/Docs/Schemas/LayoutConfigJsonJSC.ts @@ -468,6 +468,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -531,7 +555,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -586,10 +610,10 @@ export default { "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -600,7 +624,7 @@ export default { ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -624,7 +648,7 @@ export default { ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -641,7 +665,7 @@ export default { ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -655,18 +679,18 @@ export default { ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -680,7 +704,7 @@ export default { ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, @@ -999,7 +1023,6 @@ export default { "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1018,10 +1041,11 @@ export default { "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1040,7 +1064,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1053,7 +1077,7 @@ export default { ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1064,7 +1088,7 @@ export default { ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1118,6 +1142,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -1170,7 +1218,6 @@ export default { "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -1189,10 +1236,11 @@ export default { "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -1211,7 +1259,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -1224,7 +1272,7 @@ export default { ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1235,7 +1283,7 @@ export default { ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -1289,6 +1337,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ diff --git a/Docs/Schemas/LineRenderingConfigJson.schema.json b/Docs/Schemas/LineRenderingConfigJson.schema.json index 13f63a675..cd636b995 100644 --- a/Docs/Schemas/LineRenderingConfigJson.schema.json +++ b/Docs/Schemas/LineRenderingConfigJson.schema.json @@ -241,6 +241,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -304,7 +328,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/LineRenderingConfigJsonJSC.ts b/Docs/Schemas/LineRenderingConfigJsonJSC.ts index c2596f4fb..6f0007229 100644 --- a/Docs/Schemas/LineRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/LineRenderingConfigJsonJSC.ts @@ -236,6 +236,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -299,7 +323,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/MappingConfigJson.schema.json b/Docs/Schemas/MappingConfigJson.schema.json index 781aeaaa4..6ac39c55a 100644 --- a/Docs/Schemas/MappingConfigJson.schema.json +++ b/Docs/Schemas/MappingConfigJson.schema.json @@ -3,10 +3,10 @@ "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -17,7 +17,7 @@ ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -41,7 +41,7 @@ ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -58,7 +58,7 @@ ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -72,18 +72,18 @@ ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -97,7 +97,7 @@ ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, @@ -274,6 +274,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -337,7 +361,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/MappingConfigJsonJSC.ts b/Docs/Schemas/MappingConfigJsonJSC.ts index ec439c61c..90f027d07 100644 --- a/Docs/Schemas/MappingConfigJsonJSC.ts +++ b/Docs/Schemas/MappingConfigJsonJSC.ts @@ -3,10 +3,10 @@ export default { "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -17,7 +17,7 @@ export default { ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -41,7 +41,7 @@ export default { ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -58,7 +58,7 @@ export default { ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -72,18 +72,18 @@ export default { ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -97,7 +97,7 @@ export default { ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, @@ -269,6 +269,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -332,7 +356,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/PointRenderingConfigJson.schema.json b/Docs/Schemas/PointRenderingConfigJson.schema.json index b5416d6be..87701204e 100644 --- a/Docs/Schemas/PointRenderingConfigJson.schema.json +++ b/Docs/Schemas/PointRenderingConfigJson.schema.json @@ -339,6 +339,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -402,7 +426,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/PointRenderingConfigJsonJSC.ts b/Docs/Schemas/PointRenderingConfigJsonJSC.ts index 2034e9d27..e0ce8ac9f 100644 --- a/Docs/Schemas/PointRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/PointRenderingConfigJsonJSC.ts @@ -334,6 +334,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -397,7 +421,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json b/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json index 73982b597..56c115ec3 100644 --- a/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json +++ b/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json @@ -3,7 +3,6 @@ "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -22,10 +21,11 @@ "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -44,7 +44,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -57,7 +57,7 @@ ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -68,7 +68,7 @@ ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -122,6 +122,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -338,6 +362,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -401,7 +449,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -458,10 +506,10 @@ "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -472,7 +520,7 @@ ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -496,7 +544,7 @@ ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -513,7 +561,7 @@ ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -527,18 +575,18 @@ ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -552,7 +600,7 @@ ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, diff --git a/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts b/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts index 03784a9c9..58a35e028 100644 --- a/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts @@ -3,7 +3,6 @@ export default { "type": "object", "properties": { "id": { - "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nquestion: What is the id of this tagRendering?", "type": "string" }, "mappings": { @@ -22,10 +21,11 @@ export default { "type": "object", "properties": { "key": { + "description": "question What is the name of the attribute that should be written to?\nifunset: do not offer a freeform textfield as answer option", "type": "string" }, "type": { - "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values", + "description": "question: What is the input type?\nThe type of the text-field, e.g. 'string', 'nat', 'float', 'date',...\nSee Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values\nsuggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: \"value=\"+type.name, then: \"\"+type.name+\" \"+type.explanation.split(\"\\n\")[0]}))", "type": "string" }, "placeholder": { @@ -44,7 +44,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", + "description": "question: Show the freeform as box within the question?\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nifunset: do not show the", "type": "boolean" }, "default": { @@ -57,7 +57,7 @@ export default { ] }, "question": { - "description": "If it turns out that this tagRendering doesn't match _any_ value, then we show this question.\nIf undefined, the question is never asked and this tagrendering is read-only", + "description": "question: What question should be shown to the contributor?\n\nA question is presented ot the user if no mapping matches and the 'freeform' key is not set as well.\n\nifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering", "anyOf": [ { "$ref": "#/definitions/Record" @@ -68,7 +68,7 @@ export default { ] }, "questionHint": { - "description": "A hint which is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like", + "description": "question: Should some extra information be shown to the contributor, alongside the question?\nThis hint is shown in subtle text under the question.\nThis can give some extra information on what the answer should ook like\nifunset: No extra hint is given", "anyOf": [ { "$ref": "#/definitions/Record" @@ -122,6 +122,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -333,6 +357,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -396,7 +444,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -451,10 +499,10 @@ export default { "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -465,7 +513,7 @@ export default { ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -489,7 +537,7 @@ export default { ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -506,7 +554,7 @@ export default { ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -520,18 +568,18 @@ export default { ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -545,7 +593,7 @@ export default { ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, diff --git a/Docs/Schemas/RewritableConfigJson.schema.json b/Docs/Schemas/RewritableConfigJson.schema.json index c2e82c10a..1c7f723d8 100644 --- a/Docs/Schemas/RewritableConfigJson.schema.json +++ b/Docs/Schemas/RewritableConfigJson.schema.json @@ -201,6 +201,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -264,7 +288,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -321,10 +345,10 @@ "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -335,7 +359,7 @@ ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -359,7 +383,7 @@ ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -376,7 +400,7 @@ ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -390,18 +414,18 @@ ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -415,7 +439,7 @@ ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, diff --git a/Docs/Schemas/RewritableConfigJsonJSC.ts b/Docs/Schemas/RewritableConfigJsonJSC.ts index a9aca899a..f8dafe492 100644 --- a/Docs/Schemas/RewritableConfigJsonJSC.ts +++ b/Docs/Schemas/RewritableConfigJsonJSC.ts @@ -196,6 +196,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -259,7 +283,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", @@ -314,10 +338,10 @@ export default { "properties": { "if": { "$ref": "#/definitions/TagConfigJson", - "description": "quesiton: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" + "description": "question: What tags should be matched to show this option?\n\nIf in 'question'-mode and the contributor selects this option, these tags will be applied to the object" }, "then": { - "description": "Shown if the 'if is fulfilled\nType: rendered", + "description": "Question: What corresponding text should be shown?\nShown if the `if` is fulfilled\nType: rendered", "anyOf": [ { "$ref": "#/definitions/Record" @@ -328,7 +352,7 @@ export default { ] }, "icon": { - "description": "An extra icon supporting the choice\nType: icon", + "description": "question: What icon should be shown next to this mapping?\n\nThis icon will only be shown if the value is known, it is not displayed in the options (but might be in the future)\n\nifunset: Show no icon\nType: icon", "anyOf": [ { "type": "object", @@ -352,7 +376,7 @@ export default { ] }, "hideInAnswer": { - "description": "In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", + "description": "question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick?\niftrue: Never show this mapping as option to pick\nifunset: Always show this mapping as option to pick\ntype: tag\n\nIn some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).\n\nIn the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.\nIn this case, one of the mappings can be hiden by setting this flag.\n\nTo demonstrate an example making a default assumption:\n\nmappings: [\n {\n if: \"access=\", -- no access tag present, we assume accessible\n then: \"Accessible to the general public\",\n hideInAnswer: true\n },\n {\n if: \"access=yes\",\n then: \"Accessible to the general public\", -- the user selected this, we add that to OSM\n },\n {\n if: \"access=no\",\n then: \"Not accessible to the public\"\n }\n]\n\n\nFor example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.\nThen, we would add two mappings:\n{\n if: \"operator=Agentschap Natuur en Bos\" -- the non-abbreviated version which should be uploaded\n then: \"Maintained by Agentschap Natuur en Bos\"\n},\n{\n if: \"operator=ANB\", -- we don't want to upload abbreviations\n then: \"Maintained by Agentschap Natuur en Bos\"\n hideInAnswer: true\n}\n\nHide in answer can also be a tagsfilter, e.g. to make sure an option is only shown when appropriate.\nKeep in mind that this is reverse logic: it will be hidden in the answer if the condition is true, it will thus only show in the case of a mismatch\n\ne.g., for toilets: if \"wheelchair=no\", we know there is no wheelchair dedicated room.\nFor the location of the changing table, the option \"in the wheelchair accessible toilet is weird\", so we write:\n\n{\n \"question\": \"Where is the changing table located?\"\n \"mappings\": [\n {\"if\":\"changing_table:location=female\",\"then\":\"In the female restroom\"},\n {\"if\":\"changing_table:location=male\",\"then\":\"In the male restroom\"},\n {\"if\":\"changing_table:location=wheelchair\",\"then\":\"In the wheelchair accessible restroom\", \"hideInAnswer\": \"wheelchair=no\"},\n\n ]\n}\n\nAlso have a look for the meta-tags\n{\n if: \"operator=Agentschap Natuur en Bos\",\n then: \"Maintained by Agentschap Natuur en Bos\",\n hideInAnswer: \"_country!=be\"\n}", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -369,7 +393,7 @@ export default { ] }, "ifnot": { - "description": "Only 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`", + "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`", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -383,18 +407,18 @@ export default { ] }, "addExtraTags": { - "description": "If chosen as answer, these tags will be applied as well onto the object.\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", + "description": "question: What extra tags should be added to the object if this object is chosen?\ntype: simple_tag[]\n\nIf chosen as answer, these tags will be applied onto the object, together with the tags from the `if`\nNot compatible with multiAnswer.\n\nThis can be used e.g. to erase other keys which indicate the 'not' value:\n```json\n{\n \"if\": \"crossing:marking=rainbow\",\n \"then\": \"This is a rainbow crossing\",\n \"addExtraTags\": [\"not:crossing:marking=\"]\n}\n```", "type": "array", "items": { "type": "string" } }, "searchTerms": { - "description": "If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options", + "description": "question: If there are many options, what search terms match too?\nIf there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction\n\nSearchterms (per language) allow to easily find an option if there are many options\ngroup: hidden", "$ref": "#/definitions/Record" }, "priorityIf": { - "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly", + "description": "If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden\nUse this sparingly\ngroup: hidden", "anyOf": [ { "$ref": "#/definitions/{and:TagConfigJson[];}" @@ -408,7 +432,7 @@ export default { ] }, "#": { - "description": "Used for comments or to disable a validation\n\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", + "description": "Used for comments or to disable a validation\n\ngroup: hidden\nignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed", "type": "string" } }, diff --git a/Docs/Schemas/TagRenderingConfigJson.schema.json b/Docs/Schemas/TagRenderingConfigJson.schema.json index 7a1ec0bc6..8aae16f1d 100644 --- a/Docs/Schemas/TagRenderingConfigJson.schema.json +++ b/Docs/Schemas/TagRenderingConfigJson.schema.json @@ -39,6 +39,30 @@ } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -102,7 +126,7 @@ ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/Docs/Schemas/TagRenderingConfigJsonJSC.ts b/Docs/Schemas/TagRenderingConfigJsonJSC.ts index 4db078051..1ef94a235 100644 --- a/Docs/Schemas/TagRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/TagRenderingConfigJsonJSC.ts @@ -39,6 +39,30 @@ export default { } ] }, + "icon": { + "description": "question: what icon should be shown next to the 'render' value?\nAn icon shown next to the rendering; typically shown pretty small\nThis is only shown next to the \"render\" value\nType: icon", + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "description": "The path to the icon\nType: icon", + "type": "string" + }, + "class": { + "description": "A hint to mapcomplete on how to render this icon within the mapping.\nThis is translated to 'mapping-icon-', so defining your own in combination with a custom CSS is possible (but discouraged)", + "type": "string" + } + }, + "required": [ + "path" + ] + }, + { + "type": "string" + } + ] + }, "condition": { "description": "question: When should this item be shown?\n\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", "anyOf": [ @@ -102,7 +126,7 @@ export default { ] }, "icon": { - "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\nType: icon", + "description": "question: What icon should be added to this mapping?\nAn icon supporting this mapping; typically shown pretty small\ninline: {icon}\nType: icon", "anyOf": [ { "type": "object", diff --git a/package.json b/package.json index 165e2f7cb..5c1485bc6 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "start": "npm run generate:layeroverview && npm run strt", "strt": "vite --host", "strttest": "export NODE_OPTIONS=--max_old_space_size=8364 && parcel serve test.html assets/templates/*.svg assets/templates/fonts/*.ttf", - "watch:css": "tailwindcss -i index.css -o public/css/index-tailwind-output.css --watch", - "generate:css": "tailwindcss -i index.css -o public/css/index-tailwind-output.css", + "watch:css": "tailwindcss -i src/index.css -o public/css/index-tailwind-output.css --watch", + "generate:css": "tailwindcss -i src/index.css -o public/css/index-tailwind-output.css", "generate:doctests": "doctest-ts-improved . --ignore .*.spec.ts --ignore .*ConfigJson.ts", "test:run-only": "vitest --run test", "test": " export NODE_OPTIONS=\"--max-old-space-size=8192\" && npm run clean:tests && (npm run generate:doctests 2>&1 | grep -v \"No doctests found in\") && npm run test:run-only && npm run clean:tests", diff --git a/public/css/index-tailwind-output.css b/public/css/index-tailwind-output.css index 2cd4c9d5b..342dc79a7 100644 --- a/public/css/index-tailwind-output.css +++ b/public/css/index-tailwind-output.css @@ -698,16 +698,6 @@ video { position: sticky; } -<<<<<<< HEAD -======= -.inset-0 { - top: 0px; - right: 0px; - bottom: 0px; - left: 0px; -} - ->>>>>>> master .-inset-1 { top: -0.25rem; right: -0.25rem; @@ -747,26 +737,6 @@ video { bottom: 0px; } -.top-12 { - top: 3rem; -} - -.left-3 { - left: 0.75rem; -} - -.top-3 { - top: 0.75rem; -} - -.right-2 { - right: 0.5rem; -} - -.bottom-3 { - bottom: 0.75rem; -} - .right-1\/3 { right: 33.333333%; } @@ -877,6 +847,11 @@ video { margin-right: 0.5rem; } +.my-1 { + margin-top: 0.25rem; + margin-bottom: 0.25rem; +} + .mx-4 { margin-left: 1rem; margin-right: 1rem; @@ -887,6 +862,10 @@ video { margin-right: 3rem; } +.mb-4 { + margin-bottom: 1rem; +} + .mr-2 { margin-right: 0.5rem; } @@ -919,10 +898,6 @@ video { margin-right: 0.25rem; } -.mb-4 { - margin-bottom: 1rem; -} - .ml-1 { margin-left: 0.25rem; } @@ -1125,11 +1100,6 @@ video { height: 1rem; } -.h-min { - height: -webkit-min-content; - height: min-content; -} - .h-1\/2 { height: 50%; } @@ -1509,10 +1479,6 @@ video { overflow: hidden; } -.overflow-scroll { - overflow: scroll; -} - .overflow-y-auto { overflow-y: auto; } @@ -1560,18 +1526,14 @@ video { border-radius: 1rem; } -.rounded-3xl { - border-radius: 1.5rem; +.rounded-md { + border-radius: 0.375rem; } .rounded-lg { border-radius: 0.5rem; } -.rounded-md { - border-radius: 0.375rem; -} - .rounded-sm { border-radius: 0.125rem; } @@ -1642,7 +1604,6 @@ video { border-bottom-width: 2px; } -<<<<<<< HEAD .border-l-4 { border-left-width: 4px; } @@ -1651,12 +1612,6 @@ video { border-top-width: 1px; } -======= -.border-t { - border-top-width: 1px; -} - ->>>>>>> master .border-r { border-right-width: 1px; } @@ -1713,11 +1668,6 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-red-500 { - --tw-bg-opacity: 1; - background-color: rgb(239 68 68 / var(--tw-bg-opacity)); -} - .bg-black { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); @@ -1754,10 +1704,6 @@ video { padding: 0.5rem; } -.p-3 { - padding: 0.75rem; -} - .p-4 { padding: 1rem; } @@ -1802,10 +1748,6 @@ video { padding-right: 0.5rem; } -.pl-3 { - padding-left: 0.75rem; -} - .pl-2 { padding-left: 0.5rem; } @@ -1834,6 +1776,10 @@ video { padding-left: 1rem; } +.pl-3 { + padding-left: 0.75rem; +} + .pr-0 { padding-right: 0px; } @@ -1893,11 +1839,6 @@ video { line-height: 1.5rem; } -.text-xs { - font-size: 0.75rem; - line-height: 1rem; -} - .font-bold { font-weight: 700; } @@ -2136,12 +2077,6 @@ video { backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); } -.transition-colors { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - .transition { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter; transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; @@ -2150,12 +2085,14 @@ video { transition-duration: 150ms; } -.ease-in-out { +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; } -.\[a-zA-Z0-9\:_\] { - a-z-a--z0-9: ; +.ease-in-out { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } .\[key\:string\] { @@ -2166,6 +2103,10 @@ video { _: string; } +.\[a-zA-Z0-9\:_\] { + a-z-a--z0-9: ; +} + :root { /* * The main colour scheme of mapcomplete is configured here. @@ -2304,7 +2245,29 @@ input[type=text] { * This very important section defines what the various input elements look like within the 'low-interaction' and 'interactive'-blocks */ +button.small, .button.small { + line-height: 1rem; + margin: 0; + margin-left: 0.5rem; + padding: 0.25rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + font-size: unset; + border: 2px solid var(--button-background); + border-radius: 0.5rem; + font-weight: normal; + transition: all 250ms; + --tw-text-opacity: 1; + --tw-bg-opacity: 1; + background: var(--low-interaction-background); + color: var(--low-interaction-foreground); +} + button, .button { + align-items: center; display: inline-flex; line-height: 1.25rem; margin: 0.2rem; @@ -2313,7 +2276,6 @@ button, .button { padding-right: 0.6rem; font-size: large; font-weight: bold; - /*-- invisible border: rendered on hover*/ border: 2px solid var(--button-background); border-radius: 0.5rem; transition: all 250ms; @@ -2327,21 +2289,6 @@ button, .button { box-shadow: 0 5px 10px #88888888; } -button.small, .button.small { - line-height: 1rem; - margin: 0; - padding: 0.1rem; - font-size: unset; - /*-- invisible border: rendered on hover*/ - border: 2px solid var(--low-interaction-background); - border-radius: 0.1rem; - transition: all 250ms; - --tw-text-opacity: 1; - --tw-bg-opacity: 1; - background: var(--low-interaction-background); - color: var(--low-interaction-foreground); -} - button.selected, .button.selected { background-color: var(--catch-detail-color); border-color: var(--catch-detail-color); @@ -2754,10 +2701,6 @@ a.link-underline { } @media (min-width: 640px) { - .sm\:top-3 { - top: 0.75rem; - } - .sm\:m-2 { margin: 0.5rem; } @@ -2796,40 +2739,18 @@ a.link-underline { height: 6rem; } - .sm\:w-fit { - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - } - .sm\:w-24 { width: 6rem; } - .sm\:max-w-sm { - max-width: 24rem; - } - .sm\:max-w-xl { max-width: 36rem; } - .sm\:flex-row { - flex-direction: row; - } - - .sm\:flex-wrap { - flex-wrap: wrap; - } - .sm\:flex-nowrap { flex-wrap: nowrap; } - .sm\:items-start { - align-items: flex-start; - } - .sm\:items-stretch { align-items: stretch; } @@ -2850,10 +2771,6 @@ a.link-underline { padding: 0.5rem; } - .sm\:pl-0 { - padding-left: 0px; - } - .sm\:pt-1 { padding-top: 0.25rem; } @@ -2919,10 +2836,6 @@ a.link-underline { width: 2rem; } - .md\:w-1\/3 { - width: 33.333333%; - } - .md\:w-6\/12 { width: 50%; } diff --git a/scripts/fixSchemas.ts b/scripts/fixSchemas.ts index 5cb973d1d..1e5262358 100644 --- a/scripts/fixSchemas.ts +++ b/scripts/fixSchemas.ts @@ -5,6 +5,7 @@ import { AllSharedLayers } from "../src/Customizations/AllSharedLayers" import { AllKnownLayouts } from "../src/Customizations/AllKnownLayouts" import { ConfigMeta } from "../src/UI/Studio/configMeta" import { Utils } from "../src/Utils" +import Validators from "../src/UI/InputElement/Validators" const metainfo = { type: "One of the inputValidator types", @@ -21,6 +22,16 @@ const metainfo = { suggestions: "a javascript expression generating mappings", } +/** + * Applies 'onEach' on every leaf of the JSONSchema + * @param onEach + * @param scheme + * @param fullScheme + * @param path + * @param isHandlingReference + * @param required + * @constructor + */ function WalkScheme( onEach: (schemePart: JsonSchema, path: string[]) => T, scheme: JsonSchema, @@ -45,10 +56,15 @@ function WalkScheme( // We abort here to avoid infinite recursion return [] } + // The 'scheme' might contain some extra info, such as 'description' + // This effectively overwrites properties from the loaded scheme const loadedScheme = fullScheme.definitions[definitionName] + const syntheticScheme = { ...loadedScheme, ...scheme } + syntheticScheme["child-description"] = loadedScheme.description + delete syntheticScheme["$ref"] return WalkScheme( onEach, - loadedScheme, + syntheticScheme, fullScheme, path, [...isHandlingReference, definitionName], @@ -111,65 +127,106 @@ function WalkScheme( return results } +function extractHintsFrom( + description: string, + fieldnames: string[], + path: (string | number)[], + type: any +): Record { + if (!description) { + return {} + } + const hints = {} + const lines = description.split("\n") + for (const fieldname of fieldnames) { + const hintIndex = lines.findIndex((line) => + line + .trim() + .toLocaleLowerCase() + .startsWith(fieldname + ":") + ) + if (hintIndex < 0) { + continue + } + const hintLine = lines[hintIndex].substring((fieldname + ":").length).trim() + if (fieldname === "type") { + hints["typehint"] = hintLine + } else { + hints[fieldname] = hintLine + } + } + + if (hints["types"]) { + const numberOfExpectedSubtypes = hints["types"].replaceAll("|", ";").split(";").length + if (!Array.isArray(type)) { + throw ( + "At " + + path.join(".") + + "Invalid hint in the documentation: `types` indicates that there are " + + numberOfExpectedSubtypes + + " subtypes, but object does not support subtypes. Did you mean `type` instead?\n\tTypes are: " + + hints["types"] + ) + } + const numberOfActualTypes = type.length + if (numberOfActualTypes !== numberOfExpectedSubtypes) { + throw `At ${path.join( + "." + )}\nInvalid hint in the documentation: \`types\` indicates that there are ${numberOfExpectedSubtypes} subtypes, but there are ${numberOfActualTypes} subtypes +\tTypes are: ${hints["types"]}` + } + } + + if (hints["suggestions"]) { + const suggestions = hints["suggestions"] + const f = new Function("{ layers, themes, validators }", suggestions) + hints["suggestions"] = f({ + layers: AllSharedLayers.sharedLayers, + themes: AllKnownLayouts.allKnownLayouts, + validators: Validators, + }) + } + return hints +} + +/** + * Extracts the 'configMeta' from the given schema, based on attributes in the description + * @param fieldnames + * @param fullSchema + */ function addMetafields(fieldnames: string[], fullSchema: JsonSchema): ConfigMeta[] { + const fieldNamesSet = new Set(fieldnames) const onEach = (schemePart, path) => { if (schemePart.description === undefined) { return } + if (path.length === 2 && path[0] === "mappings" && path[1] === "if") { + console.log("HI") + } const type = schemePart.items?.anyOf ?? schemePart.type ?? schemePart.anyOf - const hints = {} - let description = schemePart.description.split("\n") - for (const fieldname of fieldnames) { - const hintIndex = description.findIndex((line) => - line - .trim() - .toLocaleLowerCase() - .startsWith(fieldname + ":") - ) - if (hintIndex < 0) { + let description = schemePart.description + + let hints = extractHintsFrom(description, fieldnames, path, type) + const childDescription = schemePart["child-description"] + if (childDescription) { + const childHints = extractHintsFrom(childDescription, fieldnames, path, type) + hints = { ...childHints, ...hints } + description = description ?? childDescription + } + + const cleanedDescription: string[] = [] + for (const line of description.split("\n")) { + const keyword = line.split(":").at(0).trim().toLowerCase() + if (fieldNamesSet.has(keyword)) { continue } - const hintLine = description[hintIndex].substring((fieldname + ":").length).trim() - description.splice(hintIndex, 1) - if (fieldname === "type") { - hints["typehint"] = hintLine - } else { - hints[fieldname] = hintLine - } + cleanedDescription.push(line) } - - if (hints["types"]) { - const numberOfExpectedSubtypes = hints["types"].replaceAll("|", ";").split(";").length - if (!Array.isArray(type)) { - throw ( - "At " + - path.join(".") + - "Invalid hint in the documentation: `types` indicates that there are " + - numberOfExpectedSubtypes + - " subtypes, but object does not support subtypes. Did you mean `type` instead?\n\tTypes are: " + - hints["types"] - ) - } - const numberOfActualTypes = type.length - if (numberOfActualTypes !== numberOfExpectedSubtypes) { - throw `At ${path.join( - "." - )}\nInvalid hint in the documentation: \`types\` indicates that there are ${numberOfExpectedSubtypes} subtypes, but there are ${numberOfActualTypes} subtypes -\tTypes are: ${hints["types"]}` - } + return { + hints, + type, + description: cleanedDescription.join("\n"), } - - if (hints["suggestions"]) { - const suggestions = hints["suggestions"] - console.log("Creating suggestions for expression", suggestions) - const f = new Function("{ layers, themes }", suggestions) - hints["suggestions"] = f({ - layers: AllSharedLayers.sharedLayers, - themes: AllKnownLayouts.allKnownLayouts, - }) - } - - return { hints, type, description: description.join("\n") } } return WalkScheme(onEach, fullSchema, fullSchema, [], [], fullSchema.required).map( @@ -209,8 +266,6 @@ function substituteReferences( path.type[i] = target continue } - - console.log("Expanding " + name) } } } @@ -236,10 +291,10 @@ function validateMeta(path: ConfigMeta): string | undefined { return undefined } if (path.hints.question === undefined && !Array.isArray(path.type)) { - return ( + /* return ( ctx + " does not have a question set. As such, MapComplete-studio users will not be able to set this property" - ) + )//*/ } return undefined @@ -250,18 +305,19 @@ function extractMeta( path: string, allDefinitions: Record ): string[] { - let themeSchema: JsonSchema = JSON.parse( + const schema: JsonSchema = JSON.parse( readFileSync("./Docs/Schemas/" + typename + ".schema.json", { encoding: "utf8" }) ) - const metakeys = Array.from(Object.keys(metainfo)) + const metakeys = Array.from(Object.keys(metainfo)).map((s) => s.toLowerCase()) - const paths = addMetafields(metakeys, themeSchema) + const paths = addMetafields(metakeys, schema) - substituteReferences(paths, themeSchema, allDefinitions) + substituteReferences(paths, schema, allDefinitions) - writeFileSync("./src/assets/" + path + ".json", JSON.stringify(paths, null, " ")) - console.log("Written meta to ./assets/" + path) + const fullPath = "./src/assets/schemas/" + path + ".json" + writeFileSync(fullPath, JSON.stringify(paths, null, " ")) + console.log("Written meta to " + fullPath) return Utils.NoNull(paths.map((p) => validateMeta(p))) } @@ -290,15 +346,17 @@ function main() { encoding: "utf8", }) } - const errs = extractMeta("LayerConfigJson", "layerconfigmeta", allDefinitions) - extractMeta("LayoutConfigJson", "layoutconfigmeta", allDefinitions) - extractMeta("TagRenderingConfigJson", "tagrenderingconfigmeta", allDefinitions) - extractMeta( - "QuestionableTagRenderingConfigJson", - "questionabletagrenderingconfigmeta", - allDefinitions + const errs: string[] = [] + // errs = extractMeta("LayerConfigJson", "layerconfigmeta", allDefinitions) + // errs.push(...extractMeta("LayoutConfigJson", "layoutconfigmeta", allDefinitions)) + // errs.push(...extractMeta("TagRenderingConfigJson", "tagrenderingconfigmeta", allDefinitions)) + errs.push( + ...extractMeta( + "QuestionableTagRenderingConfigJson", + "questionabletagrenderingconfigmeta", + allDefinitions + ) ) - if (errs.length > 0) { for (const err of errs) { console.error(err) diff --git a/src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts b/src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts index 5bc8bc1cb..e0e834059 100644 --- a/src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts +++ b/src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts @@ -1,21 +1,27 @@ import { TagConfigJson } from "./TagConfigJson" import { TagRenderingConfigJson } from "./TagRenderingConfigJson" +import { Translatable } from "./Translatable" export interface MappingConfigJson { /** - * quesiton: What tags should be matched to show this option? + * question: What tags should be matched to show this option? * * If in 'question'-mode and the contributor selects this option, these tags will be applied to the object */ if: TagConfigJson /** - * Shown if the 'if is fulfilled + * Question: What corresponding text should be shown? + * Shown if the `if` is fulfilled * Type: rendered */ then: string | Record /** - * An extra icon supporting the choice + * question: What icon should be shown next to this mapping? + * + * This icon will only be shown if the value is known, it is not displayed in the options (but might be in the future) + * + * ifunset: Show no icon * Type: icon */ icon?: @@ -33,6 +39,11 @@ export interface MappingConfigJson { } /** + * question: Under what circumstances should this mapping be hidden from the possibilities a contributor can pick? + * iftrue: Never show this mapping as option to pick + * ifunset: Always show this mapping as option to pick + * type: tag + * * In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation). * * In the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user. @@ -93,7 +104,10 @@ export interface MappingConfigJson { * } */ hideInAnswer?: boolean | TagConfigJson + /** + * question: What tags should be applied if this mapping is _not_ chosen? + * * Only applicable if 'multiAnswer' is set. * This is for situations such as: * `accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected. @@ -104,7 +118,10 @@ export interface MappingConfigJson { ifnot?: TagConfigJson /** - * If chosen as answer, these tags will be applied as well onto the object. + * question: What extra tags should be added to the object if this object is chosen? + * type: simple_tag[] + * + * If chosen as answer, these tags will be applied onto the object, together with the tags from the `if` * Not compatible with multiAnswer. * * This can be used e.g. to erase other keys which indicate the 'not' value: @@ -120,21 +137,25 @@ export interface MappingConfigJson { addExtraTags?: string[] /** + * question: If there are many options, what search terms match too? * If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction * * Searchterms (per language) allow to easily find an option if there are many options + * group: hidden */ searchTerms?: Record /** * If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden * Use this sparingly + * group: hidden */ priorityIf?: TagConfigJson /** * Used for comments or to disable a validation * + * group: hidden * ignore-image-in-then: normally, a `then`-clause is not allowed to have an `img`-html-element as icons are preferred. In some cases (most notably title-icons), this is allowed */ "#"?: string | "ignore-image-in-then" @@ -145,7 +166,7 @@ export interface MappingConfigJson { * If the desired tags are missing and a question is defined, a question will be shown instead. */ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJson { - /** + /* * The id of the tagrendering, should be an unique string. * Used to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise. * @@ -176,7 +197,8 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs */ freeform?: { /** - * @inheritDoc + * question What is the name of the attribute that should be written to? + * ifunset: do not offer a freeform textfield as answer option */ key: string @@ -184,6 +206,7 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs * question: What is the input type? * The type of the text-field, e.g. 'string', 'nat', 'float', 'date',... * See Docs/SpecialInputElements.md and UI/Input/ValidatedTextField.ts for supported values + * suggestions: return validators.AllValidators.filter(type => !type.isMeta).map((type) => ({if: "value="+type.name, then: ""+type.name+" "+type.explanation.split("\n")[0]})) */ type?: string /** @@ -203,11 +226,12 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs addExtraTags?: string[] /** - * When set, influences the way a question is asked. + * question: Show the freeform as box within the question? * Instead of showing a full-width text field, the text field will be shown within the rendering of the question. * * This combines badly with special input elements, as it'll distort the layout. - * Note that this will be set automatically if no special elements are present. + * ifunset: show the freeform input field full-width + * iftrue: show the freeform input field as a small field within the question */ inline?: boolean @@ -219,16 +243,21 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs } /** - * If it turns out that this tagRendering doesn't match _any_ value, then we show this question. - * If undefined, the question is never asked and this tagrendering is read-only + * question: What question should be shown to the contributor? + * + * A question is presented ot the user if no mapping matches and the 'freeform' key is not set as well. + * + * ifunset: This tagrendering will be shown if it is known, but cannot be edited by the contributor, effectively resutling in a read-only rendering */ - question?: string | Record + question?: string | Translatable /** - * A hint which is shown in subtle text under the question. + * question: Should some extra information be shown to the contributor, alongside the question? + * This hint is shown in subtle text under the question. * This can give some extra information on what the answer should ook like + * ifunset: No extra hint is given */ - questionHint?: string | Record + questionHint?: string | Translatable /** * A list of labels. These are strings that are used for various purposes, e.g. to filter them away diff --git a/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts b/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts index a51fb953a..1f031dda2 100644 --- a/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts +++ b/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts @@ -138,6 +138,7 @@ export interface TagRenderingConfigJson { /** * question: What icon should be added to this mapping? * An icon supporting this mapping; typically shown pretty small + * inline: {icon} * Type: icon */ icon?: diff --git a/src/Models/ThemeConfig/TagRenderingConfig.ts b/src/Models/ThemeConfig/TagRenderingConfig.ts index 891a53993..f0465c245 100644 --- a/src/Models/ThemeConfig/TagRenderingConfig.ts +++ b/src/Models/ThemeConfig/TagRenderingConfig.ts @@ -150,7 +150,9 @@ export default class TagRenderingConfig { json.freeform.type && Validators.availableTypes.indexOf(json.freeform.type) < 0 ) { - throw `At ${context}: invalid type, perhaps you meant ${Utils.sortedByLevenshteinDistance( + throw `At ${context}: invalid type ${ + json.freeform.type + }, perhaps you meant ${Utils.sortedByLevenshteinDistance( json.freeform.key, Validators.availableTypes, (s) => s diff --git a/src/UI/InputElement/Helpers/SimpleTagInput.svelte b/src/UI/InputElement/Helpers/SimpleTagInput.svelte new file mode 100644 index 000000000..4e2747876 --- /dev/null +++ b/src/UI/InputElement/Helpers/SimpleTagInput.svelte @@ -0,0 +1,20 @@ + + + + diff --git a/src/UI/InputElement/Helpers/TagInput.svelte b/src/UI/InputElement/Helpers/TagInput.svelte new file mode 100644 index 000000000..dca277b73 --- /dev/null +++ b/src/UI/InputElement/Helpers/TagInput.svelte @@ -0,0 +1,33 @@ + + + + diff --git a/src/UI/InputElement/InputHelpers.ts b/src/UI/InputElement/InputHelpers.ts index 0693cf21d..d707d57c6 100644 --- a/src/UI/InputElement/InputHelpers.ts +++ b/src/UI/InputElement/InputHelpers.ts @@ -15,6 +15,8 @@ import { Feature } from "geojson" import { GeoOperations } from "../../Logic/GeoOperations" import ImageHelper from "./Helpers/ImageHelper.svelte" import TranslationInput from "./Helpers/TranslationInput.svelte" +import TagInput from "./Helpers/TagInput.svelte" +import SimpleTagInput from "./Helpers/SimpleTagInput.svelte" export interface InputHelperProperties { /** @@ -59,9 +61,11 @@ export default class InputHelpers { wikidata: InputHelpers.constructWikidataHelper, image: (value) => new SvelteUIElement(ImageHelper, { value }), translation: (value) => new SvelteUIElement(TranslationInput, { value }), + tag: (value) => new SvelteUIElement(TagInput, { value }), + simple_tag: (value) => new SvelteUIElement(SimpleTagInput, { value }), } as const - public static hideInputField : string[] = ["translation"] + public static hideInputField: string[] = ["translation", "simple_tag", "tag"] /** * Constructs a mapProperties-object for the given properties. diff --git a/src/UI/InputElement/Validator.ts b/src/UI/InputElement/Validator.ts index 9b61c4b0b..ab48ad4ff 100644 --- a/src/UI/InputElement/Validator.ts +++ b/src/UI/InputElement/Validator.ts @@ -1,6 +1,6 @@ -import BaseUIElement from "../BaseUIElement"; -import { Translation } from "../i18n/Translation"; -import Translations from "../i18n/Translations"; +import BaseUIElement from "../BaseUIElement" +import { Translation } from "../i18n/Translation" +import Translations from "../i18n/Translations" /** * A 'TextFieldValidator' contains various methods to check and cleanup an entered value or to give feedback. @@ -16,13 +16,23 @@ export abstract class Validator { /** * What HTML-inputmode to use */ - public readonly inputmode?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search' + public readonly inputmode?: + | "none" + | "text" + | "tel" + | "url" + | "email" + | "numeric" + | "decimal" + | "search" public readonly textArea: boolean + public readonly isMeta?: boolean + constructor( name: string, explanation: string | BaseUIElement, - inputmode?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search', + inputmode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search", textArea?: false | boolean ) { this.name = name diff --git a/src/UI/InputElement/Validators.ts b/src/UI/InputElement/Validators.ts index 77e113d95..5eb9e33fa 100644 --- a/src/UI/InputElement/Validators.ts +++ b/src/UI/InputElement/Validators.ts @@ -23,6 +23,8 @@ import ImageUrlValidator from "./Validators/ImageUrlValidator" import TagKeyValidator from "./Validators/TagKeyValidator" import TranslationValidator from "./Validators/TranslationValidator" import FediverseValidator from "./Validators/FediverseValidator" +import IconValidator from "./Validators/IconValidator" +import TagValidator from "./Validators/TagValidator" export type ValidatorType = (typeof Validators.availableTypes)[number] @@ -48,7 +50,9 @@ export default class Validators { "simple_tag", "key", "translation", + "icon", "fediverse", + "tag", ] as const public static readonly AllValidators: ReadonlyArray = [ @@ -70,20 +74,15 @@ export default class Validators { new ColorValidator(), new ImageUrlValidator(), new SimpleTagValidator(), + new TagValidator(), new TagKeyValidator(), new TranslationValidator(), + new IconValidator(), new FediverseValidator(), ] private static _byType = Validators._byTypeConstructor() - private static _byTypeConstructor(): Map { - const map = new Map() - for (const validator of Validators.AllValidators) { - map.set(validator.name, validator) - } - return map - } public static HelpText(): BaseUIElement { const explanations: BaseUIElement[] = Validators.AllValidators.map((type) => new Combine([new Title(type.name, 3), type.explanation]).SetClass("flex flex-col") @@ -95,6 +94,14 @@ export default class Validators { ]).SetClass("flex flex-col") } + private static _byTypeConstructor(): Map { + const map = new Map() + for (const validator of Validators.AllValidators) { + map.set(validator.name, validator) + } + return map + } + static get(type: ValidatorType): Validator { return Validators._byType.get(type) } diff --git a/src/UI/InputElement/Validators/IconValidator.ts b/src/UI/InputElement/Validators/IconValidator.ts new file mode 100644 index 000000000..da35c6d3e --- /dev/null +++ b/src/UI/InputElement/Validators/IconValidator.ts @@ -0,0 +1,46 @@ +import { Validator } from "../Validator" +import { Translation } from "../../i18n/Translation" +import licenses from "../../../assets/generated/license_info.json" +import { Utils } from "../../../Utils" + +export default class IconValidator extends Validator { + private static allLicenses = new Set(licenses.map((l) => l.path)) + private static allLicensesArr = Array.from(IconValidator.allLicenses) + public static readonly isMeta = true + constructor() { + super("icon", "Makes sure that a valid .svg-path is added") + } + + getFeedback(s: string, getCountry, sloppy?: boolean): Translation | undefined { + if (!s.startsWith("http")) { + if (!IconValidator.allLicenses.has(s)) { + const close = sloppy + ? [] + : Utils.sortedByLevenshteinDistance( + s.substring(s.lastIndexOf("/")), + IconValidator.allLicensesArr, + (s) => s.substring(s.lastIndexOf("/")) + ).slice(0, 5) + return new Translation( + [ + `Unkown builtin icon ${s}, perhaps you meant one of:
    `, + ...close.map( + (item) => + `
  • ${item}
  • ` + ), + "
", + ].join("") + ) + } + } + + if (!s.endsWith(".svg")) { + return new Translation("An icon should end with `.svg`") + } + return undefined + } + + isValid(key: string, getCountry?: () => string): boolean { + return this.getFeedback(key, getCountry, true) === undefined + } +} diff --git a/src/UI/InputElement/Validators/ImageUrlValidator.ts b/src/UI/InputElement/Validators/ImageUrlValidator.ts index 2c18e1d41..5d9e11507 100644 --- a/src/UI/InputElement/Validators/ImageUrlValidator.ts +++ b/src/UI/InputElement/Validators/ImageUrlValidator.ts @@ -3,6 +3,7 @@ import { Translation } from "../../i18n/Translation" export default class ImageUrlValidator extends UrlValidator { private static readonly allowedExtensions = ["jpg", "jpeg", "svg", "png"] + public readonly isMeta = true constructor() { super( diff --git a/src/UI/InputElement/Validators/SimpleTagValidator.ts b/src/UI/InputElement/Validators/SimpleTagValidator.ts index a982b1f75..f39ca9d1d 100644 --- a/src/UI/InputElement/Validators/SimpleTagValidator.ts +++ b/src/UI/InputElement/Validators/SimpleTagValidator.ts @@ -8,6 +8,8 @@ import TagKeyValidator from "./TagKeyValidator" */ export default class SimpleTagValidator extends Validator { private static readonly KeyValidator = new TagKeyValidator() + + public readonly isMeta = true constructor() { super( "simple_tag", diff --git a/src/UI/InputElement/Validators/TagKeyValidator.ts b/src/UI/InputElement/Validators/TagKeyValidator.ts index 5212feb20..510735739 100644 --- a/src/UI/InputElement/Validators/TagKeyValidator.ts +++ b/src/UI/InputElement/Validators/TagKeyValidator.ts @@ -3,6 +3,8 @@ import { Translation } from "../../i18n/Translation" import Translations from "../../i18n/Translations" export default class TagKeyValidator extends Validator { + + public readonly isMeta = true constructor() { super("key", "Validates a key, mostly that no weird characters are used") } diff --git a/src/UI/InputElement/Validators/TagValidator.ts b/src/UI/InputElement/Validators/TagValidator.ts new file mode 100644 index 000000000..aa4afef4f --- /dev/null +++ b/src/UI/InputElement/Validators/TagValidator.ts @@ -0,0 +1,24 @@ +import { Validator } from "../Validator" +import { Translation } from "../../i18n/Translation" +import Translations from "../../i18n/Translations" +import TagKeyValidator from "./TagKeyValidator" +import SimpleTagValidator from "./SimpleTagValidator" + +/** + * Checks that the input conforms a JSON-encoded tag expression or a simpleTag`key=value`, + */ +export default class TagValidator extends Validator { + + public readonly isMeta = true + constructor() { + super("tag", "A simple tag of the format `key=value` OR a tagExpression") + } + + getFeedback(tag: string, _): Translation | undefined { + return undefined + } + + isValid(tag: string, _): boolean { + return this.getFeedback(tag, _) === undefined + } +} diff --git a/src/UI/InputElement/Validators/TranslationValidator.ts b/src/UI/InputElement/Validators/TranslationValidator.ts index 5793e9371..79b8e0cfc 100644 --- a/src/UI/InputElement/Validators/TranslationValidator.ts +++ b/src/UI/InputElement/Validators/TranslationValidator.ts @@ -1,6 +1,8 @@ import { Validator } from "../Validator" export default class TranslationValidator extends Validator { + + public readonly isMeta = true constructor() { super("translation", "Makes sure the the string is of format `Record` ") } diff --git a/src/UI/Popup/TagRendering/TagRenderingEditable.svelte b/src/UI/Popup/TagRendering/TagRenderingEditable.svelte index c0db8b3b6..11c4646a7 100644 --- a/src/UI/Popup/TagRendering/TagRenderingEditable.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingEditable.svelte @@ -29,7 +29,7 @@ }) ) - let htmlElem: HTMLBaseElement + let htmlElem: HTMLDivElement $: { if (editMode && htmlElem !== undefined) { // EditMode switched to true, so the person wants to make a change @@ -37,7 +37,7 @@ // Some delay is applied to give Svelte the time to render the _question_ window.setTimeout(() => { - Utils.scrollIntoView(htmlElem) + Utils.scrollIntoView( htmlElem) }, 50) } } diff --git a/src/UI/Studio/EditLayer.svelte b/src/UI/Studio/EditLayer.svelte index 6bc7d9f12..3ef0340e0 100644 --- a/src/UI/Studio/EditLayer.svelte +++ b/src/UI/Studio/EditLayer.svelte @@ -1,7 +1,7 @@ + + + +{#if editMode} +
+
+ +
+ + +
+{:else} +
+ {#if Object.keys($thenParsed).length > 0} + + {new Translation($thenParsed).txt} + + {:else} + No then is set + {/if} + +
+{/if} + diff --git a/src/UI/Studio/Region.svelte b/src/UI/Studio/Region.svelte index f9c324568..ffbc234ce 100644 --- a/src/UI/Studio/Region.svelte +++ b/src/UI/Studio/Region.svelte @@ -2,28 +2,32 @@ * A 'region' is a collection of properties that can be edited which are somewhat related. * They will typically be a subset of some properties */ -import type {ConfigMeta} from "./configMeta"; +import type { ConfigMeta } from "./configMeta"; import EditLayerState from "./EditLayerState"; import SchemaBasedInput from "./SchemaBasedInput.svelte"; -export let state: EditLayerState -export let configs: ConfigMeta[] -export let title: string +export let state: EditLayerState; +export let configs: ConfigMeta[]; +export let title: string | undefined = undefined; + +export let path: (string | number)[] = []; {#if title} +

{title}

-
- - {#each configs as config} - - {/each} +
+ + {#each configs as config} + + {/each}
+
{:else} -
- {#each configs as config} - - {/each} -
+
+ {#each configs as config} + + {/each} +
{/if} diff --git a/src/UI/Studio/RegisteredTagInput.svelte b/src/UI/Studio/RegisteredTagInput.svelte index c95d48c7e..0764ef3d0 100644 --- a/src/UI/Studio/RegisteredTagInput.svelte +++ b/src/UI/Studio/RegisteredTagInput.svelte @@ -2,7 +2,7 @@ import EditLayerState from "./EditLayerState"; import {UIEventSource} from "../../Logic/UIEventSource"; import type {TagConfigJson} from "../../Models/ThemeConfig/Json/TagConfigJson"; - import TagInput from "./TagInput/TagInput.svelte"; + import FullTagInput from "./TagInput/FullTagInput.svelte"; import type {ConfigMeta} from "./configMeta"; import {PencilAltIcon} from "@rgossiaux/svelte-heroicons/solid"; import { onDestroy } from "svelte"; @@ -40,13 +40,14 @@

{schema.hints.question ?? "What tags should be applied?"}

{schema.description} - +
+
RegisteredTagInput based on schema: {JSON.stringify(schema)}
{:else}
diff --git a/src/UI/Studio/SchemaBasedArray.svelte b/src/UI/Studio/SchemaBasedArray.svelte index 782eedd7d..b5d5bfe3f 100644 --- a/src/UI/Studio/SchemaBasedArray.svelte +++ b/src/UI/Studio/SchemaBasedArray.svelte @@ -10,16 +10,18 @@ export let state: EditLayerState; export let schema: ConfigMeta; + let title = schema.path.at(-1); let singular = title; - if (title.endsWith("s")) { + if (title?.endsWith("s")) { singular = title.slice(0, title.length - 1); } let article = "a"; - if (singular.match(/^[aeoui]/)) { + if (singular?.match(/^[aeoui]/)) { article = "an"; } export let path: (string | number)[] = []; + const isTagRenderingBlock = path.length === 1 && path[0] === "tagRenderings"; const subparts = state.getSchemaStartingWith(schema.path); @@ -39,8 +41,11 @@ let createdItems = values.data.length; - function createItem() { + function createItem(valueToSet?: any) { values.data.push(createdItems); + if (valueToSet) { + state.setValueAt([...path, createdItems], valueToSet); + } createdItems++; values.ping(); } @@ -87,16 +92,24 @@ {/each} {:else} {#each $values as value (value)} -
-

{singular} {value}

- -
+ + {#if !isTagRenderingBlock} +
+

{singular} {value}

+ +
+ {/if}
- {#if path.length === 1 && path[0] === "tagRenderings"} - + {#if isTagRenderingBlock} + + + {:else} {#each subparts as subpart} @@ -105,5 +118,11 @@
{/each} {/if} - +
+ + {#if path.length === 1 && path[0] === "tagRenderings"} + + {/if} + +
diff --git a/src/UI/Studio/SchemaBasedField.svelte b/src/UI/Studio/SchemaBasedField.svelte index 47630103c..8df47ed9a 100644 --- a/src/UI/Studio/SchemaBasedField.svelte +++ b/src/UI/Studio/SchemaBasedField.svelte @@ -10,6 +10,7 @@ } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"; import EditLayerState from "./EditLayerState"; import { onDestroy } from "svelte"; + import type { JsonSchemaType } from "./jsonSchema"; export let state: EditLayerState @@ -21,6 +22,9 @@ if(type === "rendered"){ type = "translation" } + if(type.endsWith("[]")){ + type = type.substring(0, type.length - 2) + } const isTranslation =schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" const configJson: QuestionableTagRenderingConfigJson = { @@ -47,7 +51,23 @@ }] } - if (schema.type === "boolean" || (Array.isArray(schema.type) && schema.type.some(t => t["type"] === "boolean"))) { + function mightBeBoolean(type: undefined | JsonSchemaType): boolean { + if(type === undefined){ + return false + } + if(type["type"]){ + type = type["type"] + } + if(type === "boolean"){ + return true + } + if(!Array.isArray(type)){ + return false + } + + return type.some(t => mightBeBoolean(t) ) + } + if (mightBeBoolean(schema.type)) { configJson.mappings = configJson.mappings ?? [] configJson.mappings.push( { @@ -101,7 +121,7 @@ {#if err !== undefined} {err} {:else} -
+
{/if} diff --git a/src/UI/Studio/SchemaBasedInput.svelte b/src/UI/Studio/SchemaBasedInput.svelte index 82d86fa05..3382c71f0 100644 --- a/src/UI/Studio/SchemaBasedInput.svelte +++ b/src/UI/Studio/SchemaBasedInput.svelte @@ -1,31 +1,25 @@ {#if schema.hints.typehint === "tagrendering[]"} - - + + {:else if schema.type === "array"} - -{:else if schema.hints.typehint === "tag"} - + {:else if schema.type === "translation"} - + {:else if schema.hints.types} - + {:else} - + {/if} diff --git a/src/UI/Studio/SchemaBaseMultiType.svelte b/src/UI/Studio/SchemaBasedMultiType.svelte similarity index 98% rename from src/UI/Studio/SchemaBaseMultiType.svelte rename to src/UI/Studio/SchemaBasedMultiType.svelte index 8d5f2f187..c4bf47ad4 100644 --- a/src/UI/Studio/SchemaBaseMultiType.svelte +++ b/src/UI/Studio/SchemaBasedMultiType.svelte @@ -26,7 +26,6 @@ const hasBooleanOption = (schema.type)?.findIndex(t => t["type"] === "boolean"); const types = schema.hints.types.split(";"); if (hasBooleanOption >= 0) { - console.log(path.join("."), ": types are", types, ", boolean index is", hasBooleanOption); types.splice(hasBooleanOption); } diff --git a/src/UI/Studio/TagExpression.svelte b/src/UI/Studio/TagExpression.svelte index 3c74bdaa6..9739f62e3 100644 --- a/src/UI/Studio/TagExpression.svelte +++ b/src/UI/Studio/TagExpression.svelte @@ -2,118 +2,121 @@ * Allows to create `and` and `or` expressions graphically */ -import {UIEventSource} from "../../Logic/UIEventSource"; -import type {TagConfigJson} from "../../Models/ThemeConfig/Json/TagConfigJson"; +import { UIEventSource } from "../../Logic/UIEventSource"; +import type { TagConfigJson } from "../../Models/ThemeConfig/Json/TagConfigJson"; import BasicTagInput from "./TagInput/BasicTagInput.svelte"; -import TagInput from "./TagInput/TagInput.svelte"; -import {TrashIcon} from "@babeard/svelte-heroicons/mini"; +import FullTagInput from "./TagInput/FullTagInput.svelte"; +import { TrashIcon } from "@babeard/svelte-heroicons/mini"; -export let tag: UIEventSource -let mode: "and" | "or" = "and" +export let tag: UIEventSource; +let mode: "and" | "or" = "and"; -let basicTags: UIEventSource[]> = new UIEventSource([]) +let basicTags: UIEventSource[]> = new UIEventSource([]); /** * Sub-expressions */ -let expressions: UIEventSource[]> = new UIEventSource([]) -export let uploadableOnly: boolean -export let overpassSupportNeeded: boolean +let expressions: UIEventSource[]> = new UIEventSource([]); + +export let uploadableOnly: boolean; +export let overpassSupportNeeded: boolean; + +export let silent: boolean; function update(_) { - let config: TagConfigJson = {} + let config: TagConfigJson = {}; if (!mode) { - return + return; } - const tags = [] + const tags = []; - const subpartSources = ([]>basicTags.data).concat(expressions.data) + const subpartSources = ([]>basicTags.data).concat(expressions.data); for (const src of subpartSources) { - const t = src.data + const t = src.data; if (!t) { // We indicate upstream that this value is invalid - tag.setData(undefined) - return + tag.setData(undefined); + return; } - tags.push(t) + tags.push(t); } if (tags.length === 1) { - tag.setData(tags[0]) + tag.setData(tags[0]); } else { - config[mode] = tags - tag.setData(config) + config[mode] = tags; + tag.setData(config); } } function addBasicTag(value?: string) { - const src = new UIEventSource(value) + const src = new UIEventSource(value); basicTags.data.push(src); - basicTags.ping() - src.addCallbackAndRunD(_ => update(_)) + basicTags.ping(); + src.addCallbackAndRunD(_ => update(_)); } function removeTag(basicTag: UIEventSource) { - const index = basicTags.data.indexOf(basicTag) - console.log("Removing", index, basicTag) + const index = basicTags.data.indexOf(basicTag); + console.log("Removing", index, basicTag); if (index >= 0) { - basicTag.setData(undefined) - basicTags.data.splice(index, 1) - basicTags.ping() + basicTag.setData(undefined); + basicTags.data.splice(index, 1); + basicTags.ping(); } } function removeExpression(expr: UIEventSource) { - const index = expressions.data.indexOf(expr) + const index = expressions.data.indexOf(expr); if (index >= 0) { - expr.setData(undefined) - expressions.data.splice(index, 1) - expressions.ping() + expr.setData(undefined); + expressions.data.splice(index, 1); + expressions.ping(); } } function addExpression(expr?: TagConfigJson) { - const src = new UIEventSource(expr) + const src = new UIEventSource(expr); expressions.data.push(src); - expressions.ping() - src.addCallbackAndRunD(_ => update(_)) + expressions.ping(); + src.addCallbackAndRunD(_ => update(_)); } -$: update(mode) -expressions.addCallback(_ => update(_)) -basicTags.addCallback(_ => update(_)) +$: update(mode); +expressions.addCallback(_ => update(_)); +basicTags.addCallback(_ => update(_)); -let initialTag: TagConfigJson = tag.data +let initialTag: TagConfigJson = tag.data; function initWith(initialTag: TagConfigJson) { if (typeof initialTag === "string") { - addBasicTag(initialTag) - return + addBasicTag(initialTag); + return; } - mode = <"or" | "and">Object.keys(initialTag)[0] - const subExprs = (initialTag[mode]) - if (subExprs.length == 0) { - return + mode = <"or" | "and">Object.keys(initialTag)[0]; + const subExprs = (initialTag[mode]); + if (!subExprs || subExprs.length == 0) { + return; } if (subExprs.length == 1) { - initWith(subExprs[0]) + initWith(subExprs[0]); return; } for (const subExpr of subExprs) { if (typeof subExpr === "string") { - addBasicTag(subExpr) + addBasicTag(subExpr); } else { - addExpression(subExpr) + addExpression(subExpr); } } } if (!initialTag) { - addBasicTag() + addBasicTag(); } else { - initWith(initialTag) + initWith(initialTag); } @@ -122,37 +125,44 @@ if (!initialTag) {
- + - {/if} - + + {/if} +
{#each $basicTags as basicTag (basicTag)}
- - + + {#if $basicTags.length + $expressions.length > 1} + + {/if}
{/each} {#each $expressions as expression} - - - + {/each}
- - - + {#if !uploadableOnly} + + + {/if} +
diff --git a/src/UI/Studio/TagInfoStats.svelte b/src/UI/Studio/TagInfoStats.svelte index 06da9f4c1..e3d403a6a 100644 --- a/src/UI/Studio/TagInfoStats.svelte +++ b/src/UI/Studio/TagInfoStats.svelte @@ -2,58 +2,61 @@ * A small component showing statistics from tagInfo. * Will show this in an 'alert' if very little (<250) tags are known */ -import {TagUtils} from "../../Logic/Tags/TagUtils"; -import {Store, UIEventSource} from "../../Logic/UIEventSource"; -import type {TagInfoStats} from "../../Logic/Web/TagInfo"; +import { TagUtils } from "../../Logic/Tags/TagUtils"; +import { Store, UIEventSource } from "../../Logic/UIEventSource"; +import type { TagInfoStats } from "../../Logic/Web/TagInfo"; import TagInfo from "../../Logic/Web/TagInfo"; -import {twMerge} from "tailwind-merge"; +import { twMerge } from "tailwind-merge"; import Loading from "../Base/Loading.svelte"; -export let tag: UIEventSource -const tagStabilized = tag.stabilized(500) +export let silent = false; +export let tag: UIEventSource; +const tagStabilized = tag.stabilized(500); const tagInfoStats: Store = tagStabilized.bind(tag => { if (!tag) { - return undefined + return undefined; } try { - const t = TagUtils.Tag(tag) - const k = t["key"] - let v = t["value"] + const t = TagUtils.Tag(tag); + const k = t["key"]; + let v = t["value"]; if (typeof v !== "string") { - v = undefined + v = undefined; } if (!k) { - return undefined + return undefined; } - return UIEventSource.FromPromise(TagInfo.global.getStats(k, v)) + return UIEventSource.FromPromise(TagInfo.global.getStats(k, v)); } catch (e) { - return undefined + return undefined; } -}) +}); const tagInfoUrl: Store = tagStabilized.mapD(tag => { try { - const t = TagUtils.Tag(tag) - const k = t["key"] - let v = t["value"] + const t = TagUtils.Tag(tag); + const k = t["key"]; + let v = t["value"]; if (typeof v !== "string") { - v = undefined + v = undefined; } if (!k) { - return undefined + return undefined; } - return TagInfo.global.webUrl(k, v) + return TagInfo.global.webUrl(k, v); } catch (e) { - return undefined + return undefined; } -}) -const total = tagInfoStats.mapD(data => data.data.find(i => i.type === "all").count) +}); +const total = tagInfoStats.mapD(data => data.data.find(i => i.type === "all").count); {#if $tagStabilized !== $tag} - -{:else if $tagInfoStats } + {#if !silent} + + {/if} +{:else if $tagInfoStats && (!silent || $total < 250) } {$total} features on OSM have this tag diff --git a/src/UI/Studio/TagInput/BasicTagInput.svelte b/src/UI/Studio/TagInput/BasicTagInput.svelte index abd251928..bd67d9c63 100644 --- a/src/UI/Studio/TagInput/BasicTagInput.svelte +++ b/src/UI/Studio/TagInput/BasicTagInput.svelte @@ -6,11 +6,14 @@ import Tr from "../../Base/Tr.svelte"; import {TagUtils} from "../../../Logic/Tags/TagUtils"; import TagInfoStats from "../TagInfoStats.svelte"; + import { Translation } from "../../i18n/Translation"; export let tag: UIEventSource = new UIEventSource(undefined) export let uploadableOnly: boolean export let overpassSupportNeeded: boolean + export let silent : boolean = false + let feedbackGlobal = tag.map(tag => { if (!tag) { return undefined @@ -24,11 +27,11 @@ }) - let feedbackKey = new UIEventSource(undefined) + let feedbackKey = new UIEventSource(undefined) let keyValue = new UIEventSource(undefined) - let feedbackValue = new UIEventSource(undefined) + let feedbackValue = new UIEventSource(undefined) /** * The value of the tag. The name is a bit confusing */ @@ -79,7 +82,11 @@ function setTag(_) { const k = keyValue.data - const v = valueValue.data + const v = valueValue.data ?? "" + if(k === undefined || k === ""){ + tag.setData(undefined) + return + } const t = k + mode + v try { TagUtils.Tag(t) @@ -116,5 +123,5 @@ {:else if $feedbackGlobal} {/if} - +
diff --git a/src/UI/Studio/TagInput/FullTagInput.svelte b/src/UI/Studio/TagInput/FullTagInput.svelte new file mode 100644 index 000000000..a0c2bff11 --- /dev/null +++ b/src/UI/Studio/TagInput/FullTagInput.svelte @@ -0,0 +1,19 @@ + + +
+ + + +
diff --git a/src/UI/Studio/TagInput/TagInput.svelte b/src/UI/Studio/TagInput/TagInput.svelte deleted file mode 100644 index e4ecc5df8..000000000 --- a/src/UI/Studio/TagInput/TagInput.svelte +++ /dev/null @@ -1,18 +0,0 @@ - - -
- - - -
diff --git a/src/UI/Studio/TagRenderingFreeformInput.svelte b/src/UI/Studio/TagRenderingFreeformInput.svelte new file mode 100644 index 000000000..fa5727ac9 --- /dev/null +++ b/src/UI/Studio/TagRenderingFreeformInput.svelte @@ -0,0 +1,14 @@ + + +XYZ diff --git a/src/UI/Studio/TagRenderingInput.svelte b/src/UI/Studio/TagRenderingInput.svelte index fcbe57f0f..3be0c7cea 100644 --- a/src/UI/Studio/TagRenderingInput.svelte +++ b/src/UI/Studio/TagRenderingInput.svelte @@ -12,6 +12,11 @@ import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"; import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte"; import { UIEventSource } from "../../Logic/UIEventSource"; import * as questions from "../../assets/generated/layers/questions.json"; +import MappingInput from "./MappingInput.svelte"; +import { TrashIcon } from "@rgossiaux/svelte-heroicons/outline"; +import questionableTagRenderingSchemaRaw from "../../assets/schemas/questionabletagrenderingconfigmeta.json"; +import SchemaBasedField from "./SchemaBasedField.svelte"; +import Region from "./Region.svelte"; export let state: EditLayerState; export let schema: ConfigMeta; @@ -19,11 +24,11 @@ export let path: (string | number)[]; let value = state.getCurrentValueFor(path); -let mappings: MappingConfigJson[] = []; +let mappingsBuiltin: MappingConfigJson[] = []; for (const tr of questions.tagRenderings) { let description = tr["description"] ?? tr["question"] ?? "No description available"; description = description["en"] ?? description; - mappings.push({ + mappingsBuiltin.push({ if: "value=" + tr["id"], then: { "en": "Builtin " + tr["id"] + "
" + description + "
" @@ -34,28 +39,77 @@ for (const tr of questions.tagRenderings) { const configBuiltin = new TagRenderingConfig({ question: "Which builtin element should be shown?", - mappings + mappings: mappingsBuiltin }); -const configOverride = { - render: "This is a builtin question which changes some properties. Editing those is not possible within MapComplete Studio" -}; - const tags = new UIEventSource({ value }); tags.addCallbackAndRunD(tgs => { state.setValueAt(path, tgs["value"]); }); +let mappings: UIEventSource = state.getStoreFor([...path, "mappings"]); + +const topLevelItems: Record = {}; +for (const item of questionableTagRenderingSchemaRaw) { + if (item.path.length === 1) { + topLevelItems[item.path[0]] = item; + } +} + +function initMappings() { + if (mappings.data === undefined) { + mappings.setData([]); + } +} + +const freeformSchema = questionableTagRenderingSchemaRaw.filter(schema => schema.path.length >= 1 && schema.path[0] === "freeform"); +console.log("FreeformSchema:", freeformSchema) {#if typeof value === "string"} - -{:else} -
- TR{JSON.stringify(state.getCurrentValueFor(path))} +
+ +
+{:else} +
+
+ +
+ + + + + {#each ($mappings ?? []) as mapping, i (mapping)} +
+ + + +
+ {/each} + + + + + + + + + +
+ {/if} diff --git a/src/UI/StylesheetTestGui.svelte b/src/UI/StylesheetTestGui.svelte index 54308382c..b83d4477a 100644 --- a/src/UI/StylesheetTestGui.svelte +++ b/src/UI/StylesheetTestGui.svelte @@ -38,6 +38,11 @@ Main action (disabled) + +
+