Compare commits
No commits in common. "44c6f1917bab2c1fed6d1b5f5b5f5e1b775bc98d" and "e48c94760d2c9fcfff5cceba02903c96cb951834" have entirely different histories.
44c6f1917b
...
e48c94760d
33
nupes-elections-front/package-lock.json
generated
33
nupes-elections-front/package-lock.json
generated
@ -17,10 +17,8 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"highcharts": "^11.4.3",
|
"highcharts": "^11.4.3",
|
||||||
"highcharts-react-official": "^3.2.1",
|
"highcharts-react-official": "^3.2.1",
|
||||||
"leaflet": "^1.9.4",
|
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-leaflet": "^4.2.1",
|
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
@ -4055,17 +4053,6 @@
|
|||||||
"url": "https://opencollective.com/popperjs"
|
"url": "https://opencollective.com/popperjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-leaflet/core": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==",
|
|
||||||
"license": "Hippocratic-2.1",
|
|
||||||
"peerDependencies": {
|
|
||||||
"leaflet": "^1.9.0",
|
|
||||||
"react": "^18.0.0",
|
|
||||||
"react-dom": "^18.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.16.1",
|
"version": "1.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
|
||||||
@ -13926,12 +13913,6 @@
|
|||||||
"shell-quote": "^1.8.1"
|
"shell-quote": "^1.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/leaflet": {
|
|
||||||
"version": "1.9.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
|
||||||
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
|
|
||||||
"license": "BSD-2-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
@ -16817,20 +16798,6 @@
|
|||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-leaflet": {
|
|
||||||
"version": "4.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz",
|
|
||||||
"integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==",
|
|
||||||
"license": "Hippocratic-2.1",
|
|
||||||
"dependencies": {
|
|
||||||
"@react-leaflet/core": "^2.1.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"leaflet": "^1.9.0",
|
|
||||||
"react": "^18.0.0",
|
|
||||||
"react-dom": "^18.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||||
|
@ -12,10 +12,8 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"highcharts": "^11.4.3",
|
"highcharts": "^11.4.3",
|
||||||
"highcharts-react-official": "^3.2.1",
|
"highcharts-react-official": "^3.2.1",
|
||||||
"leaflet": "^1.9.4",
|
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-leaflet": "^4.2.1",
|
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
|
@ -13,9 +13,6 @@ import * as Highcharts from 'highcharts'
|
|||||||
import highchartsItem from 'highcharts/modules/item-series'
|
import highchartsItem from 'highcharts/modules/item-series'
|
||||||
import HighchartsReact from 'highcharts-react-official'
|
import HighchartsReact from 'highcharts-react-official'
|
||||||
import {useEffect, useState} from "react"
|
import {useEffect, useState} from "react"
|
||||||
import {GeoJSON, MapContainer, Popup, TileLayer, useMap} from "react-leaflet"
|
|
||||||
|
|
||||||
import 'leaflet/dist/leaflet.css'
|
|
||||||
|
|
||||||
highchartsItem(Highcharts)
|
highchartsItem(Highcharts)
|
||||||
|
|
||||||
@ -42,7 +39,18 @@ function ResultatsTable({blocs, nuances, listes, resultats, siegesParListe}) {
|
|||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{listes_triees.map((liste) => (
|
{listes_triees.map((liste) => (
|
||||||
<ListeRow key={liste.numero} liste={liste} voix={voix_listes[liste.numero] || 0} resultats={resultats} siegesParListe={siegesParListe} blocs={blocs} nuances={nuances} />
|
<TableRow key={liste.numero}>
|
||||||
|
<TableCell>{liste.numero}</TableCell>
|
||||||
|
<TableCell>{liste.nom}</TableCell>
|
||||||
|
<TableCell sx={{backgroundColor: nuances.filter(nuance => nuance.code === liste.nuance)[0].couleur, padding: "0.2em"}}></TableCell>
|
||||||
|
<TableCell>{liste.nuance}</TableCell>
|
||||||
|
<TableCell sx={{backgroundColor: blocs.filter(bloc => bloc.nom === liste.bloc)[0].couleur, padding: "0.2em"}}></TableCell>
|
||||||
|
<TableCell>{liste.bloc}</TableCell>
|
||||||
|
<TableCell>{voix_listes[liste.numero] || 0}</TableCell>
|
||||||
|
<TableCell>{(100 * (voix_listes[liste.numero] || 0) / resultats.inscrits).toFixed(2)} %</TableCell>
|
||||||
|
<TableCell>{(100 * (voix_listes[liste.numero] || 0) / resultats.exprimes).toFixed(2)} %</TableCell>
|
||||||
|
<TableCell>{siegesParListe[liste.numero]}</TableCell>
|
||||||
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
@ -51,25 +59,6 @@ function ResultatsTable({blocs, nuances, listes, resultats, siegesParListe}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ListeRow({liste, voix, resultats, siegesParListe, blocs, nuances}) {
|
|
||||||
const bloc = blocs.filter(bloc => bloc.nom === liste.bloc)[0]
|
|
||||||
const nuance = nuances.filter(nuance => nuance.code === liste.nuance)[0]
|
|
||||||
|
|
||||||
return <TableRow key={liste.numero}>
|
|
||||||
<TableCell>{liste.numero}</TableCell>
|
|
||||||
<TableCell>{liste.nom}</TableCell>
|
|
||||||
<TableCell sx={{backgroundColor: nuance.couleur, padding: "0.2em"}}></TableCell>
|
|
||||||
<TableCell>{liste.nuance}</TableCell>
|
|
||||||
<TableCell sx={{backgroundColor: bloc.couleur, padding: "0.2em"}}></TableCell>
|
|
||||||
<TableCell>{liste.bloc}</TableCell>
|
|
||||||
<TableCell>{voix}</TableCell>
|
|
||||||
<TableCell>{(100 * voix / resultats.inscrits).toFixed(2)} %</TableCell>
|
|
||||||
<TableCell>{(100 * voix / resultats.exprimes).toFixed(2)} %</TableCell>
|
|
||||||
<TableCell>{siegesParListe[liste.numero]}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function ParticipationTable({resultats}) {
|
function ParticipationTable({resultats}) {
|
||||||
return <>
|
return <>
|
||||||
<TableContainer component={Paper}>
|
<TableContainer component={Paper}>
|
||||||
@ -125,96 +114,6 @@ function ParticipationTable({resultats}) {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function RegionGeoJSON({resultats_region, listes, blocs, nuances, grouperParBloc = false}) {
|
|
||||||
const voix_listes = resultats_region?.voix_listes ?? {}
|
|
||||||
const listes_triees = listes.toSorted((l1, l2) => {
|
|
||||||
return (voix_listes[l2.numero] || 0) - (voix_listes[l1.numero] || 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
const voixParBloc = {}
|
|
||||||
const voixParNuance = {}
|
|
||||||
for (let bloc of blocs) {
|
|
||||||
voixParBloc[bloc.nom] = 0
|
|
||||||
}
|
|
||||||
for (let nuance of nuances) {
|
|
||||||
voixParNuance[nuance.code] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let liste of listes) {
|
|
||||||
voixParBloc[liste.bloc] += resultats_region.voix_listes[liste.numero] || 0
|
|
||||||
voixParNuance[liste.nuance] += resultats_region.voix_listes[liste.numero] || 0
|
|
||||||
}
|
|
||||||
|
|
||||||
let couleur = 'grey'
|
|
||||||
if (grouperParBloc) {
|
|
||||||
let maxVoix = 0
|
|
||||||
for (let bloc of blocs) {
|
|
||||||
if (voixParBloc[bloc.nom] > maxVoix) {
|
|
||||||
maxVoix = voixParBloc[bloc.nom]
|
|
||||||
couleur = bloc.couleur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let maxVoix = 0
|
|
||||||
for (let nuance of nuances) {
|
|
||||||
if (voixParNuance[nuance.code] > maxVoix) {
|
|
||||||
maxVoix = voixParNuance[nuance.code]
|
|
||||||
couleur = nuance.couleur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return <GeoJSON
|
|
||||||
key={resultats_region.region.code_insee}
|
|
||||||
data={{'type': "Feature", 'properties': resultats_region, 'geometry': resultats_region.geometry}}
|
|
||||||
style={{fillColor: couleur, fillOpacity: 0.5, color: 'white'}}>
|
|
||||||
<Popup>
|
|
||||||
<strong><a href={`/elections/europeennes/2024/region/${resultats_region.region.code_insee}/`}>{resultats_region.region.nom}</a></strong>
|
|
||||||
<ul>
|
|
||||||
{listes_triees.slice(0, 5).map(liste =>
|
|
||||||
<li key={liste.numero}>{liste.nom} : {voix_listes[liste.numero]} ({(100 * voix_listes[liste.numero] / resultats_region.exprimes).toFixed(2)} %)</li>)}
|
|
||||||
</ul>
|
|
||||||
</Popup>
|
|
||||||
</GeoJSON>
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContenuCarte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc = false}) {
|
|
||||||
const [regions, setRegions] = useState([])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!resultats || !resultats.france || !resultats.france.regions)
|
|
||||||
return
|
|
||||||
|
|
||||||
setRegions(regions => [])
|
|
||||||
|
|
||||||
resultats.france.regions.forEach(region_code => {
|
|
||||||
fetch(`/data/resultats/europeennes2024/regions/${region_code}.json`).then(response => response.json())
|
|
||||||
.then(region => setRegions(regions => [...regions, region]))
|
|
||||||
})
|
|
||||||
}, [typeResultats, resultats])
|
|
||||||
|
|
||||||
const map = useMap()
|
|
||||||
|
|
||||||
return <>
|
|
||||||
{regions.map(region => <RegionGeoJSON key={region.region.code_insee} resultats_region={region} listes={listes} blocs={blocs} nuances={nuances} grouperParBloc={grouperParBloc} />)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
function Carte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc = false}) {
|
|
||||||
const center = [46.603354, 1.888334]
|
|
||||||
|
|
||||||
return <>
|
|
||||||
<MapContainer center={center} zoom={6} style={{height: "90vh"}}>
|
|
||||||
<TileLayer
|
|
||||||
attribution='© Les contributeur⋅rices <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
||||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
||||||
/>
|
|
||||||
<ContenuCarte typeResultats={typeResultats} resultats={resultats} listes={listes} blocs={blocs} nuances={nuances} grouperParBloc={grouperParBloc} />
|
|
||||||
</MapContainer>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Election2024({typeResultats = "france"}) {
|
export default function Election2024({typeResultats = "france"}) {
|
||||||
const {zoneId} = useParams()
|
const {zoneId} = useParams()
|
||||||
|
|
||||||
@ -422,10 +321,8 @@ export default function Election2024({typeResultats = "france"}) {
|
|||||||
title: {
|
title: {
|
||||||
text: `Résultats des élections européennes 2024 : ${zoneName}`,
|
text: `Résultats des élections européennes 2024 : ${zoneName}`,
|
||||||
},
|
},
|
||||||
tooltip: {
|
legend: {
|
||||||
formatter: function () {
|
labelFormat: '{name} <span style="opacity: 0.4">{x}</span>'
|
||||||
return `<span>${this.x}</span> : <strong>${this.y}</strong> voix (${(100 * this.y / resultats.exprimes).toFixed(2)} %)<br>`
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
categories: categoriesVoix,
|
categories: categoriesVoix,
|
||||||
@ -458,6 +355,5 @@ export default function Election2024({typeResultats = "france"}) {
|
|||||||
/>
|
/>
|
||||||
<ResultatsTable blocs={blocs} nuances={nuances} listes={listes} resultats={resultats} siegesParListe={siegesParListe} />
|
<ResultatsTable blocs={blocs} nuances={nuances} listes={listes} resultats={resultats} siegesParListe={siegesParListe} />
|
||||||
<ParticipationTable resultats={resultats} />
|
<ParticipationTable resultats={resultats} />
|
||||||
<Carte typeResultats={typeResultats} resultats={resultats} listes={listes} blocs={blocs} nuances={nuances} voixParBloc={voixParBloc} voixParNuance={voixParNuance} grouperParBloc={grouperParBloc} />
|
|
||||||
</>
|
</>
|
||||||
}
|
};
|
@ -73,11 +73,6 @@ def exporter_resultats_france(engine: Engine, verbose: bool = False) -> None:
|
|||||||
session.add(resultats_france)
|
session.add(resultats_france)
|
||||||
|
|
||||||
resultats_dict = {
|
resultats_dict = {
|
||||||
'france': {
|
|
||||||
'regions': [reg.code_insee for reg in session.execute(select(Region)).scalars().all()],
|
|
||||||
'departements': [dpt.code_insee for dpt in session.execute(select(Departement)).scalars().all()],
|
|
||||||
'circonscriptions': [circo.id for circo in session.execute(select(Circonscription)).scalars().all()],
|
|
||||||
},
|
|
||||||
"inscrits": resultats_france.inscrits,
|
"inscrits": resultats_france.inscrits,
|
||||||
"votants": resultats_france.votants,
|
"votants": resultats_france.votants,
|
||||||
"abstentions": resultats_france.abstentions,
|
"abstentions": resultats_france.abstentions,
|
||||||
@ -110,11 +105,7 @@ def exporter_resultats_regions(engine: Engine, verbose: bool = False) -> None:
|
|||||||
regions_iterator = tqdm(regions, desc="Régions") if verbose else regions
|
regions_iterator = tqdm(regions, desc="Régions") if verbose else regions
|
||||||
for region in regions_iterator:
|
for region in regions_iterator:
|
||||||
region_json = {'code_insee': region.code_insee, 'nom': region.libelle,
|
region_json = {'code_insee': region.code_insee, 'nom': region.libelle,
|
||||||
'departements': [dpt.code_insee for dpt in region.departements],
|
'departements': [dpt.code_insee for dpt in region.departements]}
|
||||||
'circonscriptions':
|
|
||||||
[circo.id for circo in session.execute(
|
|
||||||
select(Circonscription).join(Departement).filter_by(region_code=region.code_insee))
|
|
||||||
.scalars().all()]}
|
|
||||||
regions_json.append(region_json)
|
regions_json.append(region_json)
|
||||||
|
|
||||||
resultats_region = session.execute(select(ResultatsRegion).filter_by(region_id=region.code_insee)) \
|
resultats_region = session.execute(select(ResultatsRegion).filter_by(region_id=region.code_insee)) \
|
||||||
@ -327,7 +318,6 @@ def exporter_resultats_bureaux_vote(engine: Engine, verbose: bool = False) -> No
|
|||||||
iterator = tqdm(bureaux_vote, desc="Bureaux de vote") if verbose else bureaux_vote
|
iterator = tqdm(bureaux_vote, desc="Bureaux de vote") if verbose else bureaux_vote
|
||||||
for bureau_vote in iterator:
|
for bureau_vote in iterator:
|
||||||
bureau_vote_json = {'id': bureau_vote.id,
|
bureau_vote_json = {'id': bureau_vote.id,
|
||||||
'libelle': bureau_vote.libelle,
|
|
||||||
'commune': bureau_vote.commune_code,
|
'commune': bureau_vote.commune_code,
|
||||||
'circonscription': bureau_vote.circo_code}
|
'circonscription': bureau_vote.circo_code}
|
||||||
bureaux_vote_json.append(bureau_vote_json)
|
bureaux_vote_json.append(bureau_vote_json)
|
||||||
|
@ -251,7 +251,7 @@ def importer_bureaux_vote(engine: Engine, verbose: bool = False) -> None:
|
|||||||
numero_circo = int(bv_dict['codeCirconscription'][len(dpt_code):])
|
numero_circo = int(bv_dict['codeCirconscription'][len(dpt_code):])
|
||||||
code_circo = f"{dpt_code}-{numero_circo:02d}"
|
code_circo = f"{dpt_code}-{numero_circo:02d}"
|
||||||
bv_id = bv_dict['id_bv'].split()[0]
|
bv_id = bv_dict['id_bv'].split()[0]
|
||||||
bv_libelle = f"Bureau {code_bv} de {bv_dict['nomCommune']}"
|
bv_libelle = f"Bureau {code_bv}"
|
||||||
|
|
||||||
if not session.execute(select(Commune).filter_by(code_insee=code_commune)).scalar_one_or_none():
|
if not session.execute(select(Commune).filter_by(code_insee=code_commune)).scalar_one_or_none():
|
||||||
print("Commune non trouvée avec le code", code_commune, "et le nom", bv_dict['nomCommune'])
|
print("Commune non trouvée avec le code", code_commune, "et le nom", bv_dict['nomCommune'])
|
||||||
|
@ -29,9 +29,6 @@ def importer_resultats_bv(engine: Engine, verbose: bool = False) -> None:
|
|||||||
# Communes nouvelles ayant défusionné en 2024
|
# Communes nouvelles ayant défusionné en 2024
|
||||||
# TODO Gérer
|
# TODO Gérer
|
||||||
continue
|
continue
|
||||||
elif com_code == "98601":
|
|
||||||
# 3 royaumes à Wallis-et-Futuna, mais un seul résultat de commune
|
|
||||||
com_code = "98611"
|
|
||||||
|
|
||||||
if bv := session.execute(select(BureauVote).filter_by(commune_code=com_code, code_bureau=bv_code)) \
|
if bv := session.execute(select(BureauVote).filter_by(commune_code=com_code, code_bureau=bv_code)) \
|
||||||
.scalar_one_or_none():
|
.scalar_one_or_none():
|
||||||
@ -123,9 +120,6 @@ def importer_resultats_commune(engine: Engine, verbose: bool = False) -> None:
|
|||||||
# Communes nouvelles ayant défusionné en 2024
|
# Communes nouvelles ayant défusionné en 2024
|
||||||
# TODO Gérer
|
# TODO Gérer
|
||||||
continue
|
continue
|
||||||
elif com_code == "98601":
|
|
||||||
# 3 royaumes à Wallis-et-Futuna, mais un seul résultat de commune
|
|
||||||
com_code = "98611"
|
|
||||||
|
|
||||||
resultats_commune = session.execute(select(ResultatsCommune).filter_by(commune_id=com_code)) \
|
resultats_commune = session.execute(select(ResultatsCommune).filter_by(commune_id=com_code)) \
|
||||||
.scalar_one_or_none()
|
.scalar_one_or_none()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user