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
|
|
@ -21,7 +21,15 @@
|
|||
const isTranslation = schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema);
|
||||
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 inline = schema.hints.inline !== undefined;
|
||||
if (isTranslation) {
|
||||
|
|
@ -165,7 +173,7 @@
|
|||
{/each}
|
||||
{/if}
|
||||
{#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}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -24,63 +24,63 @@ export let overpassSupportNeeded: boolean;
|
|||
export let silent: boolean;
|
||||
|
||||
function update(_) {
|
||||
let config: TagConfigJson = <any>{};
|
||||
if (!mode) {
|
||||
return;
|
||||
}
|
||||
const tags = [];
|
||||
let config: TagConfigJson = <any>{};
|
||||
if (!mode) {
|
||||
return;
|
||||
}
|
||||
const tags = [];
|
||||
|
||||
const subpartSources = (<UIEventSource<string | TagConfigJson>[]>basicTags.data).concat(expressions.data);
|
||||
for (const src of subpartSources) {
|
||||
const t = src.data;
|
||||
if (!t) {
|
||||
// We indicate upstream that this value is invalid
|
||||
tag.setData(undefined);
|
||||
return;
|
||||
}
|
||||
tags.push(t);
|
||||
}
|
||||
if (tags.length === 1) {
|
||||
tag.setData(tags[0]);
|
||||
} else {
|
||||
config[mode] = tags;
|
||||
tag.setData(config);
|
||||
const subpartSources = (<UIEventSource<string | TagConfigJson>[]>basicTags.data).concat(expressions.data);
|
||||
for (const src of subpartSources) {
|
||||
const t = src.data;
|
||||
if (!t) {
|
||||
// We indicate upstream that this value is invalid
|
||||
tag.setData(undefined);
|
||||
return;
|
||||
}
|
||||
tags.push(t);
|
||||
}
|
||||
if (tags.length === 1) {
|
||||
tag.setData(tags[0]);
|
||||
} else {
|
||||
config[mode] = tags;
|
||||
tag.setData(config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function addBasicTag(value?: string) {
|
||||
const src = new UIEventSource(value);
|
||||
basicTags.data.push(src);
|
||||
basicTags.ping();
|
||||
src.addCallbackAndRunD(_ => update(_));
|
||||
const src = new UIEventSource(value);
|
||||
basicTags.data.push(src);
|
||||
basicTags.ping();
|
||||
src.addCallbackAndRunD(_ => update(_));
|
||||
}
|
||||
|
||||
function removeTag(basicTag: UIEventSource<any>) {
|
||||
const index = basicTags.data.indexOf(basicTag);
|
||||
console.log("Removing", index, basicTag);
|
||||
if (index >= 0) {
|
||||
basicTag.setData(undefined);
|
||||
basicTags.data.splice(index, 1);
|
||||
basicTags.ping();
|
||||
}
|
||||
const index = basicTags.data.indexOf(basicTag);
|
||||
console.log("Removing", index, basicTag);
|
||||
if (index >= 0) {
|
||||
basicTag.setData(undefined);
|
||||
basicTags.data.splice(index, 1);
|
||||
basicTags.ping();
|
||||
}
|
||||
}
|
||||
|
||||
function removeExpression(expr: UIEventSource<any>) {
|
||||
const index = expressions.data.indexOf(expr);
|
||||
if (index >= 0) {
|
||||
expr.setData(undefined);
|
||||
expressions.data.splice(index, 1);
|
||||
expressions.ping();
|
||||
}
|
||||
const index = expressions.data.indexOf(expr);
|
||||
if (index >= 0) {
|
||||
expr.setData(undefined);
|
||||
expressions.data.splice(index, 1);
|
||||
expressions.ping();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function addExpression(expr?: TagConfigJson) {
|
||||
const src = new UIEventSource(expr);
|
||||
expressions.data.push(src);
|
||||
expressions.ping();
|
||||
src.addCallbackAndRunD(_ => update(_));
|
||||
const src = new UIEventSource(expr);
|
||||
expressions.data.push(src);
|
||||
expressions.ping();
|
||||
src.addCallbackAndRunD(_ => update(_));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -91,32 +91,36 @@ basicTags.addCallback(_ => update(_));
|
|||
let initialTag: TagConfigJson = tag.data;
|
||||
|
||||
function initWith(initialTag: TagConfigJson) {
|
||||
if (typeof initialTag === "string") {
|
||||
addBasicTag(initialTag);
|
||||
return;
|
||||
if (typeof initialTag === "string") {
|
||||
if (initialTag.startsWith("{")) {
|
||||
initialTag = JSON.parse(initialTag);
|
||||
} else {
|
||||
addBasicTag(initialTag);
|
||||
return;
|
||||
}
|
||||
mode = <"or" | "and">Object.keys(initialTag)[0];
|
||||
const subExprs = (<TagConfigJson[]>initialTag[mode]);
|
||||
if (!subExprs || subExprs.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (subExprs.length == 1) {
|
||||
initWith(subExprs[0]);
|
||||
return;
|
||||
}
|
||||
for (const subExpr of subExprs) {
|
||||
if (typeof subExpr === "string") {
|
||||
addBasicTag(subExpr);
|
||||
} else {
|
||||
addExpression(subExpr);
|
||||
}
|
||||
}
|
||||
mode = <"or" | "and">Object.keys(initialTag)[0];
|
||||
const subExprs = (<TagConfigJson[]>initialTag[mode]);
|
||||
if (!subExprs || subExprs.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (subExprs.length == 1) {
|
||||
initWith(subExprs[0]);
|
||||
return;
|
||||
}
|
||||
for (const subExpr of subExprs) {
|
||||
if (typeof subExpr === "string") {
|
||||
addBasicTag(subExpr);
|
||||
} else {
|
||||
addExpression(subExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialTag) {
|
||||
addBasicTag();
|
||||
addBasicTag();
|
||||
} else {
|
||||
initWith(initialTag);
|
||||
initWith(initialTag);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -125,45 +129,45 @@ if (!initialTag) {
|
|||
|
||||
<div class="flex items-center">
|
||||
|
||||
{#if !uploadableOnly}
|
||||
<select bind:value={mode}>
|
||||
<option value="and">and</option>
|
||||
<option value="or">or</option>
|
||||
</select>
|
||||
{/if}
|
||||
{#if !uploadableOnly}
|
||||
<select bind:value={mode}>
|
||||
<option value="and">and</option>
|
||||
<option value="or">or</option>
|
||||
</select>
|
||||
{/if}
|
||||
|
||||
<div class="border-l-4 border-black flex flex-col ml-1 pl-1">
|
||||
{#each $basicTags as basicTag (basicTag)}
|
||||
<div class="flex">
|
||||
<BasicTagInput {silent} {overpassSupportNeeded} {uploadableOnly} tag={basicTag} />
|
||||
{#if $basicTags.length + $expressions.length > 1}
|
||||
<button class="border border-black rounded-full w-fit h-fit p-0"
|
||||
on:click={() => removeTag(basicTag)}>
|
||||
<TrashIcon class="w-4 h-4 p-1" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{#each $expressions as expression}
|
||||
<FullTagInput {silent} {overpassSupportNeeded} {uploadableOnly} tag={expression}>
|
||||
<button class="small" slot="delete" on:click={() => removeExpression(expression)}>
|
||||
<TrashIcon class="w-3 h-3 p-0" />
|
||||
Delete subexpression
|
||||
</button>
|
||||
</FullTagInput>
|
||||
{/each}
|
||||
<div class="flex">
|
||||
<button class="w-fit small" on:click={() => addBasicTag()}>
|
||||
Add a tag
|
||||
</button>
|
||||
{#if !uploadableOnly}
|
||||
<!-- Do not allow to add an expression, as everything is 'and' anyway -->
|
||||
<button class="w-fit small" on:click={() => addExpression()}>
|
||||
Add an expression
|
||||
</button>
|
||||
{/if}
|
||||
<slot name="delete" />
|
||||
</div>
|
||||
<div class="border-l-4 border-black flex flex-col ml-1 pl-1">
|
||||
{#each $basicTags as basicTag (basicTag)}
|
||||
<div class="flex">
|
||||
<BasicTagInput {silent} {overpassSupportNeeded} {uploadableOnly} tag={basicTag} />
|
||||
{#if $basicTags.length + $expressions.length > 1}
|
||||
<button class="border border-black rounded-full w-fit h-fit p-0"
|
||||
on:click={() => removeTag(basicTag)}>
|
||||
<TrashIcon class="w-4 h-4 p-1" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{#each $expressions as expression}
|
||||
<FullTagInput {silent} {overpassSupportNeeded} {uploadableOnly} tag={expression}>
|
||||
<button class="small" slot="delete" on:click={() => removeExpression(expression)}>
|
||||
<TrashIcon class="w-3 h-3 p-0" />
|
||||
Delete subexpression
|
||||
</button>
|
||||
</FullTagInput>
|
||||
{/each}
|
||||
<div class="flex">
|
||||
<button class="w-fit small" on:click={() => addBasicTag()}>
|
||||
Add a tag
|
||||
</button>
|
||||
{#if !uploadableOnly}
|
||||
<!-- Do not allow to add an expression, as everything is 'and' anyway -->
|
||||
<button class="w-fit small" on:click={() => addExpression()}>
|
||||
Add an expression
|
||||
</button>
|
||||
{/if}
|
||||
<slot name="delete" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -58,6 +58,6 @@ const total = tagInfoStats.mapD(data => data.data.find(i => i.type === "all").co
|
|||
{/if}
|
||||
{:else if $tagInfoStats && (!silent || $total < 250) }
|
||||
<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>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -130,5 +130,5 @@
|
|||
{:else if $feedbackGlobal}
|
||||
<Tr cls="alert" t={$feedbackGlobal}/>
|
||||
{/if}
|
||||
<TagInfoStats {silent} {tag}/>
|
||||
<TagInfoStats {silent} {tag}/>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue