Skip to content

Commit

Permalink
feat: Notification bar #1007
Browse files Browse the repository at this point in the history
  • Loading branch information
mturoci committed Jan 19, 2022
1 parent 0dfe518 commit 3482acd
Show file tree
Hide file tree
Showing 12 changed files with 524 additions and 16 deletions.
9 changes: 7 additions & 2 deletions py/examples/message_bar.py
Expand Up @@ -7,16 +7,21 @@
page = site['/demo']

page['example'] = ui.form_card(
box='1 1 4 10',
box='1 1 3 10',
items=[
ui.message_bar(type='blocked', text='This action is blocked.'),
ui.message_bar(type='error', text='This is an error message'),
ui.message_bar(type='warning', text='This is a warning message.'),
ui.message_bar(type='info', text='This is an information message.'),
ui.message_bar(type='success', text='This is an success message.'),
ui.message_bar(type='success', text='This is a success message.'),
ui.message_bar(type='danger', text='This is a danger message.'),
ui.message_bar(type='success', text='This is a **MARKDOWN** _message_.'),
ui.message_bar(type='success', text='This is an <b>HTML</b> <i>message</i>.'),
ui.message_bar(type='info', text='With a button.', buttons=[ui.button(name='btn', label='Button')]),
ui.message_bar(type='info', text='With a button as link.',
buttons=[ui.button(name='btn', label='Button', link=True)]),
ui.message_bar(type='info', text='With multiline text that should hopefully span at least 2 rows',
buttons=[ui.button(name='btn', label='Button')]),
]
)
page.save()
61 changes: 61 additions & 0 deletions py/examples/meta_notification_bar.py
@@ -0,0 +1,61 @@
# Meta / Notification bar
# Display a notification bar #notification_bar. #meta
# Use this kind of notification when an immediate user feedback is needed. For cases when
# the feedback is not immediate (long-running jobs), use ui.notification as it will
# be visible even when the user is not currently focusing browser tab with your Wave app.
# ---
from h2o_wave import main, app, Q, ui


@app('/demo')
async def serve(q: Q):
if not q.client.initialized:
q.page['form'] = ui.form_card(box='1 1 2 4', items=[
ui.button(name='top_right', label='Success top-right'),
ui.button(name='top_center', label='Error top-center'),
ui.button(name='top_left', label='Warning top-left'),
ui.button(name='bottom_right', label='Info bottom-right'),
ui.button(name='bottom_center', label='Info bottom-center'),
ui.button(name='bottom_left', label='Info bottom-left'),
])
q.client.initialized = True
if q.args.top_right:
q.page['meta'] = ui.meta_card(box='', notification_bar=ui.notification_bar(
text='Success notification',
type='success',
position='top-right',
buttons=[ui.button(name='btn1', label='Button 1', link=True)]
))
if q.args.top_center:
q.page['meta'] = ui.meta_card(box='', notification_bar=ui.notification_bar(
text='Error notification that should hopefully span at least two lines',
type='error',
position='top-center',
buttons=[
ui.button(name='btn1', label='Button 1'),
ui.button(name='btn2', label='Button 2')
]
))
if q.args.top_left:
q.page['meta'] = ui.meta_card(box='', notification_bar=ui.notification_bar(
text='Warning notification',
type='warning',
position='top-left',
))
if q.args.bottom_right:
q.page['meta'] = ui.meta_card(box='', notification_bar=ui.notification_bar(
text='Info notification',
type='info',
position='bottom-right',
))
if q.args.bottom_center:
q.page['meta'] = ui.meta_card(box='', notification_bar=ui.notification_bar(
text='Info notification',
position='bottom-center',
))
if q.args.bottom_left:
q.page['meta'] = ui.meta_card(box='', notification_bar=ui.notification_bar(
text='Default notification',
position='bottom-left',
))
await q.page.save()
1 change: 1 addition & 0 deletions py/examples/tour.conf
Expand Up @@ -193,6 +193,7 @@ meta_side_panel.py
meta_title.py
meta_icon.py
meta_notification.py
meta_notification_bar.py
meta_refresh.py
meta_redirect.py
meta_theme.py
Expand Down
126 changes: 126 additions & 0 deletions py/h2o_wave/types.py
Expand Up @@ -890,12 +890,14 @@ def __init__(
type: Optional[str] = None,
text: Optional[str] = None,
name: Optional[str] = None,
buttons: Optional[List['Component']] = None,
width: Optional[str] = None,
visible: Optional[bool] = None,
):
_guard_enum('MessageBar.type', type, _MessageBarType, True)
_guard_scalar('MessageBar.text', text, (str,), False, True, False)
_guard_scalar('MessageBar.name', name, (str,), False, True, False)
_guard_vector('MessageBar.buttons', buttons, (Component,), False, True, False)
_guard_scalar('MessageBar.width', width, (str,), False, True, False)
_guard_scalar('MessageBar.visible', visible, (bool,), False, True, False)
self.type = type
Expand All @@ -904,6 +906,8 @@ def __init__(
"""The text displayed on the message bar."""
self.name = name
"""An identifying name for this component."""
self.buttons = buttons
"""Specify one or more action buttons."""
self.width = width
"""The width of the message bar, e.g. '100px'. Defaults to '100%'."""
self.visible = visible
Expand All @@ -914,12 +918,14 @@ def dump(self) -> Dict:
_guard_enum('MessageBar.type', self.type, _MessageBarType, True)
_guard_scalar('MessageBar.text', self.text, (str,), False, True, False)
_guard_scalar('MessageBar.name', self.name, (str,), False, True, False)
_guard_vector('MessageBar.buttons', self.buttons, (Component,), False, True, False)
_guard_scalar('MessageBar.width', self.width, (str,), False, True, False)
_guard_scalar('MessageBar.visible', self.visible, (bool,), False, True, False)
return _dump(
type=self.type,
text=self.text,
name=self.name,
buttons=None if self.buttons is None else [__e.dump() for __e in self.buttons],
width=self.width,
visible=self.visible,
)
Expand All @@ -933,19 +939,23 @@ def load(__d: Dict) -> 'MessageBar':
_guard_scalar('MessageBar.text', __d_text, (str,), False, True, False)
__d_name: Any = __d.get('name')
_guard_scalar('MessageBar.name', __d_name, (str,), False, True, False)
__d_buttons: Any = __d.get('buttons')
_guard_vector('MessageBar.buttons', __d_buttons, (dict,), False, True, False)
__d_width: Any = __d.get('width')
_guard_scalar('MessageBar.width', __d_width, (str,), False, True, False)
__d_visible: Any = __d.get('visible')
_guard_scalar('MessageBar.visible', __d_visible, (bool,), False, True, False)
type: Optional[str] = __d_type
text: Optional[str] = __d_text
name: Optional[str] = __d_name
buttons: Optional[List['Component']] = None if __d_buttons is None else [Component.load(__e) for __e in __d_buttons]
width: Optional[str] = __d_width
visible: Optional[bool] = __d_visible
return MessageBar(
type,
text,
name,
buttons,
width,
visible,
)
Expand Down Expand Up @@ -8297,6 +8307,112 @@ def load(__d: Dict) -> 'MarkupCard':
)


_NotificationBarType = ['info', 'error', 'warning', 'success', 'danger', 'blocked']


class NotificationBarType:
INFO = 'info'
ERROR = 'error'
WARNING = 'warning'
SUCCESS = 'success'
DANGER = 'danger'
BLOCKED = 'blocked'


_NotificationBarPosition = ['top-right', 'bottom-right', 'bottom-center', 'bottom-left', 'top-left', 'top-center']


class NotificationBarPosition:
TOP_RIGHT = 'top-right'
BOTTOM_RIGHT = 'bottom-right'
BOTTOM_CENTER = 'bottom-center'
BOTTOM_LEFT = 'bottom-left'
TOP_LEFT = 'top-left'
TOP_CENTER = 'top-center'


class NotificationBar:
"""Create a notification bar.

A notification bar is an area at the edge of a primary view that displays relevant status information.
You can use a notification bar to tell the user about a result of an action, e.g. "Data has been successfully saved".
"""
def __init__(
self,
text: str,
type: Optional[str] = None,
timeout: Optional[int] = None,
buttons: Optional[List[Component]] = None,
position: Optional[str] = None,
events: Optional[List[str]] = None,
):
_guard_scalar('NotificationBar.text', text, (str,), False, False, False)
_guard_enum('NotificationBar.type', type, _NotificationBarType, True)
_guard_scalar('NotificationBar.timeout', timeout, (int,), False, True, False)
_guard_vector('NotificationBar.buttons', buttons, (Component,), False, True, False)
_guard_enum('NotificationBar.position', position, _NotificationBarPosition, True)
_guard_vector('NotificationBar.events', events, (str,), False, True, False)
self.text = text
"""The text displayed on the notification bar."""
self.type = type
"""The icon and color of the notification bar. Defaults to 'info'. One of 'info', 'error', 'warning', 'success', 'danger', 'blocked'. See enum h2o_wave.ui.NotificationBarType."""
self.timeout = timeout
"""When should the notification bar disappear in seconds. Defaults to 5."""
self.buttons = buttons
"""Specify one or more action buttons."""
self.position = position
"""Specify the location of notification. Defaults to 'top-right'. One of 'top-right', 'bottom-right', 'bottom-center', 'bottom-left', 'top-left', 'top-center'. See enum h2o_wave.ui.NotificationBarPosition."""
self.events = events
"""The events to capture on this notification bar."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
_guard_scalar('NotificationBar.text', self.text, (str,), False, False, False)
_guard_enum('NotificationBar.type', self.type, _NotificationBarType, True)
_guard_scalar('NotificationBar.timeout', self.timeout, (int,), False, True, False)
_guard_vector('NotificationBar.buttons', self.buttons, (Component,), False, True, False)
_guard_enum('NotificationBar.position', self.position, _NotificationBarPosition, True)
_guard_vector('NotificationBar.events', self.events, (str,), False, True, False)
return _dump(
text=self.text,
type=self.type,
timeout=self.timeout,
buttons=None if self.buttons is None else [__e.dump() for __e in self.buttons],
position=self.position,
events=self.events,
)

@staticmethod
def load(__d: Dict) -> 'NotificationBar':
"""Creates an instance of this class using the contents of a dict."""
__d_text: Any = __d.get('text')
_guard_scalar('NotificationBar.text', __d_text, (str,), False, False, False)
__d_type: Any = __d.get('type')
_guard_enum('NotificationBar.type', __d_type, _NotificationBarType, True)
__d_timeout: Any = __d.get('timeout')
_guard_scalar('NotificationBar.timeout', __d_timeout, (int,), False, True, False)
__d_buttons: Any = __d.get('buttons')
_guard_vector('NotificationBar.buttons', __d_buttons, (dict,), False, True, False)
__d_position: Any = __d.get('position')
_guard_enum('NotificationBar.position', __d_position, _NotificationBarPosition, True)
__d_events: Any = __d.get('events')
_guard_vector('NotificationBar.events', __d_events, (str,), False, True, False)
text: str = __d_text
type: Optional[str] = __d_type
timeout: Optional[int] = __d_timeout
buttons: Optional[List[Component]] = None if __d_buttons is None else [Component.load(__e) for __e in __d_buttons]
position: Optional[str] = __d_position
events: Optional[List[str]] = __d_events
return NotificationBar(
text,
type,
timeout,
buttons,
position,
events,
)


_ZoneDirection = ['row', 'column']


Expand Down Expand Up @@ -9042,6 +9158,7 @@ def __init__(
title: Optional[str] = None,
refresh: Optional[int] = None,
notification: Optional[str] = None,
notification_bar: Optional[NotificationBar] = None,
redirect: Optional[str] = None,
icon: Optional[str] = None,
layouts: Optional[List[Layout]] = None,
Expand All @@ -9060,6 +9177,7 @@ def __init__(
_guard_scalar('MetaCard.title', title, (str,), False, True, False)
_guard_scalar('MetaCard.refresh', refresh, (int,), False, True, False)
_guard_scalar('MetaCard.notification', notification, (str,), False, True, False)
_guard_scalar('MetaCard.notification_bar', notification_bar, (NotificationBar,), False, True, False)
_guard_scalar('MetaCard.redirect', redirect, (str,), False, True, False)
_guard_scalar('MetaCard.icon', icon, (str,), False, True, False)
_guard_vector('MetaCard.layouts', layouts, (Layout,), False, True, False)
Expand All @@ -9081,6 +9199,8 @@ def __init__(
"""Refresh rate in seconds. A value of 0 turns off live-updates. Values != 0 are currently ignored (reserved for future use)."""
self.notification = notification
"""Display a desktop notification."""
self.notification_bar = notification_bar
"""Display an in-app notification bar."""
self.redirect = redirect
"""Redirect the page to a new URL."""
self.icon = icon
Expand Down Expand Up @@ -9114,6 +9234,7 @@ def dump(self) -> Dict:
_guard_scalar('MetaCard.title', self.title, (str,), False, True, False)
_guard_scalar('MetaCard.refresh', self.refresh, (int,), False, True, False)
_guard_scalar('MetaCard.notification', self.notification, (str,), False, True, False)
_guard_scalar('MetaCard.notification_bar', self.notification_bar, (NotificationBar,), False, True, False)
_guard_scalar('MetaCard.redirect', self.redirect, (str,), False, True, False)
_guard_scalar('MetaCard.icon', self.icon, (str,), False, True, False)
_guard_vector('MetaCard.layouts', self.layouts, (Layout,), False, True, False)
Expand All @@ -9133,6 +9254,7 @@ def dump(self) -> Dict:
title=self.title,
refresh=self.refresh,
notification=self.notification,
notification_bar=None if self.notification_bar is None else self.notification_bar.dump(),
redirect=self.redirect,
icon=self.icon,
layouts=None if self.layouts is None else [__e.dump() for __e in self.layouts],
Expand All @@ -9159,6 +9281,8 @@ def load(__d: Dict) -> 'MetaCard':
_guard_scalar('MetaCard.refresh', __d_refresh, (int,), False, True, False)
__d_notification: Any = __d.get('notification')
_guard_scalar('MetaCard.notification', __d_notification, (str,), False, True, False)
__d_notification_bar: Any = __d.get('notification_bar')
_guard_scalar('MetaCard.notification_bar', __d_notification_bar, (dict,), False, True, False)
__d_redirect: Any = __d.get('redirect')
_guard_scalar('MetaCard.redirect', __d_redirect, (str,), False, True, False)
__d_icon: Any = __d.get('icon')
Expand Down Expand Up @@ -9189,6 +9313,7 @@ def load(__d: Dict) -> 'MetaCard':
title: Optional[str] = __d_title
refresh: Optional[int] = __d_refresh
notification: Optional[str] = __d_notification
notification_bar: Optional[NotificationBar] = None if __d_notification_bar is None else NotificationBar.load(__d_notification_bar)
redirect: Optional[str] = __d_redirect
icon: Optional[str] = __d_icon
layouts: Optional[List[Layout]] = None if __d_layouts is None else [Layout.load(__e) for __e in __d_layouts]
Expand All @@ -9207,6 +9332,7 @@ def load(__d: Dict) -> 'MetaCard':
title,
refresh,
notification,
notification_bar,
redirect,
icon,
layouts,
Expand Down

0 comments on commit 3482acd

Please sign in to comment.