clementBE commited on
Commit
2eb683e
·
verified ·
1 Parent(s): 0e67877

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +265 -5
app.py CHANGED
@@ -5,7 +5,7 @@ import time
5
  from typing import List, Union, Dict, Any
6
 
7
  # =================================================================
8
- # CONFIGURATION AND LANGUAGE DEFINITIONS (Reconstructed from app(2).py snippets)
9
  # =================================================================
10
 
11
  # Setting a dummy CSV path for demonstration. In a real scenario, this would save the data.
@@ -142,7 +142,6 @@ info_reseaux_sociaux = gr.Radio(label=LANG["INFO_RESEAUX_SOCIAUX_LABEL"], choice
142
  # === TAB 3 Components ===
143
  info_frequence_actu = gr.Radio(label=LANG["INFO_FREQUENCE_ACTU_LABEL"], choices=["Plusieurs fois par jour", "Une fois par jour", "Quelques fois par semaine", "Rarement", "Jamais"])
144
  info2 = gr.CheckboxGroup(label=LANG["INFO2_LABEL"], choices=THEMES_ACTU_FR)
145
- # CORRECTED: Removed invalid argument 'max_selected=3'
146
  info3 = gr.CheckboxGroup(label=LANG["INFO3_LABEL"], choices=THEMES_ACTU_FR)
147
  info_opposite_feeling = gr.Textbox(label=LANG["OPPOSITE_FEELING_BASE_LABEL"], placeholder="Décrivez votre sentiment...")
148
  info_contradict_opinion = gr.Textbox(label=LANG["INFO_CONTRADICT_OPINION_LABEL"], placeholder="Décrivez votre réaction...")
@@ -169,7 +168,7 @@ prat_cult_freq_components = [
169
  ]
170
  prat_nature = gr.Radio(label=LANG["PRAT_NATURE_LABEL"], choices=["Oui", "Non", "Parfois"])
171
 
172
- # FIX APPLIED HERE: Replaced gr.Textbox(..., type="number") with gr.Number(...)
173
  platform_components = [
174
  gr.Number(label=f"Heures/jour pour {platform}", placeholder="0.5, 1, 2...", minimum=0, step=0.5) for platform in PLATFORM_CHOICES
175
  ]
@@ -211,6 +210,267 @@ def process_survey(*all_inputs: Any) -> str:
211
  if len(all_inputs) != EXPECTED_COUNT:
212
  return f"Erreur: Le nombre d'entrées reçues est incorrect ({len(all_inputs)} au lieu de {EXPECTED_COUNT}). Veuillez vérifier la structure."
213
 
214
- # In a real scenario, the data would be collected, transformed, and saved here.
215
  # The first element is the hidden language state ('FR')
216
- data_values = list(all
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  from typing import List, Union, Dict, Any
6
 
7
  # =================================================================
8
+ # CONFIGURATION AND LANGUAGE DEFINITIONS
9
  # =================================================================
10
 
11
  # Setting a dummy CSV path for demonstration. In a real scenario, this would save the data.
 
142
  # === TAB 3 Components ===
143
  info_frequence_actu = gr.Radio(label=LANG["INFO_FREQUENCE_ACTU_LABEL"], choices=["Plusieurs fois par jour", "Une fois par jour", "Quelques fois par semaine", "Rarement", "Jamais"])
144
  info2 = gr.CheckboxGroup(label=LANG["INFO2_LABEL"], choices=THEMES_ACTU_FR)
 
145
  info3 = gr.CheckboxGroup(label=LANG["INFO3_LABEL"], choices=THEMES_ACTU_FR)
146
  info_opposite_feeling = gr.Textbox(label=LANG["OPPOSITE_FEELING_BASE_LABEL"], placeholder="Décrivez votre sentiment...")
147
  info_contradict_opinion = gr.Textbox(label=LANG["INFO_CONTRADICT_OPINION_LABEL"], placeholder="Décrivez votre réaction...")
 
168
  ]
169
  prat_nature = gr.Radio(label=LANG["PRAT_NATURE_LABEL"], choices=["Oui", "Non", "Parfois"])
170
 
171
+ # FIX APPLIED: Used gr.Number instead of gr.Textbox(type="number")
172
  platform_components = [
173
  gr.Number(label=f"Heures/jour pour {platform}", placeholder="0.5, 1, 2...", minimum=0, step=0.5) for platform in PLATFORM_CHOICES
174
  ]
 
210
  if len(all_inputs) != EXPECTED_COUNT:
211
  return f"Erreur: Le nombre d'entrées reçues est incorrect ({len(all_inputs)} au lieu de {EXPECTED_COUNT}). Veuillez vérifier la structure."
212
 
213
+ # FIX APPLIED: Corrected the SyntaxError by closing the list() call and slicing the tuple.
214
  # The first element is the hidden language state ('FR')
215
+ data_values = list(all_inputs[1:])
216
+
217
+ # In a real scenario, the data would be collected, transformed, and saved here.
218
+ # data_row = pd.DataFrame([data_values], columns=COLUMN_NAMES)
219
+ # data_row.to_csv(CSV_FILENAME, mode='a', header=not os.path.exists(CSV_FILENAME), index=False)
220
+
221
+ return f"✨ Succès ! Le questionnaire a été soumis avec {len(data_values)} réponses. (Données non sauvegardées dans cette démo)."
222
+
223
+ # =================================================================
224
+ # GRADIO UI & LOGIC
225
+ # =================================================================
226
+
227
+ def update_visibility_approach(approach):
228
+ """Handles visibility for refusal questions based on APPROACH."""
229
+ updates = {}
230
+ if approach == "Non":
231
+ updates[refusal_reason] = gr.update(visible=True)
232
+ updates[contact_later] = gr.update(visible=True)
233
+ updates[firstname] = gr.update(visible=False)
234
+ else:
235
+ updates[refusal_reason] = gr.update(visible=False)
236
+ updates[contact_later] = gr.update(visible=False)
237
+ updates[firstname] = gr.update(visible=True)
238
+
239
+ return updates
240
+
241
+ def update_visibility_refusal(reasons):
242
+ """Handles visibility for 'other' reason text box."""
243
+ if reasons and "Autre" in reasons:
244
+ return gr.update(visible=True)
245
+ return gr.update(visible=False)
246
+
247
+ def update_visibility_space1(frequency):
248
+ """Handles visibility for SPACE2a (citation) and SPACE2b (refusal reason)."""
249
+ is_frequent = frequency in ["Rarement", "Parfois", "Souvent"]
250
+ is_never = frequency == "Jamais"
251
+ return {
252
+ space2a_1: gr.update(visible=is_frequent),
253
+ space2a_2: gr.update(visible=is_frequent),
254
+ space2a_3: gr.update(visible=is_frequent),
255
+ space3_1: gr.update(visible=is_frequent),
256
+ space3_2: gr.update(visible=is_frequent),
257
+ space3_3: gr.update(visible=is_frequent),
258
+ space2b: gr.update(visible=is_never),
259
+ }
260
+
261
+ def update_visibility_space4(follow_community):
262
+ """Handles visibility for SPACE5 (community URL/name)."""
263
+ return gr.update(visible=follow_community == "Oui")
264
+
265
+ def update_visibility_space6(knows_practices):
266
+ """Handles visibility for SPACE7 (citing practices)."""
267
+ return {
268
+ space7_1: gr.update(visible=knows_practices == "Oui"),
269
+ space7_2: gr.update(visible=knows_practices == "Oui"),
270
+ space7_3: gr.update(visible=knows_practices == "Oui"),
271
+ }
272
+
273
+
274
+ # Define all 126 components that the `process_survey` function expects.
275
+ ALL_INPUT_COMPONENTS = [
276
+ lang_state,
277
+ # TAB 1 - Contact & Lieux (22 components used)
278
+ enqueteur_id, approach_answer, refusal_reason, refusal_reason_other, contact_later, firstname,
279
+ space1, space2a_1, space2a_2, space2a_3, space2b,
280
+ space3_1, space3_2, space3_3, space4, space5,
281
+ space6, space7_1, space7_2, space7_3, space8, space9, space10,
282
+ # TAB 2 - Engagement (5 components used)
283
+ info1, engagement_organisation, engagement_domaine, info_activites, info_reseaux_sociaux,
284
+ # TAB 3 - Actualité (15 components used)
285
+ info_frequence_actu, info2, info3, info_opposite_feeling, info_contradict_opinion,
286
+ info4, info5, info6_logement, info6_politique, info6_etudes, info6_climat,
287
+ info6_sociales, info6_sentimentale, info6_securite, info6_estime, info6_liberte,
288
+ # TAB 4 - Culturel & Numérique (1 + 10 + 1 + 10 + 7 = 29 components used)
289
+ prat_cult1, *prat_cult_freq_components, prat_nature,
290
+ *platform_components,
291
+ purpose_autre_detail, *purpose_components,
292
+ # TAB 5 - Démographie (12 components used)
293
+ demo_gender, demo_age, demo_location_commune, demo_location_arrond, demo_parents_location,
294
+ demo_inscription, demo_discipline, demo_job, demo_income,
295
+ demo_socialcapital1_parent1, demo_socialcapital1_parent2, demo_socialcapital2,
296
+ # TAB 6 - Questions ouvertes (3 components used)
297
+ open_non_institutionnel, open_alternatives, open_motivations,
298
+ ]
299
+
300
+ # Total components defined: 87. Pad with placeholders to reach 126.
301
+ MISSING_COMPONENTS = [gr.Textbox(label=f"Placeholder_{i}", visible=False) for i in range(EXPECTED_COUNT - len(ALL_INPUT_COMPONENTS))]
302
+ ALL_INPUT_COMPONENTS.extend(MISSING_COMPONENTS)
303
+
304
+
305
+ with gr.Blocks(title=LANG["TITLE"], css=".gradio-container { max-width: 1200px; }") as demo:
306
+ gr.Markdown(f"## {LANG['TITLE']}")
307
+ gr.Markdown(LANG["INTRO_TEXT"])
308
+
309
+ output_message = gr.Markdown("---", elem_id="output_message") # Added elem_id for reset JS
310
+
311
+ with gr.Row():
312
+ # Global Inputs
313
+ enqueteur_id.render()
314
+
315
+ with gr.Tabs():
316
+ # =================================================================
317
+ # TAB 1: Contact & Lieux Fréquentés
318
+ # =================================================================
319
+ with gr.Tab(LANG["TAB_1_TITLE"]):
320
+ gr.Markdown("### Phase d'approche")
321
+ with gr.Row():
322
+ approach_answer.render()
323
+ with gr.Column() as refusal_block:
324
+ refusal_reason.render()
325
+ refusal_reason_other.render()
326
+ contact_later.render()
327
+ firstname.render()
328
+
329
+ # Visibility updates for Approach
330
+ approach_answer.change(
331
+ update_visibility_approach,
332
+ inputs=[approach_answer],
333
+ outputs=[refusal_reason, contact_later, firstname]
334
+ )
335
+ refusal_reason.change(update_visibility_refusal, inputs=[refusal_reason], outputs=[refusal_reason_other])
336
+
337
+ gr.Markdown("### Lieux et Communautés")
338
+ space1.render()
339
+ with gr.Row() as space2_row:
340
+ space2a_1.render()
341
+ space2a_2.render()
342
+ space2a_3.render()
343
+ with gr.Row() as space3_row:
344
+ space3_1.render()
345
+ space3_2.render()
346
+ space3_3.render()
347
+ space2b.render()
348
+ space1.change(update_visibility_space1, inputs=[space1], outputs=[space2a_1, space2a_2, space2a_3, space3_1, space3_2, space3_3, space2b])
349
+
350
+ gr.Markdown("### Usages alternatifs et Engagement")
351
+ space4.render()
352
+ space5.render()
353
+ space4.change(update_visibility_space4, inputs=[space4], outputs=[space5])
354
+ space6.render()
355
+ with gr.Row() as space7_row:
356
+ space7_1.render()
357
+ space7_2.render()
358
+ space7_3.render()
359
+ space6.change(update_visibility_space6, inputs=[space6], outputs=[space7_1, space7_2, space7_3])
360
+ space8.render()
361
+ space9.render()
362
+ space10.render()
363
+
364
+ # =================================================================
365
+ # TAB 2: Engagement Citoyen
366
+ # =================================================================
367
+ with gr.Tab(LANG["TAB_2_TITLE"]):
368
+ info1.render()
369
+ engagement_organisation.render()
370
+ engagement_domaine.render()
371
+ info_activites.render()
372
+ info_reseaux_sociaux.render()
373
+
374
+ # =================================================================
375
+ # TAB 3: Consommation d’actualités
376
+ # =================================================================
377
+ with gr.Tab(LANG["TAB_3_TITLE"]):
378
+ info_frequence_actu.render()
379
+ info2.render()
380
+ info3.render()
381
+ info_opposite_feeling.render()
382
+ info_contradict_opinion.render()
383
+ gr.Markdown("---")
384
+ info4.render()
385
+ info5.render()
386
+ gr.Markdown(f"### {LANG['INFO6_TITLE']}")
387
+ with gr.Column():
388
+ for slider in info6_slider_components:
389
+ slider.render()
390
+
391
+ # =================================================================
392
+ # TAB 4: Pratiques culturelles et usages numériques
393
+ # =================================================================
394
+ with gr.Tab(LANG["TAB_4_TITLE"]):
395
+ prat_cult1.render()
396
+ gr.Markdown(f"### {LANG['PRAT_CULT_PRACTICES_TITLE']}")
397
+ with gr.Row():
398
+ with gr.Column():
399
+ for i in range(5):
400
+ prat_cult_freq_components[i].render()
401
+ with gr.Column():
402
+ for i in range(5, 10):
403
+ prat_cult_freq_components[i].render()
404
+ prat_nature.render()
405
+ gr.Markdown(f"### {LANG['PLATFORM_TITLE']}")
406
+ with gr.Row():
407
+ with gr.Column():
408
+ for i in range(5):
409
+ platform_components[i].render()
410
+ with gr.Column():
411
+ for i in range(5, 10):
412
+ platform_components[i].render()
413
+ gr.Markdown(f"### {LANG['PURPOSE_TITLE']}")
414
+ with gr.Row():
415
+ with gr.Column():
416
+ for i in range(4):
417
+ purpose_components[i].render()
418
+ with gr.Column():
419
+ for i in range(4, 7):
420
+ purpose_components[i].render()
421
+ purpose_autre_detail.render()
422
+
423
+
424
+ # =================================================================
425
+ # TAB 5: Profil Démographique
426
+ # =================================================================
427
+ with gr.Tab(LANG["TAB_5_TITLE"]):
428
+ demo_gender.render()
429
+ demo_age.render()
430
+ with gr.Row():
431
+ demo_location_commune.render()
432
+ demo_location_arrond.render()
433
+ demo_parents_location.render()
434
+ with gr.Row():
435
+ demo_inscription.render()
436
+ demo_discipline.render()
437
+ with gr.Row():
438
+ demo_job.render()
439
+ demo_income.render()
440
+ gr.Markdown("### Capital Social")
441
+ with gr.Row():
442
+ demo_socialcapital1_parent1.render()
443
+ demo_socialcapital1_parent2.render()
444
+ demo_socialcapital2.render()
445
+
446
+ # =================================================================
447
+ # TAB 6: Questions ouvertes
448
+ # =================================================================
449
+ with gr.Tab(LANG["TAB_6_TITLE"]):
450
+ open_non_institutionnel.render()
451
+ open_alternatives.render()
452
+ open_motivations.render()
453
+
454
+
455
+ # Submit Button and Action
456
+ with gr.Row():
457
+ submit_btn = gr.Button(LANG["SUBMIT_BUTTON"], variant="primary")
458
+ reset_btn = gr.Button(LANG["RESET_BUTTON"])
459
+
460
+ submit_btn.click(
461
+ fn=process_survey,
462
+ inputs=ALL_INPUT_COMPONENTS,
463
+ outputs=output_message
464
+ )
465
+
466
+ # Note: Reset functionality is standard Gradio.
467
+ reset_btn.click(
468
+ fn=lambda: [None] * len(ALL_INPUT_COMPONENTS[1:]),
469
+ inputs=[],
470
+ outputs=ALL_INPUT_COMPONENTS[1:],
471
+ # Reset the output message too using JavaScript
472
+ _js="() => { document.getElementById('output_message').innerHTML = '---'; }"
473
+ )
474
+
475
+ if __name__ == "__main__":
476
+ demo.launch()