forked from MapComplete/MapComplete
Add question box as special rendering
This commit is contained in:
parent
15664df63f
commit
d47fd7e746
42 changed files with 956 additions and 311 deletions
|
@ -5,27 +5,27 @@ import { Utils } from "../../Utils"
|
|||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { Feature } from "geojson"
|
||||
import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore"
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
|
||||
import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer.svelte"
|
||||
import TagRenderingAnswer from "../../UI/Popup/TagRendering/TagRenderingAnswer.svelte"
|
||||
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
|
||||
|
||||
export default class TitleHandler {
|
||||
constructor(
|
||||
selectedElement: Store<Feature>,
|
||||
selectedLayer: Store<LayerConfig>,
|
||||
allElements: FeaturePropertiesStore,
|
||||
layout: LayoutConfig
|
||||
state: SpecialVisualizationState
|
||||
) {
|
||||
const currentTitle: Store<string> = selectedElement.map(
|
||||
(selected) => {
|
||||
const defaultTitle = layout?.title?.txt ?? "MapComplete"
|
||||
const defaultTitle = state.layout?.title?.txt ?? "MapComplete"
|
||||
|
||||
if (selected === undefined) {
|
||||
return defaultTitle
|
||||
}
|
||||
|
||||
const tags = selected.properties
|
||||
for (const layer of layout?.layers ?? []) {
|
||||
for (const layer of state.layout?.layers ?? []) {
|
||||
if (layer.title === undefined) {
|
||||
continue
|
||||
}
|
||||
|
@ -33,7 +33,12 @@ export default class TitleHandler {
|
|||
const tagsSource =
|
||||
allElements.getStore(tags.id) ??
|
||||
new UIEventSource<Record<string, string>>(tags)
|
||||
const title = new SvelteUIElement(TagRenderingAnswer, { tags: tagsSource })
|
||||
const title = new SvelteUIElement(TagRenderingAnswer, {
|
||||
tags: tagsSource,
|
||||
state,
|
||||
selectedElement: selectedElement.data,
|
||||
layer: selectedLayer.data,
|
||||
})
|
||||
return (
|
||||
new Combine([defaultTitle, " | ", title]).ConstructElement()
|
||||
?.textContent ?? defaultTitle
|
||||
|
|
|
@ -39,7 +39,7 @@ export class And extends TagsFilter {
|
|||
return new And(ands)
|
||||
}
|
||||
|
||||
matchesProperties(tags: any): boolean {
|
||||
matchesProperties(tags: Record<string, string>): boolean {
|
||||
for (const tagsFilter of this.and) {
|
||||
if (!tagsFilter.matchesProperties(tags)) {
|
||||
return false
|
||||
|
@ -147,7 +147,7 @@ export class And extends TagsFilter {
|
|||
return [].concat(...this.and.map((subkeys) => subkeys.usedTags()))
|
||||
}
|
||||
|
||||
asChange(properties: any): { k: string; v: string }[] {
|
||||
asChange(properties: Record<string, string>): { k: string; v: string }[] {
|
||||
const result = []
|
||||
for (const tagsFilter of this.and) {
|
||||
result.push(...tagsFilter.asChange(properties))
|
||||
|
@ -375,7 +375,7 @@ export class And extends TagsFilter {
|
|||
return !this.and.some((t) => !t.isNegative())
|
||||
}
|
||||
|
||||
visit(f: (TagsFilter: any) => void) {
|
||||
visit(f: (tagsFilter: TagsFilter) => void) {
|
||||
f(this)
|
||||
this.and.forEach((sub) => sub.visit(f))
|
||||
}
|
||||
|
|
|
@ -15,11 +15,11 @@ export default class ComparingTag implements TagsFilter {
|
|||
this._representation = representation
|
||||
}
|
||||
|
||||
asChange(properties: any): { k: string; v: string }[] {
|
||||
asChange(properties: Record<string, string>): { k: string; v: string }[] {
|
||||
throw "A comparable tag can not be used to be uploaded to OSM"
|
||||
}
|
||||
|
||||
asHumanString(linkToWiki: boolean, shorten: boolean, properties: any) {
|
||||
asHumanString(linkToWiki: boolean, shorten: boolean, properties: Record<string, string>) {
|
||||
return this._key + this._representation
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ export default class ComparingTag implements TagsFilter {
|
|||
* t.matchesProperties({key: 0}) // => true
|
||||
* t.matchesProperties({differentKey: 42}) // => false
|
||||
*/
|
||||
matchesProperties(properties: any): boolean {
|
||||
matchesProperties(properties: Record<string, string>): boolean {
|
||||
return this._predicate(properties[this._key])
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ export class Or extends TagsFilter {
|
|||
return new Or(or)
|
||||
}
|
||||
|
||||
matchesProperties(properties: any): boolean {
|
||||
matchesProperties(properties: Record<string, string>): boolean {
|
||||
for (const tagsFilter of this.or) {
|
||||
if (tagsFilter.matchesProperties(properties)) {
|
||||
return true
|
||||
|
@ -82,7 +82,7 @@ export class Or extends TagsFilter {
|
|||
return [].concat(...this.or.map((subkeys) => subkeys.usedTags()))
|
||||
}
|
||||
|
||||
asChange(properties: any): { k: string; v: string }[] {
|
||||
asChange(properties: Record<string, string>): { k: string; v: string }[] {
|
||||
const result = []
|
||||
for (const tagsFilter of this.or) {
|
||||
result.push(...tagsFilter.asChange(properties))
|
||||
|
@ -260,7 +260,7 @@ export class Or extends TagsFilter {
|
|||
return this.or.some((t) => t.isNegative())
|
||||
}
|
||||
|
||||
visit(f: (TagsFilter: any) => void) {
|
||||
visit(f: (tagsFilter: TagsFilter) => void) {
|
||||
f(this)
|
||||
this.or.forEach((t) => t.visit(f))
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ export class RegexTag extends TagsFilter {
|
|||
* new RegexTag("key","value").matchesProperties({"otherkey":"value"}) // => false
|
||||
* new RegexTag("key","value",true).matchesProperties({"otherkey":"something"}) // => true
|
||||
*/
|
||||
matchesProperties(tags: any): boolean {
|
||||
matchesProperties(tags: Record<string, string>): boolean {
|
||||
if (typeof this.key === "string") {
|
||||
const value = tags[this.key] ?? ""
|
||||
return RegexTag.doesMatch(value, this.value) != this.invert
|
||||
|
@ -244,7 +244,7 @@ export class RegexTag extends TagsFilter {
|
|||
return []
|
||||
}
|
||||
|
||||
asChange(properties: any): { k: string; v: string }[] {
|
||||
asChange(properties: Record<string, string>): { k: string; v: string }[] {
|
||||
if (this.invert) {
|
||||
return []
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export default class SubstitutingTag implements TagsFilter {
|
|||
this._invert = invert
|
||||
}
|
||||
|
||||
private static substituteString(template: string, dict: any): string {
|
||||
private static substituteString(template: string, dict: Record<string, string>): string {
|
||||
for (const k in dict) {
|
||||
template = template.replace(new RegExp("\\{" + k + "\\}", "g"), dict[k])
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export default class SubstitutingTag implements TagsFilter {
|
|||
* assign.matchesProperties({"_date:now": "2021-03-29"}) // => false
|
||||
* assign.matchesProperties({"some_key": "2021-03-29"}) // => false
|
||||
*/
|
||||
matchesProperties(properties: any): boolean {
|
||||
matchesProperties(properties: Record<string, string>): boolean {
|
||||
const value = properties[this._key]
|
||||
if (value === undefined || value === "") {
|
||||
return false
|
||||
|
@ -89,7 +89,7 @@ export default class SubstitutingTag implements TagsFilter {
|
|||
return []
|
||||
}
|
||||
|
||||
asChange(properties: any): { k: string; v: string }[] {
|
||||
asChange(properties: Record<string, string>): { k: string; v: string }[] {
|
||||
if (this._invert) {
|
||||
throw "An inverted substituting tag can not be used to create a change"
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export default class SubstitutingTag implements TagsFilter {
|
|||
return false
|
||||
}
|
||||
|
||||
visit(f: (TagsFilter: any) => void) {
|
||||
visit(f: (tagsFilter: TagsFilter) => void) {
|
||||
f(this)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ export class Tag extends TagsFilter {
|
|||
* isEmpty.matchesProperties({"key": undefined}) // => true
|
||||
*
|
||||
*/
|
||||
matchesProperties(properties: any): boolean {
|
||||
matchesProperties(properties: Record<string, string>): boolean {
|
||||
const foundValue = properties[this.key]
|
||||
if (foundValue === undefined && (this.value === "" || this.value === undefined)) {
|
||||
// The tag was not found
|
||||
|
@ -62,7 +62,11 @@ export class Tag extends TagsFilter {
|
|||
t.asHumanString() // => "key=value"
|
||||
t.asHumanString(true) // => "<a href='https://wiki.openstreetmap.org/wiki/Key:key' target='_blank'>key</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:key%3Dvalue' target='_blank'>value</a>"
|
||||
*/
|
||||
asHumanString(linkToWiki?: boolean, shorten?: boolean, currentProperties?: any) {
|
||||
asHumanString(
|
||||
linkToWiki?: boolean,
|
||||
shorten?: boolean,
|
||||
currentProperties?: Record<string, string>
|
||||
) {
|
||||
let v = this.value
|
||||
if (shorten) {
|
||||
v = Utils.EllipsesAfter(v, 25)
|
||||
|
@ -134,7 +138,7 @@ export class Tag extends TagsFilter {
|
|||
return false
|
||||
}
|
||||
|
||||
visit(f: (TagsFilter) => void) {
|
||||
visit(f: (tagsFilter: TagsFilter) => void) {
|
||||
f(this)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,13 @@ export abstract class TagsFilter {
|
|||
*/
|
||||
abstract shadows(other: TagsFilter): boolean
|
||||
|
||||
abstract matchesProperties(properties: any): boolean
|
||||
abstract matchesProperties(properties: Record<string, string>): boolean
|
||||
|
||||
abstract asHumanString(linkToWiki: boolean, shorten: boolean, properties: any): string
|
||||
abstract asHumanString(
|
||||
linkToWiki: boolean,
|
||||
shorten: boolean,
|
||||
properties: Record<string, string>
|
||||
): string
|
||||
|
||||
abstract usedKeys(): string[]
|
||||
|
||||
|
@ -27,7 +31,7 @@ export abstract class TagsFilter {
|
|||
*
|
||||
* Note: properties are the already existing tags-object. It is only used in the substituting tag
|
||||
*/
|
||||
abstract asChange(properties: any): { k: string; v: string }[]
|
||||
abstract asChange(properties: Record<string, string>): { k: string; v: string }[]
|
||||
|
||||
/**
|
||||
* Returns an optimized version (or self) of this tagsFilter
|
||||
|
@ -54,5 +58,5 @@ export abstract class TagsFilter {
|
|||
/**
|
||||
* Walks the entire tree, every tagsFilter will be passed into the function once
|
||||
*/
|
||||
abstract visit(f: (TagsFilter) => void)
|
||||
abstract visit(f: (tagsFilter: TagsFilter) => void)
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ export class QueryParameters {
|
|||
return source
|
||||
}
|
||||
|
||||
public static SetDefaultFor(key: string, value: string) {
|
||||
if (QueryParameters.defaults[key] === value) {
|
||||
return
|
||||
}
|
||||
QueryParameters.defaults[key] = value
|
||||
QueryParameters.Serialize()
|
||||
}
|
||||
|
||||
public static GetBooleanQueryParameter(
|
||||
key: string,
|
||||
deflt: boolean,
|
||||
|
@ -80,6 +88,11 @@ export class QueryParameters {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query parameters of the page location
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
private static Serialize() {
|
||||
const parts = []
|
||||
for (const key of QueryParameters.order) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue