Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,14 +3,15 @@ import pandas as pd
|
|
| 3 |
import os
|
| 4 |
import time
|
| 5 |
from typing import List, Union, Dict, Any, Tuple
|
|
|
|
| 6 |
|
| 7 |
# =================================================================
|
| 8 |
# CONFIGURATION AND LANGUAGE DEFINITIONS
|
| 9 |
# =================================================================
|
| 10 |
|
| 11 |
-
# Setting EXPECTED_DATA_COUNT based on the final verified structure:
|
| 12 |
-
EXPECTED_DATA_COUNT =
|
| 13 |
-
EXPECTED_COUNT =
|
| 14 |
|
| 15 |
# --- Shared Choices (French Only) ---
|
| 16 |
FREQ_FR = ["Jamais", "Rarement", "Parfois", "Souvent"]
|
|
@@ -52,6 +53,33 @@ INFO5_CHOICES = [
|
|
| 52 |
"autre réaction"
|
| 53 |
]
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
# --- Language Definitions (French Only) ---
|
| 57 |
LANG_FR = {
|
|
@@ -68,14 +96,10 @@ LANG_FR = {
|
|
| 68 |
"SPACE1_LABEL": "SPACE1 - Fréquentes-tu des lieux culturels (au sens large, y compris alternatifs, non institutionnels) ?",
|
| 69 |
"SPACE2A_TITLE": "Derniers lieux culturels fréquentés (3 max. - si Rarement/Parfois/Souvent)",
|
| 70 |
"SPACE2B_LABEL": "SPACE2b (si “jamais”) - Pourquoi ne fréquentes-tu jamais de lieux culturels ? (plusieurs réponses possibles)",
|
| 71 |
-
|
| 72 |
-
# FIX: Mise à jour du titre SPACE3 selon la nouvelle qualification demandée (titre SPACE4)
|
| 73 |
"SPACE3_TITLE": "SPACE4 - Pourrais-tu qualifier ces lieux ?",
|
| 74 |
"SPACE3_QUAL_1": "Lieu 1 : Alternatif/Underground (1) à Institutionnel/Mainstream (10)",
|
| 75 |
"SPACE3_QUAL_2": "Lieu 2 : Alternatif (1) à Institutionnel (10)",
|
| 76 |
"SPACE3_QUAL_3": "Lieu 3 : Alternatif (1) à Institutionnel (10)",
|
| 77 |
-
|
| 78 |
-
# Les labels suivants conservent leur numérotation pour la cohérence des variables
|
| 79 |
"SPACE4_LABEL": "SPACE4_bis - Est-ce que tu suis régulièrement une communauté alternative en ligne (médias sociaux, newsletter, groupe dédié...)",
|
| 80 |
"SPACE5_LABEL": "SPACE5 - Peux-tu indiquer son nom ou son url ? (si SPACE4_bis=oui)",
|
| 81 |
"SPACE6_LABEL": "SPACE6 - As-tu connaissance de pratiques d’engagement citoyen dans ces lieux ?",
|
|
@@ -83,8 +107,9 @@ LANG_FR = {
|
|
| 83 |
"SPACE_DOMAIN_LABEL": "Peux-tu caractériser le domaine dans lequel s’inscrit principalement cette pratique ?",
|
| 84 |
"SPACE11_LABEL": "SPACE11 - Sais-tu si elle s’appuie sur une communauté en ligne et l’usage d’un média social en ligne ?",
|
| 85 |
"SPACE2B_OPTIONS": ["Pas le temps", "Trop cher", "Je ne sais pas où aller", "Pas intéressé", "Autre"],
|
| 86 |
-
"
|
| 87 |
"ENGAGEMENT_ORGANISATION_LABEL": "ENGAGE2 - Dans quelle(s) organisation(s) es-tu engagé·e ?",
|
|
|
|
| 88 |
"ENGAGEMENT_DOMAINE_LABEL": "ENGAGE3 - Dans quel domaine ? (Si engagé·e)",
|
| 89 |
"INFO_ACTIVITES_LABEL": "ENGAGE4 - Participes-tu ou as-tu participé à une ou plusieurs des activités suivantes ?",
|
| 90 |
"INFO_RESEAUX_SOCIAUX_LABEL": "ENGAGE5 - Utilises-tu les réseaux sociaux pour t’engager dans des causes ?",
|
|
@@ -103,7 +128,8 @@ LANG_FR = {
|
|
| 103 |
"PLATFORM_TITLE": "DIGITAL1 - Quelles plateformes utilises-tu le plus ? (Heures/jour approx.)",
|
| 104 |
"PURPOSE_TITLE": "DIGITAL2 - Pour quel(s) usage(s) emploies-tu ces plateformes ?",
|
| 105 |
"DEMO_GENDER_LABEL": "DEMO_GENDER - Ton genre :",
|
| 106 |
-
|
|
|
|
| 107 |
"DEMO_LOCATION_COMMUNE_LABEL": "DEMO_LOCATION - Commune de résidence habituelle :",
|
| 108 |
"DEMO_LOCATION_ARROND_LABEL": "Arrondissement (si Paris) :",
|
| 109 |
"DEMO_PARENTS_LOCATION_LABEL": "DEMO_PARENTS - Est-ce le lieu d’habitation de tes parents ?",
|
|
@@ -149,12 +175,10 @@ space2a_2 = gr.Textbox(label="Lieu 2", visible=False)
|
|
| 149 |
space2a_3 = gr.Textbox(label="Lieu 3", visible=False)
|
| 150 |
space2b = gr.CheckboxGroup(label=LANG["SPACE2B_LABEL"], choices=LANG["SPACE2B_OPTIONS"], visible=False)
|
| 151 |
|
| 152 |
-
# FIX: Mise à jour des sliders SPACE3 (nouveau label et description)
|
| 153 |
space3_1 = gr.Slider(label=LANG["SPACE3_QUAL_1"], minimum=1, maximum=10, step=1, visible=False)
|
| 154 |
space3_2 = gr.Slider(label=LANG["SPACE3_QUAL_2"], minimum=1, maximum=10, step=1, visible=False)
|
| 155 |
space3_3 = gr.Slider(label=LANG["SPACE3_QUAL_3"], minimum=1, maximum=10, step=1, visible=False)
|
| 156 |
|
| 157 |
-
# Les composants suivants conservent leur nom de variable (space4, space5, space6...) pour la cohérence des données
|
| 158 |
space4 = gr.Radio(label=LANG["SPACE4_LABEL"], choices=["Oui", "Non"])
|
| 159 |
space5 = gr.Textbox(label=LANG["SPACE5_LABEL"], visible=False)
|
| 160 |
space6 = gr.Radio(label=LANG["SPACE6_LABEL"], choices=["Oui", "Non", "Ne sait pas"])
|
|
@@ -170,8 +194,9 @@ space_domain_3 = gr.Radio(label=f"Pratique 3 - {LANG['SPACE_DOMAIN_LABEL']}", ch
|
|
| 170 |
space11 = gr.CheckboxGroup(label=LANG["SPACE11_LABEL"], choices=SOCIAL_MEDIA_CHOICES)
|
| 171 |
|
| 172 |
# === TAB 2 Components ===
|
| 173 |
-
|
| 174 |
-
|
|
|
|
| 175 |
engagement_domaine = gr.Textbox(label=LANG["ENGAGEMENT_DOMAINE_LABEL"], placeholder="Domaine de l'engagement...")
|
| 176 |
info_activites = gr.CheckboxGroup(label=LANG["INFO_ACTIVITES_LABEL"], choices=["Participer à une manifestation/grève", "Contacter un élu", "Signer une pétition en ligne", "Boycotter un produit/marque", "Faire un don à une association", "Autre"], interactive=True)
|
| 177 |
info_reseaux_sociaux = gr.Radio(label=LANG["INFO_RESEAUX_SOCIAUX_LABEL"], choices=["Oui", "Non", "Parfois"])
|
|
@@ -224,14 +249,17 @@ purpose_components.append(gr.Radio(label=f"Fréquence pour: {PURPOSE_CHOICES[-1]
|
|
| 224 |
purpose_social, purpose_professionnel, purpose_autre_freq) = purpose_components
|
| 225 |
|
| 226 |
|
| 227 |
-
# === TAB 5 Components ===
|
| 228 |
demo_gender = gr.Radio(label=LANG["DEMO_GENDER_LABEL"], choices=["Homme", "Femme", "Non-binaire", "Préfère ne pas dire"])
|
| 229 |
-
|
|
|
|
| 230 |
demo_location_commune = gr.Textbox(label=LANG["DEMO_LOCATION_COMMUNE_LABEL"], placeholder="Nom de la commune")
|
| 231 |
demo_location_arrond = gr.Textbox(label=LANG["DEMO_LOCATION_ARROND_LABEL"], placeholder="ex: 75005")
|
| 232 |
demo_parents_location = gr.Radio(label=LANG["DEMO_PARENTS_LOCATION_LABEL"], choices=["Oui", "Non"])
|
| 233 |
-
|
| 234 |
-
|
|
|
|
|
|
|
| 235 |
demo_job = gr.Radio(label=LANG["DEMO_JOB_LABEL"], choices=["Oui", "Non"])
|
| 236 |
demo_income = gr.Radio(label=LANG["DEMO_INCOME_LABEL"], choices=INCOME_CHOICES)
|
| 237 |
demo_socialcapital1_parent1 = gr.Radio(label=LANG["DEMO_SOCIALCAPITAL1_PARENT1_LABEL"], choices=INSEE_CHOICES)
|
|
@@ -268,6 +296,8 @@ def get_column_names(data_components: list) -> list:
|
|
| 268 |
clean_name = "SPACE4_QUAL_2"
|
| 269 |
elif "Lieu 3 : Alternatif" in name:
|
| 270 |
clean_name = "SPACE4_QUAL_3"
|
|
|
|
|
|
|
| 271 |
|
| 272 |
names.append(clean_name)
|
| 273 |
else:
|
|
@@ -329,6 +359,9 @@ def update_domain_visibility(practice_text):
|
|
| 329 |
is_cited = bool(practice_text.strip())
|
| 330 |
return gr.update(visible=is_cited)
|
| 331 |
|
|
|
|
|
|
|
|
|
|
| 332 |
def process_survey(*data_values: Any) -> Tuple[str, gr.File]:
|
| 333 |
"""
|
| 334 |
Processes survey data, creates a temporary CSV file, and returns the path
|
|
@@ -341,23 +374,30 @@ def process_survey(*data_values: Any) -> Tuple[str, gr.File]:
|
|
| 341 |
error_msg = f"Erreur critique: Le nombre d'entrées reçues est incorrect ({len(all_inputs_list)} au lieu de {EXPECTED_COUNT}). Veuillez contacter le développeur."
|
| 342 |
return error_msg, gr.update(visible=False, value=None)
|
| 343 |
|
| 344 |
-
# Language is hardcoded as "FR"
|
| 345 |
language = "FR"
|
| 346 |
|
| 347 |
try:
|
| 348 |
column_names = get_column_names(DATA_INPUT_COMPONENTS)
|
| 349 |
-
column_names.insert(0, "DEMO_LANGUAGE")
|
| 350 |
|
| 351 |
data_row = [language] + all_inputs_list
|
| 352 |
|
| 353 |
df = pd.DataFrame([data_row], columns=column_names)
|
| 354 |
|
| 355 |
-
#
|
| 356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
os.makedirs(os.path.dirname(temp_filename), exist_ok=True)
|
| 358 |
df.to_csv(temp_filename, index=False, encoding='utf-8')
|
| 359 |
|
| 360 |
-
success_msg = f"✨ Succès ! Le questionnaire a été soumis. Cliquez sur le lien ci-dessous pour **Télécharger le Fichier CSV**."
|
| 361 |
|
| 362 |
return success_msg, gr.update(value=temp_filename, visible=True)
|
| 363 |
|
|
@@ -375,15 +415,15 @@ DATA_INPUT_COMPONENTS = [
|
|
| 375 |
# TAB 1 - Contact & Lieux (22)
|
| 376 |
approach_answer, refusal_reason, refusal_reason_other, contact_later,
|
| 377 |
space1, space2a_1, space2a_2, space2a_3, space2b,
|
| 378 |
-
space3_1, space3_2, space3_3,
|
| 379 |
space4, space5,
|
| 380 |
space6,
|
| 381 |
space7_1, space_domain_1,
|
| 382 |
space7_2, space_domain_2,
|
| 383 |
space7_3, space_domain_3,
|
| 384 |
space11,
|
| 385 |
-
# TAB 2 - Engagement (
|
| 386 |
-
|
| 387 |
# TAB 3 - Actualité (16)
|
| 388 |
info_frequence_actu, info2, info3, info_opposite_feeling, info_contradict_opinion,
|
| 389 |
info4, info5,
|
|
@@ -453,7 +493,6 @@ with gr.Blocks(title=LANG["TITLE"], css=".gradio-container { max-width: 1200px;
|
|
| 453 |
space2a_2.render()
|
| 454 |
space2a_3.render()
|
| 455 |
|
| 456 |
-
# FIX: Nouveau titre pour la qualification des lieux (SPACE4 dans le texte)
|
| 457 |
gr.Markdown(f"#### {LANG['SPACE3_TITLE']}")
|
| 458 |
with gr.Row() as space3_row:
|
| 459 |
space3_1.render()
|
|
@@ -464,7 +503,7 @@ with gr.Blocks(title=LANG["TITLE"], css=".gradio-container { max-width: 1200px;
|
|
| 464 |
space1.change(update_visibility_space1, inputs=[space1], outputs=[space2a_1, space2a_2, space2a_3, space3_1, space3_2, space3_3, space2b])
|
| 465 |
|
| 466 |
gr.Markdown("### Usages alternatifs et Engagement")
|
| 467 |
-
space4.render()
|
| 468 |
space5.render()
|
| 469 |
space4.change(update_visibility_space4, inputs=[space4], outputs=[space5])
|
| 470 |
|
|
@@ -498,11 +537,19 @@ with gr.Blocks(title=LANG["TITLE"], css=".gradio-container { max-width: 1200px;
|
|
| 498 |
# TAB 2: Engagement Citoyen
|
| 499 |
# =================================================================
|
| 500 |
with gr.Tab(LANG["TAB_2_TITLE"]):
|
| 501 |
-
|
| 502 |
-
|
|
|
|
| 503 |
engagement_domaine.render()
|
| 504 |
info_activites.render()
|
| 505 |
info_reseaux_sociaux.render()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
|
| 507 |
# =================================================================
|
| 508 |
# TAB 3: Consommation d’actualités
|
|
@@ -578,18 +625,18 @@ with gr.Blocks(title=LANG["TITLE"], css=".gradio-container { max-width: 1200px;
|
|
| 578 |
|
| 579 |
|
| 580 |
# =================================================================
|
| 581 |
-
# TAB 5: Profil Démographique
|
| 582 |
# =================================================================
|
| 583 |
with gr.Tab(LANG["TAB_5_TITLE"]):
|
| 584 |
demo_gender.render()
|
| 585 |
-
demo_age.render()
|
| 586 |
with gr.Row():
|
| 587 |
demo_location_commune.render()
|
| 588 |
demo_location_arrond.render()
|
| 589 |
demo_parents_location.render()
|
| 590 |
with gr.Row():
|
| 591 |
-
demo_inscription.render()
|
| 592 |
-
demo_discipline.render()
|
| 593 |
with gr.Row():
|
| 594 |
demo_job.render()
|
| 595 |
demo_income.render()
|
|
@@ -612,7 +659,7 @@ with gr.Blocks(title=LANG["TITLE"], css=".gradio-container { max-width: 1200px;
|
|
| 612 |
# =================================================================
|
| 613 |
with gr.Tab(LANG["TAB_7_TITLE"]):
|
| 614 |
gr.Markdown("### Finalisation du Questionnaire")
|
| 615 |
-
gr.Markdown("Vérifiez que toutes vos réponses sont complètes avant de soumettre. Une fois soumis, le fichier CSV
|
| 616 |
|
| 617 |
with gr.Row():
|
| 618 |
submit_btn.render()
|
|
|
|
| 3 |
import os
|
| 4 |
import time
|
| 5 |
from typing import List, Union, Dict, Any, Tuple
|
| 6 |
+
from datetime import datetime
|
| 7 |
|
| 8 |
# =================================================================
|
| 9 |
# CONFIGURATION AND LANGUAGE DEFINITIONS
|
| 10 |
# =================================================================
|
| 11 |
|
| 12 |
+
# Setting EXPECTED_DATA_COUNT based on the final verified structure: 90
|
| 13 |
+
EXPECTED_DATA_COUNT = 90
|
| 14 |
+
EXPECTED_COUNT = 90
|
| 15 |
|
| 16 |
# --- Shared Choices (French Only) ---
|
| 17 |
FREQ_FR = ["Jamais", "Rarement", "Parfois", "Souvent"]
|
|
|
|
| 53 |
"autre réaction"
|
| 54 |
]
|
| 55 |
|
| 56 |
+
ENGAGE1_CHOICES = [
|
| 57 |
+
"non",
|
| 58 |
+
"en tant que sympathisant",
|
| 59 |
+
"comme donateur-rice",
|
| 60 |
+
"en tant que bénévole",
|
| 61 |
+
"comme participant·e/spectateur-rice",
|
| 62 |
+
"comme organisateur-rice/responsable"
|
| 63 |
+
]
|
| 64 |
+
|
| 65 |
+
ENGAGE2_CHOICES = [
|
| 66 |
+
"une association",
|
| 67 |
+
"un collectif",
|
| 68 |
+
"une ONG",
|
| 69 |
+
"un parti politique",
|
| 70 |
+
"un syndicat étudiant",
|
| 71 |
+
"une assemblée ou une instance représentative (collectivité, communes…)",
|
| 72 |
+
"autre (préciser)",
|
| 73 |
+
"aucune de ces formes"
|
| 74 |
+
]
|
| 75 |
+
|
| 76 |
+
# FIX: Nouvelles listes pour DEMO_INSCRIPTION et DEMO_DISCIPLINE
|
| 77 |
+
DEMO_INSCRIPTION_CHOICES = ["L1", "L2", "L3", "M1", "M2", "D", "DU", "autre niveau d’étude/diplôme"]
|
| 78 |
+
DEMO_DISCIPLINE_CHOICES = [
|
| 79 |
+
"Cinéma", "Communication", "Langues", "LEA", "Lettres", "Médiation", "Musique",
|
| 80 |
+
"Sciences du langage", "Théâtre", "Traduction", "Autres"
|
| 81 |
+
]
|
| 82 |
+
|
| 83 |
|
| 84 |
# --- Language Definitions (French Only) ---
|
| 85 |
LANG_FR = {
|
|
|
|
| 96 |
"SPACE1_LABEL": "SPACE1 - Fréquentes-tu des lieux culturels (au sens large, y compris alternatifs, non institutionnels) ?",
|
| 97 |
"SPACE2A_TITLE": "Derniers lieux culturels fréquentés (3 max. - si Rarement/Parfois/Souvent)",
|
| 98 |
"SPACE2B_LABEL": "SPACE2b (si “jamais”) - Pourquoi ne fréquentes-tu jamais de lieux culturels ? (plusieurs réponses possibles)",
|
|
|
|
|
|
|
| 99 |
"SPACE3_TITLE": "SPACE4 - Pourrais-tu qualifier ces lieux ?",
|
| 100 |
"SPACE3_QUAL_1": "Lieu 1 : Alternatif/Underground (1) à Institutionnel/Mainstream (10)",
|
| 101 |
"SPACE3_QUAL_2": "Lieu 2 : Alternatif (1) à Institutionnel (10)",
|
| 102 |
"SPACE3_QUAL_3": "Lieu 3 : Alternatif (1) à Institutionnel (10)",
|
|
|
|
|
|
|
| 103 |
"SPACE4_LABEL": "SPACE4_bis - Est-ce que tu suis régulièrement une communauté alternative en ligne (médias sociaux, newsletter, groupe dédié...)",
|
| 104 |
"SPACE5_LABEL": "SPACE5 - Peux-tu indiquer son nom ou son url ? (si SPACE4_bis=oui)",
|
| 105 |
"SPACE6_LABEL": "SPACE6 - As-tu connaissance de pratiques d’engagement citoyen dans ces lieux ?",
|
|
|
|
| 107 |
"SPACE_DOMAIN_LABEL": "Peux-tu caractériser le domaine dans lequel s’inscrit principalement cette pratique ?",
|
| 108 |
"SPACE11_LABEL": "SPACE11 - Sais-tu si elle s’appuie sur une communauté en ligne et l’usage d’un média social en ligne ?",
|
| 109 |
"SPACE2B_OPTIONS": ["Pas le temps", "Trop cher", "Je ne sais pas où aller", "Pas intéressé", "Autre"],
|
| 110 |
+
"ENGAGE1_LABEL": "ENGAGE1 - Toi-même, participes-tu à des pratiques d’engagement citoyen ?",
|
| 111 |
"ENGAGEMENT_ORGANISATION_LABEL": "ENGAGE2 - Dans quelle(s) organisation(s) es-tu engagé·e ?",
|
| 112 |
+
"ENGAGE2_AUTRE_DETAIL_LABEL": "ENGAGE2 - Précisez 'autre'",
|
| 113 |
"ENGAGEMENT_DOMAINE_LABEL": "ENGAGE3 - Dans quel domaine ? (Si engagé·e)",
|
| 114 |
"INFO_ACTIVITES_LABEL": "ENGAGE4 - Participes-tu ou as-tu participé à une ou plusieurs des activités suivantes ?",
|
| 115 |
"INFO_RESEAUX_SOCIAUX_LABEL": "ENGAGE5 - Utilises-tu les réseaux sociaux pour t’engager dans des causes ?",
|
|
|
|
| 128 |
"PLATFORM_TITLE": "DIGITAL1 - Quelles plateformes utilises-tu le plus ? (Heures/jour approx.)",
|
| 129 |
"PURPOSE_TITLE": "DIGITAL2 - Pour quel(s) usage(s) emploies-tu ces plateformes ?",
|
| 130 |
"DEMO_GENDER_LABEL": "DEMO_GENDER - Ton genre :",
|
| 131 |
+
# FIX: Nouveau label pour l'âge
|
| 132 |
+
"DEMO_AGE_LABEL": "DEMO_AGE - Ton âge (années) :",
|
| 133 |
"DEMO_LOCATION_COMMUNE_LABEL": "DEMO_LOCATION - Commune de résidence habituelle :",
|
| 134 |
"DEMO_LOCATION_ARROND_LABEL": "Arrondissement (si Paris) :",
|
| 135 |
"DEMO_PARENTS_LOCATION_LABEL": "DEMO_PARENTS - Est-ce le lieu d’habitation de tes parents ?",
|
|
|
|
| 175 |
space2a_3 = gr.Textbox(label="Lieu 3", visible=False)
|
| 176 |
space2b = gr.CheckboxGroup(label=LANG["SPACE2B_LABEL"], choices=LANG["SPACE2B_OPTIONS"], visible=False)
|
| 177 |
|
|
|
|
| 178 |
space3_1 = gr.Slider(label=LANG["SPACE3_QUAL_1"], minimum=1, maximum=10, step=1, visible=False)
|
| 179 |
space3_2 = gr.Slider(label=LANG["SPACE3_QUAL_2"], minimum=1, maximum=10, step=1, visible=False)
|
| 180 |
space3_3 = gr.Slider(label=LANG["SPACE3_QUAL_3"], minimum=1, maximum=10, step=1, visible=False)
|
| 181 |
|
|
|
|
| 182 |
space4 = gr.Radio(label=LANG["SPACE4_LABEL"], choices=["Oui", "Non"])
|
| 183 |
space5 = gr.Textbox(label=LANG["SPACE5_LABEL"], visible=False)
|
| 184 |
space6 = gr.Radio(label=LANG["SPACE6_LABEL"], choices=["Oui", "Non", "Ne sait pas"])
|
|
|
|
| 194 |
space11 = gr.CheckboxGroup(label=LANG["SPACE11_LABEL"], choices=SOCIAL_MEDIA_CHOICES)
|
| 195 |
|
| 196 |
# === TAB 2 Components ===
|
| 197 |
+
engage1_role = gr.CheckboxGroup(label=LANG["ENGAGE1_LABEL"], choices=ENGAGE1_CHOICES)
|
| 198 |
+
engage2_type = gr.CheckboxGroup(label=LANG["ENGAGEMENT_ORGANISATION_LABEL"], choices=ENGAGE2_CHOICES)
|
| 199 |
+
engage2_autre_detail = gr.Textbox(label=LANG["ENGAGE2_AUTRE_DETAIL_LABEL"], visible=False)
|
| 200 |
engagement_domaine = gr.Textbox(label=LANG["ENGAGEMENT_DOMAINE_LABEL"], placeholder="Domaine de l'engagement...")
|
| 201 |
info_activites = gr.CheckboxGroup(label=LANG["INFO_ACTIVITES_LABEL"], choices=["Participer à une manifestation/grève", "Contacter un élu", "Signer une pétition en ligne", "Boycotter un produit/marque", "Faire un don à une association", "Autre"], interactive=True)
|
| 202 |
info_reseaux_sociaux = gr.Radio(label=LANG["INFO_RESEAUX_SOCIAUX_LABEL"], choices=["Oui", "Non", "Parfois"])
|
|
|
|
| 249 |
purpose_social, purpose_professionnel, purpose_autre_freq) = purpose_components
|
| 250 |
|
| 251 |
|
| 252 |
+
# === TAB 5 Components (Mises à jour) ===
|
| 253 |
demo_gender = gr.Radio(label=LANG["DEMO_GENDER_LABEL"], choices=["Homme", "Femme", "Non-binaire", "Préfère ne pas dire"])
|
| 254 |
+
# FIX: Changement en Number
|
| 255 |
+
demo_age = gr.Number(label=LANG["DEMO_AGE_LABEL"], minimum=18, maximum=100, step=1, placeholder="ex: 25")
|
| 256 |
demo_location_commune = gr.Textbox(label=LANG["DEMO_LOCATION_COMMUNE_LABEL"], placeholder="Nom de la commune")
|
| 257 |
demo_location_arrond = gr.Textbox(label=LANG["DEMO_LOCATION_ARROND_LABEL"], placeholder="ex: 75005")
|
| 258 |
demo_parents_location = gr.Radio(label=LANG["DEMO_PARENTS_LOCATION_LABEL"], choices=["Oui", "Non"])
|
| 259 |
+
# FIX: Changement en CheckboxGroup
|
| 260 |
+
demo_inscription = gr.CheckboxGroup(label=LANG["DEMO_INSCRIPTION_LABEL"], choices=DEMO_INSCRIPTION_CHOICES)
|
| 261 |
+
# FIX: Changement en CheckboxGroup
|
| 262 |
+
demo_discipline = gr.CheckboxGroup(label=LANG["DEMO_DISCIPLINE_LABEL"], choices=DEMO_DISCIPLINE_CHOICES)
|
| 263 |
demo_job = gr.Radio(label=LANG["DEMO_JOB_LABEL"], choices=["Oui", "Non"])
|
| 264 |
demo_income = gr.Radio(label=LANG["DEMO_INCOME_LABEL"], choices=INCOME_CHOICES)
|
| 265 |
demo_socialcapital1_parent1 = gr.Radio(label=LANG["DEMO_SOCIALCAPITAL1_PARENT1_LABEL"], choices=INSEE_CHOICES)
|
|
|
|
| 296 |
clean_name = "SPACE4_QUAL_2"
|
| 297 |
elif "Lieu 3 : Alternatif" in name:
|
| 298 |
clean_name = "SPACE4_QUAL_3"
|
| 299 |
+
elif clean_name == "ENGAGE2_Précisez_'autre'":
|
| 300 |
+
clean_name = "ENGAGE2_Autre_Precision"
|
| 301 |
|
| 302 |
names.append(clean_name)
|
| 303 |
else:
|
|
|
|
| 359 |
is_cited = bool(practice_text.strip())
|
| 360 |
return gr.update(visible=is_cited)
|
| 361 |
|
| 362 |
+
def update_visibility_engage2_autre(engage2_choices: List[str]):
|
| 363 |
+
return gr.update(visible="autre (préciser)" in engage2_choices)
|
| 364 |
+
|
| 365 |
def process_survey(*data_values: Any) -> Tuple[str, gr.File]:
|
| 366 |
"""
|
| 367 |
Processes survey data, creates a temporary CSV file, and returns the path
|
|
|
|
| 374 |
error_msg = f"Erreur critique: Le nombre d'entrées reçues est incorrect ({len(all_inputs_list)} au lieu de {EXPECTED_COUNT}). Veuillez contacter le développeur."
|
| 375 |
return error_msg, gr.update(visible=False, value=None)
|
| 376 |
|
|
|
|
| 377 |
language = "FR"
|
| 378 |
|
| 379 |
try:
|
| 380 |
column_names = get_column_names(DATA_INPUT_COMPONENTS)
|
| 381 |
+
column_names.insert(0, "DEMO_LANGUAGE")
|
| 382 |
|
| 383 |
data_row = [language] + all_inputs_list
|
| 384 |
|
| 385 |
df = pd.DataFrame([data_row], columns=column_names)
|
| 386 |
|
| 387 |
+
# Nommage du fichier: Enquêteur ID + Date
|
| 388 |
+
enqueteur_id_val = all_inputs_list[0]
|
| 389 |
+
current_date_str = datetime.now().strftime("%Y-%m-%d")
|
| 390 |
+
|
| 391 |
+
safe_enqueteur_id = str(enqueteur_id_val).strip()
|
| 392 |
+
safe_enqueteur_id = "".join(c if c.isalnum() else '_' for c in safe_enqueteur_id)
|
| 393 |
+
if not safe_enqueteur_id:
|
| 394 |
+
safe_enqueteur_id = "NO_ID"
|
| 395 |
+
|
| 396 |
+
temp_filename = f"/tmp/{safe_enqueteur_id}_{current_date_str}.csv"
|
| 397 |
os.makedirs(os.path.dirname(temp_filename), exist_ok=True)
|
| 398 |
df.to_csv(temp_filename, index=False, encoding='utf-8')
|
| 399 |
|
| 400 |
+
success_msg = f"✨ Succès ! Le questionnaire a été soumis. Cliquez sur le lien ci-dessous pour **Télécharger le Fichier CSV** nommé `{safe_enqueteur_id}_{current_date_str}.csv`."
|
| 401 |
|
| 402 |
return success_msg, gr.update(value=temp_filename, visible=True)
|
| 403 |
|
|
|
|
| 415 |
# TAB 1 - Contact & Lieux (22)
|
| 416 |
approach_answer, refusal_reason, refusal_reason_other, contact_later,
|
| 417 |
space1, space2a_1, space2a_2, space2a_3, space2b,
|
| 418 |
+
space3_1, space3_2, space3_3,
|
| 419 |
space4, space5,
|
| 420 |
space6,
|
| 421 |
space7_1, space_domain_1,
|
| 422 |
space7_2, space_domain_2,
|
| 423 |
space7_3, space_domain_3,
|
| 424 |
space11,
|
| 425 |
+
# TAB 2 - Engagement (6)
|
| 426 |
+
engage1_role, engage2_type, engage2_autre_detail, engagement_domaine, info_activites, info_reseaux_sociaux,
|
| 427 |
# TAB 3 - Actualité (16)
|
| 428 |
info_frequence_actu, info2, info3, info_opposite_feeling, info_contradict_opinion,
|
| 429 |
info4, info5,
|
|
|
|
| 493 |
space2a_2.render()
|
| 494 |
space2a_3.render()
|
| 495 |
|
|
|
|
| 496 |
gr.Markdown(f"#### {LANG['SPACE3_TITLE']}")
|
| 497 |
with gr.Row() as space3_row:
|
| 498 |
space3_1.render()
|
|
|
|
| 503 |
space1.change(update_visibility_space1, inputs=[space1], outputs=[space2a_1, space2a_2, space2a_3, space3_1, space3_2, space3_3, space2b])
|
| 504 |
|
| 505 |
gr.Markdown("### Usages alternatifs et Engagement")
|
| 506 |
+
space4.render()
|
| 507 |
space5.render()
|
| 508 |
space4.change(update_visibility_space4, inputs=[space4], outputs=[space5])
|
| 509 |
|
|
|
|
| 537 |
# TAB 2: Engagement Citoyen
|
| 538 |
# =================================================================
|
| 539 |
with gr.Tab(LANG["TAB_2_TITLE"]):
|
| 540 |
+
engage1_role.render()
|
| 541 |
+
engage2_type.render()
|
| 542 |
+
engage2_autre_detail.render()
|
| 543 |
engagement_domaine.render()
|
| 544 |
info_activites.render()
|
| 545 |
info_reseaux_sociaux.render()
|
| 546 |
+
|
| 547 |
+
engage2_type.change(
|
| 548 |
+
fn=update_visibility_engage2_autre,
|
| 549 |
+
inputs=[engage2_type],
|
| 550 |
+
outputs=[engage2_autre_detail]
|
| 551 |
+
)
|
| 552 |
+
|
| 553 |
|
| 554 |
# =================================================================
|
| 555 |
# TAB 3: Consommation d’actualités
|
|
|
|
| 625 |
|
| 626 |
|
| 627 |
# =================================================================
|
| 628 |
+
# TAB 5: Profil Démographique (Mise à jour Age, Inscription, Discipline)
|
| 629 |
# =================================================================
|
| 630 |
with gr.Tab(LANG["TAB_5_TITLE"]):
|
| 631 |
demo_gender.render()
|
| 632 |
+
demo_age.render() # FIX: Rendu du Number
|
| 633 |
with gr.Row():
|
| 634 |
demo_location_commune.render()
|
| 635 |
demo_location_arrond.render()
|
| 636 |
demo_parents_location.render()
|
| 637 |
with gr.Row():
|
| 638 |
+
demo_inscription.render() # FIX: Rendu du CheckboxGroup
|
| 639 |
+
demo_discipline.render() # FIX: Rendu du CheckboxGroup
|
| 640 |
with gr.Row():
|
| 641 |
demo_job.render()
|
| 642 |
demo_income.render()
|
|
|
|
| 659 |
# =================================================================
|
| 660 |
with gr.Tab(LANG["TAB_7_TITLE"]):
|
| 661 |
gr.Markdown("### Finalisation du Questionnaire")
|
| 662 |
+
gr.Markdown("Vérifiez que toutes vos réponses sont complètes avant de soumettre. Une fois soumis, le fichier CSV (nommé avec l'identifiant de l'enquêteur et la date) apparaîtra ci-dessous pour téléchargement.")
|
| 663 |
|
| 664 |
with gr.Row():
|
| 665 |
submit_btn.render()
|