Tag suggestions
This commit is contained in:
parent
5f256aba19
commit
162615f789
|
@ -40,7 +40,7 @@
|
||||||
<NoteTagButton on:click={focusTags} />
|
<NoteTagButton on:click={focusTags} />
|
||||||
</div>
|
</div>
|
||||||
<div hidden={!showTags && $noteTags.length === 0}>
|
<div hidden={!showTags && $noteTags.length === 0}>
|
||||||
<NoteTags {noteTags} bind:this={tagsComponent} />
|
<NoteTags {note} {noteTags} bind:this={tagsComponent} />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="note-card__body" class:note-card__body--editing={$editing}>
|
<div class="note-card__body" class:note-card__body--editing={$editing}>
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FaXmark from '$icon/fa-xmark.svelte';
|
import FaXmark from '$icon/fa-xmark.svelte';
|
||||||
import type { NoteTagsStore } from '$lib/stores/note-tags';
|
import type { NoteTagsStore } from '$lib/stores/note-tags';
|
||||||
|
import type { Note } from '$lib/stores/notes';
|
||||||
import type { Tag } from '$lib/stores/tags';
|
import type { Tag } from '$lib/stores/tags';
|
||||||
import Button from '../button.svelte';
|
import Button from '../button.svelte';
|
||||||
|
|
||||||
|
export let note: Note;
|
||||||
export let noteTags: NoteTagsStore;
|
export let noteTags: NoteTagsStore;
|
||||||
|
|
||||||
export function focusTextbox() {
|
export function focusTextbox() {
|
||||||
|
@ -12,14 +14,22 @@
|
||||||
|
|
||||||
let textbox: HTMLInputElement;
|
let textbox: HTMLInputElement;
|
||||||
let newTagLabel: string = '';
|
let newTagLabel: string = '';
|
||||||
|
let suggestions: string[] = [];
|
||||||
|
|
||||||
function addTag(event: KeyboardEvent) {
|
async function onKeyup(event: KeyboardEvent) {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
noteTags.add({ label: newTagLabel });
|
addTag();
|
||||||
newTagLabel = '';
|
} else {
|
||||||
|
suggestions = await noteTags.search(newTagLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addTag() {
|
||||||
|
noteTags.add({ label: newTagLabel });
|
||||||
|
newTagLabel = '';
|
||||||
|
suggestions = [];
|
||||||
|
}
|
||||||
|
|
||||||
function removeTag(tagId: Tag['id']) {
|
function removeTag(tagId: Tag['id']) {
|
||||||
noteTags.remove(tagId);
|
noteTags.remove(tagId);
|
||||||
}
|
}
|
||||||
|
@ -49,9 +59,15 @@
|
||||||
bind:this={textbox}
|
bind:this={textbox}
|
||||||
name="newTag"
|
name="newTag"
|
||||||
aria-label="New tag"
|
aria-label="New tag"
|
||||||
|
list={`note-tag--${note.id}`}
|
||||||
bind:value={newTagLabel}
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -115,6 +131,10 @@
|
||||||
&:focus {
|
&:focus {
|
||||||
border: 1px solid hsl(0 0% 0% / 0.4);
|
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 type { Note, NotesStore } from './notes';
|
||||||
import { db } from '$lib/db/client';
|
import { db } from '$lib/db/client';
|
||||||
import type { Tag, NewTag, TagsStore } from './tags';
|
import type { Tag, NewTag, TagsStore } from './tags';
|
||||||
|
@ -77,4 +77,21 @@ export class NoteTagsStore implements Readable<Tag[]> {
|
||||||
this.notes.refreshNotes();
|
this.notes.refreshNotes();
|
||||||
this.tags.refreshTags();
|
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