Skip to content

Commit e05c0ca

Browse files
committed
added: home streamlit home page steup
1 parent 9820f72 commit e05c0ca

File tree

1 file changed

+209
-27
lines changed
  • tutorial/markdown/nodejs/dataApi-appsync-tutorial

1 file changed

+209
-27
lines changed

tutorial/markdown/nodejs/dataApi-appsync-tutorial/tutorial.md

Lines changed: 209 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -296,16 +296,171 @@ Now we'll build a simple web UI to call AppSync and visualize hotels on a map.
296296
**What is Streamlit?**
297297
Streamlit is a Python framework for building data apps with minimal code. You write Python functions, and Streamlit renders them as interactive web UIs.
298298

299-
**Steps:**
299+
**Application structure:**
300+
We'll build a multi-page Streamlit app with two Python files:
301+
1. **`home.py`** — Main entry point with navigation, connection settings, and a home page
302+
2. **`search_hotels.py`** — Hotel search page with city filter and interactive map visualization
303+
304+
#### Setup
305+
306+
Create and activate a virtual environment, then install dependencies:
307+
```bash
308+
python3 -m venv .venv
309+
source .venv/bin/activate
310+
pip install streamlit requests pandas pydeck
311+
```
300312

301-
1. Create and activate a virtual environment, then install dependencies:
302-
```bash
303-
python3 -m venv .venv
304-
source .venv/bin/activate
305-
pip install streamlit requests pandas pydeck
306-
```
313+
#### Build the navigation and connection settings (`home.py`)
307314

308-
2. Create a file (e.g., `search_hotels.py`) with the following code.
315+
**What does `home.py` do?**
316+
This is the main entry point for the Streamlit app. It provides:
317+
- A home page with information about the demo
318+
- A sidebar navigation menu to switch between pages
319+
- Connection settings inputs (GraphQL endpoint, API key, Couchbase credentials) stored in Streamlit's `session_state`
320+
- Dynamic page loading based on user selection
321+
- Validation to ensure required settings are filled before accessing feature pages
322+
323+
**Code walkthrough:**
324+
325+
```python
326+
import importlib
327+
import streamlit as st
328+
329+
330+
PAGES = {
331+
"Home": "home",
332+
"Search Hotels": "search_hotels",
333+
}
334+
335+
336+
def render_home():
337+
"""
338+
Display the home page with information about the demo.
339+
Explains what the app does and how AppSync + Data API + Streamlit work together.
340+
"""
341+
st.title("Home")
342+
st.subheader("About this demo")
343+
st.markdown(
344+
"This Streamlit app calls an AWS AppSync GraphQL API that uses Couchbase Data API behind the scenes to search hotels by city and visualize results on a map."
345+
)
346+
st.markdown(
347+
"**Why dataAPI for serverless?** It keeps credentials and query logic secure on the server behind AppSync, avoids heavy SDK initialization overhead, and perfectly fits stateless, scalable Lambda functions."
348+
)
349+
st.subheader("What this demo showcases and how to proceed")
350+
st.markdown(
351+
"- Enter your AppSync GraphQL endpoint and API key in the sidebar (plus Couchbase creds).\n"
352+
"- Go to 'Search Hotels' to run a city filter; resolvers invoke dataAPI to query Couchbase.\n"
353+
"- View results in a list and on a map; try different cities.\n"
354+
"- Extend this starter by adding mutations or subscriptions in your AppSync schema."
355+
)
356+
357+
358+
def render():
359+
"""
360+
Main render function: sets up sidebar navigation and connection settings.
361+
Flow:
362+
1. Display navigation menu in sidebar (Home, Search Hotels, etc.)
363+
2. Collect connection settings (GraphQL endpoint, API key, Couchbase username/password)
364+
- These are stored in session_state so they persist across page changes
365+
3. If user is on the Home page, render it directly
366+
4. For other pages, validate that all required connection settings are filled
367+
5. Dynamically import and render the selected page module
368+
369+
Why session_state?
370+
Streamlit reruns the entire script on every interaction. session_state persists data
371+
across reruns, so users don't have to re-enter connection settings when switching pages.
372+
373+
Why dynamic imports?
374+
Instead of hardcoding imports for all pages, we use importlib to load page modules
375+
based on the user's selection. This keeps the code modular and extensible.
376+
"""
377+
# Sidebar navigation menu
378+
st.sidebar.header("Navigation")
379+
page_name = st.sidebar.selectbox("Go to", list(PAGES.keys()))
380+
381+
# Connection settings input fields
382+
# These persist in session_state across page navigations
383+
st.sidebar.header("Connection Settings")
384+
st.session_state["gql_endpoint"] = st.sidebar.text_input(
385+
"GraphQL Endpoint",
386+
value=st.session_state.get("gql_endpoint", ""),
387+
)
388+
st.session_state["api_key"] = st.sidebar.text_input(
389+
"GraphQL API Key",
390+
value=st.session_state.get("api_key", ""),
391+
type="password",
392+
)
393+
st.session_state["username"] = st.sidebar.text_input(
394+
"Couchbase Username",
395+
value=st.session_state.get("username", ""),
396+
)
397+
st.session_state["password"] = st.sidebar.text_input(
398+
"Couchbase Password",
399+
value=st.session_state.get("password", ""),
400+
type="password",
401+
)
402+
403+
# Map page name to module name
404+
module_name = PAGES[page_name]
405+
406+
# Home page doesn't require connection settings, render it directly
407+
if module_name == "home":
408+
render_home()
409+
return
410+
411+
# For non-Home pages, validate required connection settings
412+
required_keys = [
413+
"gql_endpoint",
414+
"api_key",
415+
"username",
416+
"password",
417+
]
418+
labels = {
419+
"gql_endpoint": "GraphQL Endpoint",
420+
"api_key": "GraphQL API Key",
421+
"username": "Couchbase Username",
422+
"password": "Couchbase Password",
423+
}
424+
missing = [labels[k] for k in required_keys if not st.session_state.get(k)]
425+
if missing:
426+
st.error(f"Please fill the required connection settings: {', '.join(missing)}")
427+
return
428+
429+
# Dynamically import and render the selected page
430+
try:
431+
module = importlib.import_module(module_name)
432+
if hasattr(module, "render"):
433+
module.render()
434+
else:
435+
st.error("Selected page is missing a render() function.")
436+
except Exception as exc:
437+
st.error(f"Failed to load page: {exc}")
438+
439+
440+
if __name__ == "__main__":
441+
render()
442+
```
443+
444+
**Key takeaways:**
445+
- `PAGES` dictionary maps user-friendly page names to Python module names.
446+
- `session_state` stores connection settings so they persist when the user switches pages.
447+
- Input fields use `type="password"` for sensitive data (API key, password) to mask them in the UI.
448+
- The app validates required settings before loading feature pages, providing clear error messages if any are missing.
449+
- `importlib.import_module()` dynamically loads page modules, making it easy to add new pages without modifying the main file.
450+
451+
---
452+
453+
#### Build the hotel search page (`search_hotels.py`)
454+
455+
Create a file `search_hotels.py` with the following code. This page handles the actual hotel search functionality.
456+
457+
**What does `search_hotels.py` do?**
458+
This page:
459+
- Provides a text input for users to enter a city name
460+
- Calls the AppSync GraphQL API with the city filter
461+
- Transforms hotel results into map-friendly data with color-coded ratings
462+
- Displays hotels on an interactive map using pydeck
463+
- Shows a raw JSON response in an expandable section for debugging
309464

310465
**Code walkthrough:**
311466

@@ -597,25 +752,52 @@ if __name__ == "__main__":
597752
7. Streamlit computes a rating from reviews, maps it to a color, and plots each hotel on a map.
598753
8. Hovering over a hotel shows name, rating, address, price, phone, url.
599754

600-
**Key points:**
601-
- `fetch_hotels()` is a standard GraphQL HTTP client: POST to AppSync with `query` + `variables`.
602-
- `compute_rating_from_reviews()` averages the `Overall` rating from all reviews and scales 0–5 to 0–10.
603-
- `color_from_rating()` interpolates red→green based on rating for visual feedback.
604-
- `build_map()` uses pydeck's ScatterplotLayer to plot lat/lon points with color and tooltips.
605-
606-
3. Run the app:
607-
```bash
608-
streamlit run search_hotels.py
609-
```
610-
611-
4. In the browser sidebar, set:
612-
- **GraphQL Endpoint**: your AppSync API URL (e.g., `https://xxx.appsync-api.us-east-1.amazonaws.com/graphql`)
613-
- **GraphQL API Key**: your AppSync API key
614-
- **Couchbase Username**: your Couchbase username (e.g., `Administrator`)
615-
- **Couchbase Password**: your Couchbase password
616-
- (Optional) **Mapbox Token**: for a prettier map
617-
618-
5. Go to "Search Hotels", enter a city (e.g., "London"), and click "Search".
755+
**Key functions explained:**
756+
- `get_connection_settings()` — Retrieves connection details from Streamlit's `session_state` (populated by `home.py`).
757+
- `build_query()` — Constructs the GraphQL query string for `listHotelsInCity`.
758+
- `build_variables()` — Maps UI inputs (city, username, password) to GraphQL variables.
759+
- `fetch_hotels()` — Standard GraphQL HTTP client that POSTs to AppSync with `query` + `variables`.
760+
- `compute_rating_from_reviews()` — Averages the `Overall` rating from all reviews and scales 0–5 to 0–10.
761+
- `color_from_rating()` — Interpolates red→green color based on rating for visual feedback (red = poor, green = excellent).
762+
- `hotels_to_points()` — Transforms GraphQL hotel results into map-friendly data with lat/lon and color.
763+
- `build_map()` — Creates a pydeck ScatterplotLayer to plot hotels with color-coded ratings and interactive tooltips.
764+
765+
**Data flow:**
766+
1. User enters city → clicks "Search"
767+
2. `fetch_hotels()` → AppSync GraphQL API
768+
3. AppSync → resolver → Data API → Couchbase
769+
4. Data API returns hotels → AppSync → Streamlit
770+
5. Streamlit computes ratings, maps to colors, and plots on map
771+
772+
---
773+
774+
#### Run and test the application
775+
776+
**Start the Streamlit app:**
777+
778+
```bash
779+
streamlit run home.py
780+
```
781+
782+
This starts the Streamlit web server and automatically opens the app in your browser (usually at `http://localhost:8501`).
783+
784+
**Configure connection settings:**
785+
786+
In the browser sidebar, fill in the required connection settings:
787+
- **GraphQL Endpoint**: Your AppSync API URL (e.g., `https://xxx.appsync-api.us-east-1.amazonaws.com/graphql`)
788+
- **GraphQL API Key**: Your AppSync API key
789+
- **Couchbase Username**: Your Couchbase username (e.g., `Administrator`)
790+
- **Couchbase Password**: Your Couchbase password
791+
792+
**Search for hotels:**
793+
794+
1. Use the navigation dropdown in the sidebar to select **"Search Hotels"**
795+
2. Enter a city name (e.g., "London", "San Francisco", "Paris")
796+
3. Click the **"Search"** button
797+
4. View the results:
798+
- Hotels appear as colored dots on the map (green = high rating, red = low rating)
799+
- Hover over any hotel marker to see details (name, rating, address, price, phone, URL)
800+
- Expand the "Raw response" section to see the full JSON data from AppSync
619801

620802
#### Screenshots
621803

0 commit comments

Comments
 (0)