async def serve(q: Q): hash = q.args['#'] if hash: blurb = q.page['blurb'] if hash == 'menu/spam': blurb.content = "Sorry, we're out of spam!" elif hash == 'menu/ham': blurb.content = "Sorry, we're out of ham!" elif hash == 'menu/eggs': blurb.content = "Sorry, we're out of eggs!" elif hash == 'about': blurb.content = 'Everything here is gluten-free!' else: q.page['nav'] = ui.markdown_card( box='1 1 4 1', title='Links!', content= '[Spam](#menu/spam) | [Ham](#menu/ham) | [Eggs](#menu/eggs) | [About](#about)', ) q.page['blurb'] = ui.markdown_card( box='1 2 4 2', title='Store', content='Welcome to our store!', ) await q.page.save()
async def serve(q: Q): if not q.client.initialized: q.client.initialized = True q.page['nav'] = ui.markdown_card( box='1 1 4 2', title='Links!', content= '[Spam](#menu/spam) / [Ham](#menu/ham) / [Eggs](#menu/eggs) / [About](#about)', ) q.page['blurb'] = ui.markdown_card( box='1 3 4 2', title='Store', content='Welcome to our store!', ) hash = q.args['#'] blurb = q.page['blurb'] if hash == 'menu/spam': blurb.content = "Sorry, we're out of spam!" elif hash == 'menu/ham': blurb.content = "Sorry, we're out of ham!" elif hash == 'menu/eggs': blurb.content = "Sorry, we're out of eggs!" elif hash == 'about': blurb.content = 'Everything here is gluten-free!' else: blurb.content = 'Welcome to our store!' await q.page.save()
async def serve(q: Q): if not q.client.initialized: q.client.initialized = True q.page['nav'] = ui.markdown_card( box='1 1 4 2', title='Menu', content= '[Spam](#menu/spam) / [Ham](#menu/ham) / [Eggs](#menu/eggs) / [About](#about)', ) q.page['blurb'] = ui.markdown_card( box='1 3 4 2', title='Description', content='Welcome to our store!', ) q.page['cart'] = ui.form_card( box='1 5 4 2', title='Cart', items=[ ui.text('Your cart is empty!'), ui.buttons([ ui.button(name=buy_now.__name__, label='Buy Now!', primary=True), ui.button(name='empty_cart', label='Clear cart'), ]) ], ) await q.page.save() else: await handle_on(q)
async def serve(q: Q): hash = q.args['#'] if hash: blurb = q.page['blurb'] if hash == 'menu/spam': blurb.content = "Sorry, we're out of spam!" elif hash == 'menu/ham': blurb.content = "Sorry, we're out of ham!" elif hash == 'menu/eggs': blurb.content = "Sorry, we're out of eggs!" elif hash == 'about': blurb.content = 'Everything here is gluten-free!' else: q.page['nav'] = ui.toolbar_card( box='1 1 4 1', items=[ ui.command(name='#menu/spam', label='Spam'), ui.command(name='#menu/ham', label='Ham'), ui.command(name='#menu/eggs', label='Eggs'), ui.command(name='#about', label='About'), ], ) q.page['blurb'] = ui.markdown_card( box='1 2 4 2', title='Store', content='Welcome to our store!', ) await q.page.save()
async def serve(q: Q): if not q.client.initialized: q.client.initialized = True q.page['pricing'] = ui.plot_card(box='1 1 4 5', title='Interval', data=data(fields='product price', rows=[ ['spam', 1.49], ['eggs', 2.49], ['ham', 1.99], ], pack=True), plot=ui.plot([ ui.mark(type='interval', x='=product', y='=price', y_min=0) ]), events=['select_marks']) q.page['details'] = ui.markdown_card( box='1 6 4 2', title='Selected Product', content='Nothing selected.', ) await q.page.save() else: await handle_on(q)
def render_customer_summary(q: Q, training_df, contributions_df, row, can_approve): top_feature = \ contributions_df.idxmin(axis=1)[row] if can_approve else contributions_df.idxmax(axis=1)[row] explanation_data = { 'will_or_will_not': 'will' if can_approve else 'will not', 'top_contributing_feature': top_feature, 'value_of_top_contributing_feature': str(training_df.loc[row][top_feature]), 'accept_or_reject': 'approve' if can_approve else 'reject', } explanation = ''' - This customer **{{will_or_will_not}}** most probably settle the next month credit card balance. - Having a {{top_contributing_feature}} of {{value_of_top_contributing_feature}} is the top reason for that. - It's a good idea to **{{accept_or_reject}}** this customer. ''' q.page["risk_explanation"] = ui.markdown_card( box='risk_explanation', title='Summary on Customer', content='=' + explanation, data=explanation_data, )
async def serve(q: Q): if not q.client.initialized: # First visit q.client.initialized = True q.client.points = 25 q.client.alpha = 50 q.page['controls'] = ui.form_card( box='1 1 2 3', items=[ ui.text_xl("Lets make some plots"), ui.slider(name='points', label='Points', min=5, max=50, step=1, value=q.client.points, trigger=True), ui.slider(name='alpha', label='Alpha', min=5, max=100, step=1, value=q.client.alpha, trigger=True), ]) q.page['plot'] = ui.markdown_card(box='3 1 2 3', title='Your plot!', content='') if q.args.points is not None: q.client.points = q.args.points if q.args.alpha is not None: q.client.alpha = q.args.alpha n = q.client.points # Render plot plt.figure(figsize=(2, 2)) plt.scatter(np.random.rand(n), np.random.rand(n), s=(30 * np.random.rand(n))**2, c=np.random.rand(n), alpha=q.client.alpha / 100.0) image_filename = f'{str(uuid.uuid4())}.png' plt.savefig(image_filename) # Upload image_path, = await q.site.upload([image_filename]) # Clean up os.remove(image_filename) # Display our plot in our markdown card q.page['plot'].content = f'![plot]({image_path})' # Save page await q.page.save()
async def serve(q: Q): if not q.client.initialized: q.page['meta'] = ui.meta_card( box='', # Load Sigma.js scripts=[ ui.script( path= 'https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.2.1/sigma.min.js' ) ], # Call Javascript to render our graph using Sigma.js. script=ui.inline_script( content=render_graph, # Ensure that Sigma.js is available before running our script. requires=['sigma'], # Ensure that the 'graph' element is available before running our script. targets=['graph'])) # Add a placeholder named 'graph' to house our rendered graph. q.page['vis'] = ui.markup_card( box='1 1 6 8', title='Select a node', content='<div id="graph" style="width: 800px; height: 500px;"/>') # Add another card to display which node was selected. q.page['details'] = ui.markdown_card( box='1 9 6 1', title='', content='The selected node will be displayed here.', ) q.client.initialized = True else: if q.events.graph: selected_node = q.events.graph.node_clicked if selected_node: q.page[ 'details'].content = f'You clicked on node {selected_node}' await q.page.save()
async def serve(q: Q): if not q.client.initialized: q.client.initialized = True q.page['table'] = ui.form_card( box='1 1 4 7', items=[ ui.text_l('Airline Passenger Counts'), ui.text( make_markdown_table( fields=air_passengers_fields, rows=add_links_to_cells(air_passengers_rows), )), ], ) q.page['message'] = ui.markdown_card( box='1 8 4 1', title='', content='Click on a cell in the table above!', ) await handle_on(q) await q.page.save()
async def serve(q: Q): content = 'Welcome to our store!' location = q.args['#'] if location: if location == 'menu/spam': content = "Sorry, we're out of spam!" elif location == 'menu/ham': content = "Sorry, we're out of ham!" elif location == 'menu/eggs': content = "Sorry, we're out of eggs!" elif location == 'about': content = 'Everything here is gluten-free!' if not q.client.initialized: q.page['nav'] = ui.tab_card( box='1 1 4 1', items=[ ui.tab(name='#menu/spam', label='Spam'), ui.tab(name='#menu/ham', label='Ham'), ui.tab(name='#menu/eggs', label='Eggs'), ui.tab(name='#about', label='About'), ], value=f'#{location}' if location else None, ) q.page['blurb'] = ui.markdown_card( box='1 2 4 2', title='Store', content=content, ) q.client.initialized = True elif location: blurb = q.page['blurb'] blurb.content = content await q.page.save()
nav=[ ui.nav_group('Menu', items=[ ui.nav_item(name='#menu/spam', label='Spam'), ui.nav_item(name='#menu/ham', label='Ham'), ui.nav_item(name='#menu/eggs', label='Eggs'), ]), ui.nav_group('Help', items=[ ui.nav_item(name='#about', label='About'), ui.nav_item(name='#support', label='Support'), ]) ], ) page['controls'] = ui.markdown_card( # If the viewport width >= 0, place in content zone. # If the viewport width >= 768, place in sidebar zone. # If the viewport width >= 1200, place in sidebar zone. box=ui.boxes('content', 'sidebar', 'sidebar'), title='Controls', content=content, ) page['chart1'] = ui.markdown_card( box=ui.boxes( # If the viewport width >= 0, place as second item in content zone. ui.box(zone='content', order=2), # If the viewport width >= 768, place in content zone. 'content', # If the viewport width >= 1200, place as first item in charts zone, use 2 parts of available space. ui.box(zone='charts', order=1, size=2), ), title='Chart 1', content=content, )
def show_form(q: Q): q.page["meta"] = ui.meta_card( box="", title="Tennis Match Prediction", refresh=1, layouts=[ ui.layout( breakpoint="xs", width="1200px", zones=[ ui.zone("header"), ui.zone("tournament"), ui.zone( "players", direction=ui.ZoneDirection.ROW, zones=[ ui.zone("player1", size="50%"), ui.zone("player2", size="50%"), ], ), ui.zone("submit", size="50%"), ui.zone("result", size="50%"), ], ) ], ) q.page["header"] = ui.header_card( box="header", title="Tennis Match Prediction", subtitle="" ) q.page["tournament"] = ui.form_card( box="tournament", items=[ # Tournament name ui.dropdown( name="t_name", label="Tournament Name", placeholder="Wimbledon", choices=[ ui.choice(name=t_name, label=t_name) for t_name in tourn_ids.keys() ], trigger=False, ), # Round ui.dropdown( name="t_round", label="Round", placeholder="Final", choices=[ ui.choice(name=t_round, label=t_round) for t_round in round_list ], trigger=False, ), ], ) q.page["p1"] = ui.form_card( box="player1", items=[ ui.text_l("Player 1"), ui.dropdown( name="p1_name", label="Name", placeholder="Roger Federer", choices=[ ui.choice(name=p_name, label=p_name) for p_name in player_ids.keys() ], trigger=False, ), ui.textbox(name="p1_rank", label="Rank"), ui.textbox(name="p1_age", label="Age"), ], ) q.page["player2"] = ui.form_card( box="player2", items=[ ui.text_l("Player 2"), ui.dropdown( name="p2_name", label="Name", placeholder="Rafael Nadal", choices=[ ui.choice(name=p_name, label=p_name) for p_name in player_ids.keys() ], trigger=False, ), ui.textbox(name="p2_rank", label="Rank"), ui.textbox(name="p2_age", label="Age"), ], ) q.page["submit"] = ui.form_card( box="submit", items=[ ui.buttons( items=[ui.button(name="submit", label="Submit", primary=True)], justify="center", ) ], ) result_str = "" if not q.client.result_str else q.client.result_str q.page["result"] = ui.markdown_card( box="result", title="Results", content=result_str, )
# Hello World! # A simple example to get you started with Q. # --- # Import `Site` and the `ui` module from the `h2o_wave` package from h2o_wave import site, ui # Get the web page at route '/demo'. # If you're running this example on your local machine, # this page will refer to http://localhost:10101/demo. page = site['/demo'] # Add a Markdown card named `hello` to the page. page['hello'] = ui.markdown_card( box='1 1 2 2', title='Hello World!', content='And now for something completely different!', ) # Finally, sync the page to send our changes to the server. page.save()
# Meta / Notification # Display a desktop #notification. #meta # --- import time from h2o_wave import site, ui page = site['/demo'] page['meta'] = ui.meta_card(box='') page['example'] = ui.markdown_card( box='1 1 2 2', title='Desktop Notifications', content='This page should display a desktop notification in a few seconds. Wait for it...', ) page.save() time.sleep(5) page['meta'].notification = 'And now for something completely different!' page.save()
# Meta / Refresh # Turn off live updates for static pages to conserve server resources. # #meta #refresh # --- from h2o_wave import site, ui page = site['/demo'] # Set refresh rate to zero ("no updates") page['meta'] = ui.meta_card(box='', refresh=0) page['example'] = ui.markdown_card( box='1 1 2 2', title='No updates for you', content='This page stops receiving updates once loaded.', ) page.save()
async def serve(q: Q): if not q.client.initialized: q.client.initialized = True # Create a plot x = [random() for x in range(500)] y = [random() for y in range(500)] s1 = ColumnDataSource(data=dict(x=x, y=y)) p1 = figure(plot_width=400, plot_height=400, tools="lasso_select", title="Select Here") p1.circle('x', 'y', source=s1, alpha=0.6) s2 = ColumnDataSource(data=dict(x=[], y=[])) p2 = figure(plot_width=400, plot_height=400, x_range=(0, 1), y_range=(0, 1), tools="", title="Watch Here") p2.circle('x', 'y', source=s2, alpha=0.6) s1.selected.js_on_change( 'indices', CustomJS(args=dict(s1=s1, s2=s2), code=""" var indices = cb_obj.indices; var d1 = s1.data; var d2 = s2.data; d2['x'] = [] d2['y'] = [] for (var i = 0; i < indices.length; i++) { d2['x'].push(d1['x'][indices[i]]) d2['y'].push(d1['y'][indices[i]]) } s2.change.emit(); // Send the selected indices to the Wave app via an event. // Here, // - The first argument, 'the_plot', is some name to uniquely identify the source of the event. // - The second argument, 'selected', is some name to uniquely identify the type of event. // - The third argument is any arbitrary data to be sent as part of the event. // Ordinarily, we would just call wave.emit('the_plot', 'selected', indices), but this particular // example triggers events every time the indices change (which is several times per second), // so we use a 'debounced' version of 'emit()' that waits for a second before emitting an event. // Here, 'emit_debounced()' is not part of the Wave API, but custom-built for this example - see // the inline_script's 'content' below. emit_debounced('the_plot', 'selected', indices); // The indices will be accessible to the Wave app using 'q.events.the_plot.selected'. """)) layout = row(p1, p2) # Serialize the plot as JSON. # See https://docs.bokeh.org/en/latest/docs/user_guide/embed.html#json-items plot_id = 'my_plot' plot_data = json.dumps(json_item(layout, plot_id)) q.page['meta'] = ui.meta_card( box='', # Import Bokeh Javascript libraries from CDN scripts=[ui.script(path=f) for f in CDN.js_files], # Execute custom Javascript script=ui.inline_script( # The inline script does two things: content=f''' // 1. Create a debounced version of `wave.emit()` and make it accessible to Bokeh's event handler. // window.emit_debounced() is the name of new, debounced (calmer) version of wave.emit() that waits // for 1000ms before emitting an event. window.emit_debounced=window.wave.debounce(1000, window.wave.emit); // 2. Make Bokeh render the plot. Bokeh.embed.embed_item({plot_data}); ''', # Ensure that the Bokeh Javascript library is loaded requires=['Bokeh'], # Ensure that the target HTML container element is available targets=[plot_id], ), ) q.page['plot'] = ui.markup_card( box='1 1 6 6', title='', content=f'<div id="{plot_id}"></div>', ) q.page['details'] = ui.markdown_card( box='1 7 6 2', title='Selected Marks', content='Nothing selected.', ) else: if q.events.the_plot.selected: q.page[ 'details'].content = f'You selected {q.events.the_plot.selected}' await q.page.save()
# #Upload files to the Wave server. # --- import os from h2o_wave import site, ui def write_csv(filename, rows): with open(filename, 'w', encoding='utf-8') as f: f.write('\n'.join([','.join([str(x) for x in row]) for row in rows])) # Create a couple of fake CSV files write_csv('squares.csv', [[x, x * x] for x in range(1, 11)]) write_csv('cubes.csv', [[x, x * x * x] for x in range(1, 11)]) # Upload CSVs squares_path, cubes_path = site.upload(['squares.csv', 'cubes.csv']) # Delete local CSVs os.remove('squares.csv') os.remove('cubes.csv') # Display links to these CSVs page = site['/demo'] page['example'] = ui.markdown_card( box='1 1 2 2', title='Download CSVs', content=f'[Squares]({squares_path}) [Cubes]({cubes_path})', ) page.save()
async def render_customer_page(q: Q): clear_page(q) row_index = int(q.args.customer_table[0]) customer_row = q.app.customer_df.loc[row_index] score = q.app.predictions_df.loc[row_index] approve = bool(score < APPROVAL_THRESHOLD) contribs = q.app.contributions_df.loc[row_index].drop('BiasTerm') q.client.selected_customer_id = customer_row['ID'] # details q.client.cards.add('customer_features') q.page['customer_features'] = ui.form_card( box='customer_features', items=[ ui.table(name='customer_features', columns=[ ui.table_column(name='attribute', label='Attribute', sortable=False, searchable=False, max_width='100'), ui.table_column(name='value', label='Value', sortable=False, searchable=False, max_width='100') ], rows=[ ui.table_row(name=index, cells=[index, row]) for index, row in customer_row.map(str).iteritems() ], groupable=False, resettable=False, multiple=False, height='525px') ]) # summary top_feature = contribs.idxmin(axis=1) if approve else contribs.idxmax( axis=1) explanation_data = { 'will_or_will_not': 'will' if approve else 'will not', 'top_contributing_feature': top_feature, 'value_of_top_contributing_feature': str(customer_row[top_feature]), 'accept_or_reject': 'approve' if approve else 'reject', } explanation = ( "- This customer **{{will_or_will_not}}** most probably settle the next month credit card balance.\n" "- Having a **{{top_contributing_feature}}** of **{{value_of_top_contributing_feature}}** is the top reason for that.\n" "- It's recommended to **{{accept_or_reject}}** this customer.") q.client.cards.add('customer_risk_explanation') q.page['customer_risk_explanation'] = ui.markdown_card( box='customer_risk_explanation', title='Summary on Customer', content='=' + explanation, data=explanation_data, ) # shap plot shap_values = list(zip(contribs.index, contribs)) shap_values.sort(key=lambda x: x[1]) q.client.cards.add('customer_shap_plot') q.page['customer_shap_plot'] = ui.plot_card( box='customer_shap_plot', title='Effectiveness of each attribute on defaulting next payment', data=data(['label', 'value'], rows=shap_values), plot=ui.plot([ ui.mark(type='interval', x='=value', x_title='Feature Contributions', y='=label') ])) # approve/reject buttons q.client.cards.add('button_group') q.page['button_group'] = ui.form_card(box='button_group', items=[ ui.buttons([ ui.button(name='approve', label='Approve', primary=approve), ui.button( name='reject', label='Reject', primary=not approve), ]) ])
# Meta / Title # Set the browser window title for a page. #meta # --- from h2o_wave import site, ui page = site['/demo'] page['meta'] = ui.meta_card(box='', title='And now for something completely different!') page['example'] = ui.markdown_card( box='1 1 2 2', title='', content='<a href="/demo" target="_blank">Open this page in a new window</a> to view its title.', ) page.save()
# Cards have a `box` attribute that specifies its column, row, width and height. # box = 'column row width height' # They indicate the 1-based column/row to position the top-left corner of the card. # In this example, we place multiple cards on a page to demonstrate their `box` values. page = site['/demo'] boxes = [ '1 1 1 1', '2 1 2 1', '4 1 3 1', '7 1 4 1', '11 1 2 2', '1 2 1 9', '2 2 1 4', '3 2 1 2', '2 6 1 5', '3 4 1 7', '4 2 7 9', '11 9 2 2', '11 3 2 6', ] for box in boxes: page[f'card_{box.replace(" ", "_")}'] = ui.markdown_card(box=box, title=box, content='') page.save()
# Meta / Redirect # #Redirect the page to a new URL or hash. #meta # --- import time from h2o_wave import site, ui page = site['/demo'] page['meta'] = ui.meta_card(box='') page['example'] = ui.markdown_card( box='1 1 2 2', title='Redirect a page', content= 'This page should redirect to Wikipedia in a few seconds. Wait for it...', ) page.save() time.sleep(3) # Redirect to a hash. page['meta'].redirect = '#widgets' page.save() time.sleep(3) # Redirect to a URL. page['meta'].redirect = 'https://www.wikipedia.org' page.save()
async def responsive_layout(q: Q): if not q.user.columns: q.user.columns = [ ui.table_column(name='Index', label='Index', searchable=True, sortable=True, data_type='number'), ui.table_column(name='Started', label='Started', searchable=True), ui.table_column(name='Ended', label='Ended', searchable=True), ui.table_column(name='Duration', label='Duration (mins)', data_type='number'), ui.table_column(name='Scores', label='Scores', data_type='number'), ] if not q.client.LB_columns: q.client.LB_columns = [ ui.table_column(name='User', label='User', searchable=True, max_width='100px'), ui.table_column(name='Scores', label='Scores', searchable=True, max_width='100px', sortable=True), ] q.page['meta'] = ui.meta_card( box='', title='Streak Counter', layouts=[ ui.layout( # If the viewport width >= 0: breakpoint='xs', zones=[ # 80px high header ui.zone('header', size='80px'), # Use remaining space for content ui.zone('content') ]), ui.layout( # If the viewport width >= 768: breakpoint='m', zones=[ # 80px high header ui.zone('header', size='80px'), # Use remaining space for body ui.zone( 'body', direction=ui.ZoneDirection.ROW, zones=[ # 250px wide sidebar ui.zone('sidebar', size='250px'), # Use remaining space for content ui.zone('content'), ]), ui.zone('footer'), ]), ui.layout( # If the viewport width >= 1200: breakpoint='xl', width='1200px', zones=[ # 80px high header ui.zone('header', size='80px'), # Use remaining space for body ui.zone( 'body', direction=ui.ZoneDirection.ROW, zones=[ # 300px wide sidebar ui.zone('sidebar', size='300px'), # Use remaining space for other widgets ui.zone( 'other', zones=[ # Use one half for charts ui.zone('charts', direction=ui.ZoneDirection.ROW), # Use other half for content ui.zone('content', size='500px'), ]), ]), ui.zone('footer'), ]) ]) q.page['header'] = ui.header_card( # Place card in the header zone, regardless of viewport size. box='header', title='Code Streak Counter', subtitle='Count your programming Streak while staying healthy !!!', ) q.page['LeaderBoard'] = ui.form_card( # If the viewport width >= 0, place in content zone. # If the viewport width >= 768, place in sidebar zone. # If the viewport width >= 1200, place in sidebar zone. box=ui.boxes('content', 'sidebar', 'sidebar'), # title='Leader Board', items=[ ui.text_l(content=f"Hi {q.auth.username.capitalize()}..!"), ui.text_xl( content= f"Your Total Score: {q.user.stop_watch.df['Scores'].sum()}"), ui.table( name='leaderboard', columns=q.client.LB_columns, rows=[ ui.table_row(name=user, cells=[user, str(score)]) for user, score in q.app.lb_dict.items() ], groupable=False, downloadable=True, resettable=False, height='425px', ), ui.link(name='logout', label='Log Out', button=True, path=f'/_logout', target='_current') ], ) q.page['stopwatch'] = ui.form_card( box=ui.boxes( # If the viewport width >= 0, place as second item in content zone. ui.box(zone='content', order=2), # If the viewport width >= 768, place in content zone. 'content', # If the viewport width >= 1200, place as first item in charts zone, use 2 parts of available space. ui.box(zone='charts', order=1, size=2), ), items=[ ui.text_xl( content= f"<h1><center>{str(q.user.stop_watch.minutes).zfill(2)} : {str(q.user.stop_watch.seconds).zfill(2)}</center></h1>" ), ui.text_l(content=f"<center>Lets crack some code!</center>"), ui.buttons([ ui.button(name='start', label='Start', primary=True), ui.button(name='stop', label='Stop', primary=False) ], justify='center') ], ) q.page['UserStreaks'] = ui.markdown_card( box=ui.boxes( # If the viewport width >= 0, place as third item in content zone. ui.box(zone='content', order=3), # If the viewport width >= 768, place as second item in content zone. ui.box(zone='content', order=2), # If the viewport width >= 1200, place as second item in charts zone, use 1 part of available space. ui.box(zone='charts', order=2, size=1), ), title='User Streaks', content="""=Last Streak Started: {{streak_start}} <p data-test='UserStreaks_Last_Ended'>Last Streak Ended: {{streak_end}}</p> <p data-test='UserStreaks_Total_Streaks'>Total Streaks: {{total_streaks}}</p> Total Coding Time: {{total_time}} """, data=dict(streak_start=q.user.stop_watch.last_start, streak_end=q.user.stop_watch.last_stop, total_streaks=q.user.stop_watch.total_streaks, total_time=f"{str(q.user.stop_watch.total_hours).zfill(2)} :\ {str(q.user.stop_watch.total_minutes).zfill(2)} : \ {str(q.user.stop_watch.total_seconds).zfill(2)}")) q.page['history'] = ui.form_card( box=ui.boxes( # If the viewport width >= 0, place as fourth item in content zone. ui.box(zone='content', order=4), # If the viewport width >= 768, place as third item in content zone. ui.box(zone='content', order=3), # If the viewport width >= 1200, place in content zone. 'content'), items=[ ui.table(name='streaks_table', columns=q.user.columns, rows=[ ui.table_row(name=str(row.Index + 1), cells=[ str(row.Index + 1), row.Started, row.Ended, str(row.Duration), str(row.Scores) ]) for row in q.user.stop_watch.df.itertuples() ], groupable=False, downloadable=True, resettable=False, height='425px') ], title='History', ) q.page['footer'] = ui.footer_card(box='footer', caption='(c) 2021 H2O.ai ')
# Markdown / Data # Display dynamic formatted content using #markdown. # --- import time from h2o_wave import site, ui page = site['/demo'] beer_verse = ''' {{before}} bottles of beer on the wall, {{before}} bottles of beer. Take one down, pass it around, {{after}} bottles of beer on the wall... ''' beer_card = page.add('example', ui.markdown_card( box='1 1 4 2', title='99 Bottles of Beer', content='=' + beer_verse, # Make the verse a template expression by prefixing a '='. data=dict(before='99', after='98'), )) page.save() for i in range(98, 2, -1): time.sleep(1) beer_card.data.before = str(i) beer_card.data.after = str(i - 1) page.save()
# #layout # --- from h2o_wave import site, ui # Every page has a grid system in place. # The grid has 12 columns and 10 rows. # A column is 134 pixels wide. # A row is 76 pixels high. # The gap between rows and columns is set to 15 pixels. # Cards have a `box` attribute that specifies its column, row, width and height. # box = 'column row width height' # They indicate the 1-based column/row to position the top-left corner of the card. # In this example, we place a 1x1 card in each column/row on a page # to demonstrate their column/row values. page = site['/demo'] columns = 12 rows = 10 for column in range(1, columns + 1): for row in range(1, rows + 1): box = f'{column} {row} 1 1' page[f'card_{column}_{row}'] = ui.markdown_card(box=box, title=box, content='') page.save()
- The quick brown fox jumped over the lazy dog. - The quick brown fox jumped over the lazy dog. - The quick brown fox jumped over the lazy dog. Ordered list: 1. The quick brown fox jumped over the lazy dog. 1. The quick brown fox jumped over the lazy dog. 1. The quick brown fox jumped over the lazy dog. Image: ![Monty Python](https://upload.wikimedia.org/wikipedia/en/c/cb/Flyingcircus_2.jpg) Table: | Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Item 1 | Item 2 | Item 3 | | Item 1 | Item 2 | Item 3 | | Item 1 | Item 2 | Item 3 | ''' page['example'] = ui.markdown_card( box='1 1 3 -1', title='I was made using markdown!', content=sample_markdown, ) page.save()
# Meta / Inline Stylesheet # Use inline CSS to style a Wave app in case of quirks. Prefer using native Wave components if possible. # --- from h2o_wave import site, ui page = site['/demo'] style = ''' p { color: red; } ''' # Add a placeholder. page['example'] = ui.markdown_card( box='1 1 2 2', title='Try out the styling', content='I should be red!', ) # Add the style to the page. page['meta'] = ui.meta_card(box='', stylesheet=ui.inline_stylesheet(style)) page.save()