Tag suggestions
This commit is contained in:
parent
5f256aba19
commit
162615f789
|
@ -40,7 +40,7 @@
|
|||
<NoteTagButton on:click={focusTags} />
|
||||
</div>
|
||||
<div hidden={!showTags && $noteTags.length === 0}>
|
||||
<NoteTags {noteTags} bind:this={tagsComponent} />
|
||||
<NoteTags {note} {noteTags} bind:this={tagsComponent} />
|
||||
</div>
|
||||
</header>
|
||||
<div class="note-card__body" class:note-card__body--editing={$editing}>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<script lang="ts">
|
||||
import FaXmark from '$icon/fa-xmark.svelte';
|
||||
import type { NoteTagsStore } from '$lib/stores/note-tags';
|
||||
import type { Note } from '$lib/stores/notes';
|
||||
import type { Tag } from '$lib/stores/tags';
|
||||
import Button from '../button.svelte';
|
||||
|
||||
export let note: Note;
|
||||
export let noteTags: NoteTagsStore;
|
||||
|
||||
export function focusTextbox() {
|
||||
|
@ -12,12 +14,20 @@
|
|||
|
||||
let textbox: HTMLInputElement;
|
||||
let newTagLabel: string = '';
|
||||
let suggestions: string[] = [];
|
||||
|
||||
function addTag(event: KeyboardEvent) {
|
||||
async function onKeyup(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter') {
|
||||
addTag();
|
||||
} else {
|
||||
suggestions = await noteTags.search(newTagLabel);
|
||||
}
|
||||
}
|
||||
|
||||
function addTag() {
|
||||
noteTags.add({ label: newTagLabel });
|
||||
newTagLabel = '';
|
||||
}
|
||||
suggestions = [];
|
||||
}
|
||||
|
||||
function removeTag(tagId: Tag['id']) {
|
||||
|
@ -49,9 +59,15 @@
|
|||
bind:this={textbox}
|
||||
name="newTag"
|
||||
aria-label="New tag"
|
||||
list={`note-tag--${note.id}`}
|
||||
bind:value={newTagLabel}
|
||||
on:keypress={addTag}
|
||||
on:keyup={onKeyup}
|
||||
/>
|
||||
<datalist id={`note-tag--${note.id}`}>
|
||||
{#each suggestions as suggestion}
|
||||
<option value={suggestion} />
|
||||
{/each}
|
||||
</datalist>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -115,6 +131,10 @@
|
|||
&:focus {
|
||||
border: 1px solid hsl(0 0% 0% / 0.4);
|
||||
}
|
||||
|
||||
&::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { writable, type Readable } from 'svelte/store';
|
||||
import { writable, type Readable, get } from 'svelte/store';
|
||||
import type { Note, NotesStore } from './notes';
|
||||
import { db } from '$lib/db/client';
|
||||
import type { Tag, NewTag, TagsStore } from './tags';
|
||||
|
@ -77,4 +77,21 @@ export class NoteTagsStore implements Readable<Tag[]> {
|
|||
this.notes.refreshNotes();
|
||||
this.tags.refreshTags();
|
||||
};
|
||||
|
||||
search = async (searchString: string): Promise<string[]> => {
|
||||
if (!searchString) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const currentTags = get(this.noteTags).map((tag) => tag.label);
|
||||
const results = await db
|
||||
.selectFrom('tag')
|
||||
.select('label')
|
||||
.where('label', 'like', `%${searchString}%`)
|
||||
.where('label', 'not in', [...currentTags, searchString])
|
||||
.limit(10)
|
||||
.execute();
|
||||
|
||||
return results.map((result) => result.label);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue