Static webapp (HTML/JS/CSS pur, pas de bundler) déployée sur GitHub Pages. Affiche les projets européens (FP7, H2020, Horizon Europe) où INRAE Transfert SAS participe. Les données sont générées par un script Python à partir des exports CORDIS officiels.
~/codium/cordis-it/
├── index.html ← shell HTML (tabs, filtres, modale) — modifier avec précaution
├── css/style.css ← tous les styles
├── js/
│ ├── data.js ← constantes, helpers, state global (VISIBLE_PROJECTS, FILTERED, FILTERS, VIEW_MODE…)
│ ├── sidebar.js ← filtres latéraux (buildSidebar)
│ ├── cards.js ← onglet Projects (renderCards)
│ ├── partners.js ← onglet Partners (renderPartners)
│ ├── geography.js ← onglet Geography (choroplèthe, régions, chart temporel)
│ ├── disciplines.js ← onglet Disciplines (accordéon EuroSciVoc, sélection multi)
│ ├── budget.js ← onglet Budget (stats + charts)
│ ├── timeline.js ← onglet Timeline (Gantt + concurrent)
│ ├── modal.js ← modale détail projet
│ └── app.js ← bootstrap, apply(), renderAll(), bindEvents()
├── data/
│ ├── inrae_projects.json ← données générées par prepare_data.py (ne pas éditer à la main)
│ ├── geo-paths.json ← chemins SVG pour la carte choroplèthe
│ └── cache/ ← ZIP CORDIS en cache local (dans .gitignore)
├── scripts/
│ └── prepare_data.py ← pipeline d'ingestion CORDIS (FP7 + H2020 + Horizon Europe)
├── .env ← token GitHub (dans .gitignore, ne jamais commiter)
├── deploy.sh ← copie index.html si nécessaire
└── CLAUDE.md ← ce fichier
- Données : JSON statique (
data/inrae_projects.json), chargé viafetch()au démarrage - Charts : Chart.js 4.4.1 (CDN)
- Fonts : Spectral, Fira Code, Lato (Google Fonts)
- Carte : SVG choroplèthe avec chemins dans
geo-paths.json - Taxonomie : EuroSciVoc (arbre accordéon L1–L5 dans l'onglet Disciplines)
- Déploiement :
git push→ GitHub Pages automatique (branchemain)
- Langue : français dans la conversation, anglais pour tous les labels UI
- Couleur principale IT :
--it: #1a4f8a - Monospace : Fira Code (badges, métadonnées, codes)
- Badges programmes :
.tg-fp7(violet),.tg-h2020(bleu),.tg-he(vert) - Modifications chirurgicales uniquement — jamais réécrire un fichier entier si un str_replace suffit
- Branche unique : toujours sur
main, ne jamais créer d'autre branche - Montrer le diff avant toute modification de fichier, attendre confirmation
- Ne jamais commiter sans demander confirmation explicite avec le message proposé
- Ne jamais pusher sans demander confirmation explicite
source .env
git remote set-url origin https://${GITHUB_TOKEN}@github.com/avermue/cordis-it.git
git push origin main
git remote set-url origin https://github.com/avermue/cordis-it.gitDemander confirmation et exécuter le script si les modifications touchent à :
scripts/prepare_data.pylui-même- La structure des données attendues par le JS (nouveaux champs, nouveaux programmes)
- Un bug de données constaté dans l'interface
Ne pas relancer si :
- Modification purement CSS/visuelle
- Modification d'un rendu JS sans impact sur les données
- Correction d'un bug d'affichage
Procédure — toujours demander confirmation avant d'exécuter :
"La modification touche aux données. Je dois relancer prepare_data.py. Je propose :
python3 scripts/prepare_data.py --no-download(~1 min, utilise le cache). On retélécharge tout (sans--no-download) seulement si les ZIP sont obsolètes. J'exécute ?"
Puis attendre "oui" avant de lancer :
cd ~/codium/cordis-it
python3 scripts/prepare_data.py --no-download # utilise les ZIP en cache (rapide, ~1 min)
python3 scripts/prepare_data.py # retélécharge tout (lent, ~10 min)Après exécution, afficher le bloc SUMMARY pour validation des comptages.
Après toute modification de fichier, proposer systématiquement de lancer le serveur :
"Veux-tu que je lance le serveur local pour tester ?"
Si oui, exécuter :
cd ~/codium/cordis-it
python3 -m http.server 8080Puis indiquer : → ouvrir http://localhost:8080 en navigation privée
1. Modifier le(s) fichier(s) → montrer le diff → attendre OK
2. Si données impactées → proposer de relancer prepare_data.py → attendre OK → exécuter → afficher SUMMARY
3. Proposer de lancer le serveur local → attendre OK → exécuter
4. Attendre confirmation "ça marche en local"
5. Proposer le commit avec message → attendre confirmation
6. Proposer le push → attendre confirmation → exécuter avec procédure .env
ALL= tous les projets bruts chargés depuis le JSON (hasIT || hasINRAE, ~826 projets)VIEW_MODE='IT' | 'INRAE' | 'BOTH'— choix utilisateur, persisté danslocalStorage(clécordis-it.viewMode)VISIBLE_PROJECTS= sous-ensemble deALLselonVIEW_MODE(recalculé viaapplyViewMode())FILTERED= sous-ensemble deVISIBLE_PROJECTSaprès application des filtres utilisateur- Les stats des onglets Geography et Disciplines utilisent
VISIBLE_PROJECTS(pasFILTERED) schemeGroupest calculé côté JS à partir defundingSchemeShort(pasfundingScheme)SCHEME_GROUPSest conçu pour ne jamais laisser de projet enOther. Le fallback'Other': () => truereste comme garde-fou silencieux mais doit rester vide en pratique. Si un nouveau schema apparaît dans le ZIP CORDIS et tombe dansOther, étendre les règles plutôt que d'accepter la catégorie.- Statut : seules deux valeurs possibles dans le JSON final →
SIGNED(Ongoing) etCLOSED.TERMINATEDest normalisé enCLOSEDcôté pipeline (post-overrides) — c'est juste un libellé alternatif CORDIS pour les projets achevés. - Statut live vs ZIP : le dump ZIP CORDIS est très en retard sur le site web.
prepare_data.pyvérifie sur cordis.europa.eu chaque projetSIGNED && endDate < today(IT et INRAE depuis 2026-05-06) et stocke les corrections dansdata/status_overrides.json. - FP7 : tous les projets ont le statut
CLOSED, période 2008–2014 - EuroSciVoc : absent pour FP6 et antérieur, présent pour FP7/H2020/HE
- Ne jamais utiliser
FILTEREDpour calculer les comptages de l'onglet Disciplines → utiliserVISIBLE_PROJECTS+_domDescendants - À chaque changement de
VIEW_MODE, invaliderwindow._domDescendantsetwindow._domToIds(déjà fait dansapplyViewMode()) topicToCat(): toujours matcher sur les parties exactes du code topic (split sur-) pour éviter les faux positifsschemeGroup()doit recevoirfundingSchemeShortet nonfundingSchemebrut (les codes FP7 commeCP-TPne matchent pas sinon). Pour les schemas HORIZON (préfixe stripé), travailler sur la valeur stripée (ex.AGet nonHORIZON-AG).- Si on étend
_fp7_mapdansprepare_data.py, étendre aussiSCHEME_GROUPScôté JS (filet de sécurité pour les ZIP non encore régénérés). Et inversement. buildSidebar()reconstruit les checkboxes — appelersyncSidebarCheckboxes()en fin pour re-cocher les filtres actifs (sinon lesFILTERSrestent en mémoire mais visuellement décochés après changement deVIEW_MODE).- Toujours vérifier la balance accolades/crochets après toute modification JS (parser string-aware si doute)