[ui] constrain value types for certain attrs / selector contexts
parent
267e427a87
commit
f082edd6b5
|
@ -195,7 +195,8 @@
|
|||
{#if editable}
|
||||
<div class="selector">
|
||||
<Selector
|
||||
type="entity"
|
||||
type="value"
|
||||
valueTypes={["Address"]}
|
||||
bind:value={groupToAdd}
|
||||
on:input={addGroup}
|
||||
placeholder="Choose an entity..."
|
||||
|
|
|
@ -1,21 +1,35 @@
|
|||
<script lang="ts">
|
||||
import Selector from "./Selector.svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import type { IValue } from "upend/types";
|
||||
import type { IValue, VALUE_TYPE } from "upend/types";
|
||||
import IconButton from "./IconButton.svelte";
|
||||
import { isEqual } from "lodash";
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let editable: boolean;
|
||||
export let attribute: string | undefined = undefined;
|
||||
export let value: IValue;
|
||||
let newValue: IValue = value;
|
||||
|
||||
// todo - grab from db
|
||||
const TYPES_FOR_ATTR: { [key: string]: VALUE_TYPE[] } = {
|
||||
LBL: ["String"],
|
||||
FILE_SIZE: ["Number"],
|
||||
FILE_MIME: ["String"],
|
||||
ADDED: ["Number"],
|
||||
LAST_VISITED: ["Number"]
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="editable">
|
||||
{#if editable}
|
||||
<div class="inner">
|
||||
<div class="selector">
|
||||
<Selector type="value" bind:value={newValue} />
|
||||
<Selector
|
||||
type="value"
|
||||
valueTypes={TYPES_FOR_ATTR[attribute]}
|
||||
bind:value={newValue}
|
||||
/>
|
||||
</div>
|
||||
<IconButton
|
||||
name="check-circle"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { debounce } from "lodash";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import type { IValue } from "upend/types";
|
||||
import type { IValue, VALUE_TYPE } from "upend/types";
|
||||
import {
|
||||
baseSearchOnce,
|
||||
createLabelled,
|
||||
|
@ -14,7 +14,8 @@
|
|||
|
||||
export let attribute: string | undefined = undefined;
|
||||
export let value: IValue | undefined = undefined;
|
||||
export let type: "attribute" | "value" | "entity";
|
||||
export let type: "attribute" | "value";
|
||||
export let valueTypes: VALUE_TYPE[] | undefined = undefined;
|
||||
export let placeholder = "";
|
||||
|
||||
let inputValue = "";
|
||||
|
@ -43,7 +44,8 @@
|
|||
}
|
||||
|
||||
let options: SelectorOption[] = [];
|
||||
const updateOptions = debounce(async (query: string) => {
|
||||
let objects = [];
|
||||
const updateOptions = debounce(async (query: string, doSearch: boolean) => {
|
||||
if (query.length == 0) {
|
||||
options = [];
|
||||
return;
|
||||
|
@ -62,14 +64,10 @@
|
|||
});
|
||||
break;
|
||||
}
|
||||
case "value":
|
||||
case "entity": {
|
||||
const result = await baseSearchOnce(query);
|
||||
const objects = await getObjects(result.entries);
|
||||
|
||||
case "value": {
|
||||
options = [];
|
||||
|
||||
if (type === "value") {
|
||||
if (valueTypes === undefined || valueTypes.includes("Number")) {
|
||||
const number = parseFloat(query);
|
||||
if (!Number.isNaN(number)) {
|
||||
options.push({
|
||||
|
@ -79,6 +77,9 @@
|
|||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (valueTypes === undefined || valueTypes.includes("String")) {
|
||||
options.push({
|
||||
value: {
|
||||
t: "String",
|
||||
|
@ -87,51 +88,59 @@
|
|||
});
|
||||
}
|
||||
|
||||
let exactHits = Object.entries(addressToLabels)
|
||||
.filter(([_, labels]) =>
|
||||
labels
|
||||
.map((l) => l.toLowerCase())
|
||||
.includes(inputValue.toLowerCase())
|
||||
)
|
||||
.map(([addr, _]) => addr);
|
||||
if (valueTypes === undefined || valueTypes.includes("Address")) {
|
||||
if (doSearch) {
|
||||
const result = await baseSearchOnce(query);
|
||||
objects = await getObjects(result.entries);
|
||||
}
|
||||
|
||||
if (exactHits.length) {
|
||||
exactHits.forEach((addr) =>
|
||||
options.push({
|
||||
value: {
|
||||
t: "Address",
|
||||
c: addr,
|
||||
},
|
||||
})
|
||||
);
|
||||
} else {
|
||||
options.push({
|
||||
labelToCreate: inputValue,
|
||||
});
|
||||
}
|
||||
let exactHits = Object.entries(addressToLabels)
|
||||
.filter(([_, labels]) =>
|
||||
labels
|
||||
.map((l) => l.toLowerCase())
|
||||
.includes(inputValue.toLowerCase())
|
||||
)
|
||||
.map(([addr, _]) => addr);
|
||||
|
||||
options.push(
|
||||
...objects
|
||||
.filter(([addr, _]) => !exactHits.includes(addr))
|
||||
.slice(0, 25)
|
||||
.map(([address, _]) => {
|
||||
return {
|
||||
if (exactHits.length) {
|
||||
exactHits.forEach((addr) =>
|
||||
options.push({
|
||||
value: {
|
||||
t: "Address",
|
||||
c: address,
|
||||
c: addr,
|
||||
},
|
||||
} as SelectorOption;
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
options.push({
|
||||
labelToCreate: inputValue,
|
||||
});
|
||||
}
|
||||
|
||||
options.push(
|
||||
...objects
|
||||
.filter(([addr, _]) => !exactHits.includes(addr))
|
||||
.slice(0, 25)
|
||||
.map(([address, _]) => {
|
||||
return {
|
||||
value: {
|
||||
t: "Address",
|
||||
c: address,
|
||||
},
|
||||
} as SelectorOption;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
options = options;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
|
||||
$: {
|
||||
if (inputFocused) {
|
||||
updateOptions(inputValue);
|
||||
updateOptions(inputValue, true);
|
||||
addressToLabels = {};
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +148,7 @@
|
|||
let addressToLabels: { [key: string]: string[] } = {};
|
||||
function onAddressResolved(address: string, ev: CustomEvent<string[]>) {
|
||||
addressToLabels[address] = ev.detail;
|
||||
updateOptions(inputValue);
|
||||
updateOptions(inputValue, false);
|
||||
}
|
||||
|
||||
async function set(option: SelectorOption) {
|
||||
|
@ -149,7 +158,6 @@
|
|||
inputValue = option.attribute;
|
||||
break;
|
||||
case "value":
|
||||
case "entity":
|
||||
if (!option.labelToCreate) {
|
||||
value = option.value;
|
||||
inputValue = String(option.value.c);
|
||||
|
|
|
@ -292,6 +292,7 @@
|
|||
<td class="value">
|
||||
<Editable
|
||||
{editable}
|
||||
attribute={entry.attribute}
|
||||
value={entry.value}
|
||||
on:edit={(ev) =>
|
||||
updateEntry(entry.address, entry.attribute, ev.detail)}
|
||||
|
|
Loading…
Reference in New Issue