@@ -284,15 +284,20 @@ def perspective_panel(
284284 tables : list [str ] | None = None ,
285285 default_tables : list [str ] | None = None ,
286286 layouts : dict [str , str ] | None = None ,
287+ schemas : dict [str , dict [str , str ]] | None = None ,
287288 ) -> Any :
288289 """A Perspective workspace panel (the primary data view), bound to the theme + `view` state.
289290
290291 Data rides Perspective's own websocket at ``route``; the panel only carries the workspace
291292 layout/theme config. ``default_tables`` are the ones the generated layout opens, defaulting
292- to all of ``tables``. Add it to `Region.MAIN`.
293+ to all of ``tables``. ``schemas`` (table name -> column name -> type) lets the generated
294+ layout apply per-table defaults (timestamp sort, hidden id column). Add it to `Region.MAIN`.
293295 """
294296 tables = list (tables or [])
295- default_layout = self ._default_layout (list (default_tables ) if default_tables is not None else tables )
297+ default_layout = self ._default_layout (
298+ list (default_tables ) if default_tables is not None else tables ,
299+ schemas = schemas ,
300+ )
296301 layout_expr : Any = default_layout
297302 for name , layout_json in (layouts or {}).items ():
298303 try :
@@ -448,13 +453,23 @@ def _form_overrides(overrides: dict[str, dict[str, Any]], form_field_cls: Any) -
448453 return result
449454
450455 @staticmethod
451- def _default_layout (tables : list [str ]) -> dict [str , Any ]:
452- """A perspective workspace config that shows every table in its own datagrid tab."""
456+ def _default_layout (tables : list [str ], schemas : dict [str , dict [str , str ]] | None = None ) -> dict [str , Any ]:
457+ """A perspective workspace config that shows every table in its own datagrid tab.
458+
459+ With ``schemas`` (table name -> column name -> type), panels match the legacy UI's defaults:
460+ sorted by ``timestamp`` descending when the table has one, and the ``id`` column hidden.
461+ """
453462 panels : dict [str , Any ] = {}
454463 panel_ids : list [str ] = []
455464 for i , table in enumerate (tables ):
456465 panel_id = f"CSP_GATEWAY_{ i } "
457- panels [panel_id ] = {"table" : table , "plugin" : "Datagrid" , "title" : table }
466+ panel : dict [str , Any ] = {"table" : table , "plugin" : "Datagrid" , "title" : table }
467+ schema = (schemas or {}).get (table ) or {}
468+ if "timestamp" in schema :
469+ panel ["sort" ] = [["timestamp" , "desc" ]]
470+ if "id" in schema :
471+ panel ["columns" ] = [column for column in schema if column != "id" ]
472+ panels [panel_id ] = panel
458473 panel_ids .append (panel_id )
459474 return {
460475 "layout" : {"type" : "tab-layout" , "tabs" : panel_ids , "selected" : 0 },
@@ -773,7 +788,11 @@ def mount(self) -> None:
773788 layout = "installed" ,
774789 wire = wire ,
775790 routes = routes ,
776- store = {"dark" : False , ** self ._store_seeds },
791+ # `dark` matches the browser preference at boot (client-evaluated, like the legacy UI's
792+ # prefers-color-scheme detection), and a manual toggle is persisted per browser and takes
793+ # precedence on later loads.
794+ store = {"dark" : Js ('matchMedia("(prefers-color-scheme: dark)").matches' ), ** self ._store_seeds },
795+ persist = {"dark" : "csp-gateway:dark" },
777796 # Emitted after the component packages' own CSS, so a custom stylesheet can override the
778797 # shell palette, and before `head`, which carries only document resets.
779798 stylesheets = custom_css ,
0 commit comments