diff --git a/Docs/SpecialRenderings.md b/Docs/SpecialRenderings.md index 3b2364118f..9cda1c2394 100644 --- a/Docs/SpecialRenderings.md +++ b/Docs/SpecialRenderings.md @@ -139,7 +139,7 @@ Show a literal text within braces -----|-----|----- | | text | _undefined_ | The value to show | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L313](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L313) #### Example usage of braced @@ -149,7 +149,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows the title of the popup. Useful for some cases, e.g. 'What is phone number of {title()}?' -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L293](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L293) #### Example usage of title @@ -163,7 +163,7 @@ If the given key can be interpreted as a JSON, only show the key containing the -----|-----|----- | | key | value | The attribute to interpret as json | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L260](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L260) #### Example usage of translated @@ -177,7 +177,7 @@ Visualises data of a POI, sometimes with data updating capabilities Prints all key-value pairs of the object - used for debugging -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L274](/src/UI/Popup/DataVisualisations.ts#L274) #### Example usage of all_tags @@ -191,7 +191,7 @@ Converts a short, canonical value into the long, translated text including the u -----|-----|----- | | key | _undefined_ | The key of the tag to give the canonical text for | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L168](/src/UI/Popup/DataVisualisations.ts#L168) #### Example usage of canonical @@ -206,7 +206,7 @@ Converts compass degrees (with 0° being north, 90° being east, ...) into a hum | key | _direction:centerpoint | The attribute containing the degrees | | offset | 0 | Offset value that is added to the actual value, e.g. `180` to indicate the opposite (backward) direction | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L45](/src/UI/Popup/DataVisualisations.ts#L45) #### Example usage of direction_absolute @@ -216,7 +216,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Gives a distance indicator and a compass pointing towards the location from your GPS-location. If clicked, centers the map on the object -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L28](/src/UI/Popup/DataVisualisations.ts#L28) #### Example usage of direction_indicator @@ -232,7 +232,7 @@ A small element, showing if the POI is currently open and when the next change i | prefix | _empty string_ | Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__ | | postfix | _empty string_ | Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__ | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L127](/src/UI/Popup/DataVisualisations.ts#L127) #### Example usage of opening_hours_state @@ -248,7 +248,7 @@ Creates an opening-hours table. Usage: {opening_hours_table(opening_hours)} to c | prefix | _empty string_ | Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__ | | postfix | _empty string_ | Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__ | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L89](/src/UI/Popup/DataVisualisations.ts#L89) #### Example usage of opening_hours_table @@ -258,7 +258,7 @@ A normal opening hours table can be invoked with `{opening_hours_table()}`. A ta Show general statistics about all the elements currently in view. Intended to use on the `current_view`-layer. They will be split per layer -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L209](/src/UI/Popup/DataVisualisations.ts#L209) #### Example usage of statistics @@ -286,7 +286,7 @@ Elements to help with importing data to OSM. For example: buttons to import a fe | text | _undefined_ | The text to show on the button | | icon | ./assets/svg/robot.svg | The icon to show on the button | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/AutoApplyButtonVis.ts#L64](/src/UI/Popup/AutoApplyButtonVis.ts#L64) #### Example usage of auto_apply @@ -302,7 +302,7 @@ Gives an interactive element which shows a tag comparison between the OSM-object | host | _undefined_ | The domain name(s) where data might be fetched from - this is needed to set the CSP. A domain must include 'https', e.g. 'https://example.com'. For multiple domains, separate them with ';'. If you don't know the possible domains, use '*'. | | readonly | _undefined_ | If 'yes', will not show 'apply'-buttons | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts#L239](/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts#L239) #### Example usage of compare_data @@ -362,7 +362,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | icon | ./assets/svg/addSmall.svg | A nice icon to show in the button | | way_to_conflate | _undefined_ | The key, of which the corresponding value is the id of the OSM-way that must be conflated; typically a calculatedTag | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts#L25](/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts#L25) #### Example usage of conflate_button @@ -426,7 +426,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | maproulette_id | _undefined_ | The property name of the maproulette_id - this is probably `mr_taskId`. If given, the maproulette challenge will be marked as fixed. Only use this if part of a maproulette-layer. | | to_point | _undefined_ | If set, a feature will be converted to a centerpoint | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/ImportButtons/PointImportButtonViz.ts#L17](/src/UI/Popup/ImportButtons/PointImportButtonViz.ts#L17) #### Example usage of import_button @@ -491,7 +491,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | snap_onto_layers | _undefined_ | If no existing nearby point exists, but a line of a specified layer is closeby, snap to this layer instead | | snap_to_layer_max_distance | 0.1 | Distance to distort the geometry to snap to this layer | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/ImportButtons/WayImportButtonViz.ts#L22](/src/UI/Popup/ImportButtons/WayImportButtonViz.ts#L22) #### Example usage of import_way_button @@ -509,7 +509,7 @@ Attempts to load (via a proxy) the specified website and parsed ld+json from the | mode | _undefined_ | If `display`, only show the data in tabular and readonly form, ignoring already existing tags. This is used to explicitly show all the tags. If unset or anything else, allow to apply/import on OSM | | collapsed | yes | If the containing accordion should be closed | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts#L102](/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts#L102) #### Example usage of linked_data_from_website @@ -528,7 +528,7 @@ Change the status of the given MapRoulette task | maproulette_id | mr_taskId | The property name containing the maproulette id | | ask_feedback | _empty string_ | If not an empty string, this will be used as question to ask some additional feedback. A text field will be added | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts#L19](/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts#L19) #### Example usage of maproulette_set_status @@ -558,7 +558,7 @@ Sends the images linked to the current object to plantnet.org and asks it what p -----|-----|----- | | image_key | image,mapillary,image,wikidata,wikimedia_commons,image,panoramax,image,image | The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/PlantNetDetectionViz.ts#L13](/src/UI/Popup/PlantNetDetectionViz.ts#L13) #### Example usage of plantnet_detection @@ -589,7 +589,7 @@ Note that these values can be prepare with javascript in the theme by using a [c | id_of_object_to_apply_this_one | _undefined_ | If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element | | maproulette_id | _undefined_ | If specified, this maproulette-challenge will be closed when the tags are applied. This should be the `id` of the individual task, _not_ the task_id (which corresponds with the challenge). | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/TagApplyViz.ts#L13](/src/UI/SpecialVisualisations/TagApplyViz.ts#L13) #### Example usage of tag_apply @@ -603,7 +603,7 @@ These special visualisations are (mostly) interactive components that most eleme An element which allows to add a new point on the 'last_click'-location. Only makes sense in the layer `last_click` -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L245](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L245) #### Example usage of add_new_point @@ -613,7 +613,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Adds a button which allows to delete the object at this location. The config will be read from the layer config -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L154](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L154) #### Example usage of delete_button @@ -628,7 +628,7 @@ Shows a 'nothing is currently known-message if there is at least one unanswered | text | _undefined_ | Text to show | | cssClasses | _undefined_ | Classes to apply onto the text | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L213](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L213) #### Example usage of if_nothing_known @@ -643,7 +643,7 @@ A small map showing the selected feature. | zoomlevel | 18 | The (maximum) zoomlevel: the target zoomlevel after fitting the entire feature. The minimap will fit the entire feature, then zoom out to this zoom level. The higher, the more zoomed in with 1 being the entire world and 19 being really close | | idKey | id | (Matches all resting arguments) This argument should be the key of a property of the feature. The corresponding value is interpreted as either the id or the a list of ID's. The features with these ID's will be shown on this minimap. (Note: if the key is 'id', list interpration is disabled) | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L81](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L81) #### Example usage of minimap @@ -653,7 +653,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Adds a button which allows to move the object to another location. The config will be read from the layer config -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L129](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L129) #### Example usage of move_button @@ -668,7 +668,7 @@ Generates a QR-code to share the selected object | text | _undefined_ | Extra text on the side of the QR-code | | textClass | _undefined_ | CSS class of the the side text | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L180](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L180) #### Example usage of qr_code @@ -684,7 +684,7 @@ The special element which shows the questions which are unknown. Added by defaul | blacklisted-labels | _undefined_ | One or more ';'-separated labels of questions which should _not_ be included. Note that the questionbox which is added by default will blacklist 'hidden'. If both a whitelist and a blacklist are given, will show questions having at least one label from the whitelist but none of the blacklist. | | show_all | _undefined_ | Either `no`, `yes` or `user-preference`. Indicates if all questions should be shown at once | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L25](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L25) #### Example usage of questions @@ -699,7 +699,7 @@ Creates a link that (attempts to) open the native 'share'-screen | url | _undefined_ | The url to share (default: current URL) | | text | _undefined_ | The text to show on the button. If none is given, will act as a titleIcon | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/ShareLinkViz.ts#L7](/src/UI/Popup/ShareLinkViz.ts#L7) #### Example usage of share_link @@ -709,7 +709,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Adds a button which allows to split a way -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L111](/src/UI/SpecialVisualisations/UISpecialVisualisations.ts#L111) #### Example usage of split_button @@ -723,7 +723,7 @@ Elements relating to marking an object as favourite (giving it a heart). Default A small button that allows a (logged in) contributor to mark a location as a favourite location, sized to fit a title-icon -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/FavouriteVisualisations.ts#L32](/src/UI/SpecialVisualisations/FavouriteVisualisations.ts#L32) #### Example usage of favourite_icon @@ -733,7 +733,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet A button that allows a (logged in) contributor to mark a location as a favourite location -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/FavouriteVisualisations.ts#L9](/src/UI/SpecialVisualisations/FavouriteVisualisations.ts#L9) #### Example usage of favourite_status @@ -751,7 +751,7 @@ Creates an image carousel for the given sources. An attempt will be made to gues -----|-----|----- | | image_key | image;mapillary;image;wikidata;wikimedia_commons;image;panoramax;image;image | The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ImageVisualisations.ts#L57](/src/UI/SpecialVisualisations/ImageVisualisations.ts#L57) #### Example usage of image_carousel @@ -767,7 +767,7 @@ Creates a button where a user can upload an image to panoramax | label | _undefined_ | The text to show on the button | | disable_blur | _undefined_ | If set to 'true' or 'yes', then face blurring will be disabled. To be used sparingly | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ImageVisualisations.ts#L90](/src/UI/SpecialVisualisations/ImageVisualisations.ts#L90) #### Example usage of image_upload @@ -782,7 +782,7 @@ A component showing nearby images loaded from various online services such as Ma | mode | closed | Either `open` or `closed`. If `open`, then the image carousel will always be shown | | readonly | _undefined_ | If 'readonly' or 'yes', will not show the 'link'-button | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ImageVisualisations.ts#L15](/src/UI/SpecialVisualisations/ImageVisualisations.ts#L15) #### Example usage of nearby_images @@ -800,7 +800,7 @@ Adds an image to a node -----|-----|----- | | Id-key | id | The property name where the ID of the note to close can be found | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/NoteVisualisations.ts#L123](/src/UI/SpecialVisualisations/NoteVisualisations.ts#L123) #### Example usage of add_image_to_note @@ -814,7 +814,7 @@ A textfield to add a comment to a node (with the option to close the note). -----|-----|----- | | Id-key | id | The property name where the ID of the note to close can be found | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/NoteVisualisations.ts#L81](/src/UI/SpecialVisualisations/NoteVisualisations.ts#L81) #### Example usage of add_note_comment @@ -833,7 +833,7 @@ Button to close a note. A predefined text can be defined to close the note with. | minZoom | _undefined_ | If set, only show the closenote button if zoomed in enough | | zoomButton | _undefined_ | Text to show if not zoomed in enough | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/NoteVisualisations.ts#L22](/src/UI/SpecialVisualisations/NoteVisualisations.ts#L22) #### Example usage of close_note @@ -843,7 +843,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Creates a new map note on the given location. This options is placed in the 'last_click'-popup automatically if the 'notes'-layer is enabled -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/NoteVisualisations.ts#L102](/src/UI/SpecialVisualisations/NoteVisualisations.ts#L102) #### Example usage of open_note @@ -858,7 +858,7 @@ Visualises the comments for notes | commentsKey | comments | The property name of the comments, which should be stringified json | | start | 0 | Drop the first 'start' comments | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/NoteVisualisations.ts#L143](/src/UI/SpecialVisualisations/NoteVisualisations.ts#L143) #### Example usage of visualize_note_comments @@ -878,7 +878,7 @@ Invites the contributor to leave a review. Somewhat small UI-element until inter | fallback | _undefined_ | The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value | | question | _undefined_ | The question to ask during the review | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L15](/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L15) #### Example usage of create_review @@ -893,7 +893,7 @@ Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs | subjectKey | name | The key to use to determine the subject. If specified, the subject will be tags[subjectKey] | | fallback | _undefined_ | The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L62](/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L62) #### Example usage of list_reviews @@ -908,7 +908,7 @@ Shows stars which represent the average rating on mangrove. | subjectKey | name | The key to use to determine the subject. If the value is specified, the subject will be tags[subjectKey] and will use this to filter the reviews. | | fallback | _undefined_ | The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L97](/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L97) #### Example usage of rating @@ -924,7 +924,7 @@ A pragmatic combination of `create_review` and `list_reviews` | fallback | _undefined_ | The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value | | question | _undefined_ | The question to ask in the review form. Optional | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L155](/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L155) #### Example usage of reviews @@ -942,7 +942,7 @@ A button which clears the locally downloaded data and the service worker. Login -----|-----|----- | | text | _undefined_ | The text to show on the button | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L111](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L111) #### Example usage of clear_caches @@ -952,7 +952,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet A button to remove the travelled track information from the device -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L221](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L221) #### Example usage of clear_location_history @@ -962,7 +962,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows which questions are disabled for every layer. Used in 'settings' -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L43](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L43) #### Example usage of disabled_questions @@ -972,7 +972,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows the current tags of the GPS-representing object, used for debugging -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L66](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L66) #### Example usage of gps_all_tags @@ -982,7 +982,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows the current tags of the GPS-representing object, used for debugging -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L55](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L55) #### Example usage of gyroscope_all_tags @@ -996,7 +996,7 @@ Only makes sense in the usersettings. Allows to import a mangrove public key and -----|-----|----- | | text | _undefined_ | The text that is shown on the button | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L133](/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts#L133) #### Example usage of import_mangrove_key @@ -1006,7 +1006,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet A component to set the language of the user interface -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L21](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L21) #### Example usage of language_picker @@ -1021,7 +1021,7 @@ Show a login button | force | _undefined_ | Always show this button, even if logged in | | message | _undefined_ | Message to display on the button | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L134](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L134) #### Example usage of login_button @@ -1031,7 +1031,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows a button where the user can log out -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L198](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L198) #### Example usage of logout @@ -1041,7 +1041,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet A module showing the pending changes, with the option to clear the pending changes -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L210](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L210) #### Example usage of pending_changes @@ -1056,7 +1056,7 @@ A QR-code which shares the current URL and adds the login token. Anyone with thi | text | _undefined_ | Extra text on the side of the QR-code | | textClass | _undefined_ | CSS class of the the side text | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L163](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L163) #### Example usage of qr_login @@ -1066,7 +1066,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows the current state of storage -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L87](/src/UI/SpecialVisualisations/SettingsVisualisations.ts#L87) #### Example usage of storage_all_tags @@ -1086,7 +1086,7 @@ A collapsable group (accordion) | labels | _undefined_ | A `;`-separated list of either identifiers or label names. All tagRenderings matching this value will be shown in the accordion | | blacklist | _undefined_ | A `;`-separated list of either identifiers or label names. Matching tagrenderings will _not_ be included, even if they are in `labels` | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L174](/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L174) #### Example usage of group @@ -1102,7 +1102,7 @@ Given an embedded tagRendering (read only) and a key, will read the keyname as a | tagrendering | _undefined_ | An entire tagRenderingConfig | | classes | _undefined_ | CSS-classes to apply on every individual item. Seperated by `space` | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L90](/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L90) #### Example usage of multi @@ -1124,7 +1124,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Opens the current view in the iD-editor -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L216](/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L216) #### Example usage of open_in_iD @@ -1134,7 +1134,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Opens the current view in the JOSM-editor -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L230](/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L230) #### Example usage of open_in_josm @@ -1149,7 +1149,7 @@ Shows a tagRendering from a different object as if this was the object itself | featureId | _undefined_ | The key of the attribute which contains the id of the feature from which to use the tags | | tagRenderingId | _undefined_ | The layer-id and tagRenderingId to render. Can be multiple value if ';'-separated (in which case every value must also contain the layerId, e.g. `layerId.tagRendering0; layerId.tagRendering1`). Note: this can cause layer injection | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L17](/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts#L17) #### Example usage of steal @@ -1167,7 +1167,7 @@ Converts a fediverse username or link into a clickable link -----|-----|----- | | key | _undefined_ | The attribute-name containing the link | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L16](/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L16) #### Example usage of fediverse_link @@ -1186,7 +1186,7 @@ Construct a link. By using the 'special' visualisation notation, translations sh | arialabel | _undefined_ | If set, this text will be used as aria-label | | icon | _undefined_ | If set, show this icon next to the link. You might want to combine this with `class: button` | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L139](/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L139) #### Example usage of link @@ -1200,7 +1200,7 @@ Adds a button to open mapillary on the specified location -----|-----|----- | | zoom | 18 | The startzoom of mapillary | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/MapillaryLinkVis.ts#L8](/src/UI/Popup/MapillaryLinkVis.ts#L8) #### Example usage of mapillary_link @@ -1217,7 +1217,7 @@ Creates a `mailto`-link where some fields are already set and correctly escaped. | body | _undefined_ | The text in the email | | button_text | _undefined_ | The text shown on the button in the UI | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L106](/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L106) #### Example usage of send_email @@ -1231,7 +1231,7 @@ Shows the label of the corresponding wikidata-item -----|-----|----- | | keyToShowWikidataFor | wikidata | Use the wikidata entry from this key to show the label | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L66](/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L66) #### Example usage of wikidata_label @@ -1245,7 +1245,7 @@ A box showing the corresponding wikipedia article(s) - based on the **wikidata** -----|-----|----- | | keyToShowWikipediaFor | wikidata;wikipedia | Use the wikidata entry from this key to show the wikipedia article for. Multiple keys can be given (separated by ';'), in which case the first matching value is used | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L38](/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts#L38) #### Example usage of wikipedia @@ -1259,7 +1259,7 @@ Various elements Exports the selected feature as GeoJson-file -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataExportVisualisations.ts#L42](/src/UI/Popup/DataExportVisualisations.ts#L42) #### Example usage of export_as_geojson @@ -1269,7 +1269,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Exports the selected feature as GPX-file -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataExportVisualisations.ts#L10](/src/UI/Popup/DataExportVisualisations.ts#L10) #### Example usage of export_as_gpx @@ -1286,7 +1286,7 @@ Create a histogram for a list of given values, read from the properties. | countHeader | _empty string_ | This text will be placed above the bars | | colors* | _undefined_ | (Matches all resting arguments - optional) Matches a regex onto a color value, e.g. `3[a-zA-Z+-]*:#33cc33` | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/HistogramViz.ts#L6](/src/UI/Popup/HistogramViz.ts#L6) #### Example usage of histogram @@ -1305,7 +1305,7 @@ The language element allows to show and pick all known (modern) languages. The k | render_all | {list()} | The full rendering. Use `{list}` to show where the list of languages must come. Optional if mode=single | | no_known_languages | _undefined_ | The text that is shown if no languages are known for this key. If this text is omitted, the languages will be prompted instead | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/LanguageElement/LanguageElement.ts#L9](/src/UI/Popup/LanguageElement/LanguageElement.ts#L9) #### Example usage of language_chooser @@ -1333,7 +1333,7 @@ A button to apply the tagging of this object onto a list of other features. This | autoapply | _undefined_ | A boolean indicating wether this tagging should be applied automatically if the relevant tags on this object are changed. A visual element indicating the multi_apply is still shown | | overwrite | _undefined_ | If set to 'true', the tags on the other objects will always be overwritten. The default behaviour will be to only change the tags on other objects if they are either undefined or had the same value before the change | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/MultiApplyViz.ts#L7](/src/UI/Popup/MultiApplyViz.ts#L7) #### Example usage of multi_apply @@ -1343,7 +1343,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Shows the extra description from the presets of the layer, if one matches. It will pick the most specific one (e.g. if preset `A` implies `B`, but `B` does not imply `A`, it'll pick B) or the first one if no ordering can be made. Might be empty -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L221](/src/UI/Popup/DataVisualisations.ts#L221) #### Example usage of preset_description @@ -1353,7 +1353,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet An editable tag rendering which allows to change the type -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L238](/src/UI/Popup/DataVisualisations.ts#L238) #### Example usage of preset_type_select @@ -1367,7 +1367,7 @@ Shows a (json of) tags in a human-readable way + links to the wiki -----|-----|----- | | key | value | The key to look for the tags | -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/DataVisualisations.ts#L291](/src/UI/Popup/DataVisualisations.ts#L291) #### Example usage of tags @@ -1377,7 +1377,7 @@ Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplet Uploads the GPS-history as GPX to OpenStreetMap.org; clears the history afterwards. The actual feature is ignored. -Defined in [/src/UI/SpecialVisualization.ts#L98](/home/pietervdvn/git/MapComplete/src/UI/SpecialVisualization.ts) +Defined in [/src/UI/Popup/UploadToOsmViz.ts#L11](/src/UI/Popup/UploadToOsmViz.ts#L11) #### Example usage of upload_to_osm diff --git a/scripts/SourceOverview.ts b/scripts/SourceOverview.ts new file mode 100644 index 0000000000..a775912259 --- /dev/null +++ b/scripts/SourceOverview.ts @@ -0,0 +1,168 @@ +import { RasterLayerProperties } from "../src/Models/RasterLayerProperties" +import { AvailableRasterLayers, RasterLayerPolygon } from "../src/Models/RasterLayers" +import { Utils } from "../src/Utils" +import * as eli from "../public/assets/data/editor-layer-index.json" +import * as layers_global from "../src/assets/global-raster-layers.json" +import eli_global from "../src/assets/generated/editor-layer-index-global.json" +import bing from "../src/assets/bing.json" +import Constants from "../src/Models/Constants" +import ThemeConfig from "../src/Models/ThemeConfig/ThemeConfig" +import { ThemeConfigJson } from "../src/Models/ThemeConfig/Json/ThemeConfigJson" +import SpecialVisualizations from "../src/UI/SpecialVisualizations" +import ValidationUtils from "../src/Models/ThemeConfig/Conversion/ValidationUtils" +import { QuestionableTagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" +import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" +import { ImmutableStore } from "../src/Logic/UIEventSource" + +export interface SourceInfo { + host: string +} + +/** + * Generates what URLs the webapp might access, and why + */ +export class SourceOverview { + private eliUrlsCached: string[] + + public async getOverview( layout: ThemeConfig, + layoutJson: ThemeConfigJson, + options: { + scriptSrcs: string[] + }): Promise { + const apiUrls: string[] = [ + ...Constants.allServers, + "https://www.openstreetmap.org", + "https://api.openstreetmap.org", + "https://pietervdvn.goatcounter.com", + "https://api.panoramax.xyz", + "https://panoramax.mapcomplete.org", + "https://data.velopark.be", + "https://data.mapcomplete.org", + ].concat(...(await this.eliUrls())) + + for (const sv of SpecialVisualizations.specialVisualizations) { + if (typeof sv.needsUrls === "function") { + // Handled below + continue + } + apiUrls.push(...(sv.needsUrls ?? [])) + } + + + const usedSpecialVisualisations = [].concat( + ...layoutJson.layers.map((l) => + ValidationUtils.getAllSpecialVisualisations( + (l).tagRenderings ?? [] + ) + ) + ) + for (const usedSpecialVisualisation of usedSpecialVisualisations) { + if (typeof usedSpecialVisualisation === "string") { + continue + } + const neededUrls = usedSpecialVisualisation.func.needsUrls ?? [] + if (typeof neededUrls === "function") { + let needed: string | string[] = neededUrls(usedSpecialVisualisation.args) + if (typeof needed === "string") { + needed = [needed] + } + apiUrls.push(...needed) + } + } + + apiUrls.push("https://schema.org") + const eliLayers: RasterLayerPolygon[] = AvailableRasterLayers.layersAvailableAt( + new ImmutableStore({ lon: 0, lat: 0 }) + ).store.data + { + const vectorLayers = eliLayers.filter((l) => l.properties.type === "vector") + const vectorSources = vectorLayers.map((l) => l.properties.url) + vectorSources.push(...vectorLayers.map((l) => l.properties.style)) + apiUrls.push( + ...vectorSources.map((url) => { + if (url?.startsWith("pmtiles://")) { + return url.substring("pmtiles://".length) + } + return url + }) + ) + } + const geojsonSources: string[] = layout.layers.map((l) => l.source?.geojsonSource) + + return apiUrls.concat(...geojsonSources) + + } + + private async eliUrls(): Promise { + if (this.eliUrlsCached) { + return this.eliUrlsCached + } + const urls: string[] = [] + const regex = /{switch:([^}]+)}/ + const rasterLayers: { properties: RasterLayerProperties }[] = [ + AvailableRasterLayers.defaultBackgroundLayer, + ...eli.features, + bing, + ...eli_global.map((properties) => ({ properties })), + ...layers_global.layers.map((properties) => ({ properties })), + ] + for (const feature of rasterLayers) { + const f = feature + const url = f.properties.url + const match = url.match(regex) + if (match) { + const domains = match[1].split(",") + const subpart = match[0] + urls.push(...domains.map((d) => url.replace(subpart, d))) + } else { + urls.push(url) + } + + if (f.properties.type === "vector") { + // We also need to whitelist eventual sources + let url = f.properties.url + urls.push(...(f.properties["connect-src"] ?? [])) + if (url.startsWith("pmtiles://")) { + url = url.substring("pmtiles://".length) + } + if (url.endsWith(".pmtiles")) { + continue + } + try { + console.log("Downloading ", url) + const styleSpec = await Utils.downloadJsonCached(url, 1000 * 120, { + Origin: "https://mapcomplete.org", + }) + for (const key of Object.keys(styleSpec?.["sources"] ?? {})) { + const url = styleSpec["sources"][key].url + if (!url) { + continue + } + let urlClipped = url + if (url.indexOf("?") > 0) { + urlClipped = url?.substring(0, url.indexOf("?")) + } + console.log("Source url ", key, url) + urls.push(url) + if (urlClipped.endsWith(".json")) { + const tileInfo = await Utils.downloadJsonCached(url, 1000 * 120, { + Origin: "https://mapcomplete.org", + }) + urls.push(tileInfo["tiles"] ?? []) + } + } + urls.push(...(styleSpec["tiles"] ?? [])) + urls.push(styleSpec["sprite"]) + urls.push(styleSpec["glyphs"]) + } catch (e) { + console.error( + "ERROR: could not download a resource, some sprites might not be whitelisted and thus not load" + ) + } + } + } + this.eliUrlsCached = urls + return Utils.NoNull(urls).sort() + } + +} diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 590bdc6816..8f1813d39c 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -7,21 +7,10 @@ import ThemeConfig from "../src/Models/ThemeConfig/ThemeConfig" import xml2js from "xml2js" import ScriptUtils from "./ScriptUtils" import { Utils } from "../src/Utils" -import SpecialVisualizations from "../src/UI/SpecialVisualizations" import Constants from "../src/Models/Constants" -import { AvailableRasterLayers, RasterLayerPolygon } from "../src/Models/RasterLayers" -import { ImmutableStore } from "../src/Logic/UIEventSource" -import * as eli from "../public/assets/data/editor-layer-index.json" -import * as layers_global from "../src/assets/global-raster-layers.json" -import eli_global from "../src/assets/generated/editor-layer-index-global.json" -import bing from "../src/assets/bing.json" - -import ValidationUtils from "../src/Models/ThemeConfig/Conversion/ValidationUtils" -import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" -import { QuestionableTagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" import Script from "./Script" import crypto from "crypto" -import { RasterLayerProperties } from "../src/Models/RasterLayerProperties" +import { SourceOverview } from "./SourceOverview" const sharp = require("sharp") @@ -36,8 +25,6 @@ class GenerateLayouts extends Script { .join("\n") private readonly removeOtherLanguagesHash = "sha256-" + crypto.createHash("sha256").update(this.removeOtherLanguages).digest("base64") - private previousSrc: Set = new Set() - private eliUrlsCached: string[] private date = new Date().toISOString() private branchName: string = undefined private alreadyWritten: Set = new Set() @@ -265,78 +252,7 @@ class GenerateLayouts extends Script { return values.join("\n") } - async eliUrls(): Promise { - if (this.eliUrlsCached) { - return this.eliUrlsCached - } - const urls: string[] = [] - const regex = /{switch:([^}]+)}/ - const rasterLayers: { properties: RasterLayerProperties }[] = [ - AvailableRasterLayers.defaultBackgroundLayer, - ...eli.features, - bing, - ...eli_global.map((properties) => ({ properties })), - ...layers_global.layers.map((properties) => ({ properties })), - ] - for (const feature of rasterLayers) { - const f = feature - const url = f.properties.url - const match = url.match(regex) - if (match) { - const domains = match[1].split(",") - const subpart = match[0] - urls.push(...domains.map((d) => url.replace(subpart, d))) - } else { - urls.push(url) - } - - if (f.properties.type === "vector") { - // We also need to whitelist eventual sources - let url = f.properties.url - urls.push(...(f.properties["connect-src"] ?? [])) - if (url.startsWith("pmtiles://")) { - url = url.substring("pmtiles://".length) - } - if (url.endsWith(".pmtiles")) { - continue - } - try { - console.log("Downloading ", url) - const styleSpec = await Utils.downloadJsonCached(url, 1000 * 120, { - Origin: "https://mapcomplete.org", - }) - for (const key of Object.keys(styleSpec?.["sources"] ?? {})) { - const url = styleSpec["sources"][key].url - if (!url) { - continue - } - let urlClipped = url - if (url.indexOf("?") > 0) { - urlClipped = url?.substring(0, url.indexOf("?")) - } - console.log("Source url ", key, url) - urls.push(url) - if (urlClipped.endsWith(".json")) { - const tileInfo = await Utils.downloadJsonCached(url, 1000 * 120, { - Origin: "https://mapcomplete.org", - }) - urls.push(tileInfo["tiles"] ?? []) - } - } - urls.push(...(styleSpec["tiles"] ?? [])) - urls.push(styleSpec["sprite"]) - urls.push(styleSpec["glyphs"]) - } catch (e) { - console.error( - "ERROR: could not download a resource, some sprites might not be whitelisted and thus not load" - ) - } - } - } - this.eliUrlsCached = urls - return Utils.NoNull(urls).sort() - } - + private readonly sourceOverview = new SourceOverview() async generateCsp( layout: ThemeConfig, layoutJson: ThemeConfigJson, @@ -344,66 +260,10 @@ class GenerateLayouts extends Script { scriptSrcs: string[] } ): Promise { - const apiUrls: string[] = [ - ...Constants.allServers, - "https://www.openstreetmap.org", - "https://api.openstreetmap.org", - "https://pietervdvn.goatcounter.com", - "https://api.panoramax.xyz", - "https://panoramax.mapcomplete.org", - "https://data.velopark.be", - "https://data.mapcomplete.org", - ].concat(...(await this.eliUrls())) - - SpecialVisualizations.specialVisualizations.forEach((sv) => { - if (typeof sv.needsUrls === "function") { - // Handled below - return - } - apiUrls.push(...(sv.needsUrls ?? [])) - }) - - const usedSpecialVisualisations = [].concat( - ...layoutJson.layers.map((l) => - ValidationUtils.getAllSpecialVisualisations( - (l).tagRenderings ?? [] - ) - ) - ) - for (const usedSpecialVisualisation of usedSpecialVisualisations) { - if (typeof usedSpecialVisualisation === "string") { - continue - } - const neededUrls = usedSpecialVisualisation.func.needsUrls ?? [] - if (typeof neededUrls === "function") { - let needed: string | string[] = neededUrls(usedSpecialVisualisation.args) - if (typeof needed === "string") { - needed = [needed] - } - apiUrls.push(...needed) - } - } - - const geojsonSources: string[] = layout.layers.map((l) => l.source?.geojsonSource) + const urls = await this.sourceOverview.getOverview(layout, layoutJson, options) const hosts = new Set() - hosts.add("https://schema.org") - const eliLayers: RasterLayerPolygon[] = AvailableRasterLayers.layersAvailableAt( - new ImmutableStore({ lon: 0, lat: 0 }) - ).store.data - { - const vectorLayers = eliLayers.filter((l) => l.properties.type === "vector") - const vectorSources = vectorLayers.map((l) => l.properties.url) - vectorSources.push(...vectorLayers.map((l) => l.properties.style)) - apiUrls.push( - ...vectorSources.map((url) => { - if (url?.startsWith("pmtiles://")) { - return url.substring("pmtiles://".length) - } - return url - }) - ) - } - for (let connectSource of apiUrls.concat(geojsonSources)) { + + for (let connectSource of urls) { if (!connectSource) { continue } @@ -425,17 +285,12 @@ class GenerateLayouts extends Script { } const connectSrc = Array.from(hosts).sort() - - const newSrcs = connectSrc.filter((newItem) => !this.previousSrc.has(newItem)) - console.log( "Got", hosts.size, "connect-src items for theme", layout.id, - newSrcs.length > 0 ? "(extra sources: " + newSrcs.join(" ") + ")" : "" ) - this.previousSrc = hosts const csp: Record = { "default-src": "'self'", diff --git a/src/UI/Popup/AutoApplyButtonVis.ts b/src/UI/Popup/AutoApplyButtonVis.ts index c2dba91cc0..a0c135aa66 100644 --- a/src/UI/Popup/AutoApplyButtonVis.ts +++ b/src/UI/Popup/AutoApplyButtonVis.ts @@ -1,20 +1,16 @@ import { Store, Stores, UIEventSource } from "../../Logic/UIEventSource" import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" import { Changes } from "../../Logic/Osm/Changes" -import { - SpecialVisualization, - SpecialVisualizationState, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" +import { SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" import { IndexedFeatureSource } from "../../Logic/FeatureSource/FeatureSource" import SvelteUIElement from "../Base/SvelteUIElement" import { Feature } from "geojson" import AutoApplyButton from "./AutoApplyButton.svelte" -export interface AutoAction extends SpecialVisualization { +export abstract class AutoAction extends SpecialVisualization { supportsAutoAction: boolean - applyActionOn( + abstract applyActionOn( feature: Feature, state: { theme: ThemeConfig @@ -26,8 +22,8 @@ export interface AutoAction extends SpecialVisualization { ): Promise } -export default class AutoApplyButtonVis implements SpecialVisualizationSvelte { - public readonly docs: string +export default class AutoApplyButtonVis extends SpecialVisualizationSvelte { + public readonly docs: string = "" public readonly funcName: string = "auto_apply" public readonly needsUrls = [] public readonly group = "data_import" @@ -65,6 +61,7 @@ export default class AutoApplyButtonVis implements SpecialVisualizationSvelte { ] constructor(allSpecialVisualisations: SpecialVisualization[]) { + super() this.docs = AutoApplyButtonVis.generateDocs( allSpecialVisualisations .filter((sv) => sv["supportsAutoAction"] === true) @@ -124,7 +121,5 @@ export default class AutoApplyButtonVis implements SpecialVisualizationSvelte { return new SvelteUIElement(AutoApplyButton, { state, ids: stableIds, options }) } - getLayerDependencies(args: string[]): string[] { - return [args[0]] - } + getLayerDependencies = (args: string[]): string[] => [args[0]] } diff --git a/src/UI/Popup/DataExportVisualisations.ts b/src/UI/Popup/DataExportVisualisations.ts new file mode 100644 index 0000000000..ebfb34ba37 --- /dev/null +++ b/src/UI/Popup/DataExportVisualisations.ts @@ -0,0 +1,67 @@ +import { SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { UIEventSource } from "../../Logic/UIEventSource" +import { Feature, LineString } from "geojson" +import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import Translations from "../i18n/Translations" +import SvelteUIElement from "../Base/SvelteUIElement" +import ExportFeatureButton from "./ExportFeatureButton.svelte" +import { GeoOperations } from "../../Logic/GeoOperations" + +class ExportAsGpxVis extends SpecialVisualizationSvelte { + funcName = "export_as_gpx" + docs = "Exports the selected feature as GPX-file" + args = [] + needsUrls = [] + + constr( + state: SpecialVisualizationState, + tags: UIEventSource>, + argument: string[], + feature: Feature, + layer: LayerConfig, + ) { + if (feature.geometry.type !== "LineString") { + return undefined + } + const t = Translations.t.general.download + + return new SvelteUIElement(ExportFeatureButton, { + tags, + feature, + layer, + mimetype: "{gpx=application/gpx+xml}", + extension: "gpx", + construct: (feature: Feature, title: string) => + GeoOperations.toGpx(feature, title), + helpertext: t.downloadGpxHelper, + maintext: t.downloadFeatureAsGpx, + }) + } +} + +class ExportAsGeojsonVis extends SpecialVisualizationSvelte { + funcName = "export_as_geojson" + docs = "Exports the selected feature as GeoJson-file" + args = [] + + constr(state, tags, args, feature, layer) { + const t = Translations.t.general.download + return new SvelteUIElement(ExportFeatureButton, { + tags, + feature, + layer, + mimetype: "application/vnd.geo+json", + extension: "geojson", + construct: (feature: Feature) => + JSON.stringify(feature, null, " "), + maintext: t.downloadFeatureAsGeojson, + helpertext: t.downloadGeoJsonHelper, + }) + } +} + +export class DataExportVisualisations { + public static initList(): SpecialVisualization[] { + return [new ExportAsGpxVis(), new ExportAsGeojsonVis()] + } +} diff --git a/src/UI/Popup/DataVisualisations.ts b/src/UI/Popup/DataVisualisations.ts new file mode 100644 index 0000000000..d1b5a885fd --- /dev/null +++ b/src/UI/Popup/DataVisualisations.ts @@ -0,0 +1,352 @@ +import { SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { HistogramViz } from "./HistogramViz" +import { Store, UIEventSource } from "../../Logic/UIEventSource" +import { Feature } from "geojson" +import BaseUIElement from "../BaseUIElement" +import SvelteUIElement from "../Base/SvelteUIElement" +import DirectionIndicator from "../Base/DirectionIndicator.svelte" +import { VariableUiElement } from "../Base/VariableUIElement" +import { GeoOperations } from "../../Logic/GeoOperations" +import Translations from "../i18n/Translations" +import Constants from "../../Models/Constants" +import opening_hours from "opening_hours" +import { OH } from "../OpeningHours/OpeningHours" +import OpeningHoursWithError from "../OpeningHours/Visualisation/OpeningHoursWithError.svelte" +import NextChangeViz from "../OpeningHours/NextChangeViz.svelte" +import { Unit } from "../../Models/Unit" +import AllFeaturesStatistics from "../Statistics/AllFeaturesStatistics.svelte" +import { LanguageElement } from "./LanguageElement/LanguageElement" +import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" +import { And } from "../../Logic/Tags/And" +import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig" +import TagRenderingEditable from "./TagRendering/TagRenderingEditable.svelte" +import AllTagsPanel from "./AllTagsPanel/AllTagsPanel.svelte" +import { FixedUiElement } from "../Base/FixedUiElement" +import { TagUtils } from "../../Logic/Tags/TagUtils" + +class DirectionIndicatorVis extends SpecialVisualization { + funcName = "direction_indicator" + args = [] + + docs = "Gives a distance indicator and a compass pointing towards the location from your GPS-location. If clicked, centers the map on the object" + group = "data" + + constr( + state: SpecialVisualizationState, + tagSource: UIEventSource>, + argument: string[], + feature: Feature, + ): BaseUIElement { + return new SvelteUIElement(DirectionIndicator, { state, feature }) + } +} + +class DirectionAbsolute extends SpecialVisualization { + funcName = "direction_absolute" + docs = "Converts compass degrees (with 0° being north, 90° being east, ...) into a human readable, translated direction such as 'north', 'northeast'" + args = [ + { + name: "key", + type: "key", + doc: "The attribute containing the degrees", + defaultValue: "_direction:centerpoint", + }, + { + name: "offset", + doc: "Offset value that is added to the actual value, e.g. `180` to indicate the opposite (backward) direction", + defaultValue: "0", + }, + ] + group = "data" + + constr( + state: SpecialVisualizationState, + tagSource: UIEventSource>, + args: string[], + ): BaseUIElement { + const key = args[0] === "" ? "_direction:centerpoint" : args[0] + const offset = args[1] === "" ? 0 : Number(args[1]) + + return new VariableUiElement( + tagSource + .map((tags) => { + console.log("Direction value", tags[key], key) + return tags[key] + }) + .mapD((value) => { + const dir = GeoOperations.bearingToHuman( + GeoOperations.parseBearing(value) + offset, + ) + console.log("Human dir", dir) + return Translations.t.general.visualFeedback.directionsAbsolute[dir] + }), + ) + } +} + + +class OpeningHoursTableVis extends SpecialVisualizationSvelte { + funcName = "opening_hours_table" + docs = "Creates an opening-hours table. Usage: {opening_hours_table(opening_hours)} to create a table of the tag 'opening_hours'." + args = [ + { + name: "key", + defaultValue: "opening_hours", + type: "key", + doc: "The tagkey from which the table is constructed.", + }, + { + name: "prefix", + defaultValue: "", + doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__", + }, + { + name: "postfix", + defaultValue: "", + doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__", + }, + ] + group = "data" + needsUrls = [Constants.countryCoderEndpoint] + example = + "A normal opening hours table can be invoked with `{opening_hours_table()}`. A table for e.g. conditional access with opening hours can be `{opening_hours_table(access:conditional, no @ &LPARENS, &RPARENS)}`" + + constr(state, tagSource: UIEventSource, args) { + const [key, prefix, postfix] = args + const openingHoursStore: Store = + OH.CreateOhObjectStore(tagSource, key, prefix, postfix) + return new SvelteUIElement(OpeningHoursWithError, { + tags: tagSource, + key, + opening_hours_obj: openingHoursStore, + }) + } +} + +class OpeningHoursState extends SpecialVisualizationSvelte { + group = "data" + funcName = "opening_hours_state" + docs = "A small element, showing if the POI is currently open and when the next change is" + args = [ + { + name: "key", + type: "key", + defaultValue: "opening_hours", + doc: "The tagkey from which the opening hours are read.", + }, + { + name: "prefix", + defaultValue: "", + doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__", + }, + { + name: "postfix", + defaultValue: "", + doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__", + }, + ] + + constr( + state: SpecialVisualizationState, + tags: UIEventSource>, + args: string[], + ): SvelteUIElement { + const keyToUse = args[0] + const prefix = args[1] + const postfix = args[2] + return new SvelteUIElement(NextChangeViz, { + state, + keyToUse, + tags, + prefix, + postfix, + }) + } +} + +class Canonical extends SpecialVisualization { + group = "data" + funcName = "canonical" + + docs = "Converts a short, canonical value into the long, translated text including the unit. This only works if a `unit` is defined for the corresponding value. The unit specification will be included in the text. " + example = + "If the object has `length=42`, then `{canonical(length)}` will be shown as **42 meter** (in english), **42 metre** (in french), ..." + args = [ + { + name: "key", + type: "key", + doc: "The key of the tag to give the canonical text for", + required: true, + }, + ] + + constr(state, tagSource, args) { + const key = args[0] + return new VariableUiElement( + tagSource + .map((tags) => tags[key]) + .map((value) => { + if (value === undefined) { + return undefined + } + const allUnits: Unit[] = [].concat( + ...(state?.theme?.layers?.map((lyr) => lyr.units) ?? []), + ) + const unit = allUnits.filter((unit) => + unit.isApplicableToKey(key), + )[0] + if (unit === undefined) { + return value + } + const getCountry = () => tagSource.data._country + return unit.asHumanLongValue(value, getCountry) + }), + ) + } +} + +class StatisticsVis extends SpecialVisualizationSvelte { + funcName = "statistics" + group = "data" + docs = "Show general statistics about all the elements currently in view. Intended to use on the `current_view`-layer. They will be split per layer" + args = [] + + constr(state) { + + return new SvelteUIElement(AllFeaturesStatistics, { state }) + } +} + +class PresetDescription extends SpecialVisualization { + funcName = "preset_description" + docs = "Shows the extra description from the presets of the layer, if one matches. It will pick the most specific one (e.g. if preset `A` implies `B`, but `B` does not imply `A`, it'll pick B) or the first one if no ordering can be made. Might be empty" + args = [] + + constr( + state: SpecialVisualizationState, + tagSource: UIEventSource>, + ): BaseUIElement { + const translation = tagSource.map((tags) => { + const layer = state.theme.getMatchingLayer(tags) + return layer?.getMostMatchingPreset(tags)?.description + }) + return new VariableUiElement(translation) + } +} + +class PresetTypeSelect extends SpecialVisualizationSvelte { + funcName = "preset_type_select" + docs = "An editable tag rendering which allows to change the type" + args = [] + + constr( + state: SpecialVisualizationState, + tags: UIEventSource>, + argument: string[], + selectedElement: Feature, + layer: LayerConfig, + ): SvelteUIElement { + const t = Translations.t.preset_type + const question: QuestionableTagRenderingConfigJson = { + id: layer.id + "-type", + question: t.question.translations, + mappings: layer.presets.map((pr) => ({ + if: new And(pr.tags).asJson(), + icon: "auto", + then: (pr.description ? t.typeDescription : t.typeTitle).Subs({ + title: pr.title, + description: pr.description, + }).translations, + })), + } + const config = new TagRenderingConfig(question) + return new SvelteUIElement(TagRenderingEditable, { + config, + tags, + selectedElement, + state, + layer, + }) + } +} + +class AllTagsVis extends SpecialVisualizationSvelte { + funcName = "all_tags" + docs = "Prints all key-value pairs of the object - used for debugging" + args = [] + group = "data" + + constr( + state, + tags: UIEventSource>, + _, + __, + layer: LayerConfig, + ) { + return new SvelteUIElement(AllTagsPanel, { tags, layer }) + } +} + +class TagsVis extends SpecialVisualization { + funcName = "tags" + docs = "Shows a (json of) tags in a human-readable way + links to the wiki" + + args = [ + { + name: "key", + type: "key", + defaultValue: "value", + doc: "The key to look for the tags", + }, + ] + + constr( + state: SpecialVisualizationState, + tagSource: UIEventSource>, + argument: string[], + ): BaseUIElement { + const key = argument[0] ?? "value" + return new VariableUiElement( + tagSource.map((tags) => { + let value = tags[key] + if (!value) { + return new FixedUiElement("No tags found").SetClass("font-bold") + } + if (typeof value === "string" && value.startsWith("{")) { + value = JSON.parse(value) + } + try { + const parsed = TagUtils.Tag(value) + return parsed.asHumanString(true, false, {}) + } catch (e) { + return new FixedUiElement( + "Could not parse this tag: " + + JSON.stringify(value) + + " due to " + + e, + ).SetClass("alert") + } + }), + ) + } +} + +export class DataVisualisations { + public static initList(): SpecialVisualization[] { + return [ + new HistogramViz(), + new StatisticsVis(), + new DirectionAbsolute(), + new DirectionIndicatorVis(), + new OpeningHoursTableVis(), + new OpeningHoursState(), + new Canonical(), + new LanguageElement(), + new PresetDescription(), + new PresetTypeSelect(), + new AllTagsVis(), + new TagsVis(), + ] + } +} diff --git a/src/UI/Popup/HistogramViz.ts b/src/UI/Popup/HistogramViz.ts index 59d9bc820d..7af411f9d3 100644 --- a/src/UI/Popup/HistogramViz.ts +++ b/src/UI/Popup/HistogramViz.ts @@ -3,7 +3,7 @@ import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisua import Histogram from "../BigComponents/Histogram" import { Feature } from "geojson" -export class HistogramViz implements SpecialVisualization { +export class HistogramViz extends SpecialVisualization { funcName = "histogram" docs = "Create a histogram for a list of given values, read from the properties." needsUrls = [] diff --git a/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts b/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts index b8ea4f0625..ba92a7bc17 100644 --- a/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts @@ -13,6 +13,7 @@ import { IndexedFeatureSource } from "../../../Logic/FeatureSource/FeatureSource import { Changes } from "../../../Logic/Osm/Changes" import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import { OsmConnection } from "../../../Logic/Osm/OsmConnection" +import { OsmTags } from "../../../Models/OsmFeature" export interface ConflateFlowArguments extends ImportFlowArguments { way_to_conflate: string @@ -21,7 +22,7 @@ export interface ConflateFlowArguments extends ImportFlowArguments { snap_onto_layers?: string } -export default class ConflateImportButtonViz implements SpecialVisualization, AutoAction { +export default class ConflateImportButtonViz extends SpecialVisualization implements AutoAction { supportsAutoAction: boolean = true needsUrls = [] group = "data_import" @@ -85,7 +86,7 @@ export default class ConflateImportButtonViz implements SpecialVisualization, Au constr( state: SpecialVisualizationState, - tagSource: UIEventSource>, + tagSource: UIEventSource, argument: string[], feature: Feature ): BaseUIElement { @@ -111,7 +112,5 @@ export default class ConflateImportButtonViz implements SpecialVisualization, Au }) } - getLayerDependencies(args: string[]) { - return ImportFlowUtils.getLayerDependenciesWithSnapOnto(this.args, args) - } + getLayerDependencies = (args: string[]) => ImportFlowUtils.getLayerDependenciesWithSnapOnto(this.args, args) } diff --git a/src/UI/Popup/ImportButtons/PointImportButtonViz.ts b/src/UI/Popup/ImportButtons/PointImportButtonViz.ts index f29aa90f6f..662ada2f0d 100644 --- a/src/UI/Popup/ImportButtons/PointImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/PointImportButtonViz.ts @@ -9,53 +9,46 @@ import { Utils } from "../../../Utils" import { ImportFlowUtils } from "./ImportFlow" import Translations from "../../i18n/Translations" import { GeoOperations } from "../../../Logic/GeoOperations" +import { OsmTags } from "../../../Models/OsmFeature" /** * The wrapper to make the special visualisation for the PointImportFlow */ -export class PointImportButtonViz implements SpecialVisualization { - public readonly funcName: string - public readonly docs: string | BaseUIElement - public readonly example?: string - public readonly args: { name: string; defaultValue?: string; doc: string; split?: boolean }[] +export class PointImportButtonViz extends SpecialVisualization { + public readonly funcName = "import_button" + public readonly docs: string = "This button will copy the point from an external dataset into OpenStreetMap" + + ImportFlowUtils.documentationGeneral + public readonly args: { name: string; defaultValue?: string; doc: string; split?: boolean }[] = [ + ...ImportFlowUtils.generalArguments, + { + name: "snap_onto_layers", + doc: "If a way of the given layer(s) is closeby, will snap the new point onto this way (similar as preset might snap). To show multiple layers to snap onto, use a `;`-seperated list", + }, + { + name: "max_snap_distance", + doc: "The maximum distance that the imported point will be moved to snap onto a way in an already existing layer (in meters). This is previewed to the contributor, similar to the 'add new point'-action of MapComplete", + defaultValue: "5", + }, + { + name: "note_id", + doc: "If given, this key will be read. The corresponding note on OSM will be closed, stating 'imported'", + }, + { + name: "maproulette_id", + doc: "The property name of the maproulette_id - this is probably `mr_taskId`. If given, the maproulette challenge will be marked as fixed. Only use this if part of a maproulette-layer.", + }, + { + name: "to_point", + doc: "If set, a feature will be converted to a centerpoint", + }, + ] public needsUrls = [] group = "data_import" - constructor() { - this.funcName = "import_button" - - this.docs = - "This button will copy the point from an external dataset into OpenStreetMap" + - ImportFlowUtils.documentationGeneral - this.args = [ - ...ImportFlowUtils.generalArguments, - { - name: "snap_onto_layers", - doc: "If a way of the given layer(s) is closeby, will snap the new point onto this way (similar as preset might snap). To show multiple layers to snap onto, use a `;`-seperated list", - }, - { - name: "max_snap_distance", - doc: "The maximum distance that the imported point will be moved to snap onto a way in an already existing layer (in meters). This is previewed to the contributor, similar to the 'add new point'-action of MapComplete", - defaultValue: "5", - }, - { - name: "note_id", - doc: "If given, this key will be read. The corresponding note on OSM will be closed, stating 'imported'", - }, - { - name: "maproulette_id", - doc: "The property name of the maproulette_id - this is probably `mr_taskId`. If given, the maproulette challenge will be marked as fixed. Only use this if part of a maproulette-layer.", - }, - { - name: "to_point", - doc: "If set, a feature will be converted to a centerpoint", - }, - ] - } constr( state: SpecialVisualizationState, - tagSource: UIEventSource>, + tagSource: UIEventSource, argument: string[], feature: Feature ): BaseUIElement { diff --git a/src/UI/Popup/ImportButtons/PointImportFlowState.ts b/src/UI/Popup/ImportButtons/PointImportFlowState.ts index 395b3472f7..5814c76b5b 100644 --- a/src/UI/Popup/ImportButtons/PointImportFlowState.ts +++ b/src/UI/Popup/ImportButtons/PointImportFlowState.ts @@ -6,7 +6,7 @@ import { Feature, Point } from "geojson" import Maproulette from "../../../Logic/Maproulette" import { GeoOperations } from "../../../Logic/GeoOperations" import { Tag } from "../../../Logic/Tags/Tag" -import ThemeViewState from "../../../Models/ThemeViewState" +import { SpecialVisualizationState } from "../../SpecialVisualization" export interface PointImportFlowArguments extends ImportFlowArguments { max_snap_distance?: string @@ -21,7 +21,7 @@ export class PointImportFlowState extends ImportFlow { public readonly startCoordinate: [number, number] constructor( - state: ThemeViewState, + state: SpecialVisualizationState, originalFeature: Feature, args: PointImportFlowArguments, tagsToApply: Store, diff --git a/src/UI/Popup/ImportButtons/WayImportButtonViz.ts b/src/UI/Popup/ImportButtons/WayImportButtonViz.ts index 2e3bbdb139..1c00a89074 100644 --- a/src/UI/Popup/ImportButtons/WayImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/WayImportButtonViz.ts @@ -14,11 +14,12 @@ import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import { Changes } from "../../../Logic/Osm/Changes" import { IndexedFeatureSource } from "../../../Logic/FeatureSource/FeatureSource" import FullNodeDatabaseSource from "../../../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" +import { OsmTags } from "../../../Models/OsmFeature" /** * Wrapper around 'WayImportFlow' to make it a special visualisation */ -export default class WayImportButtonViz implements AutoAction, SpecialVisualization { +export default class WayImportButtonViz extends SpecialVisualization implements AutoAction { public readonly funcName: string = "import_way_button" needsUrls = [] group = "data_import" @@ -62,7 +63,7 @@ export default class WayImportButtonViz implements AutoAction, SpecialVisualizat constr( state: SpecialVisualizationState, - tagSource: UIEventSource>, + tagSource: UIEventSource, argument: string[], feature: Feature, _: LayerConfig @@ -125,7 +126,5 @@ export default class WayImportButtonViz implements AutoAction, SpecialVisualizat await state.changes.applyAction(action) } - getLayerDependencies(args: string[]) { - return ImportFlowUtils.getLayerDependenciesWithSnapOnto(this.args, args) - } + getLayerDependencies = (args: string[]) => ImportFlowUtils.getLayerDependenciesWithSnapOnto(this.args, args) } diff --git a/src/UI/Popup/LanguageElement/LanguageElement.ts b/src/UI/Popup/LanguageElement/LanguageElement.ts index a9a5df1d51..71b1663041 100644 --- a/src/UI/Popup/LanguageElement/LanguageElement.ts +++ b/src/UI/Popup/LanguageElement/LanguageElement.ts @@ -6,7 +6,7 @@ import { Feature } from "geojson" import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" import { default as LanguageElementSvelte } from "./LanguageElement.svelte" -export class LanguageElement implements SpecialVisualization { +export class LanguageElement extends SpecialVisualization { funcName: string = "language_chooser" needsUrls = [] @@ -45,7 +45,7 @@ export class LanguageElement implements SpecialVisualization { }, ] - example: ` + example= ` \`\`\`json {"special": "type": "language_chooser", diff --git a/src/UI/Popup/MapillaryLinkVis.ts b/src/UI/Popup/MapillaryLinkVis.ts index ab05fd9e7f..048e99f94c 100644 --- a/src/UI/Popup/MapillaryLinkVis.ts +++ b/src/UI/Popup/MapillaryLinkVis.ts @@ -5,7 +5,7 @@ import { Feature } from "geojson" import SvelteUIElement from "../Base/SvelteUIElement" import MapillaryLink from "../BigComponents/MapillaryLink.svelte" -export class MapillaryLinkVis implements SpecialVisualizationSvelte { +export class MapillaryLinkVis extends SpecialVisualizationSvelte { funcName = "mapillary_link" group = "web_and_communication" diff --git a/src/UI/Popup/MultiApplyViz.ts b/src/UI/Popup/MultiApplyViz.ts index edd9f47c4d..39534440f5 100644 --- a/src/UI/Popup/MultiApplyViz.ts +++ b/src/UI/Popup/MultiApplyViz.ts @@ -4,7 +4,7 @@ import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisua import SvelteUIElement from "../Base/SvelteUIElement" import MultiApplyButton from "./MultiApplyButton.svelte" -export class MultiApplyViz implements SpecialVisualization { +export class MultiApplyViz extends SpecialVisualization { funcName = "multi_apply" needsUrls = [] docs = diff --git a/src/UI/Popup/PlantNetDetectionViz.ts b/src/UI/Popup/PlantNetDetectionViz.ts index 6e7e2efbe7..979f67c0b2 100644 --- a/src/UI/Popup/PlantNetDetectionViz.ts +++ b/src/UI/Popup/PlantNetDetectionViz.ts @@ -10,7 +10,7 @@ import SvelteUIElement from "../Base/SvelteUIElement" import PlantNet from "../PlantNet/PlantNet.svelte" import { default as PlantNetCode } from "../../Logic/Web/PlantNet" -export class PlantNetDetectionViz implements SpecialVisualization { +export class PlantNetDetectionViz extends SpecialVisualization { funcName = "plantnet_detection" needsUrls = [PlantNetCode.baseUrl] group = "data_import" diff --git a/src/UI/Popup/ShareLinkViz.ts b/src/UI/Popup/ShareLinkViz.ts index fe6a921389..903722ac9c 100644 --- a/src/UI/Popup/ShareLinkViz.ts +++ b/src/UI/Popup/ShareLinkViz.ts @@ -4,7 +4,7 @@ import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../Specia import SvelteUIElement from "../Base/SvelteUIElement" import ShareButton from "../Base/ShareButton.svelte" -export class ShareLinkViz implements SpecialVisualizationSvelte { +export class ShareLinkViz extends SpecialVisualizationSvelte { funcName = "share_link" group = "default" docs = "Creates a link that (attempts to) open the native 'share'-screen" diff --git a/src/UI/Popup/UploadToOsmViz.ts b/src/UI/Popup/UploadToOsmViz.ts index 7a23f6340d..05821c4879 100644 --- a/src/UI/Popup/UploadToOsmViz.ts +++ b/src/UI/Popup/UploadToOsmViz.ts @@ -8,7 +8,7 @@ import UploadTraceToOsmUI from "../BigComponents/UploadTraceToOsmUI.svelte" /** * Wrapper around 'UploadTraceToOsmUI' */ -export class UploadToOsmViz implements SpecialVisualization { +export class UploadToOsmViz extends SpecialVisualization { funcName = "upload_to_osm" docs = "Uploads the GPS-history as GPX to OpenStreetMap.org; clears the history afterwards. The actual feature is ignored." diff --git a/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts b/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts index fa195e62f0..8a7677e391 100644 --- a/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts @@ -1,7 +1,6 @@ -import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" +import { SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" import Maproulette from "../../Logic/Maproulette" import SvelteUIElement from "../Base/SvelteUIElement" -import MaprouletteSetStatus from "../MapRoulette/MaprouletteSetStatus.svelte" import { PointImportButtonViz } from "../Popup/ImportButtons/PointImportButtonViz" import WayImportButtonViz from "../Popup/ImportButtons/WayImportButtonViz" import ConflateImportButtonViz from "../Popup/ImportButtons/ConflateImportButtonViz" @@ -17,6 +16,271 @@ import ComparisonTool from "../Comparison/ComparisonTool.svelte" import { Utils } from "../../Utils" import TagApplyViz from "./TagApplyViz" +class MaprouletteSetStatus extends SpecialVisualizationSvelte { + funcName = "maproulette_set_status" + group = "data_import" + docs = "Change the status of the given MapRoulette task" + needsUrls = [Maproulette.defaultEndpoint] + example = + " The following example sets the status to '2' (false positive)\n" + + "\n" + + "```json\n" + + "{\n" + + " \"id\": \"mark_duplicate\",\n" + + " \"render\": {\n" + + " \"special\": {\n" + + " \"type\": \"maproulette_set_status\",\n" + + " \"message\": {\n" + + " \"en\": \"Mark as not found or false positive\"\n" + + " },\n" + + " \"status\": \"2\",\n" + + " \"image\": \"close\"\n" + + " }\n" + + " }\n" + + "}\n" + + "```" + args = [ + { + name: "message", + doc: "A message to show to the user", + }, + { + name: "image", + doc: "Image to show", + defaultValue: "confirm", + }, + { + name: "message_confirm", + doc: "What to show when the task is closed, either by the user or was already closed.", + }, + { + name: "status", + doc: "A statuscode to apply when the button is clicked. 1 = `close`, 2 = `false_positive`, 3 = `skip`, 4 = `deleted`, 5 = `already fixed` (on the map, e.g. for duplicates), 6 = `too hard`", + defaultValue: "1", + }, + { + name: "maproulette_id", + doc: "The property name containing the maproulette id", + defaultValue: "mr_taskId", + }, + { + name: "ask_feedback", + doc: "If not an empty string, this will be used as question to ask some additional feedback. A text field will be added", + defaultValue: "", + }, + ] + + constr(state, tagsSource, args) { + let [ + message, + image, + message_closed, + statusToSet, + maproulette_id_key, + askFeedback, + ] = args + if (image === "") { + image = "confirm" + } + if (maproulette_id_key === "" || maproulette_id_key === undefined) { + maproulette_id_key = "mr_taskId" + } + statusToSet = statusToSet ?? "1" + return new SvelteUIElement(MaprouletteSetStatus, { + state, + tags: tagsSource, + message, + image, + message_closed, + statusToSet, + maproulette_id_key, + askFeedback, + }) + } +} + +class LinkedDataFromWebsite extends SpecialVisualization { + funcName = "linked_data_from_website" + group = "data_import" + docs = "Attempts to load (via a proxy) the specified website and parsed ld+json from there. Suitable data will be offered to import into OSM. Note: this element is added by default" + args = [ + { + name: "key", + defaultValue: "website", + doc: "Attempt to load ld+json from the specified URL. This can be in an embedded