Suchfunktion eingebaut
This commit is contained in:
+125
-2
@@ -668,6 +668,40 @@ h1 {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-bar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, minmax(150px, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar label {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar input,
|
||||||
|
.filter-bar select {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 9px;
|
||||||
|
background: #111;
|
||||||
|
color: #eee;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .search {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-info {
|
||||||
|
color: #999;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
@@ -720,6 +754,16 @@ a.button:hover {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.filter-bar {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .search {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
body {
|
body {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
@@ -828,9 +872,32 @@ a.button:hover {
|
|||||||
|
|
||||||
<h2>Fertige Aufnahmen</h2>
|
<h2>Fertige Aufnahmen</h2>
|
||||||
|
|
||||||
|
<div class="filter-bar">
|
||||||
|
<label>Zeitraum<select id="dateFilter">
|
||||||
|
<option value="all">Alle</option>
|
||||||
|
<option value="today">Heute</option>
|
||||||
|
<option value="yesterday">Gestern</option>
|
||||||
|
<option value="7">Letzte 7 Tage</option>
|
||||||
|
<option value="30">Letzte 30 Tage</option>
|
||||||
|
<option value="month">Dieser Monat</option>
|
||||||
|
<option value="lastmonth">Letzter Monat</option>
|
||||||
|
<option value="year">Dieses Jahr</option>
|
||||||
|
</select></label>
|
||||||
|
<label>Redner<select id="artistFilter">
|
||||||
|
<option value="">Alle Redner</option>
|
||||||
|
{% for artist in artists %}<option value="{{ artist }}">{{ artist }}</option>{% endfor %}
|
||||||
|
</select></label>
|
||||||
|
<label>Veranstaltung<select id="albumFilter">
|
||||||
|
<option value="">Alle Veranstaltungen</option>
|
||||||
|
{% for album in albums %}<option value="{{ album }}">{{ album }}</option>{% endfor %}
|
||||||
|
</select></label>
|
||||||
|
<label class="search">Beschreibung / Volltext<input id="textFilter" type="search" placeholder="Beschreibung, Redner, Veranstaltung, Dateiname …"></label>
|
||||||
|
</div>
|
||||||
|
<div class="filter-info" id="filterInfo"></div>
|
||||||
|
|
||||||
{% if recordings %}
|
{% if recordings %}
|
||||||
|
|
||||||
<table>
|
<table id="finishedTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Zeitpunkt</th>
|
<th>Zeitpunkt</th>
|
||||||
@@ -846,7 +913,11 @@ a.button:hover {
|
|||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
{% for item in recordings %}
|
{% for item in recordings %}
|
||||||
<tr>
|
<tr class="finished-row"
|
||||||
|
data-ts="{{ item.sort_ts }}"
|
||||||
|
data-artist="{{ item.artist }}"
|
||||||
|
data-album="{{ item.album }}"
|
||||||
|
data-search="{{ (item.filename ~ ' ' ~ item.artist ~ ' ' ~ item.title ~ ' ' ~ item.album)|lower }}">
|
||||||
|
|
||||||
<td>{{ item.datetime }}</td>
|
<td>{{ item.datetime }}</td>
|
||||||
|
|
||||||
@@ -894,6 +965,51 @@ a.button:hover {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
function applyFilters() {
|
||||||
|
const range = document.getElementById('dateFilter').value;
|
||||||
|
const artist = document.getElementById('artistFilter').value;
|
||||||
|
const album = document.getElementById('albumFilter').value;
|
||||||
|
const text = document.getElementById('textFilter').value.trim().toLowerCase();
|
||||||
|
const now = new Date();
|
||||||
|
const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime() / 1000;
|
||||||
|
const tomorrow = todayStart + 86400;
|
||||||
|
const yesterday = todayStart - 86400;
|
||||||
|
const week = todayStart - 6 * 86400;
|
||||||
|
const days30 = todayStart - 29 * 86400;
|
||||||
|
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1).getTime() / 1000;
|
||||||
|
const lastMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1).getTime() / 1000;
|
||||||
|
const lastMonthEnd = monthStart;
|
||||||
|
const yearStart = new Date(now.getFullYear(), 0, 1).getTime() / 1000;
|
||||||
|
let visible = 0;
|
||||||
|
|
||||||
|
document.querySelectorAll('.finished-row').forEach(row => {
|
||||||
|
const ts = Number(row.dataset.ts);
|
||||||
|
let dateOk = true;
|
||||||
|
if (range === 'today') dateOk = ts >= todayStart && ts < tomorrow;
|
||||||
|
else if (range === 'yesterday') dateOk = ts >= yesterday && ts < todayStart;
|
||||||
|
else if (range === '7') dateOk = ts >= week;
|
||||||
|
else if (range === '30') dateOk = ts >= days30;
|
||||||
|
else if (range === 'month') dateOk = ts >= monthStart;
|
||||||
|
else if (range === 'lastmonth') dateOk = ts >= lastMonthStart && ts < lastMonthEnd;
|
||||||
|
else if (range === 'year') dateOk = ts >= yearStart;
|
||||||
|
|
||||||
|
const artistOk = !artist || row.dataset.artist === artist;
|
||||||
|
const albumOk = !album || row.dataset.album === album;
|
||||||
|
const textOk = !text || row.dataset.search.includes(text);
|
||||||
|
const ok = dateOk && artistOk && albumOk && textOk;
|
||||||
|
row.style.display = ok ? '' : 'none';
|
||||||
|
if (ok) visible++;
|
||||||
|
});
|
||||||
|
|
||||||
|
const total = document.querySelectorAll('.finished-row').length;
|
||||||
|
document.getElementById('filterInfo').textContent = `${visible} von ${total} Aufnahmen`;
|
||||||
|
}
|
||||||
|
|
||||||
|
['dateFilter', 'artistFilter', 'albumFilter', 'textFilter'].forEach(id =>
|
||||||
|
document.getElementById(id)?.addEventListener('input', applyFilters)
|
||||||
|
);
|
||||||
|
applyFilters();
|
||||||
|
|
||||||
async function updateLiveSection() {
|
async function updateLiveSection() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/live", { cache: "no-store" });
|
const response = await fetch("/api/live", { cache: "no-store" });
|
||||||
@@ -943,7 +1059,12 @@ def render_index():
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
for item in files:
|
||||||
|
item["sort_ts"] = item["sort_date"]
|
||||||
|
|
||||||
files.sort(key=lambda item: item["sort_date"], reverse=True)
|
files.sort(key=lambda item: item["sort_date"], reverse=True)
|
||||||
|
artists = sorted({item["artist"] for item in files if item["artist"]})
|
||||||
|
albums = sorted({item["album"] for item in files if item["album"]})
|
||||||
|
|
||||||
with state_lock:
|
with state_lock:
|
||||||
process = ffmpeg_process
|
process = ffmpeg_process
|
||||||
@@ -975,6 +1096,8 @@ def render_index():
|
|||||||
return render_template_string(
|
return render_template_string(
|
||||||
HTML,
|
HTML,
|
||||||
recordings=files,
|
recordings=files,
|
||||||
|
artists=artists,
|
||||||
|
albums=albums,
|
||||||
recording=recording,
|
recording=recording,
|
||||||
normalizing_filename=normalizing_filename,
|
normalizing_filename=normalizing_filename,
|
||||||
status_error=status_error,
|
status_error=status_error,
|
||||||
|
|||||||
Reference in New Issue
Block a user