Merge branch 'develop' into feature/bicycle_road
BIN
Docs/Misc/Climbing.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
Docs/Misc/Kakampink.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
Docs/Misc/StatisticsOnwheels.png
Normal file
After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
BIN
Docs/Misc/shop_selection.gif
Normal file
After Width: | Height: | Size: 300 KiB |
53
Docs/Presentations/SOTM2022-workshop.abstract.txt
Normal file
|
@ -0,0 +1,53 @@
|
|||
# What do I want to tell at SOTM '22?
|
||||
|
||||
4 main topics:
|
||||
|
||||
The MapComplete Editor:
|
||||
|
||||
- What is MapComplete? The vision
|
||||
+ Simple to use viewer
|
||||
+ Simple to contribute
|
||||
+ Packed with features under the hood (where applicable)
|
||||
+ Pareto frontier
|
||||
|
||||
- What is a theme?
|
||||
+ One or more layers + introduction text + some meta (such as icon)
|
||||
+ Vision on what the target group is (who will use it? For what purpose?)
|
||||
+ Written in a .json-file
|
||||
|
||||
- What is a .json-file
|
||||
+ A flat text-file (create a .txt)
|
||||
|
||||
- What is a layer?
|
||||
+ One logical type of feature
|
||||
- Specifiy the tags that are needed to match
|
||||
- Uses OSM as default datasource, but an online (sliced) geojson is an option too, e.g. to show/import
|
||||
+ Specifies the elements to show in the popup
|
||||
+ Specifies how it is rendered
|
||||
+ Specifies if new elements can be added and with which tags
|
||||
-> Don't mix, e.g. don't mix post-boxes with post offices
|
||||
-> Don't use an adverb, e.g. "all shops ~~which accept cash~~". What if the shop is already there but the payment methods are not known yet? (use a filter instead)
|
||||
|
||||
- What is a TagRendering?
|
||||
+ Converts the objects attributes into a text on the screen
|
||||
+ If a question is added, it'll ask the user the right answer
|
||||
-> Do use full sentences
|
||||
-> Start with the step 'attributes to text', then add the question
|
||||
-> Don't write "yes, this POI has ..." or even worse "yes"/"no"
|
||||
|
||||
- Deploying
|
||||
+ copy paste into a base64-decoder
|
||||
+ Go to "mapcomplete.osm.be/index?userlayout=true#<paste your encoded file here>"
|
||||
+ Oh Noes! An error msg!
|
||||
|
||||
- sharing
|
||||
+ Share often and early. I'd rather have a half-finished theme via chat/wiki that can be improved upon then no theme at all
|
||||
+ When done: make a pull request via github (you'll get translations, documentation, integration with taginfo and a chatbot for free)
|
||||
|
||||
- A dash of Magic
|
||||
+ Calculated tags
|
||||
+ Twin layers (fritures)
|
||||
+ Imports
|
||||
|
||||
- Future work:
|
||||
+ Improve this flow
|
BIN
Docs/Presentations/WikidataAndMapComplete.mp4
Normal file
|
@ -235,7 +235,7 @@ export default class SimpleMetaTaggers {
|
|||
|
||||
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`)",
|
||||
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`; `1` will be rewritten to `1m` as well)",
|
||||
keys: ["Theme-defined keys"],
|
||||
|
||||
},
|
||||
|
@ -261,13 +261,14 @@ export default class SimpleMetaTaggers {
|
|||
continue;
|
||||
}
|
||||
const value = feature.properties[key]
|
||||
const denom = unit.findDenomination(value)
|
||||
const denom = unit.findDenomination(value, () => feature.properties["_country"])
|
||||
if (denom === undefined) {
|
||||
// no valid value found
|
||||
break;
|
||||
}
|
||||
const [, denomination] = denom;
|
||||
let canonical = denomination?.canonicalValue(value) ?? undefined;
|
||||
const defaultDenom = unit.getDefaultDenomination(() => feature.properties["_country"])
|
||||
let canonical = denomination?.canonicalValue(value, defaultDenom == denomination) ?? undefined;
|
||||
if (canonical === value) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
import {Translation} from "../UI/i18n/Translation";
|
||||
import {ApplicableUnitJson} from "./ThemeConfig/Json/UnitConfigJson";
|
||||
import {DenominationConfigJson} from "./ThemeConfig/Json/UnitConfigJson";
|
||||
import Translations from "../UI/i18n/Translations";
|
||||
import {Store, UIEventSource} from "../Logic/UIEventSource";
|
||||
import {Store} from "../Logic/UIEventSource";
|
||||
import BaseUIElement from "../UI/BaseUIElement";
|
||||
import Toggle from "../UI/Input/Toggle";
|
||||
|
||||
export class Denomination {
|
||||
public readonly canonical: string;
|
||||
public readonly _canonicalSingular: string;
|
||||
public readonly default: boolean;
|
||||
public readonly useAsDefaultInput: boolean | string[]
|
||||
public readonly useIfNoUnitGiven : boolean | string[]
|
||||
public readonly prefix: boolean;
|
||||
public readonly alternativeDenominations: string [];
|
||||
private readonly _human: Translation;
|
||||
private readonly _humanSingular?: Translation;
|
||||
|
||||
|
||||
constructor(json: ApplicableUnitJson, context: string) {
|
||||
constructor(json: DenominationConfigJson, context: string) {
|
||||
context = `${context}.unit(${json.canonicalDenomination})`
|
||||
this.canonical = json.canonicalDenomination.trim()
|
||||
if (this.canonical === undefined) {
|
||||
|
@ -32,8 +33,12 @@ export class Denomination {
|
|||
|
||||
this.alternativeDenominations = json.alternativeDenomination?.map(v => v.trim()) ?? []
|
||||
|
||||
this.default = json.default ?? false;
|
||||
|
||||
if(json["default"] !== undefined) {
|
||||
throw `${context} uses the old 'default'-key. Use "useIfNoUnitGiven" or "useAsDefaultInput" instead`
|
||||
}
|
||||
this.useIfNoUnitGiven = json.useIfNoUnitGiven
|
||||
this.useAsDefaultInput = json.useAsDefaultInput ?? json.useIfNoUnitGiven
|
||||
|
||||
this._human = Translations.T(json.human, context + "human")
|
||||
this._humanSingular = Translations.T(json.humanSingular, context + "humanSingular")
|
||||
|
||||
|
@ -68,32 +73,31 @@ export class Denomination {
|
|||
* const unit = new Denomination({
|
||||
* canonicalDenomination: "m",
|
||||
* alternativeDenomination: ["meter"],
|
||||
* 'default': true,
|
||||
* human: {
|
||||
* en: "meter"
|
||||
* }
|
||||
* }, "test")
|
||||
* unit.canonicalValue("42m") // =>"42 m"
|
||||
* unit.canonicalValue("42") // =>"42 m"
|
||||
* unit.canonicalValue("42 m") // =>"42 m"
|
||||
* unit.canonicalValue("42 meter") // =>"42 m"
|
||||
*
|
||||
* unit.canonicalValue("42m", true) // =>"42 m"
|
||||
* unit.canonicalValue("42", true) // =>"42 m"
|
||||
* unit.canonicalValue("42 m", true) // =>"42 m"
|
||||
* unit.canonicalValue("42 meter", true) // =>"42 m"
|
||||
* unit.canonicalValue("42m", true) // =>"42 m"
|
||||
* unit.canonicalValue("42", true) // =>"42 m"
|
||||
*
|
||||
* // Should be trimmed if canonical is empty
|
||||
* const unit = new Denomination({
|
||||
* canonicalDenomination: "",
|
||||
* alternativeDenomination: ["meter","m"],
|
||||
* 'default': true,
|
||||
* human: {
|
||||
* en: "meter"
|
||||
* }
|
||||
* }, "test")
|
||||
* unit.canonicalValue("42m") // =>"42"
|
||||
* unit.canonicalValue("42") // =>"42"
|
||||
* unit.canonicalValue("42 m") // =>"42"
|
||||
* unit.canonicalValue("42 meter") // =>"42"
|
||||
* unit.canonicalValue("42m", true) // =>"42"
|
||||
* unit.canonicalValue("42", true) // =>"42"
|
||||
* unit.canonicalValue("42 m", true) // =>"42"
|
||||
* unit.canonicalValue("42 meter", true) // =>"42"
|
||||
*/
|
||||
public canonicalValue(value: string, actAsDefault?: boolean) : string {
|
||||
public canonicalValue(value: string, actAsDefault: boolean) : string {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -114,7 +118,7 @@ export class Denomination {
|
|||
*
|
||||
* Returns null if it doesn't match this unit
|
||||
*/
|
||||
public StrippedValue(value: string, actAsDefault?: boolean): string {
|
||||
public StrippedValue(value: string, actAsDefault: boolean): string {
|
||||
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
|
@ -153,15 +157,26 @@ export class Denomination {
|
|||
}
|
||||
}
|
||||
|
||||
if (this.default || actAsDefault) {
|
||||
const parsed = Number(value.trim())
|
||||
if (!isNaN(parsed)) {
|
||||
return value.trim();
|
||||
}
|
||||
if (!actAsDefault) {
|
||||
return null
|
||||
}
|
||||
|
||||
const parsed = Number(value.trim())
|
||||
if (!isNaN(parsed)) {
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
isDefaultUnit(country: () => string) {
|
||||
if(this.useIfNoUnitGiven === true){
|
||||
return true
|
||||
}
|
||||
if(this.useIfNoUnitGiven === false){
|
||||
return false
|
||||
}
|
||||
return this.useIfNoUnitGiven.indexOf(country()) >= 0
|
||||
}
|
||||
}
|
|
@ -13,11 +13,16 @@ import {AddContextToTranslations} from "./AddContextToTranslations";
|
|||
class ExpandTagRendering extends Conversion<string | TagRenderingConfigJson | { builtin: string | string[], override: any }, TagRenderingConfigJson[]> {
|
||||
private readonly _state: DesugaringContext;
|
||||
private readonly _self: LayerConfigJson;
|
||||
private readonly _options: {
|
||||
/* If true, will copy the 'osmSource'-tags into the condition */
|
||||
applyCondition?: true | boolean;
|
||||
};
|
||||
|
||||
constructor(state: DesugaringContext, self: LayerConfigJson) {
|
||||
constructor(state: DesugaringContext, self: LayerConfigJson, options?: { applyCondition?: true | boolean;}) {
|
||||
super("Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question", [], "ExpandTagRendering");
|
||||
this._state = state;
|
||||
this._self = self;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
convert(json: string | TagRenderingConfigJson | { builtin: string | string[]; override: any }, context: string): { result: TagRenderingConfigJson[]; errors: string[]; warnings: string[] } {
|
||||
|
@ -65,12 +70,14 @@ class ExpandTagRendering extends Conversion<string | TagRenderingConfigJson | {
|
|||
|
||||
const contextWriter = new AddContextToTranslations<TagRenderingConfigJson>("layers:")
|
||||
for (let i = 0; i < matchingTrs.length; i++) {
|
||||
// The matched tagRenderings are 'stolen' from another layer. This means that they must match the layer condition before being shown
|
||||
let found: TagRenderingConfigJson = Utils.Clone(matchingTrs[i]);
|
||||
if (found.condition === undefined) {
|
||||
found.condition = layer.source.osmTags
|
||||
} else {
|
||||
found.condition = {and: [found.condition, layer.source.osmTags]}
|
||||
if(this._options?.applyCondition){
|
||||
// The matched tagRenderings are 'stolen' from another layer. This means that they must match the layer condition before being shown
|
||||
if (found.condition === undefined) {
|
||||
found.condition = layer.source.osmTags
|
||||
} else {
|
||||
found.condition = {and: [found.condition, layer.source.osmTags]}
|
||||
}
|
||||
}
|
||||
|
||||
found = contextWriter.convertStrict(found, layer.id + ".tagRenderings." + found["id"])
|
||||
|
@ -561,7 +568,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
|
|||
new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
||||
new On("tagRenderings", layer => new Concat(new ExpandTagRendering(state, layer))),
|
||||
new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
||||
new On("mapRendering", layer => new Each(new On("icon", new FirstOf(new ExpandTagRendering(state, layer))))),
|
||||
new On("mapRendering", layer => new Each(new On("icon", new FirstOf(new ExpandTagRendering(state, layer, {applyCondition: false}))))),
|
||||
new SetDefault("titleIcons", ["defaults"]),
|
||||
new On("titleIcons", layer => new Concat(new ExpandTagRendering(state, layer)))
|
||||
);
|
||||
|
|
|
@ -613,6 +613,13 @@ export class ValidateLayer extends DesugaringStep<LayerConfigJson> {
|
|||
information.push(...(r.information ?? []))
|
||||
}
|
||||
|
||||
{
|
||||
const hasCondition = json.mapRendering?.filter(mr => mr["icon"] !== undefined && mr["icon"]["condition"] !== undefined)
|
||||
if(hasCondition?.length > 0){
|
||||
errors.push("At "+context+":\n One or more icons in the mapRenderings have a condition set. Don't do this, as this will result in an invisible but clickable element. Use extra filters in the source instead. The offending mapRenderings are:\n"+JSON.stringify(hasCondition, null, " "))
|
||||
}
|
||||
}
|
||||
|
||||
if (json.presets !== undefined) {
|
||||
|
||||
// Check that a preset will be picked up by the layer itself
|
||||
|
|
|
@ -14,13 +14,32 @@ export default interface UnitConfigJson {
|
|||
/**
|
||||
* The possible denominations
|
||||
*/
|
||||
applicableUnits: ApplicableUnitJson[]
|
||||
applicableUnits: DenominationConfigJson[]
|
||||
|
||||
}
|
||||
|
||||
export interface ApplicableUnitJson {
|
||||
export interface DenominationConfigJson {
|
||||
|
||||
|
||||
/**
|
||||
* The canonical value which will be added to the value in OSM.
|
||||
* If this evaluates to true and the value to interpret has _no_ unit given, assumes that this unit is meant.
|
||||
* Alternatively, a list of country codes can be given where this acts as the default interpretation
|
||||
*
|
||||
* E.g., a denomination using "meter" would probably set this flag to "true";
|
||||
* a denomination for "mp/h" will use the condition "_country=gb" to indicate that it is the default in the UK.
|
||||
*
|
||||
* If none of the units indicate that they are the default, the first denomination will be used instead
|
||||
*/
|
||||
useIfNoUnitGiven?: boolean | string[]
|
||||
|
||||
/**
|
||||
* Use this value as default denomination when the user inputs a value (e.g. to force using 'centimeters' instead of 'meters' by default).
|
||||
* If unset for all values, this will use 'useIfNoUnitGiven'. If at least one denomination has this set, this will default to false
|
||||
*/
|
||||
useAsDefaultInput?: boolean | string[]
|
||||
|
||||
/**
|
||||
* The canonical value for this denomination which will be added to the value in OSM.
|
||||
* e.g. "m" for meters
|
||||
* If the user inputs '42', the canonical value will be added and it'll become '42m'.
|
||||
*
|
||||
|
@ -28,8 +47,11 @@ export interface ApplicableUnitJson {
|
|||
* In this case, an empty string should be used
|
||||
*/
|
||||
canonicalDenomination: string,
|
||||
|
||||
|
||||
/**
|
||||
* The canonical denomination in the case that the unit is precisely '1'
|
||||
* The canonical denomination in the case that the unit is precisely '1'.
|
||||
* Used for display purposes
|
||||
*/
|
||||
canonicalDenominationSingular?: string,
|
||||
|
||||
|
@ -63,9 +85,5 @@ export interface ApplicableUnitJson {
|
|||
*/
|
||||
prefix?: boolean
|
||||
|
||||
/**
|
||||
* The default interpretation - only one can be set.
|
||||
* If none is set, the first unit will be considered the default interpretation of a value without a unit
|
||||
*/
|
||||
default?: boolean
|
||||
|
||||
}
|
|
@ -14,8 +14,6 @@ import List from "../../UI/Base/List";
|
|||
import {MappingConfigJson, QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson";
|
||||
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
|
||||
import {Paragraph} from "../../UI/Base/Paragraph";
|
||||
import spec = Mocha.reporters.spec;
|
||||
import SpecialVisualizations from "../../UI/SpecialVisualizations";
|
||||
|
||||
export interface Mapping {
|
||||
readonly if: TagsFilter,
|
||||
|
|
|
@ -8,14 +8,11 @@ export class Unit {
|
|||
public readonly appliesToKeys: Set<string>;
|
||||
public readonly denominations: Denomination[];
|
||||
public readonly denominationsSorted: Denomination[];
|
||||
public readonly defaultDenom: Denomination;
|
||||
public readonly eraseInvalid: boolean;
|
||||
private readonly possiblePostFixes: string[] = []
|
||||
|
||||
constructor(appliesToKeys: string[], applicableUnits: Denomination[], eraseInvalid: boolean) {
|
||||
constructor(appliesToKeys: string[], applicableDenominations: Denomination[], eraseInvalid: boolean) {
|
||||
this.appliesToKeys = new Set(appliesToKeys);
|
||||
this.denominations = applicableUnits;
|
||||
this.defaultDenom = applicableUnits.filter(denom => denom.default)[0]
|
||||
this.denominations = applicableDenominations;
|
||||
this.eraseInvalid = eraseInvalid
|
||||
|
||||
const seenUnitExtensions = new Set<string>();
|
||||
|
@ -52,8 +49,6 @@ export class Unit {
|
|||
addPostfixesOf(denomination._canonicalSingular)
|
||||
denomination.alternativeDenominations.forEach(addPostfixesOf)
|
||||
}
|
||||
this.possiblePostFixes = Array.from(possiblePostFixes)
|
||||
this.possiblePostFixes.sort((a, b) => b.length - a.length)
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,16 +66,12 @@ export class Unit {
|
|||
}
|
||||
// Some keys do have unit handling
|
||||
|
||||
const defaultSet = json.applicableUnits.filter(u => u.default === true)
|
||||
// No default is defined - we pick the first as default
|
||||
if (defaultSet.length === 0) {
|
||||
json.applicableUnits[0].default = true
|
||||
}
|
||||
|
||||
// Check that there are not multiple defaults
|
||||
if (defaultSet.length > 1) {
|
||||
throw `Multiple units are set as default: they have canonical values of ${defaultSet.map(u => u.canonicalDenomination).join(", ")}`
|
||||
if(json.applicableUnits.some(denom => denom.useAsDefaultInput !== undefined)){
|
||||
json.applicableUnits.forEach(denom => {
|
||||
denom.useAsDefaultInput = denom.useAsDefaultInput ?? false
|
||||
})
|
||||
}
|
||||
|
||||
const applicable = json.applicableUnits.map((u, i) => new Denomination(u, `${ctx}.units[${i}]`))
|
||||
return new Unit(appliesTo, applicable, json.eraseInvalidValues ?? false)
|
||||
}
|
||||
|
@ -96,12 +87,13 @@ export class Unit {
|
|||
/**
|
||||
* Finds which denomination is applicable and gives the stripped value back
|
||||
*/
|
||||
findDenomination(valueWithDenom: string): [string, Denomination] {
|
||||
findDenomination(valueWithDenom: string, country: () => string): [string, Denomination] {
|
||||
if (valueWithDenom === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const defaultDenom = this.getDefaultDenomination(country)
|
||||
for (const denomination of this.denominationsSorted) {
|
||||
const bare = denomination.StrippedValue(valueWithDenom)
|
||||
const bare = denomination.StrippedValue(valueWithDenom, defaultDenom === denomination)
|
||||
if (bare !== null) {
|
||||
return [bare, denomination]
|
||||
}
|
||||
|
@ -109,11 +101,11 @@ export class Unit {
|
|||
return [undefined, undefined]
|
||||
}
|
||||
|
||||
asHumanLongValue(value: string): BaseUIElement {
|
||||
asHumanLongValue(value: string, country: () => string): BaseUIElement {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const [stripped, denom] = this.findDenomination(value)
|
||||
const [stripped, denom] = this.findDenomination(value, country)
|
||||
const human = stripped === "1" ? denom?.humanSingular : denom?.human
|
||||
if (human === undefined) {
|
||||
return new FixedUiElement(stripped ?? value);
|
||||
|
@ -124,24 +116,46 @@ export class Unit {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value without any (sub)parts of any denomination - usefull as preprocessing step for validating inputs.
|
||||
* E.g.
|
||||
* if 'megawatt' is a possible denomination, then '5 Meg' will be rewritten to '5' (which can then be validated as a valid pnat)
|
||||
*
|
||||
* Returns the original string if nothign matches
|
||||
*/
|
||||
stripUnitParts(str: string) {
|
||||
if (str === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const denominationPart of this.possiblePostFixes) {
|
||||
if (str.endsWith(denominationPart)) {
|
||||
return str.substring(0, str.length - denominationPart.length).trim()
|
||||
public getDefaultInput(country: () => string | string[]) {
|
||||
console.log("Searching the default denomination for input", country)
|
||||
for (const denomination of this.denominations) {
|
||||
if (denomination.useAsDefaultInput === true) {
|
||||
return denomination
|
||||
}
|
||||
if (denomination.useAsDefaultInput === undefined || denomination.useAsDefaultInput === false) {
|
||||
continue
|
||||
}
|
||||
let countries: string | string[] = country()
|
||||
if (typeof countries === "string") {
|
||||
countries = countries.split(",")
|
||||
}
|
||||
const denominationCountries: string[] = denomination.useAsDefaultInput
|
||||
if (countries.some(country => denominationCountries.indexOf(country) >= 0)) {
|
||||
return denomination
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
return this.denominations[0]
|
||||
}
|
||||
|
||||
public getDefaultDenomination(country: () => string){
|
||||
for (const denomination of this.denominations) {
|
||||
if (denomination.useIfNoUnitGiven === true || denomination.canonical === "") {
|
||||
return denomination
|
||||
}
|
||||
if (denomination.useIfNoUnitGiven === undefined || denomination.useIfNoUnitGiven === false) {
|
||||
continue
|
||||
}
|
||||
let countries: string | string[] = country()
|
||||
if (typeof countries === "string") {
|
||||
countries = countries.split(",")
|
||||
}
|
||||
const denominationCountries: string[] = denomination.useIfNoUnitGiven
|
||||
if (countries.some(country => denominationCountries.indexOf(country) >= 0)) {
|
||||
return denomination
|
||||
}
|
||||
}
|
||||
return this.denominations[0]
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import BaseUIElement from "../BaseUIElement";
|
||||
import {Chart, ChartConfiguration, ChartType, DefaultDataPoint, registerables} from 'chart.js';
|
||||
Chart.register(...registerables);
|
||||
Chart?.register(...(registerables ?? []));
|
||||
|
||||
|
||||
export default class ChartJs<
|
||||
|
|
|
@ -78,7 +78,6 @@ export class SubtleButton extends UIElement {
|
|||
})
|
||||
const loading = new Lazy(() => new Loading(loadingText) )
|
||||
return new VariableUiElement(state.map(st => {
|
||||
console.log("State is: ", st)
|
||||
if(st === "idle"){
|
||||
return button
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import {QueryParameters} from "../../Logic/Web/QueryParameters";
|
|||
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
||||
import {InputElement} from "../Input/InputElement";
|
||||
import {DropDown} from "../Input/DropDown";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
|
||||
export default class FilterView extends VariableUiElement {
|
||||
constructor(filteredLayer: UIEventSource<FilteredLayer[]>,
|
||||
|
@ -91,7 +92,7 @@ export default class FilterView extends VariableUiElement {
|
|||
if (filteredLayer.layerDef.name === undefined) {
|
||||
// Name is not defined: we hide this one
|
||||
return new Toggle(
|
||||
filteredLayer?.layerDef?.description?.Clone()?.SetClass("subtle") ,
|
||||
new FixedUiElement(filteredLayer?.layerDef?.id ).SetClass("block") ,
|
||||
undefined,
|
||||
state?.featureSwitchIsDebugging
|
||||
);
|
||||
|
|
|
@ -90,7 +90,7 @@ export class TextFieldDef {
|
|||
if (options.unit !== undefined) {
|
||||
// Reformatting is handled by the unit in this case
|
||||
options["isValid"] = str => {
|
||||
const denom = options.unit.findDenomination(str);
|
||||
const denom = options.unit.findDenomination(str, options?.country);
|
||||
if (denom === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ export class TextFieldDef {
|
|||
}
|
||||
})
|
||||
)
|
||||
unitDropDown.GetValue().setData(unit.defaultDenom)
|
||||
unitDropDown.GetValue().setData(unit.getDefaultInput(options.country))
|
||||
unitDropDown.SetClass("w-min")
|
||||
|
||||
const fixedDenom = unit.denominations.length === 1 ? unit.denominations[0] : undefined
|
||||
|
@ -169,7 +169,7 @@ export class TextFieldDef {
|
|||
},
|
||||
(valueWithDenom: string) => {
|
||||
// Take the value from OSM and feed it into the textfield and the dropdown
|
||||
const withDenom = unit.findDenomination(valueWithDenom);
|
||||
const withDenom = unit.findDenomination(valueWithDenom, options?.country);
|
||||
if (withDenom === undefined) {
|
||||
// Not a valid value at all - we give it undefined and leave the details up to the other elements (but we keep the previous denomination)
|
||||
return [undefined, fixedDenom]
|
||||
|
|
|
@ -617,6 +617,7 @@ export default class TagRenderingQuestion extends Combine {
|
|||
const tagsData = tags.data;
|
||||
const feature = state?.allElements?.ContainingFeatures?.get(tagsData.id)
|
||||
const center = feature != undefined ? GeoOperations.centerpointCoordinates(feature) : [0, 0]
|
||||
console.log("Creating a tr-question with applicableUnit", applicableUnit)
|
||||
const input: InputElement<string> = ValidatedTextField.ForType(configuration.freeform.type)?.ConstructInputElement({
|
||||
country: () => tagsData._country,
|
||||
location: [center[1], center[0]],
|
||||
|
|
|
@ -1273,6 +1273,9 @@ export default class SpecialVisualizations {
|
|||
const tagRendering = layer.tagRenderings.find(tr => tr.id === tagRenderingId)
|
||||
tagRenderings.push([layer, tagRendering])
|
||||
}
|
||||
if(tagRenderings.length === 0){
|
||||
throw "Could not create stolen tagrenddering: tagRenderings not found"
|
||||
}
|
||||
return new VariableUiElement(featureTags.map(tags => {
|
||||
const featureId = tags[featureIdKey]
|
||||
if (featureId === undefined) {
|
||||
|
|
4
Utils.ts
|
@ -151,8 +151,8 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
|||
return res;
|
||||
}
|
||||
|
||||
public static NoNull<T>(array: T[]): T[] {
|
||||
return array?.filter(o => o !== undefined && o !== null)
|
||||
public static NoNull<T>(array: T[]): NonNullable<T>[] {
|
||||
return <any> array?.filter(o => o !== undefined && o !== null)
|
||||
}
|
||||
|
||||
public static Hist(array: string[]): Map<string, number> {
|
||||
|
|
|
@ -271,6 +271,9 @@
|
|||
"smoking",
|
||||
"service:electricity",
|
||||
"dog-access",
|
||||
"internet",
|
||||
"internet-fee",
|
||||
"internet-ssid",
|
||||
"reviews"
|
||||
],
|
||||
"filter": [
|
||||
|
|
|
@ -185,6 +185,7 @@
|
|||
"alternativeDenomination": [
|
||||
"meter"
|
||||
],
|
||||
"useIfNoUnitGiven": true,
|
||||
"human": {
|
||||
"en": "meter",
|
||||
"fr": "mètre",
|
||||
|
@ -193,7 +194,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"default": true,
|
||||
"useAsDefaultInput": true,
|
||||
"canonicalDenomination": "cm",
|
||||
"alternativeDenomination": [
|
||||
"centimeter",
|
||||
|
|
|
@ -467,10 +467,12 @@
|
|||
"units": [
|
||||
{
|
||||
"appliesToKey": [
|
||||
"kerb:height"
|
||||
"kerb:height",
|
||||
"width"
|
||||
],
|
||||
"applicableUnits": [
|
||||
{
|
||||
{
|
||||
"useIfNoUnitGiven": true,
|
||||
"canonicalDenomination": "m",
|
||||
"alternativeDenomination": [
|
||||
"meter"
|
||||
|
@ -483,7 +485,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"default": true,
|
||||
"useAsDefaultInput": true,
|
||||
"canonicalDenomination": "cm",
|
||||
"alternativeDenomination": [
|
||||
"centimeter",
|
||||
|
|
|
@ -764,6 +764,9 @@
|
|||
},
|
||||
"service:electricity",
|
||||
"dog-access",
|
||||
"internet",
|
||||
"internet-fee",
|
||||
"internet-ssid",
|
||||
"reviews"
|
||||
],
|
||||
"filter": [
|
||||
|
|
|
@ -80,7 +80,10 @@
|
|||
"phone",
|
||||
"email",
|
||||
"website",
|
||||
"wheelchair-access"
|
||||
"wheelchair-access",
|
||||
"internet",
|
||||
"internet-fee",
|
||||
"internet-ssid"
|
||||
],
|
||||
"allowMove": {
|
||||
"enableImproveAccuracy": true,
|
||||
|
|
|
@ -1,3 +1,45 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
|
||||
<path d="M 0.5 3 C 0.223 3 0 3.223 0 3.5 L 0 4 L 0 8 L 0 9 L 0 9.5 L 0 11 L 1 11 L 1 9.5 L 1 9 L 13 9 L 13 10.5 L 13 11 L 13.5 11 L 14 11 L 14 10.5 L 14 9 L 14 8 L 14 6 L 14 5.5 C 14 5.223 13.777 5 13.5 5 C 13.223 5 13 5.223 13 5.5 L 13 6 L 13 8 L 1 8 L 1 4 L 1 3.5 C 1 3.223 0.777 3 0.5 3 z M 3.5 4 C 2.671573 4 2 4.671573 2 5.5 C 2 6.328427 2.671573 7 3.5 7 C 4.328427 7 5 6.328427 5 5.5 C 5 4.671573 4.328427 4 3.5 4 z M 6 5 L 6 7 L 12 7 C 12 6 10.963825 5 10 5 L 6 5 z"/>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="500"
|
||||
height="500"
|
||||
viewBox="0 0 500 500"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="hotel.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="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#111111"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:zoom="0.5912918"
|
||||
inkscape:cx="43.125915"
|
||||
inkscape:cy="341.6249"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1007"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4">
|
||||
<sodipodi:guide
|
||||
position="-213.39489,250.02313"
|
||||
orientation="0,-1"
|
||||
id="guide827" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
d="m 20.793355,103.8662 c -9.838754,0 -17.7594848,7.92073 -17.7594848,17.75948 v 17.75948 142.07589 35.51898 17.75949 53.27845 H 38.552842 V 334.73952 316.98003 H 464.78049 v 53.27845 17.75949 h 17.7595 17.75948 v -17.75949 -53.27845 -35.51898 -71.03793 -17.75949 c 0,-9.83876 -7.92073,-17.75949 -17.75948,-17.75949 -9.83876,0 -17.7595,7.92073 -17.7595,17.75949 v 17.75949 71.03793 H 38.552842 V 139.38516 121.62568 c 0,-9.83875 -7.920731,-17.75948 -17.759487,-17.75948 z m 106.556915,35.51896 c -29.424876,0 -53.278458,23.85359 -53.278458,53.27847 0,29.42487 23.853582,53.27845 53.278458,53.27845 29.42487,0 53.27845,-23.85358 53.27845,-53.27845 0,-29.42488 -23.85358,-53.27847 -53.27845,-53.27847 z m 88.79743,35.51898 v 71.03794 h 213.11382 c 0,-35.51896 -36.80387,-71.03794 -71.03793,-71.03794 z"
|
||||
id="path2"
|
||||
style="stroke-width:35.519" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 569 B After Width: | Height: | Size: 2 KiB |
|
@ -456,7 +456,6 @@
|
|||
{
|
||||
"applicableUnits": [
|
||||
{
|
||||
"default": true,
|
||||
"canonicalDenomination": "",
|
||||
"alternativeDenomination": [
|
||||
"mm",
|
||||
|
|
|
@ -178,8 +178,6 @@
|
|||
"centroid"
|
||||
],
|
||||
"icon": {
|
||||
"render": null,
|
||||
"condition": "indoor=room",
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
|
|
|
@ -339,8 +339,7 @@
|
|||
"nl": "centimeter",
|
||||
"de": "Zentimeter",
|
||||
"fr": "centimètre"
|
||||
},
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"canonicalDenomination": "m",
|
||||
|
|
|
@ -110,16 +110,19 @@
|
|||
"allowSplit": true,
|
||||
"mapRendering": [
|
||||
{
|
||||
"render": null,
|
||||
"icon": {
|
||||
"render": null,
|
||||
"mappings": [
|
||||
{
|
||||
"if": "maxspeed~[1-9]0|1[0-4]0",
|
||||
"then": "./assets/themes/maxspeed/maxspeed_{maxspeed} mph.svg"
|
||||
},
|
||||
{
|
||||
"if": "maxspeed~[1-9]0|1[0-4]0 mph",
|
||||
"then": "./assets/themes/maxspeed/maxspeed_{maxspeed}.svg"
|
||||
}
|
||||
]
|
||||
},
|
||||
"condition": "maxspeed!=30",
|
||||
"iconSize": {
|
||||
"render": "32,32,center"
|
||||
},
|
||||
|
@ -154,7 +157,6 @@
|
|||
"kmh",
|
||||
"kph"
|
||||
],
|
||||
"default": true,
|
||||
"human": {
|
||||
"en": "kilometers/hour",
|
||||
"ca": "quilòmetres/hora",
|
||||
|
@ -172,6 +174,7 @@
|
|||
},
|
||||
{
|
||||
"canonicalDenomination": "mph",
|
||||
"useIfNoUnitGiven": ["gb","us"],
|
||||
"alternativeDenomination": [
|
||||
"m/u",
|
||||
"mh",
|
||||
|
|
|
@ -164,6 +164,15 @@
|
|||
"fr": "Il n'y a pas de places de stationnement pour personnes à mobilité réduite"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": "capacity:disabled=0",
|
||||
"then": {
|
||||
"en": "There are no disabled parking spots",
|
||||
"nl": "Er zijn geen parkeerplaatsen voor gehandicapten",
|
||||
"de": "Es gibt keine barrierefreien Stellplätze",
|
||||
"fr": "Il n'y a pas de places de stationnement pour personnes à mobilité réduite"
|
||||
}
|
||||
}
|
||||
],
|
||||
"question": {
|
||||
|
@ -247,9 +256,9 @@
|
|||
"iconBadges": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"capacity:disabled~*",
|
||||
"capacity:disabled!=no"
|
||||
"or": [
|
||||
"capacity:disabled>0",
|
||||
"capacity:disabled=yes"
|
||||
]
|
||||
},
|
||||
"then": "circle:white;./assets/layers/toilet/wheelchair.svg"
|
||||
|
|
10
assets/layers/parking_spaces/license_info.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"path": "parking_space.svg",
|
||||
"license": "CC0",
|
||||
"authors": [
|
||||
"Robin van der Linde"
|
||||
],
|
||||
"sources": []
|
||||
}
|
||||
]
|
70
assets/layers/parking_spaces/parking_space.svg
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="500"
|
||||
height="500"
|
||||
viewBox="0 0 132.29166 132.29167"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||
sodipodi:docname="Parking_space.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="105.28861"
|
||||
inkscape:cy="436.23499"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
inkscape:window-x="2149"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Laag 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;stroke:#1d5485;stroke-width:5px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 26.458333,121.70833 0,-111.124997 h 79.374997 l 0,111.124997"
|
||||
id="path833"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<g
|
||||
aria-label="P"
|
||||
id="text833"
|
||||
style="font-style:normal;font-weight:normal;font-size:68.771px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.71928">
|
||||
<path
|
||||
d="m 82.499093,56.25664 q 0,3.32438 -1.175286,6.178645 -1.141706,2.820686 -3.22364,4.90262 -2.585629,2.585629 -6.111486,3.895233 -3.525857,1.276025 -8.898592,1.276025 H 56.44133 V 91.145836 H 49.792571 V 41.145824 h 13.566155 q 4.499665,0 7.622567,0.772331 3.122902,0.738751 5.540633,2.350571 2.854265,1.914037 4.398926,4.768302 1.578241,2.854265 1.578241,7.219612 z m -6.917396,0.167898 q 0,-2.585628 -0.906649,-4.499665 -0.906649,-1.914037 -2.753526,-3.122902 -1.611821,-1.040968 -3.693755,-1.477502 -2.048355,-0.470115 -5.204837,-0.470115 h -6.5816 v 19.979858 h 5.607792 q 4.029551,0 6.54802,-0.705172 2.51847,-0.738751 4.09671,-2.316992 1.578241,-1.61182 2.216253,-3.391538 0.671592,-1.779719 0.671592,-3.995972 z"
|
||||
style="stroke-width:1.71928"
|
||||
id="path835" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
155
assets/layers/parking_spaces/parking_spaces.json
Normal file
|
@ -0,0 +1,155 @@
|
|||
{
|
||||
"id": "parking_spaces",
|
||||
"name": {
|
||||
"en": "Parking Spaces"
|
||||
},
|
||||
"description": {
|
||||
"en": "Layer showing individual parking spaces."
|
||||
},
|
||||
"minzoom": 20,
|
||||
"source": {
|
||||
"osmTags": "amenity=parking_space"
|
||||
},
|
||||
"tagRenderings": [
|
||||
{
|
||||
"id": "type",
|
||||
"question": {
|
||||
"en": "What kind of parking space is this?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "parking_space=",
|
||||
"then": {
|
||||
"en": "This is a normal parking space"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": "parking_space=normal",
|
||||
"then": {
|
||||
"en": "This is a normal parking space."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=disabled",
|
||||
"then": {
|
||||
"en": "This is a disabled parking space."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=private",
|
||||
"then": {
|
||||
"en": "This is a private parking space."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=charging",
|
||||
"then": {
|
||||
"en": "This is parking space reserved for charging vehicles."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=delivery",
|
||||
"then": {
|
||||
"en": "This is parking space reserved for deliveries."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=hgv",
|
||||
"then": {
|
||||
"en": "This is parking space reserved for heavy goods vehicles."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=caravan",
|
||||
"then": {
|
||||
"en": "This is parking space reserved for caravans or RVs."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=bus",
|
||||
"then": {
|
||||
"en": "This is parking space reserved for buses."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=motorcycle",
|
||||
"then": {
|
||||
"en": "This is parking space reserved for motorcycles."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=parent",
|
||||
"then": {
|
||||
"en": "This is a parking space reserved for parents with children."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=staff",
|
||||
"then": {
|
||||
"en": "This is a parking space reserved for staff."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=taxi",
|
||||
"then": {
|
||||
"en": "This is a parking space reserved for taxis."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=trailer",
|
||||
"then": {
|
||||
"en": "This is a parking space reserved for vehicles towing a trailer."
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "parking_space=car_sharing",
|
||||
"then": {
|
||||
"en": "This is a parking space reserved for car sharing."
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "capacity",
|
||||
"render": {
|
||||
"en": "This parking spaces has {capacity} spaces."
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "capacity=1",
|
||||
"then": {
|
||||
"en": "This parking space has 1 space."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Parking Space"
|
||||
}
|
||||
},
|
||||
"mapRendering": [
|
||||
{
|
||||
"icon": {
|
||||
"render": "./assets/layers/parking_spaces/parking_space.svg",
|
||||
"mappings": [
|
||||
{
|
||||
"if": "parking_space=disabled",
|
||||
"then": "./assets/layers/toilet/wheelchair.svg"
|
||||
}
|
||||
]
|
||||
},
|
||||
"iconSize": "20,20,center",
|
||||
"location": [
|
||||
"point",
|
||||
"centroid"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "#696969",
|
||||
"width": "1"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -201,6 +201,9 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"internet",
|
||||
"internet-fee",
|
||||
"internet-ssid",
|
||||
"questions",
|
||||
"reviews"
|
||||
],
|
||||
|
@ -365,4 +368,4 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -264,7 +264,7 @@
|
|||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "access=public",
|
||||
"if": "access=yes",
|
||||
"then": {
|
||||
"nl": "Publiek toegankelijk",
|
||||
"fr": "Accessible au public",
|
||||
|
@ -309,6 +309,19 @@
|
|||
"de": "Der Sportplatz ist nicht öffentlich zugänglich (es ist ein privater Sportplatz)",
|
||||
"es": "Privada - no accesible al público"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "access=public",
|
||||
"then": {
|
||||
"nl": "Publiek toegankelijk",
|
||||
"fr": "Accessible au public",
|
||||
"en": "Public access",
|
||||
"it": "Aperto al pubblico",
|
||||
"ru": "Свободный доступ",
|
||||
"de": "Der Sportplatz ist öffentlich zugänglich",
|
||||
"es": "Acceso público"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
],
|
||||
"applicableUnits": [
|
||||
{
|
||||
"useIfNoUnitGiven": true,
|
||||
"canonicalDenomination": "m",
|
||||
"alternativeDenomination": [
|
||||
"meter"
|
||||
|
@ -74,16 +75,16 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"default": true,
|
||||
"useAsDefaultInput": true,
|
||||
"canonicalDenomination": "cm",
|
||||
"alternativeDenomination": [
|
||||
"centimeter",
|
||||
"cms"
|
||||
],
|
||||
"human": {
|
||||
"en": "centimeter",
|
||||
"fr": "centimètre",
|
||||
"de": "Zentimeter"
|
||||
"en": " centimeter",
|
||||
"fr": " centimètre",
|
||||
"de": " Zentimeter"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1148,5 +1148,110 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"internet": {
|
||||
"question": {
|
||||
"en": "Does this place offer internet access?",
|
||||
"nl": "Biedt deze plaats internettoegang aan?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "internet_access=wlan",
|
||||
"then": {
|
||||
"en": "This place offers wireless internet access",
|
||||
"nl": "Deze plaats biedt draadloze internettoegang aan"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "internet_access=no",
|
||||
"then": {
|
||||
"en": "This place <b>does not</b> offer internet access",
|
||||
"nl": "Deze plaats biedt <b>geen</b> internettoegang aan"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "internet_access=yes",
|
||||
"then": {
|
||||
"en": "This place offers internet access",
|
||||
"nl": "Deze plaats biedt internettoegang aan"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": "internet_access=terminal",
|
||||
"then": {
|
||||
"en": "This place offers internet access via a terminal or computer",
|
||||
"nl": "Deze plaats biedt internettoegang via een terminal of computer aan"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "internet_access=wired",
|
||||
"then": {
|
||||
"en": "This place offers wired internet access",
|
||||
"nl": "Deze plaats biedt bedrade internettoegang aan"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"internet-fee": {
|
||||
"condition": {
|
||||
"and": [
|
||||
"internet_access!=no",
|
||||
"internet_access!="
|
||||
]
|
||||
},
|
||||
"question": {
|
||||
"en": "Is there a fee for internet access?",
|
||||
"nl": "Zijn er kosten voor internettoegang?"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "internet_access:fee=yes",
|
||||
"then": {
|
||||
"en": "There is a fee for the internet access at this place",
|
||||
"nl": "Er zijn kosten voor internettoegang op deze plaats"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "internet_access:fee=no",
|
||||
"then": {
|
||||
"en": "Internet access is free at this place",
|
||||
"nl": "Internettoegang is gratis op deze plaats"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": "internet_access:fee=customers",
|
||||
"then": {
|
||||
"en": "Internet access is free at this place, for customers only",
|
||||
"nl": "Internettoegang is gratis op deze plaats, alleen voor klanten"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"internet-ssid": {
|
||||
"condition": "internet_access=wlan",
|
||||
"question": {
|
||||
"en": "What is the network name for the wireless internet access?",
|
||||
"nl": "Wat is de netwerknaam voor de draadloze internettoegang?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "internet_access:ssid",
|
||||
"type": "string",
|
||||
"placeholder": {
|
||||
"en": "Enter the network name",
|
||||
"nl": "Voer de netwerknaam in"
|
||||
}
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "internet_access:ssid=Telekom",
|
||||
"then": "Telekom",
|
||||
"hideInAnswer": "_country!=de"
|
||||
}
|
||||
],
|
||||
"render": {
|
||||
"en": "The network name is <b>{internet_access:ssid}</b>",
|
||||
"nl": "De netwerknaam is <b>{internet_access:ssid}</b>"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -132,8 +132,7 @@
|
|||
"ca": " metre",
|
||||
"nb_NO": " meter",
|
||||
"es": " metro"
|
||||
},
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"canonicalDenomination": "ft",
|
||||
|
|
18
assets/themes/hotels/hotels.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"id": "hotels",
|
||||
"title": {
|
||||
"en": "Hotels"
|
||||
},
|
||||
"description": {
|
||||
"en": "On this map, you'll find hotels in your area"
|
||||
},
|
||||
"maintainer": "MapComplete",
|
||||
"version": "0.0.1",
|
||||
"icon": "./assets/layers/hotel/hotel.svg",
|
||||
"startLat": 50.8552,
|
||||
"startLon": 4.3755,
|
||||
"startZoom": 13,
|
||||
"layers": [
|
||||
"hotel"
|
||||
]
|
||||
}
|
|
@ -207,6 +207,10 @@
|
|||
"if": "theme=healthcare",
|
||||
"then": "./assets/layers/doctors/doctors.svg"
|
||||
},
|
||||
{
|
||||
"if": "theme=hotels",
|
||||
"then": "./assets/layers/hotel/hotel.svg"
|
||||
},
|
||||
{
|
||||
"if": "theme=indoors",
|
||||
"then": "./assets/layers/entrance/entrance.svg"
|
||||
|
|
|
@ -1,142 +1,142 @@
|
|||
[
|
||||
{
|
||||
"path": "maxspeed_10.svg",
|
||||
"path": "maxspeed_10 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_100.svg",
|
||||
"path": "maxspeed_100 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_110.svg",
|
||||
"path": "maxspeed_110 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_120.svg",
|
||||
"path": "maxspeed_120 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_130.svg",
|
||||
"path": "maxspeed_130 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_140.svg",
|
||||
"path": "maxspeed_140 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_20.svg",
|
||||
"path": "maxspeed_20 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_30.svg",
|
||||
"path": "maxspeed_30 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_40.svg",
|
||||
"path": "maxspeed_40 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_50.svg",
|
||||
"path": "maxspeed_50 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_60.svg",
|
||||
"path": "maxspeed_60 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_70.svg",
|
||||
"path": "maxspeed_70 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_80.svg",
|
||||
"path": "maxspeed_80 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "maxspeed_90.svg",
|
||||
"path": "maxspeed_90 mph.svg",
|
||||
"license": "CC 4.0",
|
||||
"authors": [
|
||||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -146,7 +146,7 @@
|
|||
"yopaseopor"
|
||||
],
|
||||
"sources": [
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30.svg"
|
||||
"https://raw.githubusercontent.com/yopaseopor/beta_preset_josm/master/ES/traffic_signs/ES/ES_R301-30 mph.svg"
|
||||
]
|
||||
}
|
||||
]
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -45,6 +45,7 @@
|
|||
"startZoom": 12,
|
||||
"widenFactor": 1.2,
|
||||
"layers": [
|
||||
"parking"
|
||||
"parking",
|
||||
"parking_spaces"
|
||||
]
|
||||
}
|
|
@ -3566,7 +3566,7 @@
|
|||
},
|
||||
"width": {
|
||||
"question": "Wie breit ist diese Tür bzw. dieser Eingang?",
|
||||
"render": "Diese Tür hat eine Durchgangsbreite von {canonical(width)} Meter"
|
||||
"render": "Diese Tür hat eine Durchgangsbreite von {canonical(width)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -4249,10 +4249,51 @@
|
|||
},
|
||||
"question": "Welche Bauform hat der Hydrant?",
|
||||
"render": " Hydranten-Typ: {fire_hydrant:type}"
|
||||
},
|
||||
"hydrant-couplings-diameters": {
|
||||
"question": "Welchen Durchmesser haben die Kupplungen dieses Hydranten?",
|
||||
"freeform": {
|
||||
"placeholder": "Kupplungsdurchmesser"
|
||||
},
|
||||
"render": "Kupplungsdurchmesser: {couplings:diameters}"
|
||||
},
|
||||
"hydrant-couplings": {
|
||||
"freeform": {
|
||||
"placeholder": "Art der Kupplung"
|
||||
},
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Storz-Kupplung"
|
||||
},
|
||||
"1": {
|
||||
"then": "UNI-Kupplung"
|
||||
},
|
||||
"2": {
|
||||
"then": "Barcelona-Kupplung"
|
||||
}
|
||||
},
|
||||
"question": "Welche Art von Kupplungen hat dieser Hydrant?",
|
||||
"render": "Kupplungen: {couplings:type}"
|
||||
},
|
||||
"hydrant-diameter": {
|
||||
"freeform": {
|
||||
"placeholder": "Rohrdurchmesser"
|
||||
},
|
||||
"question": "Was ist der Rohrdurchmesser dieses Hydranten?",
|
||||
"render": "Rohrdurchmesser: {canonical(fire_hydrant:diameter)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": "Hydrant"
|
||||
},
|
||||
"units": {
|
||||
"0": {
|
||||
"applicableUnits": {
|
||||
"0": {
|
||||
"human": "Millimeter"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"indoors": {
|
||||
|
@ -4366,7 +4407,7 @@
|
|||
"then": "Der Bordstein hat kein taktiles Pflaster."
|
||||
},
|
||||
"2": {
|
||||
"then": "Der Bordstein hat ein taktiles Pflaster, das aber falsch ist"
|
||||
"then": "Der Bordstein hat ein taktiles Pflaster, das aber falsch ist."
|
||||
}
|
||||
},
|
||||
"question": "Gibt es am Bordstein ein taktiles Pflaster?"
|
||||
|
@ -4648,7 +4689,7 @@
|
|||
}
|
||||
},
|
||||
"question": "Wie hoch ist die zulässige Höchstgeschwindigkeit, die man auf dieser Straße fahren darf?",
|
||||
"render": "Die zulässige Höchstgeschwindigkeit auf dieser Straße ist {maxspeed}"
|
||||
"render": "Die zulässige Höchstgeschwindigkeit auf dieser Straße ist {canonical(maxspeed)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -7156,4 +7197,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3566,7 +3566,7 @@
|
|||
},
|
||||
"width": {
|
||||
"question": "What is the width of this door/entrance?",
|
||||
"render": "This door has a width of {canonical(width)} meter"
|
||||
"render": "This door has a width of {canonical(width)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -4438,7 +4438,7 @@
|
|||
"then": "This kerb does not have tactile paving."
|
||||
},
|
||||
"2": {
|
||||
"then": "This kerb has tactile paving, but it is incorrect"
|
||||
"then": "This kerb has tactile paving, but it is incorrect."
|
||||
}
|
||||
},
|
||||
"question": "Is there tactile paving at this kerb?"
|
||||
|
@ -4720,7 +4720,7 @@
|
|||
}
|
||||
},
|
||||
"question": "What is the legal maximum speed one is allowed to drive on this road?",
|
||||
"render": "The maximum allowed speed on this road is {maxspeed}"
|
||||
"render": "The maximum allowed speed on this road is {canonical(maxspeed)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -7228,4 +7228,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3049,7 +3049,7 @@
|
|||
"then": "Cette bordure n'a pas de revêtement podotactile."
|
||||
},
|
||||
"2": {
|
||||
"then": "Cette bordure a un pavage tactile, mais il est incorrect"
|
||||
"then": "Cette bordure a un pavage tactile, mais il est incorrect."
|
||||
}
|
||||
},
|
||||
"question": "Y a-t-il un revêtement tactile sur cette bordure ?"
|
||||
|
@ -4459,4 +4459,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3406,6 +3406,9 @@
|
|||
"presets": {
|
||||
"0": {
|
||||
"title": "een toegang"
|
||||
},
|
||||
"1": {
|
||||
"title": "een binnendeur"
|
||||
}
|
||||
},
|
||||
"tagRenderings": {
|
||||
|
@ -3509,7 +3512,7 @@
|
|||
},
|
||||
"width": {
|
||||
"question": "Wat is de breedte van deze deur/toegang?",
|
||||
"render": "Deze deur heeft een breedte van {canonical(width)} meter"
|
||||
"render": "Deze deur heeft een breedte van {canonical(width)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -4221,7 +4224,43 @@
|
|||
"description": "Een basis voor indoor-navigatie: toont binnenruimtes",
|
||||
"name": "Binnenruimtes",
|
||||
"title": {
|
||||
"render": "Binnenruimte {name}"
|
||||
"render": "Binnenruimte {name}",
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Binnenruimte {name}"
|
||||
},
|
||||
"4": {
|
||||
"then": "Binnendeur {name}"
|
||||
},
|
||||
"3": {
|
||||
"then": "Gang in gebouw {name}"
|
||||
},
|
||||
"1": {
|
||||
"then": "Gebied in gebouw {name}"
|
||||
},
|
||||
"5": {
|
||||
"then": "Verdieping in gebouw {name}"
|
||||
},
|
||||
"2": {
|
||||
"then": "Muur in gebouw {name}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tagRenderings": {
|
||||
"name": {
|
||||
"render": "Deze ruimte heet {name}",
|
||||
"question": "Wat is de naam van deze ruimte?",
|
||||
"freeform": {
|
||||
"placeholder": "Naam van de ruimte"
|
||||
}
|
||||
},
|
||||
"ref": {
|
||||
"question": "Wat is het referentienummer van deze ruimte?",
|
||||
"freeform": {
|
||||
"placeholder": "Referentienummer van de ruimte (bv. '1.1' of A1' )"
|
||||
},
|
||||
"render": "Deze ruimte heeft het referentienummer {ref}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"information_board": {
|
||||
|
@ -4264,7 +4303,16 @@
|
|||
"1": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Drempes met of zonder"
|
||||
"question": "Stoepranden met of zonder voelbare bestrating"
|
||||
},
|
||||
"1": {
|
||||
"question": "Stoeprand met voelbare bestrating"
|
||||
},
|
||||
"2": {
|
||||
"question": "Stoeprand zonder voelbare bestrating"
|
||||
},
|
||||
"3": {
|
||||
"question": "Stoeprand zonder informatie over voelbare bestrating"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4303,6 +4351,20 @@
|
|||
}
|
||||
},
|
||||
"question": "Hoe hoog is deze stoeprand?"
|
||||
},
|
||||
"tactile-paving": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Deze stoeprand heeft voelbare bestrating."
|
||||
},
|
||||
"1": {
|
||||
"then": "Deze stoeprand heeft geen voelbare bestrating."
|
||||
},
|
||||
"2": {
|
||||
"then": "Deze stoeprand heeft voelbare bestrating, maar deze is incorrect."
|
||||
}
|
||||
},
|
||||
"question": "Is er voelbare bestrating bij deze stoeprand?"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -4353,6 +4415,10 @@
|
|||
"override": {
|
||||
"question": "Wanneer is deze kinderopvang geopend?"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"question": "Wat is de naam van deze faciliteit?",
|
||||
"render": "Deze faciliteit heet <b>{name}</b>"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -4423,7 +4489,7 @@
|
|||
"then": "Dit is een woonerf en heeft dus een maximale snelheid van 20km/h"
|
||||
}
|
||||
},
|
||||
"render": "De maximum toegestane snelheid op deze weg is {maxspeed}"
|
||||
"render": "De maximum toegestane snelheid op deze weg is {canonical(maxspeed)}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -6800,5 +6866,92 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"maproulette": {
|
||||
"filter": {
|
||||
"0": {
|
||||
"options": {
|
||||
"1": {
|
||||
"question": "Toon aangemaakte taken"
|
||||
},
|
||||
"8": {
|
||||
"question": "Toon uitgeschakelde taken"
|
||||
},
|
||||
"0": {
|
||||
"question": "Toon taken met alle statussen"
|
||||
},
|
||||
"3": {
|
||||
"question": "Toon vals-positieve taken"
|
||||
},
|
||||
"4": {
|
||||
"question": "Toon overgeslagen taken"
|
||||
},
|
||||
"5": {
|
||||
"question": "Toon verwijderde taken"
|
||||
},
|
||||
"6": {
|
||||
"question": "Toon al opgeloste taken"
|
||||
},
|
||||
"7": {
|
||||
"question": "Toon taken die als te lastig gemarkeerd zijn"
|
||||
},
|
||||
"2": {
|
||||
"question": "Toon opgeloste taken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Naam uitdaging bevat {search}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "ID uitdaging is {search}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Laag met alle taken uit MapRoulette",
|
||||
"name": "MapRoulette Taken"
|
||||
},
|
||||
"transit_routes": {
|
||||
"tagRenderings": {
|
||||
"operator": {
|
||||
"question": "Welk bedrijf exploiteert deze buslijn?",
|
||||
"render": "Deze buslijn wordt geëxploiteerd door {operator}"
|
||||
},
|
||||
"from": {
|
||||
"render": "Deze buslijn begint bij {from}",
|
||||
"question": "Wat is het beginpunt van deze buslijn?"
|
||||
},
|
||||
"to": {
|
||||
"render": "Deze buslijn eindigt bij {to}",
|
||||
"question": "Wat is het eindpunt van deze buslijn?"
|
||||
},
|
||||
"colour": {
|
||||
"question": "Wat is de kleur van deze buslijn?",
|
||||
"render": "Deze buslijn heeft de kleur {colour}"
|
||||
},
|
||||
"name": {
|
||||
"question": "Wat is de naam van deze buslijn (bv. Bus XX: Van => Via => Naar)"
|
||||
},
|
||||
"network": {
|
||||
"question": "Bij welk netwerk hoort deze buslijn?",
|
||||
"render": "Deze buslijn is onderdeel van het {network} netwerk"
|
||||
},
|
||||
"via": {
|
||||
"question": "Via welk punt gaat deze buslijn?",
|
||||
"render": "Deze buslijn gaat via {via}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": "Buslijn"
|
||||
},
|
||||
"description": "Laag met buslijnen",
|
||||
"name": "Buslijnen"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"readMessages": "Je hebt ongelezen berichten. Je moet deze lezen voordat je een punt verwijderd, een andere bijdrager heeft misschien feedback",
|
||||
"reasons": {
|
||||
"disused": "Het wordt niet meer onderhouden of is verwijderd",
|
||||
"duplicate": "Dit punt is een duplicaat van een ander punt",
|
||||
"duplicate": "Dit object is een duplicaat van een ander object",
|
||||
"notFound": "Het kon niet gevonden worden",
|
||||
"test": "Dit punt was een test en was nooit echt aanwezig"
|
||||
},
|
||||
|
@ -49,19 +49,19 @@
|
|||
"confirmIntro": "<h3>Voeg een {title} toe?</h3>Het punt dat je toevoegt, is <b>zichtbaar voor iedereen</b>. Veel applicaties gebruiken deze data, voeg dus enkel punten toe die echt bestaan.",
|
||||
"disableFilters": "Zet alle filters af",
|
||||
"disableFiltersExplanation": "Interessepunten kunnen verborgen zijn door een filter",
|
||||
"hasBeenImported": "Dit object is reeds geimporteerd",
|
||||
"hasBeenImported": "Dit object is reeds geïmporteerd",
|
||||
"import": {
|
||||
"hasBeenImported": "Dit object is geïmporteerd",
|
||||
"howToTest": "Voor testmode, voeg <b>test=true</b> of <b>backend=osm-test</b> to aan de URL. De wijzigingenset zal in de console geprint worden. Gelieve een PR te openen om dit thema als officieel thema toe te voegen en zo de import-knop te activeren.",
|
||||
"importTags": "Het element zal deze tags krijgen: {tags}",
|
||||
"officialThemesOnly": "In onofficiële thema's is de importeerknop uitgeschakeld om ongelukjes te vermijden",
|
||||
"wrongType": "Dit object is geen punt of lijn, en kan daarom niet geïmporteerd worden",
|
||||
"wrongTypeToConflate": "Dit element is geen punt of weg en kan dus niet samengevoegd worden",
|
||||
"wrongTypeToConflate": "Dit object is geen punt of weg en kan dus niet samengevoegd worden",
|
||||
"zoomInMore": "Zoom verder in om dit object af te handelen"
|
||||
},
|
||||
"importTags": "Het object zal deze tags krijgen: {tags}",
|
||||
"intro": "Kies hieronder welk punt je wilt toevoegen<br/>",
|
||||
"layerNotEnabled": "De laag {layer} is gedeactiveerd. Activeer deze om een punt toe te voegen",
|
||||
"layerNotEnabled": "De laag {layer} is gedeactiveerd. Activeer deze om een object toe te voegen",
|
||||
"openLayerControl": "Open de laag-instellingen",
|
||||
"pleaseLogin": "Gelieve je aan te melden om een punt toe te voegen",
|
||||
"presetInfo": "Het nieuwe object krijgt de attributen {tags}",
|
||||
|
@ -272,7 +272,8 @@
|
|||
"died": "Gestorven: {value}"
|
||||
},
|
||||
"searchWikidata": "Zoek op Wikidata",
|
||||
"wikipediaboxTitle": "Wikipedia"
|
||||
"wikipediaboxTitle": "Wikipedia",
|
||||
"searchToShort": "Je zoekopdracht is te kort, vul een langere tekst in"
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
|
@ -578,7 +579,8 @@
|
|||
"noNearOrIn": "Sorry, Ik begreep je opdracht niet omdat ik geen <code>dichtbij</code> of <code>in</code> in je zoekopdracht.\nProbeer iets als <code>Zoek drinkwater in Londen</code>, <code>Zoek frituur in Brussel</code><p></p>\n <p>Daarnaast kan je ook <code>info {cmd}</code> proberen, om info te krijgen over een enkel object.</p>",
|
||||
"nothingFound": "Sorry, ik kon niets vinden voor <code>{search}</code>, dus kan ik {layerTitle} niet zoeken",
|
||||
"overview": "Ik heb {length} overeenkomende items gevonden.",
|
||||
"searching": "Aan het zoeken naar {layerTitle} {mode} <code>{search}</code>…"
|
||||
"searching": "Aan het zoeken naar {layerTitle} {mode} <code>{search}</code>…",
|
||||
"docs": "Zoekt voor POIs in of nabij een locatie"
|
||||
},
|
||||
"shutdown": {
|
||||
"argmode": "Geeft aan op welke manier ik moet afsluiten. Dit moet één van de volgende woorden zijn: {verbs}",
|
||||
|
|
|
@ -34,6 +34,47 @@
|
|||
},
|
||||
"question": "Does this place have an audio induction loop for people with reduced hearing?"
|
||||
},
|
||||
"internet": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This place offers wireless internet access"
|
||||
},
|
||||
"1": {
|
||||
"then": "This place <b>does not</b> offer internet access"
|
||||
},
|
||||
"2": {
|
||||
"then": "This place offers internet access"
|
||||
},
|
||||
"3": {
|
||||
"then": "This place offers internet access via a terminal or computer"
|
||||
},
|
||||
"4": {
|
||||
"then": "This place offers wired internet access"
|
||||
}
|
||||
},
|
||||
"question": "Does this place offer internet access?"
|
||||
},
|
||||
"internet-fee": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "There is a fee for the internet access at this place"
|
||||
},
|
||||
"1": {
|
||||
"then": "Internet access is free at this place"
|
||||
},
|
||||
"2": {
|
||||
"then": "Internet access is free at this place, for customers only"
|
||||
}
|
||||
},
|
||||
"question": "Is there a fee for internet access?"
|
||||
},
|
||||
"internet-ssid": {
|
||||
"freeform": {
|
||||
"placeholder": "Enter the network name"
|
||||
},
|
||||
"question": "What is the network name for the wireless internet access?",
|
||||
"render": "The network name is <b>{internet_access:ssid}</b>"
|
||||
},
|
||||
"level": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
|
|
|
@ -23,6 +23,47 @@
|
|||
"email": {
|
||||
"question": "Wat is het e-mailadres van {title()}?"
|
||||
},
|
||||
"internet": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Deze plaats biedt draadloze internettoegang aan"
|
||||
},
|
||||
"1": {
|
||||
"then": "Deze plaats biedt <b>geen</b> internettoegang aan"
|
||||
},
|
||||
"2": {
|
||||
"then": "Deze plaats biedt internettoegang aan"
|
||||
},
|
||||
"3": {
|
||||
"then": "Deze plaats biedt internettoegang via een terminal of computer aan"
|
||||
},
|
||||
"4": {
|
||||
"then": "Deze plaats biedt bedrade internettoegang aan"
|
||||
}
|
||||
},
|
||||
"question": "Biedt deze plaats internettoegang aan?"
|
||||
},
|
||||
"internet-fee": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Er zijn kosten voor internettoegang op deze plaats"
|
||||
},
|
||||
"1": {
|
||||
"then": "Internettoegang is gratis op deze plaats"
|
||||
},
|
||||
"2": {
|
||||
"then": "Internettoegang is gratis op deze plaats, alleen voor klanten"
|
||||
}
|
||||
},
|
||||
"question": "Zijn er kosten voor internettoegang?"
|
||||
},
|
||||
"internet-ssid": {
|
||||
"freeform": {
|
||||
"placeholder": "Voer de netwerknaam in"
|
||||
},
|
||||
"question": "Wat is de netwerknaam voor de draadloze internettoegang?",
|
||||
"render": "De netwerknaam is <b>{internet_access:ssid}</b>"
|
||||
},
|
||||
"level": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
|
|
|
@ -906,6 +906,28 @@
|
|||
"tagRenderings": {
|
||||
"streetname": {
|
||||
"render": "Diese Straße heißt {name}"
|
||||
},
|
||||
"left-right-questions": {
|
||||
"renderings": {
|
||||
"1": {
|
||||
"question": "Gibt es auf dieser Straßenseite einen Bürgersteig?",
|
||||
"mappings": {
|
||||
"1": {
|
||||
"then": "Nein, es gibt keinen Bürgersteig für Fußgänger"
|
||||
},
|
||||
"0": {
|
||||
"then": "Ja, es gibt einen Bürgersteig auf dieser Straßenseite"
|
||||
},
|
||||
"2": {
|
||||
"then": "Es gibt einen separat kartierten Bürgersteig für Fußgänger"
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"question": "Wie breit ist der Bürgersteig auf dieser Straßenseite?",
|
||||
"render": "Dieser Bürgersteig ist {sidewalk:left|right:width}m breit"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
|
@ -1008,4 +1030,4 @@
|
|||
"shortDescription": "Eine Karte mit Abfalleimern",
|
||||
"title": "Abfalleimer"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"cannotBeDeleted": "這圖徵無法刪除",
|
||||
"delete": "刪除",
|
||||
"explanations": {
|
||||
"hardDelete": "這個點已經在開放街圖被刪除了,可以被實驗性的貢獻者恢復",
|
||||
"hardDelete": "這個圖徵已經在開放街圖被刪除了,可以被實驗性的貢獻者恢復",
|
||||
"selectReason": "請選擇為什麼這個圖徵應該被刪除",
|
||||
"softDelete": "這個圖徵已經被更新,然後從程式被隱藏了。<span class=\"subtle\">{reason}</span>"
|
||||
},
|
||||
|
|
|
@ -7,22 +7,21 @@ describe("Unit", () => {
|
|||
|
||||
it("should convert a value back and forth", () => {
|
||||
|
||||
const unit = new Denomination({
|
||||
const denomintion = new Denomination({
|
||||
"canonicalDenomination": "MW",
|
||||
"alternativeDenomination": ["megawatts", "megawatt"],
|
||||
"human": {
|
||||
"en": " megawatts",
|
||||
"nl": " megawatt"
|
||||
},
|
||||
"default": true
|
||||
}, "test");
|
||||
|
||||
const canonical = unit.canonicalValue("5")
|
||||
const canonical = denomintion.canonicalValue("5", true)
|
||||
expect(canonical).eq( "5 MW")
|
||||
const units = new Unit(["key"], [unit], false)
|
||||
const [detected, detectedDenom] = units.findDenomination("5 MW")
|
||||
const units = new Unit(["key"], [denomintion], false)
|
||||
const [detected, detectedDenom] = units.findDenomination("5 MW", () => "be")
|
||||
expect(detected).eq( "5")
|
||||
expect(detectedDenom).eq( unit)
|
||||
expect(detectedDenom).eq( denomintion)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
|