eptm_dashboard/.venv/lib/python3.12/site-packages/reflex_components_gridjs/datatable.py

128 lines
4.2 KiB
Python

"""Table components."""
from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from reflex_base.components.component import NoSSRComponent, field
from reflex_base.components.tags import Tag
from reflex_base.utils import types
from reflex_base.utils.imports import ImportDict
from reflex_base.utils.serializers import serialize
from reflex_base.vars.base import LiteralVar, Var, is_computed_var
class Gridjs(NoSSRComponent):
"""A component that wraps a nivo bar component."""
library = "gridjs-react@6.1.1"
lib_dependencies: list[str] = ["gridjs@6.2.0"]
class DataTable(Gridjs):
"""A data table component."""
tag = "Grid"
alias = "DataTableGrid"
data: Any = field(
doc="The data to display. Either a list of lists or a pandas dataframe."
)
columns: Var[Sequence] = field(
doc="The list of columns to display. Required if data is a list and should not be provided if the data field is a dataframe"
)
search: Var[bool] = field(doc="Enable a search bar.")
sort: Var[bool] = field(doc="Enable sorting on columns.")
resizable: Var[bool] = field(doc="Enable resizable columns.")
pagination: Var[bool | dict] = field(doc="Enable pagination.")
@classmethod
def create(cls, *children, **props):
"""Create a datatable component.
Args:
*children: The children of the component.
**props: The props to pass to the component.
Returns:
The datatable component.
Raises:
ValueError: If a pandas dataframe is passed in and columns are also provided.
"""
data = props.get("data")
columns = props.get("columns")
# The annotation should be provided if data is a computed var. We need this to know how to
# render pandas dataframes.
if is_computed_var(data) and data._var_type == Any:
msg = "Annotation of the computed var assigned to the data field should be provided."
raise ValueError(msg)
if (
columns is not None
and is_computed_var(columns)
and columns._var_type == Any
):
msg = "Annotation of the computed var assigned to the column field should be provided."
raise ValueError(msg)
# If data is a pandas dataframe and columns are provided throw an error.
if (
types.is_dataframe(type(data))
or (isinstance(data, Var) and types.is_dataframe(data._var_type))
) and columns is not None:
msg = "Cannot pass in both a pandas dataframe and columns to the data_table component."
raise ValueError(msg)
# If data is a list and columns are not provided, throw an error
if (
(isinstance(data, Var) and types.typehint_issubclass(data._var_type, list))
or isinstance(data, list)
) and columns is None:
msg = "column field should be specified when the data field is a list type"
raise ValueError(msg)
# Create the component.
return super().create(
*children,
**props,
)
def add_imports(self) -> ImportDict:
"""Add the imports for the datatable component.
Returns:
The import dict for the component.
"""
return {"": "gridjs/dist/theme/mermaid.css"}
def _render(self) -> Tag:
if isinstance(self.data, Var) and types.is_dataframe(self.data._var_type):
self.columns = self.data._replace(
_js_expr=f"{self.data._js_expr}.columns",
_var_type=list[Any],
)
self.data = self.data._replace(
_js_expr=f"{self.data._js_expr}.data",
_var_type=list[list[Any]],
)
if types.is_dataframe(type(self.data)):
# If given a pandas df break up the data and columns
data = serialize(self.data)
if not isinstance(data, dict):
msg = "Serialized dataframe should be a dict."
raise ValueError(msg)
self.columns = LiteralVar.create(data["columns"])
self.data = LiteralVar.create(data["data"])
# Render the table.
return super()._render()