From 9d6ebfc31cd49e48e5ff7a90ff263b20b1383ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ml=C3=A1dek?= Date: Tue, 6 Feb 2024 22:32:10 +0100 Subject: [PATCH] fix(webui): Notes aren't duplicated (manifested as unreliable saving) also rework semantics of `WidgetChange` --- webui/src/lib/components/Inspect.svelte | 66 ++++++++++--------- .../lib/components/utils/NotesEditor.svelte | 37 +++-------- .../lib/components/widgets/EntryList.svelte | 30 +++++---- webui/src/lib/types/base.ts | 10 +-- 4 files changed, 64 insertions(+), 79 deletions(-) diff --git a/webui/src/lib/components/Inspect.svelte b/webui/src/lib/components/Inspect.svelte index 7884d84..861aa6f 100644 --- a/webui/src/lib/components/Inspect.svelte +++ b/webui/src/lib/components/Inspect.svelte @@ -233,40 +233,42 @@ async function onChange(ev: CustomEvent) { dbg('onChange', ev.detail); - const change = ev.detail; - switch (change.type) { - case 'create': - await api.putEntry({ - entity: address, - attribute: change.attribute, - value: change.value - }); - break; - case 'delete': - await api.deleteEntry(change.address); - break; - case 'update': - await api.putEntityAttribute(address, change.attribute, change.value); - break; - case 'entry-add': - await api.putEntry({ - entity: change.address, - attribute: ATTR_IN, - value: { t: 'Address', c: address } - }); - break; - case 'entry-delete': { - const inEntry = $entity?.attr[`~${ATTR_IN}`]?.find((e) => e.entity === change.address); - if (inEntry) { - await api.deleteEntry(inEntry.address); - } else { - console.warn("Couldn't find IN entry for entity %s?!", change.address); + const changes = Array.isArray(ev.detail) ? ev.detail : [ev.detail]; + for (const change of changes) { + switch (change.type) { + case 'create': + await api.putEntry({ + entity: address, + attribute: change.attribute, + value: change.value + }); + break; + case 'delete': + await api.deleteEntry(change.address); + break; + case 'upsert': + await api.putEntityAttribute(address, change.attribute, change.value); + break; + case 'entry-add': + await api.putEntry({ + entity: change.address, + attribute: ATTR_IN, + value: { t: 'Address', c: address } + }); + break; + case 'entry-delete': { + const inEntry = $entity?.attr[`~${ATTR_IN}`]?.find((e) => e.entity === change.address); + if (inEntry) { + await api.deleteEntry(inEntry.address); + } else { + console.warn("Couldn't find IN entry for entity %s?!", change.address); + } + break; } - break; + default: + console.error('Unimplemented AttributeChange', change); + return; } - default: - console.error('Unimplemented AttributeChange', change); - return; } revalidate(); } diff --git a/webui/src/lib/components/utils/NotesEditor.svelte b/webui/src/lib/components/utils/NotesEditor.svelte index 403d005..5413766 100644 --- a/webui/src/lib/components/utils/NotesEditor.svelte +++ b/webui/src/lib/components/utils/NotesEditor.svelte @@ -2,45 +2,24 @@ import { debounce } from 'lodash'; import { createEventDispatcher } from 'svelte'; import { useEntity } from '$lib/entity'; - import type { AttributeCreate, AttributeUpdate } from '$lib/types/base'; - import type { UpEntry } from '@upnd/upend'; + import type { WidgetChange } from '$lib/types/base'; import LabelBorder from './LabelBorder.svelte'; - const dispatch = createEventDispatcher(); + const dispatch = createEventDispatcher<{ change: WidgetChange }>(); export let address: string; $: ({ entity } = useEntity(address)); - let noteEntry: UpEntry | undefined; - let notes: string | undefined = undefined; - $: { - if ($entity?.attr['NOTE']?.length && $entity?.attr['NOTE'][0]?.value?.c) { - noteEntry = $entity?.attr['NOTE'][0]; - notes = String(noteEntry.value.c); - } else { - noteEntry = undefined; - notes = undefined; - } - } + $: notes = $entity?.get('NOTE')?.toString(); let contentEl: HTMLDivElement; const update = debounce(() => { - if (noteEntry) { - dispatch('change', { - type: 'update', - address: noteEntry.address, - attribute: 'NOTE', - value: { t: 'String', c: contentEl.innerText } - } as AttributeUpdate); - } else { - dispatch('change', { - type: 'create', - address: address, - attribute: 'NOTE', - value: { t: 'String', c: contentEl.innerText } - } as AttributeCreate); - } + dispatch('change', { + type: 'upsert', + attribute: 'NOTE', + value: { t: 'String', c: contentEl.innerText } + }); }, 500); diff --git a/webui/src/lib/components/widgets/EntryList.svelte b/webui/src/lib/components/widgets/EntryList.svelte index b556f5e..e1c4b37 100644 --- a/webui/src/lib/components/widgets/EntryList.svelte +++ b/webui/src/lib/components/widgets/EntryList.svelte @@ -4,7 +4,7 @@ import Ellipsis from '../utils/Ellipsis.svelte'; import UpObject from '../display/UpObject.svelte'; import { createEventDispatcher } from 'svelte'; - import type { AttributeUpdate, WidgetChange } from '$lib/types/base'; + import type { WidgetChange } from '$lib/types/base'; import type { UpEntry, UpListing } from '@upnd/upend'; import IconButton from '../utils/IconButton.svelte'; import Selector, { type SelectorValue, selectorValueAsValue } from '../utils/Selector.svelte'; @@ -18,7 +18,7 @@ import UpLink from '../display/UpLink.svelte'; import { ATTR_ADDED, ATTR_LABEL } from '@upnd/upend/constants'; - const dispatch = createEventDispatcher(); + const dispatch = createEventDispatcher<{ change: WidgetChange }>(); export let columns: string | undefined = undefined; export let header = true; @@ -63,7 +63,7 @@ type: 'create', attribute, value: await selectorValueAsValue(value) - } as WidgetChange); + }); newEntryAttribute = ''; newEntryValue = undefined; } @@ -72,13 +72,18 @@ dispatch('change', { type: 'delete', address } as WidgetChange); } } - async function updateEntry(address: string, attribute: string, value: SelectorValue) { - dispatch('change', { - type: 'update', - address, - attribute, - value: await selectorValueAsValue(value) - } as AttributeUpdate); + async function updateEntry(oldEntry: UpEntry, value: SelectorValue) { + dispatch('change', [ + { + type: 'delete', + address: oldEntry.address + }, + { + type: 'create', + attribute: oldEntry.attribute, + value: await selectorValueAsValue(value) + } + ]); } // Labelling @@ -268,10 +273,7 @@ class="cell value mark-value" data-address={entry.value.t === 'Address' ? entry.value.c : undefined} > - updateEntry(entry.address, entry.attribute, ev.detail)} - > + updateEntry(entry, ev.detail)}> {#if entry.value.t === 'Address'}