Update documentation with new features and improved usability

Update several documentation files (.toml, .md) to reflect new features such as a QR code flyer page, share/PDF export buttons, and dependency updates, including version increments to v1.1.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 923ae0e3-a363-4db8-b04a-e8baca2a1330
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 88b9da52-be77-4c86-854b-f097a8c7ae86
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8af7d2ec-2cc3-4ece-8af3-9f071488d072/923ae0e3-a363-4db8-b04a-e8baca2a1330/Z3YUti7
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
pironantoine
2026-04-04 10:27:58 +00:00
parent 7e9eb3c360
commit f72a64f23e
5 changed files with 188 additions and 23 deletions
+4 -4
View File
@@ -11,22 +11,22 @@ title = "Guide d'auto-hébergement RockyLinux"
id = "QwHkF1SFkRpZFuyRMNI9h" id = "QwHkF1SFkRpZFuyRMNI9h"
uri = "file://docs/GITEA_TUTO.md" uri = "file://docs/GITEA_TUTO.md"
type = "text" type = "text"
title = "Tutoriel — Récupérer le projet sur Gitea" title = "Tutoriel Gitea — mis à jour"
[[outputs]] [[outputs]]
id = "wdBpdE1lSme8lM2xYd3oJ" id = "wdBpdE1lSme8lM2xYd3oJ"
uri = "file://docs/DAT.md" uri = "file://docs/DAT.md"
type = "text" type = "text"
title = "DAT — Document d'Architecture Technique" title = "DAT v1.1 — Architecture Technique"
[[outputs]] [[outputs]]
id = "NXFvDFOIzX862xNq15Mak" id = "NXFvDFOIzX862xNq15Mak"
uri = "file://docs/DEX.md" uri = "file://docs/DEX.md"
type = "text" type = "text"
title = "DEX — Document d'Exploitation" title = "DEX v1.1 — Exploitation"
[[outputs]] [[outputs]]
id = "kJNXgVnYp_LQmPcWr6Osb" id = "kJNXgVnYp_LQmPcWr6Osb"
uri = "file://docs/WIKI.md" uri = "file://docs/WIKI.md"
type = "text" type = "text"
title = "Wiki — La Voix du Peuple" title = "Wiki v1.1 — La Voix du Peuple"
+54 -5
View File
@@ -1,11 +1,20 @@
# Document d'Architecture Technique — La Voix du Peuple # Document d'Architecture Technique — La Voix du Peuple
**Version** : 1.0 **Version** : 1.1
**Date** : Avril 2026 **Date** : Avril 2026
**Statut** : En production (Replit), prêt pour auto-hébergement **Statut** : En production (Replit), prêt pour auto-hébergement
--- ---
## Historique des versions
| Version | Date | Modifications |
|---------|------|---------------|
| 1.0 | Avril 2026 | Version initiale |
| 1.1 | Avril 2026 | Ajout page Flyer QR, boutons Partager / PDF, `qrcode.react` |
---
## 1. Présentation générale ## 1. Présentation générale
**La Voix du Peuple** est une plateforme civique permettant à des citoyens de soumettre des propositions politiques. Ces contributions sont : **La Voix du Peuple** est une plateforme civique permettant à des citoyens de soumettre des propositions politiques. Ces contributions sont :
@@ -13,6 +22,7 @@
1. Filtrées par un agent IA selon le droit international des droits humains 1. Filtrées par un agent IA selon le droit international des droits humains
2. Synthétisées automatiquement en un résumé clair par thème 2. Synthétisées automatiquement en un résumé clair par thème
3. Affichées en temps réel à destination d'élus ou de décideurs 3. Affichées en temps réel à destination d'élus ou de décideurs
4. Exportables (PDF, partage natif) et diffusables via un flyer imprimable avec QR code
--- ---
@@ -63,14 +73,31 @@
| Routing | Wouter | | Routing | Wouter |
| État serveur | TanStack Query | | État serveur | TanStack Query |
| Client API | `@workspace/api-client-react` (généré depuis OpenAPI) | | Client API | `@workspace/api-client-react` (généré depuis OpenAPI) |
| QR code | `qrcode.react` (page Flyer) |
| Police | Bahnschrift (titres), Inter (corps) | | Police | Bahnschrift (titres), Inter (corps) |
**Pages** : **Pages** :
- `/` — Page principale (formulaire + fil + synthèse)
- `/about` — À propos et fondements juridiques
- `/transparence` — Fonctionnement technique et données collectées
**Variables d'environnement** : | URL | Description |
|-----|-------------|
| `/` | Page principale : formulaire de soumission, fil des contributions, colonne de synthèse |
| `/about` | À propos et fondements juridiques |
| `/transparence` | Fonctionnement de l'IA, données collectées, limites |
| `/flyer` | Flyer imprimable avec QR code configurable pour diffusion physique |
**Fonctionnalités de la colonne de synthèse** :
- Bouton **Partager / Copier** : compose un texte horodaté (texte + nombre de contributions + date) et l'envoie via l'API Web Share (mobile) ou le presse-papier (bureau) ; un toast confirme la copie
- Bouton **PDF** : ouvre une fenêtre dédiée avec un rendu mise en page (tricolore, titre, métadonnées, texte, pied de page `lavoixdupeuple.fr`) et déclenche l'impression navigateur
**Page Flyer (`/flyer`)** :
- QR code SVG haute résolution (niveau de correction H) pointant vers l'URL de destination
- URL modifiable en temps réel via un champ texte, sans rechargement
- URL par défaut définie par la constante `DEFAULT_QR_URL` en ligne 10 de `src/pages/flyer.tsx`
- Passage d'une URL via paramètre GET : `/flyer?url=https://monsite.fr`
- Barre de contrôle masquée à l'impression (`@media print`) — seul le flyer A4 est imprimé
- Bouton "Imprimer / Exporter PDF" sur la page
**Variables d'environnement frontend** :
- `BASE_URL` — Préfixe de chemin (injecté par Vite) - `BASE_URL` — Préfixe de chemin (injecté par Vite)
- `PORT` — Port du serveur de développement (assigné par Replit) - `PORT` — Port du serveur de développement (assigné par Replit)
@@ -194,6 +221,7 @@ Internet ──▶ HAProxy (TLS, load balancing)
| SQL injection | Requêtes paramétrées (psycopg2) | | SQL injection | Requêtes paramétrées (psycopg2) |
| Secrets | Variables d'environnement uniquement, jamais dans le code | | Secrets | Variables d'environnement uniquement, jamais dans le code |
| Données personnelles | Aucune IP stockée, pseudonyme facultatif | | Données personnelles | Aucune IP stockée, pseudonyme facultatif |
| Export PDF | Généré côté client uniquement, aucune donnée transmise au serveur |
--- ---
@@ -215,3 +243,24 @@ POST /api/ideas
└─ Réponse JSON 201 └─ Réponse JSON 201
``` ```
## 8. Flux d'export / partage (côté client)
```
Clic "Partager / Copier"
├─ Composition du texte horodaté (date locale, nb contributions, texte synthèse)
├─ navigator.share disponible ? → Partage natif (mobile)
└─ Sinon → navigator.clipboard.writeText → toast de confirmation
Clic "PDF"
├─ Génération HTML en mémoire (tricolore, titre, méta, texte, pied de page)
├─ window.open("", "_blank") → document.write(html)
└─ window.print() → dialogue d'impression / export PDF navigateur
Page /flyer — Clic "Imprimer / Exporter PDF"
├─ CSS @media print masque .no-print (barre de contrôle, navbar)
└─ window.print() → impression du flyer A4 seul
```
+62 -5
View File
@@ -1,10 +1,19 @@
# Document d'Exploitation — La Voix du Peuple # Document d'Exploitation — La Voix du Peuple
**Version** : 1.0 **Version** : 1.1
**Date** : Avril 2026 **Date** : Avril 2026
--- ---
## Historique des versions
| Version | Date | Modifications |
|---------|------|---------------|
| 1.0 | Avril 2026 | Version initiale |
| 1.1 | Avril 2026 | Ajout section flyer QR, export PDF, partage horodaté |
---
## 1. Démarrage et arrêt des services ## 1. Démarrage et arrêt des services
### Sur Replit ### Sur Replit
@@ -83,8 +92,10 @@ git pull gitea main
# Mettre à jour les dépendances Python si requirements.txt a changé # Mettre à jour les dépendances Python si requirements.txt a changé
pip install -r artifacts/flask-api/requirements.txt pip install -r artifacts/flask-api/requirements.txt
# Reconstruire le frontend si le code frontend a changé # Mettre à jour les dépendances Node si package.json a changé
pnpm install pnpm install
# Reconstruire le frontend si le code frontend a changé
pnpm --filter @workspace/voix-du-peuple run build --config vite.config.selfhost.ts pnpm --filter @workspace/voix-du-peuple run build --config vite.config.selfhost.ts
# Redémarrer l'API # Redémarrer l'API
@@ -204,7 +215,49 @@ Modèles Mistral disponibles (avril 2026) :
--- ---
## 8. Purge des données ## 8. Gestion du flyer QR code
La page `/flyer` génère un flyer A4 imprimable avec un QR code.
### Changer l'URL de destination
**Méthode 1 — Interface (sans code)** : ouvrir `/flyer`, modifier le champ "Destination du QR code", cliquer "Appliquer", puis imprimer.
**Méthode 2 — Paramètre URL** : ajouter `?url=` à l'adresse de la page, ex. :
```
https://lavoixdupeuple.fr/flyer?url=https://autresite.fr
```
**Méthode 3 — Modification permanente dans le code** : éditer la ligne 10 de `artifacts/voix-du-peuple/src/pages/flyer.tsx` :
```ts
const DEFAULT_QR_URL = "https://lavoixdupeuple.fr";
```
Reconstruire ensuite le frontend (`pnpm build`).
### Imprimer / exporter en PDF
Sur la page `/flyer`, cliquer **Imprimer / Exporter PDF**. La barre de configuration disparaît automatiquement à l'impression, seul le flyer A4 est produit. Pour obtenir un PDF, choisir "Enregistrer en PDF" dans la boîte de dialogue du navigateur.
---
## 9. Export de la synthèse
Deux boutons sont disponibles dans l'en-tête de la colonne de synthèse (page principale) :
### Partager / Copier
- Sur mobile (navigateurs supportant Web Share) : ouvre le menu de partage natif du système
- Sur bureau : copie le texte dans le presse-papier avec horodatage et compteur de contributions ; un message de confirmation apparaît
### PDF
Génère et ouvre une page HTML mise en page (tricolore, titre, date, texte de synthèse, pied de page) puis déclenche l'impression. Choisir "Enregistrer en PDF" dans la boîte de dialogue pour obtenir un fichier.
> Ces deux fonctions s'exécutent entièrement côté client — aucune donnée n'est envoyée au serveur.
---
## 10. Purge des données
```sql ```sql
-- Supprimer toutes les contributions (irréversible) -- Supprimer toutes les contributions (irréversible)
@@ -222,7 +275,7 @@ Après une purge, la synthèse se régénère automatiquement à la prochaine co
--- ---
## 9. Dépannage courant ## 11. Dépannage courant
| Symptôme | Cause probable | Solution | | Symptôme | Cause probable | Solution |
|----------|---------------|----------| |----------|---------------|----------|
@@ -232,13 +285,17 @@ Après une purge, la synthèse se régénère automatiquement à la prochaine co
| Frontend vide (page blanche) | Build manquant ou `BASE_URL` incorrect | Relancer le build Vite, vérifier la config Nginx | | Frontend vide (page blanche) | Build manquant ou `BASE_URL` incorrect | Relancer le build Vite, vérifier la config Nginx |
| Rate limit atteint (429) | Trop de soumissions depuis la même IP | Normal — attendre 1 minute | | Rate limit atteint (429) | Trop de soumissions depuis la même IP | Normal — attendre 1 minute |
| Modèle IA introuvable (404) | Nom de modèle incorrect dans `FILTER_MODEL` | Corriger le nom, redémarrer le service | | Modèle IA introuvable (404) | Nom de modèle incorrect dans `FILTER_MODEL` | Corriger le nom, redémarrer le service |
| QR code ne redirige pas | URL incorrecte dans le champ ou la constante | Vérifier `DEFAULT_QR_URL` dans `flyer.tsx`, ou passer `?url=` en paramètre |
| Bouton "Copier" sans retour visuel | Navigateur sans accès au presse-papier (HTTP non sécurisé) | Servir le site en HTTPS |
| Fenêtre PDF bloquée | Bloqueur de popups actif | Autoriser les popups pour ce site dans le navigateur |
--- ---
## 10. Contacts et ressources ## 12. Contacts et ressources
- Documentation Mistral : https://docs.mistral.ai - Documentation Mistral : https://docs.mistral.ai
- PostgreSQL : https://www.postgresql.org/docs/ - PostgreSQL : https://www.postgresql.org/docs/
- Flask : https://flask.palletsprojects.com - Flask : https://flask.palletsprojects.com
- qrcode.react : https://github.com/zpao/qrcode.react
- Guide de déploiement complet : `DEPLOIEMENT.md` - Guide de déploiement complet : `DEPLOIEMENT.md`
- Architecture : `docs/DAT.md` - Architecture : `docs/DAT.md`
+42 -5
View File
@@ -2,6 +2,8 @@
Ce tutoriel explique comment pousser le code de **La Voix du Peuple** depuis Replit vers votre instance Gitea, et comment vous synchroniser ensuite à votre rythme. Ce tutoriel explique comment pousser le code de **La Voix du Peuple** depuis Replit vers votre instance Gitea, et comment vous synchroniser ensuite à votre rythme.
> **État du dépôt** : branche `main`, 10 commits. Remote actif : `gitsafe-backup`.
--- ---
## Prérequis ## Prérequis
@@ -117,7 +119,14 @@ cd voix-du-peuple
cp .env.example .env cp .env.example .env
nano .env # Renseignez DATABASE_URL, MISTRAL_API_KEY, SESSION_SECRET nano .env # Renseignez DATABASE_URL, MISTRAL_API_KEY, SESSION_SECRET
# Suivre ensuite le guide DEPLOIEMENT.md # Installer les dépendances Python
pip install -r artifacts/flask-api/requirements.txt
# Installer les dépendances Node
pnpm install
# Construire le frontend
pnpm --filter @workspace/voix-du-peuple run build --config vite.config.selfhost.ts
``` ```
--- ---
@@ -145,12 +154,40 @@ git remote -v
| Branche | Usage | | Branche | Usage |
|---------|-------| |---------|-------|
| `main` | Code de production, stable | | `main` | Code de production, stable**seule branche à pousser vers Gitea** |
| `replit-agent` | Branche de travail de l'agent Replit (interne) | | `replit-agent` | Branche de travail interne de l'agent Replit — ne pas pousser |
> Il est conseillé de ne travailler que sur `main` et de ne jamais pousser `replit-agent` vers votre Gitea.
```bash ```bash
# Pousser uniquement main # Pousser uniquement main
git push gitea main git push gitea main
``` ```
---
## Contenu du dépôt (structure principale)
```
artifacts/
flask-api/ ← Backend Python Flask
app.py ← Routes API
ai_agent.py ← Intégration Mistral / OpenAI
database.py ← Accès PostgreSQL
requirements.txt ← Dépendances Python
voix-du-peuple/ ← Frontend React + Vite
src/
pages/
home.tsx ← Page principale (synthèse, partage, PDF)
about.tsx ← À propos
transparence.tsx ← Fonctionnement & données
flyer.tsx ← Flyer QR code imprimable
App.tsx ← Routing et navbar
index.css ← Styles globaux + @media print
deploy/
nginx.conf ← Config Nginx production
voix-du-peuple-api.service ← Unité systemd Gunicorn
docs/
DAT.md ← Architecture technique
DEX.md ← Exploitation
WIKI.md ← Page wiki
GITEA_TUTO.md ← Ce fichier
```
+26 -4
View File
@@ -4,7 +4,8 @@
**Stack** : Python / Flask · React / Vite · PostgreSQL · Mistral AI **Stack** : Python / Flask · React / Vite · PostgreSQL · Mistral AI
**Hébergement** : Replit (dev) / Auto-hébergeable (RockyLinux, Debian) **Hébergement** : Replit (dev) / Auto-hébergeable (RockyLinux, Debian)
**Dépôt** : `voix-du-peuple` (Gitea) **Dépôt** : `voix-du-peuple` (Gitea)
**Statut** : Actif — avril 2026 **Statut** : Actif — avril 2026
**Version doc** : 1.1
--- ---
@@ -15,18 +16,20 @@ Un outil permettant à des citoyens de soumettre des propositions politiques en
- **filtrées** automatiquement par une IA selon les textes internationaux des droits humains (DUDH, PIDCP, CEDH…) - **filtrées** automatiquement par une IA selon les textes internationaux des droits humains (DUDH, PIDCP, CEDH…)
- **synthétisées** en un résumé structuré par thèmes, destiné à des élus ou décideurs - **synthétisées** en un résumé structuré par thèmes, destiné à des élus ou décideurs
- **affichées** en temps réel sur la page principale - **affichées** en temps réel sur la page principale
- **exportables** : copie horodatée dans le presse-papier, PDF mise en page, ou flyer A4 avec QR code pour diffusion physique
L'objectif est de fournir aux représentants politiques un document clair et utilisable issu des préoccupations citoyennes, sans intermédiaire. L'objectif est de fournir aux représentants politiques un document clair et utilisable issu des préoccupations citoyennes, sans intermédiaire.
--- ---
## Fonctionnement en 5 points ## Fonctionnement en 6 points
1. Un citoyen saisit une proposition sur la page principale 1. Un citoyen saisit une proposition sur la page principale
2. L'IA (Mistral Small) vérifie que le contenu respecte les droits fondamentaux 2. L'IA (Mistral Small) vérifie que le contenu respecte les droits fondamentaux
3. Si la contribution est acceptée, elle s'ajoute à la base et déclenche une re-synthèse 3. Si la contribution est acceptée, elle s'ajoute à la base et déclenche une re-synthèse
4. L'IA (Mistral Large) relit toutes les contributions et produit un résumé thématique 4. L'IA (Mistral Large) relit toutes les contributions et produit un résumé thématique
5. Le résumé s'affiche en temps réel à droite de l'écran 5. Le résumé s'affiche en temps réel à droite de l'écran
6. Le résumé peut être partagé (texte horodaté), exporté en PDF, ou diffusé via un flyer QR imprimable
--- ---
@@ -34,9 +37,26 @@ L'objectif est de fournir aux représentants politiques un document clair et uti
| URL | Contenu | | URL | Contenu |
|-----|---------| |-----|---------|
| `/` | Formulaire de soumission + contributions récentes + synthèse | | `/` | Formulaire de soumission + contributions récentes + synthèse (avec boutons Partager / PDF) |
| `/about` | Description du projet et fondements juridiques | | `/about` | Description du projet et fondements juridiques |
| `/transparence` | Fonctionnement de l'IA, données collectées, limites | | `/transparence` | Fonctionnement de l'IA, données collectées, limites |
| `/flyer` | Flyer A4 imprimable avec QR code configurable pour diffusion physique |
---
## Fonctionnalités d'export et de diffusion
### Partager la synthèse
Bouton dans l'en-tête de la colonne de synthèse. Sur mobile : partage natif (WhatsApp, mail…). Sur bureau : copie dans le presse-papier avec date et heure.
### Exporter en PDF
Bouton "PDF" dans la même zone. Ouvre une fenêtre avec le résumé mis en page (tricolore, titre, date, texte, pied de page) pour impression ou export PDF depuis le navigateur.
### Flyer QR imprimable
Page `/flyer` : flyer format A4 avec grand QR code. L'URL encodée est modifiable :
- Via le champ texte en haut de la page (sans recharger)
- Via le paramètre URL `/flyer?url=https://monsite.fr`
- En modifiant la constante `DEFAULT_QR_URL` dans `src/pages/flyer.tsx`
--- ---
@@ -50,6 +70,7 @@ L'objectif est de fournir aux représentants politiques un document clair et uti
| IA | Mistral AI (API OpenAI-compatible) | | IA | Mistral AI (API OpenAI-compatible) |
| Modération | `mistral-small-latest` | | Modération | `mistral-small-latest` |
| Synthèse | `mistral-large-latest` | | Synthèse | `mistral-large-latest` |
| QR code | `qrcode.react` |
| Police | Bahnschrift (titres), Inter (corps) | | Police | Bahnschrift (titres), Inter (corps) |
--- ---
@@ -75,6 +96,8 @@ SYNTHESIS_MODEL — Modèle de synthèse (optionnel)
**Non collecté** : adresse IP, compte utilisateur, cookies de suivi. **Non collecté** : adresse IP, compte utilisateur, cookies de suivi.
**Export / partage** : entièrement côté client, rien n'est envoyé au serveur lors d'un partage ou d'un export PDF.
--- ---
## Liens ## Liens
@@ -82,5 +105,4 @@ SYNTHESIS_MODEL — Modèle de synthèse (optionnel)
- Tutoriel Gitea → [`docs/GITEA_TUTO.md`](./GITEA_TUTO.md) - Tutoriel Gitea → [`docs/GITEA_TUTO.md`](./GITEA_TUTO.md)
- Architecture technique → [`docs/DAT.md`](./DAT.md) - Architecture technique → [`docs/DAT.md`](./DAT.md)
- Exploitation → [`docs/DEX.md`](./DEX.md) - Exploitation → [`docs/DEX.md`](./DEX.md)
- Guide déploiement → [`DEPLOIEMENT.md`](../DEPLOIEMENT.md)
- Fonctionnement technique (in-app) → `/transparence` - Fonctionnement technique (in-app) → `/transparence`