upend/webui/src/lib/components/utils/NotesEditor.svelte

78 lines
1.8 KiB
Svelte

<script lang="ts">
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 LabelBorder from './LabelBorder.svelte';
import { i18n } from '$lib/i18n';
import { format } from 'date-fns';
const dispatch = createEventDispatcher();
export let address: string;
let lastSaved: Date | undefined;
$: ({ entity } = useEntity(address));
let noteEntry: UpEntry | undefined;
let notes: string | undefined = undefined;
$: {
if ($entity?.attr['NOTE']?.[0]?.value?.c) {
noteEntry = $entity?.attr['NOTE'][0];
notes = String(noteEntry.value.c);
} else {
noteEntry = undefined;
notes = undefined;
}
}
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);
}
lastSaved = new Date();
}, 500);
function onInput() {
lastSaved = undefined;
update();
}
</script>
<LabelBorder hide={!notes?.length}>
<span slot="header">Notes</span>
<div class="notes" contenteditable on:input={onInput} bind:this={contentEl}>
{notes ? notes : ''}
</div>
<div class="status">
{#if lastSaved}
{$i18n.t('Last saved at {{time}}', { time: format(lastSaved, 'HH:mm') })}
{:else}
{$i18n.t('Waiting for changes...')}
{/if}
</div>
</LabelBorder>
<style lang="scss">
.notes {
background: var(--background);
border-radius: 4px;
padding: 0.5em !important;
}
</style>