Suchfunktion eingebaut
This commit is contained in:
+125
-2
@@ -668,6 +668,40 @@ h1 {
|
||||
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 {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
@@ -720,6 +754,16 @@ a.button:hover {
|
||||
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) {
|
||||
body {
|
||||
padding: 12px;
|
||||
@@ -828,9 +872,32 @@ a.button:hover {
|
||||
|
||||
<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 %}
|
||||
|
||||
<table>
|
||||
<table id="finishedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Zeitpunkt</th>
|
||||
@@ -846,7 +913,11 @@ a.button:hover {
|
||||
<tbody>
|
||||
|
||||
{% 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>
|
||||
|
||||
@@ -894,6 +965,51 @@ a.button:hover {
|
||||
</div>
|
||||
|
||||
<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() {
|
||||
try {
|
||||
const response = await fetch("/api/live", { cache: "no-store" });
|
||||
@@ -943,7 +1059,12 @@ def render_index():
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
|
||||
for item in files:
|
||||
item["sort_ts"] = item["sort_date"]
|
||||
|
||||
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:
|
||||
process = ffmpeg_process
|
||||
@@ -975,6 +1096,8 @@ def render_index():
|
||||
return render_template_string(
|
||||
HTML,
|
||||
recordings=files,
|
||||
artists=artists,
|
||||
albums=albums,
|
||||
recording=recording,
|
||||
normalizing_filename=normalizing_filename,
|
||||
status_error=status_error,
|
||||
|
||||
Reference in New Issue
Block a user