From 9f3e5bea93fa5f8e4a22bc357d0f79d198b2fe3b Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 6 May 2025 18:44:15 +0200 Subject: [PATCH 1/4] clean up --- migrate_cache.py | 63 -------------------------------------------- swap_city_country.py | 34 ------------------------ 2 files changed, 97 deletions(-) delete mode 100644 migrate_cache.py delete mode 100644 swap_city_country.py diff --git a/migrate_cache.py b/migrate_cache.py deleted file mode 100644 index 6f67065..0000000 --- a/migrate_cache.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -""" -migrate_cache.py - -Migrate DiskCache caches from “old” in‐memory entries (bytes, mime) into -“new” on‐disk read=True entries so that Flask can send them via send_file(path). - -Usage: - python migrate_cache.py /path/to/filecache_audio \ - /path/to/filecache_image \ - /path/to/filecache_video \ - /path/to/filecache_other -""" - -import io -import sys -from diskcache import Cache - -def migrate_cache(cache_path): - """ - Walks every key in the cache at `cache_path`. If the value is a tuple of - (bytes, mime), re‐writes it via read=True so DiskCache stores it as a file. - """ - print(f"➡ Migrating cache at {cache_path!r}") - cache = Cache(cache_path) - migrated = 0 - skipped = 0 - - # Iterate keys without loading everything into memory - for key in cache.iterkeys(): - try: - val = cache.get(key) - except Exception as e: - print(f" [ERROR] key={key!r} get failed: {e}") - continue - - # Detect old‐style entries: (bytes, mime) - if ( - isinstance(val, tuple) - and len(val) == 2 - and isinstance(val[0], (bytes, bytearray)) - and isinstance(val[1], str) - ): - data, mime = val - buf = io.BytesIO(data) - buf.seek(0) - # Re‐store as an on‐disk file - cache.set(key, buf, read=True) - migrated += 1 - else: - skipped += 1 - - cache.close() - print(f" → Done: migrated={migrated}, skipped={skipped}\n") - - -if __name__ == "__main__": - if len(sys.argv) < 2: - print("Usage: migrate_cache.py [ ...]") - sys.exit(1) - - for directory in sys.argv[1:]: - migrate_cache(directory) diff --git a/swap_city_country.py b/swap_city_country.py deleted file mode 100644 index 505967a..0000000 --- a/swap_city_country.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -import sqlite3 - -# — CONFIGURE — -DB_NAME = 'access_log.db' -INDICATORS = [ - "Germany", - "Canada", - "Paraguay", - "Uruguay", - "France", - "Australia", - "Ukraine", - "India" -] -# — END CONFIG — - -# connect exactly as you use elsewhere -log_db = sqlite3.connect(DB_NAME, check_same_thread=False) - -# build and run the swap -placeholders = ",".join("?" for _ in INDICATORS) -sql = f""" - UPDATE file_access_log - SET city = country, - country = city - WHERE city IN ({placeholders}) -""" -cur = log_db.cursor() -cur.execute(sql, INDICATORS) -log_db.commit() - -print(f"Swapped city↔country on {cur.rowcount} row{'s' if cur.rowcount!=1 else ''}.") -log_db.close() From 2e8f586f5bbbb65e64069f304378e1675d238e43 Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 6 May 2025 19:54:11 +0200 Subject: [PATCH 2/4] fir into gui structure --- analytics.py | 28 ++++++++- auth.py | 8 ++- folder_secret_config_editor.py | 9 ++- static/app.css | 22 +++++++ templates/base.html | 67 +++++++++------------- templates/connections.html | 12 ++-- templates/dashboard.html | 4 +- templates/folder_secret_config_editor.html | 4 +- templates/mylinks.html | 8 +-- templates/search.html | 18 ++---- templates/songs_dashboard.html | 6 +- 11 files changed, 104 insertions(+), 82 deletions(-) diff --git a/analytics.py b/analytics.py index 4d562aa..65c6c50 100644 --- a/analytics.py +++ b/analytics.py @@ -10,6 +10,8 @@ import auth file_access_temp = [] +app_config = auth.return_app_config() + # Example database name; you can change to whatever you want: DB_NAME = 'access_log.db' @@ -190,11 +192,26 @@ def songs_dashboard(): performance_data = [(count, titel) for titel, count in performance_counts.items()] performance_data.sort(reverse=True, key=lambda x: x[0]) - return render_template('songs_dashboard.html', timeframe=timeframe_param, performance_data=performance_data, site=site, category=category, admin_enabled=auth.is_admin()) + title_short = app_config.get('TITLE_SHORT', 'Default Title') + title_long = app_config.get('TITLE_LONG' , 'Default Title') + + return render_template('songs_dashboard.html', + timeframe=timeframe_param, + performance_data=performance_data, + site=site, + category=category, + admin_enabled=auth.is_admin(), + title_short=title_short, + title_long=title_long) @require_secret def connections(): - return render_template('connections.html', admin_enabled=auth.is_admin()) + title_short = app_config.get('TITLE_SHORT', 'Default Title') + title_long = app_config.get('TITLE_LONG' , 'Default Title') + return render_template('connections.html', + admin_enabled=auth.is_admin(), + title_short=title_short, + title_long=title_long) @require_secret def dashboard(): @@ -465,6 +482,9 @@ def dashboard(): # Convert the top-files rows to a list of dictionaries rows = [dict(rel_path=r[0], access_count=r[1]) for r in rows] + title_short = app_config.get('TITLE_SHORT', 'Default Title') + title_long = app_config.get('TITLE_LONG' , 'Default Title') + return render_template( "dashboard.html", timeframe=session['timeframe'], @@ -478,7 +498,9 @@ def dashboard(): unique_user=unique_user, cached_percentage=cached_percentage, timeframe_data=timeframe_data, - admin_enabled=auth.is_admin() + admin_enabled=auth.is_admin(), + title_short=title_short, + title_long=title_long ) def export_to_excel(): diff --git a/auth.py b/auth.py index 01d27aa..e604ed0 100644 --- a/auth.py +++ b/auth.py @@ -235,6 +235,9 @@ def mylinks(): token_url[token] = url token_valid_to[token] = token_item.get('validity', 'Unbekannt') + title_short = app_config.get('TITLE_SHORT', 'Default Title') + title_long = app_config.get('TITLE_LONG' , 'Default Title') + return render_template('mylinks.html', valid_secrets=valid_secrets, secret_qr_codes=secret_qr_codes, @@ -247,7 +250,10 @@ def mylinks(): token_folders=token_folders, token_url=token_url, token_valid_to=token_valid_to, - admin_enabled=is_admin() + admin_enabled=is_admin(), + + title_short=title_short, + title_long=title_long ) diff --git a/folder_secret_config_editor.py b/folder_secret_config_editor.py index 7e93f2d..c437919 100644 --- a/folder_secret_config_editor.py +++ b/folder_secret_config_editor.py @@ -6,6 +6,7 @@ import secrets import string import auth +app_config = auth.return_app_config() # Secret alphabet ALPHABET = string.ascii_letters + string.digits @@ -13,7 +14,13 @@ ALPHABET = string.ascii_letters + string.digits @auth.require_admin def folder_secret_config_editor(): - return render_template('folder_secret_config_editor.html', alphabet=ALPHABET, admin_enabled=auth.is_admin()) + title_short = app_config.get('TITLE_SHORT', 'Default Title') + title_long = app_config.get('TITLE_LONG' , 'Default Title') + return render_template('folder_secret_config_editor.html', + alphabet=ALPHABET, + admin_enabled=auth.is_admin(), + title_short=title_short, + title_long=title_long) @auth.require_admin def folder_secret_config_action(): diff --git a/static/app.css b/static/app.css index 57c34dc..38b9f06 100644 --- a/static/app.css +++ b/static/app.css @@ -4,6 +4,7 @@ html, body { color: var(--main-text-color); height: 100%; margin: 0; + /* padding: 0; */ } /* Global Styles */ @@ -23,6 +24,7 @@ body { display: flex; align-items: center; padding: 10px 20px; + /* width: 100%; */ } .site-header img.logo { height: 50px; @@ -51,6 +53,12 @@ body { font-size: 18px; } +.container-fluid { + height: 100%; + display: flex; + flex-direction: column; +} + /* Breadcrumb Styles */ .breadcrumb { margin-bottom: 15px; @@ -294,3 +302,17 @@ footer { .image-item.loaded .thumbnail { transform: scale(1.05); } + +.qr-code { + max-width: 300px; + display: block; + margin: auto; +} + +.card { + margin-bottom: 20px; +} + +.locked { background-color:#eee; } + +.unlocked { background-color: #fff3cd; } \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 5789a34..c212de4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -7,52 +7,39 @@ {% block title %}Meine Links{% endblock %} - - + + {% block head_extra %}{% endblock %} + +
+ +
+ + App + | + Meine Links + | + Verbindungen + | + Auswertung-Downloads + | + Auswertung-Wiederholungen + {% if admin_enabled %} + | + Ordnerkonfiguration + {% endif %} +
- -
- App - Meine Links - Verbindungen - Auswertung-Downloads - Auswertung-Wiederholungen - {% if admin_enabled %} - Ordnerkonfiguration - {% endif %} - {% block nav_extra %}{% endblock %} + {% block content %}{% endblock %}
-
-

{% block nav_brand %}Übersicht deiner gültigen Links{% endblock %}

-
- - {% block content %}{% endblock %} {% block scripts %}{% endblock %} diff --git a/templates/connections.html b/templates/connections.html index 6daa255..67b59b9 100644 --- a/templates/connections.html +++ b/templates/connections.html @@ -3,14 +3,6 @@ {% block title %}Recent Connections{% endblock %} -{% block nav_brand %}Downloads der letzten 10 Minuten{% endblock %} - -{% block nav_extra %} - - Anzahl Verbindungen: 0 - -{% endblock %} - {% block head_extra %} - +

Suche

diff --git a/templates/songs_dashboard.html b/templates/songs_dashboard.html index f5aa56e..a08c7e5 100644 --- a/templates/songs_dashboard.html +++ b/templates/songs_dashboard.html @@ -2,16 +2,14 @@ {% extends 'base.html' %} {# page title #} -{% block title %}Edit Folder Config{% endblock %} - -{# override navbar text: #} -{% block nav_brand %}Dashboard - Analyse Wiederholungen{% endblock %} +{% block title %}Analyse Wiederholungen{% endblock %} {# page content #} {% block content %}
+

Analyse Wiederholungen

From eccfce1a0c24a8ad64e895052decca149398bf6e Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 6 May 2025 20:02:20 +0200 Subject: [PATCH 3/4] small touch --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index c212de4..a104459 100644 --- a/templates/base.html +++ b/templates/base.html @@ -21,7 +21,7 @@
-
+
App | From 88c4eecb3bef566c19d510d5eb005ab94d82991e Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 6 May 2025 20:24:23 +0200 Subject: [PATCH 4/4] select folder during search --- search.py | 12 ++++++++++-- templates/search.html | 11 +++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/search.py b/search.py index 913b07b..3a9c4b6 100644 --- a/search.py +++ b/search.py @@ -16,12 +16,18 @@ with open("app_config.json", 'r') as file: def searchcommand(): query = request.form.get("query", "").strip() category = request.form.get("category", "").strip() + searchfolder = request.form.get("folder", "").strip() + include_transcript = request.form.get("includeTranscript") in ["true", "on"] words = [w for w in query.split() if w] cursor = search_db.cursor() allowed_basefolders = list(session['folders'].keys()) - print("Allowed base folders:", allowed_basefolders) + + # if the search folder is allowed to be searched, select it + # if not just allowed_basefolders rules apply + if searchfolder != "" and searchfolder in allowed_basefolders: + allowed_basefolders = [searchfolder] if not include_transcript: conditions = [] @@ -93,10 +99,12 @@ def searchcommand(): return jsonify(results=results) def search(): + allowed_basefolders = list(session['folders'].keys()) title_short = app_config.get('TITLE_SHORT', 'Default Title') title_long = app_config.get('TITLE_LONG' , 'Default Title') return render_template("search.html", title_short=title_short, - title_long=title_long + title_long=title_long, + search_folders=allowed_basefolders ) diff --git a/templates/search.html b/templates/search.html index dfd810f..fde8869 100644 --- a/templates/search.html +++ b/templates/search.html @@ -88,6 +88,16 @@
+ +
+ + +
@@ -198,6 +208,7 @@ document.addEventListener('DOMContentLoaded', function() { const formData = new FormData(); formData.append('query', query); formData.append('category', category); + formData.append('folder', document.getElementById('folder').value); formData.append('includeTranscript', includeTranscript); fetch('/searchcommand', {