forked from MapComplete/MapComplete
Refactoring: port unit picker
This commit is contained in:
parent
622df2df19
commit
2b05d79dbb
8 changed files with 188 additions and 67 deletions
|
|
@ -7,17 +7,20 @@
|
|||
import {createEventDispatcher, onDestroy} from "svelte";
|
||||
import InputHelper from "../../InputElement/InputHelper.svelte";
|
||||
import type {Feature} from "geojson";
|
||||
import {Unit} from "../../../Models/Unit";
|
||||
|
||||
export let value: UIEventSource<string>;
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
|
||||
export let feature: Feature = undefined;
|
||||
export let unit: Unit | undefined
|
||||
|
||||
let placeholder = config.freeform?.placeholder
|
||||
$: {
|
||||
placeholder = config.freeform?.placeholder
|
||||
}
|
||||
let inline = config.freeform.inline
|
||||
|
||||
export let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined);
|
||||
|
||||
|
|
@ -35,13 +38,14 @@
|
|||
|
||||
{#if config.freeform.inline}
|
||||
<Inline key={config.freeform.key} {tags} template={config.render}>
|
||||
<ValidatedInput {feedback} {getCountry} on:selected={() => dispatch("selected")}
|
||||
<ValidatedInput {feedback} {getCountry} {unit} on:selected={() => dispatch("selected")}
|
||||
type={config.freeform.type} {placeholder} {value}></ValidatedInput>
|
||||
</Inline>
|
||||
{:else}
|
||||
<ValidatedInput {feedback} {getCountry} on:selected={() => dispatch("selected")}
|
||||
<ValidatedInput {feedback} {getCountry} {unit} on:selected={() => dispatch("selected")}
|
||||
type={config.freeform.type} {placeholder} {value}></ValidatedInput>
|
||||
|
||||
{/if}
|
||||
|
||||
<InputHelper args={config.freeform.helperArgs} {feature} type={config.freeform.type} {value}/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
</script>
|
||||
|
||||
{#if config !== undefined && (config?.condition === undefined || config.condition.matchesProperties(_tags))}
|
||||
<div class={"link-underline flex flex-col w-full "+classes+" "+extraClasses}>
|
||||
<div class={"link-underline inline-block w-full "+classes+" "+extraClasses}>
|
||||
{#if trs.length === 1}
|
||||
<TagRenderingMapping mapping={trs[0]} {tags} {state} {selectedElement} {layer}></TagRenderingMapping>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte";
|
||||
import {Translation} from "../../i18n/Translation";
|
||||
import Constants from "../../../Models/Constants";
|
||||
import {TagUtils} from "../../../Logic/Tags/TagUtils";
|
||||
import {Unit} from "../../../Models/Unit";
|
||||
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined);
|
||||
|
||||
let unit: Unit = layer.units?.find(unit => unit.appliesToKeys.has(config.freeform?.key))
|
||||
|
||||
// Will be bound if a freeform is available
|
||||
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key]);
|
||||
let selectedMapping: number = undefined;
|
||||
|
|
@ -41,11 +43,13 @@
|
|||
return m.hideInAnswer.matchesProperties(tags.data)
|
||||
})
|
||||
// We received a new config -> reinit
|
||||
unit = layer.units.find(unit => unit.appliesToKeys.has(config.freeform?.key))
|
||||
|
||||
if (config.mappings?.length > 0 && (checkedMappings === undefined || checkedMappings?.length < config.mappings.length)) {
|
||||
checkedMappings = [...config.mappings.map(_ => false), false /*One element extra in case a freeform value is added*/];
|
||||
}
|
||||
if (config.freeform?.key) {
|
||||
if(!config.multiAnswer){ // Somehow, setting multianswer freeform values is broken if this is not set
|
||||
if (!config.multiAnswer) { // Somehow, setting multianswer freeform values is broken if this is not set
|
||||
freeformInput.setData(tags.data[config.freeform.key]);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -77,7 +81,7 @@
|
|||
}>();
|
||||
|
||||
function onSave() {
|
||||
if(selectedTags === undefined){
|
||||
if (selectedTags === undefined) {
|
||||
return
|
||||
}
|
||||
if (layer.source === null) {
|
||||
|
|
@ -152,7 +156,7 @@
|
|||
|
||||
{#if config.freeform?.key && !(mappings?.length > 0)}
|
||||
<!-- There are no options to choose from, simply show the input element: fill out the text field -->
|
||||
<FreeformInput {config} {tags} {feedback} feature={selectedElement} value={freeformInput}/>
|
||||
<FreeformInput {config} {tags} {feedback} {unit} feature={selectedElement} value={freeformInput}/>
|
||||
{:else if mappings !== undefined && !config.multiAnswer}
|
||||
<!-- Simple radiobuttons as mapping -->
|
||||
<div class="flex flex-col">
|
||||
|
|
@ -169,7 +173,7 @@
|
|||
<label class="flex">
|
||||
<input type="radio" bind:group={selectedMapping} name={"mappings-radio-"+config.id}
|
||||
value={config.mappings?.length}>
|
||||
<FreeformInput {config} {tags} {feedback} feature={selectedElement} value={freeformInput}
|
||||
<FreeformInput {config} {tags} {feedback} {unit} feature={selectedElement} value={freeformInput}
|
||||
on:selected={() => selectedMapping = config.mappings?.length }/>
|
||||
</label>
|
||||
{/if}
|
||||
|
|
@ -188,7 +192,7 @@
|
|||
<label class="flex">
|
||||
<input type="checkbox" name={"mappings-checkbox-"+config.id+"-"+config.mappings?.length}
|
||||
bind:checked={checkedMappings[config.mappings.length]}>
|
||||
<FreeformInput {config} {tags} {feedback} feature={selectedElement} value={freeformInput}
|
||||
<FreeformInput {config} {tags} {feedback} {unit} feature={selectedElement} value={freeformInput}
|
||||
on:selected={() => checkedMappings[config.mappings.length] = true}/>
|
||||
</label>
|
||||
{/if}
|
||||
|
|
@ -210,7 +214,8 @@
|
|||
<!-- TagRenderingQuestion-buttons -->
|
||||
<slot name="cancel"></slot>
|
||||
<slot name="save-button" {selectedTags}>
|
||||
<button on:click={onSave} class={(selectedTags === undefined ? "disabled" : "button-shadow")+" primary"}>
|
||||
<button on:click={onSave}
|
||||
class={(selectedTags === undefined ? "disabled" : "button-shadow")+" primary"}>
|
||||
<Tr t={Translations.t.general.save}/>
|
||||
</button>
|
||||
</slot>
|
||||
|
|
|
|||
67
UI/Popup/UnitInput.svelte
Normal file
67
UI/Popup/UnitInput.svelte
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<script lang="ts">
|
||||
|
||||
import {Unit} from "../../Models/Unit";
|
||||
import {Store, UIEventSource} from "../../Logic/UIEventSource";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import {onDestroy} from "svelte";
|
||||
|
||||
export let unit: Unit
|
||||
|
||||
|
||||
/**
|
||||
* The current value of the input field
|
||||
* Not necessarily a correct number
|
||||
*/
|
||||
export let textValue: UIEventSource<string>
|
||||
/**
|
||||
* The actual _valid_ value that is upstreamed
|
||||
*/
|
||||
export let upstreamValue: Store<string>
|
||||
|
||||
let isSingle: Store<boolean> = textValue.map(v => Number(v) === 1)
|
||||
|
||||
export let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
export let getCountry = () => "be"
|
||||
console.log("Unit", unit)
|
||||
onDestroy(upstreamValue.addCallbackAndRun(v => {
|
||||
if (v === undefined) {
|
||||
if (!selectedUnit.data) {
|
||||
selectedUnit.setData(unit.getDefaultDenomination(getCountry).canonical)
|
||||
}
|
||||
return
|
||||
}
|
||||
const selected = unit.findDenomination(v, getCountry)
|
||||
if (selected === undefined) {
|
||||
selectedUnit.setData(unit.getDefaultDenomination(getCountry).canonical)
|
||||
return
|
||||
}
|
||||
const [value, denomination] = selected
|
||||
selectedUnit.setData(denomination.canonical)
|
||||
return
|
||||
}))
|
||||
|
||||
onDestroy(textValue.addCallbackAndRunD(v => {
|
||||
// Fallback in case that the user manually types a denomination
|
||||
const [value, denomination] = unit.findDenomination(v, getCountry)
|
||||
if (value === undefined || denomination === undefined) {
|
||||
return
|
||||
}
|
||||
textValue.setData(value)
|
||||
selectedUnit.setData(denomination.canonical)
|
||||
|
||||
}))
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<select bind:value={$selectedUnit}>
|
||||
{#each unit.denominations as denom (denom.canonical)}
|
||||
<option value={denom.canonical}>
|
||||
{#if $isSingle}
|
||||
<Tr t={denom.humanSingular}/>
|
||||
{:else }
|
||||
<Tr t={denom.human}/>
|
||||
{/if}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
Loading…
Add table
Add a link
Reference in a new issue