From: PhiTux Date: Fri, 3 Jan 2025 17:16:46 +0000 (+0100) Subject: added search function (including primitive exact/OR/AND) X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=c687b1890d1d09167480bc8bdcd40b41656a6f86;p=DailyTxT.git added search function (including primitive exact/OR/AND) --- diff --git a/backend/server/routers/logs.py b/backend/server/routers/logs.py index a6cf338..1d7a785 100644 --- a/backend/server/routers/logs.py +++ b/backend/server/routers/logs.py @@ -1,5 +1,6 @@ import datetime import logging +import re from fastapi import APIRouter, Cookie from pydantic import BaseModel from fastapi import Depends @@ -86,4 +87,100 @@ async def getLog(date: str, cookie = Depends(users.isLoggedIn)): date_written = security.decrypt_text(dayLog["date_written"], enc_key) return {"text": text, "date_written": date_written} - return {"text": "", "date_written": ""} \ No newline at end of file + return {"text": "", "date_written": ""} + +def get_start_index(text, index): + # find a whitespace two places before the index + + if index == 0: + return 0 + + for i in range(3): + startIndex = text.rfind(" ", 0, index-1) + index = startIndex + if startIndex == -1: + return 0 + + return startIndex + 1 + +def get_end_index(text, index): + # find a whitespace two places after the index + + if index == len(text) - 1: + return len(text) + + for i in range(3): + endIndex = text.find(" ", index+1) + index = endIndex + if endIndex == -1: + return len(text) + + return endIndex + + +def get_context(text: str, searchString: str, exact: bool): + # replace whitespace with non-breaking space + text = re.sub(r'\s+', " ", text) + + if exact: + pos = text.find(searchString) + else: + pos = text.lower().find(searchString.lower()) + if pos == -1: + return "Dailytxt: Error formatting..." + + start = get_start_index(text, pos) + end = get_end_index(text, pos + len(searchString) - 1) + return text[start:pos] + "" + text[pos:pos+len(searchString)] + "" + text[pos+len(searchString):end] + + +@router.get("/search") +async def search(searchString: str, cookie = Depends(users.isLoggedIn)): + results = [] + + enc_key = security.get_enc_key(cookie["user_id"], cookie["derived_key"]) + + # search in all years and months (dirs) + for year in fileHandling.get_years(cookie["user_id"]): + for month in fileHandling.get_months(cookie["user_id"], year): + content:dict = fileHandling.getDay(cookie["user_id"], year, int(month)) + if "days" not in content.keys(): + continue + for dayLog in content["days"]: + text = security.decrypt_text(dayLog["text"], enc_key) + + # "..." -> exact + # ... | ... -> or + # ... ... -> and + + if searchString.startswith('"') and searchString.endswith('"'): + if searchString[1:-1] in text: + context = get_context(text, searchString[1:-1], True) + results.append({"year": year, "month": month, "day": dayLog["day"], "text": context}) + + + elif "|" in searchString: + words = searchString.split("|") + for word in words: + if word.strip().lower() in text.lower(): + context = get_context(text, word.strip(), False) + results.append({"year": year, "month": month, "day": dayLog["day"], "text": context}) + break + + + elif " " in searchString: + if all([word.strip().lower() in text.lower() for word in searchString.split()]): + context = get_context(text, searchString.split()[0].strip(), False) + results.append({"year": year, "month": month, "day": dayLog["day"], "text": context}) + + + else: + if searchString.lower() in text.lower(): + context = get_context(text, searchString, False) + results.append({"year": year, "month": month, "day": dayLog["day"], "text": context}) + + + # sort by year and month and day + results.sort(key=lambda x: (int(x["year"]), int(x["month"]), int(x["day"])), reverse=True) + print(results) + return results \ No newline at end of file diff --git a/backend/server/utils/fileHandling.py b/backend/server/utils/fileHandling.py index fb78d71..0bc50ac 100644 --- a/backend/server/utils/fileHandling.py +++ b/backend/server/utils/fileHandling.py @@ -61,4 +61,14 @@ def writeDay(user_id, year, month, content): else: with f: f.write(json.dumps(content, indent=4)) - return True \ No newline at end of file + return True + +def get_years(user_id): + for entry in os.scandir(os.path.join(settings.data_path, str(user_id))): + if entry.is_dir() and entry.name.isnumeric() and len(entry.name) == 4: + yield entry.name + +def get_months(user_id, year): + for entry in os.scandir(os.path.join(settings.data_path, str(user_id), year)): + if entry.is_file() and entry.name.endswith(".json"): + yield entry.name.split(".")[0] \ No newline at end of file diff --git a/frontend/src/lib/searchStore.js b/frontend/src/lib/searchStore.js new file mode 100644 index 0000000..b21437a --- /dev/null +++ b/frontend/src/lib/searchStore.js @@ -0,0 +1,4 @@ +import { writable } from "svelte/store"; + +export let searchString = writable(""); +export let searchResults = writable([]); \ No newline at end of file diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 3ff8dc8..ed672ab 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -7,7 +7,7 @@ import { dev } from '$app/environment'; import { goto } from '$app/navigation'; import { onMount } from 'svelte'; - //import { selectedDate } from './calendar.svelte.js'; + import { searchString, searchResults } from '$lib/searchStore.js'; let API_URL = dev ? `${window.location.origin.replace(/:5173.*$/gm, '')}:8000` @@ -176,6 +176,42 @@ return false; } } + + $effect(() => { + if ($searchString === '') { + $searchResults = []; + } + }); + + let isSearching = $state(false); + function search() { + console.log($searchString); + + if (isSearching) { + return; + } + isSearching = true; + + axios + .get(API_URL + '/logs/search', { + params: { + searchString: $searchString + } + }) + .then((response) => { + $searchResults = [...response.data]; + isSearching = false; + }) + .catch((error) => { + $searchResults = []; + console.error(error); + isSearching = false; + + // toast + const toast = new bootstrap.Toast(document.getElementById('toastErrorSearching')); + toast.show(); + }); + } @@ -191,13 +227,13 @@ aria-label="Close" > - + -
+
- +
@@ -207,11 +243,14 @@
{$selectedDate.toLocaleDateString('locale', { weekday: 'long' })}
- {$selectedDate.toLocaleDateString('locale')} + {$selectedDate.toLocaleDateString('locale', { + day: '2-digit', + month: '2-digit', + year: 'numeric' + })}
Geschrieben am:
- {logDateWritten}
history
@@ -254,10 +293,26 @@
Fehler beim Laden des Textes!
+ +