Add question box as special rendering
This commit is contained in:
parent
15664df63f
commit
d47fd7e746
42 changed files with 956 additions and 311 deletions
51
UI/Popup/QuestionViz.ts
Normal file
51
UI/Popup/QuestionViz.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import { Feature } from "geojson"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||
import Questionbox from "./TagRendering/Questionbox.svelte"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
|
||||
/**
|
||||
* Thin wrapper around QuestionBox.svelte to include it into the special Visualisations
|
||||
*/
|
||||
export default class QuestionViz implements SpecialVisualization {
|
||||
funcName = "questions"
|
||||
docs =
|
||||
"The special element which shows the questions which are unkown. Added by default if not yet there"
|
||||
args = [
|
||||
{
|
||||
name: "labels",
|
||||
doc: "One or more ';'-separated labels. If these are given, only questions with these labels will be given. Use `unlabeled` for all questions that don't have an explicit label. If none given, all questions will be shown",
|
||||
},
|
||||
{
|
||||
name: "blacklisted-labels",
|
||||
doc: "One or more ';'-separated labels of questions which should _not_ be included",
|
||||
},
|
||||
]
|
||||
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tags: UIEventSource<Record<string, string>>,
|
||||
args: string[],
|
||||
feature: Feature,
|
||||
layer: LayerConfig
|
||||
): BaseUIElement {
|
||||
const labels = args[0]
|
||||
?.split(";")
|
||||
?.map((s) => s.trim())
|
||||
?.filter((s) => s !== "")
|
||||
const blacklist = args[1]
|
||||
?.split(";")
|
||||
?.map((s) => s.trim())
|
||||
?.filter((s) => s !== "")
|
||||
return new SvelteUIElement(Questionbox, {
|
||||
layer,
|
||||
tags,
|
||||
selectedElement: feature,
|
||||
state,
|
||||
onlyForLabels: labels,
|
||||
notForLabels: blacklist,
|
||||
})
|
||||
}
|
||||
}
|
26
UI/Popup/TagRendering/FreeformInput.svelte
Normal file
26
UI/Popup/TagRendering/FreeformInput.svelte
Normal file
|
@ -0,0 +1,26 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import ValidatedInput from "../../InputElement/ValidatedInput.svelte";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import Inline from "./Inline.svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
export let value: UIEventSource<string>;
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined);
|
||||
|
||||
let dispatch = createEventDispatcher<{ "selected" }>();
|
||||
</script>
|
||||
<Inline key={config.freeform.key} {tags} template={config.render}>
|
||||
<ValidatedInput {feedback} type={config.freeform.type}
|
||||
{value} on:selected={() => dispatch("selected")}></ValidatedInput>
|
||||
</Inline>
|
||||
{#if $feedback !== undefined}
|
||||
<div class="alert">
|
||||
<Tr t={$feedback} />
|
||||
</div>
|
||||
{/if}
|
26
UI/Popup/TagRendering/Inline.svelte
Normal file
26
UI/Popup/TagRendering/Inline.svelte
Normal file
|
@ -0,0 +1,26 @@
|
|||
<script lang="ts">
|
||||
import { Utils } from "../../../Utils.js";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import { onDestroy } from "svelte";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import Locale from "../../i18n/Locale";
|
||||
|
||||
export let template: Translation;
|
||||
let _template: string
|
||||
onDestroy(Locale.language.addCallbackAndRunD(l => {
|
||||
_template = template.textFor(l)
|
||||
}))
|
||||
export let key: string;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
let _tags = tags.data;
|
||||
onDestroy(tags.addCallbackAndRunD(tags => {
|
||||
_tags = tags;
|
||||
}));
|
||||
let [before, after] = _template.split("{" + key + "}");
|
||||
</script>
|
||||
|
||||
<span>
|
||||
{Utils.SubstituteKeys(before, _tags)}
|
||||
<slot />
|
||||
{Utils.SubstituteKeys(after, _tags)}
|
||||
</span>
|
108
UI/Popup/TagRendering/Questionbox.svelte
Normal file
108
UI/Popup/TagRendering/Questionbox.svelte
Normal file
|
@ -0,0 +1,108 @@
|
|||
<script lang="ts">
|
||||
|
||||
/**
|
||||
* Shows all questions for which the answers are unknown.
|
||||
* The questions can either be shown all at once or one at a time (in which case they can be skipped)
|
||||
*/
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import type { Feature } from "geojson";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
import If from "../../Base/If.svelte";
|
||||
import { onDestroy } from "svelte";
|
||||
import TagRenderingQuestion from "./TagRenderingQuestion.svelte";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import Translations from "../../i18n/Translations.js";
|
||||
|
||||
export let layer: LayerConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let selectedElement: Feature;
|
||||
export let state: SpecialVisualizationState;
|
||||
|
||||
/**
|
||||
* If set, only questions for these labels will be shown
|
||||
*/
|
||||
export let onlyForLabels: string[] | undefined = undefined;
|
||||
const _onlyForLabels = new Set(onlyForLabels);
|
||||
/**
|
||||
* If set, only questions _not_ having these labels will be shown
|
||||
*/
|
||||
export let notForLabels: string[] | undefined = undefined;
|
||||
const _notForLabels = new Set(notForLabels);
|
||||
|
||||
function allowed(labels: string[]) {
|
||||
if (onlyForLabels?.length > 0 && !labels.some(l => _onlyForLabels.has(l))) {
|
||||
return false;
|
||||
}
|
||||
if (notForLabels?.length > 0 && labels.some(l => _notForLabels.has(l))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log("Got layer", layer, onlyForLabels, notForLabels);
|
||||
|
||||
const baseQuestions = (layer.tagRenderings ?? [])?.filter(tr => allowed(tr.labels) && tr.question !== undefined);
|
||||
console.log("BaseQuestions are", baseQuestions);
|
||||
let skippedQuestions = new UIEventSource<Set<string>>(new Set<string>());
|
||||
let answered : number = 0
|
||||
let questionsToAsk = tags.map(tags => {
|
||||
const questionsToAsk: TagRenderingConfig[] = [];
|
||||
for (const baseQuestion of baseQuestions) {
|
||||
if (skippedQuestions.data.has(baseQuestion.id) > 0) {
|
||||
continue;
|
||||
}
|
||||
if (baseQuestion.condition !== undefined && !baseQuestion.condition.matchesProperties(tags)) {
|
||||
continue;
|
||||
}
|
||||
questionsToAsk.push(baseQuestion);
|
||||
}
|
||||
return questionsToAsk;
|
||||
|
||||
}, [skippedQuestions]);
|
||||
let _questionsToAsk: TagRenderingConfig[];
|
||||
let _firstQuestion: TagRenderingConfig
|
||||
onDestroy(questionsToAsk.subscribe(qta => {
|
||||
_questionsToAsk = qta;
|
||||
_firstQuestion = qta[0]
|
||||
}));
|
||||
|
||||
function skip(question: TagRenderingConfig, didAnswer: boolean = false) {
|
||||
skippedQuestions.data.add(question.id);
|
||||
skippedQuestions.ping();
|
||||
if(didAnswer ){
|
||||
answered ++
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if _questionsToAsk.length === 0}
|
||||
All done! You answered {answered} questions and skipped {$skippedQuestions.size} questions.
|
||||
{#if $skippedQuestions.size > 0 }
|
||||
<button on:click={() => skippedQuestions.setData(new Set())}>Re-activate skipped questions</button>
|
||||
{/if}
|
||||
{:else }
|
||||
<div>
|
||||
<If condition={state.userRelatedState.showAllQuestionsAtOnce}>
|
||||
<div>
|
||||
{#each _questionsToAsk as question (question.id)}
|
||||
<TagRenderingQuestion config={question} {tags} {selectedElement} {state} {layer}></TagRenderingQuestion>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div slot="else">
|
||||
<TagRenderingQuestion
|
||||
config={_firstQuestion} {layer} {selectedElement} {state} {tags}
|
||||
on:saved={() => {skip(_firstQuestion, true)}}>
|
||||
<button on:click={() => {skip(_firstQuestion)} }
|
||||
slot="cancel">
|
||||
<Tr t={Translations.t.general.skip}></Tr>
|
||||
</button>
|
||||
</TagRenderingQuestion>
|
||||
|
||||
</div>
|
||||
|
||||
</If>
|
||||
</div>
|
||||
{/if}
|
|
@ -1,14 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { Translation } from "../i18n/Translation";
|
||||
import SpecialVisualizations from "../SpecialVisualizations";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import SpecialVisualizations from "../../SpecialVisualizations";
|
||||
import { onDestroy } from "svelte";
|
||||
import Locale from "../i18n/Locale";
|
||||
import type { RenderingSpecification, SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import { Utils } from "../../Utils.js";
|
||||
import Locale from "../../i18n/Locale";
|
||||
import type { RenderingSpecification, SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import { Utils } from "../../../Utils.js";
|
||||
import type { Feature } from "geojson";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource.js";
|
||||
import ToSvelte from "../Base/ToSvelte.svelte";
|
||||
import FromHtml from "../Base/FromHtml.svelte";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource.js";
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte";
|
||||
import FromHtml from "../../Base/FromHtml.svelte";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
|
||||
/**
|
||||
* The 'specialTranslation' renders a `Translation`-object, but interprets the special values as well
|
||||
|
@ -17,18 +18,18 @@
|
|||
export let state: SpecialVisualizationState;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let feature: Feature;
|
||||
export let layer: LayerConfig
|
||||
let txt: string;
|
||||
onDestroy(Locale.language.addCallbackAndRunD(l => {
|
||||
txt = t.textFor(l);
|
||||
}));
|
||||
let specs: RenderingSpecification[];
|
||||
specs = SpecialVisualizations.constructSpecification(txt);
|
||||
let specs: RenderingSpecification[] = SpecialVisualizations.constructSpecification(txt);
|
||||
</script>
|
||||
|
||||
{#each specs as specpart}
|
||||
{#if typeof specpart === "string"}
|
||||
<FromHtml src= {Utils.SubstituteKeys(specpart, $tags)}></FromHtml>
|
||||
{:else if $tags !== undefined }
|
||||
<ToSvelte construct={specpart.func.constr(state, tags, specpart.args, feature)}></ToSvelte>
|
||||
<ToSvelte construct={specpart.func.constr(state, tags, specpart.args, feature, layer)}></ToSvelte>
|
||||
{/if}
|
||||
{/each}
|
38
UI/Popup/TagRendering/TagRenderingAnswer.svelte
Normal file
38
UI/Popup/TagRendering/TagRenderingAnswer.svelte
Normal file
|
@ -0,0 +1,38 @@
|
|||
<script lang="ts">
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { Utils } from "../../../Utils";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import TagRenderingMapping from "./TagRenderingMapping.svelte";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import type { Feature } from "geojson";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import { onDestroy } from "svelte";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
|
||||
export let tags: UIEventSource<Record<string, string> | undefined>;
|
||||
let _tags: Record<string, string>;
|
||||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
_tags = tags;
|
||||
}));
|
||||
export let state: SpecialVisualizationState;
|
||||
export let selectedElement: Feature;
|
||||
export let config: TagRenderingConfig;
|
||||
export let layer: LayerConfig
|
||||
let trs: { then: Translation; icon?: string; iconClass?: string }[];
|
||||
$: trs = Utils.NoNull(config?.GetRenderValues(_tags));
|
||||
</script>
|
||||
|
||||
{#if config !== undefined && (config?.condition === undefined || config.condition.matchesProperties(_tags))}
|
||||
{#if trs.length === 1}
|
||||
<TagRenderingMapping mapping={trs[0]} {tags} {state} {selectedElement} {layer}></TagRenderingMapping>
|
||||
{/if}
|
||||
{#if trs.length > 1}
|
||||
<ul>
|
||||
{#each trs as mapping}
|
||||
<li>
|
||||
<TagRenderingMapping {mapping} {tags} {state} {selectedElement} {layer}></TagRenderingMapping>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{/if}
|
46
UI/Popup/TagRendering/TagRenderingEditable.svelte
Normal file
46
UI/Popup/TagRendering/TagRenderingEditable.svelte
Normal file
|
@ -0,0 +1,46 @@
|
|||
<script lang="ts">
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import type { Feature } from "geojson";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import TagRenderingAnswer from "./TagRenderingAnswer.svelte";
|
||||
import { PencilAltIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||
import TagRenderingQuestion from "./TagRenderingQuestion.svelte";
|
||||
import { onDestroy } from "svelte";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import Translations from "../../i18n/Translations.js";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let selectedElement: Feature;
|
||||
export let state: SpecialVisualizationState;
|
||||
export let layer: LayerConfig
|
||||
|
||||
export let showQuestionIfUnknown : boolean= false
|
||||
let editMode = false
|
||||
onDestroy(tags.addCallbackAndRunD(tags => {
|
||||
editMode = showQuestionIfUnknown && !config.IsKnown(tags)
|
||||
|
||||
}))
|
||||
|
||||
</script>
|
||||
|
||||
{#if config.question}
|
||||
{#if editMode}
|
||||
<TagRenderingQuestion {config} {tags} {selectedElement} {state} {layer} >
|
||||
<button slot="cancel" on:click={() => {editMode = false}}>
|
||||
<Tr t={Translations.t.general.cancel}/>
|
||||
</button>
|
||||
</TagRenderingQuestion>
|
||||
{:else}
|
||||
<div class="flex justify-between">
|
||||
<TagRenderingAnswer {config} {tags} {selectedElement} {state} {layer} />
|
||||
<button on:click={() => {editMode = true}} class="w-6 h-6 rounded-full subtle-background p-1">
|
||||
<PencilAltIcon></PencilAltIcon>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{:else }
|
||||
<TagRenderingAnswer {config} {tags} {selectedElement} {state} {layer} />
|
||||
{/if}
|
|
@ -1,13 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { Translation } from "../i18n/Translation";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import SpecialTranslation from "./SpecialTranslation.svelte";
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import type { Feature } from "geojson";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
|
||||
export let selectedElement: Feature
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let state: SpecialVisualizationState
|
||||
export let layer: LayerConfig
|
||||
export let mapping: {
|
||||
then: Translation; icon?: string; iconClass?: | "small"
|
||||
| "medium"
|
||||
|
@ -22,11 +24,11 @@
|
|||
</script>
|
||||
|
||||
{#if mapping.icon !== undefined}
|
||||
<div class="flex">
|
||||
<div class="inline-flex">
|
||||
<img class={iconclass+" mr-1"} src={mapping.icon}>
|
||||
<SpecialTranslation t={mapping.then} {tags} {state} feature={selectedElement}></SpecialTranslation>
|
||||
<SpecialTranslation t={mapping.then} {tags} {state} {layer} feature={selectedElement}></SpecialTranslation>
|
||||
</div>
|
||||
{:else if mapping.then !== undefined}
|
||||
<SpecialTranslation t={mapping.then} {tags} {state} feature={selectedElement}></SpecialTranslation>
|
||||
<SpecialTranslation t={mapping.then} {tags} {state} {layer} feature={selectedElement}></SpecialTranslation>
|
||||
{/if}
|
||||
|
147
UI/Popup/TagRendering/TagRenderingQuestion.svelte
Normal file
147
UI/Popup/TagRendering/TagRenderingQuestion.svelte
Normal file
|
@ -0,0 +1,147 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import If from "../../Base/If.svelte";
|
||||
import TagRenderingMapping from "./TagRenderingMapping.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter";
|
||||
import FreeformInput from "./FreeformInput.svelte";
|
||||
import Translations from "../../i18n/Translations.js";
|
||||
import FromHtml from "../../Base/FromHtml.svelte";
|
||||
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let selectedElement: Feature;
|
||||
export let state: SpecialVisualizationState;
|
||||
export let layer: LayerConfig;
|
||||
|
||||
// Will be bound if a freeform is available
|
||||
let freeformInput = new UIEventSource<string>(undefined);
|
||||
let selectedMapping: number = 0;
|
||||
let checkedMappings: boolean[];
|
||||
if (config.mappings?.length > 0) {
|
||||
checkedMappings = [...config.mappings.map(_ => false), false /*One element extra in case a freeform value is added*/];
|
||||
}
|
||||
let selectedTags: TagsFilter = undefined;
|
||||
$:selectedTags = config?.constructChangeSpecification($freeformInput, selectedMapping, checkedMappings);
|
||||
|
||||
function mappingIsHidden(mapping: Mapping): boolean {
|
||||
if (mapping.hideInAnswer === undefined || mapping.hideInAnswer === false) {
|
||||
return false;
|
||||
}
|
||||
if (mapping.hideInAnswer === true) {
|
||||
return true;
|
||||
}
|
||||
return (<TagsFilter>mapping.hideInAnswer).matchesProperties(tags.data);
|
||||
}
|
||||
|
||||
let dispatch = createEventDispatcher<{
|
||||
"saved": {
|
||||
config: TagRenderingConfig,
|
||||
applied: TagsFilter
|
||||
}
|
||||
}>();
|
||||
|
||||
function onSave() {
|
||||
dispatch("saved", { config, applied: selectedTags });
|
||||
const change = new ChangeTagAction(
|
||||
tags.data.id,
|
||||
selectedTags,
|
||||
tags.data,
|
||||
{
|
||||
theme: state.layout.id,
|
||||
changeType: "answer"
|
||||
}
|
||||
);
|
||||
change.CreateChangeDescriptions().then(changes =>
|
||||
state.changes.applyChanges(changes)
|
||||
).catch(console.error);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{#if config.question !== undefined}
|
||||
<div class="border border-black subtle-background flex flex-col">
|
||||
<If condition={state.featureSwitchIsTesting}>
|
||||
<div class="flex justify-between">
|
||||
<Tr t={config.question}></Tr>
|
||||
<span class="alert">{config.id}</span>
|
||||
</div>
|
||||
<Tr slot="else" t={config.question}></Tr>
|
||||
</If>
|
||||
|
||||
{#if config.questionhint}
|
||||
<div class="subtle">
|
||||
<Tr t={config.questionHint}></Tr>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if config.freeform?.key && !(config.mappings?.length > 0)}
|
||||
<!-- There are no options to choose from, simply show the input element: fill out the text field -->
|
||||
<FreeformInput {config} {tags} value={freeformInput} />
|
||||
{/if}
|
||||
|
||||
{#if config.mappings !== undefined && !config.multiAnswer}
|
||||
<!-- Simple radiobuttons as mapping -->
|
||||
<div class="flex flex-col">
|
||||
{#each config.mappings as mapping, i (mapping.then)}
|
||||
{#if !mappingIsHidden(mapping) }
|
||||
<label>
|
||||
<input type="radio" bind:group={selectedMapping} name={"mappings-radio-"+config.id} value={i}>
|
||||
<TagRenderingMapping {mapping} {tags} {state} {selectedElement} {layer}></TagRenderingMapping>
|
||||
</label>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if config.freeform?.key}
|
||||
<label>
|
||||
<input type="radio" bind:group={selectedMapping} name={"mappings-radio-"+config.id}
|
||||
value={config.mappings.length}>
|
||||
<FreeformInput {config} {tags} value={freeformInput}
|
||||
on:selected={() => selectedMapping = config.mappings.length } />
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if config.mappings !== undefined && config.multiAnswer}
|
||||
<!-- Multiple answers can be chosen: checkboxes -->
|
||||
<div class="flex flex-col">
|
||||
{#each config.mappings as mapping, i (mapping.then)}
|
||||
{#if !mappingIsHidden(mapping) }
|
||||
<label>
|
||||
<input type="checkbox" name={"mappings-checkbox-"+config.id+"-"+i} bind:checked={checkedMappings[i]}>
|
||||
<TagRenderingMapping {mapping} {tags} {state} {selectedElement}></TagRenderingMapping>
|
||||
</label>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if config.freeform?.key}
|
||||
<label>
|
||||
<input type="checkbox" name={"mappings-checkbox-"+config.id+"-"+config.mappings.length}
|
||||
bind:checked={checkedMappings[config.mappings.length]}>
|
||||
<FreeformInput {config} {tags} value={freeformInput}
|
||||
on:selected={() => checkedMappings[config.mappings.length] = true} />
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<FromHtml src={selectedTags?.asHumanString(true, true, {})} />
|
||||
|
||||
<div>
|
||||
<!-- TagRenderingQuestion-buttons -->
|
||||
<slot name="cancel"></slot>
|
||||
<button on:click={onSave}>
|
||||
<Tr t={Translations.t.general.save}></Tr>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/if}
|
|
@ -1,34 +0,0 @@
|
|||
<script lang="ts">
|
||||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { Utils } from "../../Utils";
|
||||
import { Translation } from "../i18n/Translation";
|
||||
import TagRenderingMapping from "./TagRenderingMapping.svelte";
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import type { Feature } from "geojson";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import { onDestroy } from "svelte";
|
||||
|
||||
export let tags: UIEventSource<Record<string, string> | undefined>;
|
||||
let _tags : Record<string, string>
|
||||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
_tags = tags
|
||||
}))
|
||||
export let state: SpecialVisualizationState
|
||||
export let selectedElement: Feature
|
||||
export let config: TagRenderingConfig;
|
||||
let trs: { then: Translation; icon?: string; iconClass?: string }[];
|
||||
$: trs = Utils.NoNull(config?.GetRenderValues(_tags));
|
||||
</script>
|
||||
|
||||
{#if config !== undefined && (config?.condition === undefined || config.condition.matchesProperties(tags))}
|
||||
<div>
|
||||
{#if trs.length === 1}
|
||||
<TagRenderingMapping mapping={trs[0]} {tags} {state} feature={selectedElement}></TagRenderingMapping>
|
||||
{/if}
|
||||
{#if trs.length > 1}
|
||||
{#each trs as mapping}
|
||||
<TagRenderingMapping mapping={trs} {tags} {state} feature=""{selectedElement}></TagRenderingMapping>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
|
@ -1,53 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import If from "../Base/If.svelte";
|
||||
import ValidatedInput from "../InputElement/ValidatedInput.svelte";
|
||||
import TagRenderingMapping from "./TagRenderingMapping.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
||||
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let selectedElement: Feature;
|
||||
|
||||
export let state: SpecialVisualizationState;
|
||||
state.featureSwitchIsTesting;
|
||||
|
||||
let freeformInput = new UIEventSource<string>(undefined);
|
||||
</script>
|
||||
|
||||
{#if config.question !== undefined}
|
||||
<div class="border border-black subtle-background">
|
||||
<If condition={state.featureSwitchIsTesting}>
|
||||
<div class="flex justify-between">
|
||||
<Tr t={config.question}></Tr>
|
||||
{config.id}
|
||||
</div>
|
||||
<Tr slot="else" t={config.question}></Tr>
|
||||
</If>
|
||||
|
||||
{#if config.questionhint}
|
||||
<div class="subtle">
|
||||
<Tr t={config.question}></Tr>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if config.freeform?.key && !(config.mappings?.length > 0)}
|
||||
<!-- There are no options to choose from, simply show the input element: fill out the text field -->
|
||||
<ValidatedInput type={config.freeform.type} value={freeformInput}></ValidatedInput>
|
||||
{/if}
|
||||
|
||||
{#if config.mappings !== undefined}
|
||||
<div class="flex flex-col">
|
||||
{#each config.mappings as mapping}
|
||||
{#if mapping.hideInAnswer === true || !(mapping.hideInAnswer) || (console.log(tags) || true) || !(mapping.hideInAnswer?.matchesProperties($tags)) }
|
||||
<TagRenderingMapping {mapping} {tags} {state} {selectedElement}></TagRenderingMapping>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
{/if}
|
Loading…
Add table
Add a link
Reference in a new issue