fix(webui): Notes aren't duplicated (manifested as unreliable saving)
also rework semantics of `WidgetChange`
This commit is contained in:
parent
f1b608f824
commit
9d6ebfc31c
4 changed files with 64 additions and 79 deletions
|
@ -233,7 +233,8 @@
|
|||
|
||||
async function onChange(ev: CustomEvent<WidgetChange>) {
|
||||
dbg('onChange', ev.detail);
|
||||
const change = ev.detail;
|
||||
const changes = Array.isArray(ev.detail) ? ev.detail : [ev.detail];
|
||||
for (const change of changes) {
|
||||
switch (change.type) {
|
||||
case 'create':
|
||||
await api.putEntry({
|
||||
|
@ -245,7 +246,7 @@
|
|||
case 'delete':
|
||||
await api.deleteEntry(change.address);
|
||||
break;
|
||||
case 'update':
|
||||
case 'upsert':
|
||||
await api.putEntityAttribute(address, change.attribute, change.value);
|
||||
break;
|
||||
case 'entry-add':
|
||||
|
@ -268,6 +269,7 @@
|
|||
console.error('Unimplemented AttributeChange', change);
|
||||
return;
|
||||
}
|
||||
}
|
||||
revalidate();
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
type: 'upsert',
|
||||
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);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
</script>
|
||||
|
||||
|
|
|
@ -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,
|
||||
async function updateEntry(oldEntry: UpEntry, value: SelectorValue) {
|
||||
dispatch('change', [
|
||||
{
|
||||
type: 'delete',
|
||||
address: oldEntry.address
|
||||
},
|
||||
{
|
||||
type: 'create',
|
||||
attribute: oldEntry.attribute,
|
||||
value: await selectorValueAsValue(value)
|
||||
} as AttributeUpdate);
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
// Labelling
|
||||
|
@ -268,10 +273,7 @@
|
|||
class="cell value mark-value"
|
||||
data-address={entry.value.t === 'Address' ? entry.value.c : undefined}
|
||||
>
|
||||
<Editable
|
||||
value={entry.value}
|
||||
on:edit={(ev) => updateEntry(entry.address, entry.attribute, ev.detail)}
|
||||
>
|
||||
<Editable value={entry.value} on:edit={(ev) => updateEntry(entry, ev.detail)}>
|
||||
{#if entry.value.t === 'Address'}
|
||||
<UpObject
|
||||
link
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
import type { IValue } from '@upnd/upend/types';
|
||||
|
||||
export type WidgetChange =
|
||||
export type WidgetOperation =
|
||||
| AttributeCreate
|
||||
| AttributeUpdate
|
||||
| AttributeUpsert
|
||||
| AttributeDelete
|
||||
| EntryInAdd
|
||||
| EntryInDelete;
|
||||
|
||||
export type WidgetChange = WidgetOperation | WidgetOperation[];
|
||||
|
||||
export interface AttributeCreate {
|
||||
type: 'create';
|
||||
attribute: string;
|
||||
value: IValue;
|
||||
}
|
||||
|
||||
export interface AttributeUpdate {
|
||||
type: 'update';
|
||||
export interface AttributeUpsert {
|
||||
type: 'upsert';
|
||||
attribute: string;
|
||||
value: IValue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue