Skip to content

Commit 875744b

Browse files
Add support for themes
1 parent 6134815 commit 875744b

17 files changed

Lines changed: 669 additions & 29 deletions

app.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,54 @@ function setActiveTier(tier, options = {}) {
822822
if (entry) await replayQuerySession(entry);
823823
};
824824

825+
// Heatmap panel rendering and temporal animation bridges
826+
window.renderCurseurTemps = function() {
827+
const container = document.getElementById("curseur-temps-container");
828+
if (!container) return;
829+
const render = window.ui?.composants?.curseur_temps?.rendre_curseur_temps;
830+
if (typeof render !== "function") return;
831+
const plage = window.ui?.etat?.obtenir_plage_heatmap?.() ?? { debut: 1400, fin: 2000 };
832+
const courante = window.ui?.etat?.obtenir_annee_heatmap?.() ?? plage.debut;
833+
container.innerHTML = render(plage.debut, plage.fin, courante);
834+
};
835+
836+
window.filtrerHeatmapParAnnee = function(annee) {
837+
const vue = window._heatmapVue;
838+
if (vue && typeof vue.filtrer_par_annee === "function") vue.filtrer_par_annee(annee);
839+
};
840+
841+
let _heatmapAnimId = null;
842+
window.jouerAnimationHeatmap = function(debut, fin, vitesse) {
843+
if (_heatmapAnimId) clearInterval(_heatmapAnimId);
844+
const step = vitesse || 60;
845+
let annee = debut ?? (window.ui?.etat?.obtenir_plage_heatmap?.()?.debut ?? 1400);
846+
const end = fin ?? (window.ui?.etat?.obtenir_plage_heatmap?.()?.fin ?? 2000);
847+
_heatmapAnimId = setInterval(() => {
848+
annee += 1;
849+
if (annee > end) { clearInterval(_heatmapAnimId); _heatmapAnimId = null; return; }
850+
window.ui?.etat?.definir_annee_heatmap?.(annee);
851+
window.filtrerHeatmapParAnnee(annee);
852+
window.renderCurseurTemps?.();
853+
}, step);
854+
};
855+
856+
window.arreterAnimationHeatmap = function() {
857+
if (_heatmapAnimId) { clearInterval(_heatmapAnimId); _heatmapAnimId = null; }
858+
};
859+
860+
window.afficherHeatmapPanel = async function(mouvementId) {
861+
const container = document.getElementById("heatmap-panel-container");
862+
if (!container) return;
863+
container.hidden = false;
864+
const canvas = document.getElementById("heatmap-canvas");
865+
if (!canvas) return;
866+
const creer = window.ui?.visualisations?.heatmap_vue?.creer_vue_heatmap;
867+
if (typeof creer === "function") {
868+
window._heatmapVue = await creer(canvas, mouvementId);
869+
}
870+
window.renderCurseurTemps?.();
871+
};
872+
825873
function applyTierFromUrl() {
826874
const params = new URLSearchParams(window.location.search);
827875
const tier = params.get("tier");

bundle.js

Lines changed: 357 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

graphql/artist_details.graphql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,10 @@ query ArtistDetails($id: ItemId!, $languageCode: LanguageCode!) {
3636
}
3737
}
3838
}
39+
image: statements(propertyId: "P18") {
40+
value {
41+
... on StringValue { content }
42+
}
43+
}
3944
}
4045
}

index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,12 @@ <h3 class="section-title">Interpretation</h3>
423423
<div id="trajectoire-panel-container" class="trajectoire-panel-overlay" hidden>
424424
<div id="__ml_trajectoire_root"></div>
425425
</div>
426+
427+
<!-- Heatmap Panel - geographic diffusion with temporal animation -->
428+
<div id="heatmap-panel-container" class="heatmap-panel-overlay" hidden>
429+
<canvas id="heatmap-canvas" width="600" height="380" aria-label="Geographic diffusion heatmap"></canvas>
430+
<div id="curseur-temps-container"></div>
431+
</div>
426432
</main>
427433

428434
<footer class="footer-rail panel" role="contentinfo">

src/donnees/normalisation.multi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ déf normaliser_artiste(element: dictionnaire) -> dictionnaire:
122122
"deathplace": _envelopper_elements(lieu_deces),
123123
"deathplaceLabel": _etiquettes_jointes(lieu_deces),
124124
"movement": _envelopper_elements(mouvement),
125-
"movementLabel": _etiquettes_jointes(mouvement)
125+
"movementLabel": _etiquettes_jointes(mouvement),
126+
"image": {"value": _premiere_valeur_contenu(element.obtenir("image", []))}
126127
}
127128

128129

src/principal.multi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ importer ui.visualisations.polyglot_studio_vue
1616
importer ui.visualisations.chronologie_vue
1717
importer ui.visualisations.graphe_vue
1818
importer ui.composants.session_requete
19+
importer ui.composants.curseur_temps
1920
importer semantique.intersections
21+
importer ui.visualisations.heatmap_vue
22+
importer ui.visualisations.empreinte_vue
23+
importer semantique.empreinte
24+
importer utilitaires.media
2025

2126
# ui.etat is intentionally owned by Multilingual. The browser shell may keep a
2227
# temporary compatibility fallback, but new application state belongs here.

src/semantique/__init__.multi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ importer .graphe
33
importer .filtres
44
importer .geographique
55
importer .temporel
6+
importer .empreinte

src/semantique/empreinte.multi

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Distribution des sujets P180 par lentille sémantique.
2+
# Mapping embarqué pour éviter les problèmes d'accès aux constantes inter-modules.
3+
4+
_LENTILLES_SUJETS = {
5+
"couleur": ["Q1075", "Q571", "Q1379522", "Q1076"],
6+
"geometrie": ["Q10307", "Q127020", "Q188913", "Q192762"],
7+
"symbolisme": ["Q34379", "Q6881637", "Q45621"],
8+
"emotion": ["Q9415", "Q26742", "Q40241"],
9+
"mythologie": ["Q34379", "Q178885", "Q11042"],
10+
"religion": ["Q45621", "Q9176", "Q645883"],
11+
"nature": ["Q441", "Q15284", "Q25306", "Q45"],
12+
"politique": ["Q7163", "Q6256", "Q5"],
13+
"industrialisation": ["Q2016", "Q28823", "Q11019"]
14+
}
15+
16+
_LABELS_LENTILLES = {
17+
"couleur": "Couleur",
18+
"geometrie": "Géométrie",
19+
"symbolisme": "Symbolisme",
20+
"emotion": "Émotion",
21+
"mythologie": "Mythologie",
22+
"religion": "Religion",
23+
"nature": "Nature",
24+
"politique": "Politique",
25+
"industrialisation": "Industrialisation"
26+
}
27+
28+
29+
déf calculer_empreinte_depuis_sujets(sujets_ids: liste) -> dictionnaire:
30+
"""Compter combien de sujets P180 tombent dans chaque lentille sémantique."""
31+
sujets_vus = {}
32+
pour s dans sujets_ids:
33+
sujets_vus[s] = vrai
34+
35+
frequences = {}
36+
pour lentille dans _LENTILLES_SUJETS:
37+
sujets_lentille = _LENTILLES_SUJETS.obtenir(lentille, [])
38+
compteur = 0
39+
pour sujet dans sujets_lentille:
40+
si sujet dans sujets_vus:
41+
compteur = compteur + 1
42+
si compteur > 0:
43+
frequences[lentille] = compteur
44+
45+
retour frequences
46+
47+
48+
déf obtenir_label_lentille(lentille: chaine) -> chaine:
49+
"""Retourner le libellé français d'une lentille."""
50+
retour _LABELS_LENTILLES.obtenir(lentille, lentille)

src/ui/composants/__init__.multi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
importer .panneau_filtres
33
importer .barre_recherche
44
importer .panneau_detail
5+
importer .curseur_temps
56

67
exporter barre_recherche.rendre_barre_recherche
78
exporter panneau_detail.rendre_panneau_detail
9+
exporter curseur_temps.rendre_curseur_temps
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
importer ui.etat
2+
importer ui.i18n
3+
4+
5+
déf _t(cle: chaine) -> chaine:
6+
retour ui.i18n.obtenir_texte(cle, ui.etat.mode_langue_actif)
7+
8+
9+
déf rendre_curseur_temps(debut: nombre, fin: nombre, actuelle: nombre) -> chaine:
10+
"""Rendre le contrôle de curseur temporel pour l'animation de diffusion géographique."""
11+
si debut >= fin:
12+
retour ""
13+
14+
debut_str = chaine(round(debut))
15+
fin_str = chaine(round(fin))
16+
actuelle_str = chaine(round(actuelle))
17+
18+
change_handler = "window.ui&&window.ui.etat&&window.ui.etat.definir_annee_heatmap&&window.ui.etat.definir_annee_heatmap(Number(this.value));window.filtrerHeatmapParAnnee&&window.filtrerHeatmapParAnnee(Number(this.value));window.renderCurseurTemps&&window.renderCurseurTemps()"
19+
play_handler = "window.jouerAnimationHeatmap&&window.jouerAnimationHeatmap(" + debut_str + "," + fin_str + ",60)"
20+
pause_handler = "window.arreterAnimationHeatmap&&window.arreterAnimationHeatmap()"
21+
22+
html = "<div class='curseur-temps'>"
23+
html = html + "<div class='curseur-temps-header'>"
24+
html = html + "<span class='curseur-temps-titre'>" + _t("heatmap.temporalCursor") + "</span>"
25+
html = html + "<span class='curseur-temps-annee'>" + actuelle_str + "</span>"
26+
html = html + "</div>"
27+
html = html + "<input type='range' class='curseur-temps-slider' min='" + debut_str + "' max='" + fin_str + "' value='" + actuelle_str + "' onchange='" + change_handler + "' />"
28+
html = html + "<div class='curseur-temps-controls'>"
29+
html = html + "<span class='curseur-temps-borne'>" + debut_str + "</span>"
30+
html = html + "<button class='curseur-temps-btn' onclick='" + play_handler + "'>" + _t("heatmap.play") + "</button>"
31+
html = html + "<button class='curseur-temps-btn' onclick='" + pause_handler + "'>" + _t("heatmap.pause") + "</button>"
32+
html = html + "<span class='curseur-temps-borne'>" + fin_str + "</span>"
33+
html = html + "</div>"
34+
html = html + "</div>"
35+
retour html

0 commit comments

Comments
 (0)