diff --git a/analytics.py b/analytics.py index b16ebc6..cbccb40 100644 --- a/analytics.py +++ b/analytics.py @@ -353,6 +353,8 @@ def dashboard(): start_dt = now - timedelta(hours=24) elif session['timeframe'] == '7days': start_dt = now - timedelta(days=7) + elif session['timeframe'] == '14days': + start_dt = now - timedelta(days=14) elif session['timeframe'] == '30days': start_dt = now - timedelta(days=30) elif session['timeframe'] == '365days': @@ -381,7 +383,7 @@ def dashboard(): # removed and moved to file_access() function # 2. Distinct device trend - # We'll group by hour if "today", by day if "7days"/"30days", by month if "365days" + # We'll group by hour if "today", by day if 7days/14days/30days, by month if 365days if session['timeframe'] == 'last24hours': # Group by hour: substr(timestamp, 12, 2) -> HH query = f''' @@ -391,7 +393,7 @@ def dashboard(): GROUP BY bucket ORDER BY bucket ''' - elif session['timeframe'] in ('7days', '30days'): + elif session['timeframe'] in ('7days', '14days', '30days'): # Group by day: substr(timestamp, 1, 10) -> YYYY-MM-DD query = f''' SELECT substr(timestamp, 1, 10) AS bucket, COUNT(DISTINCT device_id) AS count @@ -426,7 +428,7 @@ def dashboard(): ] # 3. Download trend - # We'll group by hour if "today", by day if "7days"/"30days", by month if "365days". + # We'll group by hour if "today", by day if 7days/14days/30days, by month if 365days. if session['timeframe'] == 'last24hours': # Hour: substr(timestamp, 12, 2) -> HH query = f''' @@ -436,7 +438,7 @@ def dashboard(): GROUP BY bucket ORDER BY bucket ''' - elif session['timeframe'] in ('7days', '30days'): + elif session['timeframe'] in ('7days', '14days', '30days'): # Day: substr(timestamp, 1, 10) -> YYYY-MM-DD query = f''' SELECT substr(timestamp, 1, 10) AS bucket, COUNT(*) AS count diff --git a/auth.py b/auth.py index e604ed0..72c2cca 100644 --- a/auth.py +++ b/auth.py @@ -152,7 +152,7 @@ def require_secret(f): header_text_color = app_config.get('header_text_color', '#fff') background_color = app_config.get('background_color', '#fff') main_text_color = app_config.get('main_text_color', '#000') - return render_template('index.html', + return render_template('permission.html', title_short=title_short, title_long=title_long, header_color=header_color, @@ -160,7 +160,7 @@ def require_secret(f): main_text_color=main_text_color, background_color=background_color, admin_enabled=is_admin() - ) + ), 403 # Forbidden return decorated_function def require_admin(f): diff --git a/helperfunctions.py b/helperfunctions.py index 92ba3c0..4c9f17e 100644 --- a/helperfunctions.py +++ b/helperfunctions.py @@ -107,7 +107,7 @@ def generate_top_list(category): now = datetime.now() # We'll compare the timestamp - start_dt = now - timedelta(days=30) + start_dt = now - timedelta(days=14) start_str = start_dt.isoformat() # Filter for mimes that start with the given type diff --git a/static/app.css b/static/app.css index 9911970..cf0740a 100644 --- a/static/app.css +++ b/static/app.css @@ -346,4 +346,25 @@ footer { @keyframes spin { to { transform: rotate(360deg); } +} + +.card-body.collapsable { + display: none; + transition: max-height 0.3s ease; + overflow: hidden; + +} + +.card-body.collapsable.show { + display: block; + max-height: 1000px; +} + +.toggle-icon { + font-size: 1.5rem; + user-select: none; +} + +.toggle-icon:hover { + color: #007bff; } \ No newline at end of file diff --git a/static/app.js b/static/app.js index cf4e913..af89095 100644 --- a/static/app.js +++ b/static/app.js @@ -498,4 +498,4 @@ function syncThemeColor() { .forEach(svg => svg.setAttribute('fill', cssVar)); } -document.addEventListener('DOMContentLoaded', syncThemeColor); \ No newline at end of file +document.addEventListener('DOMContentLoaded', syncThemeColor); diff --git a/static/general.js b/static/general.js new file mode 100644 index 0000000..56d59d4 --- /dev/null +++ b/static/general.js @@ -0,0 +1,34 @@ + document.addEventListener('DOMContentLoaded', function() { + // (No per-icon setup needed here—just ensure your CSS is in place.) + }); + + // 1) Delegate clicks on any .toggle-icon, now or in the future: + document.addEventListener('click', function(e) { + // Find the closest .toggle-icon ancestor of the click target, if any + if (!e.target.classList.contains('toggle-icon')) return; + var icon = e.target; + + // Prevent clicks on the icon from bubbling further if you want + e.stopPropagation(); + + // Locate its .card-body.collapsable in the same card + var card = icon.closest('.card'); + if (!card) return; + var body = card.querySelector('.card-body.collapsable'); + if (!body) return; + + // Toggle the 'show' class and swap +/– text + if (body.classList.contains('show')) { + // Collapse: remove show, update icon, remove from set + body.classList.remove('show'); + icon.textContent = '+'; + icon.setAttribute('aria-expanded', 'false'); + openCards.add(key); + } else { + // Expand: add show, update icon, add to set + body.classList.add('show'); + icon.textContent = '–'; + icon.setAttribute('aria-expanded', 'true'); + openCards.add(key); + } + }); diff --git a/templates/base.html b/templates/base.html index c4f288d..3552ee0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -57,7 +57,7 @@ {% block scripts %}{% endblock %} - + diff --git a/templates/connections.html b/templates/connections.html index 67b59b9..e89f48c 100644 --- a/templates/connections.html +++ b/templates/connections.html @@ -26,7 +26,7 @@ {% block content %}
-

Übersicht deiner gültigen Links

+

Verbindungen der letzten 10 Minuten

Anzahl Verbindungen: 0 diff --git a/templates/dashboard.html b/templates/dashboard.html index afe2494..90fbe78 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -20,6 +20,8 @@ Last 24 Hours {% elif session['timeframe'] == '7days' %} Last 7 Days + {% elif session['timeframe'] == '14days' %} + Last 14 Days {% elif session['timeframe'] == '30days' %} Last 30 Days {% elif session['timeframe'] == '365days' %} @@ -41,6 +43,12 @@ Last 7 Days +
  • + + Last 14 Days + +
  • diff --git a/templates/file_access.html b/templates/file_access.html index 8c97e95..78ac21d 100644 --- a/templates/file_access.html +++ b/templates/file_access.html @@ -9,7 +9,7 @@
  • +
  • + + Last 14 Days + +
  • @@ -62,10 +70,11 @@ {% for top20_item in top20 %}
    -
    - Top 20 Dateizugriffe ({{ top20_item['category'] }}) +
    + {{ top20_item['category'] }} + +
    -
    +
    @@ -92,8 +101,6 @@ {% endfor %} - {% endblock %} - - {% block scripts %} - {% endblock %} + + diff --git a/templates/folder_secret_config_editor.html b/templates/folder_secret_config_editor.html index 451edb6..05b14e5 100644 --- a/templates/folder_secret_config_editor.html +++ b/templates/folder_secret_config_editor.html @@ -92,7 +92,8 @@ // header const h5 = document.createElement('h5'); - h5.innerHTML = `Link${expired ? ' ! abgelaufen !' : ''}`; + folderNames = rec.folders.map(f => f.foldername).join(', '); + h5.innerHTML = `Ordner: ${folderNames}${expired ? ' ! abgelaufen !' : ''}`; body.appendChild(h5); // secret input diff --git a/templates/index.html b/templates/permission.html similarity index 100% rename from templates/index.html rename to templates/permission.html diff --git a/templates/songs_dashboard.html b/templates/songs_dashboard.html index f018e25..3be3b24 100644 --- a/templates/songs_dashboard.html +++ b/templates/songs_dashboard.html @@ -46,6 +46,8 @@ type="button" id="timeframeDropdown" data-bs-toggle="dropdown" aria-expanded="false"> {% if session['songs_dashboard_timeframe'] == '7' %} Last 7 Days + {% elif session['songs_dashboard_timeframe'] == '14' %} + Last 14 Days {% elif session['songs_dashboard_timeframe'] == '30' %} Last 30 Days {% elif session['songs_dashboard_timeframe'] == '90' %} @@ -65,6 +67,12 @@ Last 7 Days +
  • + + Last 14 Days + +
  • diff --git a/transcribe_all.py b/transcribe_all.py index de02fa6..e8df9af 100755 --- a/transcribe_all.py +++ b/transcribe_all.py @@ -1,6 +1,7 @@ import os import sys import time +import torch import whisper import concurrent.futures import json @@ -18,7 +19,6 @@ with open("transcription_config.yml", "r", encoding="utf-8") as file: settings = yaml.safe_load(file) folder_list = settings.get("folder_list") model_name = settings.get("model_name") - device = settings.get("device") def load_audio_librosa(path: str, sr: int = 16_000) -> np.ndarray: audio, orig_sr = librosa.load(path, sr=sr) # load + resample to 16 kHz @@ -222,7 +222,10 @@ def process_folder(root_folder): else: print(f"Checked {checked_files} files. Start to transcribe {len(valid_files)} files.") - print("Loading Whisper model...") + # Choose “cuda” if available, otherwise “cpu” + device = "cuda" if torch.cuda.is_available() else "cpu" + print(f"Loading Whisper model on {device}…") + model = whisper.load_model(model_name, device=device) # Use a thread pool to pre-load files concurrently.