Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -26,6 +26,20 @@ from ui_generators import (
|
|
26 |
# Configure logging
|
27 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
# --- Guarded Analytics Fetch ---
|
30 |
def guarded_fetch_analytics(token_state):
|
31 |
"""Guarded call to fetch_and_render_analytics, ensuring token and basic data structures."""
|
@@ -64,6 +78,9 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
64 |
"bubble_posts_df": pd.DataFrame(), "fetch_count_for_api": 0,
|
65 |
"bubble_mentions_df": pd.DataFrame(),
|
66 |
"bubble_follower_stats_df": pd.DataFrame(),
|
|
|
|
|
|
|
67 |
"url_user_token_temp_storage": None
|
68 |
})
|
69 |
|
@@ -82,14 +99,17 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
82 |
# Process token, fetch Bubble data, determine sync needs
|
83 |
status_msg, new_state, btn_update = process_and_store_bubble_token(url_token, org_urn_val, current_state)
|
84 |
# Display initial dashboard content based on (potentially empty) Bubble data
|
85 |
-
dashboard_content = display_main_dashboard(new_state)
|
86 |
return status_msg, new_state, btn_update, dashboard_content
|
87 |
|
88 |
with gr.Tabs():
|
89 |
with gr.TabItem("1️⃣ Dashboard & Sync"):
|
90 |
gr.Markdown("System checks for existing data from Bubble. The 'Sync' button activates if new data needs to be fetched from LinkedIn based on the last sync times and data availability.")
|
91 |
sync_data_btn = gr.Button("🔄 Sync LinkedIn Data", variant="primary", visible=False, interactive=False)
|
|
|
|
|
92 |
sync_status_html_output = gr.HTML("<p style='text-align:center;'>Sync status will appear here.</p>")
|
|
|
93 |
dashboard_display_html = gr.HTML("<p style='text-align:center;'>Dashboard loading...</p>")
|
94 |
|
95 |
# Chain of events for initial load:
|
@@ -99,26 +119,31 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
99 |
outputs=[status_box, token_state, sync_data_btn, dashboard_display_html],
|
100 |
show_progress="full"
|
101 |
)
|
102 |
-
#
|
103 |
-
#
|
104 |
-
#
|
105 |
-
# Adding this for robustness, but ensure it doesn't cause unwanted multiple runs if state isn't managed carefully.
|
106 |
-
# Consider using a flag in token_state if multiple triggers become an issue.
|
107 |
-
# For now, relying on org_urn_display.change as the primary trigger post-load.
|
108 |
|
109 |
# When Sync button is clicked:
|
110 |
sync_data_btn.click(
|
111 |
-
fn=
|
|
|
|
|
|
|
|
|
|
|
112 |
inputs=[token_state],
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
115 |
).then(
|
116 |
-
fn=process_and_store_bubble_token, # Re-check sync status and update button
|
117 |
-
inputs=[url_user_token_display, org_urn_display, token_state],
|
118 |
-
outputs=[status_box, token_state, sync_data_btn],
|
119 |
-
show_progress=False
|
120 |
).then(
|
121 |
-
fn=display_main_dashboard, # Refresh dashboard display
|
122 |
inputs=[token_state],
|
123 |
outputs=[dashboard_display_html],
|
124 |
show_progress=False
|
@@ -182,4 +207,5 @@ if __name__ == "__main__":
|
|
182 |
logging.error("Matplotlib is not installed. Plots will not be generated. Please install it: pip install matplotlib")
|
183 |
|
184 |
# Launch the Gradio app
|
185 |
-
|
|
|
|
26 |
# Configure logging
|
27 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
28 |
|
29 |
+
# --- Helper function to load HTML animation ---
|
30 |
+
def get_sync_animation_html():
|
31 |
+
"""Loads the HTML content for the sync animation."""
|
32 |
+
try:
|
33 |
+
# Ensure this path is correct relative to where app.py is run
|
34 |
+
with open("sync_animation.html", "r", encoding="utf-8") as f:
|
35 |
+
return f.read()
|
36 |
+
except FileNotFoundError:
|
37 |
+
logging.error("sync_animation.html not found. Please ensure it's in the same directory as app.py.")
|
38 |
+
return "<p style='text-align:center; color: red;'>Animation file not found. Syncing...</p>"
|
39 |
+
except Exception as e:
|
40 |
+
logging.error(f"Error loading sync_animation.html: {e}")
|
41 |
+
return f"<p style='text-align:center; color: red;'>Error loading animation: {e}. Syncing...</p>"
|
42 |
+
|
43 |
# --- Guarded Analytics Fetch ---
|
44 |
def guarded_fetch_analytics(token_state):
|
45 |
"""Guarded call to fetch_and_render_analytics, ensuring token and basic data structures."""
|
|
|
78 |
"bubble_posts_df": pd.DataFrame(), "fetch_count_for_api": 0,
|
79 |
"bubble_mentions_df": pd.DataFrame(),
|
80 |
"bubble_follower_stats_df": pd.DataFrame(),
|
81 |
+
"bubble_operations_log_df": pd.DataFrame(), # Added from your state_manager logic
|
82 |
+
"mentions_should_sync_now": False, # Added from your state_manager logic
|
83 |
+
"fs_should_sync_now": False, # Added from your state_manager logic
|
84 |
"url_user_token_temp_storage": None
|
85 |
})
|
86 |
|
|
|
99 |
# Process token, fetch Bubble data, determine sync needs
|
100 |
status_msg, new_state, btn_update = process_and_store_bubble_token(url_token, org_urn_val, current_state)
|
101 |
# Display initial dashboard content based on (potentially empty) Bubble data
|
102 |
+
dashboard_content = display_main_dashboard(new_state) # Ensure this function handles potentially empty dfs
|
103 |
return status_msg, new_state, btn_update, dashboard_content
|
104 |
|
105 |
with gr.Tabs():
|
106 |
with gr.TabItem("1️⃣ Dashboard & Sync"):
|
107 |
gr.Markdown("System checks for existing data from Bubble. The 'Sync' button activates if new data needs to be fetched from LinkedIn based on the last sync times and data availability.")
|
108 |
sync_data_btn = gr.Button("🔄 Sync LinkedIn Data", variant="primary", visible=False, interactive=False)
|
109 |
+
|
110 |
+
# This HTML component will now display the animation during sync
|
111 |
sync_status_html_output = gr.HTML("<p style='text-align:center;'>Sync status will appear here.</p>")
|
112 |
+
|
113 |
dashboard_display_html = gr.HTML("<p style='text-align:center;'>Dashboard loading...</p>")
|
114 |
|
115 |
# Chain of events for initial load:
|
|
|
119 |
outputs=[status_box, token_state, sync_data_btn, dashboard_display_html],
|
120 |
show_progress="full"
|
121 |
)
|
122 |
+
# Note: The logic for also triggering on url_user_token_display.change has been removed
|
123 |
+
# as org_urn_display.change should be sufficient if get_url_user_token updates both,
|
124 |
+
# or if org_urn is the primary trigger. If issues arise, this can be revisited.
|
|
|
|
|
|
|
125 |
|
126 |
# When Sync button is clicked:
|
127 |
sync_data_btn.click(
|
128 |
+
fn=lambda: get_sync_animation_html(), # Step 1: Show animation
|
129 |
+
inputs=None,
|
130 |
+
outputs=[sync_status_html_output],
|
131 |
+
show_progress=False # Animation is its own progress indicator
|
132 |
+
).then(
|
133 |
+
fn=sync_all_linkedin_data_orchestrator, # Step 2: Run the actual sync
|
134 |
inputs=[token_state],
|
135 |
+
# sync_all_linkedin_data_orchestrator must return:
|
136 |
+
# 1. HTML string for status (replaces animation)
|
137 |
+
# 2. Updated token_state
|
138 |
+
outputs=[sync_status_html_output, token_state],
|
139 |
+
show_progress=False # Rely on animation; or set to "full" if you want Gradio's default too
|
140 |
).then(
|
141 |
+
fn=process_and_store_bubble_token, # Step 3: Re-check sync status and update button
|
142 |
+
inputs=[url_user_token_display, org_urn_display, token_state],
|
143 |
+
outputs=[status_box, token_state, sync_data_btn],
|
144 |
+
show_progress=False
|
145 |
).then(
|
146 |
+
fn=display_main_dashboard, # Step 4: Refresh dashboard display
|
147 |
inputs=[token_state],
|
148 |
outputs=[dashboard_display_html],
|
149 |
show_progress=False
|
|
|
207 |
logging.error("Matplotlib is not installed. Plots will not be generated. Please install it: pip install matplotlib")
|
208 |
|
209 |
# Launch the Gradio app
|
210 |
+
# Ensure share=False for local testing unless you intend to share it via Gradio's link
|
211 |
+
app.launch(server_name="0.0.0.0", server_port=7860, debug=True, share=False)
|