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)
         | 
|  |