nesticot commited on
Commit
9dc0942
·
verified ·
1 Parent(s): 4a8cb4c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -1
app.py CHANGED
@@ -11,6 +11,84 @@ theme.tabulator_site()
11
  # CONSTANTS & CONFIGURATION
12
  # =============================================================================
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  # Initialize scrapers
15
  scraper = api_scraper.MLB_Scrape()
16
  df_year_old_group = pl.read_parquet('pitch_data_agg_2024.parquet')
@@ -260,8 +338,22 @@ def merge_and_format(df_group, old_df, cols_sub=None, cols_pct=None, suffix="_ol
260
  return df_merge
261
 
262
 
263
- # UI Definition
 
 
 
264
  app_ui = ui.page_fluid(
 
 
 
 
 
 
 
 
 
 
 
265
  ui.card(
266
  ui.card_header("2025 MLB Pitch Data App"),
267
  ui.row(
 
11
  # CONSTANTS & CONFIGURATION
12
  # =============================================================================
13
 
14
+ # Custom CSS for loading spinner
15
+ CUSTOM_CSS = """
16
+ <style>
17
+ /* Loading Overlay */
18
+ .loading-overlay {
19
+ position: fixed;
20
+ top: 0;
21
+ left: 0;
22
+ width: 100%;
23
+ height: 100%;
24
+ background: rgba(255, 255, 255, 0.92);
25
+ display: flex;
26
+ flex-direction: column;
27
+ justify-content: center;
28
+ align-items: center;
29
+ z-index: 9999;
30
+ opacity: 0;
31
+ visibility: hidden;
32
+ transition: opacity 0.3s ease, visibility 0.3s ease;
33
+ }
34
+
35
+ .loading-overlay.active {
36
+ opacity: 1;
37
+ visibility: visible;
38
+ }
39
+
40
+ /* Spinner */
41
+ .spinner {
42
+ width: 60px;
43
+ height: 60px;
44
+ border: 5px solid #e0e0e0;
45
+ border-top: 5px solid #0d6efd;
46
+ border-radius: 50%;
47
+ animation: spin 1s linear infinite;
48
+ margin-bottom: 20px;
49
+ }
50
+
51
+ @keyframes spin {
52
+ 0% { transform: rotate(0deg); }
53
+ 100% { transform: rotate(360deg); }
54
+ }
55
+
56
+ .loading-text {
57
+ font-size: 18px;
58
+ color: #333;
59
+ font-weight: 500;
60
+ }
61
+
62
+ /* Hide content while loading initially */
63
+ .shiny-busy ~ .container-fluid .card {
64
+ opacity: 0.6;
65
+ pointer-events: none;
66
+ }
67
+ </style>
68
+ """
69
+
70
+ # Custom JavaScript for busy state handling
71
+ CUSTOM_JS = """
72
+ <script>
73
+ $(document).ready(function() {
74
+ // Show loading overlay when Shiny is busy
75
+ $(document).on('shiny:busy', function(event) {
76
+ $('.loading-overlay').addClass('active');
77
+ });
78
+
79
+ // Hide loading overlay when Shiny is idle
80
+ $(document).on('shiny:idle', function(event) {
81
+ $('.loading-overlay').removeClass('active');
82
+ });
83
+
84
+ // Show loading on refresh button click
85
+ $(document).on('click', '#refresh', function() {
86
+ $('.loading-overlay').addClass('active');
87
+ });
88
+ });
89
+ </script>
90
+ """
91
+
92
  # Initialize scrapers
93
  scraper = api_scraper.MLB_Scrape()
94
  df_year_old_group = pl.read_parquet('pitch_data_agg_2024.parquet')
 
338
  return df_merge
339
 
340
 
341
+ # =============================================================================
342
+ # UI DEFINITION
343
+ # =============================================================================
344
+
345
  app_ui = ui.page_fluid(
346
+ # Inject custom CSS and JS
347
+ ui.head_content(ui.HTML(CUSTOM_CSS), ui.HTML(CUSTOM_JS)),
348
+
349
+ # Loading overlay
350
+ ui.div(
351
+ ui.div(class_="spinner"),
352
+ ui.div("Loading data...", class_="loading-text"),
353
+ class_="loading-overlay",
354
+ id="loading-overlay"
355
+ ),
356
+
357
  ui.card(
358
  ui.card_header("2025 MLB Pitch Data App"),
359
  ui.row(