UX: make working with ranges and units easier for theme developers, show ranges in selected unit by converting them

This commit is contained in:
Pieter Vander Vennet 2025-09-11 02:13:07 +02:00
parent d64ad9b643
commit e157a84710
5 changed files with 25 additions and 15 deletions

View file

@ -215,6 +215,9 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
}
}
}
if (json["range"]) {
context.err("Detected a range in the tagRendering. A `range` goes in the freeform object")
}
if (json.render && json["question"] && json.freeform === undefined) {
context.err(
`Detected a tagrendering which takes input without freeform key in ${context}; the question is ${new Translation(

View file

@ -1,6 +1,7 @@
import { TagConfigJson } from "./TagConfigJson"
import { TagRenderingConfigJson } from "./TagRenderingConfigJson"
import type { Translatable } from "./Translatable"
import RewritableConfigJson from "./RewritableConfigJson"
export interface MappingConfigJson {
/**
@ -203,7 +204,7 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
*
* question: What are common options?
*/
mappings?: MappingConfigJson[]
mappings?: MappingConfigJson[] | RewritableConfigJson<MappingConfigJson>
/**
* question: Should a contributor be allowed to select multiple mappings?
@ -298,13 +299,17 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
helperArgs?: any
/**
* question: what units
* question: what units/denominations should be shown?
*
* If this is a string, the corresponding values from "unit.json" will be used, such as
* `pressure`, `power`, `speed`, `distance`
* See [the generated documentation](Docs/builtin_units.md) for more information
*
* group: hidden
*
* Note: this is actually a syntactic sugar and is translated to the unit-syntax on layer level
*/
unit?: {
unit?: string | {
/**
* What is the quantity? E.g. 'voltage', 'speed', ...
* See [builtin_units.md] for options

View file

@ -5,10 +5,7 @@ import { TagUtils } from "../../Logic/Tags/TagUtils"
import { And } from "../../Logic/Tags/And"
import { Utils } from "../../Utils"
import { Tag } from "../../Logic/Tags/Tag"
import {
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "./Json/QuestionableTagRenderingConfigJson"
import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson"
import Validators, { ValidatorType } from "../../UI/InputElement/Validators"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
import { RegexTag } from "../../Logic/Tags/RegexTag"
@ -822,7 +819,7 @@ export default class TagRenderingConfig {
() => currentProperties["_country"]
)
// In general, we want a space between the amount and the unit
freeformValue = formatted + " " + denom.canonical
freeformValue = formatted + (denom.addSpace ? " " : "") + denom.canonical
} else {
freeformValue = validator.reformat(
freeformValue,

View file

@ -145,12 +145,7 @@ export class UnitUtils {
const loaded = this.allUnits.get(name)
if (loaded === undefined) {
throw (
"No unit with quantity name " +
name +
" found (at " +
ctx +
"). Try one of: " +
Array.from(this.allUnits.keys()).join(", ")
`No unit with quantity name ${name} found (at ${ctx}). Try one of: ${Array.from(this.allUnits.keys()).join(", ")}. Alternatively, use \`{"quantity": "...", "denominations": ["...", "...", ...]}\`, e.g. \`{"quantity": "distance", "denominations":["m","cm"]}\``
)
}
return loaded

View file

@ -14,6 +14,7 @@
import type { ValueRange } from "../../Models/ThemeConfig/TagRenderingConfig"
import Translations from "../i18n/Translations"
import BaseUIElement from "../BaseUIElement"
import { Denomination } from "../../Models/Denomination"
export let type: ValidatorType
export let feedback: UIEventSource<Translation> | undefined = undefined
@ -91,6 +92,7 @@
if (!range) {
return true
}
const currentUnit: Denomination = unit.denominations.find(d => d.canonical === selectedUnit?.data)
if (typeof canonicalValue === "string") {
canonicalValue = Number(canonicalValue)
}
@ -103,7 +105,11 @@
if (canonicalValue > range.max) {
let max: number | string | BaseUIElement = range.max
if (unit) {
max = unit.asHumanLongValue(max, getCountry)
if (currentUnit?.factorToCanonical !== undefined) {
max = unit.asHumanLongValue(Math.round(max / currentUnit.factorToCanonical) + currentUnit.canonical, getCountry)
} else {
max = unit.asHumanLongValue(max, getCountry)
}
}
feedback.set(t.tooHigh.Subs({ max }))
return false
@ -111,7 +117,11 @@
if (canonicalValue < range.min) {
let min: number | string | BaseUIElement = range.min
if (unit) {
if (currentUnit?.factorToCanonical !== undefined) {
min = unit.asHumanLongValue(Math.round(min / currentUnit.factorToCanonical) + currentUnit.canonical, getCountry)
} else {
min = unit.asHumanLongValue(min, getCountry)
}
}
feedback.set(t.tooLow.Subs({ min }))
return false