GuglielmoTor commited on
Commit
84a0a22
·
verified ·
1 Parent(s): 9a76dec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -79
app.py CHANGED
@@ -196,12 +196,15 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
196
  logging.error(f"Config not found for plot_id {plot_id_clicked}")
197
  # Ensure this error return matches the expected number of outputs
198
  num_plots = len(plot_configs)
199
- error_list = [gr.update(visible=False)] * 10 # Base action panel UI elements (incl. new hint)
200
- error_list.extend([current_active_action_from_state, current_chat_plot_id, current_chat_histories, current_explored_plot_id]) # States
201
- error_list.extend([gr.update()] * num_plots) # Panel visibilities
202
- error_list.extend([gr.update()] * (2 * num_plots)) # Bomb, Formula icons
203
- error_list.extend([gr.update()] * num_plots) # Explore icons
204
- error_list.extend([gr.update()] * num_unique_sections) # Section title visibilities
 
 
 
205
  return error_list
206
 
207
  clicked_plot_label = clicked_plot_config["label"]
@@ -212,7 +215,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
212
  action_col_visible_update = gr.update(visible=False)
213
  insights_chatbot_visible_update, insights_chat_input_visible_update, insights_suggestions_row_visible_update = gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
214
  formula_display_visible_update = gr.update(visible=False)
215
- formula_close_hint_visible_update = gr.update(visible=False) # NEW: Default to hidden
216
  chatbot_content_update, s1_upd, s2_upd, s3_upd, formula_content_update = gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
217
 
218
  new_active_action_state_to_set, new_current_chat_plot_id = None, current_chat_plot_id
@@ -223,10 +226,9 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
223
 
224
  if is_toggling_off:
225
  new_active_action_state_to_set = None
226
- action_col_visible_update = gr.update(visible=False) # Hide the whole right panel
227
- # formula_close_hint_visible_update is already set to hidden by default
228
  logging.info(f"Toggling OFF panel {action_type} for {plot_id_clicked}.")
229
- if current_explored_plot_id: # If an explore view was active, restore it
230
  explored_cfg = next((p for p in plot_configs if p["id"] == current_explored_plot_id), None)
231
  explored_sec = explored_cfg["section"] if explored_cfg else None
232
  for i, sec_name in enumerate(unique_ordered_sections):
@@ -235,28 +237,28 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
235
  is_exp = (cfg["id"] == current_explored_plot_id)
236
  panel_vis_updates.append(gr.update(visible=is_exp))
237
  explore_btn_updates.append(gr.update(value=ACTIVE_ICON if is_exp else EXPLORE_ICON))
238
- else: # No explore active, make all plots and sections visible
239
  for i in range(num_unique_sections): section_title_vis_updates[i] = gr.update(visible=True)
240
  for _ in plot_configs:
241
  panel_vis_updates.append(gr.update(visible=True))
242
  explore_btn_updates.append(gr.update(value=EXPLORE_ICON))
243
- for _ in plot_configs: # Reset bomb/formula icons
244
  action_btn_updates.extend([gr.update(value=BOMB_ICON), gr.update(value=FORMULA_ICON)])
245
  if action_type == "insights": new_current_chat_plot_id = None
246
 
247
- else: # Opening a new panel or switching to a different one
248
  new_active_action_state_to_set = hypothetical_new_active_state
249
- action_col_visible_update = gr.update(visible=True) # Show the right panel
250
- new_explored_plot_id_to_set = None # Cancel any active explore view
251
  logging.info(f"Toggling ON panel {action_type} for {plot_id_clicked}. Cancelling explore view.")
252
 
253
- for i, sec_name in enumerate(unique_ordered_sections): # Show only relevant section title
254
  section_title_vis_updates[i] = gr.update(visible=(sec_name == clicked_plot_section))
255
- for cfg in plot_configs: # Show only relevant plot panel
256
  panel_vis_updates.append(gr.update(visible=(cfg["id"] == plot_id_clicked)))
257
- explore_btn_updates.append(gr.update(value=EXPLORE_ICON)) # Reset all explore buttons
258
 
259
- for cfg_btn in plot_configs: # Set active icons for bomb/formula
260
  is_act_ins = new_active_action_state_to_set == {"plot_id": cfg_btn["id"], "type": "insights"}
261
  is_act_for = new_active_action_state_to_set == {"plot_id": cfg_btn["id"], "type": "formula"}
262
  action_btn_updates.extend([gr.update(value=ACTIVE_ICON if is_act_ins else BOMB_ICON),
@@ -277,7 +279,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
277
  s1_upd,s2_upd,s3_upd = gr.update(value=sugg[0] if sugg else "N/A"),gr.update(value=sugg[1] if len(sugg)>1 else "N/A"),gr.update(value=sugg[2] if len(sugg)>2 else "N/A")
278
  elif action_type == "formula":
279
  formula_display_visible_update = gr.update(visible=True)
280
- formula_close_hint_visible_update = gr.update(visible=True) # NEW: Show hint
281
  f_key = PLOT_ID_TO_FORMULA_KEY_MAP.get(plot_id_clicked)
282
  f_text = f"**Formula/Methodology for: {clicked_plot_label}** (ID: `{plot_id_clicked}`)\n\n"
283
  if f_key and f_key in PLOT_FORMULAS:
@@ -291,14 +293,16 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
291
  action_col_visible_update, insights_chatbot_visible_update, chatbot_content_update,
292
  insights_chat_input_visible_update, insights_suggestions_row_visible_update,
293
  s1_upd, s2_upd, s3_upd, formula_display_visible_update, formula_content_update,
294
- formula_close_hint_visible_update, # NEW
295
  new_active_action_state_to_set, new_current_chat_plot_id, updated_chat_histories,
296
  new_explored_plot_id_to_set
297
  ]
298
  final_updates.extend(panel_vis_updates)
299
- final_updates.extend(action_btn_updates)
300
- final_updates.extend(explore_btn_updates)
301
  final_updates.extend(section_title_vis_updates)
 
 
302
  return final_updates
303
 
304
  async def handle_chat_message_submission(user_message: str, current_plot_id: str, chat_histories: dict, current_plot_data_for_chatbot: dict ):
@@ -323,16 +327,20 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
323
  num_plots = len(plot_configs)
324
  if not plot_ui_objects:
325
  logging.error("plot_ui_objects not populated for handle_explore_click.")
326
- # Match expected outputs: states (3) + panels (N) + explore_btns (N) + bomb_btns (N) + formula_btns (N) + section_titles (M) + formula_hint (1)
327
- err_list = [current_explored_plot_id_from_state, gr.update(visible=False), current_active_panel_action_state]
328
- err_list.extend([gr.update()] * (num_plots * 4 + num_unique_sections + 1) )
329
- return err_list
 
 
 
 
330
 
331
  new_explored_id_to_set, is_toggling_off_explore = None, (plot_id_clicked == current_explored_plot_id_from_state)
332
  action_col_upd, new_active_panel_state_upd = gr.update(), current_active_panel_action_state
333
  panel_vis, explore_btns, bomb_btns, formula_btns = [], [], [], []
334
  section_title_vis = [gr.update()] * num_unique_sections
335
- formula_hint_upd = gr.update(visible=False) # Hide formula hint when exploring
336
 
337
  clicked_cfg = next((p for p in plot_configs if p["id"] == plot_id_clicked), None)
338
  sec_of_clicked = clicked_cfg["section"] if clicked_cfg else None
@@ -343,48 +351,65 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
343
  for i in range(num_unique_sections): section_title_vis[i] = gr.update(visible=True)
344
  for _ in plot_configs:
345
  panel_vis.append(gr.update(visible=True)); explore_btns.append(gr.update(value=EXPLORE_ICON))
346
- bomb_btns.append(gr.update()); formula_btns.append(gr.update()) # No change to these unless panel was active
347
  else:
348
  new_explored_id_to_set = plot_id_clicked
349
  logging.info(f"Exploring {plot_id_clicked}. Hiding other plots/sections.")
350
  for i, sec_name in enumerate(unique_ordered_sections): section_title_vis[i] = gr.update(visible=(sec_name == sec_of_clicked))
351
- for cfg in plot_configs:
352
  is_target = (cfg["id"] == new_explored_id_to_set)
353
- panel_vis.append(gr.update(visible=is_target)); explore_btns.append(gr.update(value=ACTIVE_ICON if is_target else EXPLORE_ICON))
354
- if current_active_panel_action_state: # Close insight/formula if explore is activated
 
 
 
 
 
 
355
  logging.info("Closing active insight/formula panel due to explore click.")
356
  action_col_upd = gr.update(visible=False); new_active_panel_state_upd = None
357
- for _ in plot_configs: bomb_btns.extend([gr.update(value=BOMB_ICON), gr.update(value=FORMULA_ICON)])
 
 
358
  else:
359
- for _ in plot_configs: bomb_btns.append(gr.update()); formula_btns.append(gr.update())
 
 
360
 
 
 
361
  return [new_explored_id_to_set, action_col_upd, new_active_panel_state_upd, formula_hint_upd] + \
362
  panel_vis + explore_btns + bomb_btns + formula_btns + section_title_vis
363
 
364
  # --- Define Output Lists for Event Handlers ---
 
365
  _base_action_panel_ui_outputs = [
366
  global_actions_column_ui, insights_chatbot_ui, insights_chatbot_ui,
367
  insights_chat_input_ui, insights_suggestions_row_ui,
368
  insights_suggestion_1_btn, insights_suggestion_2_btn, insights_suggestion_3_btn,
369
- formula_display_markdown_ui, formula_display_markdown_ui,
370
- formula_close_hint_md # NEW
371
  ]
 
372
  _action_panel_state_outputs = [active_panel_action_state, current_chat_plot_id_st, chat_histories_st, explored_plot_id_state]
373
 
374
- action_panel_outputs_list = _base_action_panel_ui_outputs + _action_panel_state_outputs
375
- action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("panel_component", gr.update()) for pc in plot_configs]) # Panel vis
376
- action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("bomb_button", gr.update()) for pc in plot_configs]) # Bomb icon
377
- action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("formula_button", gr.update()) for pc in plot_configs]) # Formula icon
378
- action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("explore_button", gr.update()) for pc in plot_configs]) # Explore icon
379
- action_panel_outputs_list.extend([section_titles_map.get(s_name, gr.update()) for s_name in unique_ordered_sections]) # Section Titles
380
-
381
- _explore_state_outputs = [explored_plot_id_state, global_actions_column_ui, active_panel_action_state, formula_close_hint_md] # NEW: add hint to explore outputs
382
- explore_outputs_list = _explore_state_outputs
383
- explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("panel_component", gr.update()) for pc in plot_configs])
384
- explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("explore_button", gr.update()) for pc in plot_configs])
385
- explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("bomb_button", gr.update()) for pc in plot_configs])
386
- explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("formula_button", gr.update()) for pc in plot_configs])
387
- explore_outputs_list.extend([section_titles_map.get(s_name, gr.update()) for s_name in unique_ordered_sections])
 
 
 
388
 
389
  action_click_inputs = [active_panel_action_state, chat_histories_st, current_chat_plot_id_st, plot_data_for_chatbot_st, explored_plot_id_state]
390
  explore_click_inputs = [explored_plot_id_state, active_panel_action_state]
@@ -416,46 +441,47 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
416
  plot_gen_results = update_analytics_plots_figures(current_token_state, date_filter_val, custom_start_val, custom_end_val, plot_configs)
417
  status_msg, gen_figs, new_summaries = plot_gen_results[0], plot_gen_results[1:-1], plot_gen_results[-1]
418
 
419
- all_updates = [status_msg]
420
- all_updates.extend(gen_figs if len(gen_figs) == len(plot_configs) else [create_placeholder_plot("Error", f"Fig missing {i}") for i in range(len(plot_configs))])
 
 
 
 
 
 
 
 
 
 
 
421
 
422
- all_updates.extend([ # Reset action panel UI (11 elements including new hint)
423
- gr.update(visible=False), gr.update(value=[], visible=False), gr.update(value="", visible=False),
424
- gr.update(visible=False), gr.update(value="S1"), gr.update(value="S2"), gr.update(value="S3"),
425
- gr.update(value="Formula details here.", visible=False), gr.update(visible=False), # Formula MD and Hint MD
426
- None, None, {}, new_summaries # Reset states (4 elements)
427
- ]) # Total 11 + 4 = 15 here
428
- for _ in plot_configs: # Reset button icons & panel visibility (4 per plot)
429
- all_updates.extend([gr.update(value=BOMB_ICON), gr.update(value=FORMULA_ICON), gr.update(value=EXPLORE_ICON), gr.update(visible=True)])
430
  all_updates.append(None) # Reset explored_plot_id_state (1 element)
431
- all_updates.extend([gr.update(visible=True)] * num_unique_sections) # Make all section titles visible (M elements)
 
432
  logging.info(f"Prepared {len(all_updates)} updates for analytics refresh.")
433
  return all_updates
434
 
435
- apply_filter_and_sync_outputs_list = [analytics_status_md] # Status (1)
436
- apply_filter_and_sync_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("plot_component", gr.update()) for pc in plot_configs]) # Plot figures (N)
437
- apply_filter_and_sync_outputs_list.extend([ # Action panel UI reset (11 elements)
438
- global_actions_column_ui, insights_chatbot_ui, insights_chat_input_ui,
439
- insights_suggestions_row_ui, insights_suggestion_1_btn, insights_suggestion_2_btn, insights_suggestion_3_btn,
440
- formula_display_markdown_ui, formula_close_hint_md, # Added hint
441
- active_panel_action_state, current_chat_plot_id_st, chat_histories_st, plot_data_for_chatbot_st # States (4) -> total 11+4 = 15 for this block
442
- ]) # This was 12, now 13 with hint. State resets are separate. Let's be precise.
443
- # Action Panel UI (9) + Formula MD (1) + Hint MD (1) = 11
444
- # States (4) = active_panel_action_state, current_chat_plot_id_st, chat_histories_st, plot_data_for_chatbot_st
445
- # So, 11 UI + 4 states = 15 elements.
446
 
447
- # Corrected block for apply_filter_outputs:
448
  _ui_resets_for_filter = [
449
  global_actions_column_ui, insights_chatbot_ui, insights_chat_input_ui,
450
  insights_suggestions_row_ui, insights_suggestion_1_btn, insights_suggestion_2_btn, insights_suggestion_3_btn,
451
- formula_display_markdown_ui, formula_close_hint_md # 9 elements
452
  ]
453
- _state_resets_for_filter = [active_panel_action_state, current_chat_plot_id_st, chat_histories_st, plot_data_for_chatbot_st] # 4 elements
454
-
455
  apply_filter_and_sync_outputs_list.extend(_ui_resets_for_filter)
 
 
 
456
  apply_filter_and_sync_outputs_list.extend(_state_resets_for_filter)
457
 
458
- for pc in plot_configs: # Button icons (3) and panel visibility (1) = 4 per plot
 
459
  pid = pc["id"]
460
  apply_filter_and_sync_outputs_list.extend([
461
  plot_ui_objects.get(pid, {}).get("bomb_button", gr.update()),
@@ -463,8 +489,14 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
463
  plot_ui_objects.get(pid, {}).get("explore_button", gr.update()),
464
  plot_ui_objects.get(pid, {}).get("panel_component", gr.update())
465
  ])
466
- apply_filter_and_sync_outputs_list.append(explored_plot_id_state) # Reset explored state (1)
467
- apply_filter_and_sync_outputs_list.extend([section_titles_map.get(s_name, gr.update()) for s_name in unique_ordered_sections]) # Section Titles (M)
 
 
 
 
 
 
468
 
469
  apply_filter_btn.click(
470
  fn=refresh_all_analytics_ui_elements,
 
196
  logging.error(f"Config not found for plot_id {plot_id_clicked}")
197
  # Ensure this error return matches the expected number of outputs
198
  num_plots = len(plot_configs)
199
+ # Count for action_panel_outputs_list: 11 base UI + 4 states + N panels + 3N buttons + M sections = 15 + 4N + M
200
+ # 15 + 4*19 + 6 = 15 + 76 + 6 = 97
201
+ error_list_len = 11 + 4 + num_plots + (3 * num_plots) + num_unique_sections # Matches action_panel_outputs_list structure
202
+ error_list = [gr.update()] * error_list_len
203
+ # Manually set key states to avoid further issues if possible
204
+ error_list[11] = current_active_action_from_state # active_panel_action_state
205
+ error_list[12] = current_chat_plot_id # current_chat_plot_id_st
206
+ error_list[13] = current_chat_histories # chat_histories_st
207
+ error_list[14] = current_explored_plot_id # explored_plot_id_state
208
  return error_list
209
 
210
  clicked_plot_label = clicked_plot_config["label"]
 
215
  action_col_visible_update = gr.update(visible=False)
216
  insights_chatbot_visible_update, insights_chat_input_visible_update, insights_suggestions_row_visible_update = gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
217
  formula_display_visible_update = gr.update(visible=False)
218
+ formula_close_hint_visible_update = gr.update(visible=False)
219
  chatbot_content_update, s1_upd, s2_upd, s3_upd, formula_content_update = gr.update(), gr.update(), gr.update(), gr.update(), gr.update()
220
 
221
  new_active_action_state_to_set, new_current_chat_plot_id = None, current_chat_plot_id
 
226
 
227
  if is_toggling_off:
228
  new_active_action_state_to_set = None
229
+ action_col_visible_update = gr.update(visible=False)
 
230
  logging.info(f"Toggling OFF panel {action_type} for {plot_id_clicked}.")
231
+ if current_explored_plot_id:
232
  explored_cfg = next((p for p in plot_configs if p["id"] == current_explored_plot_id), None)
233
  explored_sec = explored_cfg["section"] if explored_cfg else None
234
  for i, sec_name in enumerate(unique_ordered_sections):
 
237
  is_exp = (cfg["id"] == current_explored_plot_id)
238
  panel_vis_updates.append(gr.update(visible=is_exp))
239
  explore_btn_updates.append(gr.update(value=ACTIVE_ICON if is_exp else EXPLORE_ICON))
240
+ else:
241
  for i in range(num_unique_sections): section_title_vis_updates[i] = gr.update(visible=True)
242
  for _ in plot_configs:
243
  panel_vis_updates.append(gr.update(visible=True))
244
  explore_btn_updates.append(gr.update(value=EXPLORE_ICON))
245
+ for _ in plot_configs:
246
  action_btn_updates.extend([gr.update(value=BOMB_ICON), gr.update(value=FORMULA_ICON)])
247
  if action_type == "insights": new_current_chat_plot_id = None
248
 
249
+ else:
250
  new_active_action_state_to_set = hypothetical_new_active_state
251
+ action_col_visible_update = gr.update(visible=True)
252
+ new_explored_plot_id_to_set = None
253
  logging.info(f"Toggling ON panel {action_type} for {plot_id_clicked}. Cancelling explore view.")
254
 
255
+ for i, sec_name in enumerate(unique_ordered_sections):
256
  section_title_vis_updates[i] = gr.update(visible=(sec_name == clicked_plot_section))
257
+ for cfg in plot_configs:
258
  panel_vis_updates.append(gr.update(visible=(cfg["id"] == plot_id_clicked)))
259
+ explore_btn_updates.append(gr.update(value=EXPLORE_ICON))
260
 
261
+ for cfg_btn in plot_configs:
262
  is_act_ins = new_active_action_state_to_set == {"plot_id": cfg_btn["id"], "type": "insights"}
263
  is_act_for = new_active_action_state_to_set == {"plot_id": cfg_btn["id"], "type": "formula"}
264
  action_btn_updates.extend([gr.update(value=ACTIVE_ICON if is_act_ins else BOMB_ICON),
 
279
  s1_upd,s2_upd,s3_upd = gr.update(value=sugg[0] if sugg else "N/A"),gr.update(value=sugg[1] if len(sugg)>1 else "N/A"),gr.update(value=sugg[2] if len(sugg)>2 else "N/A")
280
  elif action_type == "formula":
281
  formula_display_visible_update = gr.update(visible=True)
282
+ formula_close_hint_visible_update = gr.update(visible=True)
283
  f_key = PLOT_ID_TO_FORMULA_KEY_MAP.get(plot_id_clicked)
284
  f_text = f"**Formula/Methodology for: {clicked_plot_label}** (ID: `{plot_id_clicked}`)\n\n"
285
  if f_key and f_key in PLOT_FORMULAS:
 
293
  action_col_visible_update, insights_chatbot_visible_update, chatbot_content_update,
294
  insights_chat_input_visible_update, insights_suggestions_row_visible_update,
295
  s1_upd, s2_upd, s3_upd, formula_display_visible_update, formula_content_update,
296
+ formula_close_hint_visible_update,
297
  new_active_action_state_to_set, new_current_chat_plot_id, updated_chat_histories,
298
  new_explored_plot_id_to_set
299
  ]
300
  final_updates.extend(panel_vis_updates)
301
+ final_updates.extend(action_btn_updates) # Should be 2*N items
302
+ final_updates.extend(explore_btn_updates) # Should be N items
303
  final_updates.extend(section_title_vis_updates)
304
+ # Total: 11 (base UI) + 4 (states) + N (panels) + 2N (action_btns) + N (explore_btns) + M (sections)
305
+ # = 15 + 4N + M. For N=19, M=6: 15 + 76 + 6 = 97. This matches action_panel_outputs_list.
306
  return final_updates
307
 
308
  async def handle_chat_message_submission(user_message: str, current_plot_id: str, chat_histories: dict, current_plot_data_for_chatbot: dict ):
 
327
  num_plots = len(plot_configs)
328
  if not plot_ui_objects:
329
  logging.error("plot_ui_objects not populated for handle_explore_click.")
330
+ # explore_outputs_list: 4 base states/UI + N panels + N explore_btns + 2N action_btns + M sections
331
+ # = 4 + 4N + M. For N=19, M=6: 4 + 76 + 6 = 86
332
+ error_list_len = 4 + num_plots + num_plots + (2 * num_plots) + num_unique_sections
333
+ error_list = [gr.update()] * error_list_len
334
+ error_list[0] = current_explored_plot_id_from_state
335
+ error_list[2] = current_active_panel_action_state
336
+ return error_list
337
+
338
 
339
  new_explored_id_to_set, is_toggling_off_explore = None, (plot_id_clicked == current_explored_plot_id_from_state)
340
  action_col_upd, new_active_panel_state_upd = gr.update(), current_active_panel_action_state
341
  panel_vis, explore_btns, bomb_btns, formula_btns = [], [], [], []
342
  section_title_vis = [gr.update()] * num_unique_sections
343
+ formula_hint_upd = gr.update(visible=False)
344
 
345
  clicked_cfg = next((p for p in plot_configs if p["id"] == plot_id_clicked), None)
346
  sec_of_clicked = clicked_cfg["section"] if clicked_cfg else None
 
351
  for i in range(num_unique_sections): section_title_vis[i] = gr.update(visible=True)
352
  for _ in plot_configs:
353
  panel_vis.append(gr.update(visible=True)); explore_btns.append(gr.update(value=EXPLORE_ICON))
354
+ bomb_btns.append(gr.update()); formula_btns.append(gr.update())
355
  else:
356
  new_explored_id_to_set = plot_id_clicked
357
  logging.info(f"Exploring {plot_id_clicked}. Hiding other plots/sections.")
358
  for i, sec_name in enumerate(unique_ordered_sections): section_title_vis[i] = gr.update(visible=(sec_name == sec_of_clicked))
359
+ for cfg_idx, cfg in enumerate(plot_configs): # Iterate with index for bomb_btns/formula_btns
360
  is_target = (cfg["id"] == new_explored_id_to_set)
361
+ panel_vis.append(gr.update(visible=is_target))
362
+ explore_btns.append(gr.update(value=ACTIVE_ICON if is_target else EXPLORE_ICON))
363
+ # Initialize bomb_btns and formula_btns correctly for all plots
364
+ if current_active_panel_action_state and current_active_panel_action_state.get("plot_id") == cfg["id"]:
365
+ # This should not happen if we are closing active panel below
366
+ pass # Will be overridden
367
+
368
+ if current_active_panel_action_state:
369
  logging.info("Closing active insight/formula panel due to explore click.")
370
  action_col_upd = gr.update(visible=False); new_active_panel_state_upd = None
371
+ # Reset all bomb and formula buttons
372
+ bomb_btns = [gr.update(value=BOMB_ICON) for _ in plot_configs]
373
+ formula_btns = [gr.update(value=FORMULA_ICON) for _ in plot_configs]
374
  else:
375
+ # If no panel was active, keep current state of bomb/formula buttons (no update)
376
+ bomb_btns = [gr.update() for _ in plot_configs]
377
+ formula_btns = [gr.update() for _ in plot_configs]
378
 
379
+ # Order: states (4), panels (N), explore_btns (N), bomb_btns (N), formula_btns (N), section_titles (M)
380
+ # Total: 4 + N + N + N + N + M = 4 + 4N + M.
381
  return [new_explored_id_to_set, action_col_upd, new_active_panel_state_upd, formula_hint_upd] + \
382
  panel_vis + explore_btns + bomb_btns + formula_btns + section_title_vis
383
 
384
  # --- Define Output Lists for Event Handlers ---
385
+ # Base UI for action panel (insights/formula): 11 elements
386
  _base_action_panel_ui_outputs = [
387
  global_actions_column_ui, insights_chatbot_ui, insights_chatbot_ui,
388
  insights_chat_input_ui, insights_suggestions_row_ui,
389
  insights_suggestion_1_btn, insights_suggestion_2_btn, insights_suggestion_3_btn,
390
+ formula_display_markdown_ui, formula_display_markdown_ui, # Formula MD (vis + value)
391
+ formula_close_hint_md
392
  ]
393
+ # States for action panel: 4 elements
394
  _action_panel_state_outputs = [active_panel_action_state, current_chat_plot_id_st, chat_histories_st, explored_plot_id_state]
395
 
396
+ action_panel_outputs_list = _base_action_panel_ui_outputs + _action_panel_state_outputs # 11 + 4 = 15
397
+ action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("panel_component", gr.update()) for pc in plot_configs]) # +N (panels)
398
+ action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("bomb_button", gr.update()) for pc in plot_configs]) # +N (bomb_button)
399
+ action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("formula_button", gr.update()) for pc in plot_configs]) # +N (formula_button)
400
+ action_panel_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("explore_button", gr.update()) for pc in plot_configs]) # +N (explore_button)
401
+ action_panel_outputs_list.extend([section_titles_map.get(s_name, gr.update()) for s_name in unique_ordered_sections]) # +M (sections)
402
+ # Total for action_panel_outputs_list = 15 + 4N + M. For N=19, M=6: 15 + 76 + 6 = 97.
403
+
404
+ # Base UI/States for explore click: 4 elements
405
+ _explore_base_outputs = [explored_plot_id_state, global_actions_column_ui, active_panel_action_state, formula_close_hint_md]
406
+ explore_outputs_list = _explore_base_outputs # 4
407
+ explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("panel_component", gr.update()) for pc in plot_configs]) # +N (panels)
408
+ explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("explore_button", gr.update()) for pc in plot_configs]) # +N (explore_button)
409
+ explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("bomb_button", gr.update()) for pc in plot_configs]) # +N (bomb_button)
410
+ explore_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("formula_button", gr.update()) for pc in plot_configs]) # +N (formula_button)
411
+ explore_outputs_list.extend([section_titles_map.get(s_name, gr.update()) for s_name in unique_ordered_sections]) # +M (sections)
412
+ # Total for explore_outputs_list = 4 + 4N + M. For N=19, M=6: 4 + 76 + 6 = 86.
413
 
414
  action_click_inputs = [active_panel_action_state, chat_histories_st, current_chat_plot_id_st, plot_data_for_chatbot_st, explored_plot_id_state]
415
  explore_click_inputs = [explored_plot_id_state, active_panel_action_state]
 
441
  plot_gen_results = update_analytics_plots_figures(current_token_state, date_filter_val, custom_start_val, custom_end_val, plot_configs)
442
  status_msg, gen_figs, new_summaries = plot_gen_results[0], plot_gen_results[1:-1], plot_gen_results[-1]
443
 
444
+ all_updates = [status_msg] # 1
445
+ all_updates.extend(gen_figs if len(gen_figs) == len(plot_configs) else [create_placeholder_plot("Error", f"Fig missing {i}") for i in range(len(plot_configs))]) # +N (19)
446
+
447
+ # UI Resets (9 elements) + State Resets (4 elements) = 13 elements
448
+ all_updates.extend([
449
+ gr.update(visible=False), gr.update(value=[], visible=False), gr.update(value="", visible=False), # global_actions_col, chatbot, chat_input
450
+ gr.update(visible=False), gr.update(value="S1"), gr.update(value="S2"), gr.update(value="S3"), # suggestions_row, sugg_btns
451
+ gr.update(value="Formula details here.", visible=False), gr.update(visible=False), # formula_md, formula_hint_md
452
+ None, None, {}, new_summaries # active_panel_state, current_chat_plot_id, chat_histories, plot_data_for_chatbot
453
+ ]) # +13
454
+
455
+ for _ in plot_configs: # Reset button icons (3) & panel visibility (1) = 4 per plot
456
+ all_updates.extend([gr.update(value=BOMB_ICON), gr.update(value=FORMULA_ICON), gr.update(value=EXPLORE_ICON), gr.update(visible=True)]) # +4N (76)
457
 
 
 
 
 
 
 
 
 
458
  all_updates.append(None) # Reset explored_plot_id_state (1 element)
459
+ all_updates.extend([gr.update(visible=True)] * num_unique_sections) # Make all section titles visible (M = 6 elements)
460
+ # Total: 1 + N + 13 + 4N + 1 + M = 1 + 19 + 13 + 76 + 1 + 6 = 116. This matches apply_filter_and_sync_outputs_list.
461
  logging.info(f"Prepared {len(all_updates)} updates for analytics refresh.")
462
  return all_updates
463
 
464
+ # Construction of apply_filter_and_sync_outputs_list
465
+ # This list defines the components Gradio expects to be updated.
466
+ # Its length must match the number of items returned by refresh_all_analytics_ui_elements.
467
+
468
+ apply_filter_and_sync_outputs_list = [analytics_status_md] # 1. Status
469
+ apply_filter_and_sync_outputs_list.extend([plot_ui_objects.get(pc["id"], {}).get("plot_component", gr.update()) for pc in plot_configs]) # 2. Plot figures (N)
 
 
 
 
 
470
 
471
+ # 3. UI Resets (9 elements for action panel)
472
  _ui_resets_for_filter = [
473
  global_actions_column_ui, insights_chatbot_ui, insights_chat_input_ui,
474
  insights_suggestions_row_ui, insights_suggestion_1_btn, insights_suggestion_2_btn, insights_suggestion_3_btn,
475
+ formula_display_markdown_ui, formula_close_hint_md
476
  ]
 
 
477
  apply_filter_and_sync_outputs_list.extend(_ui_resets_for_filter)
478
+
479
+ # 4. State Resets (4 elements)
480
+ _state_resets_for_filter = [active_panel_action_state, current_chat_plot_id_st, chat_histories_st, plot_data_for_chatbot_st]
481
  apply_filter_and_sync_outputs_list.extend(_state_resets_for_filter)
482
 
483
+ # 5. Plot-specific buttons (3 per plot) and panel visibility (1 per plot) = 4N elements
484
+ for pc in plot_configs:
485
  pid = pc["id"]
486
  apply_filter_and_sync_outputs_list.extend([
487
  plot_ui_objects.get(pid, {}).get("bomb_button", gr.update()),
 
489
  plot_ui_objects.get(pid, {}).get("explore_button", gr.update()),
490
  plot_ui_objects.get(pid, {}).get("panel_component", gr.update())
491
  ])
492
+
493
+ # 6. Explored state reset (1 element)
494
+ apply_filter_and_sync_outputs_list.append(explored_plot_id_state)
495
+
496
+ # 7. Section Titles (M elements)
497
+ apply_filter_and_sync_outputs_list.extend([section_titles_map.get(s_name, gr.update()) for s_name in unique_ordered_sections])
498
+ # Total elements: 1 + N + 9 + 4 + 4N + 1 + M = 15 + 5N + M
499
+ # For N=19, M=6: 15 + 5*19 + 6 = 15 + 95 + 6 = 110 + 6 = 116. This is correct.
500
 
501
  apply_filter_btn.click(
502
  fn=refresh_all_analytics_ui_elements,