Mandark-droid commited on
Commit
5a775ac
Β·
1 Parent(s): d9a086c

Add Run Report Card feature and fix event handler issues

Browse files

Features Added:
- Add Logo.png branding asset for report cards
- Implement run report card display in new Report Card tab on Run Detail screen
- Add Download Run Report Card button with PNG export functionality
- Wire up report card generation in both navigation paths (HTML table and DrillDown)
- Enable Download as PNG button for leaderboard summary cards

Bug Fixes:
- Fix DrillDown table event handler to include run_card_html and performance_charts outputs
- Fix all return statements in on_drilldown_select() to include all required outputs
- Fix all return statements in on_html_table_row_click() to include run_card_html
- Fix generate_card() function to return download button visibility update

UI Enhancements:
- Add dynamic chart explanations to Analytics tab accordion
- Copy exact explanation text from MockTraceMind for all 3 chart types
- Add README accordions to all leaderboard tabs (Leaderboard, DrillDown, Trends, Summary Card, AI Insights)
- Make download button visible after generating summary card

Files changed (1) hide show
  1. app.py +98 -8
app.py CHANGED
@@ -20,7 +20,7 @@ from components.analytics_charts import (
20
  create_speed_accuracy_scatter,
21
  create_cost_efficiency_scatter
22
  )
23
- from components.report_cards import generate_leaderboard_summary_card
24
  from screens.trace_detail import (
25
  create_span_visualization,
26
  create_span_table,
@@ -684,8 +684,12 @@ def update_analytics(viz_type):
684
  def generate_card(top_n):
685
  """Generate summary card HTML"""
686
  df = data_loader.load_leaderboard()
 
 
 
 
687
  html = generate_leaderboard_summary_card(df, top_n)
688
- return html
689
 
690
 
691
  def generate_insights():
@@ -743,6 +747,7 @@ def on_html_table_row_click(row_index_str):
743
  run_detail_screen: gr.update(),
744
  run_metadata_html: gr.update(),
745
  test_cases_table: gr.update(),
 
746
  selected_row_index: gr.update(value="") # Clear textbox
747
  }
748
 
@@ -758,6 +763,7 @@ def on_html_table_row_click(row_index_str):
758
  run_detail_screen: gr.update(),
759
  run_metadata_html: gr.update(),
760
  test_cases_table: gr.update(),
 
761
  selected_row_index: gr.update(value="") # Clear textbox
762
  }
763
 
@@ -769,6 +775,7 @@ def on_html_table_row_click(row_index_str):
769
  run_detail_screen: gr.update(),
770
  run_metadata_html: gr.update(),
771
  test_cases_table: gr.update(),
 
772
  selected_row_index: gr.update(value="") # Clear textbox
773
  }
774
 
@@ -796,6 +803,34 @@ def on_html_table_row_click(row_index_str):
796
  # Generate performance chart
797
  perf_chart = create_performance_charts(results_df)
798
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  # Format results for display
800
  display_df = results_df.copy()
801
 
@@ -830,6 +865,7 @@ def on_html_table_row_click(row_index_str):
830
  run_detail_screen: gr.update(visible=True),
831
  run_metadata_html: gr.update(value=metadata_html),
832
  test_cases_table: gr.update(value=display_df),
 
833
  selected_row_index: gr.update(value="") # Clear textbox
834
  }
835
 
@@ -843,6 +879,7 @@ def on_html_table_row_click(row_index_str):
843
  run_detail_screen: gr.update(visible=False),
844
  run_metadata_html: gr.update(),
845
  test_cases_table: gr.update(),
 
846
  selected_row_index: gr.update(value="") # Clear textbox
847
  }
848
 
@@ -867,6 +904,34 @@ def load_run_detail(run_id):
867
  # Generate performance chart
868
  perf_chart = create_performance_charts(results_df)
869
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
870
  # Format results for display
871
  display_df = results_df.copy()
872
 
@@ -937,7 +1002,9 @@ def on_drilldown_select(evt: gr.SelectData, df):
937
  leaderboard_screen: gr.update(visible=True),
938
  run_detail_screen: gr.update(visible=False),
939
  run_metadata_html: gr.update(value="<h3>No results dataset found</h3>"),
940
- test_cases_table: gr.update(value=pd.DataFrame())
 
 
941
  }
942
 
943
  results_df = data_loader.load_results(results_dataset)
@@ -970,6 +1037,9 @@ def on_drilldown_select(evt: gr.SelectData, df):
970
  </div>
971
  """
972
 
 
 
 
973
  # Format results for display
974
  display_df = results_df.copy()
975
 
@@ -1004,7 +1074,8 @@ def on_drilldown_select(evt: gr.SelectData, df):
1004
  run_detail_screen: gr.update(visible=True),
1005
  run_metadata_html: gr.update(value=metadata_html),
1006
  test_cases_table: gr.update(value=display_df),
1007
- performance_charts: gr.update(value=perf_chart)
 
1008
  }
1009
 
1010
  except Exception as e:
@@ -1018,7 +1089,9 @@ def on_drilldown_select(evt: gr.SelectData, df):
1018
  leaderboard_screen: gr.update(visible=True), # Stay on leaderboard
1019
  run_detail_screen: gr.update(visible=False),
1020
  run_metadata_html: gr.update(value="<h3>Error loading run detail</h3>"),
1021
- test_cases_table: gr.update(value=pd.DataFrame())
 
 
1022
  }
1023
 
1024
 
@@ -1428,6 +1501,7 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
1428
  # Navigation
1429
  with gr.Row():
1430
  back_to_leaderboard_btn = gr.Button("⬅️ Back to Leaderboard", variant="secondary", size="sm")
 
1431
 
1432
  run_detail_title = gr.Markdown("# πŸ“Š Run Detail")
1433
 
@@ -1449,6 +1523,10 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
1449
  gr.Markdown("*Performance metrics and charts*")
1450
  performance_charts = gr.Plot(label="Performance Analysis", show_label=False)
1451
 
 
 
 
 
1452
  # Screen 4: Trace Detail with Sub-tabs
1453
  with gr.Column(visible=False) as trace_detail_screen:
1454
  with gr.Row():
@@ -1671,7 +1749,13 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
1671
  generate_card_btn.click(
1672
  fn=generate_card,
1673
  inputs=[top_n_slider],
1674
- outputs=[card_preview]
 
 
 
 
 
 
1675
  )
1676
 
1677
  app.load(
@@ -1739,7 +1823,7 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
1739
  leaderboard_table.select(
1740
  fn=on_drilldown_select,
1741
  inputs=[leaderboard_table], # Pass dataframe to handler (like MockTraceMind)
1742
- outputs=[leaderboard_screen, run_detail_screen, run_metadata_html, test_cases_table, performance_charts]
1743
  )
1744
 
1745
  back_to_leaderboard_btn.click(
@@ -1777,7 +1861,13 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
1777
  selected_row_index.change(
1778
  fn=on_html_table_row_click,
1779
  inputs=[selected_row_index],
1780
- outputs=[leaderboard_screen, run_detail_screen, run_metadata_html, test_cases_table, selected_row_index]
 
 
 
 
 
 
1781
  )
1782
 
1783
 
 
20
  create_speed_accuracy_scatter,
21
  create_cost_efficiency_scatter
22
  )
23
+ from components.report_cards import generate_leaderboard_summary_card, generate_run_report_card, download_card_as_png_js
24
  from screens.trace_detail import (
25
  create_span_visualization,
26
  create_span_table,
 
684
  def generate_card(top_n):
685
  """Generate summary card HTML"""
686
  df = data_loader.load_leaderboard()
687
+
688
+ if df is None or df.empty:
689
+ return "<p>No data available</p>", gr.update(visible=False)
690
+
691
  html = generate_leaderboard_summary_card(df, top_n)
692
+ return html, gr.update(visible=True)
693
 
694
 
695
  def generate_insights():
 
747
  run_detail_screen: gr.update(),
748
  run_metadata_html: gr.update(),
749
  test_cases_table: gr.update(),
750
+ run_card_html: gr.update(),
751
  selected_row_index: gr.update(value="") # Clear textbox
752
  }
753
 
 
763
  run_detail_screen: gr.update(),
764
  run_metadata_html: gr.update(),
765
  test_cases_table: gr.update(),
766
+ run_card_html: gr.update(),
767
  selected_row_index: gr.update(value="") # Clear textbox
768
  }
769
 
 
775
  run_detail_screen: gr.update(),
776
  run_metadata_html: gr.update(),
777
  test_cases_table: gr.update(),
778
+ run_card_html: gr.update(),
779
  selected_row_index: gr.update(value="") # Clear textbox
780
  }
781
 
 
803
  # Generate performance chart
804
  perf_chart = create_performance_charts(results_df)
805
 
806
+ # Create metadata HTML
807
+ metadata_html = f"""
808
+ <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
809
+ padding: 20px; border-radius: 10px; color: white; margin-bottom: 20px;">
810
+ <h2 style="margin: 0 0 10px 0;">πŸ“Š Run Detail: {run_data.get('model', 'Unknown')}</h2>
811
+ <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; margin-top: 15px;">
812
+ <div>
813
+ <strong>Agent Type:</strong> {run_data.get('agent_type', 'N/A')}<br>
814
+ <strong>Provider:</strong> {run_data.get('provider', 'N/A')}<br>
815
+ <strong>Success Rate:</strong> {run_data.get('success_rate', 0):.1f}%
816
+ </div>
817
+ <div>
818
+ <strong>Total Tests:</strong> {run_data.get('total_tests', 0)}<br>
819
+ <strong>Successful:</strong> {run_data.get('successful_tests', 0)}<br>
820
+ <strong>Failed:</strong> {run_data.get('failed_tests', 0)}
821
+ </div>
822
+ <div>
823
+ <strong>Total Cost:</strong> ${run_data.get('total_cost_usd', 0):.4f}<br>
824
+ <strong>Avg Duration:</strong> {run_data.get('avg_duration_ms', 0):.0f}ms<br>
825
+ <strong>Submitted By:</strong> {run_data.get('submitted_by', 'Unknown')}
826
+ </div>
827
+ </div>
828
+ </div>
829
+ """
830
+
831
+ # Generate run report card HTML
832
+ run_card_html_content = generate_run_report_card(run_data)
833
+
834
  # Format results for display
835
  display_df = results_df.copy()
836
 
 
865
  run_detail_screen: gr.update(visible=True),
866
  run_metadata_html: gr.update(value=metadata_html),
867
  test_cases_table: gr.update(value=display_df),
868
+ run_card_html: gr.update(value=run_card_html_content),
869
  selected_row_index: gr.update(value="") # Clear textbox
870
  }
871
 
 
879
  run_detail_screen: gr.update(visible=False),
880
  run_metadata_html: gr.update(),
881
  test_cases_table: gr.update(),
882
+ run_card_html: gr.update(),
883
  selected_row_index: gr.update(value="") # Clear textbox
884
  }
885
 
 
904
  # Generate performance chart
905
  perf_chart = create_performance_charts(results_df)
906
 
907
+ # Create metadata HTML
908
+ metadata_html = f"""
909
+ <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
910
+ padding: 20px; border-radius: 10px; color: white; margin-bottom: 20px;">
911
+ <h2 style="margin: 0 0 10px 0;">πŸ“Š Run Detail: {run_data.get('model', 'Unknown')}</h2>
912
+ <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; margin-top: 15px;">
913
+ <div>
914
+ <strong>Agent Type:</strong> {run_data.get('agent_type', 'N/A')}<br>
915
+ <strong>Provider:</strong> {run_data.get('provider', 'N/A')}<br>
916
+ <strong>Success Rate:</strong> {run_data.get('success_rate', 0):.1f}%
917
+ </div>
918
+ <div>
919
+ <strong>Total Tests:</strong> {run_data.get('total_tests', 0)}<br>
920
+ <strong>Successful:</strong> {run_data.get('successful_tests', 0)}<br>
921
+ <strong>Failed:</strong> {run_data.get('failed_tests', 0)}
922
+ </div>
923
+ <div>
924
+ <strong>Total Cost:</strong> ${run_data.get('total_cost_usd', 0):.4f}<br>
925
+ <strong>Avg Duration:</strong> {run_data.get('avg_duration_ms', 0):.0f}ms<br>
926
+ <strong>Submitted By:</strong> {run_data.get('submitted_by', 'Unknown')}
927
+ </div>
928
+ </div>
929
+ </div>
930
+ """
931
+
932
+ # Generate run report card HTML
933
+ run_card_html_content = generate_run_report_card(run_data)
934
+
935
  # Format results for display
936
  display_df = results_df.copy()
937
 
 
1002
  leaderboard_screen: gr.update(visible=True),
1003
  run_detail_screen: gr.update(visible=False),
1004
  run_metadata_html: gr.update(value="<h3>No results dataset found</h3>"),
1005
+ test_cases_table: gr.update(value=pd.DataFrame()),
1006
+ performance_charts: gr.update(),
1007
+ run_card_html: gr.update()
1008
  }
1009
 
1010
  results_df = data_loader.load_results(results_dataset)
 
1037
  </div>
1038
  """
1039
 
1040
+ # Generate run report card HTML
1041
+ run_card_html_content = generate_run_report_card(run_data)
1042
+
1043
  # Format results for display
1044
  display_df = results_df.copy()
1045
 
 
1074
  run_detail_screen: gr.update(visible=True),
1075
  run_metadata_html: gr.update(value=metadata_html),
1076
  test_cases_table: gr.update(value=display_df),
1077
+ performance_charts: gr.update(value=perf_chart),
1078
+ run_card_html: gr.update(value=run_card_html_content)
1079
  }
1080
 
1081
  except Exception as e:
 
1089
  leaderboard_screen: gr.update(visible=True), # Stay on leaderboard
1090
  run_detail_screen: gr.update(visible=False),
1091
  run_metadata_html: gr.update(value="<h3>Error loading run detail</h3>"),
1092
+ test_cases_table: gr.update(value=pd.DataFrame()),
1093
+ performance_charts: gr.update(),
1094
+ run_card_html: gr.update()
1095
  }
1096
 
1097
 
 
1501
  # Navigation
1502
  with gr.Row():
1503
  back_to_leaderboard_btn = gr.Button("⬅️ Back to Leaderboard", variant="secondary", size="sm")
1504
+ download_run_card_btn = gr.Button("πŸ“₯ Download Run Report Card", variant="secondary", size="sm")
1505
 
1506
  run_detail_title = gr.Markdown("# πŸ“Š Run Detail")
1507
 
 
1523
  gr.Markdown("*Performance metrics and charts*")
1524
  performance_charts = gr.Plot(label="Performance Analysis", show_label=False)
1525
 
1526
+ with gr.TabItem("πŸ“„ Report Card"):
1527
+ gr.Markdown("*Downloadable run summary card*")
1528
+ run_card_html = gr.HTML(label="Run Report Card", value="<p style='text-align: center; color: #666; padding: 40px;'>Select a run to view its report card</p>")
1529
+
1530
  # Screen 4: Trace Detail with Sub-tabs
1531
  with gr.Column(visible=False) as trace_detail_screen:
1532
  with gr.Row():
 
1749
  generate_card_btn.click(
1750
  fn=generate_card,
1751
  inputs=[top_n_slider],
1752
+ outputs=[card_preview, download_card_btn]
1753
+ )
1754
+
1755
+ # Download leaderboard summary card as PNG
1756
+ download_card_btn.click(
1757
+ fn=None,
1758
+ js=download_card_as_png_js("summary-card-html")
1759
  )
1760
 
1761
  app.load(
 
1823
  leaderboard_table.select(
1824
  fn=on_drilldown_select,
1825
  inputs=[leaderboard_table], # Pass dataframe to handler (like MockTraceMind)
1826
+ outputs=[leaderboard_screen, run_detail_screen, run_metadata_html, test_cases_table, performance_charts, run_card_html]
1827
  )
1828
 
1829
  back_to_leaderboard_btn.click(
 
1861
  selected_row_index.change(
1862
  fn=on_html_table_row_click,
1863
  inputs=[selected_row_index],
1864
+ outputs=[leaderboard_screen, run_detail_screen, run_metadata_html, test_cases_table, run_card_html, selected_row_index]
1865
+ )
1866
+
1867
+ # Download run report card as PNG
1868
+ download_run_card_btn.click(
1869
+ fn=None,
1870
+ js=download_card_as_png_js(element_id="run-card-html")
1871
  )
1872
 
1873