Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -25,6 +25,9 @@ from ui.ui_generators import (
|
|
25 |
create_enhanced_report_tab, # NEW: Import the function to build the enhanced Report tab UI
|
26 |
BOMB_ICON, EXPLORE_ICON, FORMULA_ICON, ACTIVE_ICON
|
27 |
)
|
|
|
|
|
|
|
28 |
from ui.analytics_plot_generator import update_analytics_plots_figures, create_placeholder_plot
|
29 |
from formulas import PLOT_FORMULAS
|
30 |
|
@@ -40,18 +43,17 @@ try:
|
|
40 |
from services.report_data_handler import fetch_and_reconstruct_data_from_bubble
|
41 |
# UI formatting functions
|
42 |
from ui.insights_ui_generator import (
|
43 |
-
format_report_for_display
|
44 |
-
extract_key_results_for_selection,
|
45 |
-
format_single_okr_for_display
|
46 |
)
|
|
|
|
|
47 |
AGENTIC_MODULES_LOADED = True
|
48 |
except ImportError as e:
|
49 |
logging.error(f"Could not import agentic pipeline display modules: {e}. Tabs 3 and 4 will be disabled.")
|
50 |
AGENTIC_MODULES_LOADED = False
|
51 |
# Placeholder functions to prevent app from crashing if imports fail
|
52 |
def load_and_display_agentic_results(*args, **kwargs):
|
53 |
-
# NOTE: This return signature MUST match agentic_display_outputs
|
54 |
-
# Adjusted return values for the new split report display components
|
55 |
empty_header_html = """
|
56 |
<div class="report-title">📊 Comprehensive Analysis Report</div>
|
57 |
<div class="report-subtitle">AI-Generated Insights from Your LinkedIn Data</div>
|
@@ -66,30 +68,22 @@ except ImportError as e:
|
|
66 |
</div>
|
67 |
</div>
|
68 |
"""
|
69 |
-
#
|
70 |
-
# Ensure the placeholder returns the correct number of gr.update components
|
71 |
-
# matching the `outputs` in the .then() call later.
|
72 |
return (
|
73 |
-
gr.update(value="Modules not loaded."), # agentic_pipeline_status_md
|
74 |
-
gr.update(choices=[], value=None),
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
gr.update(value=empty_body_markdown), # report_body_markdown_display
|
82 |
-
{} # reconstruction_cache_st
|
83 |
)
|
84 |
def fetch_and_reconstruct_data_from_bubble(*args, **kwargs):
|
85 |
return None, {}
|
86 |
def format_report_for_display(report_data):
|
87 |
# Placeholder for when modules are not loaded, returns structure matching the new design
|
88 |
return {'header_html': '<h1>Agentic modules not loaded.</h1>', 'body_markdown': 'Report display unavailable.'}
|
89 |
-
def extract_key_results_for_selection(okr_data):
|
90 |
-
return []
|
91 |
-
def format_single_okr_for_display(okr_data, **kwargs):
|
92 |
-
return "Agentic modules not loaded. OKR display unavailable."
|
93 |
|
94 |
|
95 |
# --- ANALYTICS TAB MODULE IMPORT ---
|
@@ -128,7 +122,9 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
128 |
|
129 |
# States for agentic results display
|
130 |
orchestration_raw_results_st = gr.State(None)
|
131 |
-
|
|
|
|
|
132 |
selected_key_result_ids_st = gr.State([])
|
133 |
|
134 |
# --- NEW: Session-specific cache for reconstructed OKR data ---
|
@@ -232,6 +228,14 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
232 |
gr.update(value=formatted_content_parts['body_markdown'])
|
233 |
)
|
234 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
235 |
|
236 |
with gr.Tabs() as tabs:
|
237 |
# --- NEW HOME TAB ---
|
@@ -259,48 +263,13 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
259 |
|
260 |
|
261 |
with gr.TabItem("4️⃣ Agentic OKRs & Tasks", id="tab_agentic_okrs", visible=AGENTIC_MODULES_LOADED):
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
key_results_cbg = gr.CheckboxGroup(label="Select Key Results", choices=[], value=[], interactive=True)
|
270 |
-
with gr.Column(scale=3):
|
271 |
-
gr.Markdown("### Detailed OKRs and Tasks")
|
272 |
-
okr_detail_display_md = gr.Markdown("I dettagli OKR appariranno qui.")
|
273 |
-
|
274 |
-
def update_okr_display_on_selection(selected_kr_ids: list, raw_results: dict, all_krs: list):
|
275 |
-
if not raw_results or not AGENTIC_MODULES_LOADED:
|
276 |
-
return gr.update(value="Nessun dato di analisi caricato.")
|
277 |
-
actionable_okrs = raw_results.get("actionable_okrs")
|
278 |
-
if not actionable_okrs or not isinstance(actionable_okrs.get("okrs"), list):
|
279 |
-
return gr.update(value="Nessun OKR trovato.")
|
280 |
-
okrs_list, kr_id_map = actionable_okrs["okrs"], {kr['unique_kr_id']: (kr['okr_index'], kr['kr_index']) for kr in all_krs}
|
281 |
-
selected_krs_by_okr_idx = defaultdict(list)
|
282 |
-
if selected_kr_ids:
|
283 |
-
for kr_id in selected_kr_ids:
|
284 |
-
if kr_id in kr_id_map:
|
285 |
-
okr_idx, kr_idx = kr_id_map[kr_id]
|
286 |
-
selected_krs_by_okr_idx[okr_idx].append(kr_idx)
|
287 |
-
output_parts = []
|
288 |
-
for okr_idx, okr in enumerate(okrs_list):
|
289 |
-
if not selected_kr_ids:
|
290 |
-
output_parts.append(format_single_okr_for_display(okr, okr_main_index=okr_idx))
|
291 |
-
elif okr_idx in selected_krs_by_okr_idx:
|
292 |
-
accepted_indices = selected_krs_by_okr_idx.get(okr_idx)
|
293 |
-
output_parts.append(format_single_okr_for_display(okr, accepted_kr_indices=accepted_indices, okr_main_index=okr_idx))
|
294 |
-
final_md = "\n\n---\n\n".join(output_parts) if output_parts else "Nessun OKR corrisponde alla selezione."
|
295 |
-
return gr.update(value=final_md)
|
296 |
-
|
297 |
-
if AGENTIC_MODULES_LOADED:
|
298 |
-
key_results_cbg.change(
|
299 |
-
fn=update_okr_display_on_selection,
|
300 |
-
inputs=[key_results_cbg, orchestration_raw_results_st, key_results_for_selection_st],
|
301 |
-
outputs=[okr_detail_display_md]
|
302 |
-
)
|
303 |
-
|
304 |
if AGENTIC_MODULES_LOADED:
|
305 |
report_selector_dd.change(
|
306 |
fn=update_report_display, # This now calls the enhanced function
|
@@ -312,17 +281,16 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
312 |
|
313 |
# Ensure agentic_display_outputs correctly maps to the newly created components
|
314 |
# This list must match the outputs of load_and_display_agentic_results
|
|
|
315 |
agentic_display_outputs = [
|
316 |
-
agentic_pipeline_status_md,
|
317 |
-
report_selector_dd,
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
report_body_markdown_display, # 8: New Markdown output for body
|
325 |
-
reconstruction_cache_st # 9: Reconstruction cache state
|
326 |
]
|
327 |
|
328 |
initial_load_event = org_urn_display.change(
|
@@ -341,11 +309,18 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
341 |
).then(
|
342 |
fn=load_and_display_agentic_results,
|
343 |
inputs=[token_state, reconstruction_cache_st],
|
344 |
-
# MODIFIED:
|
345 |
outputs=agentic_display_outputs,
|
346 |
show_progress="minimal"
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
)
|
348 |
|
|
|
349 |
if __name__ == "__main__":
|
350 |
if not os.environ.get(LINKEDIN_CLIENT_ID_ENV_VAR):
|
351 |
logging.warning(f"WARNING: '{LINKEDIN_CLIENT_ID_ENV_VAR}' is not set.")
|
@@ -357,4 +332,3 @@ if __name__ == "__main__":
|
|
357 |
logging.warning("WARNING: 'GEMINI_API_KEY' is not set.")
|
358 |
|
359 |
app.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)), debug=True)
|
360 |
-
|
|
|
25 |
create_enhanced_report_tab, # NEW: Import the function to build the enhanced Report tab UI
|
26 |
BOMB_ICON, EXPLORE_ICON, FORMULA_ICON, ACTIVE_ICON
|
27 |
)
|
28 |
+
# NEW: Import the OKR UI generator functions
|
29 |
+
from ui.okr_ui_generator import create_enhanced_okr_tab, format_okrs_for_enhanced_display, get_empty_okr_state
|
30 |
+
|
31 |
from ui.analytics_plot_generator import update_analytics_plots_figures, create_placeholder_plot
|
32 |
from formulas import PLOT_FORMULAS
|
33 |
|
|
|
43 |
from services.report_data_handler import fetch_and_reconstruct_data_from_bubble
|
44 |
# UI formatting functions
|
45 |
from ui.insights_ui_generator import (
|
46 |
+
format_report_for_display # This will now return header HTML and body Markdown
|
|
|
|
|
47 |
)
|
48 |
+
# The functions below are no longer needed due to the new OKR display approach and are removed from insights_ui_generator.py
|
49 |
+
# from ui.insights_ui_generator import extract_key_results_for_selection, format_single_okr_for_display
|
50 |
AGENTIC_MODULES_LOADED = True
|
51 |
except ImportError as e:
|
52 |
logging.error(f"Could not import agentic pipeline display modules: {e}. Tabs 3 and 4 will be disabled.")
|
53 |
AGENTIC_MODULES_LOADED = False
|
54 |
# Placeholder functions to prevent app from crashing if imports fail
|
55 |
def load_and_display_agentic_results(*args, **kwargs):
|
56 |
+
# NOTE: This return signature MUST match agentic_display_outputs length (now 8 values)
|
|
|
57 |
empty_header_html = """
|
58 |
<div class="report-title">📊 Comprehensive Analysis Report</div>
|
59 |
<div class="report-subtitle">AI-Generated Insights from Your LinkedIn Data</div>
|
|
|
68 |
</div>
|
69 |
</div>
|
70 |
"""
|
71 |
+
# Placeholder should return sensible defaults for all outputs
|
|
|
|
|
72 |
return (
|
73 |
+
gr.update(value="Modules not loaded."), # 0: agentic_pipeline_status_md
|
74 |
+
gr.update(choices=[], value=None), # 1: report_selector_dd
|
75 |
+
None, # 2: orchestration_raw_results_st - Placeholder should return None or an empty dict if it's the source for OKR display
|
76 |
+
[], # 3: selected_key_result_ids_st (internal state, not UI)
|
77 |
+
[], # 4: key_results_for_selection_st (internal state, not UI)
|
78 |
+
gr.update(value=empty_header_html), # 5: report_header_html_display
|
79 |
+
gr.update(value=empty_body_markdown), # 6: report_body_markdown_display
|
80 |
+
{} # 7: reconstruction_cache_st
|
|
|
|
|
81 |
)
|
82 |
def fetch_and_reconstruct_data_from_bubble(*args, **kwargs):
|
83 |
return None, {}
|
84 |
def format_report_for_display(report_data):
|
85 |
# Placeholder for when modules are not loaded, returns structure matching the new design
|
86 |
return {'header_html': '<h1>Agentic modules not loaded.</h1>', 'body_markdown': 'Report display unavailable.'}
|
|
|
|
|
|
|
|
|
87 |
|
88 |
|
89 |
# --- ANALYTICS TAB MODULE IMPORT ---
|
|
|
122 |
|
123 |
# States for agentic results display
|
124 |
orchestration_raw_results_st = gr.State(None)
|
125 |
+
# The following states are no longer directly used for UI display, but might be kept for
|
126 |
+
# internal logic if needed by other parts of the agentic pipeline that are not UI-related.
|
127 |
+
key_results_for_selection_st = gr.State([])
|
128 |
selected_key_result_ids_st = gr.State([])
|
129 |
|
130 |
# --- NEW: Session-specific cache for reconstructed OKR data ---
|
|
|
228 |
gr.update(value=formatted_content_parts['body_markdown'])
|
229 |
)
|
230 |
|
231 |
+
# NEW: Function to update the enhanced OKR display
|
232 |
+
def update_okr_tab_display(raw_results: dict):
|
233 |
+
"""
|
234 |
+
Updates the enhanced OKR HTML display based on the raw agentic results.
|
235 |
+
This replaces the old update_okr_display_on_selection which used a checkbox group.
|
236 |
+
"""
|
237 |
+
return gr.update(value=format_okrs_for_enhanced_display(raw_results))
|
238 |
+
|
239 |
|
240 |
with gr.Tabs() as tabs:
|
241 |
# --- NEW HOME TAB ---
|
|
|
263 |
|
264 |
|
265 |
with gr.TabItem("4️⃣ Agentic OKRs & Tasks", id="tab_agentic_okrs", visible=AGENTIC_MODULES_LOADED):
|
266 |
+
# NEW: Call the new function to create the enhanced OKR tab UI
|
267 |
+
okr_display_html = create_enhanced_okr_tab()
|
268 |
+
|
269 |
+
# The old UI components key_results_cbg and okr_detail_display_md are removed
|
270 |
+
# No need for individual KR selection anymore, the whole structure is displayed.
|
271 |
+
|
272 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
if AGENTIC_MODULES_LOADED:
|
274 |
report_selector_dd.change(
|
275 |
fn=update_report_display, # This now calls the enhanced function
|
|
|
281 |
|
282 |
# Ensure agentic_display_outputs correctly maps to the newly created components
|
283 |
# This list must match the outputs of load_and_display_agentic_results
|
284 |
+
# REMOVED: okr_display_html from this list, as it's updated separately
|
285 |
agentic_display_outputs = [
|
286 |
+
agentic_pipeline_status_md, # 0: Status Markdown (hidden)
|
287 |
+
report_selector_dd, # 1: Dropdown for selecting reports
|
288 |
+
orchestration_raw_results_st, # 2: Raw results state (source for OKR display)
|
289 |
+
selected_key_result_ids_st, # 3: Selected KR IDs state (internal state)
|
290 |
+
key_results_for_selection_st, # 4: All KRs for selection state (internal state)
|
291 |
+
report_header_html_display, # 5: New HTML output for report header
|
292 |
+
report_body_markdown_display, # 6: New Markdown output for report body
|
293 |
+
reconstruction_cache_st, # 7: Reconstruction cache state
|
|
|
|
|
294 |
]
|
295 |
|
296 |
initial_load_event = org_urn_display.change(
|
|
|
309 |
).then(
|
310 |
fn=load_and_display_agentic_results,
|
311 |
inputs=[token_state, reconstruction_cache_st],
|
312 |
+
# MODIFIED: Outputs list updated to remove okr_display_html
|
313 |
outputs=agentic_display_outputs,
|
314 |
show_progress="minimal"
|
315 |
+
).then(
|
316 |
+
# NEW: Call the update function for the enhanced OKR tab display, now as the only source for okr_display_html
|
317 |
+
fn=update_okr_tab_display,
|
318 |
+
inputs=[orchestration_raw_results_st], # Use the raw results state
|
319 |
+
outputs=[okr_display_html],
|
320 |
+
show_progress="minimal"
|
321 |
)
|
322 |
|
323 |
+
|
324 |
if __name__ == "__main__":
|
325 |
if not os.environ.get(LINKEDIN_CLIENT_ID_ENV_VAR):
|
326 |
logging.warning(f"WARNING: '{LINKEDIN_CLIENT_ID_ENV_VAR}' is not set.")
|
|
|
332 |
logging.warning("WARNING: 'GEMINI_API_KEY' is not set.")
|
333 |
|
334 |
app.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)), debug=True)
|
|