forked from MapComplete/MapComplete
Refactoring: add metatagging, add 'last edited by' element, add 'metacondition'
This commit is contained in:
parent
771783a31c
commit
105120060d
31 changed files with 217 additions and 142 deletions
|
@ -18,6 +18,11 @@
|
|||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
_tags = tags;
|
||||
}));
|
||||
|
||||
let _metatags: Record<string, string>
|
||||
onDestroy(state.userRelatedState.preferencesAsTags .addCallbackAndRun(tags => {
|
||||
_metatags = tags;
|
||||
}));
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
@ -40,7 +45,7 @@
|
|||
|
||||
<div class="flex flex-col">
|
||||
{#each layer.tagRenderings as config (config.id)}
|
||||
{#if config.condition === undefined || config.condition.matchesProperties(_tags)}
|
||||
{#if (config.condition === undefined || config.condition.matchesProperties(_tags)) && (config.metacondition === undefined || config.metacondition.matchesProperties(_metatags))}
|
||||
{#if config.IsKnown(_tags)}
|
||||
<TagRenderingEditable {tags} {config} {state} {selectedElement} {layer} {highlightedRendering}></TagRenderingEditable>
|
||||
{/if}
|
||||
|
|
|
@ -91,6 +91,7 @@ export class MapLibreAdaptor implements MapProperties {
|
|||
// Workaround, 'ShowPointLayer' sets this flag
|
||||
return
|
||||
}
|
||||
console.log(e)
|
||||
const lon = e.lngLat.lng
|
||||
const lat = e.lngLat.lat
|
||||
lastClickLocation.setData({ lon, lat })
|
||||
|
|
|
@ -96,14 +96,15 @@
|
|||
}
|
||||
});
|
||||
state.newFeatures.features.ping();
|
||||
const tagsStore = state.featureProperties.getStore(newId);
|
||||
{
|
||||
// Set some metainfo
|
||||
const tagsStore = state.featureProperties.getStore(newId);
|
||||
const properties = tagsStore.data;
|
||||
if (snapTo) {
|
||||
// metatags (starting with underscore) are not uploaded, so we can safely mark this
|
||||
properties["_referencing_ways"] = `["${snapTo}"]`;
|
||||
}
|
||||
properties["_backend"] = state.osmConnection.Backend()
|
||||
properties["_last_edit:timestamp"] = new Date().toISOString();
|
||||
const userdetails = state.osmConnection.userDetails.data;
|
||||
properties["_last_edit:contributor"] = userdetails.name;
|
||||
|
@ -112,8 +113,9 @@
|
|||
}
|
||||
const feature = state.indexedFeatures.featuresById.data.get(newId);
|
||||
abort();
|
||||
state.selectedElement.setData(feature);
|
||||
state.selectedLayer.setData(selectedPreset.layer);
|
||||
state.selectedElement.setData(feature);
|
||||
tagsStore.ping()
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,46 +1,63 @@
|
|||
<script lang="ts">
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Table from "../Base/Table"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte";
|
||||
import Table from "../Base/Table";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import SimpleMetaTaggers from "../../Logic/SimpleMetaTagger";
|
||||
import { FixedUiElement } from "../Base/FixedUiElement";
|
||||
import { onDestroy } from "svelte";
|
||||
import Toggle, { ClickableToggle } from "../Input/Toggle";
|
||||
import Lazy from "../Base/Lazy";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
|
||||
//Svelte props
|
||||
export let tags: UIEventSource<any>
|
||||
export let state: any
|
||||
export let tags: UIEventSource<any>;
|
||||
export let state: any;
|
||||
|
||||
const calculatedTags = [].concat(
|
||||
// SimpleMetaTagger.lazyTags,
|
||||
...(state?.layoutToUse?.layers?.map((l) => l.calculatedTags?.map((c) => c[0]) ?? []) ?? [])
|
||||
)
|
||||
);
|
||||
|
||||
const allTags = tags.map((tags) => {
|
||||
const parts = []
|
||||
const parts: (string | BaseUIElement)[][] = [];
|
||||
for (const key in tags) {
|
||||
if (!tags.hasOwnProperty(key)) {
|
||||
continue
|
||||
}
|
||||
let v = tags[key]
|
||||
let v = tags[key];
|
||||
if (v === "") {
|
||||
v = "<b>empty string</b>"
|
||||
v = "<b>empty string</b>";
|
||||
}
|
||||
parts.push([key, v ?? "<b>undefined</b>"])
|
||||
parts.push([key, v ?? "<b>undefined</b>"]);
|
||||
}
|
||||
|
||||
for (const key of calculatedTags) {
|
||||
const value = tags[key]
|
||||
const value = tags[key];
|
||||
if (value === undefined) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let type = ""
|
||||
let type = "";
|
||||
if (typeof value !== "string") {
|
||||
type = " <i>" + typeof value + "</i>"
|
||||
type = " <i>" + typeof value + "</i>";
|
||||
}
|
||||
parts.push(["<i>" + key + "</i>", value])
|
||||
parts.push(["<i>" + key + "</i>", value]);
|
||||
}
|
||||
|
||||
return parts
|
||||
})
|
||||
for (const metatag of SimpleMetaTaggers.metatags.filter(mt => mt.isLazy)) {
|
||||
const title = "<i>" + metatag.keys.join(";") + "</i> (lazy)";
|
||||
const toggleState = new UIEventSource(false)
|
||||
const toggle: BaseUIElement = new Toggle(
|
||||
new Lazy(() => new FixedUiElement(metatag.keys.map(key => tags[key]).join(";"))),
|
||||
new FixedUiElement("Evaluate").onClick(() => toggleState.setData(true)) ,
|
||||
toggleState
|
||||
);
|
||||
parts.push([title, toggle]);
|
||||
}
|
||||
|
||||
const tagsTable = new Table(["Key", "Value"], $allTags).SetClass("zebra-table")
|
||||
return parts;
|
||||
});
|
||||
|
||||
let _allTags = [];
|
||||
onDestroy(allTags.addCallbackAndRunD(allTags => {
|
||||
_allTags = allTags;
|
||||
}));
|
||||
const tagsTable = new Table(["Key", "Value"], _allTags).SetClass("zebra-table");
|
||||
</script>
|
||||
|
||||
<section>
|
||||
|
|
|
@ -99,63 +99,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
})
|
||||
),
|
||||
]
|
||||
allRenderings.push(
|
||||
new Toggle(
|
||||
new Lazy(() =>
|
||||
FeatureInfoBox.createEditElements(questionBoxes, layerConfig, tags, state)
|
||||
),
|
||||
undefined,
|
||||
state.featureSwitchUserbadge
|
||||
)
|
||||
)
|
||||
|
||||
return new Combine(allRenderings).SetClass("block")
|
||||
}
|
||||
|
||||
/**
|
||||
* All the edit elements, together (note that the question boxes are passed though)
|
||||
* @param questionBoxes
|
||||
* @param layerConfig
|
||||
* @param tags
|
||||
* @param state
|
||||
* @private
|
||||
*/
|
||||
private static createEditElements(
|
||||
questionBoxes: Map<string, QuestionBox>,
|
||||
layerConfig: LayerConfig,
|
||||
tags: UIEventSource<any>,
|
||||
state: FeaturePipelineState
|
||||
): BaseUIElement {
|
||||
let editElements: BaseUIElement[] = []
|
||||
questionBoxes.forEach((questionBox) => {
|
||||
editElements.push(questionBox)
|
||||
})
|
||||
|
||||
editElements.push(
|
||||
new VariableUiElement(
|
||||
state.osmConnection.userDetails
|
||||
.map((ud) => ud.csCount)
|
||||
.map(
|
||||
(csCount) => {
|
||||
if (
|
||||
csCount <= Constants.userJourney.historyLinkVisible &&
|
||||
state.featureSwitchIsDebugging.data == false &&
|
||||
state.featureSwitchIsTesting.data === false
|
||||
) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return new TagRenderingAnswer(
|
||||
tags,
|
||||
SharedTagRenderings.SharedTagRendering.get("last_edit"),
|
||||
state
|
||||
)
|
||||
},
|
||||
[state.featureSwitchIsDebugging, state.featureSwitchIsTesting]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return new Combine(editElements).SetClass("flex flex-col")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,10 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
const baseQuestions = (layer.tagRenderings ?? [])?.filter(tr => allowed(tr.labels) && tr.question !== undefined);
|
||||
let baseQuestions = []
|
||||
$: {
|
||||
baseQuestions = (layer.tagRenderings ?? [])?.filter(tr => allowed(tr.labels) && tr.question !== undefined);
|
||||
}
|
||||
let skippedQuestions = new UIEventSource<Set<string>>(new Set<string>());
|
||||
|
||||
let questionsToAsk = tags.map(tags => {
|
||||
|
@ -80,6 +83,7 @@
|
|||
skipped++;
|
||||
}
|
||||
}
|
||||
$: console.log("Current questionbox state:", {answered, skipped, questionsToAsk, layer, selectedElement, tags})
|
||||
</script>
|
||||
|
||||
{#if _questionsToAsk.length === 0}
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
checkedMappings = [...config.mappings.map(_ => false), false /*One element extra in case a freeform value is added*/];
|
||||
}
|
||||
}
|
||||
$: console.log("Checked mappings:", checkedMappings)
|
||||
let selectedTags: TagsFilter = undefined;
|
||||
|
||||
function mappingIsHidden(mapping: Mapping): boolean {
|
||||
|
|
|
@ -63,6 +63,7 @@ export interface SpecialVisualizationState {
|
|||
readonly userRelatedState: {
|
||||
readonly mangroveIdentity: MangroveIdentity
|
||||
readonly showAllQuestionsAtOnce: UIEventSource<boolean>
|
||||
readonly preferencesAsTags: Store<Record<string, string>>
|
||||
}
|
||||
readonly lastClickObject: WritableFeatureSource
|
||||
}
|
||||
|
|
|
@ -1265,21 +1265,24 @@ export default class SpecialVisualizations {
|
|||
doc: "The URL to link to",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "class",
|
||||
doc: "CSS-classes to add to the element",
|
||||
},
|
||||
],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>,
|
||||
args: string[]
|
||||
): BaseUIElement {
|
||||
const [text, href] = args
|
||||
const [text, href, classnames] = args
|
||||
return new VariableUiElement(
|
||||
tagSource.map(
|
||||
(tags) =>
|
||||
new Link(
|
||||
Utils.SubstituteKeys(text, tags),
|
||||
Utils.SubstituteKeys(href, tags),
|
||||
true
|
||||
)
|
||||
tagSource.map((tags) =>
|
||||
new Link(
|
||||
Utils.SubstituteKeys(text, tags),
|
||||
Utils.SubstituteKeys(href, tags),
|
||||
true
|
||||
).SetClass(classnames)
|
||||
)
|
||||
)
|
||||
},
|
||||
|
|
|
@ -29,7 +29,14 @@ export class Translation extends BaseUIElement {
|
|||
}
|
||||
count++
|
||||
if (typeof translations[translationsKey] != "string") {
|
||||
console.error("Non-string object in translation: ", translations[translationsKey])
|
||||
console.error(
|
||||
"Non-string object at",
|
||||
context,
|
||||
"in translation: ",
|
||||
translations[translationsKey],
|
||||
"\n current translations are: ",
|
||||
translations
|
||||
)
|
||||
throw (
|
||||
"Error in an object depicting a translation: a non-string object was found. (" +
|
||||
context +
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue