Fix dashboard imports for Streamlit multi-page routing
- Add sys.path.insert at top of app.py and all 5 page files - Fix .streamlit/config.toml CORS/XSRF conflict - Remove duplicate st.set_page_config from page files - Verified: all pages import cleanly, dashboard boots via streamlit run - All 49 tests passing (31 original + 18 dashboard)
This commit is contained in:
@@ -9,7 +9,7 @@ font="sans serif"
|
|||||||
[server]
|
[server]
|
||||||
maxUploadSize=50
|
maxUploadSize=50
|
||||||
enableCORS=false
|
enableCORS=false
|
||||||
enableXsrfProtection=true
|
enableXsrfProtection=false
|
||||||
|
|
||||||
[browser]
|
[browser]
|
||||||
gatherUsageStats=false
|
gatherUsageStats=false
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
Multi-page Streamlit app. Run with: streamlit run dashboard/app.py
|
Multi-page Streamlit app. Run with: streamlit run dashboard/app.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Ensure project root is on path so 'dashboard' imports resolve
|
||||||
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
if str(PROJECT_ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(PROJECT_ROOT))
|
||||||
|
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
|
|
||||||
from dashboard.viz.components import inject_css
|
from dashboard.viz.components import inject_css
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys; from pathlib import Path; _p = Path(__file__).resolve().parent.parent.parent; str(_p) not in sys.path and sys.path.insert(0, str(_p))
|
||||||
"""Page 1 — Matchday Control Room.
|
"""Page 1 — Matchday Control Room.
|
||||||
|
|
||||||
KPI row, fixture difficulty heatmap, start/sit table, bump chart.
|
KPI row, fixture difficulty heatmap, start/sit table, bump chart.
|
||||||
@@ -59,7 +60,6 @@ def _build_fixture_heatmap(players, fixtures):
|
|||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
st.set_page_config(page_title="Matchday — Fantabeto", page_icon="⚽", layout="wide")
|
|
||||||
inject_css()
|
inject_css()
|
||||||
preds, fixtures, players, lineups, votes = _get_data()
|
preds, fixtures, players, lineups, votes = _get_data()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys; from pathlib import Path; _p = Path(__file__).resolve().parent.parent.parent; str(_p) not in sys.path and sys.path.insert(0, str(_p))
|
||||||
"""Page 2 — Player Intelligence.
|
"""Page 2 — Player Intelligence.
|
||||||
|
|
||||||
Radar charts, regression analysis, card risk, RAG news feed.
|
Radar charts, regression analysis, card risk, RAG news feed.
|
||||||
@@ -54,7 +55,6 @@ def _get_player_data(players, preds, votes, lineups, player_name):
|
|||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
st.set_page_config(page_title="Players — Fantabeto", page_icon="👤", layout="wide")
|
|
||||||
inject_css()
|
inject_css()
|
||||||
players, preds, votes, lineups = _get_data()
|
players, preds, votes, lineups = _get_data()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys; from pathlib import Path; _p = Path(__file__).resolve().parent.parent.parent; str(_p) not in sys.path and sys.path.insert(0, str(_p))
|
||||||
"""Page 3 — Auction War Room.
|
"""Page 3 — Auction War Room.
|
||||||
|
|
||||||
Budget waterfall, value scatter, grid-auction heatmap, budget slider simulator.
|
Budget waterfall, value scatter, grid-auction heatmap, budget slider simulator.
|
||||||
@@ -98,7 +99,6 @@ def _grid_heatmap(players):
|
|||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
st.set_page_config(page_title="Auction — Fantabeto", page_icon="💰", layout="wide")
|
|
||||||
inject_css()
|
inject_css()
|
||||||
players, preds = _get_data()
|
players, preds = _get_data()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys; from pathlib import Path; _p = Path(__file__).resolve().parent.parent.parent; str(_p) not in sys.path and sys.path.insert(0, str(_p))
|
||||||
"""Page 4 — Lineup Optimizer.
|
"""Page 4 — Lineup Optimizer.
|
||||||
|
|
||||||
SVG pitch with optimal XI, what-if toggles, opponent mirror.
|
SVG pitch with optimal XI, what-if toggles, opponent mirror.
|
||||||
@@ -84,7 +85,6 @@ def _opponent_lineup(preds, fixtures):
|
|||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
st.set_page_config(page_title="Lineup — Fantabeto", page_icon="📋", layout="wide")
|
|
||||||
inject_css()
|
inject_css()
|
||||||
preds, fixtures, players = _get_data()
|
preds, fixtures, players = _get_data()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys; from pathlib import Path; _p = Path(__file__).resolve().parent.parent.parent; str(_p) not in sys.path and sys.path.insert(0, str(_p))
|
||||||
"""Page 5 — Model Lab.
|
"""Page 5 — Model Lab.
|
||||||
|
|
||||||
SHAP beeswarm (placeholder), calibration curves, error violins, backtest.
|
SHAP beeswarm (placeholder), calibration curves, error violins, backtest.
|
||||||
@@ -112,7 +113,6 @@ def _feature_importance_plot(players):
|
|||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
st.set_page_config(page_title="Model Lab — Fantabeto", page_icon="🧪", layout="wide")
|
|
||||||
inject_css()
|
inject_css()
|
||||||
votes, preds, metrics, players = _get_data()
|
votes, preds, metrics, players = _get_data()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user