Spaces:
Running
Running
Update ui_generators.py
Browse files- ui_generators.py +81 -67
ui_generators.py
CHANGED
@@ -322,112 +322,126 @@ def run_follower_stats_tab_display(token_state):
|
|
322 |
follower_html_output = "\n".join(html_parts)
|
323 |
return follower_html_output, plot_monthly_gains, plot_seniority_dist, plot_industry_dist
|
324 |
|
325 |
-
|
326 |
-
# --- UI GENERATION LOGIC FOR ANALYTICS TAB ---
|
327 |
def create_analytics_plot_panel(plot_label_str, plot_id_str):
|
328 |
"""
|
329 |
Creates an individual plot panel with its plot component and action buttons.
|
|
|
330 |
Returns the panel (Column), plot component, and button components.
|
331 |
"""
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
# gr.HTML(f"<div class='plot-container' id='plot_container_{plot_id_str}'></div>") # If you were embedding plots differently
|
346 |
|
347 |
-
|
348 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
|
350 |
|
351 |
def build_analytics_tab_plot_area(plot_configs):
|
352 |
"""
|
353 |
-
Builds the main plot area for the Analytics tab, arranging plot panels into rows of two
|
|
|
354 |
|
355 |
Returns a tuple:
|
356 |
- plot_ui_objects (dict): Dictionary of plot UI objects.
|
357 |
- section_titles_map (dict): Dictionary mapping section names to their gr.Markdown title components.
|
358 |
"""
|
359 |
-
logging.info(f"Building plot area for {len(plot_configs)} analytics plots.")
|
360 |
plot_ui_objects = {}
|
361 |
-
section_titles_map = {}
|
362 |
-
|
363 |
-
current_section_title = ""
|
364 |
|
365 |
-
|
366 |
-
# This ensures that section_titles_map will have keys for all sections defined in plot_configs
|
367 |
-
# and that they are created in the UI in the correct order.
|
368 |
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
for config in plot_configs:
|
374 |
-
section_name = config["section"]
|
375 |
-
if section_name not in processed_sections_for_md_creation:
|
376 |
-
# Create the Markdown component for the section title
|
377 |
-
# The actual rendering order will be handled in the layout loop below
|
378 |
-
section_md_component = gr.Markdown(f"### {section_name}", visible=True) # Initially visible
|
379 |
-
section_titles_map[section_name] = section_md_component
|
380 |
-
processed_sections_for_md_creation.append(section_name)
|
381 |
-
logging.debug(f"Created Markdown component for section title: {section_name}")
|
382 |
-
|
383 |
-
# Layout loop: Iterate through plot_configs to place section titles and plot panels
|
384 |
-
i = 0
|
385 |
-
last_rendered_section_title = None # Keep track of the last section title that was actually rendered
|
386 |
-
|
387 |
-
while i < len(plot_configs):
|
388 |
-
config1 = plot_configs[i]
|
389 |
|
390 |
-
#
|
391 |
-
if
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
399 |
with gr.Row(equal_height=False):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
400 |
panel_col1, plot_comp1, bomb_btn1, explore_btn1, formula_btn1 = \
|
401 |
create_analytics_plot_panel(config1["label"], config1["id"])
|
402 |
plot_ui_objects[config1["id"]] = {
|
403 |
"plot_component": plot_comp1, "bomb_button": bomb_btn1,
|
404 |
"explore_button": explore_btn1, "formula_button": formula_btn1,
|
405 |
"label": config1["label"], "panel_component": panel_col1,
|
406 |
-
"section": config1["section"]
|
407 |
}
|
408 |
-
logging.debug(f"Created UI panel for plot_id: {config1['id']}")
|
409 |
-
|
410 |
|
411 |
-
|
412 |
-
|
|
|
413 |
# Check if the next plot is in the SAME section to place it in the same row
|
414 |
-
if config2["section"] ==
|
415 |
panel_col2, plot_comp2, bomb_btn2, explore_btn2, formula_btn2 = \
|
416 |
create_analytics_plot_panel(config2["label"], config2["id"])
|
417 |
plot_ui_objects[config2["id"]] = {
|
418 |
"plot_component": plot_comp2, "bomb_button": bomb_btn2,
|
419 |
"explore_button": explore_btn2, "formula_button": formula_btn2,
|
420 |
"label": config2["label"], "panel_component": panel_col2,
|
421 |
-
"section": config2["section"]
|
422 |
}
|
423 |
-
logging.debug(f"Created UI panel for plot_id: {config2['id']} in same row")
|
424 |
-
|
425 |
-
# If config2 is in a different section,
|
426 |
-
#
|
427 |
|
428 |
logging.info(f"Finished building plot area. Total plot objects: {len(plot_ui_objects)}. Section titles created: {len(section_titles_map)}")
|
429 |
if len(plot_ui_objects) != len(plot_configs):
|
430 |
logging.error(f"MISMATCH: Expected {len(plot_configs)} plot objects, but created {len(plot_ui_objects)}.")
|
431 |
|
432 |
-
# Return both the plot UI objects and the map of section title components
|
433 |
return plot_ui_objects, section_titles_map
|
|
|
322 |
follower_html_output = "\n".join(html_parts)
|
323 |
return follower_html_output, plot_monthly_gains, plot_seniority_dist, plot_industry_dist
|
324 |
|
|
|
|
|
325 |
def create_analytics_plot_panel(plot_label_str, plot_id_str):
|
326 |
"""
|
327 |
Creates an individual plot panel with its plot component and action buttons.
|
328 |
+
This version matches the original structure provided by the user.
|
329 |
Returns the panel (Column), plot component, and button components.
|
330 |
"""
|
331 |
+
# Values for BOMB_ICON, EXPLORE_ICON, FORMULA_ICON should be sourced from where they are defined,
|
332 |
+
# e.g., imported from config or passed as arguments if they vary.
|
333 |
+
# For consistency with app.py, let's assume they are globally accessible or correctly imported.
|
334 |
+
# If not, replace "BOMB_ICON", "EXPLORE_ICON", "FORMULA_ICON" with their actual string values like "�".
|
335 |
+
# This function will use string literals for icons if not found in global scope,
|
336 |
+
# but it's better practice to ensure they are consistently defined.
|
337 |
+
try:
|
338 |
+
from config import BOMB_ICON, EXPLORE_ICON, FORMULA_ICON # Try to import if they are in config
|
339 |
+
except ImportError:
|
340 |
+
logging.warning("Icons BOMB_ICON, EXPLORE_ICON, FORMULA_ICON not found in config, using defaults.")
|
341 |
+
BOMB_ICON = "💣"
|
342 |
+
EXPLORE_ICON = "🧭"
|
343 |
+
FORMULA_ICON = "ƒ"
|
|
|
344 |
|
345 |
+
|
346 |
+
with gr.Column() as panel_col:
|
347 |
+
with gr.Row(equal_height=False, variant="panel"):
|
348 |
+
plot_component = gr.Plot(label=plot_label_str, scale=8, show_label=True) # Ensure plot label is shown
|
349 |
+
with gr.Column(scale=2, min_width=100):
|
350 |
+
bomb_button = gr.Button(BOMB_ICON, variant="secondary", size="sm", elem_id=f"bomb_{plot_id_str}")
|
351 |
+
explore_button = gr.Button(EXPLORE_ICON, variant="secondary", size="sm", elem_id=f"explore_{plot_id_str}")
|
352 |
+
formula_button = gr.Button(FORMULA_ICON, variant="secondary", size="sm", elem_id=f"formula_{plot_id_str}")
|
353 |
+
logging.debug(f"Created analytics panel for: {plot_label_str} (ID: {plot_id_str}) using original structure.")
|
354 |
+
return panel_col, plot_component, bomb_button, explore_button, formula_button
|
355 |
|
356 |
|
357 |
def build_analytics_tab_plot_area(plot_configs):
|
358 |
"""
|
359 |
+
Builds the main plot area for the Analytics tab, arranging plot panels into rows of two,
|
360 |
+
with section titles appearing before their respective plots.
|
361 |
|
362 |
Returns a tuple:
|
363 |
- plot_ui_objects (dict): Dictionary of plot UI objects.
|
364 |
- section_titles_map (dict): Dictionary mapping section names to their gr.Markdown title components.
|
365 |
"""
|
366 |
+
logging.info(f"Building plot area for {len(plot_configs)} analytics plots with interleaved section titles.")
|
367 |
plot_ui_objects = {}
|
368 |
+
section_titles_map = {}
|
|
|
|
|
369 |
|
370 |
+
last_rendered_section = None # Keep track of the last section title rendered
|
|
|
|
|
371 |
|
372 |
+
idx = 0
|
373 |
+
while idx < len(plot_configs):
|
374 |
+
current_plot_config = plot_configs[idx]
|
375 |
+
current_section_name = current_plot_config["section"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
|
377 |
+
# If this plot belongs to a new section, display the section title
|
378 |
+
if current_section_name != last_rendered_section:
|
379 |
+
if current_section_name not in section_titles_map:
|
380 |
+
# Create the Markdown component for this section title if it doesn't exist
|
381 |
+
# This call to gr.Markdown() places it in the current layout flow.
|
382 |
+
section_md_component = gr.Markdown(f"### {current_section_name}", visible=True)
|
383 |
+
section_titles_map[current_section_name] = section_md_component
|
384 |
+
logging.debug(f"Rendered and stored Markdown for section: {current_section_name}")
|
385 |
+
else:
|
386 |
+
# If it exists, it means this section might have appeared before (e.g., non-contiguous sections in plot_configs)
|
387 |
+
# We need to ensure this existing component is "placed" again in the layout.
|
388 |
+
# In Gradio, re-referencing the component variable usually does this.
|
389 |
+
# This line might be needed if section_titles_map[current_section_name] was defined in a way that its
|
390 |
+
# previous rendering doesn't automatically carry to this new layout position.
|
391 |
+
# However, since we are iterating and creating if not exists, this branch might be less common
|
392 |
+
# if plot_configs are typically ordered by section.
|
393 |
+
# For safety, ensure it's visible.
|
394 |
+
section_titles_map[current_section_name].visible = True # Ensure it's visible
|
395 |
+
# section_titles_map[current_section_name] # Re-introduce to layout - often implicit
|
396 |
+
logging.debug(f"Re-using Markdown for section: {current_section_name}")
|
397 |
+
|
398 |
+
last_rendered_section = current_section_name
|
399 |
+
|
400 |
+
# Create a new row for the plot(s)
|
401 |
with gr.Row(equal_height=False):
|
402 |
+
# --- Process the first plot in the row (config1) ---
|
403 |
+
config1 = plot_configs[idx]
|
404 |
+
# Ensure it's from the current section we just titled (should be, due to loop structure)
|
405 |
+
if config1["section"] != current_section_name:
|
406 |
+
# This case should ideally not happen if logic is correct, means we might have skipped a section title
|
407 |
+
logging.warning(f"Plot {config1['id']} is in section {config1['section']} but current rendered section is {current_section_name}. Layout might be off.")
|
408 |
+
# Force rendering the correct section title if missed
|
409 |
+
if config1["section"] not in section_titles_map:
|
410 |
+
sec_md = gr.Markdown(f"### {config1['section']}", visible=True)
|
411 |
+
section_titles_map[config1["section"]] = sec_md
|
412 |
+
last_rendered_section = config1["section"] # Update tracker
|
413 |
+
|
414 |
panel_col1, plot_comp1, bomb_btn1, explore_btn1, formula_btn1 = \
|
415 |
create_analytics_plot_panel(config1["label"], config1["id"])
|
416 |
plot_ui_objects[config1["id"]] = {
|
417 |
"plot_component": plot_comp1, "bomb_button": bomb_btn1,
|
418 |
"explore_button": explore_btn1, "formula_button": formula_btn1,
|
419 |
"label": config1["label"], "panel_component": panel_col1,
|
420 |
+
"section": config1["section"]
|
421 |
}
|
422 |
+
logging.debug(f"Created UI panel for plot_id: {config1['id']} in section {config1['section']}")
|
423 |
+
idx += 1
|
424 |
|
425 |
+
# --- Process the second plot in the row (config2), if applicable ---
|
426 |
+
if idx < len(plot_configs):
|
427 |
+
config2 = plot_configs[idx]
|
428 |
# Check if the next plot is in the SAME section to place it in the same row
|
429 |
+
if config2["section"] == current_section_name:
|
430 |
panel_col2, plot_comp2, bomb_btn2, explore_btn2, formula_btn2 = \
|
431 |
create_analytics_plot_panel(config2["label"], config2["id"])
|
432 |
plot_ui_objects[config2["id"]] = {
|
433 |
"plot_component": plot_comp2, "bomb_button": bomb_btn2,
|
434 |
"explore_button": explore_btn2, "formula_button": formula_btn2,
|
435 |
"label": config2["label"], "panel_component": panel_col2,
|
436 |
+
"section": config2["section"]
|
437 |
}
|
438 |
+
logging.debug(f"Created UI panel for plot_id: {config2['id']} in same row, section {config2['section']}")
|
439 |
+
idx += 1
|
440 |
+
# If config2 is in a different section, the outer while loop will handle its title
|
441 |
+
# before creating its panel in a new row.
|
442 |
|
443 |
logging.info(f"Finished building plot area. Total plot objects: {len(plot_ui_objects)}. Section titles created: {len(section_titles_map)}")
|
444 |
if len(plot_ui_objects) != len(plot_configs):
|
445 |
logging.error(f"MISMATCH: Expected {len(plot_configs)} plot objects, but created {len(plot_ui_objects)}.")
|
446 |
|
|
|
447 |
return plot_ui_objects, section_titles_map
|