forked from MapComplete/MapComplete
Studio: UX improvements after usertest
This commit is contained in:
parent
44c1548e89
commit
a9bfe4f37b
11 changed files with 173 additions and 122 deletions
|
@ -18,5 +18,6 @@ The participant has extensive OpenStreetMap-knowledge but only used MapComplete
|
||||||
- [x] The 'try it out'-button should be a 'next'-button
|
- [x] The 'try it out'-button should be a 'next'-button
|
||||||
- [x] Entering an incorrect ID and pressing enter still takes you to the layer editor with an incorrect ID
|
- [x] Entering an incorrect ID and pressing enter still takes you to the layer editor with an incorrect ID
|
||||||
- [x] A name and description are obligatory to use the layer as single-layer-theme; but those error messages are unclear.
|
- [x] A name and description are obligatory to use the layer as single-layer-theme; but those error messages are unclear.
|
||||||
- [ ]
|
- [x] This user had an expression with two tags in an AND. There was some confusion if the taginfo-count gave the totals for the tags individually or for the entire expression.
|
||||||
- [ ]
|
Fix: play with padding and wording
|
||||||
|
- [x] BUG: having a complex expression for tags (e.g. with `and: [key=value, key0=value0]`) fails as the JSON would be stringified
|
||||||
|
|
|
@ -1109,7 +1109,7 @@ export class ValidateLayer extends Conversion<
|
||||||
const doMatch = baseTags.matchesProperties(properties)
|
const doMatch = baseTags.matchesProperties(properties)
|
||||||
if (!doMatch) {
|
if (!doMatch) {
|
||||||
context
|
context
|
||||||
.enters("presets", i)
|
.enters("presets", i, "tags")
|
||||||
.err(
|
.err(
|
||||||
"This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " +
|
"This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " +
|
||||||
JSON.stringify(properties) +
|
JSON.stringify(properties) +
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||||
import type { TagConfigJson } from "../../../Models/ThemeConfig/Json/TagConfigJson";
|
import type { TagConfigJson } from "../../../Models/ThemeConfig/Json/TagConfigJson";
|
||||||
import FullTagInput from "../../Studio/TagInput/FullTagInput.svelte";
|
import FullTagInput from "../../Studio/TagInput/FullTagInput.svelte";
|
||||||
|
|
||||||
export let value: UIEventSource<undefined | string>;
|
export let value: UIEventSource<TagConfigJson>;
|
||||||
export let uploadableOnly: boolean;
|
export let uploadableOnly: boolean;
|
||||||
export let overpassSupportNeeded: boolean;
|
export let overpassSupportNeeded: boolean;
|
||||||
|
|
||||||
|
@ -14,18 +14,7 @@ export let overpassSupportNeeded: boolean;
|
||||||
*/
|
*/
|
||||||
export let silent: boolean = false;
|
export let silent: boolean = false;
|
||||||
|
|
||||||
let tag: UIEventSource<string | TagConfigJson> = value.sync(s => {
|
let tag: UIEventSource<string | TagConfigJson> = value
|
||||||
try {
|
|
||||||
return JSON.parse(s);
|
|
||||||
} catch (e) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}, [], t => {
|
|
||||||
if(typeof t === "string"){
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
return JSON.stringify(t);
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
import OpeningHoursInput from "./Helpers/OpeningHoursInput.svelte";
|
import OpeningHoursInput from "./Helpers/OpeningHoursInput.svelte";
|
||||||
|
|
||||||
export let type: ValidatorType;
|
export let type: ValidatorType;
|
||||||
export let value: UIEventSource<string>;
|
export let value: UIEventSource<string | object>;
|
||||||
|
|
||||||
export let feature: Feature;
|
export let feature: Feature;
|
||||||
export let args: (string | number | boolean)[] = undefined;
|
export let args: (string | number | boolean)[] = undefined;
|
||||||
|
|
|
@ -74,7 +74,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
feedback?.setData(undefined)
|
feedback?.setData(undefined)
|
||||||
value.setData(v + (selectedUnit.data ?? ""))
|
if(selectedUnit.data){
|
||||||
|
value.setData(v + selectedUnit.data)
|
||||||
|
|
||||||
|
}else{
|
||||||
|
value.setData(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@
|
||||||
bind:group={selectedMapping}
|
bind:group={selectedMapping}
|
||||||
name={"mappings-radio-" + config.id}
|
name={"mappings-radio-" + config.id}
|
||||||
value={i}
|
value={i}
|
||||||
on:keypress={e => {console.log(e) ; if(e.key === "Enter") onSave()}}
|
on:keypress={e => {if(e.key === "Enter") onSave()}}
|
||||||
/>
|
/>
|
||||||
</TagRenderingMappingInput>
|
</TagRenderingMappingInput>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -75,6 +75,7 @@ import AllReviews from "./Reviews/AllReviews.svelte"
|
||||||
import StarsBarIcon from "./Reviews/StarsBarIcon.svelte"
|
import StarsBarIcon from "./Reviews/StarsBarIcon.svelte"
|
||||||
import ReviewForm from "./Reviews/ReviewForm.svelte"
|
import ReviewForm from "./Reviews/ReviewForm.svelte"
|
||||||
import Questionbox from "./Popup/TagRendering/Questionbox.svelte"
|
import Questionbox from "./Popup/TagRendering/Questionbox.svelte"
|
||||||
|
import { TagUtils } from "../Logic/Tags/TagUtils"
|
||||||
|
|
||||||
class NearbyImageVis implements SpecialVisualization {
|
class NearbyImageVis implements SpecialVisualization {
|
||||||
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
||||||
|
@ -1400,6 +1401,49 @@ export default class SpecialVisualizations {
|
||||||
return new FixedUiElement("{" + args[0] + "}")
|
return new FixedUiElement("{" + args[0] + "}")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
funcName: "tags",
|
||||||
|
docs: "Shows a (json of) tags in a human-readable way + links to the wiki",
|
||||||
|
needsUrls: [],
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "key",
|
||||||
|
defaultValue: "value",
|
||||||
|
doc: "The key to look for the tags",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
constr(
|
||||||
|
state: SpecialVisualizationState,
|
||||||
|
tagSource: UIEventSource<Record<string, string>>,
|
||||||
|
argument: string[],
|
||||||
|
feature: Feature,
|
||||||
|
layer: LayerConfig
|
||||||
|
): BaseUIElement {
|
||||||
|
const key = argument[0] ?? "value"
|
||||||
|
return new VariableUiElement(
|
||||||
|
tagSource.map((tags) => {
|
||||||
|
let value = tags[key]
|
||||||
|
if (!value) {
|
||||||
|
return new FixedUiElement("No tags found").SetClass("font-bold")
|
||||||
|
}
|
||||||
|
if (typeof value === "string" && value.startsWith("{")) {
|
||||||
|
value = JSON.parse(value)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const parsed = TagUtils.Tag(value)
|
||||||
|
return parsed.asHumanString(true, false, {})
|
||||||
|
} catch (e) {
|
||||||
|
return new FixedUiElement(
|
||||||
|
"Could not parse this tag: " +
|
||||||
|
JSON.stringify(value) +
|
||||||
|
" due to " +
|
||||||
|
e
|
||||||
|
).SetClass("alert")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
specialVisualizations.push(new AutoApplyButton(specialVisualizations))
|
specialVisualizations.push(new AutoApplyButton(specialVisualizations))
|
||||||
|
|
|
@ -21,7 +21,15 @@
|
||||||
const isTranslation = schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema);
|
const isTranslation = schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema);
|
||||||
let type = schema.hints.typehint ?? "string";
|
let type = schema.hints.typehint ?? "string";
|
||||||
|
|
||||||
let rendervalue = schema.type === "boolean" ? undefined : ((schema.hints.inline ?? schema.path.join(".")) + " <b>{translated(value)}</b>");
|
let rendervalue = ((schema.hints.inline ?? schema.path.join(".")) + " <b>{translated(value)}</b>");
|
||||||
|
|
||||||
|
if(schema.type === "boolean"){
|
||||||
|
rendervalue = undefined
|
||||||
|
}
|
||||||
|
if(schema.hints.typehint === "tag") {
|
||||||
|
rendervalue = "{tags()}"
|
||||||
|
}
|
||||||
|
|
||||||
let helperArgs = schema.hints.typehelper?.split(",");
|
let helperArgs = schema.hints.typehelper?.split(",");
|
||||||
let inline = schema.hints.inline !== undefined;
|
let inline = schema.hints.inline !== undefined;
|
||||||
if (isTranslation) {
|
if (isTranslation) {
|
||||||
|
@ -165,7 +173,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
{#if window.location.hostname === "127.0.0.1"}
|
{#if window.location.hostname === "127.0.0.1"}
|
||||||
<span class="subtle">{schema.path.join(".")}</span>
|
<span class="subtle">{schema.path.join(".")} {schema.hints.typehint}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -92,9 +92,13 @@ let initialTag: TagConfigJson = tag.data;
|
||||||
|
|
||||||
function initWith(initialTag: TagConfigJson) {
|
function initWith(initialTag: TagConfigJson) {
|
||||||
if (typeof initialTag === "string") {
|
if (typeof initialTag === "string") {
|
||||||
|
if (initialTag.startsWith("{")) {
|
||||||
|
initialTag = JSON.parse(initialTag);
|
||||||
|
} else {
|
||||||
addBasicTag(initialTag);
|
addBasicTag(initialTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mode = <"or" | "and">Object.keys(initialTag)[0];
|
mode = <"or" | "and">Object.keys(initialTag)[0];
|
||||||
const subExprs = (<TagConfigJson[]>initialTag[mode]);
|
const subExprs = (<TagConfigJson[]>initialTag[mode]);
|
||||||
if (!subExprs || subExprs.length == 0) {
|
if (!subExprs || subExprs.length == 0) {
|
||||||
|
|
|
@ -58,6 +58,6 @@ const total = tagInfoStats.mapD(data => data.data.find(i => i.type === "all").co
|
||||||
{/if}
|
{/if}
|
||||||
{:else if $tagInfoStats && (!silent || $total < 250) }
|
{:else if $tagInfoStats && (!silent || $total < 250) }
|
||||||
<a href={$tagInfoUrl} target="_blank" class={twMerge(($total < 250) ? "alert" : "thanks", "w-fit link-underline")}>
|
<a href={$tagInfoUrl} target="_blank" class={twMerge(($total < 250) ? "alert" : "thanks", "w-fit link-underline")}>
|
||||||
{$total} features on OSM have this tag
|
{$total} features have <span class="literal-code">{$tag}</span>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue