diff --git a/README.md b/README.md index 7d080b8bb..147598f8e 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,11 @@ Preswald tracks state and dependencies, so computations update only when needed # **🚀 Getting Started** +```markdown ## **Installation** -First, install Preswald using pip. https://pypi.org/project/preswald/ +First, install Preswald using pip (requires Python 3.7+) +[Preswald on PyPI](https://pypi.org/project/preswald/) ```bash pip install preswald @@ -72,6 +74,12 @@ or uv pip install preswald ``` +**Note:** +If you encounter issues during installation, make sure you have an updated version of pip: + +```bash +pip install --upgrade pip + ![Demo GIF](assets/demo1.gif) ## **👩‍💻 Quick Start** @@ -158,6 +166,7 @@ The first time you deploy, you'll be prompted to enter your **GitHub username** Now your app is live, shareable, and scalable—without any extra setup. + ## **🔧 Configuration** Preswald uses `preswald.toml` for project settings and theming. It’s straightforward, and it makes your app look polished. @@ -189,6 +198,25 @@ format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
+## 🛠 Troubleshooting + +### Port already in use + +If you run `preswald run` and see an error like: +``` +OSError: [Errno 98] Address already in use +``` +it means another application is already using the default port (8501). + +You have two options: +- Stop the application that's using port 8501 +- Or run Preswald on a different port: + +```bash +preswald run --port 8502 + + + ## **📚 Documentation** We’re here to help! Check out our full documentation at [Preswald Docs](https://docs.preswald.com/). diff --git a/frontend/src/components/pages/Dashboard.jsx b/frontend/src/components/pages/Dashboard.jsx index 80b839006..35ad51c7d 100644 --- a/frontend/src/components/pages/Dashboard.jsx +++ b/frontend/src/components/pages/Dashboard.jsx @@ -23,21 +23,24 @@ const Dashboard = ({ components, error, handleComponentUpdate }) => { ); } - if (!isValidComponents) { + if (!components || !components.rows) { return ( -
- +
+

+ {!components + ? 'Loading components...' + : 'Invalid components data. Please check your configuration or data source.'} +

); } - + if (components.rows.length === 0) { return (
-

No components to display

+

+ No components to display. Try running a query or verifying your configuration settings. +

); } diff --git a/preswald/interfaces/data.py b/preswald/interfaces/data.py index 5b2f38be2..d6e6a6208 100644 --- a/preswald/interfaces/data.py +++ b/preswald/interfaces/data.py @@ -1,4 +1,5 @@ import logging +import time import pandas as pd @@ -12,6 +13,9 @@ def connect(): """ Connect to all listed data sources in preswald.toml + + Returns: + A DuckDBPyConnection instance if connection is successful, otherwise None. """ try: service = PreswaldService.get_instance() @@ -21,25 +25,44 @@ def connect(): return duckdb_conn except Exception as e: logger.error(f"Error connecting to datasources: {e}") + return None -def query(sql: str, source_name: str) -> pd.DataFrame: +def query(sql: str, source_name: str) -> pd.DataFrame | None: """ - Query a data source using sql from preswald.toml by name + Query a data source using sql from preswald.toml by name. + + Args: + sql: The SQL query to run. + source_name: The name of the data source configured in preswald.toml. + + Returns: + A pandas DataFrame if successful, otherwise None """ try: service = PreswaldService.get_instance() + # Measure and log query execution time for performance monitoring + start_time = time.time() df_result = service.data_manager.query(sql, source_name) + elapsed_time = time.time() - start_time logger.info(f"Successfully queried data source: {source_name}") return df_result except Exception as e: logger.error(f"Error querying data source: {e}") + return None def get_df(source_name: str, table_name: str | None = None) -> pd.DataFrame: """ Get a dataframe from the named data source from preswald.toml If the source is a database/has multiple tables, you must specify a table_name + + Args: + source_name: The name of the configured data source. + table_name: Optional; name of the table to load if the source has multiple tables. + + Returns: + A pandas DataFrame if successful, otherwise None. """ try: service = PreswaldService.get_instance() @@ -48,3 +71,4 @@ def get_df(source_name: str, table_name: str | None = None) -> pd.DataFrame: return df_result except Exception as e: logger.error(f"Error getting a dataframe from data source: {e}") + return None