forked from MapComplete/MapComplete
Studo: WIP
This commit is contained in:
parent
7ebb3d721c
commit
338599454c
30 changed files with 42794 additions and 749 deletions
|
@ -36,7 +36,7 @@
|
|||
"properties": {
|
||||
"osmTags": {
|
||||
"$ref": "#/definitions/TagConfigJson",
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\n\n Every source must set which tags have to be present in order to load the given layer."
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\nEvery source must set which tags have to be present in order to load the given layer."
|
||||
},
|
||||
"maxCacheAge": {
|
||||
"description": "question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?\nThe maximum amount of seconds that a tile is allowed to linger in the cache\n\ntype: nat\ndefault: 30 days",
|
||||
|
@ -167,28 +167,21 @@
|
|||
]
|
||||
},
|
||||
"mapRendering": {
|
||||
"description": "Visualisation of the items on the map\n\ngroup: maprendering",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
]
|
||||
"description": "Visualisation of the items on the map\nSet 'null' explicitly if you do not want a maprendering\ngroup: maprendering",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"passAllFeatures": {
|
||||
"description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directions on cameras\niftrue: Make the features from this layer also available to the other layer; might result in this object being rendered by multiple layers\niffalse: normal behaviour: don't pass features allong\nquestion: should this layer pass features to the next layers?\ngroup: expert",
|
||||
|
@ -352,7 +345,7 @@
|
|||
]
|
||||
},
|
||||
"deletion": {
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: Use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DeleteConfigJson"
|
||||
|
@ -404,7 +397,6 @@
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"mapRendering",
|
||||
"source"
|
||||
],
|
||||
"definitions": {
|
||||
|
@ -1179,7 +1171,7 @@
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1214,7 +1206,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
@ -1375,7 +1367,7 @@
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1410,7 +1402,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
|
|
@ -36,7 +36,7 @@ export default {
|
|||
"properties": {
|
||||
"osmTags": {
|
||||
"$ref": "#/definitions/TagConfigJson",
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\n\n Every source must set which tags have to be present in order to load the given layer."
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\nEvery source must set which tags have to be present in order to load the given layer."
|
||||
},
|
||||
"maxCacheAge": {
|
||||
"description": "question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?\nThe maximum amount of seconds that a tile is allowed to linger in the cache\n\ntype: nat\ndefault: 30 days",
|
||||
|
@ -167,28 +167,21 @@ export default {
|
|||
]
|
||||
},
|
||||
"mapRendering": {
|
||||
"description": "Visualisation of the items on the map\n\ngroup: maprendering",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
]
|
||||
"description": "Visualisation of the items on the map\nSet 'null' explicitly if you do not want a maprendering\ngroup: maprendering",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"passAllFeatures": {
|
||||
"description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directions on cameras\niftrue: Make the features from this layer also available to the other layer; might result in this object being rendered by multiple layers\niffalse: normal behaviour: don't pass features allong\nquestion: should this layer pass features to the next layers?\ngroup: expert",
|
||||
|
@ -352,7 +345,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"deletion": {
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: Use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DeleteConfigJson"
|
||||
|
@ -404,7 +397,6 @@ export default {
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"mapRendering",
|
||||
"source"
|
||||
],
|
||||
"definitions": {
|
||||
|
@ -1167,7 +1159,7 @@ export default {
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1202,7 +1194,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
@ -1362,7 +1354,7 @@ export default {
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1397,7 +1389,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
|
|
@ -1076,7 +1076,7 @@
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1111,7 +1111,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
@ -1272,7 +1272,7 @@
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1307,7 +1307,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
@ -1767,7 +1767,7 @@
|
|||
"properties": {
|
||||
"osmTags": {
|
||||
"$ref": "#/definitions/TagConfigJson",
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\n\n Every source must set which tags have to be present in order to load the given layer."
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\nEvery source must set which tags have to be present in order to load the given layer."
|
||||
},
|
||||
"maxCacheAge": {
|
||||
"description": "question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?\nThe maximum amount of seconds that a tile is allowed to linger in the cache\n\ntype: nat\ndefault: 30 days",
|
||||
|
@ -1898,28 +1898,21 @@
|
|||
]
|
||||
},
|
||||
"mapRendering": {
|
||||
"description": "Visualisation of the items on the map\n\ngroup: maprendering",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
]
|
||||
"description": "Visualisation of the items on the map\nSet 'null' explicitly if you do not want a maprendering\ngroup: maprendering",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"passAllFeatures": {
|
||||
"description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directions on cameras\niftrue: Make the features from this layer also available to the other layer; might result in this object being rendered by multiple layers\niffalse: normal behaviour: don't pass features allong\nquestion: should this layer pass features to the next layers?\ngroup: expert",
|
||||
|
@ -2083,7 +2076,7 @@
|
|||
]
|
||||
},
|
||||
"deletion": {
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: Use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DeleteConfigJson"
|
||||
|
@ -2135,7 +2128,6 @@
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"mapRendering",
|
||||
"source"
|
||||
],
|
||||
"additionalProperties": false
|
||||
|
@ -2177,7 +2169,7 @@
|
|||
"properties": {
|
||||
"osmTags": {
|
||||
"$ref": "#/definitions/TagConfigJson",
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\n\n Every source must set which tags have to be present in order to load the given layer."
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\nEvery source must set which tags have to be present in order to load the given layer."
|
||||
},
|
||||
"maxCacheAge": {
|
||||
"description": "question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?\nThe maximum amount of seconds that a tile is allowed to linger in the cache\n\ntype: nat\ndefault: 30 days",
|
||||
|
@ -2308,28 +2300,21 @@
|
|||
]
|
||||
},
|
||||
"mapRendering": {
|
||||
"description": "Visualisation of the items on the map\n\ngroup: maprendering",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
]
|
||||
"description": "Visualisation of the items on the map\nSet 'null' explicitly if you do not want a maprendering\ngroup: maprendering",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"passAllFeatures": {
|
||||
"description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directions on cameras\niftrue: Make the features from this layer also available to the other layer; might result in this object being rendered by multiple layers\niffalse: normal behaviour: don't pass features allong\nquestion: should this layer pass features to the next layers?\ngroup: expert",
|
||||
|
@ -2493,7 +2478,7 @@
|
|||
]
|
||||
},
|
||||
"deletion": {
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: Use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DeleteConfigJson"
|
||||
|
@ -2579,4 +2564,4 @@
|
|||
},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
|
@ -1064,7 +1064,7 @@ export default {
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1099,7 +1099,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
@ -1259,7 +1259,7 @@ export default {
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -1294,7 +1294,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
@ -1746,7 +1746,7 @@ export default {
|
|||
"properties": {
|
||||
"osmTags": {
|
||||
"$ref": "#/definitions/TagConfigJson",
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\n\n Every source must set which tags have to be present in order to load the given layer."
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\nEvery source must set which tags have to be present in order to load the given layer."
|
||||
},
|
||||
"maxCacheAge": {
|
||||
"description": "question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?\nThe maximum amount of seconds that a tile is allowed to linger in the cache\n\ntype: nat\ndefault: 30 days",
|
||||
|
@ -1877,28 +1877,21 @@ export default {
|
|||
]
|
||||
},
|
||||
"mapRendering": {
|
||||
"description": "Visualisation of the items on the map\n\ngroup: maprendering",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
]
|
||||
"description": "Visualisation of the items on the map\nSet 'null' explicitly if you do not want a maprendering\ngroup: maprendering",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"passAllFeatures": {
|
||||
"description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directions on cameras\niftrue: Make the features from this layer also available to the other layer; might result in this object being rendered by multiple layers\niffalse: normal behaviour: don't pass features allong\nquestion: should this layer pass features to the next layers?\ngroup: expert",
|
||||
|
@ -2062,7 +2055,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"deletion": {
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: Use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DeleteConfigJson"
|
||||
|
@ -2114,7 +2107,6 @@ export default {
|
|||
},
|
||||
"required": [
|
||||
"id",
|
||||
"mapRendering",
|
||||
"source"
|
||||
]
|
||||
},
|
||||
|
@ -2155,7 +2147,7 @@ export default {
|
|||
"properties": {
|
||||
"osmTags": {
|
||||
"$ref": "#/definitions/TagConfigJson",
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\n\n Every source must set which tags have to be present in order to load the given layer."
|
||||
"description": "question: Which tags must be present on the feature to show it in this layer?\nEvery source must set which tags have to be present in order to load the given layer."
|
||||
},
|
||||
"maxCacheAge": {
|
||||
"description": "question: How long (in seconds) is the data allowed to remain cached until it must be refreshed?\nThe maximum amount of seconds that a tile is allowed to linger in the cache\n\ntype: nat\ndefault: 30 days",
|
||||
|
@ -2286,28 +2278,21 @@ export default {
|
|||
]
|
||||
},
|
||||
"mapRendering": {
|
||||
"description": "Visualisation of the items on the map\n\ngroup: maprendering",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
]
|
||||
"description": "Visualisation of the items on the map\nSet 'null' explicitly if you do not want a maprendering\ngroup: maprendering",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/default_4"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default_5"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/default<default|default|default[]|default[]>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"passAllFeatures": {
|
||||
"description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directions on cameras\niftrue: Make the features from this layer also available to the other layer; might result in this object being rendered by multiple layers\niffalse: normal behaviour: don't pass features allong\nquestion: should this layer pass features to the next layers?\ngroup: expert",
|
||||
|
@ -2471,7 +2456,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"deletion": {
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n### The delete dialog\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted fromOSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n##### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.\n\ngroup: editing\ntypes: Use an advanced delete configuration ; boolean\niftrue: Allow deletion\niffalse: Do not allow deletion",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DeleteConfigJson"
|
||||
|
@ -2554,4 +2539,4 @@ export default {
|
|||
}
|
||||
},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -79,7 +79,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
|
|
@ -44,7 +44,7 @@ export default {
|
|||
}
|
||||
},
|
||||
"inline": {
|
||||
"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",
|
||||
"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: show the freeform input field full-width\niftrue: show the freeform input field as a small field within the question",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": {
|
||||
|
@ -79,7 +79,7 @@ export default {
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
|
|
@ -200,9 +200,6 @@ function addMetafields(fieldnames: string[], fullSchema: JsonSchema): ConfigMeta
|
|||
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
|
||||
let description = schemePart.description
|
||||
|
||||
|
@ -291,10 +288,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
|
||||
|
@ -347,9 +344,9 @@ function main() {
|
|||
})
|
||||
}
|
||||
const errs: string[] = []
|
||||
// errs = extractMeta("LayerConfigJson", "layerconfigmeta", allDefinitions)
|
||||
// errs.push(...extractMeta("LayoutConfigJson", "layoutconfigmeta", allDefinitions))
|
||||
// errs.push(...extractMeta("TagRenderingConfigJson", "tagrenderingconfigmeta", allDefinitions))
|
||||
errs.push(...extractMeta("LayerConfigJson", "layerconfigmeta", allDefinitions))
|
||||
// errs.push(...extractMeta("LayoutConfigJson", "layoutconfigmeta", allDefinitions))
|
||||
errs.push(...extractMeta("TagRenderingConfigJson", "tagrenderingconfigmeta", allDefinitions))
|
||||
errs.push(
|
||||
...extractMeta(
|
||||
"QuestionableTagRenderingConfigJson",
|
||||
|
|
99
scripts/studioServer.ts
Normal file
99
scripts/studioServer.ts
Normal file
|
@ -0,0 +1,99 @@
|
|||
import * as fs from "node:fs"
|
||||
import * as http from "node:http"
|
||||
import * as path from "node:path"
|
||||
import { ReadStream } from "fs"
|
||||
import ScriptUtils from "./ScriptUtils"
|
||||
|
||||
const PORT = 1235
|
||||
const CORS = "http://localhost:1234,https://mapcomplete.org,https://dev.mapcomplete.org"
|
||||
|
||||
const MIME_TYPES = {
|
||||
default: "application/octet-stream",
|
||||
html: "text/html; charset=UTF-8",
|
||||
js: "application/javascript",
|
||||
css: "text/css",
|
||||
png: "image/png",
|
||||
jpg: "image/jpg",
|
||||
gif: "image/gif",
|
||||
ico: "image/x-icon",
|
||||
svg: "image/svg+xml",
|
||||
json: "application/json",
|
||||
}
|
||||
|
||||
const STATIC_PATH = path.join(process.cwd(), "./assets")
|
||||
|
||||
const toBool = [() => true, () => false]
|
||||
|
||||
const prepareFile: (url) => Promise<{ ext: string; found: boolean; stream: ReadStream }> = async (
|
||||
url
|
||||
) => {
|
||||
const paths = [STATIC_PATH, url]
|
||||
if (url.endsWith("/")) paths.push("index.html")
|
||||
const filePath = path.join(...paths)
|
||||
const pathTraversal = !filePath.startsWith(STATIC_PATH)
|
||||
const exists = await fs.promises.access(filePath).then(...toBool)
|
||||
const found = !pathTraversal && exists
|
||||
const streamPath = found ? filePath : STATIC_PATH + "/404.html"
|
||||
const ext = path.extname(streamPath).substring(1).toLowerCase()
|
||||
const stream = fs.createReadStream(streamPath)
|
||||
return { found, ext, stream }
|
||||
}
|
||||
|
||||
http.createServer(async (req, res) => {
|
||||
try {
|
||||
console.log(req.method + " " + req.url, "from:", req.headers.origin)
|
||||
res.setHeader(
|
||||
"Access-Control-Allow-Headers",
|
||||
"Origin, X-Requested-With, Content-Type, Accept"
|
||||
)
|
||||
res.setHeader("Access-Control-Allow-Origin", req.headers.origin ?? "*")
|
||||
if (req.method === "OPTIONS") {
|
||||
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, UPDATE")
|
||||
res.writeHead(204, { "Content-Type": MIME_TYPES.html })
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
if (req.method === "POST" || req.method === "UPDATE") {
|
||||
const paths = req.url.split("/")
|
||||
console.log("Got an update to:", paths.join("/"))
|
||||
for (let i = 1; i < paths.length; i++) {
|
||||
const p = paths.slice(0, i)
|
||||
const dir = STATIC_PATH + p.join("/")
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir)
|
||||
}
|
||||
}
|
||||
req.pipe(fs.createWriteStream(STATIC_PATH + paths.join("/") + ".new.json"))
|
||||
res.writeHead(200, { "Content-Type": MIME_TYPES.html })
|
||||
res.write("<html><body>OK</body></html>", "utf8")
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
if (req.url.endsWith("/overview")) {
|
||||
console.log("Giving overview")
|
||||
const allFiles = ScriptUtils.readDirRecSync(STATIC_PATH)
|
||||
.filter((p) => p.endsWith(".json") && !p.endsWith("license_info.json"))
|
||||
.map((p) => p.substring(STATIC_PATH.length + 1))
|
||||
res.writeHead(200, { "Content-Type": MIME_TYPES.json })
|
||||
res.write(JSON.stringify({ allFiles }))
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
if (!fs.existsSync(STATIC_PATH + req.url)) {
|
||||
res.writeHead(404, { "Content-Type": MIME_TYPES.html })
|
||||
res.write("<html><body><p>Not found...</p></body></html>")
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
const file = await prepareFile(req.url)
|
||||
const statusCode = file.found ? 200 : 404
|
||||
const mimeType = MIME_TYPES[file.ext] || MIME_TYPES.default
|
||||
res.writeHead(statusCode, { "Content-Type": mimeType })
|
||||
file.stream.pipe(res)
|
||||
res.end()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}).listen(PORT)
|
||||
|
||||
console.log(`Server running at http://127.0.0.1:${PORT}/`)
|
|
@ -149,7 +149,7 @@ class ExpandTagRendering extends Conversion<
|
|||
this._options = options
|
||||
this._tagRenderingsByLabel = new Map<string, TagRenderingConfigJson[]>()
|
||||
for (const trconfig of state.tagRenderings?.values() ?? []) {
|
||||
for (const label of trconfig.labels ?? []) {
|
||||
for (const label of trconfig["labels"] ?? []) {
|
||||
let withLabel = this._tagRenderingsByLabel.get(label)
|
||||
if (withLabel === undefined) {
|
||||
withLabel = []
|
||||
|
@ -193,7 +193,7 @@ class ExpandTagRendering extends Conversion<
|
|||
for (let foundTr of indirect) {
|
||||
foundTr = Utils.Clone<any>(foundTr)
|
||||
Utils.Merge(tagRenderingConfigJson["override"] ?? {}, foundTr)
|
||||
foundTr.id = tagRenderingConfigJson.id ?? foundTr.id
|
||||
foundTr["id"] = tagRenderingConfigJson["id"] ?? foundTr["id"]
|
||||
result.push(foundTr)
|
||||
}
|
||||
} else {
|
||||
|
@ -239,9 +239,9 @@ class ExpandTagRendering extends Conversion<
|
|||
matchingTrs = layerTrs
|
||||
} else if (id.startsWith("*")) {
|
||||
const id_ = id.substring(1)
|
||||
matchingTrs = layerTrs.filter((tr) => tr.labels?.indexOf(id_) >= 0)
|
||||
matchingTrs = layerTrs.filter((tr) => tr["labels"]?.indexOf(id_) >= 0)
|
||||
} else {
|
||||
matchingTrs = layerTrs.filter((tr) => tr.id === id || tr.labels?.indexOf(id) >= 0)
|
||||
matchingTrs = layerTrs.filter((tr) => tr["id"] === id || tr["labels"]?.indexOf(id) >= 0)
|
||||
}
|
||||
|
||||
const contextWriter = new AddContextToTranslations<TagRenderingConfigJson>("layers:")
|
||||
|
@ -489,7 +489,15 @@ class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
|
|||
}
|
||||
}
|
||||
json = JSON.parse(JSON.stringify(json))
|
||||
json.freeform.inline ??= true
|
||||
if (typeof json.freeform === "string") {
|
||||
errors.push("At " + context + ": 'freeform' is a string, but should be an object")
|
||||
return { result: json, errors }
|
||||
}
|
||||
try {
|
||||
json.freeform.inline ??= true
|
||||
} catch (e) {
|
||||
errors.push("At " + context + ": " + e.message)
|
||||
}
|
||||
return { result: json, errors }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,8 +64,7 @@ export interface LayerConfigJson {
|
|||
| {
|
||||
/**
|
||||
* question: Which tags must be present on the feature to show it in this layer?
|
||||
*
|
||||
* Every source must set which tags have to be present in order to load the given layer.
|
||||
* Every source must set which tags have to be present in order to load the given layer.
|
||||
*/
|
||||
osmTags: TagConfigJson
|
||||
/**
|
||||
|
@ -238,21 +237,19 @@ export interface LayerConfigJson {
|
|||
|
||||
/**
|
||||
* Visualisation of the items on the map
|
||||
*
|
||||
* Set 'null' explicitly if you do not want a maprendering
|
||||
* group: maprendering
|
||||
*/
|
||||
mapRendering:
|
||||
| null
|
||||
| (
|
||||
| PointRenderingConfigJson
|
||||
mapRendering?: (
|
||||
| PointRenderingConfigJson
|
||||
| LineRenderingConfigJson
|
||||
| RewritableConfigJson<
|
||||
| LineRenderingConfigJson
|
||||
| RewritableConfigJson<
|
||||
| LineRenderingConfigJson
|
||||
| PointRenderingConfigJson
|
||||
| LineRenderingConfigJson[]
|
||||
| PointRenderingConfigJson[]
|
||||
>
|
||||
)[]
|
||||
| PointRenderingConfigJson
|
||||
| LineRenderingConfigJson[]
|
||||
| PointRenderingConfigJson[]
|
||||
>
|
||||
)[]
|
||||
|
||||
/**
|
||||
* If set, this layer will pass all the features it receives onto the next layer.
|
||||
|
@ -467,7 +464,7 @@ export interface LayerConfigJson {
|
|||
* A no-delete option is offered as 'reason to delete it', but secretly retags.
|
||||
*
|
||||
* group: editing
|
||||
* types: use an advanced delete configuration ; boolean
|
||||
* types: Use an advanced delete configuration ; boolean
|
||||
* iftrue: Allow deletion
|
||||
* iffalse: Do not allow deletion
|
||||
*
|
||||
|
|
|
@ -260,7 +260,7 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
|
|||
questionHint?: string | Translatable
|
||||
|
||||
/**
|
||||
* A list of labels. These are strings that are used for various purposes, e.g. to filter them away
|
||||
* A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer
|
||||
*/
|
||||
labels?: string[]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import LanguageUtils from "../../../Utils/LanguageUtils";
|
||||
import { onDestroy } from "svelte";
|
||||
import { createEventDispatcher, onDestroy } from "svelte";
|
||||
import ValidatedInput from "../ValidatedInput.svelte";
|
||||
|
||||
export let value: UIEventSource<string> = new UIEventSource<string>("");
|
||||
|
@ -18,6 +18,7 @@
|
|||
const allLanguages: string[] = LanguageUtils.usedLanguagesSorted;
|
||||
let currentLang = new UIEventSource("en");
|
||||
const currentVal = new UIEventSource<string>("");
|
||||
let dispatch = createEventDispatcher<{ submit }>()
|
||||
|
||||
function update() {
|
||||
const v = currentVal.data;
|
||||
|
@ -49,5 +50,5 @@
|
|||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
<ValidatedInput type="string" value={currentVal} />
|
||||
<ValidatedInput type="string" value={currentVal} on:submit={() => dispatch("submit")} />
|
||||
</div>
|
||||
|
|
|
@ -4,30 +4,59 @@
|
|||
* Note that all values are stringified
|
||||
*/
|
||||
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import type { ValidatorType } from "./Validators"
|
||||
import InputHelpers from "./InputHelpers"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import type { Feature } from "geojson"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import { VariableUiElement } from "../Base/VariableUIElement"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import type { ValidatorType } from "./Validators";
|
||||
import InputHelpers from "./InputHelpers";
|
||||
import ToSvelte from "../Base/ToSvelte.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import { VariableUiElement } from "../Base/VariableUIElement";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import ImageHelper from "./Helpers/ImageHelper.svelte";
|
||||
import TranslationInput from "./Helpers/TranslationInput.svelte";
|
||||
import TagInput from "./Helpers/TagInput.svelte";
|
||||
import SimpleTagInput from "./Helpers/SimpleTagInput.svelte";
|
||||
import DirectionInput from "./Helpers/DirectionInput.svelte";
|
||||
import DateInput from "./Helpers/DateInput.svelte";
|
||||
import ColorInput from "./Helpers/ColorInput.svelte";
|
||||
|
||||
export let type: ValidatorType
|
||||
export let value: UIEventSource<string>
|
||||
export let type: ValidatorType;
|
||||
export let value: UIEventSource<string>;
|
||||
|
||||
export let feature: Feature
|
||||
export let args: (string | number | boolean)[] = undefined
|
||||
export let feature: Feature;
|
||||
export let args: (string | number | boolean)[] = undefined;
|
||||
|
||||
let properties = { feature, args: args ?? [] }
|
||||
let construct = new UIEventSource<(value, extraProperties) => BaseUIElement>(undefined)
|
||||
let properties = { feature, args: args ?? [] };
|
||||
let construct = new UIEventSource<(value, extraProperties) => BaseUIElement>(undefined);
|
||||
$: {
|
||||
construct.setData(InputHelpers.AvailableInputHelpers[type])
|
||||
const helper = InputHelpers.AvailableInputHelpers[type];
|
||||
construct.setData(helper);
|
||||
}
|
||||
let dispatch = createEventDispatcher<{ selected, submit }>();
|
||||
|
||||
</script>
|
||||
|
||||
{#if construct !== undefined}
|
||||
<ToSvelte
|
||||
construct={() =>
|
||||
{#if type === "translation" }
|
||||
<TranslationInput {value} on:submit={() => dispatch("submit")} />
|
||||
{:else if type === "direction"}
|
||||
<DirectionInput {value} mapProperties={InputHelpers.constructMapProperties(properties)} />
|
||||
{:else if type === "date"}
|
||||
<DateInput { value } />
|
||||
{:else if type === "color"}
|
||||
<ColorInput { value } />
|
||||
{:else if type === "image"}
|
||||
<ImageHelper { value } />
|
||||
{:else if type === "tag"}
|
||||
<TagInput { value } />
|
||||
{:else if type === "simple_tag"}
|
||||
<SimpleTagInput { value } />
|
||||
|
||||
{:else if $construct !== undefined}
|
||||
{#if isBaseUIElement}
|
||||
<ToSvelte
|
||||
construct={() =>
|
||||
new VariableUiElement(construct.mapD((construct) => construct(value, properties)))}
|
||||
/>
|
||||
/>
|
||||
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { ValidatorType } from "./Validators"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||
import DirectionInput from "./Helpers/DirectionInput.svelte"
|
||||
|
||||
import { MapProperties } from "../../Models/MapProperties"
|
||||
import DateInput from "./Helpers/DateInput.svelte"
|
||||
import ColorInput from "./Helpers/ColorInput.svelte"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import OpeningHoursInput from "../OpeningHours/OpeningHoursInput"
|
||||
import WikidataSearchBox from "../Wikipedia/WikidataSearchBox"
|
||||
|
@ -13,10 +10,6 @@ import { Utils } from "../../Utils"
|
|||
import Locale from "../i18n/Locale"
|
||||
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 {
|
||||
/**
|
||||
|
@ -39,6 +32,9 @@ export interface InputHelperProperties {
|
|||
}
|
||||
|
||||
export default class InputHelpers {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static readonly AvailableInputHelpers: Readonly<
|
||||
Partial<
|
||||
Record<
|
||||
|
@ -50,30 +46,21 @@ export default class InputHelpers {
|
|||
>
|
||||
>
|
||||
> = {
|
||||
direction: (value, properties) =>
|
||||
new SvelteUIElement(DirectionInput, {
|
||||
value,
|
||||
mapProperties: InputHelpers.constructMapProperties(properties),
|
||||
}),
|
||||
date: (value) => new SvelteUIElement(DateInput, { value }),
|
||||
color: (value) => new SvelteUIElement(ColorInput, { value }),
|
||||
// TODO: remake in svelte,move selection logic to 'inputHelper.svelte'
|
||||
opening_hours: (value) => new OpeningHoursInput(value),
|
||||
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", "simple_tag", "tag"]
|
||||
|
||||
// noinspection JSUnusedLocalSymbols
|
||||
/**
|
||||
* Constructs a mapProperties-object for the given properties.
|
||||
* Assumes that the first helper-args contains the desired zoom-level
|
||||
* @param properties
|
||||
* @private
|
||||
*/
|
||||
private static constructMapProperties(
|
||||
public static constructMapProperties(
|
||||
properties: InputHelperProperties
|
||||
): Partial<MapProperties> {
|
||||
let location = properties?.mapProperties?.location
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
placeholder={_placeholder}></textarea>
|
||||
</form>
|
||||
{:else}
|
||||
<form class="inline-flex" on:submit={() => dispatch("submit")}>
|
||||
<form class="inline-flex" on:submit|preventDefault={() => dispatch("submit")}>
|
||||
<input
|
||||
bind:this={htmlElem}
|
||||
bind:value={$_value}
|
||||
|
|
|
@ -66,5 +66,5 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
<InputHelper args={config.freeform.helperArgs} {feature} type={config.freeform.type} {value} />
|
||||
<InputHelper args={config.freeform.helperArgs} {feature} type={config.freeform.type} {value} on:submit={() => dispatch("submit")} />
|
||||
</div>
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
<script lang="ts">
|
||||
import {ImmutableStore, Store, UIEventSource} from "../../../Logic/UIEventSource"
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||
import Tr from "../../Base/Tr.svelte"
|
||||
import type { Feature } from "geojson"
|
||||
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig"
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
|
||||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
|
||||
import FreeformInput from "./FreeformInput.svelte"
|
||||
import Translations from "../../i18n/Translations.js"
|
||||
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction"
|
||||
import { createEventDispatcher, onDestroy } from "svelte"
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||
import SpecialTranslation from "./SpecialTranslation.svelte"
|
||||
import TagHint from "../TagHint.svelte"
|
||||
import LoginToggle from "../../Base/LoginToggle.svelte"
|
||||
import SubtleButton from "../../Base/SubtleButton.svelte"
|
||||
import Loading from "../../Base/Loading.svelte"
|
||||
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte"
|
||||
import { Translation } from "../../i18n/Translation"
|
||||
import Constants from "../../../Models/Constants"
|
||||
import { Unit } from "../../../Models/Unit"
|
||||
import UserRelatedState from "../../../Logic/State/UserRelatedState"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import { ImmutableStore, UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter";
|
||||
import FreeformInput from "./FreeformInput.svelte";
|
||||
import Translations from "../../i18n/Translations.js";
|
||||
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction";
|
||||
import { createEventDispatcher, onDestroy } from "svelte";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
import SpecialTranslation from "./SpecialTranslation.svelte";
|
||||
import TagHint from "../TagHint.svelte";
|
||||
import LoginToggle from "../../Base/LoginToggle.svelte";
|
||||
import SubtleButton from "../../Base/SubtleButton.svelte";
|
||||
import Loading from "../../Base/Loading.svelte";
|
||||
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import Constants from "../../../Models/Constants";
|
||||
import { Unit } from "../../../Models/Unit";
|
||||
import UserRelatedState from "../../../Logic/State/UserRelatedState";
|
||||
import { twJoin } from "tailwind-merge";
|
||||
|
||||
export let config: TagRenderingConfig
|
||||
export let tags: UIEventSource<Record<string, string>>
|
||||
export let selectedElement: Feature
|
||||
export let state: SpecialVisualizationState
|
||||
export let layer: LayerConfig | undefined
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let selectedElement: Feature;
|
||||
export let state: SpecialVisualizationState;
|
||||
export let layer: LayerConfig | undefined;
|
||||
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined);
|
||||
|
||||
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
|
||||
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key));
|
||||
|
||||
// Will be bound if a freeform is available
|
||||
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key])
|
||||
let selectedMapping: number = undefined
|
||||
let checkedMappings: boolean[]
|
||||
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key]);
|
||||
let selectedMapping: number = undefined;
|
||||
let checkedMappings: boolean[];
|
||||
$: {
|
||||
let tgs = $tags
|
||||
let tgs = $tags;
|
||||
mappings = config.mappings?.filter((m) => {
|
||||
if (typeof m.hideInAnswer === "boolean") {
|
||||
return !m.hideInAnswer
|
||||
return !m.hideInAnswer;
|
||||
}
|
||||
return !m.hideInAnswer.matchesProperties(tgs)
|
||||
})
|
||||
return !m.hideInAnswer.matchesProperties(tgs);
|
||||
});
|
||||
// We received a new config -> reinit
|
||||
unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
|
||||
unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key));
|
||||
|
||||
if (
|
||||
config.mappings?.length > 0 &&
|
||||
|
@ -54,23 +54,23 @@
|
|||
) {
|
||||
checkedMappings = [
|
||||
...config.mappings.map((_) => false),
|
||||
false /*One element extra in case a freeform value is added*/,
|
||||
]
|
||||
false /*One element extra in case a freeform value is added*/
|
||||
];
|
||||
}
|
||||
if (config.freeform?.key) {
|
||||
if (!config.multiAnswer) {
|
||||
// Somehow, setting multianswer freeform values is broken if this is not set
|
||||
freeformInput.setData(tgs[config.freeform.key])
|
||||
freeformInput.setData(tgs[config.freeform.key]);
|
||||
}
|
||||
} else {
|
||||
freeformInput.setData(undefined)
|
||||
freeformInput.setData(undefined);
|
||||
}
|
||||
feedback.setData(undefined)
|
||||
feedback.setData(undefined);
|
||||
}
|
||||
export let selectedTags: TagsFilter = undefined
|
||||
export let selectedTags: TagsFilter = undefined;
|
||||
|
||||
let mappings: Mapping[] = config?.mappings
|
||||
let searchTerm: UIEventSource<string> = new UIEventSource("")
|
||||
let mappings: Mapping[] = config?.mappings;
|
||||
let searchTerm: UIEventSource<string> = new UIEventSource("");
|
||||
|
||||
$: {
|
||||
try {
|
||||
|
@ -79,10 +79,10 @@
|
|||
selectedMapping,
|
||||
checkedMappings,
|
||||
tags.data
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Could not calculate changeSpecification:", e)
|
||||
selectedTags = undefined
|
||||
console.error("Could not calculate changeSpecification:", e);
|
||||
selectedTags = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,53 +91,53 @@
|
|||
config: TagRenderingConfig
|
||||
applied: TagsFilter
|
||||
}
|
||||
}>()
|
||||
}>();
|
||||
|
||||
function onSave() {
|
||||
if (selectedTags === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (layer === undefined || layer?.source === null) {
|
||||
/**
|
||||
* This is a special, priviliged layer.
|
||||
* We simply apply the tags onto the records
|
||||
*/
|
||||
const kv = selectedTags.asChange(tags.data)
|
||||
const kv = selectedTags.asChange(tags.data);
|
||||
for (const { k, v } of kv) {
|
||||
if (v === undefined) {
|
||||
delete tags.data[k]
|
||||
delete tags.data[k];
|
||||
} else {
|
||||
tags.data[k] = v
|
||||
tags.data[k] = v;
|
||||
}
|
||||
}
|
||||
tags.ping()
|
||||
return
|
||||
tags.ping();
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch("saved", { config, applied: selectedTags })
|
||||
dispatch("saved", { config, applied: selectedTags });
|
||||
const change = new ChangeTagAction(tags.data.id, selectedTags, tags.data, {
|
||||
theme: state.layout.id,
|
||||
changeType: "answer",
|
||||
})
|
||||
freeformInput.setData(undefined)
|
||||
selectedMapping = undefined
|
||||
selectedTags = undefined
|
||||
changeType: "answer"
|
||||
});
|
||||
freeformInput.setData(undefined);
|
||||
selectedMapping = undefined;
|
||||
selectedTags = undefined;
|
||||
|
||||
change
|
||||
.CreateChangeDescriptions()
|
||||
.then((changes) => state.changes.applyChanges(changes))
|
||||
.catch(console.error)
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
let featureSwitchIsTesting = state.featureSwitchIsTesting ?? new ImmutableStore(false)
|
||||
let featureSwitchIsDebugging = state.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false)
|
||||
let showTags = state.userRelatedState?.showTags ?? new ImmutableStore(undefined)
|
||||
let numberOfCs = state.osmConnection.userDetails.data.csCount
|
||||
let featureSwitchIsTesting = state.featureSwitchIsTesting ?? new ImmutableStore(false);
|
||||
let featureSwitchIsDebugging = state.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false);
|
||||
let showTags = state.userRelatedState?.showTags ?? new ImmutableStore(undefined);
|
||||
let numberOfCs = state.osmConnection.userDetails.data.csCount;
|
||||
onDestroy(
|
||||
state.osmConnection?.userDetails?.addCallbackAndRun((ud) => {
|
||||
numberOfCs = ud.csCount
|
||||
numberOfCs = ud.csCount;
|
||||
})
|
||||
)
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if config.question !== undefined}
|
||||
|
@ -218,6 +218,7 @@
|
|||
value={freeformInput}
|
||||
on:selected={() => (selectedMapping = config.mappings?.length)}
|
||||
on:submit={onSave}
|
||||
submit={onSave}
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
|
|
|
@ -1,69 +1,75 @@
|
|||
<script lang="ts">
|
||||
|
||||
import EditLayerState from "./EditLayerState";
|
||||
import layerSchemaRaw from "../../assets/schemas/layerconfigmeta.json"
|
||||
import Region from "./Region.svelte";
|
||||
import TabbedGroup from "../Base/TabbedGroup.svelte";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import type {ConfigMeta} from "./configMeta";
|
||||
import {Utils} from "../../Utils";
|
||||
import EditLayerState, { LayerStateSender } from "./EditLayerState";
|
||||
import layerSchemaRaw from "../../assets/schemas/layerconfigmeta.json";
|
||||
import Region from "./Region.svelte";
|
||||
import TabbedGroup from "../Base/TabbedGroup.svelte";
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource";
|
||||
import type { ConfigMeta } from "./configMeta";
|
||||
import { Utils } from "../../Utils";
|
||||
|
||||
import drinking_water from "../../../assets/layers/drinking_water/drinking_water.json"
|
||||
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw;
|
||||
let state = new EditLayerState(layerSchema);
|
||||
state.configuration.setData({});
|
||||
const configuration = state.configuration;
|
||||
new LayerStateSender("http://localhost:1235", state);
|
||||
/**
|
||||
* Blacklist of regions for the general area tab
|
||||
* These are regions which are handled by a different tab
|
||||
*/
|
||||
const regionBlacklist = ["hidden", undefined, "infobox", "tagrenderings", "maprendering", "editing", "title"];
|
||||
const allNames = Utils.Dedup(layerSchema.map(meta => meta.hints.group));
|
||||
|
||||
const layerSchema: ConfigMeta[] = <any> layerSchemaRaw
|
||||
let state = new EditLayerState(layerSchema)
|
||||
state.configuration.setData(drinking_water)
|
||||
/**
|
||||
* Blacklist for the general area tab
|
||||
*/
|
||||
const regionBlacklist = ["hidden",undefined,"infobox", "tagrenderings","maprendering", "editing", "title"]
|
||||
const allNames = Utils.Dedup(layerSchema.map(meta => meta.hints.group))
|
||||
const perRegion: Record<string, ConfigMeta[]> = {};
|
||||
for (const region of allNames) {
|
||||
perRegion[region] = layerSchema.filter(meta => meta.hints.group === region);
|
||||
}
|
||||
|
||||
const perRegion: Record<string, ConfigMeta[]> = {}
|
||||
for (const region of allNames) {
|
||||
perRegion[region] = layerSchema.filter(meta => meta.hints.group === region)
|
||||
const baselayerRegions: string[] = ["Basic", "presets", "filters", "advanced", "expert"];
|
||||
for (const baselayerRegion of baselayerRegions) {
|
||||
if (perRegion[baselayerRegion] === undefined) {
|
||||
console.error("BaseLayerRegions in editLayer: no items have group '" + baselayerRegion + "\"");
|
||||
}
|
||||
|
||||
const baselayerRegions: string[] = ["Basic", "presets","filters","advanced","expert"]
|
||||
for (const baselayerRegion of baselayerRegions) {
|
||||
if(perRegion[baselayerRegion] === undefined){
|
||||
console.error("BaseLayerRegions in editLayer: no items have group '"+baselayerRegion+'"')
|
||||
}
|
||||
}
|
||||
const leftoverRegions : string[] = allNames.filter(r => regionBlacklist.indexOf(r) <0 && baselayerRegions.indexOf(r) <0 )
|
||||
}
|
||||
const leftoverRegions: string[] = allNames.filter(r => regionBlacklist.indexOf(r) < 0 && baselayerRegions.indexOf(r) < 0);
|
||||
const title: Store<string> = state.getStoreFor(["id"]);
|
||||
</script>
|
||||
|
||||
<h3>Edit layer</h3>
|
||||
|
||||
<h3>Editing layer {$title}</h3>
|
||||
<h4>Leftover regions</h4>
|
||||
{leftoverRegions.join("; ")}
|
||||
<div class="m4">
|
||||
{allNames}
|
||||
<TabbedGroup tab={new UIEventSource(1)}>
|
||||
<TabbedGroup tab={new UIEventSource(2)}>
|
||||
<div slot="title0">General properties</div>
|
||||
<div class="flex flex-col" slot="content0">
|
||||
{#each baselayerRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region}/>
|
||||
{/each}
|
||||
|
||||
{#each leftoverRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region}/>
|
||||
{/each}
|
||||
{#each baselayerRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region} />
|
||||
{/each}
|
||||
{#each leftoverRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div slot="title1">Information panel (questions and answers)</div>
|
||||
<div slot="content1">
|
||||
<Region {state} configs={perRegion["tagrenderings"]} title="Popup contents">
|
||||
<div slot="description">
|
||||
The bulk of the popup content
|
||||
</div>
|
||||
</Region>
|
||||
<Region {state} configs={perRegion["title"]} title="Popup title"/>
|
||||
<Region {state} configs={perRegion["editing"]} title="Other editing elements"/>
|
||||
<Region configs={perRegion["title"]} {state} title="Popup title" />
|
||||
<Region configs={perRegion["tagrenderings"]} {state} title="Popup contents"/>
|
||||
<Region configs={perRegion["editing"]} {state} title="Other editing elements" />
|
||||
</div>
|
||||
|
||||
<div slot="title2">Rendering on the map</div>
|
||||
<div slot="content2">
|
||||
TODO: rendering on the map
|
||||
<Region configs={perRegion["maprendering"]} {state} />
|
||||
</div>
|
||||
</TabbedGroup>
|
||||
<div slot="title3">Configuration file</div>
|
||||
<div slot="content3">
|
||||
<div>
|
||||
Below, you'll find the raw configuration file in `.json`-format.
|
||||
This is mostly for debugging purposes
|
||||
</div>
|
||||
<div class="literal-code">
|
||||
{JSON.stringify($configuration, null, " ")}
|
||||
</div>
|
||||
</div>
|
||||
</TabbedGroup>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,30 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
|||
import { ConfigMeta } from "./configMeta"
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
|
||||
import { QueryParameters } from "../../Logic/Web/QueryParameters"
|
||||
|
||||
/**
|
||||
* Sends changes back to the server
|
||||
*/
|
||||
export class LayerStateSender {
|
||||
constructor(serverLocation: string, layerState: EditLayerState) {
|
||||
layerState.configuration.addCallback(async (config) => {
|
||||
// console.log("Current config is", Utils.Clone(config))
|
||||
const id = config.id
|
||||
if (id === undefined) {
|
||||
console.log("No id found in layer, not updating")
|
||||
return
|
||||
}
|
||||
const response = await fetch(`${serverLocation}/layers/${id}/${id}.json`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify(config, null, " "),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default class EditLayerState {
|
||||
public readonly osmConnection: OsmConnection
|
||||
|
@ -15,13 +39,17 @@ export default class EditLayerState {
|
|||
|
||||
constructor(schema: ConfigMeta[]) {
|
||||
this.schema = schema
|
||||
this.osmConnection = new OsmConnection({})
|
||||
this.osmConnection = new OsmConnection({
|
||||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
),
|
||||
})
|
||||
this.featureSwitches = {
|
||||
featureSwitchIsDebugging: new UIEventSource<boolean>(true),
|
||||
}
|
||||
this.configuration.addCallback((config) => {
|
||||
// console.log("Current config is", Utils.Clone(config))
|
||||
})
|
||||
console.log("Configuration store:", this.configuration)
|
||||
}
|
||||
|
||||
public getCurrentValueFor(path: ReadonlyArray<string | number>): any | undefined {
|
||||
|
@ -78,12 +106,17 @@ export default class EditLayerState {
|
|||
description: origConfig.description ?? "A translatable object",
|
||||
}
|
||||
}
|
||||
|
||||
public getSchema(path: string[]): ConfigMeta[] {
|
||||
return this.schema.filter(
|
||||
const schemas = this.schema.filter(
|
||||
(sch) =>
|
||||
sch !== undefined &&
|
||||
!path.some((part, i) => !(sch.path.length == path.length && sch.path[i] === part))
|
||||
)
|
||||
if (schemas.length == 0) {
|
||||
console.warn("No schemas found for path", path.join("."))
|
||||
}
|
||||
return schemas
|
||||
}
|
||||
|
||||
public setValueAt(path: ReadonlyArray<string | number>, v: any) {
|
||||
|
|
|
@ -13,7 +13,11 @@ export let title: string | undefined = undefined;
|
|||
export let path: (string | number)[] = [];
|
||||
|
||||
</script>
|
||||
{#if title}
|
||||
{#if configs === undefined}
|
||||
Bug: 'Region' received 'undefined'
|
||||
{:else if configs.length === 0}
|
||||
Bug: Region received empty list as configuration
|
||||
{:else if title}
|
||||
<div class="w-full flex flex-col">
|
||||
<h3>{title}</h3>
|
||||
<div class="pl-2 border border-black flex flex-col gap-y-1 w-full">
|
||||
|
@ -24,6 +28,9 @@ export let path: (string | number)[] = [];
|
|||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="literal-code">
|
||||
{JSON.stringify(configs, null, " ")}
|
||||
</div>
|
||||
<div class="pl-2 flex flex-col gap-y-1 w-full">
|
||||
{#each configs as config}
|
||||
<SchemaBasedInput {state} path={path.concat(config.path)} schema={config} />
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
<div class="flex">
|
||||
<button on:click={() => createItem()}>Add {article} {singular}</button>
|
||||
{#if path.length === 1 && path[0] === "tagRenderings"}
|
||||
<button on:click={() => {createItem();}}>Add a builtin tagRendering</button>
|
||||
<button on:click={() => {createItem("images");}}>Add a builtin tagRendering</button>
|
||||
{/if}
|
||||
<slot name="extra-button" />
|
||||
</div>
|
||||
|
|
|
@ -11,21 +11,21 @@
|
|||
import EditLayerState from "./EditLayerState";
|
||||
import { onDestroy } from "svelte";
|
||||
import type { JsonSchemaType } from "./jsonSchema";
|
||||
|
||||
import { ConfigMetaUtils } from "./configMeta.ts"
|
||||
|
||||
export let state: EditLayerState
|
||||
export let path: (string | number)[] = []
|
||||
export let schema: ConfigMeta
|
||||
let value = new UIEventSource<string>(undefined)
|
||||
|
||||
const isTranslation = schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema)
|
||||
let type = schema.hints.typehint ?? "string"
|
||||
if(type === "rendered"){
|
||||
if(isTranslation){
|
||||
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 = {
|
||||
id: path.join("_"),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import SchemaBasedArray from "./SchemaBasedArray.svelte";
|
||||
import SchemaBasedMultiType from "./SchemaBasedMultiType.svelte";
|
||||
import SchemaBasedTranslationInput from "./SchemaBasedTranslationInput.svelte";
|
||||
|
||||
import { ConfigMetaUtils } from "./configMeta.ts"
|
||||
export let schema: ConfigMeta;
|
||||
export let state: EditLayerState;
|
||||
export let path: (string | number)[] = [];
|
||||
|
@ -16,8 +16,6 @@
|
|||
<SchemaBasedArray {path} {state} {schema} />
|
||||
{:else if schema.type === "array"}
|
||||
<SchemaBasedArray {path} {state} {schema} />
|
||||
{:else if schema.type === "translation"}
|
||||
<SchemaBasedTranslationInput {path} {state} {schema} />
|
||||
{:else if schema.hints.types}
|
||||
<SchemaBasedMultiType {path} {state} {schema} />
|
||||
{:else}
|
||||
|
|
|
@ -45,12 +45,12 @@
|
|||
configJson.mappings.unshift(
|
||||
{
|
||||
if: "direct=true",
|
||||
then: "Yes " + (schema.hints.iftrue ?? ""),
|
||||
then: (schema.hints.iftrue ?? "Yes"),
|
||||
addExtraTags: ["value="]
|
||||
},
|
||||
{
|
||||
if: "direct=false",
|
||||
then: "No " + (schema.hints.iffalse ?? ""),
|
||||
then: (schema.hints.iffalse ?? "No"),
|
||||
addExtraTags: ["value="]
|
||||
}
|
||||
);
|
||||
|
@ -95,7 +95,6 @@
|
|||
}
|
||||
possibleTypes.sort((a, b) => b.optionalMatches - a.optionalMatches);
|
||||
possibleTypes.sort((a, b) => b.matchingPropertiesCount - a.matchingPropertiesCount);
|
||||
console.log(">>> possible types", possibleTypes)
|
||||
if (possibleTypes.length > 0) {
|
||||
tags.setData({ value: "" + possibleTypes[0].index });
|
||||
}
|
||||
|
@ -122,13 +121,19 @@
|
|||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
const oldOption = chosenOption;
|
||||
chosenOption = tags["value"] ? Number(tags["value"]) : defaultOption;
|
||||
const type = schema.type[chosenOption];
|
||||
console.log("Subtype is", type, {chosenOption, oldOption, schema});
|
||||
if (chosenOption !== oldOption) {
|
||||
// Reset the values beneath
|
||||
subSchemas = [];
|
||||
state.setValueAt(path, undefined);
|
||||
const o = state.getCurrentValueFor(path) ?? {}
|
||||
console.log({o})
|
||||
for(const key of type?.required ?? []){
|
||||
console.log(key)
|
||||
o[key] ??= {}
|
||||
}
|
||||
state.setValueAt(path, o);
|
||||
}
|
||||
const type = schema.type[chosenOption];
|
||||
console.log("Subtype is", type);
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
|
@ -148,6 +153,7 @@
|
|||
for (const crumble of Object.keys(type.properties)) {
|
||||
subSchemas.push(...(state.getSchema([...cleanPath, crumble])));
|
||||
}
|
||||
console.log("Got subschemas for", path, ":", subSchemas)
|
||||
}));
|
||||
|
||||
|
||||
|
|
|
@ -22,3 +22,22 @@ export interface ConfigMeta {
|
|||
required: boolean
|
||||
description: string
|
||||
}
|
||||
|
||||
export class ConfigMetaUtils {
|
||||
static isTranslation(configMeta: ConfigMeta) {
|
||||
/* {
|
||||
"$ref": "#/definitions/Record<string,string>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}*/
|
||||
if (!configMeta.type) {
|
||||
return false
|
||||
}
|
||||
if (Array.isArray(configMeta.type)) {
|
||||
return configMeta.type.some((t) => t["$ref"] === "#/definitions/Record<string,string>")
|
||||
} else {
|
||||
return configMeta.type["$ref"] === "#/definitions/Record<string,string>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -601,7 +601,8 @@
|
|||
"required": false,
|
||||
"hints": {
|
||||
"question": "Show the freeform as box within the question?",
|
||||
"ifunset": "do not show the"
|
||||
"iftrue": "show the freeform input field as a small field within the question",
|
||||
"ifunset": "show the freeform input field full-width"
|
||||
},
|
||||
"type": "boolean",
|
||||
"description": "Instead 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."
|
||||
|
@ -661,7 +662,7 @@
|
|||
"required": false,
|
||||
"hints": {},
|
||||
"type": "array",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away"
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
|
|
|
@ -126,6 +126,72 @@
|
|||
],
|
||||
"description": "\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```"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"condition",
|
||||
"and"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"condition",
|
||||
"or"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"metacondition"
|
||||
|
@ -147,6 +213,72 @@
|
|||
],
|
||||
"description": "\nIf set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"metacondition",
|
||||
"and"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"metacondition",
|
||||
"or"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"freeform"
|
||||
|
@ -178,6 +310,40 @@
|
|||
"type": "array",
|
||||
"description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"mappings",
|
||||
"if"
|
||||
],
|
||||
"required": true,
|
||||
"hints": {
|
||||
"typehint": "tag",
|
||||
"question": "When should this single mapping match?"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "\nIf this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"mappings",
|
||||
|
|
29
src/test.ts
29
src/test.ts
|
@ -1,19 +1,16 @@
|
|||
import LayoutConfig from "./Models/ThemeConfig/LayoutConfig"
|
||||
import * as theme from "./assets/generated/themes/bookcases.json"
|
||||
import ThemeViewState from "./Models/ThemeViewState"
|
||||
import Combine from "./UI/Base/Combine"
|
||||
import SpecialVisualizations from "./UI/SpecialVisualizations"
|
||||
import { Utils } from "./Utils"
|
||||
|
||||
function testspecial() {
|
||||
const layout = new LayoutConfig(<any>theme, true) // qp.data === "" ? : new AllKnownLayoutsLazy().get(qp.data)
|
||||
const state = new ThemeViewState(layout)
|
||||
|
||||
const all = SpecialVisualizations.specialVisualizations.map((s) =>
|
||||
SpecialVisualizations.renderExampleOfSpecial(state, s)
|
||||
)
|
||||
new Combine(all).AttachTo("maindiv")
|
||||
class Test {
|
||||
public async test() {
|
||||
await Utils.waitFor(0)
|
||||
const response = await fetch("http://localhost:1235/layers/atm/atm.json", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/*/
|
||||
testspecial()
|
||||
//*/
|
||||
new Test().test()
|
||||
|
|
Loading…
Reference in a new issue