GuglielmoTor commited on
Commit
c205383
·
verified ·
1 Parent(s): ee091bd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -33
app.py CHANGED
@@ -109,37 +109,55 @@ def update_analytics_plots_figures(token_state_value, date_filter_option, custom
109
 
110
  plot_figs = []
111
  try:
112
- # Generate plots, ensuring all 19 slots are potentially filled
113
- plot_fns_args = [
114
- (generate_followers_count_over_time_plot, [date_filtered_follower_stats_df, 'follower_gains_monthly']),
115
- (generate_followers_growth_rate_plot, [date_filtered_follower_stats_df, 'follower_gains_monthly']),
116
- (generate_followers_by_demographics_plot, [raw_follower_stats_df, 'follower_geo', "Follower per Località"]),
117
- (generate_followers_by_demographics_plot, [raw_follower_stats_df, 'follower_function', "Follower per Ruolo"]),
118
- (generate_followers_by_demographics_plot, [raw_follower_stats_df, 'follower_industry', "Follower per Settore"]),
119
- (generate_followers_by_demographics_plot, [raw_follower_stats_df, 'follower_seniority', "Follower per Anzianità"]),
120
- (generate_engagement_rate_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
121
- (generate_reach_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
122
- (generate_impressions_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
123
- (generate_likes_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
124
- (generate_clicks_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
125
- (generate_shares_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
126
- (generate_comments_over_time_plot, [filtered_merged_posts_df, date_column_posts]),
127
- (generate_comments_sentiment_breakdown_plot, [filtered_merged_posts_df, 'comment_sentiment']),
128
- (generate_post_frequency_plot, [filtered_merged_posts_df, date_column_posts]),
129
- (generate_content_format_breakdown_plot, [filtered_merged_posts_df, media_type_col_name]),
130
- (generate_content_topic_breakdown_plot, [filtered_merged_posts_df, eb_labels_col_name]),
131
- (generate_mentions_activity_plot, [filtered_mentions_df, date_column_mentions]), # Shared for mention_analysis_volume
132
- (generate_mention_sentiment_plot, [filtered_mentions_df]) # Shared for mention_analysis_sentiment
 
133
  ]
134
 
135
- for i, (plot_fn, args) in enumerate(plot_fns_args):
 
 
 
136
  try:
 
 
 
 
 
 
 
 
 
 
 
137
  fig = plot_fn(*args)
138
  plot_figs.append(fig)
139
- except Exception as plot_e:
140
- logging.error(f"Error generating plot for slot {i} ({plot_fn.__name__}): {plot_e}", exc_info=True)
141
- plot_figs.append(create_placeholder_plot(title=f"Errore Grafico {i+1}", message=f"Dettaglio: {str(plot_e)[:100]}"))
142
-
 
 
 
143
  message = f"📊 Analisi aggiornate per il periodo: {date_filter_option}"
144
  if date_filter_option == "Intervallo Personalizzato":
145
  s_display = start_dt_for_msg.strftime('%Y-%m-%d') if start_dt_for_msg else "Qualsiasi"
@@ -288,7 +306,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
288
  "I dettagli sulla formula/metodologia appariranno qui.", visible=False
289
  )
290
 
291
- async def handle_panel_action(
292
  plot_id_clicked: str,
293
  action_type: str,
294
  current_active_action_from_state: dict,
@@ -300,7 +318,12 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
300
  clicked_plot_config = next((p for p in plot_configs if p["id"] == plot_id_clicked), None)
301
  if not clicked_plot_config:
302
  logging.error(f"Configurazione non trovata per plot_id {plot_id_clicked}")
303
- return [gr.update(visible=False)] * 7 + [current_active_action_from_state, current_chat_plot_id, current_chat_histories] + [gr.update() for _ in range(2 * len(plot_configs))]
 
 
 
 
 
304
 
305
  clicked_plot_label = clicked_plot_config["label"]
306
 
@@ -393,7 +416,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
393
  updated_chat_histories
394
  ] + all_button_icon_updates
395
 
396
- return final_updates
397
 
398
  async def handle_chat_message_submission(
399
  user_message: str,
@@ -402,7 +425,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
402
  ):
403
  if not current_plot_id or not user_message.strip():
404
  history_for_plot = chat_histories.get(current_plot_id, [])
405
- # Corrected: Use yield and then a bare return for early exit in async generator
406
  yield history_for_plot, "", chat_histories
407
  return
408
 
@@ -430,7 +452,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
430
  ):
431
  if not current_plot_id or not suggestion_text.strip():
432
  history_for_plot = chat_histories.get(current_plot_id, [])
433
- # Corrected: Use yield and then a bare return for early exit in async generator
434
  yield history_for_plot, "", chat_histories
435
  return
436
 
@@ -525,14 +546,16 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
525
  plot_label = config_item["label"]
526
  if plot_id in plot_ui_objects:
527
  ui_obj = plot_ui_objects[plot_id]
 
528
  ui_obj["bomb_button"].click(
529
- fn=lambda current_active_val, current_chats_val, current_chat_pid, p_id=plot_id: handle_panel_action(p_id, "insights", current_active_val, current_chats_val, current_chat_pid),
530
  inputs=action_click_inputs,
531
  outputs=action_panel_outputs_list,
532
  api_name=f"action_insights_{plot_id}"
533
  )
 
534
  ui_obj["formula_button"].click(
535
- fn=lambda current_active_val, current_chats_val, current_chat_pid, p_id=plot_id: handle_panel_action(p_id, "formula", current_active_val, current_chats_val, current_chat_pid),
536
  inputs=action_click_inputs,
537
  outputs=action_panel_outputs_list,
538
  api_name=f"action_formula_{plot_id}"
 
109
 
110
  plot_figs = []
111
  try:
112
+ # Define plot functions and their arguments
113
+ # Order matters and must match plot_configs
114
+ plot_definitions = [
115
+ {"func": generate_followers_count_over_time_plot, "args": [date_filtered_follower_stats_df, 'follower_gains_monthly'], "is_demographic": False},
116
+ {"func": generate_followers_growth_rate_plot, "args": [date_filtered_follower_stats_df, 'follower_gains_monthly'], "is_demographic": False},
117
+ {"func": generate_followers_by_demographics_plot, "args": [raw_follower_stats_df, 'follower_geo', "Follower per Località"], "type_value_key": "follower_geo", "is_demographic": True},
118
+ {"func": generate_followers_by_demographics_plot, "args": [raw_follower_stats_df, 'follower_function', "Follower per Ruolo"], "type_value_key": "follower_function", "is_demographic": True},
119
+ {"func": generate_followers_by_demographics_plot, "args": [raw_follower_stats_df, 'follower_industry', "Follower per Settore"], "type_value_key": "follower_industry", "is_demographic": True},
120
+ {"func": generate_followers_by_demographics_plot, "args": [raw_follower_stats_df, 'follower_seniority', "Follower per Anzianità"], "type_value_key": "follower_seniority", "is_demographic": True},
121
+ {"func": generate_engagement_rate_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
122
+ {"func": generate_reach_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
123
+ {"func": generate_impressions_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
124
+ {"func": generate_likes_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
125
+ {"func": generate_clicks_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
126
+ {"func": generate_shares_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
127
+ {"func": generate_comments_over_time_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
128
+ {"func": generate_comments_sentiment_breakdown_plot, "args": [filtered_merged_posts_df, 'comment_sentiment'], "is_demographic": False},
129
+ {"func": generate_post_frequency_plot, "args": [filtered_merged_posts_df, date_column_posts], "is_demographic": False},
130
+ {"func": generate_content_format_breakdown_plot, "args": [filtered_merged_posts_df, media_type_col_name], "is_demographic": False},
131
+ {"func": generate_content_topic_breakdown_plot, "args": [filtered_merged_posts_df, eb_labels_col_name], "is_demographic": False},
132
+ {"func": generate_mentions_activity_plot, "args": [filtered_mentions_df, date_column_mentions], "is_demographic": False},
133
+ {"func": generate_mention_sentiment_plot, "args": [filtered_mentions_df], "is_demographic": False}
134
  ]
135
 
136
+ for i, plot_def in enumerate(plot_definitions):
137
+ plot_fn = plot_def["func"]
138
+ args = plot_def["args"]
139
+ plot_title_for_error = args[2] if plot_def["is_demographic"] else plot_fn.__name__
140
  try:
141
+ # Specific check for demographic plots if raw_follower_stats_df is empty or missing key columns
142
+ if plot_def["is_demographic"]:
143
+ df_arg = args[0] # raw_follower_stats_df
144
+ type_val_col = plot_def["type_value_key"]
145
+ if df_arg is None or df_arg.empty:
146
+ logging.warning(f"raw_follower_stats_df is empty. Cannot generate demographic plot: {plot_title_for_error}")
147
+ raise ValueError(f"Dati demografici mancanti (raw_follower_stats_df vuoto).")
148
+ if type_val_col not in df_arg.columns:
149
+ logging.warning(f"Colonna '{type_val_col}' mancante in raw_follower_stats_df per il grafico '{plot_title_for_error}'. Colonne disponibili: {df_arg.columns.tolist()}")
150
+ raise KeyError(f"Colonna dati '{type_val_col}' non trovata.")
151
+
152
  fig = plot_fn(*args)
153
  plot_figs.append(fig)
154
+ except (KeyError, ValueError) as plot_e: # Catch KeyError for missing columns, ValueError for other data issues
155
+ logging.error(f"Errore generazione grafico '{plot_title_for_error}' (slot {i}): {plot_e}", exc_info=False) # Set exc_info to False for cleaner logs for known data issues
156
+ plot_figs.append(create_placeholder_plot(title=f"Errore Dati: {plot_title_for_error}", message=f"Impossibile generare: {str(plot_e)}"))
157
+ except Exception as plot_e: # Catch other unexpected errors
158
+ logging.error(f"Errore imprevisto generazione grafico '{plot_title_for_error}' (slot {i}): {plot_e}", exc_info=True)
159
+ plot_figs.append(create_placeholder_plot(title=f"Errore Grafico: {plot_title_for_error}", message=f"Dettaglio: {str(plot_e)[:100]}"))
160
+
161
  message = f"📊 Analisi aggiornate per il periodo: {date_filter_option}"
162
  if date_filter_option == "Intervallo Personalizzato":
163
  s_display = start_dt_for_msg.strftime('%Y-%m-%d') if start_dt_for_msg else "Qualsiasi"
 
306
  "I dettagli sulla formula/metodologia appariranno qui.", visible=False
307
  )
308
 
309
+ async def handle_panel_action( # This function is async
310
  plot_id_clicked: str,
311
  action_type: str,
312
  current_active_action_from_state: dict,
 
318
  clicked_plot_config = next((p for p in plot_configs if p["id"] == plot_id_clicked), None)
319
  if not clicked_plot_config:
320
  logging.error(f"Configurazione non trovata per plot_id {plot_id_clicked}")
321
+ # Ensure we return the correct number of updates even on error
322
+ num_button_updates = 2 * len(plot_configs)
323
+ error_updates = [gr.update(visible=False)] * 10 # Updates for action column components
324
+ error_updates.extend([current_active_action_from_state, current_chat_plot_id, current_chat_histories]) # States
325
+ error_updates.extend([gr.update()] * num_button_updates) # Button icons
326
+ return error_updates
327
 
328
  clicked_plot_label = clicked_plot_config["label"]
329
 
 
416
  updated_chat_histories
417
  ] + all_button_icon_updates
418
 
419
+ return final_updates # This list should have 13 + (19*2) = 51 items
420
 
421
  async def handle_chat_message_submission(
422
  user_message: str,
 
425
  ):
426
  if not current_plot_id or not user_message.strip():
427
  history_for_plot = chat_histories.get(current_plot_id, [])
 
428
  yield history_for_plot, "", chat_histories
429
  return
430
 
 
452
  ):
453
  if not current_plot_id or not suggestion_text.strip():
454
  history_for_plot = chat_histories.get(current_plot_id, [])
 
455
  yield history_for_plot, "", chat_histories
456
  return
457
 
 
546
  plot_label = config_item["label"]
547
  if plot_id in plot_ui_objects:
548
  ui_obj = plot_ui_objects[plot_id]
549
+ # FIX: Make lambda async and await the call to handle_panel_action
550
  ui_obj["bomb_button"].click(
551
+ fn=async lambda current_active_val, current_chats_val, current_chat_pid, p_id=plot_id: await handle_panel_action(p_id, "insights", current_active_val, current_chats_val, current_chat_pid),
552
  inputs=action_click_inputs,
553
  outputs=action_panel_outputs_list,
554
  api_name=f"action_insights_{plot_id}"
555
  )
556
+ # FIX: Make lambda async and await the call to handle_panel_action
557
  ui_obj["formula_button"].click(
558
+ fn=async lambda current_active_val, current_chats_val, current_chat_pid, p_id=plot_id: await handle_panel_action(p_id, "formula", current_active_val, current_chats_val, current_chat_pid),
559
  inputs=action_click_inputs,
560
  outputs=action_panel_outputs_list,
561
  api_name=f"action_formula_{plot_id}"