Bladeren bron

Data Editor Icon header to Column

Elijah 1 jaar geleden
bovenliggende
commit
b10cab04cb
3 gewijzigde bestanden met toevoegingen van 176 en 112 verwijderingen
  1. 86 76
      reflex/components/datadisplay/dataeditor.py
  2. 88 34
      reflex/components/datadisplay/dataeditor.pyi
  3. 2 2
      reflex/utils/serializers.py

+ 86 - 76
reflex/components/datadisplay/dataeditor.py

@@ -1,71 +1,61 @@
 """Data Editor component from glide-data-grid."""
 """Data Editor component from glide-data-grid."""
 from __future__ import annotations
 from __future__ import annotations
 
 
-from enum import Enum
-from typing import Any, Callable, Dict, List, Optional, Union
+from typing import Any, Callable, Dict, List, Literal, Optional, Union
 
 
 from reflex.base import Base
 from reflex.base import Base
 from reflex.components.component import Component, NoSSRComponent
 from reflex.components.component import Component, NoSSRComponent
 from reflex.components.literals import LiteralRowMarker
 from reflex.components.literals import LiteralRowMarker
 from reflex.utils import console, format, imports, types
 from reflex.utils import console, format, imports, types
-from reflex.utils.serializers import serializer
 from reflex.vars import ImportVar, Var, get_unique_variable_name
 from reflex.vars import ImportVar, Var, get_unique_variable_name
 
 
+LiteralDataEditorGridColumnIcons = Literal[
+    "headerRowID",
+    "headerCode",
+    "headerNumber",
+    "headerString",
+    "headerBoolean",
+    "headerAudioUri",
+    "headerVideoUri",
+    "headerEmoji",
+    "headerImage",
+    "headerUri",
+    "headerPhone",
+    "headerMarkdown",
+    "headerDate",
+    "headerTime",
+    "headerEmail",
+    "headerReference",
+    "headerIfThenElse",
+    "headerSingleValue",
+    "headerLookup",
+    "headerTextTemplate",
+    "headerMath",
+    "headerRollup",
+    "headerJoinStrings",
+    "headerSplitString",
+    "headerGeoDistance",
+    "headerArray",
+    "rowOwnerOverlay",
+    "protectedColumnOverlay",
+]
+LiteralDataEditorColumnStyle = Literal["normal", "highlight"]
+
+
+class DataEditorProp(Base):
+    """Base class for Data Editor custom prop class."""
+
+    def dict(self) -> dict:
+        """Retrieve dict and format keys to camel case.
 
 
-# TODO: Fix the serialization issue for custom types.
-class GridColumnIcons(Enum):
-    """An Enum for the available icons in DataEditor."""
-
-    Array = "array"
-    AudioUri = "audio_uri"
-    Boolean = "boolean"
-    HeaderCode = "code"
-    Date = "date"
-    Email = "email"
-    Emoji = "emoji"
-    GeoDistance = "geo_distance"
-    IfThenElse = "if_then_else"
-    Image = "image"
-    JoinStrings = "join_strings"
-    Lookup = "lookup"
-    Markdown = "markdown"
-    Math = "math"
-    Number = "number"
-    Phone = "phone"
-    Reference = "reference"
-    Rollup = "rollup"
-    RowID = "row_id"
-    SingleValue = "single_value"
-    SplitString = "split_string"
-    String = "string"
-    TextTemplate = "text_template"
-    Time = "time"
-    Uri = "uri"
-    VideoUri = "video_uri"
-
-
-# @serializer
-# def serialize_gridcolumn_icon(icon: GridColumnIcons) -> str:
-#     """Serialize grid column icon.
-
-#     Args:
-#         icon: the Icon to serialize.
-
-#     Returns:
-#         The serialized value.
-#     """
-#     return "prefix" + str(icon)
-
-
-# class DataEditorColumn(Base):
-#     """Column."""
-
-#     title: str
-#     id: Optional[str] = None
-#     type_: str = "str"
-
-
-class DataEditorTheme(Base):
+        Returns:
+            Formatted dict.
+        """
+        res = super().dict()
+        return {format.to_camel_case(k): v for k, v in res.items() if v is not None}
+
+
+class DataEditorTheme(DataEditorProp):
     """The theme for the DataEditor component."""
     """The theme for the DataEditor component."""
 
 
     accent_color: Optional[str] = None
     accent_color: Optional[str] = None
@@ -102,6 +92,33 @@ class DataEditorTheme(Base):
     text_medium: Optional[str] = None
     text_medium: Optional[str] = None
 
 
 
 
+class TrailingRowOptions(DataEditorProp):
+    """Trailing Row options."""
+
+    hint: Optional[str]
+    add_icon: Optional[str]
+    target_column: Optional[int]
+    theme_override: Optional[DataEditorTheme]
+    disabled: Optional[bool]
+
+
+class DataEditorColumn(DataEditorProp):
+    """Column."""
+
+    title: str
+    id: Optional[str] = None
+    type_: str = "str"
+    group: Optional[str]
+    icon: Optional[LiteralDataEditorGridColumnIcons]
+    overlay_icon: Optional[LiteralDataEditorGridColumnIcons]
+    has_menu: Optional[bool]
+    grow: Optional[int]
+    style: Optional[LiteralDataEditorColumnStyle]
+    theme_override: Optional[DataEditorTheme]
+    trailing_row_options: Optional[TrailingRowOptions]
+    grow_offset: Optional[int]
+
+
 class DataEditor(NoSSRComponent):
 class DataEditor(NoSSRComponent):
     """The DataEditor Component."""
     """The DataEditor Component."""
 
 
@@ -114,7 +131,7 @@ class DataEditor(NoSSRComponent):
     rows: Var[int]
     rows: Var[int]
 
 
     # Headers of the columns for the data grid.
     # Headers of the columns for the data grid.
-    columns: Var[List[Dict[str, Any]]]
+    columns: Var[List[DataEditorColumn]]
 
 
     # The data.
     # The data.
     data: Var[List[List[Any]]]
     data: Var[List[List[Any]]]
@@ -307,9 +324,17 @@ class DataEditor(NoSSRComponent):
                     "Cannot pass in both a pandas dataframe and columns to the data_editor component."
                     "Cannot pass in both a pandas dataframe and columns to the data_editor component."
                 )
                 )
             else:
             else:
-                props["columns"] = [
-                    format.format_data_editor_column(col) for col in columns
-                ]
+                if (
+                    not isinstance(columns, list)
+                    or isinstance(columns, list)
+                    and columns
+                    and not isinstance(columns[0], dict)
+                ):
+                    raise ValueError(
+                        "Data Editor columns field should be a list of dictionaries"
+                    )
+
+                props["columns"] = [DataEditorColumn(**c) for c in columns]
 
 
         if "theme" in props:
         if "theme" in props:
             theme = props.get("theme")
             theme = props.get("theme")
@@ -383,18 +408,3 @@ class DataEditor(NoSSRComponent):
 
 
 # except ImportError:
 # except ImportError:
 #     pass
 #     pass
-
-
-@serializer
-def serialize_dataeditortheme(theme: DataEditorTheme):
-    """The serializer for the data editor theme.
-
-    Args:
-        theme: The theme to serialize.
-
-    Returns:
-        The serialized theme.
-    """
-    return format.json_dumps(
-        {format.to_camel_case(k): v for k, v in theme.__dict__.items() if v is not None}
-    )

+ 88 - 34
reflex/components/datadisplay/dataeditor.pyi

@@ -16,41 +16,95 @@ from reflex.utils import console, format, imports, types
 from reflex.utils.serializers import serializer
 from reflex.utils.serializers import serializer
 from reflex.vars import ImportVar, Var, get_unique_variable_name
 from reflex.vars import ImportVar, Var, get_unique_variable_name
 
 
-class GridColumnIcons(Enum): ...
+LiteralDataEditorGridColumnIcons = Literal[
+    "headerRowID",
+    "headerCode",
+    "headerNumber",
+    "headerString",
+    "headerBoolean",
+    "headerAudioUri",
+    "headerVideoUri",
+    "headerEmoji",
+    "headerImage",
+    "headerUri",
+    "headerPhone",
+    "headerMarkdown",
+    "headerDate",
+    "headerTime",
+    "headerEmail",
+    "headerReference",
+    "headerIfThenElse",
+    "headerSingleValue",
+    "headerLookup",
+    "headerTextTemplate",
+    "headerMath",
+    "headerRollup",
+    "headerJoinStrings",
+    "headerSplitString",
+    "headerGeoDistance",
+    "headerArray",
+    "rowOwnerOverlay",
+    "protectedColumnOverlay",
+]
 
 
-class DataEditorTheme(Base):
-    accent_color: Optional[str]
-    accent_fg: Optional[str]
-    accent_light: Optional[str]
-    base_font_style: Optional[str]
-    bg_bubble: Optional[str]
-    bg_bubble_selected: Optional[str]
-    bg_cell: Optional[str]
-    bg_cell_medium: Optional[str]
-    bg_header: Optional[str]
-    bg_header_has_focus: Optional[str]
-    bg_header_hovered: Optional[str]
-    bg_icon_header: Optional[str]
-    bg_search_result: Optional[str]
-    border_color: Optional[str]
-    cell_horizontal_padding: Optional[int]
-    cell_vertical_padding: Optional[int]
-    drilldown_border: Optional[str]
-    editor_font_size: Optional[str]
-    fg_icon_header: Optional[str]
-    font_family: Optional[str]
-    header_bottom_border_color: Optional[str]
-    header_font_style: Optional[str]
-    horizontal_border_color: Optional[str]
-    line_height: Optional[int]
-    link_color: Optional[str]
-    text_bubble: Optional[str]
-    text_dark: Optional[str]
-    text_group_header: Optional[str]
-    text_header: Optional[str]
-    text_header_selected: Optional[str]
-    text_light: Optional[str]
-    text_medium: Optional[str]
+LiteralDataEditorColumnStyle = Literal["normal", "highlight"]
+
+class DataEditorProp(Base): ...
+
+class DataEditorTheme(DataEditorProp):
+    accent_color: Optional[str] = None
+    accent_fg: Optional[str] = None
+    accent_light: Optional[str] = None
+    base_font_style: Optional[str] = None
+    bg_bubble: Optional[str] = None
+    bg_bubble_selected: Optional[str] = None
+    bg_cell: Optional[str] = None
+    bg_cell_medium: Optional[str] = None
+    bg_header: Optional[str] = None
+    bg_header_has_focus: Optional[str] = None
+    bg_header_hovered: Optional[str] = None
+    bg_icon_header: Optional[str] = None
+    bg_search_result: Optional[str] = None
+    border_color: Optional[str] = None
+    cell_horizontal_padding: Optional[int] = None
+    cell_vertical_padding: Optional[int] = None
+    drilldown_border: Optional[str] = None
+    editor_font_size: Optional[str] = None
+    fg_icon_header: Optional[str] = None
+    font_family: Optional[str] = None
+    header_bottom_border_color: Optional[str] = None
+    header_font_style: Optional[str] = None
+    horizontal_border_color: Optional[str] = None
+    line_height: Optional[int] = None
+    link_color: Optional[str] = None
+    text_bubble: Optional[str] = None
+    text_dark: Optional[str] = None
+    text_group_header: Optional[str] = None
+    text_header: Optional[str] = None
+    text_header_selected: Optional[str] = None
+    text_light: Optional[str] = None
+    text_medium: Optional[str] = None
+
+class TrailingRowOptions(DataEditorProp):
+    hint: Optional[str]
+    add_icon: Optional[str]
+    target_column: Optional[int]
+    theme_override: Optional[DataEditorTheme]
+    disabled: Optional[bool]
+
+class DataEditorColumn(DataEditorProp):
+    title: str
+    id: Optional[str] = None
+    type_: str = "str"
+    group: Optional[str]
+    icon: Optional[LiteralDataEditorGridColumnIcons]
+    overlay_icon: Optional[LiteralDataEditorGridColumnIcons]
+    has_menu: Optional[bool]
+    grow: Optional[int]
+    style: Optional[LiteralDataEditorColumnStyle]
+    theme_override: Optional[DataEditorTheme]
+    trailing_row_options: Optional[TrailingRowOptions]
+    grow_offset: Optional[int]
 
 
 class DataEditor(NoSSRComponent):
 class DataEditor(NoSSRComponent):
     def get_event_triggers(self) -> Dict[str, Callable]: ...
     def get_event_triggers(self) -> Dict[str, Callable]: ...

+ 2 - 2
reflex/utils/serializers.py

@@ -153,7 +153,7 @@ def serialize_primitive(value: Union[bool, int, float, None]) -> str:
 
 
 
 
 @serializer
 @serializer
-def serialize_base(value: Base) -> str:
+def serialize_base(value: Base) -> dict:
     """Serialize a Base instance.
     """Serialize a Base instance.
 
 
     Args:
     Args:
@@ -162,7 +162,7 @@ def serialize_base(value: Base) -> str:
     Returns:
     Returns:
         The serialized Base.
         The serialized Base.
     """
     """
-    return value.json()
+    return value.dict()
 
 
 
 
 @serializer
 @serializer