# dataview — Iceberg / warehouse browsing — design
> **Class:** `design` · **Function axis:** `f0` (the whole) + `f1` snapshot
> time-travel (`facett-icebergview`) · `f2` the multi-pane warehouse wall
> (`facett-warehousedeck`) · `f3` the single-table picker + auto chart
> (`facett-table::warehouse`).
> Strict: this file states only the shape as built — every claim points at a real
> `file:line` in the named crate's `src/`. The workflow is
> [`dataview-guide.md`](dataview-guide.md).
## f0 — the whole
"dataview" is not one crate; it's three composable facett components that browse
lakehouse/warehouse data at three different granularities, each an independent
`Facet` a host can drop into a deck on its own:
| component | crate | shows |
|---|---|---|
| `IcebergView` | `facett-icebergview` | **one Iceberg table's history** — a snapshot picker over a paged row grid |
| `WarehouseDeck` | `facett-warehousedeck` | **many tables/graphs at once** — a wall of panes (3D graphs, grids, charts) |
| `WarehouseTableView` | `facett-table::warehouse` | **one warehouse, many tables** — a left-hand table picker + a striped grid or auto bar-chart |
All three take **data, not a catalog handle**: none of them depend on
`iceberg`/`skade`/`nornir` (`facett-icebergview/src/lib.rs:1-7`,
`facett-warehousedeck/src/lib.rs:14-18`,
`facett-table/src/warehouse.rs:6-10`). A host (korp / nornir-viz) reads its
Iceberg/warehouse source and hands in already-materialized Arrow batches or
`PreviewTable`s; each component implements `facett_core::Elm`/`Facet` the same
way as `facett-grid` (a serializable Model, a `Msg` enum, a pure `view`), so every
one drops into a `FacetDeck` and is robot-testable through
`facett_core::harness`.
`IcebergView`'s row grid is built from `facett_table::Table`
(`facett-icebergview/src/lib.rs:54`, `:166`), not `facett-grid` — see
[`grid-design.md`](grid-design.md) for the boundary between the two table
components.
## f1 — snapshot time-travel (`facett-icebergview`)
`IcebergView` (`facett-icebergview/src/lib.rs:153-167`) pairs, per Iceberg
snapshot, a `SnapshotMeta { id, timestamp_ms, rows }`
(`lib.rs:62-69`) with its materialized `Vec<RecordBatch>`
(`Snapshot`, `lib.rs:82-95`). `IcebergState` (`lib.rs:138-150`) is the observable
Model: the table name, every snapshot's meta **newest-first**, the selected
snapshot's **id** (FC-5 — a stable id, never the picker's volatile index), and the
paging window (`page`/`page_size`). `IcebergView::new` and `set_snapshots`
(`lib.rs:173-190`, `:232-239`) call `split_sorted`
(`lib.rs:194-205`), which sorts by `timestamp_ms` descending (ties broken by the
larger id) and selects the newest by default.
`Msg` (`lib.rs:107-120`): `SelectSnapshot(id)` (time-travel by stable id, resets to
page 0), `SetPage`/`NextPage`/`PrevPage`/`SetPageSize`. `update`
(`lib.rs:312-343`) is the single mutation path; unknown ids and out-of-range pages
are clamped, never panic. Every transition calls `rebuild_grid`
(`lib.rs:345-349`), which calls `build_grid` (`lib.rs:355-391`): it slices the
selected snapshot's batches to the `[page*page_size, …)` window — walking
batch-by-batch so a page can span a batch boundary (`lib.rs:370-389`) — and maps
each windowed batch to string rows via `facett_arrow::table_from_batch`
(`lib.rs:380`), filling a `facett_table::Table`. `Effect` is uninhabited
(`lib.rs:129`): every frame is handed in already materialized, so time-travel only
re-slices in-memory data — no I/O happens inside this crate.
`view` (`lib.rs:400-494`) paints a `ComboBox` snapshot picker (newest marked `▲`,
each entry showing `#id · t=…ms · N rows`, `lib.rs:421-442`), a pager
(`lib.rs:448-460`), and renders the current page by delegating to the inner
`Table::ui` (`lib.rs:468`). `state_json` (`lib.rs:537-554`, form-3 macro
invocation `lib.rs:536`) publishes `table`, `snapshots` (newest-first), `current`,
`total_rows`, `page`, `page_size`, `page_count`, `columns`, `visible_rows`.
`copy_payload` (`lib.rs:498-507`) delegates to the inner grid's own `CopySource`,
so Ctrl-C copies the visible page as a TSV rectangle.
## f2 — the multi-pane warehouse wall (`facett-warehousedeck`)
`WarehouseDeck` (`facett-warehousedeck/src/lib.rs:361-367`) composes an arbitrary
number of panes — `Graph3D` · `Grid` · `PlotView` · `Table` — inside a
`facett_core::FacetDeck` held in a `RefCell` (`lib.rs:366`, not serializable, so it
lives outside the Model). `ViewKind` (`lib.rs:70-79`) names the four pane shapes;
`PaneData` (`lib.rs:130-140`) is what a host hands per pane (`Graph(GraphSpec)` /
`Grid(Vec<RecordBatch>)` / `Chart(ChartSpec)` / `Blob { text }`).
`WarehouseRegistry` (`lib.rs:157-250`) maps a **table name** to the `ViewKind` it
should render as; `WarehouseRegistry::default_nordisk` (`lib.rs:195-249`) is the
concrete mapping for the nornir/modgunn warehouse (e.g. `call_edges` →
`Graph3D`, `bench_runs` → `Grid`, `release_events` → `Chart`).
`WarehouseDeck::add` (`lib.rs:409-450`) builds the matching widget from
`PaneData` — a `Graph3D::new(...)` for graphs (`lib.rs:418-423`), a `Grid` via
`build_grid` (concatenating batches with `arrow_select::concat::concat_batches`,
`lib.rs:684-691`) for grids, a `PlotView::line`/`bars` for charts
(`lib.rs:431-434`), a one-column `Table` for blobs (`lib.rs:436-445`) — records a
`PaneInfo` (`lib.rs:274-288`, the stable-id `title` + per-kind counts), and pushes
the boxed `Facet` into the deck.
`WarehouseModel` (`lib.rs:296-310`) is the observable Model: `title`, `layout`
(`DeckLayout::Wall`/`Focus`, `lib.rs:253-269`), `cols` (wall column count, clamped
`1..=6`), `panes: Vec<PaneInfo>`, and `selected` (the focused pane's **stable id**
— its `PaneInfo::title`, FC-5). `Msg` (`lib.rs:317-341`) covers layout switching,
the column stepper (`IncCols`/`DecCols`/`SetCols`), pane selection/drill-in
(`SelectPane`/`DrillInto`, both keyed on the stable title), `BackToWall`, and
`FocusNext`/`FocusPrev` (wrapping cycle, `step_focus`, `lib.rs:551-564`). `update`
(`lib.rs:524-547`) is the sole mutation path; `DrillInto` both selects a pane and
switches to `Focus` layout in one message (`lib.rs:536-541`).
`view` (`lib.rs:635-679`) renders the toolbar (`lib.rs:569-627`, layout toggle +
column stepper + a pane navigator) then, in `Wall` layout, calls
`FacetDeck::wall_ui(ui, cols)` so every pane paints simultaneously
(`lib.rs:641`); in `Focus` layout it syncs the child deck's active tab to the
Model's `selected` before drawing, then reconciles a live tab click back into a
`Msg::SelectPane` so live and headless stay identical (`lib.rs:645-658`).
`state_json` (`lib.rs:722-747`, form-3) folds in `pane_count`,
`graph3d_count`/`grid_count`/`chart_count`/`blob_count`, the `panes` array, and the
composed child deck's own `state_json` under the `deck` key (whose `trace.ran`
lists `deck.wall:<title>` for every pane that actually drew).
## f3 — the single-table picker + auto chart (`facett-table::warehouse`)
`WarehouseTableView` (`facett-table/src/warehouse.rs:125-134`) is a left-panel
table picker over a `Vec<(String, PreviewTable)>`; `PreviewTable`
(`warehouse.rs:35-43`) is just named `columns` + stringified `rows`. Its
`col_is_numeric` (`warehouse.rs:48-61`) — at least half of a column's non-empty
cells parse as `f64`, and at least one does — decides which columns
`numeric_columns` (`warehouse.rs:64-66`) offers as chartable.
`WarehouseState` (`warehouse.rs:76-89`) is the observable Model: the loaded
tables in picker order, the **selected table's name** (FC-5, not the picker's
volatile index), and the chart controls (`chart: bool`, `chart_val`,
`chart_label` column indices). `Msg` (`warehouse.rs:104-115`): `Select(name)`,
`SetChart(bool)`, `SetChartValue`/`SetChartLabel`. `update`
(`warehouse.rs:204-235`): selecting a table clears stale chart-column choices
(`warehouse.rs:206-212`); turning chart mode on defaults the value column to the
first numeric column and the label column to the first non-numeric column
(`warehouse.rs:216-228`).
`view` (`warehouse.rs:297-431`) paints an `egui::Panel::left` table list
(`warehouse.rs:300-313`) and a central panel that, for the selected table, shows
either the striped grid or — when the "📊 chart" checkbox is on and the table has
a numeric column — a hand-painted horizontal bar chart with value/label `ComboBox`
pickers (`warehouse.rs:341-…`). `state_json_impl` (`warehouse.rs:436-454`, wired
in via form-3 `custom_state_json` at `warehouse.rs:484`) publishes `title`,
`tables` (names), `table_count`, `selected`, `chart` (`on`/`value_col`/
`label_col`), and `preview` (`loaded`, `columns`, `rows` as a count,
`numeric_columns`) for the selected table.