feat(v3): v3 wird Default unter /antrag/{drs}, v2 zieht nach /v2/antrag/{drs}
Routen:
- /antrag/{drs} → v3 (Standard, Bürger:innen-Modus single column)
- /v2/antrag/{drs} → v2 (alter Profi-Modus, weiterhin erreichbar)
- /v3/antrag/{drs} → Alias auf v3 (für alte Bookmarks)
UI-Hinweise auf alternative Ansichten ausgeblendet:
- v3-Topbar-Pill "Bürger:innen-Modus · Beta" + "→ Profi-Modus"-Toggle raus
- v2-Topbar-Link "→ Bürger:innen-Modus · v3 Beta" raus
Im Admin-Bereich (/v2/admin/stand) neuer Block "Alternative Ansichten"
mit Beispiel-Drucksache, Live-Link auf v3 (Default) und v2 (Profi).
Nur Admins sehen die Hinweise auf v2.
Trennlinien-Cleanup im Rest-Block:
- Doppellinie unter Abstimmungsergebnis aufgelöst (.v3-rest hatte
border-top, das v3-section.border-bottom doppelt war).
- Neue Trennlinien via Klasse v3-rest-divider-top vor:
· Teilen-Block (zwischen Ähnliche und Teilen)
· Aktions-Links (zwischen Teilen und administrativem Bereich)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4f4d9f3478
commit
1ef5578e02
25
app/main.py
25
app/main.py
@ -376,7 +376,22 @@ _MATRIX_EXPLANATIONS = {
|
|||||||
|
|
||||||
@app.get("/antrag/{drucksache:path}", response_class=HTMLResponse)
|
@app.get("/antrag/{drucksache:path}", response_class=HTMLResponse)
|
||||||
async def antrag_detail(request: Request, drucksache: str, current_user: Optional[dict] = Depends(get_current_user)):
|
async def antrag_detail(request: Request, drucksache: str, current_user: Optional[dict] = Depends(get_current_user)):
|
||||||
"""v2-Antrag-Detail (Profi-Modus): volles GWÖ-Dashboard pro Drucksache."""
|
"""Standard-Antrag-Detail (v3 Bürger:innen-Modus, single column).
|
||||||
|
|
||||||
|
Bisheriger Profi-Modus (v2, zwei Spalten) ist unter /v2/antrag/{drs}
|
||||||
|
weiterhin erreichbar — Link im Admin-Bereich (/v2/admin/stand).
|
||||||
|
"""
|
||||||
|
return await _render_antrag_detail(
|
||||||
|
request, drucksache, current_user, "v3/screens/antrag_detail.html"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/v2/antrag/{drucksache:path}", response_class=HTMLResponse)
|
||||||
|
async def antrag_detail_v2(request: Request, drucksache: str, current_user: Optional[dict] = Depends(get_current_user)):
|
||||||
|
"""Alt-Profi-Modus: zweispaltiges Layout mit allen Feldern gleichzeitig.
|
||||||
|
|
||||||
|
Ist nicht mehr Standard, bleibt aber als Power-User-Variante zugaenglich.
|
||||||
|
"""
|
||||||
return await _render_antrag_detail(
|
return await _render_antrag_detail(
|
||||||
request, drucksache, current_user, "v2/screens/antrag_detail.html"
|
request, drucksache, current_user, "v2/screens/antrag_detail.html"
|
||||||
)
|
)
|
||||||
@ -384,12 +399,8 @@ async def antrag_detail(request: Request, drucksache: str, current_user: Optiona
|
|||||||
|
|
||||||
@app.get("/v3/antrag/{drucksache:path}", response_class=HTMLResponse)
|
@app.get("/v3/antrag/{drucksache:path}", response_class=HTMLResponse)
|
||||||
async def antrag_detail_v3(request: Request, drucksache: str, current_user: Optional[dict] = Depends(get_current_user)):
|
async def antrag_detail_v3(request: Request, drucksache: str, current_user: Optional[dict] = Depends(get_current_user)):
|
||||||
"""v3-Antrag-Detail (Bürger:innen-Modus, Beta): vereinfachte Vorschau.
|
"""Alias auf den Standard (= /antrag/{drs}), damit alte Bookmarks
|
||||||
|
auf v3-URLs weiter funktionieren."""
|
||||||
Sandbox fuer Issues #184 (CD-Konformitaet) und #185 (Bürgerinnen-
|
|
||||||
Perspektive). Initial identisch zu v2; iterative Vereinfachungen
|
|
||||||
folgen pro PR. v2-Endpoint bleibt unangetastet.
|
|
||||||
"""
|
|
||||||
return await _render_antrag_detail(
|
return await _render_antrag_detail(
|
||||||
request, drucksache, current_user, "v3/screens/antrag_detail.html"
|
request, drucksache, current_user, "v3/screens/antrag_detail.html"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -407,14 +407,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── 9. Rest-Block ─────────────────────────────────────────────────── */
|
/* ── 9. Rest-Block ─────────────────────────────────────────────────── */
|
||||||
|
/* Kein eigenes border-top mehr — die letzte v3-section (z.B.
|
||||||
|
Abstimmungsergebnis) liefert bereits die Trennlinie via border-bottom.
|
||||||
|
Vorher waren beide aktiv → Doppellinie. */
|
||||||
.v3-rest {
|
.v3-rest {
|
||||||
margin-top: 28px;
|
margin-top: 28px;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
border-top: 1px solid var(--hairline);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 22px;
|
gap: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Trennlinien zwischen ausgewählten Rest-Blöcken: vor Teilen und vor
|
||||||
|
Aktions-Links (Beginn des administrativen Bereichs). */
|
||||||
|
.v3-rest > .v3-rest-block.v3-rest-divider-top,
|
||||||
|
.v3-rest > .v3-rest-aktions.v3-rest-divider-top {
|
||||||
|
border-top: 1px solid var(--hairline);
|
||||||
|
padding-top: 22px;
|
||||||
|
}
|
||||||
.v3-rest-block {
|
.v3-rest-block {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -167,6 +167,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="stand-meta" style="font-family:var(--font-mono);font-size:11px;opacity:0.5;margin-top:1.5rem;"></div>
|
<div id="stand-meta" style="font-family:var(--font-mono);font-size:11px;opacity:0.5;margin-top:1.5rem;"></div>
|
||||||
|
|
||||||
|
{# Alternative Detail-Ansichten — nur im Admin sichtbar.
|
||||||
|
Default ist v3 (`/antrag/{drs}`), der frühere Profi-Modus läuft
|
||||||
|
unter /v2/antrag/. Hier ein Sample-Link, damit Admins ihn finden. #}
|
||||||
|
<h3 class="v2-h3" style="margin-top:32px;">Alternative Ansichten</h3>
|
||||||
|
<p style="font-family:var(--font-mono);font-size:12px;opacity:0.75;line-height:1.6;">
|
||||||
|
Standard-Detailansicht ist v3 (Bürger:innen-Modus, single column).
|
||||||
|
Die frühere v2-Profi-Ansicht (zwei Spalten, alle Felder gleichzeitig)
|
||||||
|
bleibt unter <code>/v2/antrag/<Drucksache></code> erreichbar.
|
||||||
|
</p>
|
||||||
|
<p id="alt-views-sample" style="font-family:var(--font-mono);font-size:12px;line-height:1.8;">
|
||||||
|
Lade aktuelles Beispiel …
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -281,6 +294,30 @@ async function loadStand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sample-Link für Alternative Ansichten: aktuellster Antrag */
|
||||||
|
(async function () {
|
||||||
|
var el = document.getElementById('alt-views-sample');
|
||||||
|
if (!el) return;
|
||||||
|
try {
|
||||||
|
var r = await fetch('/api/assessments?limit=1');
|
||||||
|
var data = await r.json();
|
||||||
|
var a = (data && data[0]) || (data.results && data.results[0]) || null;
|
||||||
|
if (!a || !a.drucksache) {
|
||||||
|
el.textContent = 'Kein Beispiel-Antrag verfügbar.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var drs = encodeURIComponent(a.drucksache);
|
||||||
|
var labelFor = function (s) { return s.length > 70 ? s.slice(0,68) + '…' : s; };
|
||||||
|
el.innerHTML =
|
||||||
|
'<strong>Beispiel:</strong> ' + (a.bundesland || '?') + ' · Drs. ' + a.drucksache +
|
||||||
|
' — „' + labelFor((a.title || '')) + '"<br>' +
|
||||||
|
'· <a href="/antrag/' + drs + '">Standard (v3, Bürger:innen-Modus)</a><br>' +
|
||||||
|
'· <a href="/v2/antrag/' + drs + '">v2 — Profi-Modus, zwei Spalten</a>';
|
||||||
|
} catch (e) {
|
||||||
|
el.textContent = 'Konnte Beispiel-Link nicht laden.';
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
loadStand();
|
loadStand();
|
||||||
let _standInterval = setInterval(loadStand, 30000);
|
let _standInterval = setInterval(loadStand, 30000);
|
||||||
// Pause-Polling wenn Tab versteckt (#183).
|
// Pause-Polling wenn Tab versteckt (#183).
|
||||||
|
|||||||
@ -640,20 +640,6 @@ document.addEventListener('keydown', function (e) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* v3-Toggle in der Topbar: nur bei vorhandenem Antrag, Link auf
|
|
||||||
/v3/antrag/<drs>. Injektion via JS, damit v2/base.html unangetastet bleibt. */
|
|
||||||
{% if antrag is defined and antrag and antrag.drucksache %}
|
|
||||||
(function () {
|
|
||||||
var bar = document.querySelector('.v2-topbar');
|
|
||||||
if (!bar) return;
|
|
||||||
var link = document.createElement('a');
|
|
||||||
link.href = '/v3/antrag/' + encodeURIComponent({{ antrag.drucksache | tojson }});
|
|
||||||
link.textContent = '→ Bürger:innen-Modus · v3 Beta';
|
|
||||||
link.title = 'Vereinfachte Vorschau für Erst-Leser:innen (v3 Beta).';
|
|
||||||
link.style.marginLeft = 'auto';
|
|
||||||
bar.appendChild(link);
|
|
||||||
})();
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{# Matrix-Erklärungen als JSON in den Browser übertragen #}
|
{# Matrix-Erklärungen als JSON in den Browser übertragen #}
|
||||||
|
|||||||
@ -366,7 +366,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Teilen #}
|
{# Teilen #}
|
||||||
<div class="v3-rest-block">
|
<div class="v3-rest-block v3-rest-divider-top">
|
||||||
<h3 class="v3-h3">Teilen</h3>
|
<h3 class="v3-h3">Teilen</h3>
|
||||||
<div class="v3-share-buttons">
|
<div class="v3-share-buttons">
|
||||||
<button onclick="v2DetailShareCopy()" class="v3-action-btn">📋 Kopieren</button>
|
<button onclick="v2DetailShareCopy()" class="v3-action-btn">📋 Kopieren</button>
|
||||||
@ -379,7 +379,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Aktions-Links: PDF, Original, JSON, Permalink — unter Teilen #}
|
{# Aktions-Links: PDF, Original, JSON, Permalink — unter Teilen #}
|
||||||
<div class="v3-rest-aktions">
|
<div class="v3-rest-aktions v3-rest-divider-top">
|
||||||
<a href="/api/assessment/pdf?drucksache={{ antrag.drucksache | urlencode }}">PDF-Bericht</a>
|
<a href="/api/assessment/pdf?drucksache={{ antrag.drucksache | urlencode }}">PDF-Bericht</a>
|
||||||
{% if antrag.link %}
|
{% if antrag.link %}
|
||||||
<a href="{{ antrag.link }}" target="_blank" rel="noopener">Original-Antrag (Landtag)</a>
|
<a href="{{ antrag.link }}" target="_blank" rel="noopener">Original-Antrag (Landtag)</a>
|
||||||
@ -470,23 +470,6 @@
|
|||||||
{% block body_scripts %}
|
{% block body_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script>
|
<script>
|
||||||
/* v3-Topbar-Pill + Toggle zurueck zu Profi-Modus */
|
|
||||||
(function () {
|
|
||||||
var bar = document.querySelector('.v2-topbar');
|
|
||||||
if (!bar) return;
|
|
||||||
var pill = document.createElement('span');
|
|
||||||
pill.className = 'v3-beta-badge';
|
|
||||||
pill.textContent = 'Bürger:innen-Modus · Beta';
|
|
||||||
pill.title = 'Vereinfachte Ansicht. v3 ist eine frühe Vorschau.';
|
|
||||||
var toggle = document.createElement('a');
|
|
||||||
toggle.className = 'v3-modus-toggle';
|
|
||||||
toggle.href = '/antrag/' + encodeURIComponent({{ antrag.drucksache | tojson if antrag is defined and antrag else '""' | safe }});
|
|
||||||
toggle.textContent = '→ Profi-Modus';
|
|
||||||
toggle.title = 'Volle GWÖ-Detailansicht (v2) öffnen';
|
|
||||||
bar.appendChild(pill);
|
|
||||||
bar.appendChild(toggle);
|
|
||||||
})();
|
|
||||||
|
|
||||||
/* Ähnliche Anträge: /api/assessment/similar?drucksache=…&top_k=5 */
|
/* Ähnliche Anträge: /api/assessment/similar?drucksache=…&top_k=5 */
|
||||||
(async function () {
|
(async function () {
|
||||||
var box = document.getElementById('v3-similar-box');
|
var box = document.getElementById('v3-similar-box');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user