banner.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. """Banner components."""
  2. from __future__ import annotations
  3. from typing import Optional
  4. from reflex.components.base.bare import Bare
  5. from reflex.components.chakra.layout import Box
  6. from reflex.components.chakra.overlay.modal import Modal
  7. from reflex.components.chakra.typography import Text
  8. from reflex.components.component import Component
  9. from reflex.components.core.cond import cond
  10. from reflex.constants import Dirs, Hooks, Imports
  11. from reflex.utils import imports
  12. from reflex.vars import Var, VarData
  13. connect_error_var_data: VarData = VarData( # type: ignore
  14. imports=Imports.EVENTS,
  15. hooks={Hooks.EVENTS},
  16. )
  17. connection_error: Var = Var.create_safe(
  18. value="(connectError !== null) ? connectError.message : ''",
  19. _var_is_local=False,
  20. _var_is_string=False,
  21. )._replace(merge_var_data=connect_error_var_data)
  22. has_connection_error: Var = Var.create_safe(
  23. value="connectError !== null",
  24. _var_is_string=False,
  25. )._replace(_var_type=bool, merge_var_data=connect_error_var_data)
  26. class WebsocketTargetURL(Bare):
  27. """A component that renders the websocket target URL."""
  28. def _get_imports(self) -> imports.ImportDict:
  29. return {
  30. f"/{Dirs.STATE_PATH}": [imports.ImportVar(tag="getBackendURL")],
  31. "/env.json": [imports.ImportVar(tag="env", is_default=True)],
  32. }
  33. @classmethod
  34. def create(cls) -> Component:
  35. """Create a websocket target URL component.
  36. Returns:
  37. The websocket target URL component.
  38. """
  39. return super().create(contents="{getBackendURL(env.EVENT).href}")
  40. def default_connection_error() -> list[str | Var | Component]:
  41. """Get the default connection error message.
  42. Returns:
  43. The default connection error message.
  44. """
  45. return [
  46. "Cannot connect to server: ",
  47. connection_error,
  48. ". Check if server is reachable at ",
  49. WebsocketTargetURL.create(),
  50. ]
  51. class ConnectionBanner(Component):
  52. """A connection banner component."""
  53. @classmethod
  54. def create(cls, comp: Optional[Component] = None) -> Component:
  55. """Create a connection banner component.
  56. Args:
  57. comp: The component to render when there's a server connection error.
  58. Returns:
  59. The connection banner component.
  60. """
  61. if not comp:
  62. comp = Box.create(
  63. Text.create(
  64. *default_connection_error(),
  65. bg="red",
  66. color="white",
  67. ),
  68. textAlign="center",
  69. )
  70. return cond(has_connection_error, comp)
  71. class ConnectionModal(Component):
  72. """A connection status modal window."""
  73. @classmethod
  74. def create(cls, comp: Optional[Component] = None) -> Component:
  75. """Create a connection banner component.
  76. Args:
  77. comp: The component to render when there's a server connection error.
  78. Returns:
  79. The connection banner component.
  80. """
  81. if not comp:
  82. comp = Text.create(*default_connection_error())
  83. return cond(
  84. has_connection_error,
  85. Modal.create(
  86. header="Connection Error",
  87. body=comp,
  88. is_open=has_connection_error,
  89. ),
  90. )