diff --git a/src/components/datagrid_new/DataGridApp.py b/src/components/datagrid_new/DataGridApp.py index 47ef8c2..922d831 100644 --- a/src/components/datagrid_new/DataGridApp.py +++ b/src/components/datagrid_new/DataGridApp.py @@ -145,16 +145,10 @@ def post(session, _id: str, state: str, args: str = None): async def get(session, _id: str): logger.debug(f"Entering {Routes.YieldRow} with args {_id=}") instance = InstanceManager.get(session, _id) - return EventStream(instance.mk_lazy_body_content()) + return EventStream(instance.mk_body_content_sse()) - -async def number_generator2(): - for i in range(20): - yield sse_message(Div(i * 5 + 1)) - yield sse_message(Div(i * 5 + 2)) - yield sse_message(Div(i * 5 + 3)) - yield sse_message(Div(i * 5 + 4)) - yield sse_message(Div(i * 5 + 5)) - await asyncio.sleep(0.1) - - yield f"event: close\ndata: \n\n" +@rt(Routes.GetPage) +def get(session, _id: str, page_index: int): + logger.debug(f"Entering {Routes.GetPage} with args {_id=}, {page_index=}") + instance = InstanceManager.get(session, _id) + return instance.mk_body_content_page(page_index) \ No newline at end of file diff --git a/src/components/datagrid_new/assets/Datagrid.js b/src/components/datagrid_new/assets/Datagrid.js index 2df4c05..02b2aad 100644 --- a/src/components/datagrid_new/assets/Datagrid.js +++ b/src/components/datagrid_new/assets/Datagrid.js @@ -25,7 +25,7 @@ function bindScrollbars(datagridId) { const table = datagrid.querySelector(".dt2-table"); if (!verticalScrollbar || !verticalWrapper || !horizontalScrollbar || !horizontalWrapper || !body || !table) { - console.error("Essential scrollbar or content elements are missing in the datagrid."); + console.error("Essential scrollbars or content elements are missing in the datagrid."); return; } diff --git a/src/components/datagrid_new/components/DataGrid.py b/src/components/datagrid_new/components/DataGrid.py index 332e4fe..977ec12 100644 --- a/src/components/datagrid_new/components/DataGrid.py +++ b/src/components/datagrid_new/components/DataGrid.py @@ -62,6 +62,7 @@ class DataGrid(BaseComponent): self._settings: DataGridSettings = grid_settings or self._db.load_settings() self._df: DataFrame | None = self._db.load_dataframe() self._fast_access = self._init_fast_access(self._df) + self._total_rows = len(self._df) if self._df is not None else 0 # update boundaries if possible self.set_boundaries(boundaries) @@ -130,6 +131,7 @@ class DataGrid(BaseComponent): _get_column_type(self._df[make_safe_id(col_id)].dtype)) for col_index, col_id in enumerate(df.columns)] self._fast_access = self._init_fast_access(self._df) + self._total_rows = len(self._df) if self._df is not None else 0 if save_state: self._db.save_all(None, self._state, self._df) @@ -444,8 +446,9 @@ class DataGrid(BaseComponent): _mk_keyboard_management(), Div( self.mk_table_header(), - #self.mk_table_body(), - self.mk_table_body_lazy(), + # self.mk_table_body(), + # self.mk_table_body_sse(), + self.mk_table_body_page(), self.mk_table_footer(), cls="dt2-inner-table"), cls="dt2-table", @@ -486,7 +489,7 @@ class DataGrid(BaseComponent): id=f"th_{self._id}" ) - def mk_table_body_lazy(self): + def mk_table_body_sse(self): max_height = self._compute_body_max_height() @@ -501,6 +504,17 @@ class DataGrid(BaseComponent): id=f"tb_{self._id}", ) + def mk_table_body_page(self): + + max_height = self._compute_body_max_height() + + return Div( + *self.mk_body_content_page(0), + cls="dt2-body", + style=f"max-height:{max_height}px;", + id=f"tb_{self._id}", + ) + def mk_table_body(self): df = self._get_filtered_df() max_height = self._compute_body_max_height() @@ -529,7 +543,24 @@ class DataGrid(BaseComponent): id=f"tf_{self._id}" ) - async def mk_lazy_body_content(self): + def mk_body_content_page(self, page_index: int): + df = self._get_filtered_df() + start = page_index * DATAGRID_PAGE_SIZE + end = start + DATAGRID_PAGE_SIZE + if self._total_rows > end: + last_row = df.index[end - 1] + else: + last_row = None + + return [Div( + *[self.mk_body_cell(col_pos, row_index, col_def) for col_pos, col_def in enumerate(self._state.columns)], + cls="dt2-row", + data_row=f"{row_index}", + id=f"tr_{self._id}-{row_index}", + **self.commands.get_page(page_index + 1) if row_index == last_row else {} + ) for row_index in df.index[start:end]] + + async def mk_body_content_sse(self): df = self._get_filtered_df() for i, row_index in enumerate(df.index): yield sse_message(Div( diff --git a/src/components/datagrid_new/components/commands.py b/src/components/datagrid_new/components/commands.py index 1cf010c..55c0ef8 100644 --- a/src/components/datagrid_new/components/commands.py +++ b/src/components/datagrid_new/components/commands.py @@ -91,12 +91,20 @@ class DataGridCommandManager(BaseCommandManager): return { "hx-post": f"{ROUTE_ROOT}{Routes.OnClick}", "hx-target": f"#tsm_{self._id}", - "hx-trigger" : "click", + "hx-trigger": "click", "hx-swap": "outerHTML", "hx-vals": f'js:{{_id: "{self._id}", cell_id:getCellId(event), modifier:getClickModifier(event), boundaries: getCellBoundaries(event)}}', "hx-on::before-request": f'validateOnClickRequest("{self._id}", event)', } + def get_page(self, page_index=0): + return { + "hx-get": f"{ROUTE_ROOT}{Routes.GetPage}", + "hx-swap": "afterend", + "hx-vals": f'{{"_id": "{self._id}", "page": "{page_index}"}}', + "hx-trigger": "intersect once", + } + def _get_hide_show_columns_attrs(self, mode, col_defs: list, new_value, cls=""): str_col_names = ", ".join(f"'{col_def.title}'" for col_def in col_defs) tooltip_msg = f"{mode} column{'s' if len(col_defs) > 1 else ''} {str_col_names}" @@ -165,4 +173,4 @@ class FilterAllCommands(BaseCommandManager): "hx_vals": f'{{"_id": "{self._id}", "col_id":"{FILTER_INPUT_CID}"}}', "data_tooltip": "Reset filter", "cls": self.merge_class(cls, "mmt-tooltip"), - } \ No newline at end of file + } diff --git a/src/components/datagrid_new/constants.py b/src/components/datagrid_new/constants.py index ab406ff..e79b55d 100644 --- a/src/components/datagrid_new/constants.py +++ b/src/components/datagrid_new/constants.py @@ -17,6 +17,7 @@ CONTAINER_HEIGHT = "container_height" DATAGRID_STATE_FOOTER = "footer" +DATAGRID_PAGE_SIZE = 50 class Routes: Filter = "/filter" # request the filtering in the grid @@ -34,6 +35,7 @@ class Routes: ShowFooterMenu = "/show_footer_menu" UpdateState = "/update_state" YieldRow = "/yield-row" + GetPage = "/page" class ColumnType(Enum):