feat: Rubrik-Dropdown beim Live-Stellen — freie Kategoriewahl
- Neuer <select id='rubricSelect'> neben dem 🔴 Live Toggle
- Alle 10 Rubriken: Nachrichten, Angebot, Crowdfunding, Branche,
Neuerscheinungen, Ankündigungen, Zubehör, Brettspieltest, Magazin, Video, Podcast
- Bei Live+Haken: Rubrik-Wahl pflicht (Toast wenn 'Rubrik wählen…' gesetzt)
- Backend _handle_publish: nutzt rubric vom Client statt meta category-id
- SAFETY GATE bleibt: ohne Live-Haken → immer Korrektur (catid=61)
- Confirm-Dialog zeigt gewählte Rubrik an
This commit is contained in:
+32
-6
@@ -307,6 +307,9 @@ def build_index(articles: list[dict]) -> str:
|
||||
.live-toggle-label:hover {{ border-color: var(--accent); }}
|
||||
.live-toggle-label:has(input:checked) {{ background: #fef2f2; border-color: #dc3545; color: #dc3545; }}
|
||||
.live-toggle-label input {{ accent-color: #dc3545; }}
|
||||
|
||||
.rubric-live-select {{ font-family: var(--font); font-size: 0.8rem; padding: 0.35rem 0.7rem; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); cursor: pointer; }}
|
||||
.rubric-live-select:focus {{ outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px rgba(32,34,138,0.15); }}
|
||||
.upload-label {{ display: inline-flex; }}
|
||||
|
||||
.token-indicator {{ font-size: 0.7rem; margin-left: 0.6rem; opacity: 0.8; }}
|
||||
@@ -434,6 +437,20 @@ def build_index(articles: list[dict]) -> str:
|
||||
<input type="checkbox" id="liveToggle" onchange="updateLiveMode()">
|
||||
<span class="live-toggle-text">🔴 Live</span>
|
||||
</label>
|
||||
<select id="rubricSelect" class="rubric-live-select" onchange="updateLiveMode()">
|
||||
<option value="0">📂 Rubrik wählen…</option>
|
||||
<option value="9">📰 Nachrichten</option>
|
||||
<option value="64" class="sub">└ Angebot</option>
|
||||
<option value="65" class="sub">└ Crowdfunding</option>
|
||||
<option value="66" class="sub">└ Branche</option>
|
||||
<option value="67" class="sub">└ Neuerscheinungen</option>
|
||||
<option value="68" class="sub">└ Ankündigungen</option>
|
||||
<option value="69" class="sub">└ Zubehör</option>
|
||||
<option value="8">🎲 Brettspieltest</option>
|
||||
<option value="11">📖 Magazin</option>
|
||||
<option value="10">🎬 Video</option>
|
||||
<option value="55">🎙 Podcast</option>
|
||||
</select>
|
||||
<button class="btn btn-publish" id="publishBtn" onclick="publishSelected()" disabled{publish_title}>📢 Veröffentlichen</button>
|
||||
<button class="btn btn-delete" id="deleteBtn" onclick="deleteSelected()" disabled>Markierte löschen</button>
|
||||
<span class="counter" id="counter">0 markiert</span>
|
||||
@@ -612,6 +629,12 @@ def build_index(articles: list[dict]) -> str:
|
||||
const selected = Array.from(document.querySelectorAll('.article-check:checked')).map(cb => cb.value);
|
||||
if (selected.length === 0) return;
|
||||
const live = document.getElementById('liveToggle').checked;
|
||||
const rubric = document.getElementById('rubricSelect').value;
|
||||
|
||||
if (live && rubric === '0') {{
|
||||
showToast('❌ Bitte eine Rubrik wählen (Dropdown rechts neben 🔴 Live)', true);
|
||||
return;
|
||||
}}
|
||||
|
||||
// Readiness-Warnung (soft, blockiert nicht)
|
||||
const notReady = [];
|
||||
@@ -623,7 +646,8 @@ def build_index(articles: list[dict]) -> str:
|
||||
}});
|
||||
let confirmMsg;
|
||||
if (live) {{
|
||||
confirmMsg = '🔴 LIVE: ' + selected.length + ' Artikel ÖFFENTLICH veröffentlichen?\\n\\nDies ist für 10.000+ Leser sichtbar!';
|
||||
const rubricName = document.getElementById('rubricSelect').selectedOptions[0].text;
|
||||
confirmMsg = '🔴 LIVE in »' + rubricName + '«: ' + selected.length + ' Artikel ÖFFENTLICH veröffentlichen?\\n\\nDies ist für 10.000+ Leser sichtbar!';
|
||||
}} else {{
|
||||
confirmMsg = selected.length + ' Artikel auf KORREKTUR hochladen?\\n\\nNur Redaktion sichtbar. Sicher.';
|
||||
}}
|
||||
@@ -640,7 +664,7 @@ def build_index(articles: list[dict]) -> str:
|
||||
const resp = await fetch('/publish', {{
|
||||
method: 'POST',
|
||||
headers: {{'Content-Type': 'application/json', 'Authorization': 'Basic ' + auth}},
|
||||
body: JSON.stringify({{files: selected, live: live}})
|
||||
body: JSON.stringify({{files: selected, live: live, rubric: parseInt(rubric)}})
|
||||
}});
|
||||
const data = await resp.json();
|
||||
if (data.ok) {{
|
||||
@@ -1011,6 +1035,7 @@ h1{color:#c0392b;}p{color:#888;}</style></head>
|
||||
data = json.loads(body)
|
||||
files = data.get("files", [])
|
||||
allow_live = data.get("live", False) # SAFETY GATE: Nur wenn explizit true
|
||||
rubric = data.get("rubric", 0) # 0 = nicht gesetzt
|
||||
except json.JSONDecodeError:
|
||||
self._json_reply(400, {"ok": False, "error": "Invalid JSON"})
|
||||
return
|
||||
@@ -1091,10 +1116,11 @@ h1{color:#c0392b;}p{color:#888;}</style></head>
|
||||
jid_match = re.search(r'<meta\s+name="joomla-id"\s+content="(\d+)"', html_content, re.IGNORECASE)
|
||||
joomla_id = jid_match.group(1) if jid_match else None
|
||||
|
||||
# ── SAFETY GATE: Ohne live=true ALLES auf Korrektur ─────
|
||||
# Extract category from meta – NUR wenn live explizit erlaubt
|
||||
catid = 61 # Default: Korrektur (Redaktion-only, nicht öffentlich)
|
||||
if allow_live:
|
||||
# ── Kategorie: Rubrik vom Dropdown oder meta ──────────
|
||||
catid = 61 # Default: Korrektur
|
||||
if allow_live and rubric > 0:
|
||||
catid = rubric
|
||||
elif allow_live:
|
||||
cat_match = re.search(r'<meta\s+name="category-id"\s+content="(\d+)"', html_content, re.IGNORECASE)
|
||||
if cat_match:
|
||||
catid = int(cat_match.group(1))
|
||||
|
||||
Reference in New Issue
Block a user