From: PhiTux Date: Thu, 6 Mar 2025 22:36:18 +0000 (+0100) Subject: progress in tags-handling X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=8ce8f78463e3ebc07539cb16f4ae2fa269f56f7c;p=DailyTxT.git progress in tags-handling --- diff --git a/backend/server/routers/logs.py b/backend/server/routers/logs.py index 839ea77..ba1b6a7 100644 --- a/backend/server/routers/logs.py +++ b/backend/server/routers/logs.py @@ -331,12 +331,45 @@ async def downloadFile(uuid: str, cookie = Depends(users.isLoggedIn)): @router.get("/getTags") async def getTags(cookie = Depends(users.isLoggedIn)): + enc_key = security.get_enc_key(cookie["user_id"], cookie["derived_key"]) + content:dict = fileHandling.getTags(cookie["user_id"]) if not 'tags' in content: return [] else: + for tag in content['tags']: + tag['icon'] = security.decrypt_text(tag['icon'], enc_key) + tag['name'] = security.decrypt_text(tag['name'], enc_key) + tag['color'] = security.decrypt_text(tag['color'], enc_key) return content['tags'] - ### NOCH ENTSCHLÜSSELN!!!! \ No newline at end of file + +class NewTag(BaseModel): + icon: str + name: str + color: str + +@router.post("/saveTag") +async def saveTag(tag: NewTag, cookie = Depends(users.isLoggedIn)): + enc_key = security.get_enc_key(cookie["user_id"], cookie["derived_key"]) + + content:dict = fileHandling.getTags(cookie["user_id"]) + + if not 'tags' in content: + content['tags'] = [] + content['next_id'] = 1 + + enc_icon = security.encrypt_text(tag.icon, enc_key) + enc_name = security.encrypt_text(tag.name, enc_key) + enc_color = security.encrypt_text(tag.color, enc_key) + + new_tag = {"id": content['next_id'], "icon": enc_icon, "name": enc_name, "color": enc_color} + content['next_id'] += 1 + content['tags'].append(new_tag) + + if not fileHandling.writeTags(cookie["user_id"], content): + return {"success": False} + else: + return {"success": True} \ No newline at end of file diff --git a/backend/server/utils/fileHandling.py b/backend/server/utils/fileHandling.py index f2ccef8..67410f5 100644 --- a/backend/server/utils/fileHandling.py +++ b/backend/server/utils/fileHandling.py @@ -121,4 +121,15 @@ def getTags(user_id): s = f.read() if s == "": return {} - return json.loads(s) \ No newline at end of file + return json.loads(s) + +def writeTags(user_id, content): + try: + f = open(os.path.join(settings.data_path, str(user_id), "tags.json"), "w") + except Exception as e: + logger.exception(e) + return False + else: + with f: + f.write(json.dumps(content, indent=4)) + return True \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e8ddcf7..db5a44d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,6 +13,7 @@ "axios": "^1.7.8", "bootstrap": "^5.3.3", "dayjs": "^1.11.13", + "emoji-picker-element": "^1.26.1", "marked": "^15.0.6", "svelte-outside": "^0.0.3", "tiny-markdown-editor": "^0.1.31", @@ -1927,6 +1928,12 @@ "dev": true, "license": "MIT" }, + "node_modules/emoji-picker-element": { + "version": "1.26.1", + "resolved": "https://registry.npmjs.org/emoji-picker-element/-/emoji-picker-element-1.26.1.tgz", + "integrity": "sha512-XgQ9s2JdmworiqLfJC7eGbzQHGv8yb8U9XofjeRAnOMYaeLh0MfwVAz9oG1YE2U2WnzU0Pys1axMjYtPKJ7YSg==", + "license": "Apache-2.0" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index f50dac4..dcef1be 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -37,6 +37,7 @@ "axios": "^1.7.8", "bootstrap": "^5.3.3", "dayjs": "^1.11.13", + "emoji-picker-element": "^1.26.1", "marked": "^15.0.6", "svelte-outside": "^0.0.3", "tiny-markdown-editor": "^0.1.31", diff --git a/frontend/src/lib/Tag.svelte b/frontend/src/lib/Tag.svelte index c91ff37..c25dd00 100644 --- a/frontend/src/lib/Tag.svelte +++ b/frontend/src/lib/Tag.svelte @@ -2,9 +2,23 @@ import Fa from 'svelte-fa'; import { faTrash, faPencil, faXmark } from '@fortawesome/free-solid-svg-icons'; let { tag, removeTag, isEditable, isRemovable, isDeletable } = $props(); + + let fontColor = $state('#111'); + $effect(() => { + const r = parseInt(tag.color.slice(1, 3), 16); + const g = parseInt(tag.color.slice(3, 5), 16); + const b = parseInt(tag.color.slice(5, 7), 16); + const brightness = r * 0.299 + g * 0.587 + b * 0.114; + + if (brightness > 140) { + fontColor = '#111'; + } else { + fontColor = '#eee'; + } + }); - +
{tag.icon} #{tag.name}
{#if isEditable} diff --git a/frontend/src/lib/TagModal.svelte b/frontend/src/lib/TagModal.svelte new file mode 100644 index 0000000..f3a6bf4 --- /dev/null +++ b/frontend/src/lib/TagModal.svelte @@ -0,0 +1,175 @@ + + + + + diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 1923fe7..f98b4b3 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -324,8 +324,8 @@
diff --git a/frontend/src/routes/write/+page.svelte b/frontend/src/routes/write/+page.svelte index caba1b7..4f02b45 100644 --- a/frontend/src/routes/write/+page.svelte +++ b/frontend/src/routes/write/+page.svelte @@ -11,12 +11,19 @@ import '../../../node_modules/tiny-markdown-editor/dist/tiny-mde.css'; import { API_URL } from '$lib/APIurl.js'; import DatepickerLogic from '$lib/DatepickerLogic.svelte'; - import { faCloudArrowUp, faCloudArrowDown, faTrash } from '@fortawesome/free-solid-svg-icons'; + import { + faCloudArrowUp, + faCloudArrowDown, + faTrash, + faSquarePlus, + faQuestionCircle + } from '@fortawesome/free-solid-svg-icons'; import Fa from 'svelte-fa'; import { v4 as uuidv4 } from 'uuid'; import { slide, fade } from 'svelte/transition'; import { autoLoadImages } from '$lib/settingsStore'; import Tag from '$lib/Tag.svelte'; + import TagModal from '$lib/TagModal.svelte'; axios.interceptors.request.use((config) => { config.withCredentials = true; @@ -66,6 +73,13 @@ loadTags(); getLog(); + + // enable popovers + const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]'); + const popoverList = [...popoverTriggerList].map( + (popoverTriggerEl) => + new bootstrap.Popover(popoverTriggerEl, { trigger: 'focus', html: true }) + ); }); let tags = $state([]); @@ -213,15 +227,6 @@ const imageExtensions = ['jpeg', 'jpg', 'gif', 'png', 'webp']; //TODO: support svg? -> minsize is necessary... - function base64ToArrayBuffer(base64) { - var binaryString = atob(base64); - var bytes = new Uint8Array(binaryString.length); - for (var i = 0; i < binaryString.length; i++) { - bytes[i] = binaryString.charCodeAt(i); - } - return bytes.buffer; - } - $effect(() => { if (filesOfDay) { // add all files to images if correct extension @@ -669,6 +674,49 @@ function removeTag(id) { selectedTags = selectedTags.filter((tag) => tag.id !== id); } + + let editTag = $state({}); + let tagModal; + + function openTagModal(tag) { + if (tag === null) { + editTag = { + icon: '', + name: '', + color: '#f57c00' + }; + } else { + editTag = tag; + } + + tagModal.open(); + } + + let isSavingNewTag = $state(false); + function saveNewTag() { + isSavingNewTag = true; + axios + .post(API_URL + '/logs/saveTag', { + icon: editTag.icon, + name: editTag.name, + color: editTag.color + }) + .then((response) => { + if (response.data.success) { + loadTags(); + tagModal.close(); + } else { + // toast + const toast = new bootstrap.Toast(document.getElementById('toastErrorSavingTag')); + toast.show(); + } + }) + .finally(() => { + // close modal + + isSavingNewTag = false; + }); + } @@ -760,26 +808,49 @@