diff --git a/analytics.py b/analytics.py index dec11c5..eccc8b7 100644 --- a/analytics.py +++ b/analytics.py @@ -378,36 +378,7 @@ def dashboard(): params_for_filter = (start_str, filetype + '%') # 1. Top files by access count - query = f''' - SELECT rel_path, COUNT(*) as access_count - FROM file_access_log - WHERE timestamp >= ? {filetype_filter_sql} - GROUP BY rel_path - ORDER BY access_count DESC - LIMIT 1000 - ''' - with log_db: - cursor = log_db.execute(query, params_for_filter) - rows = cursor.fetchall() - - # Convert rows to a list of dictionaries and add category - rows = [ - { - 'rel_path': rel_path, - 'access_count': access_count, - 'category': hf.extract_structure_from_string(rel_path)[0] - } - for rel_path, access_count in rows - ] - - categories = set(r['category'] for r in rows) # distinct categories - top20 = [ - { - 'category': categorie, - 'files': [r for r in rows if r['category'] == categorie][:20] - } - for categorie in categories - ] + # 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" @@ -614,7 +585,6 @@ def dashboard(): return render_template( "dashboard.html", timeframe=session['timeframe'], - top20 = top20, distinct_device_data=distinct_device_data, user_agent_data=user_agent_data, folder_data=folder_data, @@ -629,6 +599,84 @@ def dashboard(): title_long=title_long ) + +@require_secret +def file_access(): + if 'timeframe' not in session: + session['timeframe'] = 'last24hours' + session['timeframe'] = request.args.get('timeframe', session['timeframe']) + + now = datetime.now() + + filetype = 'audio/' + + # Determine start time based on session['timeframe'] + if session['timeframe'] == 'last24hours': + start_dt = now - timedelta(hours=24) + elif session['timeframe'] == '7days': + start_dt = now - timedelta(days=7) + elif session['timeframe'] == '30days': + start_dt = now - timedelta(days=30) + elif session['timeframe'] == '365days': + start_dt = now - timedelta(days=365) + else: + start_dt = now - timedelta(hours=24) + + # We'll compare the textual timestamp (ISO 8601). + start_str = start_dt.isoformat() + + # Filter for mimes that start with the given type + filetype_filter_sql = "AND mime LIKE ?" + params_for_filter = (start_str, filetype + '%') + + # 1. Top files by access count + query = f''' + SELECT rel_path, COUNT(*) as access_count + FROM file_access_log + WHERE timestamp >= ? {filetype_filter_sql} + GROUP BY rel_path + ORDER BY access_count DESC + LIMIT 1000 + ''' + with log_db: + cursor = log_db.execute(query, params_for_filter) + rows = cursor.fetchall() + + # Convert rows to a list of dictionaries and add category + rows = [ + { + 'rel_path': rel_path, + 'access_count': access_count, + 'category': hf.extract_structure_from_string(rel_path)[0] + } + for rel_path, access_count in rows + ] + + # Get possible categories from the rows + categories = sorted({r['category'] for r in rows if r['category'] is not None}) + all_categories = [None] + categories + top20 = [] + for category in all_categories: + label = category if category is not None else 'Keine Kategorie gefunden !' + files = [r for r in rows if r['category'] == category][:20] + top20.append({ + 'category': label, + 'files': files + }) + + title_short = app_config.get('TITLE_SHORT', 'Default Title') + title_long = app_config.get('TITLE_LONG' , 'Default Title') + + return render_template( + "file_access.html", + timeframe=session['timeframe'], + top20 = top20, + admin_enabled=auth.is_admin(), + title_short=title_short, + title_long=title_long + ) + + def export_to_excel(): """Export search_db to an Excel file and store it locally.""" diff --git a/app.py b/app.py index a1ac5f0..a3756c9 100755 --- a/app.py +++ b/app.py @@ -43,6 +43,7 @@ if os.environ.get('FLASK_ENV') == 'production': app.config['SESSION_COOKIE_SECURE'] = True app.add_url_rule('/dashboard', view_func=a.dashboard) +app.add_url_rule('/file_access', view_func=a.file_access) app.add_url_rule('/connections', view_func=a.connections) app.add_url_rule('/mylinks', view_func=auth.mylinks) app.add_url_rule('/remove_secret', view_func=auth.remove_secret, methods=['POST']) @@ -206,6 +207,8 @@ def generate_breadcrumbs(subpath=None): path_accum = "" for part in parts: path_accum = f"{path_accum}/{part}" if path_accum else part + if 'toplist' in part: + part = part.replace('toplist', 'oft angehört') breadcrumbs.append({'name': part, 'path': path_accum}) return breadcrumbs diff --git a/static/app.js b/static/app.js index 190ef90..865ef21 100644 --- a/static/app.js +++ b/static/app.js @@ -124,9 +124,12 @@ function renderContent(data) { if (admin_enabled && data.breadcrumbs.length != 1 && dir.share) { share_link = `⚙️`; } - contentHTML += `
  • 📁 ${dir.name} - ${share_link} -
  • `; + if (dir.path.includes('toplist')) { + link_symbol = '⭐'; + } else { + link_symbol = '📁'; + } + contentHTML += `
  • ${link_symbol} ${dir.name}${share_link}
  • `; }); if (data.breadcrumbs.length === 1) { contentHTML += ``; diff --git a/templates/base.html b/templates/base.html index b2772bd..c4f288d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -45,6 +45,8 @@ | Dashbord | + Dateizugriffe + | Wiederholungen | Ordnerkonfiguration diff --git a/templates/dashboard.html b/templates/dashboard.html index 99868e2..afe2494 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -210,38 +210,7 @@ - - {% for top20_item in top20 %} -
    -
    - Top 20 Dateizugriffe ({{ top20_item['category'] }}) -
    -
    -
    - - - - - - - - - {% for row in top20_item['files'] %} - - - - - {% else %} - - - - {% endfor %} - -
    Access CountFile Path
    {{ row.access_count }}{{ row.rel_path }}
    No data available for the selected timeframe.
    -
    -
    -
    - {% endfor %} + {% endblock %} diff --git a/templates/file_access.html b/templates/file_access.html new file mode 100644 index 0000000..8c97e95 --- /dev/null +++ b/templates/file_access.html @@ -0,0 +1,99 @@ +{# templates/file_access.html #} +{% extends 'base.html' %} + +{# page title #} +{% block title %}Dateizugriffe{% endblock %} + +{# page content #} +{% block content %} + + +
    +

    Auswertung-Dateizugriffe

    + + +
    + + +
    + + + + {% for top20_item in top20 %} +
    +
    + Top 20 Dateizugriffe ({{ top20_item['category'] }}) +
    +
    +
    + + + + + + + + + {% for row in top20_item['files'] %} + + + + + {% else %} + + + + {% endfor %} + +
    Access CountFile Path
    {{ row.access_count }}{{ row.rel_path }}
    No data available for the selected timeframe.
    +
    +
    +
    + {% endfor %} +
    + {% endblock %} + + {% block scripts %} + +{% endblock %} diff --git a/templates/songs_dashboard.html b/templates/songs_dashboard.html index 99001b6..f018e25 100644 --- a/templates/songs_dashboard.html +++ b/templates/songs_dashboard.html @@ -8,7 +8,7 @@ {% block content %} -
    +

    Analyse Wiederholungen