Spaces:
Sleeping
Sleeping
Update ui/ui_generators.py
Browse files- ui/ui_generators.py +5 -87
ui/ui_generators.py
CHANGED
@@ -31,90 +31,7 @@ FORMULA_ICON = "ƒ"
|
|
31 |
ACTIVE_ICON = "❌ Close" # Ensure this matches app.py
|
32 |
|
33 |
|
34 |
-
|
35 |
-
"""Generates HTML for the main dashboard display using data from token_state."""
|
36 |
-
if not token_state or not token_state.get("token"):
|
37 |
-
logging.warning("Dashboard display: Access denied. No token available.")
|
38 |
-
return "❌ Access denied. No token available for dashboard."
|
39 |
-
|
40 |
-
html_parts = ["<div style='padding:10px;'><h3>Dashboard Overview</h3>"]
|
41 |
-
|
42 |
-
# Display Recent Posts
|
43 |
-
posts_df = token_state.get("bubble_posts_df", pd.DataFrame())
|
44 |
-
html_parts.append(f"<h4>Recent Posts ({len(posts_df)} in Bubble):</h4>")
|
45 |
-
if not posts_df.empty:
|
46 |
-
cols_to_show_posts = [col for col in [BUBBLE_POST_DATE_COLUMN_NAME, 'text', 'sentiment', 'summary_text', 'li_eb_label'] if col in posts_df.columns]
|
47 |
-
if not cols_to_show_posts:
|
48 |
-
html_parts.append("<p>No relevant post columns found to display.</p>")
|
49 |
-
else:
|
50 |
-
display_df_posts = posts_df.copy()
|
51 |
-
if BUBBLE_POST_DATE_COLUMN_NAME in display_df_posts.columns:
|
52 |
-
try:
|
53 |
-
# Ensure the date column is datetime before formatting
|
54 |
-
display_df_posts[BUBBLE_POST_DATE_COLUMN_NAME] = pd.to_datetime(display_df_posts[BUBBLE_POST_DATE_COLUMN_NAME], errors='coerce')
|
55 |
-
display_df_posts = display_df_posts.sort_values(by=BUBBLE_POST_DATE_COLUMN_NAME, ascending=False)
|
56 |
-
# Format for display after sorting
|
57 |
-
display_df_posts[BUBBLE_POST_DATE_COLUMN_NAME] = display_df_posts[BUBBLE_POST_DATE_COLUMN_NAME].dt.strftime(UI_DATE_FORMAT)
|
58 |
-
except Exception as e:
|
59 |
-
logging.error(f"Error formatting post dates for display: {e}")
|
60 |
-
html_parts.append("<p>Error formatting post dates.</p>")
|
61 |
-
html_parts.append(display_df_posts[cols_to_show_posts].head().to_html(escape=False, index=False, classes="table table-striped table-sm"))
|
62 |
-
else:
|
63 |
-
html_parts.append("<p>No posts loaded from Bubble.</p>")
|
64 |
-
html_parts.append("<hr/>")
|
65 |
-
|
66 |
-
# Display Recent Mentions
|
67 |
-
mentions_df = token_state.get("bubble_mentions_df", pd.DataFrame())
|
68 |
-
html_parts.append(f"<h4>Recent Mentions ({len(mentions_df)} in Bubble):</h4>")
|
69 |
-
if not mentions_df.empty:
|
70 |
-
cols_to_show_mentions = [col for col in [BUBBLE_MENTIONS_DATE_COLUMN_NAME, "mention_text", "sentiment_label"] if col in mentions_df.columns]
|
71 |
-
if not cols_to_show_mentions:
|
72 |
-
html_parts.append("<p>No relevant mention columns found to display.</p>")
|
73 |
-
else:
|
74 |
-
display_df_mentions = mentions_df.copy()
|
75 |
-
if BUBBLE_MENTIONS_DATE_COLUMN_NAME in display_df_mentions.columns:
|
76 |
-
try:
|
77 |
-
display_df_mentions[BUBBLE_MENTIONS_DATE_COLUMN_NAME] = pd.to_datetime(display_df_mentions[BUBBLE_MENTIONS_DATE_COLUMN_NAME], errors='coerce')
|
78 |
-
display_df_mentions = display_df_mentions.sort_values(by=BUBBLE_MENTIONS_DATE_COLUMN_NAME, ascending=False)
|
79 |
-
display_df_mentions[BUBBLE_MENTIONS_DATE_COLUMN_NAME] = display_df_mentions[BUBBLE_MENTIONS_DATE_COLUMN_NAME].dt.strftime(UI_DATE_FORMAT)
|
80 |
-
except Exception as e:
|
81 |
-
logging.error(f"Error formatting mention dates for display: {e}")
|
82 |
-
html_parts.append("<p>Error formatting mention dates.</p>")
|
83 |
-
html_parts.append(display_df_mentions[cols_to_show_mentions].head().to_html(escape=False, index=False, classes="table table-striped table-sm"))
|
84 |
-
else:
|
85 |
-
html_parts.append("<p>No mentions loaded from Bubble.</p>")
|
86 |
-
html_parts.append("<hr/>")
|
87 |
-
|
88 |
-
# Display Follower Statistics Summary
|
89 |
-
follower_stats_df = token_state.get("bubble_follower_stats_df", pd.DataFrame())
|
90 |
-
html_parts.append(f"<h4>Follower Statistics ({len(follower_stats_df)} entries in Bubble):</h4>")
|
91 |
-
if not follower_stats_df.empty:
|
92 |
-
monthly_gains = follower_stats_df[follower_stats_df[FOLLOWER_STATS_TYPE_COLUMN] == 'follower_gains_monthly'].copy()
|
93 |
-
if not monthly_gains.empty and FOLLOWER_STATS_CATEGORY_COLUMN in monthly_gains.columns and \
|
94 |
-
FOLLOWER_STATS_ORGANIC_COLUMN in monthly_gains.columns and FOLLOWER_STATS_PAID_COLUMN in monthly_gains.columns:
|
95 |
-
try:
|
96 |
-
monthly_gains.loc[:, FOLLOWER_STATS_CATEGORY_COLUMN_DT] = pd.to_datetime(monthly_gains[FOLLOWER_STATS_CATEGORY_COLUMN], errors='coerce')
|
97 |
-
monthly_gains_display = monthly_gains.sort_values(by=FOLLOWER_STATS_CATEGORY_COLUMN_DT, ascending=False)
|
98 |
-
latest_gain = monthly_gains_display.head(1).copy()
|
99 |
-
if not latest_gain.empty:
|
100 |
-
latest_gain.loc[:, FOLLOWER_STATS_CATEGORY_COLUMN] = latest_gain[FOLLOWER_STATS_CATEGORY_COLUMN_DT].dt.strftime(UI_DATE_FORMAT)
|
101 |
-
html_parts.append("<h5>Latest Monthly Follower Gain:</h5>")
|
102 |
-
html_parts.append(latest_gain[[FOLLOWER_STATS_CATEGORY_COLUMN, FOLLOWER_STATS_ORGANIC_COLUMN, FOLLOWER_STATS_PAID_COLUMN]].to_html(escape=True, index=False, classes="table table-sm"))
|
103 |
-
else:
|
104 |
-
html_parts.append("<p>No valid monthly follower gain data to display after processing.</p>")
|
105 |
-
except Exception as e:
|
106 |
-
logging.error(f"Error formatting follower gain dates for display: {e}", exc_info=True)
|
107 |
-
html_parts.append("<p>Error displaying monthly follower gain data.</p>")
|
108 |
-
else:
|
109 |
-
html_parts.append("<p>No monthly follower gain data or required columns are missing.</p>")
|
110 |
-
|
111 |
-
demographics_count = len(follower_stats_df[follower_stats_df[FOLLOWER_STATS_TYPE_COLUMN] != 'follower_gains_monthly'])
|
112 |
-
html_parts.append(f"<p>Total demographic entries (seniority, industry, etc.): {demographics_count}</p>")
|
113 |
-
else:
|
114 |
-
html_parts.append("<p>No follower statistics loaded from Bubble.</p>")
|
115 |
-
|
116 |
-
html_parts.append("</div>")
|
117 |
-
return "".join(html_parts)
|
118 |
|
119 |
|
120 |
def run_mentions_tab_display(token_state):
|
@@ -169,7 +86,7 @@ def run_mentions_tab_display(token_state):
|
|
169 |
finally:
|
170 |
# Ensure plt.close is called on the figure object, not plt itself if it's not the same
|
171 |
if fig_plot_local and fig_plot_local is not plt: # Check if fig_plot_local is a Figure object
|
172 |
-
|
173 |
return mentions_html_output, fig
|
174 |
|
175 |
|
@@ -243,7 +160,7 @@ def run_follower_stats_tab_display(token_state):
|
|
243 |
plot_monthly_gains = None
|
244 |
finally:
|
245 |
if fig_gains_local and fig_gains_local is not plt:
|
246 |
-
|
247 |
html_parts.append("<hr/>")
|
248 |
|
249 |
|
@@ -280,7 +197,7 @@ def run_follower_stats_tab_display(token_state):
|
|
280 |
plot_seniority_dist = None
|
281 |
finally:
|
282 |
if fig_seniority_local and fig_seniority_local is not plt:
|
283 |
-
|
284 |
html_parts.append("<hr/>")
|
285 |
|
286 |
# Industry Plot
|
@@ -427,3 +344,4 @@ def build_analytics_tab_plot_area(plot_configs):
|
|
427 |
logging.error(f"MISMATCH: Expected {len(plot_configs)} plot objects, but created {len(plot_ui_objects)}.")
|
428 |
|
429 |
return plot_ui_objects, section_titles_map
|
|
|
|
31 |
ACTIVE_ICON = "❌ Close" # Ensure this matches app.py
|
32 |
|
33 |
|
34 |
+
# Removed display_main_dashboard as its content is now directly embedded in app.py for the Home tab.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
|
37 |
def run_mentions_tab_display(token_state):
|
|
|
86 |
finally:
|
87 |
# Ensure plt.close is called on the figure object, not plt itself if it's not the same
|
88 |
if fig_plot_local and fig_plot_local is not plt: # Check if fig_plot_local is a Figure object
|
89 |
+
plt.close(fig_plot_local)
|
90 |
return mentions_html_output, fig
|
91 |
|
92 |
|
|
|
160 |
plot_monthly_gains = None
|
161 |
finally:
|
162 |
if fig_gains_local and fig_gains_local is not plt:
|
163 |
+
plt.close(fig_gains_local)
|
164 |
html_parts.append("<hr/>")
|
165 |
|
166 |
|
|
|
197 |
plot_seniority_dist = None
|
198 |
finally:
|
199 |
if fig_seniority_local and fig_seniority_local is not plt:
|
200 |
+
plt.close(fig_seniority_local)
|
201 |
html_parts.append("<hr/>")
|
202 |
|
203 |
# Industry Plot
|
|
|
344 |
logging.error(f"MISMATCH: Expected {len(plot_configs)} plot objects, but created {len(plot_ui_objects)}.")
|
345 |
|
346 |
return plot_ui_objects, section_titles_map
|
347 |
+
|