Spaces:
Runtime error
Runtime error
| 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() |