feat: add view history navigation and drill-into-cell

Add view navigation history with back/forward stacks (bound to < and >).

Introduce CategoryKind enum to distinguish regular categories from
virtual ones (_Index, _Dim) that are synthesized at query time.

Add DrillIntoCell command that creates a drill view showing raw data
for an aggregated cell, expanding categories on Axis::None into Row
and Column axes while filtering by the cell's fixed coordinates.

Virtual categories default to Axis::None and are automatically added
to all views when the model is initialized.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
This commit is contained in:
Edward Langley
2026-04-05 10:57:28 -07:00
parent b2d633eb7d
commit 67041dd4a5
7 changed files with 253 additions and 16 deletions

View File

@ -41,15 +41,20 @@ impl View {
pub fn on_category_added(&mut self, cat_name: &str) {
if !self.category_axes.contains_key(cat_name) {
// Auto-assign: first → Row, second → Column, rest → Page
let rows = self.categories_on(Axis::Row).len();
let cols = self.categories_on(Axis::Column).len();
let axis = if rows == 0 {
Axis::Row
} else if cols == 0 {
Axis::Column
// Virtual categories (names starting with `_`) default to Axis::None.
// Regular categories auto-assign: first → Row, second → Column, rest → Page.
let axis = if cat_name.starts_with('_') {
Axis::None
} else {
Axis::Page
let rows = self.categories_on(Axis::Row).len();
let cols = self.categories_on(Axis::Column).len();
if rows == 0 {
Axis::Row
} else if cols == 0 {
Axis::Column
} else {
Axis::Page
}
};
self.category_axes.insert(cat_name.to_string(), axis);
}