[ui] add group add feature, fix group display

also add entity type to selector, input event
feat/vaults
Tomáš Mládek 2022-01-30 16:30:14 +01:00
parent 859838f124
commit 4f426bca6f
No known key found for this signature in database
GPG Key ID: ED21612889E75EC5
2 changed files with 84 additions and 28 deletions

View File

@ -10,6 +10,8 @@
import Spinner from "./utils/Spinner.svelte"; import Spinner from "./utils/Spinner.svelte";
import NotesEditor from "./utils/NotesEditor.svelte"; import NotesEditor from "./utils/NotesEditor.svelte";
import type { AttributeChange } from "../types/base"; import type { AttributeChange } from "../types/base";
import Selector from "./utils/Selector.svelte";
import type { IValue } from "upend/types";
export let address: string; export let address: string;
export let index: number | undefined; export let index: number | undefined;
@ -99,7 +101,8 @@
$: groups = ($entity?.backlinks || []) $: groups = ($entity?.backlinks || [])
.filter((e) => e.attribute === "HAS") .filter((e) => e.attribute === "HAS")
.map((e) => e.entity); .map((e) => e.entity)
.sort(); // TODO
async function onChange(ev: CustomEvent<AttributeChange>) { async function onChange(ev: CustomEvent<AttributeChange>) {
const change = ev.detail; const change = ev.detail;
@ -137,6 +140,27 @@
} }
revalidate(); revalidate();
} }
let groupToAdd: IValue | undefined;
async function addGroup() {
if (!groupToAdd) {
return;
}
await fetch(`/api/obj`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
entity: String(groupToAdd.c),
attribute: "HAS",
value: {
t: "Address",
c: address,
},
}),
});
revalidate();
groupToAdd = undefined;
}
</script> </script>
<div class="inspect"> <div class="inspect">
@ -154,6 +178,16 @@
{#each groups as address} {#each groups as address}
<UpObject {address} link /> <UpObject {address} link />
{/each} {/each}
{#if editable}
<div class="selector">
<Selector
type="entity"
bind:value={groupToAdd}
on:input={addGroup}
placeholder="Choose an entity..."
/>
</div>
{/if}
</div> </div>
</section> </section>
</header> </header>
@ -214,8 +248,16 @@
} }
.groups { .groups {
display: flex;
margin: 0.25rem 0; margin: 0.25rem 0;
.content {
display: flex;
flex-wrap: wrap;
gap: 0.5rem 0.5rem;
align-items: center;
}
.selector {
width: 100%;
}
} }
.attributes { .attributes {

View File

@ -1,15 +1,36 @@
<script lang="ts"> <script lang="ts">
import { debounce } from "lodash"; import { debounce } from "lodash";
import { createEventDispatcher } from "svelte";
import type { IValue } from "upend/types"; import type { IValue } from "upend/types";
import { baseSearchOnce, getObjects } from "../../util/search"; import { baseSearchOnce, getObjects } from "../../util/search";
import UpObject from "../display/UpObject.svelte"; import UpObject from "../display/UpObject.svelte";
import IconButton from "./IconButton.svelte"; import IconButton from "./IconButton.svelte";
import Input from "./Input.svelte"; import Input from "./Input.svelte";
const dispatch = createEventDispatcher();
export let attribute: string | undefined = undefined; export let attribute: string | undefined = undefined;
export let value: IValue | undefined = undefined; export let value: IValue | undefined = undefined;
export let type: "attribute" | "value"; export let type: "attribute" | "value" | "entity";
export let placeholder = "";
let inputValue = "";
if (type == "attribute") {
inputValue = attribute || "";
} else {
inputValue = String(value?.c || "");
}
$: if (value === undefined) inputValue = undefined;
function onInput(ev: CustomEvent<string>) {
if (type == "attribute") {
attribute = ev.detail;
} else {
value = {
t: "String",
c: ev.detail,
};
}
}
interface SelectorOption { interface SelectorOption {
attribute?: string; attribute?: string;
@ -36,17 +57,23 @@
}); });
break; break;
} }
case "value": { case "value":
case "entity": {
const result = await baseSearchOnce(query); const result = await baseSearchOnce(query);
const objects = await getObjects(result.entries); const objects = await getObjects(result.entries);
options = [ options = [];
{
if (type === "value") {
options.push({
value: { value: {
t: "String", t: "String",
c: query, c: query,
}, },
}, });
}
options.push(
...objects.slice(0, 25).map(([address, label]) => { ...objects.slice(0, 25).map(([address, label]) => {
return { return {
value: { value: {
@ -54,8 +81,10 @@
c: address, c: address,
}, },
} as SelectorOption; } as SelectorOption;
}), })
]; );
options = options;
break; break;
} }
} }
@ -69,31 +98,15 @@
inputValue = option.attribute; inputValue = option.attribute;
break; break;
case "value": case "value":
case "entity":
value = option.value; value = option.value;
inputValue = String(option.value.c); inputValue = String(option.value.c);
break; break;
} }
dispatch("input", value);
visible = false; visible = false;
} }
let inputValue = "";
if (type == "attribute") {
inputValue = attribute || "";
} else {
inputValue = String(value?.c || "");
}
function onInput(ev: CustomEvent<string>) {
if (type == "attribute") {
attribute = ev.detail;
} else {
value = {
t: "String",
c: ev.detail,
};
}
}
let inputFocused = false; let inputFocused = false;
let hover = false; let hover = false;
$: visible = (inputFocused || hover) && Boolean(options.length); $: visible = (inputFocused || hover) && Boolean(options.length);
@ -112,6 +125,7 @@
bind:value={inputValue} bind:value={inputValue}
on:input={onInput} on:input={onInput}
on:focusChange={(ev) => (inputFocused = ev.detail)} on:focusChange={(ev) => (inputFocused = ev.detail)}
{placeholder}
/> />
{/if} {/if}
<ul <ul