datatable.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. """Table components."""
  2. from typing import Any, List, Optional
  3. from pynecone.components.component import Component
  4. from pynecone.components.tags import Tag
  5. from pynecone.utils import format, imports, types
  6. from pynecone.var import BaseVar, ComputedVar, Var
  7. class Gridjs(Component):
  8. """A component that wraps a nivo bar component."""
  9. library = "gridjs-react"
  10. class DataTable(Gridjs):
  11. """A data table component."""
  12. tag = "Grid"
  13. # The data to display. Either a list of lists or a pandas dataframe.
  14. data: Any
  15. # The list of columns to display. Required if data is a list and should not be provided
  16. # if the data field is a dataframe
  17. columns: Var[List]
  18. # Enable a search bar.
  19. search: Var[bool]
  20. # Enable sorting on columns.
  21. sort: Var[bool]
  22. # Enable resizable columns.
  23. resizable: Var[bool]
  24. # Enable pagination.
  25. pagination: Var[bool]
  26. @classmethod
  27. def get_alias(cls) -> Optional[str]:
  28. """Get the alias for the component.
  29. Returns:
  30. The alias.
  31. """
  32. return "DataTableGrid"
  33. @classmethod
  34. def create(cls, *children, **props):
  35. """Create a datatable component.
  36. Args:
  37. *children: The children of the component.
  38. **props: The props to pass to the component.
  39. Returns:
  40. The datatable component.
  41. Raises:
  42. ValueError: If a pandas dataframe is passed in and columns are also provided.
  43. """
  44. data = props.get("data")
  45. columns = props.get("columns")
  46. # The annotation should be provided if data is a computed var. We need this to know how to
  47. # render pandas dataframes.
  48. if isinstance(data, ComputedVar) and data.type_ == Any:
  49. raise ValueError(
  50. "Annotation of the computed var assigned to the data field should be provided."
  51. )
  52. if columns and isinstance(columns, ComputedVar) and columns.type_ == Any:
  53. raise ValueError(
  54. "Annotation of the computed var assigned to the column field should be provided."
  55. )
  56. # If data is a pandas dataframe and columns are provided throw an error.
  57. if (
  58. types.is_dataframe(type(data))
  59. or (isinstance(data, Var) and types.is_dataframe(data.type_))
  60. ) and props.get("columns"):
  61. raise ValueError(
  62. "Cannot pass in both a pandas dataframe and columns to the data_table component."
  63. )
  64. # If data is a list and columns are not provided, throw an error
  65. if (
  66. (isinstance(data, Var) and types._issubclass(data.type_, List))
  67. or issubclass(type(data), List)
  68. ) and not props.get("columns"):
  69. raise ValueError(
  70. "column field should be specified when the data field is a list type"
  71. )
  72. # Create the component.
  73. return super().create(
  74. *children,
  75. **props,
  76. )
  77. def _get_imports(self) -> imports.ImportDict:
  78. return imports.merge_imports(
  79. super()._get_imports(), {"": {"gridjs/dist/theme/mermaid.css"}}
  80. )
  81. def _render(self) -> Tag:
  82. if isinstance(self.data, Var):
  83. self.columns = BaseVar(
  84. name=f"{self.data.name}.columns"
  85. if types.is_dataframe(self.data.type_)
  86. else f"{self.columns.name}",
  87. type_=List[Any],
  88. state=self.data.state,
  89. )
  90. self.data = BaseVar(
  91. name=f"{self.data.name}.data"
  92. if types.is_dataframe(self.data.type_)
  93. else f"{self.data.name}",
  94. type_=List[List[Any]],
  95. state=self.data.state,
  96. )
  97. # If given a pandas df break up the data and columns
  98. if types.is_dataframe(type(self.data)):
  99. self.columns = Var.create(list(self.data.columns.values.tolist())) # type: ignore
  100. self.data = Var.create(format.format_dataframe_values(self.data)) # type: ignore
  101. # Render the table.
  102. return super()._render()