Skip to content

Instantly share code, notes, and snippets.

@mtanco
Last active May 11, 2021 19:46
Show Gist options
  • Save mtanco/807b8e83f117f8a022817c52de9bdded to your computer and use it in GitHub Desktop.
Save mtanco/807b8e83f117f8a022817c52de9bdded to your computer and use it in GitHub Desktop.
Use the AsyncIOScheduler to run a scheduled job for updating a dashboard while maintaining the ability to use all features of an interactive app
import random
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from h2o_wave import main, app, Q, ui, handle_on, on, data
SCHEDULER = AsyncIOScheduler()
@app('/')
async def serve(q: Q):
print(q.args)
"""
Handles requests from end users
Runs any time a user interacts with the app at all
"""
if not q.client.initialized:
initialize_app_for_new_client(q)
else:
await handle_on(q)
await q.page.save()
@on()
async def close_rows(q: Q):
for closed_row in q.args.data_table:
for row in q.client.data:
print(int(closed_row))
print(row[0])
if int(closed_row) == row[0]:
row[2] = 'Michelle'
update_table(q)
def initialize_app_for_new_client(q: Q):
"""
Sets up the UI and background tasks for the end user
Runs when a new browser tab comes to the app
"""
if not q.app.initialized:
initialize_app(q)
q.client.data_location = 20
q.client.data = [[i, i, ''] for i in range(0, q.client.data_location)]
q.client.dropdown_value = str(1008)
render_main_ui(q)
render_home_view(q)
start_scheduled_job(job_id=f'user_{q.app.user_count}', q=q)
q.client.initialized = True
def initialize_app(q: Q):
q.app.user_count = 1
q.app.initialized = True
def start_scheduled_job(job_id: str, q: Q):
SCHEDULER.add_job(
func=render_new_data,
args=[q],
trigger='interval',
seconds=3,
id=job_id,
)
SCHEDULER.start()
def render_main_ui(q: Q):
q.page['meta'] = ui.meta_card(
box='',
layouts=[
ui.layout(
breakpoint='xs',
width='1200px',
zones=[
ui.zone('header'),
ui.zone('command'),
ui.zone('body', direction=ui.ZoneDirection.COLUMN, zones=[
ui.zone('sidebar'),
ui.zone('content', direction=ui.ZoneDirection.ROW)
]),
ui.zone('footer'),
]
)
]
)
q.page['header'] = ui.header_card(
box='header',
title='Scheduled Plots',
subtitle='Interactive apps with scheduled data pulls',
)
q.page['footer'] = ui.footer_card(
box='footer',
caption='Made with 💛 using [H2O Wave](https://github.com/h2oai/wave)!'
)
def render_home_view(q: Q):
q.page['interactive_commands'] = ui.section_card(
box='command',
title='Testing Area',
subtitle='Confirming the app is still interactive while real-time updates are happening',
items=[
ui.dropdown(
name='dropdown_value',
choices=[ui.choice(str(i), str(i)) for i in range(1000, 1010)],
value=str(1008),
trigger=False
)
]
)
q.page['plot'] = ui.plot_card(
box='content',
title='Live Fake Monitoring',
data=data('price performance closer', size=-20), # negative means we want to cycle through with new data
plot=ui.plot([
ui.mark(type='interval', x='=price', y='=performance', x_title='Event Count', y_title='Fake Value')
])
)
q.page['plot'].data = q.client.data
q.page['table'] = ui.form_card(
box='content',
items=[
ui.table(
name='data_table',
columns=[
ui.table_column('price', 'Event Count', sortable=True, filterable=True),
ui.table_column('performance', 'Fake Value'),
ui.table_column('closer', 'Closer')
],
rows=[ui.table_row(
str(i),
[str(v) for v in q.client.data[i]]
) for i in range(len(q.client.data))],
multiple=True
),
ui.button('close_rows', 'Close Rows')
]
)
async def render_new_data(q: Q):
new_data = [q.client.data_location, random.randrange(1, 10), '']
q.client.data.append(new_data)
q.client.data_location += 1
q.page['plot'].data = [new_data]
update_table(q)
await q.page.save()
def update_table(q: Q):
q.page['table'].items[0].table.rows = [
ui.table_row(
str(i),
[str(v) for v in q.client.data[i]]
) for i in range(len(q.client.data))
]
@Alex-Wenner-FHR
Copy link

Perfect example for the scenario I sent via email last week or so. Stumbled across this looking for wave examples! Seems to crash on refresh, but may use this logic to accomplish on the hour data pulls. Thanks Michelle!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment