GuglielmoTor commited on
Commit
55594d3
·
verified ·
1 Parent(s): 58cf3bf

Create analytics_tab_setup.py

Browse files
Files changed (1) hide show
  1. ui/analytics_tab_setup.py +202 -0
ui/analytics_tab_setup.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ui/analytics_tab_setup.py
2
+ import gradio as gr
3
+ from collections import OrderedDict
4
+ from ui.ui_generators import (
5
+ build_analytics_tab_plot_area,
6
+ # BOMB_ICON, EXPLORE_ICON, FORMULA_ICON, ACTIVE_ICON # These are used by handlers, not directly in setup
7
+ )
8
+ import logging
9
+
10
+ def get_plot_configurations():
11
+ """Return the plot configuration list."""
12
+ # This configuration should ideally live in a config file or be passed if it's dynamic
13
+ plot_configs = [
14
+ {"label": "Numero di Follower nel Tempo", "id": "followers_count", "section": "Dinamiche dei Follower"},
15
+ {"label": "Tasso di Crescita Follower", "id": "followers_growth_rate", "section": "Dinamiche dei Follower"},
16
+ {"label": "Follower per Località", "id": "followers_by_location", "section": "Demografia Follower"},
17
+ {"label": "Follower per Ruolo (Funzione)", "id": "followers_by_role", "section": "Demografia Follower"},
18
+ {"label": "Follower per Settore", "id": "followers_by_industry", "section": "Demografia Follower"},
19
+ {"label": "Follower per Anzianità", "id": "followers_by_seniority", "section": "Demografia Follower"},
20
+ {"label": "Tasso di Engagement nel Tempo", "id": "engagement_rate", "section": "Approfondimenti Performance Post"},
21
+ {"label": "Copertura nel Tempo", "id": "reach_over_time", "section": "Approfondimenti Performance Post"},
22
+ {"label": "Visualizzazioni nel Tempo", "id": "impressions_over_time", "section": "Approfondimenti Performance Post"},
23
+ {"label": "Reazioni (Like) nel Tempo", "id": "likes_over_time", "section": "Approfondimenti Performance Post"},
24
+ {"label": "Click nel Tempo", "id": "clicks_over_time", "section": "Engagement Dettagliato Post nel Tempo"},
25
+ {"label": "Condivisioni nel Tempo", "id": "shares_over_time", "section": "Engagement Dettagliato Post nel Tempo"},
26
+ {"label": "Commenti nel Tempo", "id": "comments_over_time", "section": "Engagement Dettagliato Post nel Tempo"},
27
+ {"label": "Ripartizione Commenti per Sentiment", "id": "comments_sentiment", "section": "Engagement Dettagliato Post nel Tempo"},
28
+ {"label": "Frequenza Post", "id": "post_frequency_cs", "section": "Analisi Strategia Contenuti"},
29
+ {"label": "Ripartizione Contenuti per Formato", "id": "content_format_breakdown_cs", "section": "Analisi Strategia Contenuti"},
30
+ {"label": "Ripartizione Contenuti per Argomenti", "id": "content_topic_breakdown_cs", "section": "Analisi Strategia Contenuti"},
31
+ {"label": "Volume Menzioni nel Tempo (Dettaglio)", "id": "mention_analysis_volume", "section": "Analisi Menzioni (Dettaglio)"},
32
+ {"label": "Ripartizione Menzioni per Sentiment (Dettaglio)", "id": "mention_analysis_sentiment", "section": "Analisi Menzioni (Dettaglio)"}
33
+ ]
34
+ # IMPORTANT: Review if 'mention_analysis_volume' and 'mention_analysis_sentiment' plots
35
+ # can still be generated without the dedicated mentions data processing.
36
+ # If not, they should also be removed from plot_configs.
37
+ # For now, I am assuming they might draw from a general data pool in token_state.
38
+ assert len(plot_configs) == 19, "Mancata corrispondenza in plot_configs e grafici attesi. (If mentions plots were removed, adjust this number)"
39
+ return plot_configs
40
+
41
+ def _process_plot_area_result(ui_elements_tuple, unique_ordered_sections):
42
+ """Process the result from build_analytics_tab_plot_area."""
43
+ plot_ui_objects = {}
44
+ section_titles_map = {}
45
+
46
+ if isinstance(ui_elements_tuple, tuple) and len(ui_elements_tuple) == 2:
47
+ plot_ui_objects, section_titles_map = ui_elements_tuple
48
+
49
+ # Validate section titles map
50
+ if not all(sec_name in section_titles_map for sec_name in unique_ordered_sections):
51
+ logging.error("section_titles_map from build_analytics_tab_plot_area is incomplete.")
52
+ for sec_name in unique_ordered_sections:
53
+ if sec_name not in section_titles_map:
54
+ section_titles_map[sec_name] = gr.Markdown(f"### {sec_name} (Error Placeholder)")
55
+ else:
56
+ logging.error("build_analytics_tab_plot_area did not return a tuple of (plot_ui_objects, section_titles_map).")
57
+ # Fallback: ui_elements_tuple might be just plot_ui_objects if build_analytics_tab_plot_area changed
58
+ plot_ui_objects = ui_elements_tuple if isinstance(ui_elements_tuple, dict) else {}
59
+ for sec_name in unique_ordered_sections:
60
+ section_titles_map[sec_name] = gr.Markdown(f"### {sec_name} (Error Placeholder)")
61
+
62
+ return plot_ui_objects, section_titles_map
63
+
64
+ def _setup_action_panel():
65
+ """Set up the action panel with insights chat and formula display."""
66
+ gr.Markdown("### 💡 Azioni Contestuali Grafico")
67
+
68
+ insights_chatbot_ui = gr.Chatbot(
69
+ label="Chat Insights",
70
+ type="messages",
71
+ height=450,
72
+ bubble_full_width=False,
73
+ visible=False,
74
+ show_label=False,
75
+ placeholder="L'analisi AI del grafico apparirà qui. Fai domande di approfondimento!"
76
+ )
77
+
78
+ insights_chat_input_ui = gr.Textbox(
79
+ label="La tua domanda:",
80
+ placeholder="Chiedi all'AI riguardo a questo grafico...",
81
+ lines=2,
82
+ visible=False,
83
+ show_label=False
84
+ )
85
+
86
+ with gr.Row(visible=False) as insights_suggestions_row_ui:
87
+ insights_suggestion_1_btn = gr.Button(value="Suggerimento 1", size="sm", min_width=50)
88
+ insights_suggestion_2_btn = gr.Button(value="Suggerimento 2", size="sm", min_width=50)
89
+ insights_suggestion_3_btn = gr.Button(value="Suggerimento 3", size="sm", min_width=50)
90
+
91
+ formula_display_markdown_ui = gr.Markdown(
92
+ "I dettagli sulla formula/metodologia appariranno qui.",
93
+ visible=False
94
+ )
95
+
96
+ formula_close_hint_md = gr.Markdown(
97
+ "<p style='font-size:0.9em; text-align:center; margin-top:10px;'>"
98
+ "<em>Click the active ƒ button on the plot again to close this panel.</em></p>",
99
+ visible=False
100
+ )
101
+
102
+ return {
103
+ 'insights_chatbot_ui': insights_chatbot_ui,
104
+ 'insights_chat_input_ui': insights_chat_input_ui,
105
+ 'insights_suggestions_row_ui': insights_suggestions_row_ui,
106
+ 'insights_suggestion_1_btn': insights_suggestion_1_btn,
107
+ 'insights_suggestion_2_btn': insights_suggestion_2_btn,
108
+ 'insights_suggestion_3_btn': insights_suggestion_3_btn,
109
+ 'formula_display_markdown_ui': formula_display_markdown_ui,
110
+ 'formula_close_hint_md': formula_close_hint_md
111
+ }
112
+
113
+ def setup_analytics_tab():
114
+ """Set up the analytics tab with all its components and return component references."""
115
+
116
+ gr.Markdown("## 📈 Analisi Performance LinkedIn")
117
+ gr.Markdown("Seleziona un intervallo di date per i grafici. Clicca i pulsanti (💣 Insights, ƒ Formula, 🧭 Esplora) su un grafico per azioni.")
118
+
119
+ analytics_status_md = gr.Markdown("Stato analisi grafici...")
120
+
121
+ # Date filter controls
122
+ with gr.Row():
123
+ date_filter_selector = gr.Radio(
124
+ ["Sempre", "Ultimi 7 Giorni", "Ultimi 30 Giorni", "Intervallo Personalizzato"],
125
+ label="Seleziona Intervallo Date per Grafici",
126
+ value="Sempre",
127
+ scale=3
128
+ )
129
+ with gr.Column(scale=2):
130
+ custom_start_date_picker = gr.DateTime(
131
+ label="Data Inizio",
132
+ visible=False,
133
+ include_time=False,
134
+ type="datetime" # Ensure this matches expected type by handlers/plotters
135
+ )
136
+ custom_end_date_picker = gr.DateTime(
137
+ label="Data Fine",
138
+ visible=False,
139
+ include_time=False,
140
+ type="datetime" # Ensure this matches
141
+ )
142
+
143
+ apply_filter_btn = gr.Button("🔍 Applica Filtro & Aggiorna Grafici", variant="primary")
144
+
145
+ # Set up date picker visibility toggle
146
+ def toggle_custom_date_pickers(selection):
147
+ is_custom = selection == "Intervallo Personalizzato"
148
+ return gr.update(visible=is_custom), gr.update(visible=is_custom)
149
+
150
+ date_filter_selector.change(
151
+ fn=toggle_custom_date_pickers,
152
+ inputs=[date_filter_selector],
153
+ outputs=[custom_start_date_picker, custom_end_date_picker]
154
+ )
155
+
156
+ # Plot configurations
157
+ plot_configs = get_plot_configurations()
158
+ unique_ordered_sections = list(OrderedDict.fromkeys(pc["section"] for pc in plot_configs))
159
+ num_unique_sections = len(unique_ordered_sections)
160
+
161
+ # State components (defined in main app.py, but listed here for clarity of what this tab might conceptually own or interact with)
162
+ # active_panel_action_state = gr.State(None) # Managed by main app
163
+ # explored_plot_id_state = gr.State(None) # Managed by main app
164
+
165
+ # Build plot area
166
+ plot_ui_objects = {}
167
+ section_titles_map = {}
168
+ global_actions_column_ui = None # Define it to ensure it's in scope
169
+ action_components = {} # Define it
170
+
171
+ with gr.Row(equal_height=False):
172
+ with gr.Column(scale=8) as plots_area_col:
173
+ # This function is expected to create the actual plot components (e.g., gr.Plot)
174
+ # and their associated action buttons (bomb, formula, explore)
175
+ # It should return a dictionary of these plot UI objects and section title markdowns
176
+ ui_elements_tuple = build_analytics_tab_plot_area(plot_configs)
177
+ plot_ui_objects, section_titles_map = _process_plot_area_result(
178
+ ui_elements_tuple, unique_ordered_sections
179
+ )
180
+
181
+ # Action panel (global for the tab, shown/hidden based on plot interactions)
182
+ with gr.Column(scale=4, visible=False) as global_actions_col: # Assign to variable
183
+ global_actions_column_ui = global_actions_col # Store the column itself
184
+ action_components = _setup_action_panel()
185
+
186
+ # Package all components for return, so handlers can connect to them
187
+ components = {
188
+ 'analytics_status_md': analytics_status_md,
189
+ 'date_filter_selector': date_filter_selector,
190
+ 'custom_start_date_picker': custom_start_date_picker,
191
+ 'custom_end_date_picker': custom_end_date_picker,
192
+ 'apply_filter_btn': apply_filter_btn,
193
+ 'plot_configs': plot_configs, # Pass config for handlers
194
+ 'unique_ordered_sections': unique_ordered_sections, # Pass for handlers
195
+ 'num_unique_sections': num_unique_sections, # Pass for handlers
196
+ 'plot_ui_objects': plot_ui_objects, # Key for handlers to connect events
197
+ 'section_titles_map': section_titles_map, # Key for handlers to update visibility
198
+ 'global_actions_column_ui': global_actions_column_ui, # The visibility of this entire column is controlled
199
+ **action_components # Spread the dict from _setup_action_panel
200
+ }
201
+
202
+ return components