import gradio as gr import os print("APP STARTED", flush=True) from app.db.repo import init_db from app.ui.dashboard import build_dashboard, get_dashboard_data from app.controller.campaign_controller import on_campaign_select from app.controller.session_loader import load_google_ads_data from app.ads1.ads_analyst import run_ads_analyst_card from app.ads1.budget_optimizer import run_budget_optimizer_card import spaces print("šŸ”„ STEP 1: imports done", flush=True) # @spaces.GPU(duration=0) def run_ads_card(state): print("\nšŸ”„ [run_ads_card] ENTERED", flush=True) # if not state: # print("āŒ [run_ads_card] state is EMPTY", flush=True) # return "āš ļø Select a campaign first" # print("šŸ“¦ [run_ads_card] state received", flush=True) # dfs = state.get("full_dfs") # print("šŸ“Š [run_ads_card] extracted dfs:", type(dfs), flush=True) # result = run_ads_analyst_card(dfs) # print("āœ… [run_ads_card] returning result", flush=True) return "success" # def run_ads_card(state): # print("šŸ”„ FUNCTION CALLED", flush=True) # return "test" # def run_ads_card(state): # if not state: # return "āš ļø Select a campaign from the Dashboard tab first." # return run_ads_analyst_card(state["full_dfs"]) @spaces.GPU(duration=0) def run_budget_card(state): if not state: return "āš ļø Select a campaign from the Dashboard tab first." return run_budget_optimizer_card(state["full_dfs"]) def startup(): try: init_db() print("āœ… DB initialized successfully", flush=True) return "ok" except Exception as e: print("āš ļø DB failed:", e, flush=True) return "error" print("šŸ”„ STEP 2: DB init done", flush=True) # UI Optimization: Fetch data AFTER UI elements are drawn def initial_data_load(): print("šŸ”„ App loaded. Population of background states initiated...") dfs = load_google_ads_data() # Unpack dashboard metrics to fill the UI immediately spend, leads, cpl, count, formatted_df = get_dashboard_data() return dfs, formatted_df, spend, leads, cpl, count # def campaign_row_selected(evt: gr.SelectData, df, full_state): # if df.empty or full_state is None: # return gr.State(), "āš ļø Data state is missing. Please click Refresh." # row_index = evt.index[0] # campaign_name = df.iloc[row_index]["Campaign"] # campaign_state = on_campaign_select(full_state, campaign_name) # return campaign_state, f"## šŸ“Š Selected Campaign: {campaign_name}" def campaign_row_selected(df, full_state, evt: gr.SelectData): row_index = evt.index[0] campaign_name = df.iloc[row_index]["Campaign"] campaign_state = on_campaign_select(full_state, campaign_name) return campaign_state, f"## šŸ“Š Selected Campaign: {campaign_name}" print("šŸ”„ STEP 3: building UI", flush=True) with gr.Blocks() as demo: # Initialize components empty; populated safely via demo.load full_state = gr.State() campaign_state = gr.State() # df_state = gr.State() gr.Markdown("# šŸŽÆ Ads Dashboard") with gr.Tab("Dashboard"): # We modify build_dashboard to expose metric components for automated hydration gr.Markdown("## šŸ“Š Campaign Dashboard") with gr.Row(): total_spend = gr.Number(label="Total Spend") total_leads = gr.Number(label="Total Leads") average_cpl = gr.Number(label="Average CPL") active_campaigns = gr.Number(label="Active Campaigns") campaign_table = gr.Dataframe(label="Campaign Performance", interactive=True) refresh_btn = gr.Button("šŸ”„ Force Refresh Data") with gr.Tab("Analysis"): selected = gr.Markdown("šŸ‘ˆ Select a campaign from the Dashboard tab") output = gr.Markdown() with gr.Row(): gr.Button("šŸš€ Run Ads Analysis").click(run_ads_card, campaign_state, output) gr.Button("šŸ’° Run Budget Optimization").click(run_budget_card, campaign_state, output) # Core Event Bindings # campaign_table.change(fn=lambda x: x, inputs=[campaign_table], outputs=df_state) # campaign_table.select( # fn=campaign_row_selected, # inputs=[df_state, full_state], # outputs=[campaign_state, selected] # ) campaign_table.select( fn=campaign_row_selected, inputs=[campaign_table, full_state], outputs=[campaign_state, selected] ) # Button manual refresh refresh_btn.click( fn=initial_data_load, outputs=[full_state, campaign_table, total_spend, total_leads, average_cpl, active_campaigns] ) # ⚔ MAGIC FIX: App automatically loads data into UI components instantly on launch demo.load( fn=initial_data_load, outputs=[full_state, campaign_table, total_spend, total_leads, average_cpl, active_campaigns] ) demo.load(fn=startup, outputs=[]) if __name__ == "__main__": demo.launch()