Improve synthesis display, PDF exports, and priority documentation
- home.tsx: add SynthesisText component — detects "Sur X : / Concernant X :" thematic prefixes and renders them in serif/teal, replaces raw whitespace-pre-line - home.tsx: redesign client-side PDF — site color palette (#F9F7F1, #1b5f6a), Georgia serif typography, thematic prefix highlighting, tricolor stripe - app.py: redesign consultation print export — same visual identity, server-side paragraph parsing with theme span injection before HTML-escaping - transparence.tsx: rewrite priority explanation to be explicit about what "critique/haute/moyenne" means in practice (injection vs monitoring, why) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+45
-23
@@ -907,41 +907,63 @@ def export_consultation_print(slug: str):
|
||||
title_esc = html_module.escape(consultation["title"])
|
||||
subject_esc = html_module.escape(consultation["subject"])
|
||||
organizer_esc = html_module.escape(consultation.get("organizer_name") or "")
|
||||
synthesis_esc = html_module.escape(synthesis_text).replace("\n", "<br>")
|
||||
now_str = dt.datetime.now(dt.timezone.utc).strftime("%d/%m/%Y %H:%M")
|
||||
|
||||
# Mise en forme du texte : "Sur X :" / "Concernant X :" en gras teal
|
||||
import re as _re
|
||||
_THEME_RE = _re.compile(
|
||||
r'^((?:Sur|Concernant|À propos d[eu]?|En ce qui concerne|Quant à)[^:]{0,100}:\s?)([\s\S]*)$',
|
||||
_re.IGNORECASE,
|
||||
)
|
||||
paragraphs = [p.strip() for p in synthesis_text.split("\n\n") if p.strip()]
|
||||
body_html = ""
|
||||
for para in paragraphs:
|
||||
m = _THEME_RE.match(para)
|
||||
if m:
|
||||
prefix = html_module.escape(m.group(1))
|
||||
rest = html_module.escape(m.group(2))
|
||||
body_html += f'<p><span class="theme">{prefix}</span>{rest}</p>\n'
|
||||
else:
|
||||
body_html += f'<p>{html_module.escape(para)}</p>\n'
|
||||
|
||||
html_content = f"""<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{title_esc}</title>
|
||||
<style>
|
||||
body {{ font-family: Georgia, serif; max-width: 800px; margin: 40px auto; padding: 0 20px; color: #1a1a1a; }}
|
||||
.header {{ border-bottom: 3px solid #1b5f6a; padding-bottom: 16px; margin-bottom: 32px; }}
|
||||
.tricolore {{ display: flex; height: 6px; width: 60px; margin-bottom: 12px; }}
|
||||
.tricolore span {{ flex: 1; }}
|
||||
h1 {{ font-size: 24px; margin: 0 0 6px; color: #1b5f6a; }}
|
||||
.meta {{ font-size: 13px; color: #666; margin: 4px 0; }}
|
||||
.synthesis {{ font-size: 15px; line-height: 1.8; }}
|
||||
.footer {{ margin-top: 40px; border-top: 1px solid #ccc; padding-top: 12px; font-size: 11px; color: #999; }}
|
||||
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
||||
body {{ font-family: Georgia, 'Times New Roman', serif; background: #F9F7F1; color: #1a1a1a; }}
|
||||
.page {{ max-width: 700px; margin: 0 auto; background: #fff; min-height: 100vh; padding: 52px 56px; }}
|
||||
.tricolor {{ display: flex; height: 3px; margin-bottom: 40px; }}
|
||||
.tricolor span:nth-child(1) {{ flex: 1; background: #002395; }}
|
||||
.tricolor span:nth-child(2) {{ flex: 1; background: #E5E5E5; }}
|
||||
.tricolor span:nth-child(3) {{ flex: 1; background: #ED2939; }}
|
||||
.label {{ font-family: 'Courier New', monospace; font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.14em; color: #1b5f6a; margin-bottom: 10px; }}
|
||||
h1 {{ font-size: 1.5rem; font-weight: 700; color: #111; line-height: 1.25; margin-bottom: 4px; }}
|
||||
.organizer {{ font-size: 0.85rem; font-weight: 600; color: #1b5f6a; margin-top: 6px; }}
|
||||
.subject {{ font-size: 0.85rem; color: #555; margin-top: 4px; font-style: italic; }}
|
||||
.meta {{ font-family: 'Courier New', monospace; font-size: 0.68rem; color: #999; margin-top: 16px; padding-top: 16px; border-top: 1px solid #E8E4DC; margin-bottom: 36px; }}
|
||||
.body {{ font-size: 0.95rem; line-height: 1.85; color: #1a1a1a; }}
|
||||
.body p {{ margin-bottom: 1.1em; }}
|
||||
.theme {{ font-family: Georgia, serif; font-weight: 600; color: #1b5f6a; }}
|
||||
.footer {{ margin-top: 52px; padding-top: 14px; border-top: 1px solid #E8E4DC; font-family: 'Courier New', monospace; font-size: 0.6rem; color: #bbb; display: flex; justify-content: space-between; gap: 16px; }}
|
||||
@media print {{ body {{ background: white; }} .page {{ box-shadow: none; padding: 32px 40px; }} }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="tricolore">
|
||||
<span style="background:#002395"></span>
|
||||
<span style="background:#ededed"></span>
|
||||
<span style="background:#ed2939"></span>
|
||||
</div>
|
||||
<div class="page">
|
||||
<div class="tricolor"><span></span><span></span><span></span></div>
|
||||
<p class="label">La Voix du Peuple · Consultation citoyenne</p>
|
||||
<h1>{title_esc}</h1>
|
||||
{f'<p class="meta"><strong>{organizer_esc}</strong></p>' if organizer_esc else ""}
|
||||
<p class="meta">{subject_esc}</p>
|
||||
<p class="meta">Exporté le {now_str} — {idea_count} contribution(s) intégrée(s)</p>
|
||||
</div>
|
||||
<div class="synthesis">{synthesis_esc}</div>
|
||||
<div class="footer">
|
||||
La Voix du Peuple — Document généré automatiquement à partir de contributions citoyennes.
|
||||
Ce contenu reflète l'expression des participants, pas une vérité établie.
|
||||
{f'<p class="organizer">{organizer_esc}</p>' if organizer_esc else ""}
|
||||
<p class="subject">{subject_esc}</p>
|
||||
<div class="meta">Exporté le {now_str} · {idea_count} contribution(s) intégrée(s)</div>
|
||||
<div class="body">{body_html}</div>
|
||||
<div class="footer">
|
||||
<span>lavoixdupeuple.fr</span>
|
||||
<span>Modération DUDH · PIDCP · CEDH · droit pénal français</span>
|
||||
</div>
|
||||
</div>
|
||||
<script>window.print();</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user