Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -33,22 +33,32 @@ from features.chatbot.chatbot_handler import generate_llm_response
|
|
33 |
|
34 |
# --- AGENTIC PIPELINE (DISPLAY ONLY) IMPORTS ---
|
35 |
try:
|
36 |
-
#
|
37 |
from run_agentic_pipeline import load_and_display_agentic_results
|
38 |
-
#
|
39 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
AGENTIC_MODULES_LOADED = True
|
41 |
except ImportError as e:
|
42 |
logging.error(f"Could not import agentic pipeline display modules: {e}. Tabs 3 and 4 will be disabled.")
|
43 |
AGENTIC_MODULES_LOADED = False
|
44 |
-
# Placeholder
|
45 |
def load_and_display_agentic_results(*args, **kwargs):
|
46 |
-
# This tuple matches the expected number of outputs for the event handler
|
47 |
return "Modules not loaded.", gr.update(), "Modules not loaded.", "Modules not loaded.", None, [], [], "Error"
|
48 |
-
def
|
49 |
-
return
|
50 |
def format_report_for_display(report_data):
|
51 |
return "Agentic modules not loaded. Report display unavailable."
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
# --- ANALYTICS TAB MODULE IMPORT ---
|
54 |
from services.analytics_tab_module import AnalyticsTab
|
@@ -125,33 +135,83 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
125 |
fn_generate_llm_response=generate_llm_response
|
126 |
)
|
127 |
|
128 |
-
# ---
|
129 |
-
def
|
130 |
"""
|
131 |
-
Finds the selected report in the state
|
|
|
|
|
132 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
if not selected_report_id:
|
134 |
-
return
|
135 |
|
136 |
agentic_df = current_token_state.get("bubble_agentic_analysis_data")
|
137 |
if agentic_df is None or agentic_df.empty:
|
138 |
-
|
139 |
|
140 |
-
# The dropdown value is the unique ID of the report (e.g., Bubble _id)
|
141 |
selected_report_series_df = agentic_df[agentic_df['_id'] == selected_report_id]
|
142 |
-
|
143 |
if selected_report_series_df.empty:
|
144 |
-
|
|
|
145 |
|
146 |
selected_report_series = selected_report_series_df.iloc[0]
|
|
|
|
|
147 |
report_markdown = format_report_for_display(selected_report_series)
|
148 |
|
149 |
-
|
|
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
with gr.Tabs() as tabs:
|
153 |
with gr.TabItem("1️⃣ Dashboard", id="tab_dashboard"):
|
154 |
-
# REMOVED: Sync button and related UI components. This tab is now just for the main dashboard.
|
155 |
gr.Markdown("I dati visualizzati in questo pannello sono caricati direttamente da Bubble.io.")
|
156 |
dashboard_display_html = gr.HTML("<p style='text-align:center;'>Caricamento dashboard...</p>")
|
157 |
|
@@ -164,7 +224,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
164 |
agentic_pipeline_status_md = gr.Markdown("Status: Loading report data...", visible=True)
|
165 |
gr.Markdown("Questo report è stato pre-generato da un agente AI e caricato da Bubble.io. Seleziona un report dalla libreria per visualizzarlo.")
|
166 |
|
167 |
-
# NEW: Report library dropdown
|
168 |
with gr.Row():
|
169 |
report_selector_dd = gr.Dropdown(
|
170 |
label="Report Library",
|
@@ -173,7 +232,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
173 |
info="Select a previously generated report to view its details."
|
174 |
)
|
175 |
|
176 |
-
# This Markdown component will now display the selected report
|
177 |
agentic_report_display_md = gr.Markdown("Please select a report from the library to view it.")
|
178 |
|
179 |
if not AGENTIC_MODULES_LOADED:
|
@@ -231,21 +289,30 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
231 |
outputs=[okr_detail_display_md]
|
232 |
)
|
233 |
|
234 |
-
# ---
|
|
|
235 |
if AGENTIC_MODULES_LOADED:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
report_selector_dd.change(
|
237 |
-
fn=
|
238 |
inputs=[report_selector_dd, token_state],
|
239 |
-
outputs=
|
240 |
show_progress="minimal"
|
241 |
)
|
242 |
|
243 |
-
|
244 |
# --- EVENT HANDLING (SIMPLIFIED) ---
|
245 |
-
#
|
246 |
agentic_display_outputs = [
|
247 |
agentic_report_display_md,
|
248 |
-
report_selector_dd,
|
249 |
key_results_cbg,
|
250 |
okr_detail_display_md,
|
251 |
orchestration_raw_results_st,
|
@@ -274,11 +341,11 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
274 |
],
|
275 |
outputs=analytics_tab_instance.graph_refresh_outputs_list,
|
276 |
show_progress="full"
|
277 |
-
# Then, load and display the pre-computed agentic results
|
278 |
).then(
|
279 |
-
fn=load_and_display_agentic_results,
|
280 |
-
inputs=[token_state,
|
281 |
-
outputs=agentic_display_outputs,
|
282 |
show_progress="minimal"
|
283 |
)
|
284 |
|
|
|
33 |
|
34 |
# --- AGENTIC PIPELINE (DISPLAY ONLY) IMPORTS ---
|
35 |
try:
|
36 |
+
# This is the main function called on initial load to populate the agentic tabs
|
37 |
from run_agentic_pipeline import load_and_display_agentic_results
|
38 |
+
# This function is now called when a new report is selected from the dropdown
|
39 |
+
from services.report_data_handler import fetch_and_reconstruct_data_from_bubble
|
40 |
+
# UI formatting functions
|
41 |
+
from ui.insights_ui_generator import (
|
42 |
+
format_report_for_display,
|
43 |
+
extract_key_results_for_selection,
|
44 |
+
format_single_okr_for_display
|
45 |
+
)
|
46 |
AGENTIC_MODULES_LOADED = True
|
47 |
except ImportError as e:
|
48 |
logging.error(f"Could not import agentic pipeline display modules: {e}. Tabs 3 and 4 will be disabled.")
|
49 |
AGENTIC_MODULES_LOADED = False
|
50 |
+
# Placeholder functions to prevent app from crashing if imports fail
|
51 |
def load_and_display_agentic_results(*args, **kwargs):
|
|
|
52 |
return "Modules not loaded.", gr.update(), "Modules not loaded.", "Modules not loaded.", None, [], [], "Error"
|
53 |
+
def fetch_and_reconstruct_data_from_bubble(*args, **kwargs):
|
54 |
+
return None
|
55 |
def format_report_for_display(report_data):
|
56 |
return "Agentic modules not loaded. Report display unavailable."
|
57 |
+
def extract_key_results_for_selection(okr_data):
|
58 |
+
return []
|
59 |
+
def format_single_okr_for_display(okr_data, **kwargs):
|
60 |
+
return "Agentic modules not loaded. OKR display unavailable."
|
61 |
+
|
62 |
|
63 |
# --- ANALYTICS TAB MODULE IMPORT ---
|
64 |
from services.analytics_tab_module import AnalyticsTab
|
|
|
135 |
fn_generate_llm_response=generate_llm_response
|
136 |
)
|
137 |
|
138 |
+
# --- MODIFIED: Comprehensive handler for report selection and OKR display ---
|
139 |
+
def update_report_and_okr_display(selected_report_id: str, current_token_state: dict):
|
140 |
"""
|
141 |
+
Finds the selected report in the state, formats its text for display,
|
142 |
+
and crucially, fetches and reconstructs its associated OKRs and Tasks from Bubble.
|
143 |
+
Returns a full set of UI updates for all agentic components.
|
144 |
"""
|
145 |
+
# Define a default/error return tuple that matches the output components
|
146 |
+
error_return_tuple = (
|
147 |
+
gr.update(value="*Please select a report to view its details.*"),
|
148 |
+
gr.update(choices=[], value=[], interactive=False),
|
149 |
+
gr.update(value="*Please select a report to see OKRs.*"),
|
150 |
+
None,
|
151 |
+
[],
|
152 |
+
[]
|
153 |
+
)
|
154 |
+
|
155 |
if not selected_report_id:
|
156 |
+
return error_return_tuple
|
157 |
|
158 |
agentic_df = current_token_state.get("bubble_agentic_analysis_data")
|
159 |
if agentic_df is None or agentic_df.empty:
|
160 |
+
return error_return_tuple
|
161 |
|
|
|
162 |
selected_report_series_df = agentic_df[agentic_df['_id'] == selected_report_id]
|
|
|
163 |
if selected_report_series_df.empty:
|
164 |
+
error_return_tuple[0] = gr.update(value=f"*Error: Report with ID {selected_report_id} not found.*")
|
165 |
+
return error_return_tuple
|
166 |
|
167 |
selected_report_series = selected_report_series_df.iloc[0]
|
168 |
+
|
169 |
+
# 1. Format the main report text
|
170 |
report_markdown = format_report_for_display(selected_report_series)
|
171 |
|
172 |
+
# 2. Fetch and reconstruct the full OKR data for the selected report
|
173 |
+
reconstructed_data = fetch_and_reconstruct_data_from_bubble(selected_report_series)
|
174 |
|
175 |
+
# 3. Prepare UI updates for the OKR section based on the reconstructed data
|
176 |
+
if reconstructed_data:
|
177 |
+
raw_results_state = reconstructed_data
|
178 |
+
actionable_okrs_dict = reconstructed_data.get("actionable_okrs", {})
|
179 |
+
|
180 |
+
all_krs_state = extract_key_results_for_selection(actionable_okrs_dict)
|
181 |
+
if all_krs_state:
|
182 |
+
kr_choices = [(kr['kr_description'], kr['unique_kr_id']) for kr in all_krs_state]
|
183 |
+
key_results_cbg_update = gr.update(choices=kr_choices, value=[], interactive=True)
|
184 |
+
|
185 |
+
# Format all OKRs for initial display
|
186 |
+
okrs_list = actionable_okrs_dict.get("okrs", [])
|
187 |
+
output_md_parts = [
|
188 |
+
format_single_okr_for_display(okr_data, okr_main_index=okr_idx)
|
189 |
+
for okr_idx, okr_data in enumerate(okrs_list)
|
190 |
+
]
|
191 |
+
okr_details_md = "\n\n---\n\n".join(output_md_parts) if output_md_parts else "No OKRs are defined in this report."
|
192 |
+
else:
|
193 |
+
key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
|
194 |
+
okr_details_md = "No Key Results were found for this report."
|
195 |
+
all_krs_state = []
|
196 |
+
else:
|
197 |
+
# Handle case where reconstruction fails
|
198 |
+
key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
|
199 |
+
okr_details_md = "Error: Could not fetch or reconstruct OKR data for this report."
|
200 |
+
raw_results_state = None
|
201 |
+
all_krs_state = []
|
202 |
+
|
203 |
+
# 4. Return the complete set of updates for the UI
|
204 |
+
return (
|
205 |
+
report_markdown,
|
206 |
+
key_results_cbg_update,
|
207 |
+
okr_details_md,
|
208 |
+
raw_results_state,
|
209 |
+
[], # Reset selected key results on new report selection
|
210 |
+
all_krs_state
|
211 |
+
)
|
212 |
|
213 |
with gr.Tabs() as tabs:
|
214 |
with gr.TabItem("1️⃣ Dashboard", id="tab_dashboard"):
|
|
|
215 |
gr.Markdown("I dati visualizzati in questo pannello sono caricati direttamente da Bubble.io.")
|
216 |
dashboard_display_html = gr.HTML("<p style='text-align:center;'>Caricamento dashboard...</p>")
|
217 |
|
|
|
224 |
agentic_pipeline_status_md = gr.Markdown("Status: Loading report data...", visible=True)
|
225 |
gr.Markdown("Questo report è stato pre-generato da un agente AI e caricato da Bubble.io. Seleziona un report dalla libreria per visualizzarlo.")
|
226 |
|
|
|
227 |
with gr.Row():
|
228 |
report_selector_dd = gr.Dropdown(
|
229 |
label="Report Library",
|
|
|
232 |
info="Select a previously generated report to view its details."
|
233 |
)
|
234 |
|
|
|
235 |
agentic_report_display_md = gr.Markdown("Please select a report from the library to view it.")
|
236 |
|
237 |
if not AGENTIC_MODULES_LOADED:
|
|
|
289 |
outputs=[okr_detail_display_md]
|
290 |
)
|
291 |
|
292 |
+
# --- MODIFIED: Event binding for the report selector dropdown ---
|
293 |
+
# This now updates all agentic components, not just the report text.
|
294 |
if AGENTIC_MODULES_LOADED:
|
295 |
+
# Define the list of outputs that the handler function will update
|
296 |
+
report_selection_outputs = [
|
297 |
+
agentic_report_display_md,
|
298 |
+
key_results_cbg,
|
299 |
+
okr_detail_display_md,
|
300 |
+
orchestration_raw_results_st,
|
301 |
+
selected_key_result_ids_st,
|
302 |
+
key_results_for_selection_st
|
303 |
+
]
|
304 |
report_selector_dd.change(
|
305 |
+
fn=update_report_and_okr_display,
|
306 |
inputs=[report_selector_dd, token_state],
|
307 |
+
outputs=report_selection_outputs,
|
308 |
show_progress="minimal"
|
309 |
)
|
310 |
|
|
|
311 |
# --- EVENT HANDLING (SIMPLIFIED) ---
|
312 |
+
# The output list for the initial agentic load
|
313 |
agentic_display_outputs = [
|
314 |
agentic_report_display_md,
|
315 |
+
report_selector_dd,
|
316 |
key_results_cbg,
|
317 |
okr_detail_display_md,
|
318 |
orchestration_raw_results_st,
|
|
|
341 |
],
|
342 |
outputs=analytics_tab_instance.graph_refresh_outputs_list,
|
343 |
show_progress="full"
|
344 |
+
# Then, load and display the pre-computed agentic results, including reconstructed OKRs
|
345 |
).then(
|
346 |
+
fn=load_and_display_agentic_results,
|
347 |
+
inputs=[token_state], # Inputs simplified as the function now gets everything from state
|
348 |
+
outputs=agentic_display_outputs,
|
349 |
show_progress="minimal"
|
350 |
)
|
351 |
|