forked from MapComplete/MapComplete
Rework units to allow picking different default units in different locations, fixes #1011
This commit is contained in:
parent
e981abd2aa
commit
5da76b9418
17 changed files with 149 additions and 100 deletions
|
@ -235,7 +235,7 @@ export default class SimpleMetaTaggers {
|
||||||
|
|
||||||
private static canonicalize = new SimpleMetaTagger(
|
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"],
|
keys: ["Theme-defined keys"],
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -261,13 +261,14 @@ export default class SimpleMetaTaggers {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const value = feature.properties[key]
|
const value = feature.properties[key]
|
||||||
const denom = unit.findDenomination(value)
|
const denom = unit.findDenomination(value, () => feature.properties["_country"])
|
||||||
if (denom === undefined) {
|
if (denom === undefined) {
|
||||||
// no valid value found
|
// no valid value found
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const [, denomination] = denom;
|
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) {
|
if (canonical === value) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
import {Translation} from "../UI/i18n/Translation";
|
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 Translations from "../UI/i18n/Translations";
|
||||||
import {Store, UIEventSource} from "../Logic/UIEventSource";
|
import {Store} from "../Logic/UIEventSource";
|
||||||
import BaseUIElement from "../UI/BaseUIElement";
|
import BaseUIElement from "../UI/BaseUIElement";
|
||||||
import Toggle from "../UI/Input/Toggle";
|
import Toggle from "../UI/Input/Toggle";
|
||||||
|
|
||||||
export class Denomination {
|
export class Denomination {
|
||||||
public readonly canonical: string;
|
public readonly canonical: string;
|
||||||
public readonly _canonicalSingular: 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 prefix: boolean;
|
||||||
public readonly alternativeDenominations: string [];
|
public readonly alternativeDenominations: string [];
|
||||||
private readonly _human: Translation;
|
private readonly _human: Translation;
|
||||||
private readonly _humanSingular?: Translation;
|
private readonly _humanSingular?: Translation;
|
||||||
|
|
||||||
|
|
||||||
constructor(json: ApplicableUnitJson, context: string) {
|
constructor(json: DenominationConfigJson, context: string) {
|
||||||
context = `${context}.unit(${json.canonicalDenomination})`
|
context = `${context}.unit(${json.canonicalDenomination})`
|
||||||
this.canonical = json.canonicalDenomination.trim()
|
this.canonical = json.canonicalDenomination.trim()
|
||||||
if (this.canonical === undefined) {
|
if (this.canonical === undefined) {
|
||||||
|
@ -32,8 +33,12 @@ export class Denomination {
|
||||||
|
|
||||||
this.alternativeDenominations = json.alternativeDenomination?.map(v => v.trim()) ?? []
|
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._human = Translations.T(json.human, context + "human")
|
||||||
this._humanSingular = Translations.T(json.humanSingular, context + "humanSingular")
|
this._humanSingular = Translations.T(json.humanSingular, context + "humanSingular")
|
||||||
|
|
||||||
|
@ -68,32 +73,31 @@ export class Denomination {
|
||||||
* const unit = new Denomination({
|
* const unit = new Denomination({
|
||||||
* canonicalDenomination: "m",
|
* canonicalDenomination: "m",
|
||||||
* alternativeDenomination: ["meter"],
|
* alternativeDenomination: ["meter"],
|
||||||
* 'default': true,
|
|
||||||
* human: {
|
* human: {
|
||||||
* en: "meter"
|
* en: "meter"
|
||||||
* }
|
* }
|
||||||
* }, "test")
|
* }, "test")
|
||||||
* unit.canonicalValue("42m") // =>"42 m"
|
* unit.canonicalValue("42m", true) // =>"42 m"
|
||||||
* unit.canonicalValue("42") // =>"42 m"
|
* unit.canonicalValue("42", true) // =>"42 m"
|
||||||
* unit.canonicalValue("42 m") // =>"42 m"
|
* unit.canonicalValue("42 m", true) // =>"42 m"
|
||||||
* unit.canonicalValue("42 meter") // =>"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
|
* // Should be trimmed if canonical is empty
|
||||||
* const unit = new Denomination({
|
* const unit = new Denomination({
|
||||||
* canonicalDenomination: "",
|
* canonicalDenomination: "",
|
||||||
* alternativeDenomination: ["meter","m"],
|
* alternativeDenomination: ["meter","m"],
|
||||||
* 'default': true,
|
|
||||||
* human: {
|
* human: {
|
||||||
* en: "meter"
|
* en: "meter"
|
||||||
* }
|
* }
|
||||||
* }, "test")
|
* }, "test")
|
||||||
* unit.canonicalValue("42m") // =>"42"
|
* unit.canonicalValue("42m", true) // =>"42"
|
||||||
* unit.canonicalValue("42") // =>"42"
|
* unit.canonicalValue("42", true) // =>"42"
|
||||||
* unit.canonicalValue("42 m") // =>"42"
|
* unit.canonicalValue("42 m", true) // =>"42"
|
||||||
* unit.canonicalValue("42 meter") // =>"42"
|
* unit.canonicalValue("42 meter", true) // =>"42"
|
||||||
*/
|
*/
|
||||||
public canonicalValue(value: string, actAsDefault?: boolean) : string {
|
public canonicalValue(value: string, actAsDefault: boolean) : string {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +118,7 @@ export class Denomination {
|
||||||
*
|
*
|
||||||
* Returns null if it doesn't match this unit
|
* 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) {
|
if (value === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -153,15 +157,26 @@ export class Denomination {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.default || actAsDefault) {
|
if (!actAsDefault) {
|
||||||
const parsed = Number(value.trim())
|
return null
|
||||||
if (!isNaN(parsed)) {
|
}
|
||||||
return value.trim();
|
|
||||||
}
|
const parsed = Number(value.trim())
|
||||||
|
if (!isNaN(parsed)) {
|
||||||
|
return value.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isDefaultUnit(country: () => string) {
|
||||||
|
if(this.useIfNoUnitGiven === true){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if(this.useIfNoUnitGiven === false){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return this.useIfNoUnitGiven.indexOf(country()) >= 0
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -14,13 +14,32 @@ export default interface UnitConfigJson {
|
||||||
/**
|
/**
|
||||||
* The possible denominations
|
* 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
|
* e.g. "m" for meters
|
||||||
* If the user inputs '42', the canonical value will be added and it'll become '42m'.
|
* 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
|
* In this case, an empty string should be used
|
||||||
*/
|
*/
|
||||||
canonicalDenomination: string,
|
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,
|
canonicalDenominationSingular?: string,
|
||||||
|
|
||||||
|
@ -63,9 +85,5 @@ export interface ApplicableUnitJson {
|
||||||
*/
|
*/
|
||||||
prefix?: boolean
|
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
|
|
||||||
}
|
}
|
|
@ -8,14 +8,11 @@ export class Unit {
|
||||||
public readonly appliesToKeys: Set<string>;
|
public readonly appliesToKeys: Set<string>;
|
||||||
public readonly denominations: Denomination[];
|
public readonly denominations: Denomination[];
|
||||||
public readonly denominationsSorted: Denomination[];
|
public readonly denominationsSorted: Denomination[];
|
||||||
public readonly defaultDenom: Denomination;
|
|
||||||
public readonly eraseInvalid: boolean;
|
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.appliesToKeys = new Set(appliesToKeys);
|
||||||
this.denominations = applicableUnits;
|
this.denominations = applicableDenominations;
|
||||||
this.defaultDenom = applicableUnits.filter(denom => denom.default)[0]
|
|
||||||
this.eraseInvalid = eraseInvalid
|
this.eraseInvalid = eraseInvalid
|
||||||
|
|
||||||
const seenUnitExtensions = new Set<string>();
|
const seenUnitExtensions = new Set<string>();
|
||||||
|
@ -52,8 +49,6 @@ export class Unit {
|
||||||
addPostfixesOf(denomination._canonicalSingular)
|
addPostfixesOf(denomination._canonicalSingular)
|
||||||
denomination.alternativeDenominations.forEach(addPostfixesOf)
|
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
|
// Some keys do have unit handling
|
||||||
|
|
||||||
const defaultSet = json.applicableUnits.filter(u => u.default === true)
|
if(json.applicableUnits.some(denom => denom.useAsDefaultInput !== undefined)){
|
||||||
// No default is defined - we pick the first as default
|
json.applicableUnits.forEach(denom => {
|
||||||
if (defaultSet.length === 0) {
|
denom.useAsDefaultInput = denom.useAsDefaultInput ?? false
|
||||||
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(", ")}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const applicable = json.applicableUnits.map((u, i) => new Denomination(u, `${ctx}.units[${i}]`))
|
const applicable = json.applicableUnits.map((u, i) => new Denomination(u, `${ctx}.units[${i}]`))
|
||||||
return new Unit(appliesTo, applicable, json.eraseInvalidValues ?? false)
|
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
|
* 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) {
|
if (valueWithDenom === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
const defaultDenom = this.getDefaultDenomination(country)
|
||||||
for (const denomination of this.denominationsSorted) {
|
for (const denomination of this.denominationsSorted) {
|
||||||
const bare = denomination.StrippedValue(valueWithDenom)
|
const bare = denomination.StrippedValue(valueWithDenom, defaultDenom === denomination)
|
||||||
if (bare !== null) {
|
if (bare !== null) {
|
||||||
return [bare, denomination]
|
return [bare, denomination]
|
||||||
}
|
}
|
||||||
|
@ -109,11 +101,11 @@ export class Unit {
|
||||||
return [undefined, undefined]
|
return [undefined, undefined]
|
||||||
}
|
}
|
||||||
|
|
||||||
asHumanLongValue(value: string): BaseUIElement {
|
asHumanLongValue(value: string, country: () => string): BaseUIElement {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const [stripped, denom] = this.findDenomination(value)
|
const [stripped, denom] = this.findDenomination(value, country)
|
||||||
const human = stripped === "1" ? denom?.humanSingular : denom?.human
|
const human = stripped === "1" ? denom?.humanSingular : denom?.human
|
||||||
if (human === undefined) {
|
if (human === undefined) {
|
||||||
return new FixedUiElement(stripped ?? value);
|
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) {
|
public getDefaultInput(country: () => string | string[]) {
|
||||||
if (str.endsWith(denominationPart)) {
|
console.log("Searching the default denomination for input", country)
|
||||||
return str.substring(0, str.length - denominationPart.length).trim()
|
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 this.denominations[0]
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,6 +20,7 @@ import {QueryParameters} from "../../Logic/Web/QueryParameters";
|
||||||
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
||||||
import {InputElement} from "../Input/InputElement";
|
import {InputElement} from "../Input/InputElement";
|
||||||
import {DropDown} from "../Input/DropDown";
|
import {DropDown} from "../Input/DropDown";
|
||||||
|
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||||
|
|
||||||
export default class FilterView extends VariableUiElement {
|
export default class FilterView extends VariableUiElement {
|
||||||
constructor(filteredLayer: UIEventSource<FilteredLayer[]>,
|
constructor(filteredLayer: UIEventSource<FilteredLayer[]>,
|
||||||
|
@ -91,7 +92,7 @@ export default class FilterView extends VariableUiElement {
|
||||||
if (filteredLayer.layerDef.name === undefined) {
|
if (filteredLayer.layerDef.name === undefined) {
|
||||||
// Name is not defined: we hide this one
|
// Name is not defined: we hide this one
|
||||||
return new Toggle(
|
return new Toggle(
|
||||||
filteredLayer?.layerDef?.description?.Clone()?.SetClass("subtle") ,
|
new FixedUiElement(filteredLayer?.layerDef?.id ).SetClass("block") ,
|
||||||
undefined,
|
undefined,
|
||||||
state?.featureSwitchIsDebugging
|
state?.featureSwitchIsDebugging
|
||||||
);
|
);
|
||||||
|
|
|
@ -90,7 +90,7 @@ export class TextFieldDef {
|
||||||
if (options.unit !== undefined) {
|
if (options.unit !== undefined) {
|
||||||
// Reformatting is handled by the unit in this case
|
// Reformatting is handled by the unit in this case
|
||||||
options["isValid"] = str => {
|
options["isValid"] = str => {
|
||||||
const denom = options.unit.findDenomination(str);
|
const denom = options.unit.findDenomination(str, options?.country);
|
||||||
if (denom === undefined) {
|
if (denom === undefined) {
|
||||||
return false;
|
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")
|
unitDropDown.SetClass("w-min")
|
||||||
|
|
||||||
const fixedDenom = unit.denominations.length === 1 ? unit.denominations[0] : undefined
|
const fixedDenom = unit.denominations.length === 1 ? unit.denominations[0] : undefined
|
||||||
|
@ -169,7 +169,7 @@ export class TextFieldDef {
|
||||||
},
|
},
|
||||||
(valueWithDenom: string) => {
|
(valueWithDenom: string) => {
|
||||||
// Take the value from OSM and feed it into the textfield and the dropdown
|
// 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) {
|
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)
|
// 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]
|
return [undefined, fixedDenom]
|
||||||
|
|
|
@ -617,6 +617,7 @@ export default class TagRenderingQuestion extends Combine {
|
||||||
const tagsData = tags.data;
|
const tagsData = tags.data;
|
||||||
const feature = state?.allElements?.ContainingFeatures?.get(tagsData.id)
|
const feature = state?.allElements?.ContainingFeatures?.get(tagsData.id)
|
||||||
const center = feature != undefined ? GeoOperations.centerpointCoordinates(feature) : [0, 0]
|
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({
|
const input: InputElement<string> = ValidatedTextField.ForType(configuration.freeform.type)?.ConstructInputElement({
|
||||||
country: () => tagsData._country,
|
country: () => tagsData._country,
|
||||||
location: [center[1], center[0]],
|
location: [center[1], center[0]],
|
||||||
|
|
|
@ -1273,6 +1273,9 @@ export default class SpecialVisualizations {
|
||||||
const tagRendering = layer.tagRenderings.find(tr => tr.id === tagRenderingId)
|
const tagRendering = layer.tagRenderings.find(tr => tr.id === tagRenderingId)
|
||||||
tagRenderings.push([layer, tagRendering])
|
tagRenderings.push([layer, tagRendering])
|
||||||
}
|
}
|
||||||
|
if(tagRenderings.length === 0){
|
||||||
|
throw "Could not create stolen tagrenddering: tagRenderings not found"
|
||||||
|
}
|
||||||
return new VariableUiElement(featureTags.map(tags => {
|
return new VariableUiElement(featureTags.map(tags => {
|
||||||
const featureId = tags[featureIdKey]
|
const featureId = tags[featureIdKey]
|
||||||
if (featureId === undefined) {
|
if (featureId === undefined) {
|
||||||
|
|
|
@ -185,6 +185,7 @@
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"meter"
|
"meter"
|
||||||
],
|
],
|
||||||
|
"useIfNoUnitGiven": true,
|
||||||
"human": {
|
"human": {
|
||||||
"en": "meter",
|
"en": "meter",
|
||||||
"fr": "mètre",
|
"fr": "mètre",
|
||||||
|
@ -193,7 +194,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": true,
|
"useAsDefaultInput": true,
|
||||||
"canonicalDenomination": "cm",
|
"canonicalDenomination": "cm",
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"centimeter",
|
"centimeter",
|
||||||
|
|
|
@ -467,10 +467,12 @@
|
||||||
"units": [
|
"units": [
|
||||||
{
|
{
|
||||||
"appliesToKey": [
|
"appliesToKey": [
|
||||||
"kerb:height"
|
"kerb:height",
|
||||||
|
"width"
|
||||||
],
|
],
|
||||||
"applicableUnits": [
|
"applicableUnits": [
|
||||||
{
|
{
|
||||||
|
"useIfNoUnitGiven": true,
|
||||||
"canonicalDenomination": "m",
|
"canonicalDenomination": "m",
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"meter"
|
"meter"
|
||||||
|
@ -483,7 +485,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": true,
|
"useAsDefaultInput": true,
|
||||||
"canonicalDenomination": "cm",
|
"canonicalDenomination": "cm",
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"centimeter",
|
"centimeter",
|
||||||
|
|
|
@ -456,7 +456,6 @@
|
||||||
{
|
{
|
||||||
"applicableUnits": [
|
"applicableUnits": [
|
||||||
{
|
{
|
||||||
"default": true,
|
|
||||||
"canonicalDenomination": "",
|
"canonicalDenomination": "",
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"mm",
|
"mm",
|
||||||
|
|
|
@ -339,8 +339,7 @@
|
||||||
"nl": "centimeter",
|
"nl": "centimeter",
|
||||||
"de": "Zentimeter",
|
"de": "Zentimeter",
|
||||||
"fr": "centimètre"
|
"fr": "centimètre"
|
||||||
},
|
}
|
||||||
"default": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"canonicalDenomination": "m",
|
"canonicalDenomination": "m",
|
||||||
|
|
|
@ -154,7 +154,6 @@
|
||||||
"kmh",
|
"kmh",
|
||||||
"kph"
|
"kph"
|
||||||
],
|
],
|
||||||
"default": true,
|
|
||||||
"human": {
|
"human": {
|
||||||
"en": "kilometers/hour",
|
"en": "kilometers/hour",
|
||||||
"ca": "quilòmetres/hora",
|
"ca": "quilòmetres/hora",
|
||||||
|
@ -172,6 +171,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"canonicalDenomination": "mph",
|
"canonicalDenomination": "mph",
|
||||||
|
"useIfNoUnitGiven": ["gb","us"],
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"m/u",
|
"m/u",
|
||||||
"mh",
|
"mh",
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
],
|
],
|
||||||
"applicableUnits": [
|
"applicableUnits": [
|
||||||
{
|
{
|
||||||
|
"useIfNoUnitGiven": true,
|
||||||
"canonicalDenomination": "m",
|
"canonicalDenomination": "m",
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"meter"
|
"meter"
|
||||||
|
@ -74,16 +75,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": true,
|
"useAsDefaultInput": true,
|
||||||
"canonicalDenomination": "cm",
|
"canonicalDenomination": "cm",
|
||||||
"alternativeDenomination": [
|
"alternativeDenomination": [
|
||||||
"centimeter",
|
"centimeter",
|
||||||
"cms"
|
"cms"
|
||||||
],
|
],
|
||||||
"human": {
|
"human": {
|
||||||
"en": "centimeter",
|
"en": " centimeter",
|
||||||
"fr": "centimètre",
|
"fr": " centimètre",
|
||||||
"de": "Zentimeter"
|
"de": " Zentimeter"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -132,8 +132,7 @@
|
||||||
"ca": " metre",
|
"ca": " metre",
|
||||||
"nb_NO": " meter",
|
"nb_NO": " meter",
|
||||||
"es": " metro"
|
"es": " metro"
|
||||||
},
|
}
|
||||||
"default": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"canonicalDenomination": "ft",
|
"canonicalDenomination": "ft",
|
||||||
|
|
|
@ -215,10 +215,6 @@
|
||||||
"if": "theme=indoors",
|
"if": "theme=indoors",
|
||||||
"then": "./assets/layers/entrance/entrance.svg"
|
"then": "./assets/layers/entrance/entrance.svg"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"if": "theme=kakampink",
|
|
||||||
"then": "bug"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"if": "theme=kerbs_and_crossings",
|
"if": "theme=kerbs_and_crossings",
|
||||||
"then": "./assets/layers/kerbs/KerbIcon.svg"
|
"then": "./assets/layers/kerbs/KerbIcon.svg"
|
||||||
|
|
|
@ -7,22 +7,21 @@ describe("Unit", () => {
|
||||||
|
|
||||||
it("should convert a value back and forth", () => {
|
it("should convert a value back and forth", () => {
|
||||||
|
|
||||||
const unit = new Denomination({
|
const denomintion = new Denomination({
|
||||||
"canonicalDenomination": "MW",
|
"canonicalDenomination": "MW",
|
||||||
"alternativeDenomination": ["megawatts", "megawatt"],
|
"alternativeDenomination": ["megawatts", "megawatt"],
|
||||||
"human": {
|
"human": {
|
||||||
"en": " megawatts",
|
"en": " megawatts",
|
||||||
"nl": " megawatt"
|
"nl": " megawatt"
|
||||||
},
|
},
|
||||||
"default": true
|
|
||||||
}, "test");
|
}, "test");
|
||||||
|
|
||||||
const canonical = unit.canonicalValue("5")
|
const canonical = denomintion.canonicalValue("5", true)
|
||||||
expect(canonical).eq( "5 MW")
|
expect(canonical).eq( "5 MW")
|
||||||
const units = new Unit(["key"], [unit], false)
|
const units = new Unit(["key"], [denomintion], false)
|
||||||
const [detected, detectedDenom] = units.findDenomination("5 MW")
|
const [detected, detectedDenom] = units.findDenomination("5 MW", () => "be")
|
||||||
expect(detected).eq( "5")
|
expect(detected).eq( "5")
|
||||||
expect(detectedDenom).eq( unit)
|
expect(detectedDenom).eq( denomintion)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue