forked from MapComplete/MapComplete
Themes(toilets): add an allowed range to some freeform inputs, allow to specify 'units' in the freeform, add the possibility to convert units
This commit is contained in:
parent
32cb8f489f
commit
fb8ead2a2c
16 changed files with 270 additions and 103 deletions
|
|
@ -4,12 +4,17 @@
|
|||
import Validators from "./Validators"
|
||||
import { ExclamationIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
|
||||
import { createEventDispatcher, onDestroy } from "svelte"
|
||||
import { Validator } from "./Validator"
|
||||
import { Unit } from "../../Models/Unit"
|
||||
import UnitInput from "../Popup/UnitInput.svelte"
|
||||
import { Utils } from "../../Utils"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import type { ValueRange } from "../../Models/ThemeConfig/TagRenderingConfig"
|
||||
import Translations from "../i18n/Translations"
|
||||
import FloatValidator from "./Validators/FloatValidator"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
|
||||
export let type: ValidatorType
|
||||
export let feedback: UIEventSource<Translation> | undefined = undefined
|
||||
|
|
@ -18,6 +23,7 @@
|
|||
export let placeholder: string | Translation | undefined = undefined
|
||||
export let autofocus: boolean = false
|
||||
export let unit: Unit = undefined
|
||||
export let range: ValueRange = undefined
|
||||
/**
|
||||
* Valid state, exported to the calling component
|
||||
*/
|
||||
|
|
@ -42,7 +48,7 @@
|
|||
|
||||
function initValueAndDenom() {
|
||||
if (unit && value.data) {
|
||||
const [v, denom] = unit?.findDenomination(value.data, getCountry)
|
||||
const [v, denom] = unit.findDenomination(value.data, getCountry)
|
||||
if (denom) {
|
||||
unvalidatedText.setData(v)
|
||||
selectedUnit.setData(denom.canonical)
|
||||
|
|
@ -62,7 +68,6 @@
|
|||
}
|
||||
}
|
||||
initValueAndDenom()
|
||||
|
||||
$: {
|
||||
// The type changed -> reset some values
|
||||
validator = Validators.get(type ?? "string")
|
||||
|
|
@ -77,6 +82,41 @@
|
|||
initValueAndDenom()
|
||||
}
|
||||
|
||||
const t = Translations.t.validation.generic
|
||||
|
||||
/**
|
||||
* Side effect: sets the feedback, returns true/false if valid
|
||||
* @param canonicalValue
|
||||
*/
|
||||
function validateRange(canonicalValue: number): boolean {
|
||||
if (!range) {
|
||||
return true
|
||||
}
|
||||
if (canonicalValue < range.warnBelow) {
|
||||
feedback.set(t.suspiciouslyLow)
|
||||
}
|
||||
if (canonicalValue > range.warnAbove) {
|
||||
feedback.set(t.suspiciouslyHigh)
|
||||
}
|
||||
if (canonicalValue > range.max) {
|
||||
let max: number | string | BaseUIElement = range.max
|
||||
if (unit) {
|
||||
max = unit.asHumanLongValue(max)
|
||||
}
|
||||
feedback.set(t.tooHigh.Subs({ max }))
|
||||
return false
|
||||
}
|
||||
if (canonicalValue < range.min) {
|
||||
let min: number | string | BaseUIElement = range.min
|
||||
if (unit) {
|
||||
min = unit.asHumanLongValue(min)
|
||||
}
|
||||
feedback.set(t.tooLow.Subs({ min }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function setValues() {
|
||||
// Update the value stores
|
||||
const v = unvalidatedText.data
|
||||
|
|
@ -92,13 +132,22 @@
|
|||
}
|
||||
|
||||
if (selectedUnit.data) {
|
||||
value.setData(unit.toOsm(v, selectedUnit.data))
|
||||
const canonicalValue = unit.valueInCanonical(v + selectedUnit.data)
|
||||
if (validateRange(canonicalValue)) {
|
||||
value.setData(unit.toOsm(v, selectedUnit.data))
|
||||
} else {
|
||||
value.set(undefined)
|
||||
}
|
||||
} else {
|
||||
value.setData(v)
|
||||
if (validateRange(v)) {
|
||||
value.setData(v)
|
||||
} else {
|
||||
value.set(undefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(unvalidatedText.addCallbackAndRun((_) => setValues()))
|
||||
onDestroy(unvalidatedText.addCallbackAndRun(() => setValues()))
|
||||
if (unit === undefined) {
|
||||
onDestroy(
|
||||
value.addCallbackAndRunD((fromUpstream) => {
|
||||
|
|
@ -110,7 +159,7 @@
|
|||
} else {
|
||||
// Handled by the UnitInput
|
||||
}
|
||||
onDestroy(selectedUnit.addCallback((_) => setValues()))
|
||||
onDestroy(selectedUnit.addCallback(() => setValues()))
|
||||
if (validator === undefined) {
|
||||
throw (
|
||||
"Not a valid type (no validator found) for type '" +
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ export default class FloatValidator extends Validator {
|
|||
* new FloatValidator().isValid("0,2") // => true
|
||||
*/
|
||||
isValid(str: string) {
|
||||
console.log("Is valid?", str, FloatValidator.formattingHasComma)
|
||||
if (!FloatValidator.formattingHasComma) {
|
||||
str = str.replace(",", ".")
|
||||
}
|
||||
|
|
@ -28,7 +27,11 @@ export default class FloatValidator extends Validator {
|
|||
if (!FloatValidator.formattingHasComma) {
|
||||
str = str.replace(",", ".")
|
||||
}
|
||||
return "" + Number(str)
|
||||
let formatted = "" + Number(str)
|
||||
if (str.startsWith("0") && str.length > 1 && str.indexOf(".") < 0) {
|
||||
formatted = "0" + formatted
|
||||
}
|
||||
return formatted
|
||||
}
|
||||
|
||||
getFeedback(s: string): Translation {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue