Merge remote-tracking branch 'origin/development'
This commit is contained in:
commit
7c39b54215
103
analytics.py
103
analytics.py
@ -12,11 +12,8 @@ file_access_temp = []
|
|||||||
|
|
||||||
app_config = auth.return_app_config()
|
app_config = auth.return_app_config()
|
||||||
|
|
||||||
# Example database name; you can change to whatever you want:
|
|
||||||
DB_NAME = 'access_log.db'
|
|
||||||
|
|
||||||
# Create a single global connection to SQLite
|
# Create a single global connection to SQLite
|
||||||
log_db = sqlite3.connect(DB_NAME, check_same_thread=False)
|
log_db = sqlite3.connect("access_log.db", check_same_thread=False)
|
||||||
search_db = sqlite3.connect("search.db", check_same_thread=False)
|
search_db = sqlite3.connect("search.db", check_same_thread=False)
|
||||||
|
|
||||||
# geo location
|
# geo location
|
||||||
@ -144,6 +141,7 @@ def return_file_access():
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def songs_dashboard():
|
def songs_dashboard():
|
||||||
|
# — SESSION & PARAM HANDLING (unchanged) —
|
||||||
if 'songs_dashboard_timeframe' not in session:
|
if 'songs_dashboard_timeframe' not in session:
|
||||||
session['songs_dashboard_timeframe'] = "30"
|
session['songs_dashboard_timeframe'] = "30"
|
||||||
timeframe_param = request.args.get("timeframe", session['songs_dashboard_timeframe'])
|
timeframe_param = request.args.get("timeframe", session['songs_dashboard_timeframe'])
|
||||||
@ -159,50 +157,73 @@ def songs_dashboard():
|
|||||||
site = request.args.get("site", session['songs_dashboard_site'])
|
site = request.args.get("site", session['songs_dashboard_site'])
|
||||||
session['songs_dashboard_site'] = site
|
session['songs_dashboard_site'] = site
|
||||||
|
|
||||||
# Determine cutoff_date based on the days parameter
|
# — DETERMINE CUTOFF + TODAY STRINGS —
|
||||||
if timeframe_param == "all":
|
now = datetime.now()
|
||||||
cutoff_date = None # No date filtering when analyzing all time
|
params = [category, site]
|
||||||
timeframe = "all" # Pass the string to the template if needed
|
date_clauses = []
|
||||||
else:
|
if timeframe_param != "all":
|
||||||
timeframe = int(timeframe_param)
|
cutoff = now - timedelta(days=int(timeframe_param))
|
||||||
now = datetime.now()
|
date_clauses.append("performance_date >= ?")
|
||||||
cutoff_date = now - timedelta(days=timeframe)
|
params.append(cutoff.strftime("%Y-%m-%d"))
|
||||||
|
# filter out any future-dated rows at the DB level
|
||||||
|
date_clauses.append("performance_date <= ?")
|
||||||
|
params.append(now.strftime("%Y-%m-%d"))
|
||||||
|
|
||||||
|
where_sql = " AND ".join(["category = ?", "site = ?"] + date_clauses)
|
||||||
|
|
||||||
cursor = search_db.cursor()
|
cursor = search_db.cursor()
|
||||||
# Query rows with category "Gemeinsamer Gesang"
|
cursor.execute(
|
||||||
query = "SELECT titel, performance_date FROM files WHERE category = ? and site = ?"
|
f"SELECT titel, performance_date FROM files WHERE {where_sql}",
|
||||||
cursor.execute(query, (category, site))
|
params
|
||||||
|
)
|
||||||
rows = cursor.fetchall()
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
# Group and count performances per titel (only if performance_date is within the timeframe,
|
# — AGGREGATE COUNTS + LAST-PERFORMED, WITH ERROR LOGGING —
|
||||||
# or count all if cutoff_date is None)
|
performance_counts = defaultdict(int)
|
||||||
performance_counts = defaultdict(int)
|
last_performed_dates = {}
|
||||||
for titel, performance_date in rows:
|
|
||||||
if performance_date:
|
|
||||||
try:
|
|
||||||
# Convert date from "dd.mm.yyyy" format
|
|
||||||
date_obj = datetime.strptime(performance_date, "%d.%m.%Y")
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
# If cutoff_date is None, count all dates; otherwise, filter by cutoff_date.
|
|
||||||
if cutoff_date is None or date_obj >= cutoff_date:
|
|
||||||
performance_counts[titel] += 1
|
|
||||||
|
|
||||||
# Create a list of tuples: (count, titel), sorted in descending order by count.
|
for titel, perf_date_str in rows:
|
||||||
performance_data = [(count, titel) for titel, count in performance_counts.items()]
|
if not perf_date_str:
|
||||||
performance_data.sort(reverse=True, key=lambda x: x[0])
|
continue
|
||||||
|
|
||||||
|
perf_date_str = perf_date_str.strip()
|
||||||
|
try:
|
||||||
|
perf_date = datetime.strptime(perf_date_str, "%Y-%m-%d")
|
||||||
|
except ValueError:
|
||||||
|
print(f"[songs_dashboard] bad date format for “{titel}”: “{perf_date_str}”")
|
||||||
|
continue
|
||||||
|
|
||||||
|
performance_counts[titel] += 1
|
||||||
|
|
||||||
|
prev = last_performed_dates.get(titel)
|
||||||
|
if prev is None or perf_date > prev:
|
||||||
|
last_performed_dates[titel] = perf_date
|
||||||
|
|
||||||
|
# — BUILD LIST FOR TEMPLATE —
|
||||||
|
performance_data = []
|
||||||
|
for titel, count in performance_counts.items():
|
||||||
|
last_str = last_performed_dates[titel].strftime("%d.%m.%Y")
|
||||||
|
performance_data.append({
|
||||||
|
"titel": titel,
|
||||||
|
"count": count,
|
||||||
|
"last_performed": last_str
|
||||||
|
})
|
||||||
|
|
||||||
|
performance_data.sort(key=lambda x: x["count"], reverse=True)
|
||||||
|
|
||||||
|
# — RENDER —
|
||||||
|
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'),
|
||||||
|
)
|
||||||
|
|
||||||
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
|
@require_secret
|
||||||
def connections():
|
def connections():
|
||||||
|
|||||||
@ -41,9 +41,9 @@
|
|||||||
<span> | </span>
|
<span> | </span>
|
||||||
<a href="{{ url_for('connections') }}">Verbindungen</a>
|
<a href="{{ url_for('connections') }}">Verbindungen</a>
|
||||||
<span> | </span>
|
<span> | </span>
|
||||||
<a href="{{ url_for('dashboard') }}">Auswertung-Downloads</a>
|
<a href="{{ url_for('dashboard') }}">Dashbord</a>
|
||||||
<span> | </span>
|
<span> | </span>
|
||||||
<a href="{{ url_for('songs_dashboard') }}">Auswertung-Wiederholungen</a>
|
<a href="{{ url_for('songs_dashboard') }}">Wiederholungen</a>
|
||||||
{% if admin_enabled %}
|
{% if admin_enabled %}
|
||||||
<span> | </span>
|
<span> | </span>
|
||||||
<a href="{{ url_for('folder_secret_config_editor') }}" id="edit-folder-config">Ordnerkonfiguration</a>
|
<a href="{{ url_for('folder_secret_config_editor') }}" id="edit-folder-config">Ordnerkonfiguration</a>
|
||||||
|
|||||||
@ -6,8 +6,10 @@
|
|||||||
|
|
||||||
{# page‐specific content #}
|
{# page‐specific content #}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
<!-- Main Container -->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Übersicht deiner gültigen Links</h2>
|
<h2>Übersicht deiner Links</h2>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if valid_secrets %}
|
{% if valid_secrets %}
|
||||||
{% for secret in valid_secrets %}
|
{% for secret in valid_secrets %}
|
||||||
@ -17,7 +19,7 @@
|
|||||||
class="card-img-top qr-code p-3"
|
class="card-img-top qr-code p-3"
|
||||||
alt="QR Code for secret">
|
alt="QR Code for secret">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Geheimnis: {{ secret }}</h5>
|
<h5 class="card-title">Secret Link:</h5>
|
||||||
<p class="card-text">
|
<p class="card-text">
|
||||||
<small class="text-muted">Gültig bis: {{ secret_valid_to[secret] }}</small>
|
<small class="text-muted">Gültig bis: {{ secret_valid_to[secret] }}</small>
|
||||||
</p>
|
</p>
|
||||||
@ -29,16 +31,14 @@
|
|||||||
<button type="submit" class="btn btn-danger btn-sm">Link entfernen</button>
|
<button type="submit" class="btn btn-danger btn-sm">Link entfernen</button>
|
||||||
</form>
|
</form>
|
||||||
{% if secret_folders[secret] %}
|
{% if secret_folders[secret] %}
|
||||||
<h6 class="mt-3">Ordner</h6>
|
<h5 class="mt-3">Ordner:</h5>
|
||||||
<ul class="list-group list-group-flush">
|
<div class="list-group">
|
||||||
{% for folder in secret_folders[secret] %}
|
{% for folder in secret_folders[secret] %}
|
||||||
<li class="list-group-item">
|
<a class="btn btn-outline-secondary" style="margin: 5px;" href="/path/{{ folder.foldername }}">{{ folder.foldername }}</a>
|
||||||
<strong>{{ folder.foldername }}</strong>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-muted">Keine Ordner für dieses Gemeimnis hinterlegt.</p>
|
<p class="text-muted">Keine Ordner für dieses Secret hinterlegt.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -66,16 +66,14 @@
|
|||||||
<button type="submit" class="btn btn-danger btn-sm">Link entfernen</button>
|
<button type="submit" class="btn btn-danger btn-sm">Link entfernen</button>
|
||||||
</form>
|
</form>
|
||||||
{% if token_folders[token] %}
|
{% if token_folders[token] %}
|
||||||
<h6 class="mt-3">Ordner</h6>
|
<h5 class="mt-3">Ordner:</h5>
|
||||||
<ul class="list-group list-group-flush">
|
<div class="list-group">
|
||||||
{% for folder in token_folders[token] %}
|
{% for folder in token_folders[token] %}
|
||||||
<li class="list-group-item">
|
<a class="btn btn-outline-secondary" style="margin: 5px;" href="/path/{{ folder.foldername }}">{{ folder.foldername }}</a>
|
||||||
<strong>{{ folder.foldername }}</strong>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-muted">Keine Ordner für dieses Gemeimnis hinterlegt.</p>
|
<p class="text-muted">Keine Ordner für diesen Token hinterlegt.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,147 +7,146 @@
|
|||||||
{# page content #}
|
{# page content #}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<!-- Main Container -->
|
<!-- Main Container -->
|
||||||
<div class="container-fluid px-4">
|
<div class="container-fluid px-4">
|
||||||
<h2>Analyse Wiederholungen</h2>
|
<h2>Analyse Wiederholungen</h2>
|
||||||
<!-- Dropdown Controls -->
|
<!-- Dropdown Controls -->
|
||||||
<div class="mb-4 d-flex flex-wrap gap-2">
|
<div class="mb-4 d-flex flex-wrap gap-2">
|
||||||
|
<!-- Site Dropdown -->
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-secondary dropdown-toggle"
|
||||||
|
type="button" id="siteDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
{% if session['songs_dashboard_site'] == 'Speyer' %}
|
||||||
|
Speyer
|
||||||
|
{% elif session['songs_dashboard_site'] == 'Schwegenheim' %}
|
||||||
|
Schwegenheim
|
||||||
|
{% else %}
|
||||||
|
Select Site
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="siteDropdown">
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_site'] == 'Speyer' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', site='Speyer') }}">
|
||||||
|
Speyer
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_site'] == 'Schwegenheim' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', site='Schwegenheim') }}">
|
||||||
|
Schwegenheim
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Site Dropdown -->
|
<!-- Timeframe Dropdown -->
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<button class="btn btn-secondary dropdown-toggle"
|
<button class="btn btn-secondary dropdown-toggle"
|
||||||
type="button" id="siteDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
type="button" id="timeframeDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
{% if session['songs_dashboard_site'] == 'Speyer' %}
|
{% if session['songs_dashboard_timeframe'] == '7' %}
|
||||||
Speyer
|
Last 7 Days
|
||||||
{% elif session['songs_dashboard_site'] == 'Schwegenheim' %}
|
{% elif session['songs_dashboard_timeframe'] == '30' %}
|
||||||
Schwegenheim
|
Last 30 Days
|
||||||
{% else %}
|
{% elif session['songs_dashboard_timeframe'] == '90' %}
|
||||||
Select Site
|
Last 90 Days
|
||||||
{% endif %}
|
{% elif session['songs_dashboard_timeframe'] == '365' %}
|
||||||
</button>
|
Last 365 Days
|
||||||
<ul class="dropdown-menu" aria-labelledby="siteDropdown">
|
{% elif session['songs_dashboard_timeframe'] == 'all' %}
|
||||||
<li>
|
All Data
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_site'] == 'Speyer' %}active{% endif %}"
|
{% else %}
|
||||||
href="{{ url_for('songs_dashboard', site='Speyer') }}">
|
Select Timeframe
|
||||||
Speyer
|
{% endif %}
|
||||||
</a>
|
</button>
|
||||||
</li>
|
<ul class="dropdown-menu" aria-labelledby="timeframeDropdown">
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_site'] == 'Schwegenheim' %}active{% endif %}"
|
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '7' %}active{% endif %}"
|
||||||
href="{{ url_for('songs_dashboard', site='Schwegenheim') }}">
|
href="{{ url_for('songs_dashboard', timeframe='7') }}">
|
||||||
Schwegenheim
|
Last 7 Days
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
<li>
|
||||||
</div>
|
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '30' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', timeframe='30') }}">
|
||||||
|
Last 30 Days
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '90' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', timeframe='90') }}">
|
||||||
|
Last 90 Days
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '365' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', timeframe='365') }}">
|
||||||
|
Last 365 Days
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == 'all' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', timeframe='all') }}">
|
||||||
|
All Data
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Timeframe Dropdown -->
|
<!-- category Dropdown -->
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<button class="btn btn-secondary dropdown-toggle"
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="categoryDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
type="button" id="timeframeDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
{% if session['songs_dashboard_category'] == 'Gemeinsamer Gesang' %}
|
||||||
{% if session['songs_dashboard_timeframe'] == '7' %}
|
Gemeinsamer Gesang
|
||||||
Last 7 Days
|
{% elif session['songs_dashboard_category'] == 'Chor' %}
|
||||||
{% elif session['songs_dashboard_timeframe'] == '30' %}
|
Chor
|
||||||
Last 30 Days
|
{% elif session['songs_dashboard_category'] == 'Gruppenlied' %}
|
||||||
{% elif session['songs_dashboard_timeframe'] == '90' %}
|
Gruppenlied
|
||||||
Last 90 Days
|
{% else %}
|
||||||
{% elif session['songs_dashboard_timeframe'] == '365' %}
|
Select Category
|
||||||
Last 365 Days
|
{% endif %}
|
||||||
{% elif session['songs_dashboard_timeframe'] == 'all' %}
|
</button>
|
||||||
All Data
|
<ul class="dropdown-menu" aria-labelledby="categoryDropdown">
|
||||||
{% else %}
|
<li>
|
||||||
Select Timeframe
|
<a class="dropdown-item {% if session['songs_dashboard_category'] == 'Gemeinsamer Gesang' %}active{% endif %}"
|
||||||
{% endif %}
|
href="{{ url_for('songs_dashboard', category='Gemeinsamer Gesang') }}">
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="timeframeDropdown">
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '7' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', timeframe='7') }}">
|
|
||||||
Last 7 Days
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '30' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', timeframe='30') }}">
|
|
||||||
Last 30 Days
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '90' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', timeframe='90') }}">
|
|
||||||
Last 90 Days
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == '365' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', timeframe='365') }}">
|
|
||||||
Last 365 Days
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_timeframe'] == 'all' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', timeframe='all') }}">
|
|
||||||
All Data
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- category Dropdown -->
|
|
||||||
<div class="dropdown">
|
|
||||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="categoryDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
|
||||||
{% if session['songs_dashboard_category'] == 'Gemeinsamer Gesang' %}
|
|
||||||
Gemeinsamer Gesang
|
Gemeinsamer Gesang
|
||||||
{% elif session['songs_dashboard_category'] == 'Chor' %}
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_category'] == 'Chor' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', category='Chor') }}">
|
||||||
Chor
|
Chor
|
||||||
{% elif session['songs_dashboard_category'] == 'Gruppenlied' %}
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item {% if session['songs_dashboard_category'] == 'Gruppenlied' %}active{% endif %}"
|
||||||
|
href="{{ url_for('songs_dashboard', category='Gruppenlied') }}">
|
||||||
Gruppenlied
|
Gruppenlied
|
||||||
{% else %}
|
</a>
|
||||||
Select Category
|
</li>
|
||||||
{% endif %}
|
</ul>
|
||||||
</button>
|
</div>
|
||||||
<ul class="dropdown-menu" aria-labelledby="categoryDropdown">
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_category'] == 'Gemeinsamer Gesang' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', category='Gemeinsamer Gesang') }}">
|
|
||||||
Gemeinsamer Gesang
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_category'] == 'Chor' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', category='Chor') }}">
|
|
||||||
Chor
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item {% if session['songs_dashboard_category'] == 'Gruppenlied' %}active{% endif %}"
|
|
||||||
href="{{ url_for('songs_dashboard', category='Gruppenlied') }}">
|
|
||||||
Gruppenlied
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Table Output -->
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Anzahl</th>
|
|
||||||
<th>Titel</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for count, titel in performance_data %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ count }}</td>
|
|
||||||
<td>{{ titel }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
||||||
</body>
|
<!-- Table Output -->
|
||||||
</html>
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Anzahl</th>
|
||||||
|
<th>Titel</th>
|
||||||
|
<th>Zuletzt gesungen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for item in performance_data %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ item['count'] }}</td>
|
||||||
|
<td>{{ item['titel'] }}</td>
|
||||||
|
<td>{{ item['last_performed'] }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user