Last active
July 12, 2022 22:53
-
-
Save mtanco/9a5d0a1d951a9e3c877786de85866afd to your computer and use it in GitHub Desktop.
Display fake-streamed text data using H2O Wave. Pause and resume the real-time updates.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Demo of Updating App Data in one card of an app | |
""" | |
from random import randint | |
from h2o_wave import Q, app, handle_on, main, on, ui | |
@app("/") | |
async def serve(q: Q): | |
# First time a browser comes to the app | |
if not q.client.initialized: | |
await initialize_client(q) | |
# User navigating | |
if q.args.tabs_nav == "live_update": | |
await live_update(q) | |
elif q.args.tabs_nav == "other_page": | |
await other_page(q) | |
# Handle other user interactions | |
await handle_on(q) | |
# Save to screen | |
await q.page.save() | |
async def initialize_client(q: Q) -> None: | |
""" | |
This happens the first time this browser tab comes to this app | |
""" | |
if not q.app.initialized: | |
# streamed text is the same for all users - use q.client or q.user to change the level of state | |
q.app.text = [] | |
q.app.initialized = True | |
q.client.cards = [] | |
q.client.stream_data = False | |
q.page["meta"] = ui.meta_card( | |
box="", | |
title="Streaming | H2O Wave", | |
layouts=[ | |
ui.layout( | |
breakpoint="xs", | |
min_height="100vh", | |
max_width="1200px", | |
zones=[ | |
ui.zone("header"), | |
ui.zone("title"), | |
ui.zone("content", size="1"), | |
ui.zone(name="footer"), | |
], | |
) | |
], | |
) | |
q.page["header"] = ui.header_card( | |
box="header", | |
title="My Wave App", | |
subtitle="Example to get us started", | |
image="https://cloud-internal.h2o.ai/logo.svg", | |
items=[ | |
ui.tabs( | |
name="tabs_nav", | |
items=[ | |
ui.tab(name="live_update", label="Live Update"), | |
ui.tab(name="other_page", label="Other Page"), | |
], | |
) | |
], | |
) | |
q.page["footer"] = ui.footer_card( | |
box="footer", caption="Made with 💛 using [H2O Wave](https://wave.h2o.ai)." | |
) | |
# Show the user the live updating page and begin streaming data | |
await live_update(q) | |
q.client.initialized = True | |
async def live_update(q: Q): | |
""" | |
This page has two buttons to start and stop live updating and a card for holding updated content | |
""" | |
clear_cards(q) | |
button_menu = ui.section_card( | |
box="title", | |
title="", | |
subtitle="", | |
items=[ | |
ui.buttons( | |
items=[ | |
ui.button( | |
name="start_stream", | |
label="Start Stream", | |
icon="Play", | |
primary=True, | |
disabled=q.client.stream_data, | |
), | |
ui.button( | |
name="pause_stream", | |
label="Pause Stream", | |
icon="Pause", | |
primary=True, | |
disabled=not q.client.stream_data, | |
), | |
], | |
justify="end", | |
) | |
], | |
) | |
add_card(q, "button_control", button_menu) | |
streamed_text = ui.form_card( | |
box=ui.box("content", height="500px"), | |
items=[ui.text("<br />".join(q.app.text))], | |
) | |
add_card(q, "streamed_text", streamed_text) | |
async def other_page(q: Q): | |
""" | |
This is some other app functionality | |
If you want the streamed data calls to keep happening do nothing special | |
If you want them to stop when the user is away from the updating page / card use: await pause_stream(q) | |
""" | |
# await pause_stream(q) # Optional depending on your use case!!! | |
clear_cards(q) | |
demo_card = ui.form_card(box="content", items=[ui.text("Some other app stuff")]) | |
add_card(q, "demo_card", demo_card) | |
@on() | |
async def start_stream(q) -> None: | |
""" | |
User has clicked the "Start Stream" button | |
Every 2 seconds we update the content of a specific card | |
The user can still interact with other parts of the application | |
""" | |
q.client.stream_data = True # Variable so the rest of the app knows that this card is being streamed to | |
# Change information about our control buttons | |
q.page["button_control"].items[0].buttons.items[0].button.disabled = True | |
q.page["button_control"].items[0].buttons.items[1].button.disabled = False | |
# This will run until the variable is change somewhere else in the app code by a user interaction | |
while q.client.stream_data: | |
q.app.text.insert(0, create_text_data()) # Add new text to the top of the list | |
q.page["streamed_text"].items[0].text.content = "<br />".join(q.app.text) | |
await q.page.save() | |
await q.sleep(2) | |
@on() | |
async def pause_stream(q): | |
""" | |
User has clicked the "Pause Stream" button | |
Set the update variable to stop so that it no longer updates | |
""" | |
q.client.stream_data = False | |
q.page["button_control"].items[0].buttons.items[0].button.disabled = False | |
q.page["button_control"].items[0].buttons.items[1].button.disabled = True | |
# Use for cards that should be deleted on calling `clear_cards`. Useful for routing and page updates. | |
def add_card(q, name, card) -> None: | |
q.client.cards.append(name) | |
q.page[name] = card | |
def clear_cards(q) -> None: | |
for name in q.client.cards.copy(): | |
del q.page[name] | |
q.client.cards = [] | |
def create_text_data(): | |
names = ["We", "I", "They", "He", "She", "Jack", "Jim"] | |
verbs = ["was", "is", "are", "were"] | |
nouns = ["playing a game", "watching television", "talking", "dancing", "speaking"] | |
sentence = ( | |
names[randint(0, len(names) - 1)] | |
+ " " | |
+ verbs[randint(0, len(verbs) - 1)] | |
+ " " | |
+ nouns[randint(0, len(nouns) - 1)] | |
+ "." | |
) | |
return sentence |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment