From: PhiTux Date: Wed, 5 Mar 2025 23:39:02 +0000 (+0100) Subject: huge initial progress with tags X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=57f9df12c3af0ce81eb63827210cd493752951d9;p=DailyTxT.git huge initial progress with tags --- diff --git a/backend/server/routers/logs.py b/backend/server/routers/logs.py index f7b79c1..839ea77 100644 --- a/backend/server/routers/logs.py +++ b/backend/server/routers/logs.py @@ -327,4 +327,16 @@ async def downloadFile(uuid: str, cookie = Depends(users.isLoggedIn)): if file is None: raise HTTPException(status_code=500, detail="Failed to read file") content = security.decrypt_file(file, enc_key) - return StreamingResponse(iter([content])) \ No newline at end of file + return StreamingResponse(iter([content])) + +@router.get("/getTags") +async def getTags(cookie = Depends(users.isLoggedIn)): + content:dict = fileHandling.getTags(cookie["user_id"]) + + if not 'tags' in content: + return [] + + else: + return content['tags'] + + ### NOCH ENTSCHLÜSSELN!!!! \ No newline at end of file diff --git a/backend/server/utils/fileHandling.py b/backend/server/utils/fileHandling.py index 82d506c..f2ccef8 100644 --- a/backend/server/utils/fileHandling.py +++ b/backend/server/utils/fileHandling.py @@ -105,4 +105,20 @@ def removeFile(user_id, uuid): logger.exception(e) return False else: - return True \ No newline at end of file + return True + +def getTags(user_id): + try: + f = open(os.path.join(settings.data_path, str(user_id), "tags.json"), "r") + except FileNotFoundError: + logger.info(f"{user_id}/tags.json - File not found") + return {} + except Exception as e: + logger.exception(e) + raise HTTPException(status_code=500, detail="Internal Server Error when trying to open tags.json") + else: + with f: + s = f.read() + if s == "": + return {} + return json.loads(s) \ No newline at end of file diff --git a/frontend/src/lib/Tag.svelte b/frontend/src/lib/Tag.svelte new file mode 100644 index 0000000..c91ff37 --- /dev/null +++ b/frontend/src/lib/Tag.svelte @@ -0,0 +1,53 @@ + + + +
+
{tag.icon} #{tag.name}
+ {#if isEditable} + + {/if} + {#if isRemovable} + + {/if} + {#if isDeletable} + + {/if} +
+
+ + diff --git a/frontend/src/routes/write/+page.svelte b/frontend/src/routes/write/+page.svelte index 01ab16d..caba1b7 100644 --- a/frontend/src/routes/write/+page.svelte +++ b/frontend/src/routes/write/+page.svelte @@ -16,6 +16,7 @@ import { v4 as uuidv4 } from 'uuid'; import { slide, fade } from 'svelte/transition'; import { autoLoadImages } from '$lib/settingsStore'; + import Tag from '$lib/Tag.svelte'; axios.interceptors.request.use((config) => { config.withCredentials = true; @@ -62,9 +63,26 @@ handleInput(); }); + loadTags(); + getLog(); }); + let tags = $state([]); + function loadTags() { + axios + .get(API_URL + '/logs/getTags') + .then((response) => { + tags = response.data; + }) + .catch((error) => { + console.error(error); + // toast + const toast = new bootstrap.Toast(document.getElementById('toastErrorLoadingTags')); + toast.show(); + }); + } + $effect(() => { if (currentLog !== savedLog) { document.getElementsByClassName('TinyMDE')[0].classList.add('notSaved'); @@ -103,6 +121,7 @@ }); let altPressed = false; + let ctrlPressed = false; function on_key_down(event) { if (event.key === 'Alt') { event.preventDefault(); @@ -115,6 +134,14 @@ event.preventDefault(); changeDay(-1); } + if (event.key === 'Control') { + event.preventDefault(); + ctrlPressed = true; + } + if (event.key === 'g' && ctrlPressed) { + event.preventDefault(); + document.getElementById('tag-input').focus(); + } } function on_key_up(event) { @@ -551,6 +578,97 @@ const modal = new bootstrap.Modal(document.getElementById('modalImages')); modal.show(); } + + let searchTab = $state(''); + let showTagDropdown = $state(false); + + let filteredTags = $state([]); + let selectedTags = $state([]); + + // show the correct tags in the dropdown + $effect(() => { + // exclude already selected tags + let tagsWithoutSelected = tags.filter( + (tag) => !selectedTags.find((selectedTag) => selectedTag.id === tag.id) + ); + + if (searchTab === '') { + filteredTags = tagsWithoutSelected; + } else { + // remove trailing # if present + let searchString = searchTab; + if (searchString.startsWith('#')) { + searchString = searchString.slice(1); + } + + // filter tags for searchstring + filteredTags = tagsWithoutSelected.filter((tag) => + tag.name.toLowerCase().includes(searchString.toLowerCase()) + ); + } + + selectedTagIndex = 0; + }); + + let selectedTagIndex = $state(0); + // Handle Keyboard Navigation in Tag Dropdown + function handleKeyDown(event) { + if (!showTagDropdown || filteredTags.length === 0) return; + + switch (event.key) { + case 'ArrowDown': + event.preventDefault(); // Prevent cursor movement + selectedTagIndex = Math.min(selectedTagIndex + 1, filteredTags.length - 1); + ensureSelectedVisible(); + console.log(selectedTagIndex); + break; + + case 'ArrowUp': + event.preventDefault(); // Prevent cursor movement + selectedTagIndex = Math.max(selectedTagIndex - 1, 0); + ensureSelectedVisible(); + break; + + case 'Enter': + if (selectedTagIndex >= 0 && selectedTagIndex < filteredTags.length) { + event.preventDefault(); + selectTag(filteredTags[selectedTagIndex].id); + } + document.activeElement.blur(); + break; + + case 'Escape': + showTagDropdown = false; + break; + } + } + + function ensureSelectedVisible() { + setTimeout(() => { + const dropdown = document.getElementById('tagDropdown'); + const selectedElement = dropdown?.querySelector('.tag-item.selected'); + + if (dropdown && selectedElement) { + const dropdownRect = dropdown.getBoundingClientRect(); + const selectedRect = selectedElement.getBoundingClientRect(); + + if (selectedRect.top < dropdownRect.top) { + dropdown.scrollTop -= dropdownRect.top - selectedRect.top; + } else if (selectedRect.bottom > dropdownRect.bottom) { + dropdown.scrollTop += selectedRect.bottom - dropdownRect.bottom; + } + } + }, 0); + } + + function selectTag(id) { + selectedTags = [...selectedTags, tags.find((tag) => tag.id === id)]; + searchTab = ''; + } + + function removeTag(id) { + selectedTags = selectedTags.filter((tag) => tag.id !== id); + } @@ -641,7 +759,51 @@