forked from MapComplete/MapComplete
refactoring: slight cleanup of tests
This commit is contained in:
parent
2e9b1016de
commit
f8d34648a0
28 changed files with 252 additions and 353 deletions
|
@ -1,5 +1,7 @@
|
|||
import LayerConfig from "./ThemeConfig/LayerConfig"
|
||||
import { UIEventSource } from "../Logic/UIEventSource"
|
||||
import UserRelatedState from "../Logic/State/UserRelatedState"
|
||||
import { Utils } from "../Utils"
|
||||
|
||||
/**
|
||||
* Indicates if a menu is open, and if so, which tab is selected;
|
||||
|
@ -61,6 +63,19 @@ export class MenuState {
|
|||
public openUsersettings(highlightTagRendering?: string) {
|
||||
this.menuIsOpened.setData(true)
|
||||
this.menuViewTab.setData("settings")
|
||||
if (
|
||||
highlightTagRendering !== undefined &&
|
||||
!UserRelatedState.availableUserSettingsIds.some((tr) => tr === highlightTagRendering)
|
||||
) {
|
||||
console.error(
|
||||
"No tagRendering with id '" + highlightTagRendering + "'; maybe you meant:",
|
||||
Utils.sortedByLevenshteinDistance(
|
||||
highlightTagRendering,
|
||||
UserRelatedState.availableUserSettingsIds,
|
||||
(x) => x
|
||||
)
|
||||
)
|
||||
}
|
||||
this.highlightedUserSetting.setData(highlightTagRendering)
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import PointRenderingConfigJson from "../Json/PointRenderingConfigJson"
|
|||
import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"
|
||||
import ValidationUtils from "./ValidationUtils"
|
||||
import { RenderingSpecification } from "../../../UI/SpecialVisualization"
|
||||
import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
|
||||
|
||||
class ExpandFilter extends DesugaringStep<LayerConfigJson> {
|
||||
private static readonly predefinedFilters = ExpandFilter.load_filters()
|
||||
|
@ -410,6 +411,62 @@ class ExpandTagRendering extends Conversion<
|
|||
}
|
||||
}
|
||||
|
||||
class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
|
||||
constructor() {
|
||||
super(
|
||||
"If no 'inline' is set on the freeform key, it will be automatically added. If no special renderings are used, it'll be set to true",
|
||||
["freeform.inline"],
|
||||
"DetectInline"
|
||||
)
|
||||
}
|
||||
|
||||
convert(
|
||||
json: QuestionableTagRenderingConfigJson,
|
||||
context: string
|
||||
): {
|
||||
result: QuestionableTagRenderingConfigJson
|
||||
errors?: string[]
|
||||
warnings?: string[]
|
||||
information?: string[]
|
||||
} {
|
||||
if (json.freeform === undefined) {
|
||||
return { result: json }
|
||||
}
|
||||
let spec: Record<string, string>
|
||||
if (typeof json.render === "string") {
|
||||
spec = { "*": json.render }
|
||||
} else {
|
||||
spec = json.render
|
||||
}
|
||||
const errors: string[] = []
|
||||
for (const key in spec) {
|
||||
if (spec[key].indexOf("<a ") >= 0) {
|
||||
// We have a link element, it probably contains something that needs to be substituted...
|
||||
// Let's play this safe and not inline it
|
||||
return { result: json }
|
||||
}
|
||||
const fullSpecification = SpecialVisualizations.constructSpecification(spec[key])
|
||||
if (fullSpecification.length > 1) {
|
||||
// We found a special rendering!
|
||||
if (json.freeform.inline === true) {
|
||||
errors.push(
|
||||
"At " +
|
||||
context +
|
||||
": 'inline' is set, but the rendering contains a special visualisation...\n " +
|
||||
spec[key]
|
||||
)
|
||||
}
|
||||
json = JSON.parse(JSON.stringify(json))
|
||||
json.freeform.inline = false
|
||||
return { result: json, errors }
|
||||
}
|
||||
}
|
||||
json = JSON.parse(JSON.stringify(json))
|
||||
json.freeform.inline ??= true
|
||||
return { result: json, errors }
|
||||
}
|
||||
}
|
||||
|
||||
export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
|
||||
constructor() {
|
||||
super(
|
||||
|
@ -1014,6 +1071,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
|
|||
new On("tagRenderings", new Each(new RewriteSpecial())),
|
||||
new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
||||
new On("tagRenderings", (layer) => new Concat(new ExpandTagRendering(state, layer))),
|
||||
new On("tagRenderings", new Each(new DetectInline())),
|
||||
new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
||||
new On<(PointRenderingConfigJson | LineRenderingConfigJson)[], LayerConfigJson>(
|
||||
"mapRendering",
|
||||
|
|
|
@ -25,13 +25,13 @@ export interface LayerConfigJson {
|
|||
*
|
||||
* If not given, will be hidden (and thus not toggable) in the layer control
|
||||
*/
|
||||
name?: string | any
|
||||
name?: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* A description for this layer.
|
||||
* Shown in the layer selections and in the personel theme
|
||||
*/
|
||||
description?: string | any
|
||||
description?: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.
|
||||
|
@ -45,49 +45,52 @@ export interface LayerConfigJson {
|
|||
source:
|
||||
| "special"
|
||||
| "special:library"
|
||||
| ({
|
||||
/**
|
||||
* Every source must set which tags have to be present in order to load the given layer.
|
||||
*/
|
||||
osmTags: TagConfigJson
|
||||
/**
|
||||
* The maximum amount of seconds that a tile is allowed to linger in the cache
|
||||
*/
|
||||
maxCacheAge?: number
|
||||
} & {
|
||||
/**
|
||||
* The actual source of the data to load, if loaded via geojson.
|
||||
*
|
||||
* # A single geojson-file
|
||||
* source: {geoJson: "https://my.source.net/some-geo-data.geojson"}
|
||||
* fetches a geojson from a third party source
|
||||
*
|
||||
* # A tiled geojson source
|
||||
* source: {geoJson: "https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson", geoJsonZoomLevel: 14}
|
||||
* to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer
|
||||
*
|
||||
* Some API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}
|
||||
*/
|
||||
geoJson: string
|
||||
/**
|
||||
* To load a tiled geojson layer, set the zoomlevel of the tiles
|
||||
*/
|
||||
geoJsonZoomLevel?: number
|
||||
/**
|
||||
* Indicates that the upstream geojson data is OSM-derived.
|
||||
* Useful for e.g. merging or for scripts generating this cache
|
||||
*/
|
||||
isOsmCache?: boolean
|
||||
/**
|
||||
* Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this
|
||||
*/
|
||||
mercatorCrs?: boolean
|
||||
/**
|
||||
* Some API's have an id-field, but give it a different name.
|
||||
* Setting this key will rename this field into 'id'
|
||||
*/
|
||||
idKey?: string
|
||||
})
|
||||
| (
|
||||
| {
|
||||
/**
|
||||
* Every source must set which tags have to be present in order to load the given layer.
|
||||
*/
|
||||
osmTags: TagConfigJson
|
||||
/**
|
||||
* The maximum amount of seconds that a tile is allowed to linger in the cache
|
||||
*/
|
||||
maxCacheAge?: number
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* The actual source of the data to load, if loaded via geojson.
|
||||
*
|
||||
* # A single geojson-file
|
||||
* source: {geoJson: "https://my.source.net/some-geo-data.geojson"}
|
||||
* fetches a geojson from a third party source
|
||||
*
|
||||
* # A tiled geojson source
|
||||
* source: {geoJson: "https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson", geoJsonZoomLevel: 14}
|
||||
* to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer
|
||||
*
|
||||
* Some API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}
|
||||
*/
|
||||
geoJson: string
|
||||
/**
|
||||
* To load a tiled geojson layer, set the zoomlevel of the tiles
|
||||
*/
|
||||
geoJsonZoomLevel?: number
|
||||
/**
|
||||
* Indicates that the upstream geojson data is OSM-derived.
|
||||
* Useful for e.g. merging or for scripts generating this cache
|
||||
*/
|
||||
isOsmCache?: boolean
|
||||
/**
|
||||
* Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this
|
||||
*/
|
||||
mercatorCrs?: boolean
|
||||
/**
|
||||
* Some API's have an id-field, but give it a different name.
|
||||
* Setting this key will rename this field into 'id'
|
||||
*/
|
||||
idKey?: string
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -212,7 +215,7 @@ export interface LayerConfigJson {
|
|||
*
|
||||
* Do _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!
|
||||
*/
|
||||
title: string | any
|
||||
title: string | Record<string, string>
|
||||
/**
|
||||
* The tags to add. It determines the icon too
|
||||
*/
|
||||
|
@ -223,7 +226,7 @@ export interface LayerConfigJson {
|
|||
*
|
||||
* (The first sentence is until the first '.'-character in the description)
|
||||
*/
|
||||
description?: string | any
|
||||
description?: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* Example images, which show real-life pictures of what such a feature might look like
|
||||
|
|
|
@ -41,23 +41,23 @@ export interface LayoutConfigJson {
|
|||
/**
|
||||
* The title, as shown in the welcome message and the more-screen.
|
||||
*/
|
||||
title: string | any
|
||||
title: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* A short description, showed as social description and in the 'more theme'-buttons.
|
||||
* Note that if this one is not defined, the first sentence of 'description' is used
|
||||
*/
|
||||
shortDescription?: string | any
|
||||
shortDescription?: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* The description, as shown in the welcome message and the more-screen
|
||||
*/
|
||||
description: string | any
|
||||
description: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* A part of the description, shown under the login-button.
|
||||
*/
|
||||
descriptionTail?: string | any
|
||||
descriptionTail?: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* The icon representing this theme.
|
||||
|
@ -196,7 +196,7 @@ export interface LayoutConfigJson {
|
|||
| string
|
||||
| {
|
||||
builtin: string | string[]
|
||||
override: any
|
||||
override: Partial<LayerConfigJson>
|
||||
/**
|
||||
* TagRenderings with any of these labels will be removed from the layer.
|
||||
* Note that the 'id' and 'group' are considered labels too
|
||||
|
|
|
@ -186,9 +186,10 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
|
|||
|
||||
/**
|
||||
* When set, influences the way a question is asked.
|
||||
* Instead of showing a full-widht text field, the text field will be shown within the rendering of the question.
|
||||
* Instead of showing a full-width text field, the text field will be shown within the rendering of the question.
|
||||
*
|
||||
* This combines badly with special input elements, as it'll distort the layout.
|
||||
* Note that this will be set automatically if no special elements are present.
|
||||
*/
|
||||
inline?: boolean
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export interface TagRenderingConfigJson {
|
|||
/**
|
||||
* A human-readable text explaining what this tagRendering does
|
||||
*/
|
||||
description?: string | any
|
||||
description?: string | Record<string, string>
|
||||
|
||||
/**
|
||||
* Renders this value. Note that "{key}"-parts are substituted by the corresponding values of the element.
|
||||
|
@ -30,7 +30,10 @@ export interface TagRenderingConfigJson {
|
|||
* Note that this is a HTML-interpreted value, so you can add links as e.g. '<a href='{website}'>{website}</a>' or include images such as `This is of type A <br><img src='typeA-icon.svg' />`
|
||||
* type: rendered
|
||||
*/
|
||||
render?: string | any
|
||||
render?:
|
||||
| string
|
||||
| Record<string, string>
|
||||
| { special: Record<string, string | Record<string, string>> & { type: string } }
|
||||
|
||||
/**
|
||||
* Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.
|
||||
|
@ -102,7 +105,7 @@ export interface TagRenderingConfigJson {
|
|||
* If not known yet, the user will be presented with `then` as an option
|
||||
* Type: rendered
|
||||
*/
|
||||
then: string | any
|
||||
then: string | Record<string, string>
|
||||
/**
|
||||
* An icon supporting this mapping; typically shown pretty small
|
||||
* Type: icon
|
||||
|
|
|
@ -322,12 +322,6 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
new TitleHandler(this.selectedElement, this.selectedLayer, this.featureProperties, this)
|
||||
new ChangeToElementsActor(this.changes, this.featureProperties)
|
||||
new PendingChangesUploader(this.changes, this.selectedElement)
|
||||
new SelectedElementTagsUpdater({
|
||||
allElements: this.featureProperties,
|
||||
changes: this.changes,
|
||||
selectedElement: this.selectedElement,
|
||||
layoutToUse: this.layout,
|
||||
osmConnection: this.osmConnection,
|
||||
})
|
||||
new SelectedElementTagsUpdater(this)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue