fix: Upload-Zone vereinfacht — kein manueller Dateiname mehr

- Text-Input für Artikel-Dateinamen komplett entfernt
- uploadFile() nimmt jetzt den ERSTEN markierten Artikel (Checkbox)
- Drag&Drop-Zone oben: Ziel = markierter Artikel oder Hinweis
- JPEG-Accept verbessert: image/* + explizit .jpg,.jpeg,.png,.webp,.gif
- Obsolete CSS für input[type=text] in upload-zone entfernt
- Nach Upload: Auto-Reload für Badge-Update
This commit is contained in:
Hermes Agent
2026-06-19 00:08:02 +02:00
parent 681437b86b
commit 32d1e1ef86
+16 -12
View File
@@ -238,7 +238,7 @@ def build_index(articles: list[dict]) -> str:
<span class="readiness">{readiness}</span> <span class="readiness">{readiness}</span>
{image_badge} {image_badge}
<label class="row-upload-btn" title="Bild für diesen Artikel hochladen"> <label class="row-upload-btn" title="Bild für diesen Artikel hochladen">
<input type="file" accept="image/*" class="row-file-input" onchange="uploadForRow(this, '{a['filename']}')"> <input type="file" accept="image/*,.jpg,.jpeg,.png,.webp,.gif" class="row-file-input" onchange="uploadForRow(this, '{a['filename']}')">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
</label> </label>
</div>\n""" </div>\n"""
@@ -332,7 +332,6 @@ def build_index(articles: list[dict]) -> str:
.upload-zone h3 {{ font-size: 1rem; color: var(--text); margin-bottom: 0.5rem; }} .upload-zone h3 {{ font-size: 1rem; color: var(--text); margin-bottom: 0.5rem; }}
.upload-zone p {{ font-size: 0.84rem; color: var(--text-muted); margin-bottom: 0.25rem; }} .upload-zone p {{ font-size: 0.84rem; color: var(--text-muted); margin-bottom: 0.25rem; }}
.upload-zone .upload-help {{ font-size: 0.75rem; color: var(--text-muted); margin-bottom: 1rem; font-style: italic; }} .upload-zone .upload-help {{ font-size: 0.75rem; color: var(--text-muted); margin-bottom: 1rem; font-style: italic; }}
.upload-zone input[type="text"] {{ font-family: var(--font); font-size: 0.84rem; padding: 0.4rem 0.7rem; border: 1px solid var(--border); border-radius: 6px; width: 280px; max-width: 100%; margin-right: 0.5rem; }}
.upload-zone input[type="file"] {{ font-family: var(--font); font-size: 0.84rem; }} .upload-zone input[type="file"] {{ font-family: var(--font); font-size: 0.84rem; }}
.upload-zone .upload-row {{ display: flex; gap: 0.5rem; align-items: center; justify-content: center; flex-wrap: wrap; }} .upload-zone .upload-row {{ display: flex; gap: 0.5rem; align-items: center; justify-content: center; flex-wrap: wrap; }}
.upload-result {{ margin-top: 0.8rem; font-size: 0.82rem; font-family: monospace; word-break: break-all; padding: 0.5rem; background: #f0fdf4; border-radius: 6px; display: none; }} .upload-result {{ margin-top: 0.8rem; font-size: 0.82rem; font-family: monospace; word-break: break-all; padding: 0.5rem; background: #f0fdf4; border-radius: 6px; display: none; }}
@@ -409,13 +408,11 @@ def build_index(articles: list[dict]) -> str:
<span class="counter" id="counter">0 markiert</span> <span class="counter" id="counter">0 markiert</span>
</div> </div>
<div class="upload-zone" id="uploadZone"> <div class="upload-zone" id="uploadZone">
<h3>Bild für Artikel hochladen</h3> <h3>📷 Bild hochladen</h3>
<p>1. Wähle den <strong>Artikel-Dateinamen</strong> aus der Liste (z.B. <code>artikel_spirit_island_retro_2017_2026-06-13.html</code>)</p> <p style="margin-bottom:0.5rem;">Ziehe Bilder hierher oder klicke zum Auswählen.</p>
<p>2. Wähle die Bilddatei (.jpg, .png, .webp)</p> <p class="upload-help">Das Bild wird automatisch dem <strong>ersten markierten Artikel</strong> zugeordnet.<br>Oder nutze das 📷 Icon direkt neben dem gewünschten Artikel.</p>
<p class="upload-help">Das Bild wird dem Artikel zugeordnet und nach Veröffentlichung automatisch gelöscht.</p>
<div class="upload-row"> <div class="upload-row">
<input type="text" id="articleFileInput" placeholder="Artikel-Dateiname (z.B. artikel_…)" style="flex:1;min-width:200px;"> <input type="file" id="fileInput" accept="image/*,.jpg,.jpeg,.png,.webp,.gif" onchange="uploadFile()" style="font-family:var(--font);font-size:0.84rem;">
<input type="file" id="fileInput" accept="image/*" onchange="uploadFile()">
</div> </div>
<div class="upload-result" id="uploadResult"></div> <div class="upload-result" id="uploadResult"></div>
</div> </div>
@@ -451,12 +448,16 @@ def build_index(articles: list[dict]) -> str:
function uploadFile() {{ function uploadFile() {{
const file = document.getElementById('fileInput').files[0]; const file = document.getElementById('fileInput').files[0];
const articleFile = document.getElementById('articleFileInput').value.trim();
if (!file) return; if (!file) return;
if (!articleFile) {{
showToast('Bitte zuerst den Artikel-Dateinamen eingeben (z.B. artikel_spirit_island_retro_2017_2026-06-13.html)', true); // Nimm den ersten markierten Artikel als Ziel
const checked = document.querySelectorAll('.article-check:checked');
if (checked.length === 0) {{
showToast('Bitte zuerst einen Artikel markieren (Checkbox links)', true);
return; return;
}} }}
const articleFile = checked[0].value;
const formData = new FormData(); const formData = new FormData();
formData.append('file', file); formData.append('file', file);
formData.append('article', articleFile); formData.append('article', articleFile);
@@ -467,8 +468,11 @@ def build_index(articles: list[dict]) -> str:
.then(r => r.json()) .then(r => r.json())
.then(data => {{ .then(data => {{
if (data.ok) {{ if (data.ok) {{
result.textContent = '' + data.url + ' zugeordnet zu: ' + articleFile; result.textContent = '' + file.name + '' + articleFile;
result.style.background = '#f0fdf4'; result.style.background = '#f0fdf4';
showToast('✅ Bild zugeordnet: ' + articleFile.split('_2026')[0].replace(/_/g,' ').replace('artikel ',''), false);
// Reload nach 1.5s um Badge-Counter zu aktualisieren
setTimeout(() => location.reload(), 1500);
}} else {{ }} else {{
result.textContent = '' + (data.error || 'Fehler'); result.textContent = '' + (data.error || 'Fehler');
result.style.background = '#fef2f2'; result.style.background = '#fef2f2';