notification.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import asyncio
  2. from typing import Any, Callable, Literal, Optional, Union
  3. from typing_extensions import Self
  4. from ..context import context
  5. from ..element import Element
  6. from ..events import UiEventArguments, handle_event
  7. NotificationPosition = Literal[
  8. 'top-left',
  9. 'top-right',
  10. 'bottom-left',
  11. 'bottom-right',
  12. 'top',
  13. 'bottom',
  14. 'left',
  15. 'right',
  16. 'center',
  17. ]
  18. NotificationType = Optional[Literal[
  19. 'positive',
  20. 'negative',
  21. 'warning',
  22. 'info',
  23. 'ongoing',
  24. ]]
  25. class Notification(Element, component='notification.js'):
  26. def __init__(self,
  27. message: Any = '', *,
  28. position: NotificationPosition = 'bottom',
  29. close_button: Union[bool, str] = False,
  30. type: NotificationType = None, # pylint: disable=redefined-builtin
  31. color: Optional[str] = None,
  32. multi_line: bool = False,
  33. icon: Optional[str] = None,
  34. spinner: bool = False,
  35. timeout: Optional[float] = 5.0,
  36. on_dismiss: Optional[Callable] = None,
  37. **kwargs: Any,
  38. ) -> None:
  39. """Notification element
  40. Displays a notification on the screen.
  41. In contrast to `ui.notify`, this element allows to update the notification message and other properties once the notification is displayed.
  42. The notification can be removed with `dismiss()`.
  43. :param message: content of the notification
  44. :param position: position on the screen ("top-left", "top-right", "bottom-left", "bottom-right", "top", "bottom", "left", "right" or "center", default: "bottom")
  45. :param close_button: optional label of a button to dismiss the notification (default: `False`)
  46. :param type: optional type ("positive", "negative", "warning", "info" or "ongoing")
  47. :param color: optional color name
  48. :param multi_line: enable multi-line notifications
  49. :param icon: optional name of an icon to be displayed in the notification (default: `None`)
  50. :param spinner: display a spinner in the notification (default: False)
  51. :param timeout: optional timeout in seconds after which the notification is dismissed (default: 5.0)
  52. :param on_dismiss: optional callback to be invoked when the notification is dismissed
  53. Note: You can pass additional keyword arguments according to `Quasar's Notify API <https://quasar.dev/quasar-plugins/notify#notify-api>`_.
  54. """
  55. with context.client.layout:
  56. super().__init__()
  57. self._props['options'] = {
  58. 'message': str(message),
  59. 'position': position,
  60. 'multiLine': multi_line,
  61. 'spinner': spinner,
  62. 'closeBtn': close_button,
  63. 'timeout': (timeout or 0) * 1000,
  64. 'group': False,
  65. 'attrs': {'data-id': f'nicegui-dialog-{self.id}'},
  66. }
  67. if type is not None:
  68. self._props['options']['type'] = type
  69. if color is not None:
  70. self._props['options']['color'] = color
  71. if icon is not None:
  72. self._props['options']['icon'] = icon
  73. self._props['options'].update(kwargs)
  74. if on_dismiss:
  75. self.on_dismiss(on_dismiss)
  76. async def handle_dismiss() -> None:
  77. if self.client.is_auto_index_client:
  78. self.dismiss()
  79. await asyncio.sleep(1.0) # NOTE: sent dismiss message to all browsers before deleting the element
  80. if not self._deleted:
  81. self.clear()
  82. self.delete()
  83. self.on('dismiss', handle_dismiss)
  84. @property
  85. def message(self) -> str:
  86. """Message text."""
  87. return self._props['options']['message']
  88. @message.setter
  89. def message(self, value: Any) -> None:
  90. self._props['options']['message'] = str(value)
  91. self.update()
  92. @property
  93. def position(self) -> NotificationPosition:
  94. """Position on the screen."""
  95. return self._props['options']['position']
  96. @position.setter
  97. def position(self, value: NotificationPosition) -> None:
  98. self._props['options']['position'] = value
  99. self.update()
  100. @property
  101. def type(self) -> NotificationType:
  102. """Type of the notification."""
  103. return self._props['options'].get('type')
  104. @type.setter
  105. def type(self, value: NotificationType) -> None:
  106. if value is None:
  107. self._props['options'].pop('type', None)
  108. else:
  109. self._props['options']['type'] = value
  110. self.update()
  111. @property
  112. def color(self) -> Optional[str]:
  113. """Color of the notification."""
  114. return self._props['options'].get('color')
  115. @color.setter
  116. def color(self, value: Optional[str]) -> None:
  117. if value is None:
  118. self._props['options'].pop('color', None)
  119. else:
  120. self._props['options']['color'] = value
  121. self.update()
  122. @property
  123. def multi_line(self) -> bool:
  124. """Whether the notification is multi-line."""
  125. return self._props['options']['multiLine']
  126. @multi_line.setter
  127. def multi_line(self, value: bool) -> None:
  128. self._props['options']['multiLine'] = value
  129. self.update()
  130. @property
  131. def icon(self) -> Optional[str]:
  132. """Icon of the notification."""
  133. return self._props['options'].get('icon')
  134. @icon.setter
  135. def icon(self, value: Optional[str]) -> None:
  136. if value is None:
  137. self._props['options'].pop('icon', None)
  138. else:
  139. self._props['options']['icon'] = value
  140. self.update()
  141. @property
  142. def spinner(self) -> bool:
  143. """Whether the notification is a spinner."""
  144. return self._props['options']['spinner']
  145. @spinner.setter
  146. def spinner(self, value: bool) -> None:
  147. self._props['options']['spinner'] = value
  148. self.update()
  149. @property
  150. def close_button(self) -> Union[bool, str]:
  151. """Whether the notification has a close button."""
  152. return self._props['options']['closeBtn']
  153. @close_button.setter
  154. def close_button(self, value: Union[bool, str]) -> None:
  155. self._props['options']['closeBtn'] = value
  156. self.update()
  157. def on_dismiss(self, callback: Callable[..., Any]) -> Self:
  158. """Add a callback to be invoked when the notification is dismissed."""
  159. self.on('dismiss', lambda _: handle_event(callback, UiEventArguments(sender=self, client=self.client)), [])
  160. return self
  161. def dismiss(self) -> None:
  162. """Dismiss the notification."""
  163. self.run_method('dismiss')