auto-bold-gen / app.py
mmrech's picture
Deploy Gradio app with multiple files
7efdf62 verified
import gradio as gr
import pandas as pd
from data_utils import generate_initial_data, process_data, handle_data_selection
# --- Configuration ---
initial_df = generate_initial_data()
initial_regions = ["All"] + sorted(initial_df['Region'].unique().tolist())
MAX_PROFIT_SLIDER = initial_df['Profit'].max()
MIN_PROFIT_SLIDER = initial_df['Profit'].min()
def plot_data_updates(df, region, profit_limit):
"""Processes filtered data and returns updated plot objects."""
if df is None or (isinstance(df, pd.DataFrame) and df.empty):
gr.Warning("No data available to display.")
return gr.Plot(None), gr.Plot(None)
try:
daily_summary, product_summary = process_data(df, region, profit_limit)
if daily_summary.empty and product_summary.empty:
gr.Warning("No data matches the current filter criteria.")
return gr.Plot(None), gr.Plot(None)
# Line Plot: Daily Sales Trend
line_plot_update = gr.LinePlot(
daily_summary,
x="Day",
y="Total Sales",
title=f"Daily Sales Trend (Region: {region})",
tooltip=["Day", "Total Sales"],
height=300
)
# Bar Plot: Product Quantity Breakdown
bar_plot_update = gr.BarPlot(
product_summary,
x="Product",
y="Quantity",
title="Total Quantity by Product",
color="Product",
tooltip=["Product", "Quantity"],
height=300
)
return line_plot_update, bar_plot_update
except Exception as e:
gr.Error(f"An error occurred during data processing: {e}")
return gr.Plot(None), gr.Plot(None)
def respond(message, history):
"""Simple chat response function."""
if message.strip():
history = history + [[message, "You said: " + message]]
return "", history
# --- Gradio Blocks Definition ---
with gr.Blocks(theme=gr.themes.Soft(), title="Interactive Data Reporter", fill_height=True) as demo:
gr.HTML(
"<div style='text-align: center; padding: 10px; border-bottom: 1px solid #f0f0f0;'>"
"<h1>Interactive Sales Data Dashboard</h1>"
"<p>Analyze synthetic sales data using linked controls and dynamic charts.</p>"
"<p>Built with <a href='https://huggingface.co/spaces/akhaliq/anycoder' target='_blank' style='color: blue; text-decoration: none;'>anycoder</a></p>"
"</div>"
)
# State to hold the original, potentially edited dataset
raw_data_state = gr.State(value=initial_df)
with gr.Row(equal_height=False):
# --- Column 1: Controls and Raw Data Display ---
with gr.Column(scale=2, min_width=400):
with gr.Accordion("Filters and Controls", open=True):
region_dropdown = gr.Dropdown(
choices=initial_regions,
value="All",
label="Select Region",
)
profit_slider = gr.Slider(
minimum=MIN_PROFIT_SLIDER,
maximum=MAX_PROFIT_SLIDER,
value=MIN_PROFIT_SLIDER,
step=50,
label="Minimum Profit Filter",
interactive=True
)
refresh_btn = gr.Button("Apply Filters & Update Plots", variant="primary")
with gr.Group():
# Dataframe for raw data display and editing
raw_data_display = gr.Dataframe(
value=initial_df,
headers=initial_df.columns.tolist(),
datatype=['date', 'str', 'str', 'number', 'number', 'number', 'number'],
interactive=True, # Allow user edits
label="Raw Sales Data (Click a row to see details)",
height=500,
show_row_numbers=True
)
selection_output = gr.Textbox(
label="Selected Row Details",
lines=4,
interactive=False,
placeholder="Click on a row in the table above to see details here."
)
# --- Column 2: Visualizations ---
with gr.Column(scale=3, min_width=500):
with gr.Tabs():
with gr.TabItem("Graphical Report"):
with gr.Row():
line_plot_out = gr.LinePlot(label="Sales Trend Over Time")
with gr.Row():
bar_plot_out = gr.BarPlot(label="Product Quantity Breakdown")
with gr.TabItem("Chat"):
chatbot = gr.Chatbot()
msg = gr.Textbox(placeholder="Type your message here...", show_label=False)
msg.submit(respond, inputs=[msg, chatbot], outputs=[msg, chatbot])
# --- Event Listeners and Interactions ---
# Define the inputs and outputs for the main plotting function
inputs_for_plot = [raw_data_state, region_dropdown, profit_slider]
outputs_for_plot = [line_plot_out, bar_plot_out]
# 1. Update plots when the "Apply" button is clicked
refresh_btn.click(plot_data_updates, inputs=inputs_for_plot, outputs=outputs_for_plot)
# 2. Update plots when filter controls are changed (live update)
region_dropdown.change(plot_data_updates, inputs=inputs_for_plot, outputs=outputs_for_plot)
profit_slider.release(plot_data_updates, inputs=inputs_for_plot, outputs=outputs_for_plot)
# 3. Update the shared `raw_data_state` if a user edits the DataFrame component.
# This ensures that plot updates use the latest user-modified data.
def update_state(df):
return df
raw_data_display.edit(
update_state,
inputs=[raw_data_display],
outputs=[raw_data_state],
queue=False # Use a fast, non-blocking update for the state
)
# 4. Handle DataFrame row selection to show details
raw_data_display.select(
handle_data_selection,
inputs=[raw_data_state],
outputs=[selection_output]
)
# 5. Initial plot generation on application load
demo.load(plot_data_updates, inputs=inputs_for_plot, outputs=outputs_for_plot)
demo.queue().launch()