forked from MapComplete/MapComplete
Merge branch 'feature/levels' into develop
This commit is contained in:
commit
64d0aac88f
20 changed files with 976 additions and 522 deletions
|
@ -1,10 +1,9 @@
|
|||
import {UIEventSource} from "../../UIEventSource";
|
||||
import FilteredLayer from "../../../Models/FilteredLayer";
|
||||
import {Store, UIEventSource} from "../../UIEventSource";
|
||||
import FilteredLayer, {FilterState} from "../../../Models/FilteredLayer";
|
||||
import {FeatureSourceForLayer, Tiled} from "../FeatureSource";
|
||||
import {BBox} from "../../BBox";
|
||||
import {ElementStorage} from "../../ElementStorage";
|
||||
import {TagsFilter} from "../../Tags/TagsFilter";
|
||||
import {tag} from "@turf/turf";
|
||||
import {OsmFeature} from "../../../Models/OsmFeature";
|
||||
|
||||
export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled {
|
||||
|
@ -16,7 +15,9 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
public readonly bbox: BBox
|
||||
private readonly upstream: FeatureSourceForLayer;
|
||||
private readonly state: {
|
||||
locationControl: UIEventSource<{ zoom: number }>; selectedElement: UIEventSource<any>,
|
||||
locationControl: Store<{ zoom: number }>;
|
||||
selectedElement: Store<any>,
|
||||
globalFilters: Store<{ filter: FilterState }[]>,
|
||||
allElements: ElementStorage
|
||||
};
|
||||
private readonly _alreadyRegistered = new Set<UIEventSource<any>>();
|
||||
|
@ -25,9 +26,10 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
|
||||
constructor(
|
||||
state: {
|
||||
locationControl: UIEventSource<{ zoom: number }>,
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage
|
||||
locationControl: Store<{ zoom: number }>,
|
||||
selectedElement: Store<any>,
|
||||
allElements: ElementStorage,
|
||||
globalFilters: Store<{ filter: FilterState }[]>
|
||||
},
|
||||
tileIndex,
|
||||
upstream: FeatureSourceForLayer,
|
||||
|
@ -61,6 +63,10 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
self._is_dirty.setData(true)
|
||||
})
|
||||
|
||||
state.globalFilters.addCallback(_ => {
|
||||
self.update()
|
||||
})
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
|
@ -69,6 +75,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
const layer = this.upstream.layer;
|
||||
const features: { feature: OsmFeature; freshness: Date }[] = (this.upstream.features.data ?? []);
|
||||
const includedFeatureIds = new Set<string>();
|
||||
const globalFilters = self.state.globalFilters.data.map(f => f.filter);
|
||||
const newFeatures = (features ?? []).filter((f) => {
|
||||
|
||||
self.registerCallback(f.feature)
|
||||
|
@ -88,6 +95,14 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
|
|||
}
|
||||
}
|
||||
|
||||
for (const filter of globalFilters) {
|
||||
const neededTags: TagsFilter = filter?.currentFilter
|
||||
if (neededTags !== undefined && !neededTags.matchesProperties(f.feature.properties)) {
|
||||
// Hidden by the filter on the layer itself - we want to hide it no matter what
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
includedFeatureIds.add(f.feature.properties.id)
|
||||
return true;
|
||||
});
|
||||
|
|
|
@ -72,7 +72,7 @@ export default class CreateNewNodeAction extends OsmCreateAction {
|
|||
this.setElementId(id)
|
||||
for (const kv of this._basicTags) {
|
||||
if (typeof kv.value !== "string") {
|
||||
throw "Invalid value: don't use a regex in a preset"
|
||||
throw "Invalid value: don't use non-string value in a preset. The tag "+kv.key+"="+kv.value+" is not a string, the value is a "+typeof kv.value
|
||||
}
|
||||
properties[kv.key] = kv.value;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {FixedUiElement} from "../UI/Base/FixedUiElement";
|
|||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
|
||||
import {CountryCoder} from "latlon2country"
|
||||
import Constants from "../Models/Constants";
|
||||
import {TagUtils} from "./Tags/TagUtils";
|
||||
|
||||
|
||||
export class SimpleMetaTagger {
|
||||
|
@ -32,7 +33,7 @@ export class SimpleMetaTagger {
|
|||
if (!docs.cleanupRetagger) {
|
||||
for (const key of docs.keys) {
|
||||
if (!key.startsWith('_') && key.toLowerCase().indexOf("theme") < 0) {
|
||||
throw `Incorrect metakey ${key}: it should start with underscore (_)`
|
||||
throw `Incorrect key for a calculated meta value '${key}': it should start with underscore (_)`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -211,6 +212,27 @@ export default class SimpleMetaTaggers {
|
|||
return true;
|
||||
})
|
||||
);
|
||||
private static levels = new SimpleMetaTagger(
|
||||
{
|
||||
doc: "Extract the 'level'-tag into a normalized, ';'-separated value",
|
||||
keys: ["_level"]
|
||||
},
|
||||
((feature) => {
|
||||
if (feature.properties["level"] === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const l = feature.properties["level"]
|
||||
const newValue = TagUtils.LevelsParser(l).join(";")
|
||||
if(l === newValue) {
|
||||
return false;
|
||||
}
|
||||
feature.properties["level"] = newValue
|
||||
return true
|
||||
|
||||
})
|
||||
)
|
||||
|
||||
private static canonicalize = new SimpleMetaTagger(
|
||||
{
|
||||
doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`)",
|
||||
|
@ -218,7 +240,7 @@ export default class SimpleMetaTaggers {
|
|||
|
||||
},
|
||||
((feature, _, __, state) => {
|
||||
const units = Utils.NoNull([].concat(...state?.layoutToUse?.layers?.map(layer => layer.units )?? []));
|
||||
const units = Utils.NoNull([].concat(...state?.layoutToUse?.layers?.map(layer => layer.units) ?? []));
|
||||
if (units.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -317,7 +339,7 @@ export default class SimpleMetaTaggers {
|
|||
country_code: tags._country.toLowerCase(),
|
||||
state: undefined
|
||||
}
|
||||
}, <any> {tag_key: "opening_hours"});
|
||||
}, <any>{tag_key: "opening_hours"});
|
||||
|
||||
// Recalculate!
|
||||
return oh.getState() ? "yes" : "no";
|
||||
|
@ -327,13 +349,13 @@ export default class SimpleMetaTaggers {
|
|||
delete tags._isOpen
|
||||
tags["_isOpen"] = "parse_error";
|
||||
}
|
||||
}});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const tagsSource = state.allElements.getEventSourceById(feature.properties.id);
|
||||
|
||||
|
||||
|
||||
})
|
||||
)
|
||||
private static directionSimplified = new SimpleMetaTagger(
|
||||
|
@ -400,7 +422,8 @@ export default class SimpleMetaTaggers {
|
|||
SimpleMetaTaggers.currentTime,
|
||||
SimpleMetaTaggers.objectMetaInfo,
|
||||
SimpleMetaTaggers.noBothButLeftRight,
|
||||
SimpleMetaTaggers.geometryType
|
||||
SimpleMetaTaggers.geometryType,
|
||||
SimpleMetaTaggers.levels
|
||||
|
||||
];
|
||||
public static readonly lazyTags: string[] = [].concat(...SimpleMetaTaggers.metatags.filter(tagger => tagger.isLazy)
|
||||
|
|
|
@ -19,6 +19,19 @@ import TitleHandler from "../Actors/TitleHandler";
|
|||
import {BBox} from "../BBox";
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
|
||||
import {TiledStaticFeatureSource} from "../FeatureSource/Sources/StaticFeatureSource";
|
||||
import {Translation, TypedTranslation} from "../../UI/i18n/Translation";
|
||||
import {Tag} from "../Tags/Tag";
|
||||
|
||||
|
||||
export interface GlobalFilter {
|
||||
filter: FilterState,
|
||||
id: string,
|
||||
onNewPoint: {
|
||||
safetyCheck: Translation,
|
||||
confirmAddNew: TypedTranslation<{ preset: Translation }>
|
||||
tags: Tag[]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all the leaflet-map related state
|
||||
|
@ -78,6 +91,12 @@ export default class MapState extends UserRelatedState {
|
|||
* Which layers are enabled in the current theme and what filters are applied onto them
|
||||
*/
|
||||
public filteredLayers: UIEventSource<FilteredLayer[]> = new UIEventSource<FilteredLayer[]>([], "filteredLayers");
|
||||
|
||||
/**
|
||||
* Filters which apply onto all layers
|
||||
*/
|
||||
public globalFilters: UIEventSource<GlobalFilter[]> = new UIEventSource([], "globalFilters")
|
||||
|
||||
/**
|
||||
* Which overlays are shown
|
||||
*/
|
||||
|
@ -338,12 +357,12 @@ export default class MapState extends UserRelatedState {
|
|||
const pref = this.osmConnection
|
||||
.GetPreference(key)
|
||||
.sync(v => {
|
||||
if(v === undefined){
|
||||
if (v === undefined) {
|
||||
return undefined
|
||||
}
|
||||
return v === "true";
|
||||
}, [], b => {
|
||||
if(b === undefined){
|
||||
if (b === undefined) {
|
||||
return undefined
|
||||
}
|
||||
return "" + b;
|
||||
|
@ -354,7 +373,7 @@ export default class MapState extends UserRelatedState {
|
|||
|
||||
private InitializeFilteredLayers() {
|
||||
const layoutToUse = this.layoutToUse;
|
||||
if(layoutToUse === undefined){
|
||||
if (layoutToUse === undefined) {
|
||||
return new UIEventSource<FilteredLayer[]>([])
|
||||
}
|
||||
const flayers: FilteredLayer[] = [];
|
||||
|
@ -363,11 +382,11 @@ export default class MapState extends UserRelatedState {
|
|||
if (layer.syncSelection === "local") {
|
||||
isDisplayed = LocalStorageSource.GetParsed(layoutToUse.id + "-layer-" + layer.id + "-enabled", layer.shownByDefault)
|
||||
} else if (layer.syncSelection === "theme-only") {
|
||||
isDisplayed = this.getPref(layoutToUse.id+ "-layer-" + layer.id + "-enabled", layer)
|
||||
isDisplayed = this.getPref(layoutToUse.id + "-layer-" + layer.id + "-enabled", layer)
|
||||
} else if (layer.syncSelection === "global") {
|
||||
isDisplayed = this.getPref("layer-" + layer.id + "-enabled", layer)
|
||||
} else {
|
||||
isDisplayed = QueryParameters.GetBooleanQueryParameter("layer-" + layer.id, layer.shownByDefault, "Wether or not layer "+layer.id+" is shown")
|
||||
isDisplayed = QueryParameters.GetBooleanQueryParameter("layer-" + layer.id, layer.shownByDefault, "Wether or not layer " + layer.id + " is shown")
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ export class TagUtils {
|
|||
* @constructor
|
||||
*/
|
||||
public static TagD(json?: TagConfigJson, context: string = ""): TagsFilter | undefined {
|
||||
if(json === undefined){
|
||||
if (json === undefined) {
|
||||
return undefined
|
||||
}
|
||||
return TagUtils.Tag(json, context)
|
||||
|
@ -493,6 +493,16 @@ export class TagUtils {
|
|||
return " (" + joined + ") "
|
||||
}
|
||||
|
||||
public static ExtractSimpleTags(tf: TagsFilter) : Tag[] {
|
||||
const result: Tag[] = []
|
||||
tf.visit(t => {
|
||||
if(t instanceof Tag){
|
||||
result.push(t)
|
||||
}
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 'true' is opposite tags are detected.
|
||||
* Note that this method will never work perfectly
|
||||
|
@ -581,4 +591,38 @@ export class TagUtils {
|
|||
return listToFilter.some(tf => guards.some(guard => guard.shadows(tf)))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a level specifier to the various available levels
|
||||
*
|
||||
* TagUtils.LevelsParser("0") // => ["0"]
|
||||
* TagUtils.LevelsParser("1") // => ["1"]
|
||||
* TagUtils.LevelsParser("0;2") // => ["0","2"]
|
||||
* TagUtils.LevelsParser("0-5") // => ["0","1","2","3","4","5"]
|
||||
* TagUtils.LevelsParser("0") // => ["0"]
|
||||
* TagUtils.LevelsParser("-1") // => ["-1"]
|
||||
* TagUtils.LevelsParser("0;-1") // => ["0", "-1"]
|
||||
*/
|
||||
public static LevelsParser(level: string): string[] {
|
||||
let spec = Utils.NoNull([level])
|
||||
spec = [].concat(...spec.map(s => s?.split(";")))
|
||||
spec = [].concat(...spec.map(s => {
|
||||
s = s.trim()
|
||||
if (s.indexOf("-") < 0 || s.startsWith("-")) {
|
||||
return s
|
||||
}
|
||||
const [start, end] = s.split("-").map(s => Number(s.trim()))
|
||||
if (isNaN(start) || isNaN(end)) {
|
||||
return undefined
|
||||
}
|
||||
const values = []
|
||||
for (let i = start; i <= end; i++) {
|
||||
values.push(i + "")
|
||||
}
|
||||
return values
|
||||
}))
|
||||
return Utils.NoNull(spec);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import {Utils} from "../Utils";
|
||||
import { Utils } from "../Utils";
|
||||
|
||||
/**
|
||||
* A thin wrapper around a html element, which allows to generate a HTML-element.
|
||||
|
@ -40,8 +40,8 @@ export default abstract class BaseUIElement {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ScrollToTop(){
|
||||
this._constructedHtmlElement?.scrollTo(0,0)
|
||||
public ScrollToTop() {
|
||||
this._constructedHtmlElement?.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,11 +70,14 @@ export default abstract class BaseUIElement {
|
|||
return this;
|
||||
}
|
||||
|
||||
public RemoveClass(clss: string): BaseUIElement {
|
||||
public RemoveClass(classes: string): BaseUIElement {
|
||||
const all = classes.split(" ").map(clsName => clsName.trim());
|
||||
for (let clss of all) {
|
||||
if (this.clss.has(clss)) {
|
||||
this.clss.delete(clss);
|
||||
this._constructedHtmlElement?.classList.remove(clss)
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,22 @@ import Toggle from "../Input/Toggle";
|
|||
import MapControlButton from "../MapControlButton";
|
||||
import GeoLocationHandler from "../../Logic/Actors/GeoLocationHandler";
|
||||
import Svg from "../../Svg";
|
||||
import MapState from "../../Logic/State/MapState";
|
||||
import MapState, {GlobalFilter} from "../../Logic/State/MapState";
|
||||
import LevelSelector from "../Input/LevelSelector";
|
||||
import FeaturePipeline from "../../Logic/FeatureSource/FeaturePipeline";
|
||||
import {Utils} from "../../Utils";
|
||||
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
||||
import {RegexTag} from "../../Logic/Tags/RegexTag";
|
||||
import {Or} from "../../Logic/Tags/Or";
|
||||
import {Tag} from "../../Logic/Tags/Tag";
|
||||
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
||||
import Translations from "../i18n/Translations";
|
||||
import {BBox} from "../../Logic/BBox";
|
||||
import {OsmFeature} from "../../Models/OsmFeature";
|
||||
|
||||
export default class RightControls extends Combine {
|
||||
|
||||
constructor(state: MapState) {
|
||||
constructor(state: MapState & { featurePipeline: FeaturePipeline }) {
|
||||
|
||||
const geolocatioHandler = new GeoLocationHandler(
|
||||
state
|
||||
|
@ -38,7 +49,91 @@ export default class RightControls extends Combine {
|
|||
state.locationControl.ping();
|
||||
});
|
||||
|
||||
super([plus, min, geolocationButton].map(el => el.SetClass("m-0.5 md:m-1")))
|
||||
const levelsInView = state.currentBounds.map(bbox => {
|
||||
if (bbox === undefined) {
|
||||
return []
|
||||
}
|
||||
const allElementsUnfiltered: OsmFeature[] = [].concat(... state.featurePipeline.GetAllFeaturesAndMetaWithin(bbox).map(ff => ff.features))
|
||||
const allElements = allElementsUnfiltered.filter(f => BBox.get(f).overlapsWith(bbox))
|
||||
const allLevelsRaw: string[] = allElements.map(f => f.properties["level"])
|
||||
const allLevels = [].concat(...allLevelsRaw.map(l => TagUtils.LevelsParser(l)))
|
||||
if (allLevels.indexOf("0") < 0) {
|
||||
allLevels.push("0")
|
||||
}
|
||||
allLevels.sort((a, b) => a < b ? -1 : 1)
|
||||
return Utils.Dedup(allLevels)
|
||||
})
|
||||
state.globalFilters.data.push({
|
||||
filter: {
|
||||
currentFilter: undefined,
|
||||
state: undefined,
|
||||
|
||||
},
|
||||
id: "level",
|
||||
onNewPoint: undefined
|
||||
})
|
||||
const levelSelect = new LevelSelector(levelsInView)
|
||||
|
||||
const isShown = levelsInView.map(levelsInView => {
|
||||
if (levelsInView.length == 0) {
|
||||
return false;
|
||||
}
|
||||
if (state.locationControl.data.zoom <= 16) {
|
||||
return false;
|
||||
}
|
||||
if (levelsInView.length == 1 && levelsInView[0] == "0") {
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[state.locationControl])
|
||||
|
||||
function setLevelFilter() {
|
||||
console.log("Updating levels filter")
|
||||
const filter: GlobalFilter = state.globalFilters.data.find(gf => gf.id === "level")
|
||||
if (!isShown.data) {
|
||||
filter.filter = {
|
||||
state: "*",
|
||||
currentFilter: undefined,
|
||||
}
|
||||
filter.onNewPoint = undefined
|
||||
|
||||
} else {
|
||||
|
||||
const l = levelSelect.GetValue().data
|
||||
let neededLevel: TagsFilter = new RegexTag("level", new RegExp("(^|;)" + l + "(;|$)"));
|
||||
if (l === "0") {
|
||||
neededLevel = new Or([neededLevel, new Tag("level", "")])
|
||||
}
|
||||
filter.filter = {
|
||||
state: l,
|
||||
currentFilter: neededLevel
|
||||
}
|
||||
const t = Translations.t.general.levelSelection
|
||||
filter.onNewPoint = {
|
||||
confirmAddNew: t.confirmLevel.PartialSubs({level: l}),
|
||||
safetyCheck: t.addNewOnLevel.Subs({level: l}),
|
||||
tags: [new Tag("level", l)]
|
||||
}
|
||||
}
|
||||
state.globalFilters.ping();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
isShown.addCallbackAndRun(shown => {
|
||||
console.log("Is level selector shown?", shown)
|
||||
setLevelFilter()
|
||||
if (shown) {
|
||||
levelSelect.RemoveClass("invisible")
|
||||
} else {
|
||||
levelSelect.SetClass("invisible")
|
||||
}
|
||||
})
|
||||
|
||||
levelSelect.GetValue().addCallback(_ => setLevelFilter())
|
||||
|
||||
super([new Combine([levelSelect]).SetClass(""), plus, min, geolocationButton].map(el => el.SetClass("m-0.5 md:m-1")))
|
||||
this.SetClass("flex flex-col items-center")
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import ConfirmLocationOfPoint from "../NewPoint/ConfirmLocationOfPoint";
|
|||
import BaseLayer from "../../Models/BaseLayer";
|
||||
import Loading from "../Base/Loading";
|
||||
import Hash from "../../Logic/Web/Hash";
|
||||
import {GlobalFilter} from "../../Logic/State/MapState";
|
||||
|
||||
/*
|
||||
* The SimpleAddUI is a single panel, which can have multiple states:
|
||||
|
@ -66,7 +67,8 @@ export default class SimpleAddUI extends Toggle {
|
|||
locationControl: UIEventSource<Loc>,
|
||||
filteredLayers: UIEventSource<FilteredLayer[]>,
|
||||
featureSwitchFilter: UIEventSource<boolean>,
|
||||
backgroundLayer: UIEventSource<BaseLayer>
|
||||
backgroundLayer: UIEventSource<BaseLayer>,
|
||||
globalFilters: UIEventSource<GlobalFilter[]>
|
||||
},
|
||||
takeLocationFrom?: UIEventSource<{lat: number, lon: number}>
|
||||
) {
|
||||
|
|
70
UI/Input/LevelSelector.ts
Normal file
70
UI/Input/LevelSelector.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import {InputElement} from "./InputElement";
|
||||
import {Store, Stores, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Combine from "../Base/Combine";
|
||||
import Slider from "./Slider";
|
||||
import {ClickableToggle} from "./Toggle";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
|
||||
export default class LevelSelector extends VariableUiElement implements InputElement<string> {
|
||||
|
||||
private readonly _value: UIEventSource<string>;
|
||||
|
||||
constructor(currentLevels: Store<string[]>, options?: {
|
||||
value?: UIEventSource<string>
|
||||
}) {
|
||||
const value = options?.value ?? new UIEventSource<string>(undefined)
|
||||
super(Stores.ListStabilized(currentLevels).map(levels => {
|
||||
console.log("CUrrent levels are", levels)
|
||||
let slider = new Slider(0, levels.length - 1, {vertical: true});
|
||||
const toggleClass = "flex border-2 border-blue-500 w-10 h-10 place-content-center items-center border-box"
|
||||
slider.SetClass("flex elevator w-10").SetStyle(`height: ${2.5 * levels.length}rem; background: #00000000`)
|
||||
|
||||
const values = levels.map((data, i) => new ClickableToggle(
|
||||
new FixedUiElement(data).SetClass("font-bold active bg-subtle " + toggleClass),
|
||||
new FixedUiElement(data).SetClass("normal-background " + toggleClass),
|
||||
slider.GetValue().sync(
|
||||
(sliderVal) => {
|
||||
return sliderVal === i
|
||||
},
|
||||
[],
|
||||
(isSelected) => {
|
||||
return isSelected ? i : slider.GetValue().data
|
||||
}
|
||||
))
|
||||
.ToggleOnClick()
|
||||
.SetClass("flex w-10 h-10"))
|
||||
|
||||
values.reverse(/* This is a new list, no side-effects */)
|
||||
const combine = new Combine([new Combine(values), slider])
|
||||
combine.SetClass("flex flex-row overflow-hidden");
|
||||
|
||||
|
||||
slider.GetValue().addCallbackAndRun(i => {
|
||||
if (currentLevels?.data === undefined) {
|
||||
return
|
||||
}
|
||||
value.setData(currentLevels?.data[i]);
|
||||
})
|
||||
value.addCallback(level => {
|
||||
const i = currentLevels?.data?.findIndex(l => l === level)
|
||||
slider.GetValue().setData(i)
|
||||
})
|
||||
return combine
|
||||
}))
|
||||
|
||||
this._value = value
|
||||
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<string> {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
IsValid(t: string): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -4,9 +4,10 @@ import {UIEventSource} from "../../Logic/UIEventSource";
|
|||
export default class Slider extends InputElement<number> {
|
||||
|
||||
private readonly _value: UIEventSource<number>
|
||||
private min: number;
|
||||
private max: number;
|
||||
private step: number;
|
||||
private readonly min: number;
|
||||
private readonly max: number;
|
||||
private readonly step: number;
|
||||
private readonly vertical: boolean;
|
||||
|
||||
/**
|
||||
* Constructs a slider input element for natural numbers
|
||||
|
@ -16,13 +17,15 @@ export default class Slider extends InputElement<number> {
|
|||
*/
|
||||
constructor(min: number, max: number, options?: {
|
||||
value?: UIEventSource<number>,
|
||||
step?: 1 | number
|
||||
step?: 1 | number,
|
||||
vertical?: false | boolean
|
||||
}) {
|
||||
super();
|
||||
this.max = max;
|
||||
this.min = min;
|
||||
this._value = options?.value ?? new UIEventSource<number>(min)
|
||||
this.step = options?.step ?? 1;
|
||||
this.vertical = options?.vertical ?? false;
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<number> {
|
||||
|
@ -39,6 +42,10 @@ export default class Slider extends InputElement<number> {
|
|||
el.oninput = () => {
|
||||
valuestore.setData(Number(el.value))
|
||||
}
|
||||
if(this.vertical){
|
||||
el.classList.add("vertical")
|
||||
el.setAttribute('orient','vertical'); // firefox only workaround...
|
||||
}
|
||||
valuestore.addCallbackAndRunD(v => el.value = ""+valuestore.data)
|
||||
return el;
|
||||
}
|
||||
|
|
|
@ -15,12 +15,16 @@ import SimpleAddUI, {PresetInfo} from "../BigComponents/SimpleAddUI";
|
|||
import BaseLayer from "../../Models/BaseLayer";
|
||||
import Img from "../Base/Img";
|
||||
import Title from "../Base/Title";
|
||||
import {GlobalFilter} from "../../Logic/State/MapState";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import {Tag} from "../../Logic/Tags/Tag";
|
||||
|
||||
export default class ConfirmLocationOfPoint extends Combine {
|
||||
|
||||
|
||||
constructor(
|
||||
state: {
|
||||
globalFilters: UIEventSource<GlobalFilter[]>;
|
||||
featureSwitchIsTesting: UIEventSource<boolean>;
|
||||
osmConnection: OsmConnection,
|
||||
featurePipeline: FeaturePipeline,
|
||||
|
@ -106,7 +110,11 @@ export default class ConfirmLocationOfPoint extends Combine {
|
|||
).SetClass("font-bold break-words")
|
||||
.onClick(() => {
|
||||
console.log("The confirmLocationPanel - precise input yielded ", preciseInput?.GetValue()?.data)
|
||||
confirm(preset.tags, preciseInput?.GetValue()?.data ?? loc, preciseInput?.snappedOnto?.data?.properties?.id);
|
||||
const globalFilterTagsToAdd: Tag[][] = state.globalFilters.data.filter(gf => gf.onNewPoint !== undefined)
|
||||
.map(gf => gf.onNewPoint.tags)
|
||||
const globalTags : Tag[] = [].concat(...globalFilterTagsToAdd)
|
||||
console.log("Global tags to add are: ", globalTags)
|
||||
confirm([...preset.tags, ...globalTags], preciseInput?.GetValue()?.data ?? loc, preciseInput?.snappedOnto?.data?.properties?.id);
|
||||
});
|
||||
|
||||
if (preciseInput !== undefined) {
|
||||
|
@ -126,7 +134,7 @@ export default class ConfirmLocationOfPoint extends Combine {
|
|||
.onClick(() => filterViewIsOpened.setData(true))
|
||||
|
||||
|
||||
const openLayerOrConfirm = new Toggle(
|
||||
let openLayerOrConfirm = new Toggle(
|
||||
confirmButton,
|
||||
openLayerControl,
|
||||
preset.layerToAddTo.isDisplayed
|
||||
|
@ -152,6 +160,29 @@ export default class ConfirmLocationOfPoint extends Combine {
|
|||
closePopup()
|
||||
})
|
||||
|
||||
|
||||
// We assume the number of global filters won't change during the run of the program
|
||||
for (let i = 0; i < state.globalFilters.data.length; i++) {
|
||||
const hasBeenCheckedOf = new UIEventSource(false);
|
||||
|
||||
const filterConfirmPanel = new VariableUiElement(
|
||||
state.globalFilters.map(gfs => {
|
||||
const gf = gfs[i]
|
||||
const confirm = gf.onNewPoint?.confirmAddNew?.Subs({preset: preset.title})
|
||||
return new Combine([
|
||||
gf.onNewPoint?.safetyCheck,
|
||||
new SubtleButton(Svg.confirm_svg(), confirm).onClick(() => hasBeenCheckedOf.setData(true))
|
||||
])
|
||||
}
|
||||
))
|
||||
|
||||
|
||||
openLayerOrConfirm = new Toggle(
|
||||
openLayerOrConfirm, filterConfirmPanel,
|
||||
state.globalFilters.map(f => hasBeenCheckedOf.data || f[i]?.onNewPoint === undefined, [hasBeenCheckedOf])
|
||||
)
|
||||
}
|
||||
|
||||
const hasActiveFilter = preset.layerToAddTo.appliedFilters
|
||||
.map(appliedFilters => {
|
||||
const activeFilters = Array.from(appliedFilters.values()).filter(f => f?.currentFilter !== undefined);
|
||||
|
@ -172,10 +203,10 @@ export default class ConfirmLocationOfPoint extends Combine {
|
|||
).onClick(cancel)
|
||||
|
||||
|
||||
let examples : BaseUIElement = undefined;
|
||||
if(preset.exampleImages !== undefined && preset.exampleImages.length > 0){
|
||||
let examples: BaseUIElement = undefined;
|
||||
if (preset.exampleImages !== undefined && preset.exampleImages.length > 0) {
|
||||
examples = new Combine([
|
||||
new Title( preset.exampleImages.length == 1 ? Translations.t.general.example : Translations.t.general.examples),
|
||||
new Title(preset.exampleImages.length == 1 ? Translations.t.general.example : Translations.t.general.examples),
|
||||
new Combine(preset.exampleImages.map(img => new Img(img).SetClass("h-64 m-1 w-auto rounded-lg"))).SetClass("flex flex-wrap items-stretch")
|
||||
])
|
||||
|
||||
|
|
|
@ -319,4 +319,17 @@ export class TypedTranslation<T> extends Translation {
|
|||
}
|
||||
|
||||
|
||||
PartialSubs<X extends string>(text: Partial<T> & Record<X, string>): TypedTranslation<Omit<T, X>> {
|
||||
const newTranslations : Record<string, string> = {}
|
||||
for (const lang in this.translations) {
|
||||
const template = this.translations[lang]
|
||||
if(lang === "_context"){
|
||||
newTranslations[lang] = template
|
||||
continue
|
||||
}
|
||||
newTranslations[lang] = Utils.SubstituteKeys(template, text, lang)
|
||||
}
|
||||
|
||||
return new TypedTranslation<Omit<T, X>>(newTranslations, this.context)
|
||||
}
|
||||
}
|
78
assets/svg/elevator.svg
Normal file
78
assets/svg/elevator.svg
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="图层_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 65.9 66"
|
||||
style="enable-background:new 0 0 65.9 66;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="elevator.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs33">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</defs><sodipodi:namedview
|
||||
id="namedview31"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#111111"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="61.063924"
|
||||
inkscape:cx="32.105699"
|
||||
inkscape:cy="40.138265"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1007"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="图层_1" />
|
||||
<path
|
||||
d="M 48.2,15.6 H 19.3 c -1.6,0 -2.8,1.3 -2.8,2.8 v 29 c 0,1.6 1.3,2.8 2.8,2.8 h 28.9 c 1.6,0 2.8,-1.3 2.8,-2.8 V 18.5 C 51,17 49.7,15.6 48.2,15.6 Z m 0.3,30.7 c 0,0.8 -0.6,1.4 -1.4,1.4 H 20.4 C 19.6,47.7 19,47.1 19,46.3 V 19.6 c 0,-0.8 0.6,-1.4 1.4,-1.4 h 26.7 c 0.8,0 1.4,0.6 1.4,1.4 z"
|
||||
id="path2" /><polygon
|
||||
points="29.4,9.5 33.7,5.5 38.1,9.5 35.3,9.5 35.3,13.5 32.2,13.5 32.2,9.5 "
|
||||
id="polygon8" /><polygon
|
||||
points="38.1,56.6 33.7,60.5 29.4,56.6 32.2,56.6 32.2,52.5 35.3,52.5 35.3,56.6 "
|
||||
id="polygon10" /><circle
|
||||
cx="28.6"
|
||||
cy="21.4"
|
||||
r="1.9"
|
||||
id="circle12" /><path
|
||||
d="m 29.1,35.6 c 0,-0.2 -0.2,-0.5 -0.5,-0.5 -0.3,0 -0.5,0.2 -0.5,0.5 v 1.7 3 5 c 0,0.6 -0.6,1.2 -1.2,1.2 -0.6,0 -1.2,-0.5 -1.2,-1.2 V 40.5 37.3 33.2 32 28.2 28.3 c 0,-0.2 -0.1,-0.4 -0.4,-0.4 -0.2,0 -0.4,0.2 -0.4,0.4 v 1.3 3.5 1.8 c 0,0.4 -0.3,0.7 -0.7,0.7 -0.4,0 -0.7,-0.3 -0.7,-0.7 v -1 -3.5 -4.2 c 0,-1 0.8,-1.9 1.9,-1.9 h 5.2 0.3 c 0.2,0 0.5,0.1 0.6,0.3 l 2.1,2.1 2.5,-2.5 c 0.4,-0.4 1,-0.4 1.3,0 0.4,0.4 0.4,1 0,1.3 l -3.2,3.2 C 34,28.9 33.8,29 33.5,29 33.3,29 33,28.9 32.8,28.7 L 32,27.9 31.8,27.8 h -0.2 c -0.2,0 -0.4,0.2 -0.4,0.4 v 1.6 10.6 l 7.68e-4,4.906766 c 9.4e-5,0.6 -0.6,1.2 -1.2,1.2 -0.6,0 -0.957071,-0.484801 -0.957071,-1.184801 0,0 0.0563,-6.496244 0.0563,-9.721965 z"
|
||||
id="path14"
|
||||
sodipodi:nodetypes="cssccsssccccccssccsssccsscsccsccsssccssccsscc" /><circle
|
||||
cx="42.400002"
|
||||
cy="21"
|
||||
r="1.5"
|
||||
id="circle16" /><circle
|
||||
cx="42.400002"
|
||||
cy="24.5"
|
||||
r="1.5"
|
||||
id="circle18" /><circle
|
||||
cx="42.400002"
|
||||
cy="28.200001"
|
||||
r="1.5"
|
||||
id="circle20" />
|
||||
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -1 +1,76 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 228.57 239.29"><defs><style>.cls-1{fill:#1d1d1b;}</style></defs><path class="cls-1" d="M208.18,119.08V11.93c0-5.24,0-5.24,5.15-5.24,2.43,0,4.87,0,7.31,0,2.05,0,3.12.76,3,2.92-.07,1.13,0,2.27,0,3.4q0,106.5,0,213c0,.69-.06,1.39,0,2.09.13,1.9-.73,2.68-2.62,2.64-3.39-.05-6.79,0-10.19,0-1.84,0-2.73-.76-2.66-2.67s0-4,0-6Z"/><path class="cls-1" d="M20,119.06V226.75c0,3.9,0,3.92-3.91,4-3,0-5.93-.05-8.89,0-1.76,0-2.58-.7-2.55-2.47s0-3.31,0-5q0-106.12,0-212.25c0-4.17.22-4.39,4.45-4.36,2.52,0,5.05.08,7.58,0,2.26-.09,3.47.67,3.32,3.13-.1,1.47,0,3,0,4.44q0,52.41,0,104.82Z"/><path class="cls-1" d="M135.46,156.52a4.35,4.35,0,0,0-4.86-3.21,12.64,12.64,0,0,0-2.44.73c-2.07.72-4.13,1.47-6.22,2.21l-.26-.54q-1.94-4.52-3.88-9c-1.77-4.11-3.53-8.22-5.32-12.31a4.21,4.21,0,0,0-4.06-2.71c-4.84-.06-9.68-.07-14.52-.11L81,131.46c-.18,0-.5-.09-.52-.19-.16-.78-.27-1.58-.4-2.42H99.2c.35,0,.69,0,1,0a4.41,4.41,0,0,0,3.41-6.75,4.58,4.58,0,0,0-4.22-2.1q-10,0-20,0h-.72c-.52-3.24-1-6.39-1.54-9.56h-9c.55,3.45,1.11,6.9,1.66,10.35.83,5.11,1.71,10.2,2.47,15.32a4.76,4.76,0,0,0,4.92,4.29c9.22,0,18.45.11,27.68.15a.86.86,0,0,1,.91.61q4.72,11.05,9.48,22.08a4.49,4.49,0,0,0,6.12,2.69c3.69-1.31,7.39-2.61,11.07-3.95a6.74,6.74,0,0,0,1.67-1,4.71,4.71,0,0,0,1.49-2.56v-1.48C135.55,156.8,135.5,156.66,135.46,156.52Z"/><path class="cls-1" d="M53.61,145.09c.2-1.23.33-2.47.59-3.69a26.58,26.58,0,0,1,6.42-12.56,4.42,4.42,0,0,1,6.63,5.85,18.7,18.7,0,0,0-4.46,8.95,18.32,18.32,0,0,0,34.75,10.84,4.62,4.62,0,0,1,3.67-3,4.41,4.41,0,0,1,4.76,5.84,23.53,23.53,0,0,1-3.45,6.12,26.77,26.77,0,0,1-14.83,10c-1.46.38-3,.53-4.47.79l-.56.11H78.9c-.14,0-.29-.08-.43-.1a34.79,34.79,0,0,1-3.7-.6c-11-2.89-17.86-9.91-20.58-20.95-.29-1.19-.39-2.43-.58-3.64Z"/><ellipse class="cls-1" cx="72.62" cy="109.74" rx="4.51" ry="3.94"/><circle class="cls-1" cx="71.76" cy="95.49" r="8.93"/><path class="cls-1" d="M157.33,131.79H154v1.75q0,18,0,36c0,2.4-1,3.89-2.94,4.52a4.17,4.17,0,0,1-5.43-3.17,10.86,10.86,0,0,1-.13-2q0-31,0-61.93v-2.49h-2c0,.48-.07,1-.07,1.47,0,7.32,0,14.65,0,22,0,2.28-1.42,3.66-3.4,3.39a3,3,0,0,1-2.63-3.33c0-5.24,0-10.47,0-15.7,0-4.38,0-8.75,0-13.13,0-5.09,2.76-7.89,7.83-7.92q10.48-.06,21,0c4.89,0,7.67,2.88,7.67,7.77q0,14.49,0,29c0,2.3-1.56,3.7-3.6,3.31-1.57-.3-2.41-1.44-2.41-3.35q0-10.84,0-21.69v-1.76h-2v1.76q0,31.32,0,62.64a10.81,10.81,0,0,1-.17,2.13,4.23,4.23,0,0,1-4.41,3.27,4.18,4.18,0,0,1-3.9-4c0-2.95,0-5.9,0-8.84V131.79Z"/><path class="cls-1" d="M155.74,89.56a9,9,0,0,1-9.1-9,9,9,0,0,1,18,0A9,9,0,0,1,155.74,89.56Z"/><path class="cls-1" d="M191.93,36.94h-71V24.12h10l-17-17-17,17h10V36.94h-71a5.83,5.83,0,0,0-5.83,5.83V197.05a5.83,5.83,0,0,0,5.83,5.83h71V215.7h-10l17,17,17-17h-10V202.88h71a5.83,5.83,0,0,0,5.83-5.83V42.77A5.83,5.83,0,0,0,191.93,36.94Zm-7.5,147a5.83,5.83,0,0,1-5.83,5.84H49.22a5.83,5.83,0,0,1-5.83-5.84V56a5.83,5.83,0,0,1,5.83-5.83H178.6A5.83,5.83,0,0,1,184.43,56Z"/></svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="Layer_1"
|
||||
data-name="Layer 1"
|
||||
viewBox="0 0 228.57 239.29"
|
||||
version="1.1"
|
||||
sodipodi:docname="elevator_wheelchair.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview25"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#111111"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.9145025"
|
||||
inkscape:cx="60.851318"
|
||||
inkscape:cy="68.425087"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1007"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<style
|
||||
id="style2">.cls-1{fill:#1d1d1b;}</style>
|
||||
</defs>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 146.05301,172.90366 a 6.4729946,6.4729946 0 0 0 -7.2319,-4.77662 18.808885,18.808885 0 0 0 -3.63083,1.08627 c -3.08025,1.07139 -6.14562,2.18743 -9.25563,3.28858 l -0.3869,-0.80354 q -2.8868,-6.72597 -5.77361,-13.39241 c -2.63384,-6.11586 -5.2528,-12.23172 -7.9164,-18.31783 a 6.2646683,6.2646683 0 0 0 -6.04146,-4.0326 c -7.202135,-0.0893 -14.404272,-0.10416 -21.606408,-0.16368 l -19.195777,-0.17857 c -0.267848,0 -0.744022,-0.13392 -0.773783,-0.28273 -0.238087,-1.16067 -0.401772,-2.35111 -0.595218,-3.60107 h 28.451415 c 0.520816,0 1.026751,0 1.488045,0 a 6.5622772,6.5622772 0 0 0 5.074232,-10.0443 6.8152448,6.8152448 0 0 0 -6.279548,-3.12489 q -14.880448,0 -29.760895,0 H 61.546951 C 60.773168,113.739 60.058906,109.05166 59.255362,104.33456 H 45.862959 c 0.818425,5.13375 1.65173,10.26751 2.470155,15.40126 1.235077,7.60391 2.544556,15.17806 3.67547,22.79685 a 7.0830929,7.0830929 0 0 0 7.32118,6.38371 c 13.719773,0 27.454425,0.16369 41.189076,0.22321 a 1.2797185,1.2797185 0 0 1 1.35412,0.9077 q 7.02357,16.4429 14.10667,32.85603 a 6.6813208,6.6813208 0 0 0 9.10683,4.00284 c 5.49089,-1.94934 10.99665,-3.88379 16.47266,-5.87777 a 10.029421,10.029421 0 0 0 2.48503,-1.48805 7.0086907,7.0086907 0 0 0 2.21719,-3.80939 v -2.20231 c -0.0744,-0.20833 -0.14881,-0.41665 -0.20833,-0.62498 z"
|
||||
id="path10"
|
||||
style="stroke-width:1.48804" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 24.25655,155.89531 c 0.297609,-1.83029 0.491055,-3.67547 0.877946,-5.49088 a 39.552229,39.552229 0 0 1 9.553248,-18.68985 6.5785825,6.5785825 0 0 1 9.865736,8.70507 27.826436,27.826436 0 0 0 -6.636679,13.318 27.260979,27.260979 0 0 0 51.709554,16.1304 6.8747666,6.8747666 0 0 1 5.461124,-4.46413 6.5622772,6.5622772 0 0 1 7.083091,8.69018 35.013692,35.013692 0 0 1 -5.133752,9.10683 39.834957,39.834957 0 0 1 -22.067704,14.88045 c -2.172545,0.56546 -4.464134,0.78866 -6.65156,1.17555 l -0.833305,0.16369 h -5.595048 c -0.208326,0 -0.431533,-0.11905 -0.639859,-0.14881 a 51.769076,51.769076 0 0 1 -5.505766,-0.89282 c -16.368492,-4.30045 -26.576478,-14.74653 -30.62396,-31.17454 -0.431533,-1.77077 -0.580337,-3.61595 -0.863066,-5.41648 z"
|
||||
id="path12"
|
||||
style="stroke-width:1.48804" />
|
||||
<ellipse
|
||||
class="cls-1"
|
||||
cx="52.544285"
|
||||
cy="103.29292"
|
||||
rx="6.711082"
|
||||
ry="5.8628964"
|
||||
id="ellipse14"
|
||||
style="stroke-width:1.48804" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="51.264565"
|
||||
cy="82.088287"
|
||||
r="13.288239"
|
||||
id="circle16"
|
||||
style="stroke-width:1.48804" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 178.59655,136.10432 h -4.95519 v 2.60407 q 0,26.78481 0,53.56961 c 0,3.57131 -1.48804,5.7885 -4.37485,6.72597 a 6.2051465,6.2051465 0 0 1 -8.08008,-4.71711 16.160166,16.160166 0 0 1 -0.19345,-2.97609 q 0,-46.12938 0,-92.154605 v -3.705232 h -2.97609 c 0,0.714262 -0.10416,1.488045 -0.10416,2.187426 0,10.892491 0,21.799851 0,32.736981 0,3.39275 -2.11303,5.44625 -5.05935,5.04447 a 4.4641342,4.4641342 0 0 1 -3.91356,-4.95518 c 0,-7.79736 0,-15.57983 0,-23.36231 0,-6.51763 0,-13.020388 0,-19.538024 0,-7.574147 4.107,-11.740672 11.65139,-11.785314 q 15.59471,-0.08928 31.24894,0 c 7.27654,0 11.4133,4.285569 11.4133,11.562108 q 0,21.56177 0,43.1533 c 0,3.4225 -2.32135,5.50576 -5.35696,4.92542 -2.33623,-0.44641 -3.58619,-2.14278 -3.58619,-4.98495 q 0,-16.1304 0,-32.275685 v -2.618959 h -2.97609 v 2.618959 q 0,46.605565 0,93.211125 a 16.085763,16.085763 0 0 1 -0.25297,3.16953 6.2944292,6.2944292 0 0 1 -6.56227,4.86591 6.2200269,6.2200269 0 0 1 -5.80338,-5.95218 c 0,-4.38973 0,-8.77946 0,-13.15432 v -44.19492 z"
|
||||
id="path18"
|
||||
style="stroke-width:1.48804" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 176.23056,73.264187 a 13.392403,13.392403 0 0 1 -13.54121,-13.392403 13.392405,13.392405 0 0 1 26.78481,0 13.392403,13.392403 0 0 1 -13.2436,13.392403 z"
|
||||
id="path20"
|
||||
style="stroke-width:1.48804" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M 226.27477,0.4068479 H 124.01222 V -18.058024 H 138.4154 L 113.93,-42.543423 89.444601,-18.058024 H 103.84778 V 0.4068479 H 1.5852264 A 8.3970517,8.3970517 0 0 0 -6.8118252,8.8038996 V 231.0161 a 8.3970517,8.3970517 0 0 0 8.3970516,8.39705 H 103.84778 v 18.46487 H 89.444601 l 24.485399,24.4854 24.4854,-24.4854 h -14.40318 v -18.46487 h 102.26255 a 8.3970517,8.3970517 0 0 0 8.39706,-8.39705 V 8.8038996 A 8.3970517,8.3970517 0 0 0 226.27477,0.4068479 Z M 215.47239,212.13354 a 8.3970517,8.3970517 0 0 1 -8.39705,8.41145 H 20.727047 a 8.3970517,8.3970517 0 0 1 -8.397051,-8.41145 V 27.859302 A 8.3970517,8.3970517 0 0 1 20.727047,19.46225 H 207.07534 a 8.3970517,8.3970517 0 0 1 8.39705,8.397052 z"
|
||||
id="path22"
|
||||
style="stroke-width:1.44032" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 5.6 KiB |
|
@ -387,9 +387,19 @@
|
|||
],
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"path": "elevator.svg",
|
||||
"license": "CC-BY-SA 4.0",
|
||||
"authors": [
|
||||
"Yveltal"
|
||||
],
|
||||
"sources": [
|
||||
"https://commons.wikimedia.org/wiki/File:HZM_elevator_icon.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "elevator_wheelchair.svg",
|
||||
"license": "CC-BY_SA",
|
||||
"license": "CC-BY-SA",
|
||||
"authors": [
|
||||
"Robin Julien"
|
||||
],
|
||||
|
|
|
@ -1110,10 +1110,6 @@ video {
|
|||
height: 12rem;
|
||||
}
|
||||
|
||||
.max-h-screen {
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.max-h-7 {
|
||||
max-height: 1.75rem;
|
||||
}
|
||||
|
@ -1302,6 +1298,10 @@ video {
|
|||
flex-wrap: wrap-reverse;
|
||||
}
|
||||
|
||||
.place-content-center {
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
.content-start {
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
@ -1481,6 +1481,11 @@ video {
|
|||
border-color: rgba(252, 165, 165, var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-blue-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgba(59, 130, 246, var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-gray-200 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgba(229, 231, 235, var(--tw-border-opacity));
|
||||
|
@ -1510,6 +1515,11 @@ video {
|
|||
background-color: rgba(224, 231, 255, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-black {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
|
||||
|
@ -1530,11 +1540,6 @@ video {
|
|||
background-color: rgba(209, 213, 219, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-200 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(254, 202, 202, var(--tw-bg-opacity));
|
||||
|
@ -1857,15 +1862,11 @@ video {
|
|||
}
|
||||
|
||||
.z-above-map {
|
||||
z-index: 10000
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.z-above-controls {
|
||||
z-index: 10001
|
||||
}
|
||||
|
||||
.w-160 {
|
||||
width: 40rem;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.bg-subtle {
|
||||
|
@ -1892,14 +1893,14 @@ video {
|
|||
* Base colour of interactive elements, mainly the 'subtle button'
|
||||
*
|
||||
*/
|
||||
--subtle-detail-color: #DBEAFE;
|
||||
--subtle-detail-color: #dbeafe;
|
||||
--subtle-detail-color-contrast: black;
|
||||
--subtle-detail-color-light-contrast: lightgrey;
|
||||
/**
|
||||
* A stronger variant of the 'subtle-detail-colour'
|
||||
* Used as subtle button hover
|
||||
*/
|
||||
--unsubtle-detail-color: #BFDBFE;
|
||||
--unsubtle-detail-color: #bfdbfe;
|
||||
--unsubtle-detail-color-contrast: black;
|
||||
--catch-detail-color: #3a3aeb;
|
||||
--catch-detail-color-contrast: white;
|
||||
|
@ -1913,7 +1914,8 @@ video {
|
|||
--variable-title-height: 0px;
|
||||
}
|
||||
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
min-height: -webkit-fill-available;
|
||||
|
@ -1921,7 +1923,7 @@ html, body {
|
|||
padding: 0;
|
||||
background-color: var(--background-color);
|
||||
color: var(--foreground-color);
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
font-family: "Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
|
||||
.leaflet-overlay-pane .leaflet-zoom-animated {
|
||||
|
@ -1944,7 +1946,8 @@ html, body {
|
|||
height: 100% !important;
|
||||
}
|
||||
|
||||
svg, img {
|
||||
svg,
|
||||
img {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -2048,6 +2051,35 @@ a {
|
|||
height: min-content;
|
||||
}
|
||||
|
||||
/* slider */
|
||||
|
||||
input[type="range"].vertical {
|
||||
-webkit-writing-mode: bt-lr;
|
||||
-ms-writing-mode: bt-lr;
|
||||
writing-mode: bt-lr;
|
||||
/* IE */
|
||||
-webkit-appearance: slider-vertical;
|
||||
/* Chromium */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
input[type="range"].elevator::-moz-range-thumb {
|
||||
background-color: #00000000 !important;
|
||||
background-image: url("/assets/svg/elevator_wheelchair.svg");
|
||||
width: 150px !important;
|
||||
height: 30px !important;
|
||||
border: 2px;
|
||||
border-style: solid;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
border-image: linear-gradient(to right, black 50%, transparent 50%) 100% 1;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.border-detail {
|
||||
border-color: var(--foreground-color);
|
||||
}
|
||||
|
@ -2117,7 +2149,7 @@ p {
|
|||
}
|
||||
|
||||
li::marker {
|
||||
content: "•"
|
||||
content: "•";
|
||||
}
|
||||
|
||||
.subtle-background {
|
||||
|
@ -2127,7 +2159,7 @@ li::marker {
|
|||
|
||||
.normal-background {
|
||||
background: var(--background-color);
|
||||
color: var(--foreground-color)
|
||||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
.subtle-lighter {
|
||||
|
@ -2205,7 +2237,8 @@ li::marker {
|
|||
color: unset !important;
|
||||
}
|
||||
|
||||
.disable-links a.must-link, .disable-links .must-link a {
|
||||
.disable-links a.must-link,
|
||||
.disable-links .must-link a {
|
||||
/* Hide links if they are disabled */
|
||||
display: none;
|
||||
}
|
||||
|
@ -2424,7 +2457,7 @@ li::marker {
|
|||
/***************** Info box (box containing features and questions ******************/
|
||||
|
||||
input {
|
||||
color: var(--foreground-color)
|
||||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
.leaflet-popup-content {
|
||||
|
@ -2485,7 +2518,7 @@ input {
|
|||
}
|
||||
|
||||
.animate-height {
|
||||
transition: max-height .5s ease-in-out;
|
||||
transition: max-height 0.5s ease-in-out;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
|
@ -2549,7 +2582,7 @@ input {
|
|||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.mapping-icon-large{
|
||||
.mapping-icon-large {
|
||||
/* A mapping icon type */
|
||||
width: 6rem;
|
||||
max-height: 5rem;
|
||||
|
@ -2855,4 +2888,3 @@ input {
|
|||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
75
index.css
75
index.css
|
@ -14,11 +14,11 @@
|
|||
@layer utilities {
|
||||
@variants responsive {
|
||||
.z-above-map {
|
||||
z-index: 10000
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.z-above-controls {
|
||||
z-index: 10001
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.w-160 {
|
||||
|
@ -50,10 +50,8 @@
|
|||
border-top-right-radius: 999rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
:root {
|
||||
/* The main colour scheme of mapcomplete is configured here.
|
||||
* For a custom styling, set 'customCss' in your layoutConfig and overwrite some of these.
|
||||
|
@ -71,7 +69,7 @@
|
|||
* Base colour of interactive elements, mainly the 'subtle button'
|
||||
*
|
||||
*/
|
||||
--subtle-detail-color: #DBEAFE;
|
||||
--subtle-detail-color: #dbeafe;
|
||||
--subtle-detail-color-contrast: black;
|
||||
--subtle-detail-color-light-contrast: lightgrey;
|
||||
|
||||
|
@ -79,14 +77,12 @@
|
|||
* A stronger variant of the 'subtle-detail-colour'
|
||||
* Used as subtle button hover
|
||||
*/
|
||||
--unsubtle-detail-color: #BFDBFE;
|
||||
--unsubtle-detail-color: #bfdbfe;
|
||||
--unsubtle-detail-color-contrast: black;
|
||||
|
||||
|
||||
--catch-detail-color: #3a3aeb;
|
||||
--catch-detail-color-contrast: white;
|
||||
|
||||
|
||||
--non-active-tab-svg: var(--foreground-color);
|
||||
--shadow-color: #00000066;
|
||||
|
||||
|
@ -100,7 +96,8 @@
|
|||
--variable-title-height: 0px;
|
||||
}
|
||||
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
min-height: -webkit-fill-available;
|
||||
|
@ -108,7 +105,7 @@ html, body {
|
|||
padding: 0;
|
||||
background-color: var(--background-color);
|
||||
color: var(--foreground-color);
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
font-family: "Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
|
||||
.leaflet-overlay-pane .leaflet-zoom-animated {
|
||||
|
@ -131,7 +128,8 @@ html, body {
|
|||
height: 100% !important;
|
||||
}
|
||||
|
||||
svg, img {
|
||||
svg,
|
||||
img {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -210,7 +208,6 @@ a {
|
|||
.btn-secondary {
|
||||
background-color: var(--catch-detail-color);
|
||||
filter: saturate(0.5);
|
||||
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
|
@ -231,6 +228,29 @@ a {
|
|||
height: min-content;
|
||||
}
|
||||
|
||||
/* slider */
|
||||
input[type="range"].vertical {
|
||||
writing-mode: bt-lr; /* IE */
|
||||
-webkit-appearance: slider-vertical; /* Chromium */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
input[type="range"].elevator::-moz-range-thumb {
|
||||
background-color: #00000000 !important;
|
||||
background-image: url("/assets/svg/elevator_wheelchair.svg");
|
||||
width: 150px !important;
|
||||
height: 30px !important;
|
||||
border: 2px;
|
||||
border-style: solid;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
border-image: linear-gradient(to right, black 50%, transparent 50%) 100% 1;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.border-detail {
|
||||
border-color: var(--foreground-color);
|
||||
|
@ -302,7 +322,7 @@ p {
|
|||
}
|
||||
|
||||
li::marker {
|
||||
content: "•"
|
||||
content: "•";
|
||||
}
|
||||
|
||||
.subtle-background {
|
||||
|
@ -312,7 +332,7 @@ li::marker {
|
|||
|
||||
.normal-background {
|
||||
background: var(--background-color);
|
||||
color: var(--foreground-color)
|
||||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
.subtle-lighter {
|
||||
|
@ -335,7 +355,6 @@ li::marker {
|
|||
fill: var(--catch-detail-color) !important;
|
||||
}
|
||||
|
||||
|
||||
#leafletDiv {
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -375,7 +394,6 @@ li::marker {
|
|||
max-width: 2em !important;
|
||||
}
|
||||
|
||||
|
||||
.block-ruby {
|
||||
display: block ruby;
|
||||
}
|
||||
|
@ -392,14 +410,14 @@ li::marker {
|
|||
color: unset !important;
|
||||
}
|
||||
|
||||
.disable-links a.must-link, .disable-links .must-link a {
|
||||
.disable-links a.must-link,
|
||||
.disable-links .must-link a {
|
||||
/* Hide links if they are disabled */
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**************** GENERIC ****************/
|
||||
|
||||
|
||||
.alert {
|
||||
background-color: var(--alert-color);
|
||||
color: var(--foreground-color);
|
||||
|
@ -434,7 +452,6 @@ li::marker {
|
|||
padding: 0.15em 0.3em;
|
||||
}
|
||||
|
||||
|
||||
.subtle {
|
||||
color: #999;
|
||||
}
|
||||
|
@ -444,7 +461,6 @@ li::marker {
|
|||
color: #7193bb;
|
||||
}
|
||||
|
||||
|
||||
.thanks {
|
||||
background-color: #43d904;
|
||||
font-weight: bold;
|
||||
|
@ -462,7 +478,6 @@ li::marker {
|
|||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
|
||||
@keyframes slide {
|
||||
/* This is the animation on the marker to add a new point - it slides through all the possible presets */
|
||||
from {
|
||||
|
@ -506,7 +521,6 @@ li::marker {
|
|||
transform: rotate(-30deg);
|
||||
}
|
||||
|
||||
|
||||
36% {
|
||||
opacity: 0;
|
||||
transform: rotate(-30deg);
|
||||
|
@ -516,12 +530,10 @@ li::marker {
|
|||
opacity: 0;
|
||||
transform: rotate(-30deg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
|
||||
#topleft-tools {
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
@ -540,12 +552,10 @@ li::marker {
|
|||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************** Info box (box containing features and questions ******************/
|
||||
|
||||
input {
|
||||
color: var(--foreground-color)
|
||||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
.leaflet-popup-content {
|
||||
|
@ -579,7 +589,6 @@ input {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
.code {
|
||||
display: inline-block;
|
||||
background-color: lightgray;
|
||||
|
@ -600,18 +609,16 @@ input {
|
|||
max-width: 1em;
|
||||
}
|
||||
|
||||
|
||||
.slideshow-item img {
|
||||
height: var(--image-carousel-height);
|
||||
width: unset;
|
||||
}
|
||||
|
||||
.animate-height {
|
||||
transition: max-height .5s ease-in-out;
|
||||
transition: max-height 0.5s ease-in-out;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
|
||||
.zebra-table tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
@ -657,7 +664,6 @@ input {
|
|||
width: unset;
|
||||
}
|
||||
|
||||
|
||||
.mapping-icon-small {
|
||||
/* A mapping icon type */
|
||||
width: 1.5rem;
|
||||
|
@ -673,7 +679,7 @@ input {
|
|||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.mapping-icon-large{
|
||||
.mapping-icon-large {
|
||||
/* A mapping icon type */
|
||||
width: 6rem;
|
||||
max-height: 5rem;
|
||||
|
@ -681,7 +687,4 @@ input {
|
|||
margin-bottom: 0.5rem;
|
||||
margin-right: 1.5rem;
|
||||
margin-left: 1.5rem;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,10 @@
|
|||
"title": "Select layers",
|
||||
"zoomInToSeeThisLayer": "Zoom in to see this layer"
|
||||
},
|
||||
"levelSelection": {
|
||||
"addNewOnLevel": "Is the new point location on level {level}?",
|
||||
"confirmLevel": "Yes, add {preset} on level {level}"
|
||||
},
|
||||
"loading": "Loading…",
|
||||
"loadingTheme": "Loading {theme}…",
|
||||
"loginFailed": "Logging in into OpenStreetMap failed",
|
||||
|
|
|
@ -10,7 +10,7 @@ import {AllKnownLayouts} from "../Customizations/AllKnownLayouts";
|
|||
import RelationsTracker from "../Logic/Osm/RelationsTracker";
|
||||
import * as OsmToGeoJson from "osmtogeojson";
|
||||
import MetaTagging from "../Logic/MetaTagging";
|
||||
import {UIEventSource} from "../Logic/UIEventSource";
|
||||
import {ImmutableStore, UIEventSource} from "../Logic/UIEventSource";
|
||||
import {TileRange, Tiles} from "../Models/TileRange";
|
||||
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
|
||||
import ScriptUtils from "./ScriptUtils";
|
||||
|
@ -250,9 +250,10 @@ function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relations
|
|||
}
|
||||
|
||||
const filteredTile = new FilteringFeatureSource({
|
||||
locationControl: new UIEventSource<Loc>(undefined),
|
||||
locationControl: new ImmutableStore<Loc>(undefined),
|
||||
allElements: undefined,
|
||||
selectedElement: new UIEventSource<any>(undefined)
|
||||
selectedElement: new ImmutableStore<any>(undefined),
|
||||
globalFilters: new ImmutableStore([])
|
||||
},
|
||||
tileIndex,
|
||||
tile,
|
||||
|
@ -323,9 +324,10 @@ function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relations
|
|||
if (pointsOnlyLayers.indexOf(layer.id) >= 0) {
|
||||
|
||||
const filtered = new FilteringFeatureSource({
|
||||
locationControl: new UIEventSource<Loc>(undefined),
|
||||
locationControl: new ImmutableStore<Loc>(undefined),
|
||||
allElements: undefined,
|
||||
selectedElement: new UIEventSource<any>(undefined)
|
||||
selectedElement: new ImmutableStore<any>(undefined),
|
||||
globalFilters: new ImmutableStore([])
|
||||
},
|
||||
Tiles.tile_index(0, 0, 0),
|
||||
source,
|
||||
|
|
76
test.ts
76
test.ts
|
@ -1,76 +1,4 @@
|
|||
import ChartJs from "./UI/Base/ChartJs";
|
||||
import TagRenderingChart from "./UI/BigComponents/TagRenderingChart";
|
||||
import {OsmFeature} from "./Models/OsmFeature";
|
||||
import * as food from "./assets/generated/layers/food.json"
|
||||
import TagRenderingConfig from "./Models/ThemeConfig/TagRenderingConfig";
|
||||
import LevelSelector from "./UI/Input/LevelSelector";
|
||||
import {UIEventSource} from "./Logic/UIEventSource";
|
||||
import Combine from "./UI/Base/Combine";
|
||||
const data = new UIEventSource<OsmFeature[]>([
|
||||
{
|
||||
properties: {
|
||||
id: "node/1234",
|
||||
cuisine:"pizza",
|
||||
"payment:cash":"yes"
|
||||
},
|
||||
geometry:{
|
||||
type: "Point",
|
||||
coordinates: [0,0]
|
||||
},
|
||||
id: "node/1234",
|
||||
type: "Feature"
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
id: "node/42",
|
||||
cuisine:"pizza",
|
||||
"payment:cash":"yes"
|
||||
},
|
||||
geometry:{
|
||||
type: "Point",
|
||||
coordinates: [1,0]
|
||||
},
|
||||
id: "node/42",
|
||||
type: "Feature"
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
id: "node/452",
|
||||
cuisine:"pasta",
|
||||
"payment:cash":"yes",
|
||||
"payment:cards":"yes"
|
||||
},
|
||||
geometry:{
|
||||
type: "Point",
|
||||
coordinates: [2,0]
|
||||
},
|
||||
id: "node/452",
|
||||
type: "Feature"
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
id: "node/4542",
|
||||
cuisine:"something_comletely_invented",
|
||||
"payment:cards":"yes"
|
||||
},
|
||||
geometry:{
|
||||
type: "Point",
|
||||
coordinates: [3,0]
|
||||
},
|
||||
id: "node/4542",
|
||||
type: "Feature"
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
id: "node/45425",
|
||||
},
|
||||
geometry:{
|
||||
type: "Point",
|
||||
coordinates: [3,0]
|
||||
},
|
||||
id: "node/45425",
|
||||
type: "Feature"
|
||||
}
|
||||
]);
|
||||
|
||||
new Combine(food.tagRenderings.map(tr => new TagRenderingChart(data, new TagRenderingConfig(tr, "test"), {chartclasses: "w-160 h-160"})))
|
||||
.AttachTo("maindiv")
|
||||
new LevelSelector(new UIEventSource(["0","1","2","2.5","x","3"])).AttachTo("maindiv")
|
Loading…
Reference in a new issue