feat(0036b): NodeGroups admite kind=Group + loader entities
NodeGroupsWindowState gana un discriminador `kind` (Table | Group) y
un flag `focus_request` (lo consumira 0036c). Por defecto Table, asi
que el flujo historico (DuckDB rows tras expand de un nodo Table) no
cambia.
kind=Group lee directamente operations.db consultando
`entities WHERE group_id = container_id` con columnas fijas
(id, name, type_ref, status, updated_at) ordenadas por updated_at DESC.
Los nuevos loaders viven en node_groups.cpp:
- node_groups_count_for_group -> SELECT count(*) ...
- node_groups_page_for_group -> SELECT id,name,type_ref,status,
updated_at ... LIMIT ? OFFSET ?
Para columnas, opcion (A) del issue: pre-popular meta.columns con la
lista fija al abrir kind=Group, asi el render se mantiene generico.
NodeGroupsRow.values guarda los 5 campos en ese orden y row.id es la
key natural (= entity_id de la fila — al ser ya entidad, no hace falta
promocionarla).
Render en views.cpp ramifica por kind:
- Table: layout original [id_col + columns + promoted] con doble
click -> promote/focus.
- Group: layout [columns fijas] sin promoted. Doble click sobre la
fila ya pone want_focus_entity = id (los flujos posteriores 0036c-e
afinan UX). Right click ofrece "Focus in Inspector".
main.cpp dispatcha por kind al refrescar paginas y, al cerrar via X,
solo llama a node_groups_set_expanded para kind=Table (Group no usa
ese flag).
views_node_groups_windows_sync se hace kind-aware: solo reconcilia
entries kind=Table contra el set de Tables expandidas; no toca las
entries kind=Group (las gestiona views_node_groups_open).
Nueva API publica:
views_node_groups_open(app, container_id, kind, ops_db)
Crea o reusa la entry, setea focus_request=true y para kind=Group
pre-popula meta.columns + intenta leer `name` del Group para el
titulo. Sin caller todavia — la consume 0036c.
Tests:
- tests/test_node_groups_loader.py (6 tests) verifica el contrato
SQL via gx-cli. Nuevo subcomando `gx-cli group page <id>` espejea
el loader C++ exactamente (mismo SQL); tambien expuesto como tool
MCP `group_page` para que Echo pueda inspeccionar Groups.
Resultado:
- WSL: 89 -> 95 passed
- Windows: 78+11 -> 84+11 passed
- Build C++ Windows limpio, sin warnings nuevos.
- Regresion kind=Table: comportamiento identico (mismo render,
mismo loader DuckDB).
Refs: issues/0036b-kind-discriminator-and-group-loader.md
This commit is contained in:
@@ -15,6 +15,11 @@ struct GraphViewportState;
|
||||
|
||||
namespace ge {
|
||||
|
||||
// Discriminador de la NodeGroups window (issue 0036b). Una window puede
|
||||
// estar respaldada por una tabla DuckDB (kind=Table) o por una agrupacion
|
||||
// de entidades en operations.db via `entities.group_id` (kind=Group).
|
||||
enum class NodeGroupsKind { Table, Group };
|
||||
|
||||
// Estado compartido entre las vistas y el bucle render. Pasado por puntero
|
||||
// desde main.cpp.
|
||||
struct AppState {
|
||||
@@ -160,19 +165,26 @@ struct AppState {
|
||||
// Refrescado tras load_input y tras mutaciones que afecten a Tables.
|
||||
std::unordered_map<uint64_t, int64_t> node_groups_counts;
|
||||
|
||||
// ---- NodeGroups window (issue 0011, renombrado en 0036a) --------------
|
||||
// Estado runtime por ventana de NodeGroups (un Table-typed expandido).
|
||||
// Una entrada por entity_id de Table que el usuario haya expandido. La
|
||||
// ventana se cierra cuando set_expanded(false) — ya sea desde context
|
||||
// menu o cerrando la ImGui window (que pone el flag a false
|
||||
// automaticamente).
|
||||
// ---- NodeGroups window (issue 0011, renombrado en 0036a, kind en 0036b) -
|
||||
// Estado runtime por ventana de NodeGroups. Hay dos kinds (issue 0036b):
|
||||
// - Table: respaldada por DuckDB (el comportamiento original — un nodo
|
||||
// `Table` del grafo que apunta a un .duckdb + table_name).
|
||||
// - Group: respaldada por la propia operations.db. Lista las entidades
|
||||
// hijas (`entities.group_id = container_id`) con columnas fijas
|
||||
// id/name/type_ref/status/updated_at.
|
||||
//
|
||||
// Una entrada por container_id (entity_id del nodo contenedor — Table o
|
||||
// Group). La ventana se cierra al pulsar la X de ImGui o, en kind=Table,
|
||||
// al hacer set_expanded(false) desde el menu contextual.
|
||||
struct NodeGroupsWindowState {
|
||||
NodeGroupsKind kind = NodeGroupsKind::Table; // default compat 0036a
|
||||
NodeGroupsMeta meta; // refrescada cada vez que entity cambia
|
||||
int64_t total_rows = 0;
|
||||
int64_t offset = 0;
|
||||
std::vector<NodeGroupsRow> page;
|
||||
bool page_dirty = true;
|
||||
bool open = true; // bound a ImGui::Begin
|
||||
bool focus_request = false; // 0036c: pedir SetWindowFocus
|
||||
std::string last_error; // ultimo error de query (vacio = OK)
|
||||
};
|
||||
std::unordered_map<std::string, NodeGroupsWindowState> node_groups_windows;
|
||||
@@ -356,6 +368,25 @@ bool views_import_dataset_modal(AppState& app);
|
||||
// entradas para nuevos expanded y borra las que ya no aplican.
|
||||
void views_node_groups_windows_sync(AppState& app, const char* ops_db);
|
||||
|
||||
// Crea o reusa una entrada en `app.node_groups_windows[container_id]` y la
|
||||
// marca con el `kind` indicado. Setea `focus_request = true` para que el
|
||||
// render pueda llamar a ImGui::SetWindowFocus (lo consume 0036c). Si la
|
||||
// entry ya existe se respeta su kind anterior y solo se setea
|
||||
// focus_request — no recarga ni resetea offset. Si es nueva, llama a
|
||||
// `node_groups_load_metadata` para popular `meta` (en kind=Group eso pre-
|
||||
// puebla las columnas fijas; en kind=Table lee la metadata del Table-typed
|
||||
// node de operations.db).
|
||||
//
|
||||
// `ops_db` es el path de operations.db. Si esta vacio, no se carga
|
||||
// metadata pero la entry se crea de todos modos (caller puede rellenar
|
||||
// despues). Devuelve puntero a la entry — nunca nullptr salvo
|
||||
// container_id vacio.
|
||||
AppState::NodeGroupsWindowState*
|
||||
views_node_groups_open(AppState& app,
|
||||
const std::string& container_id,
|
||||
NodeGroupsKind kind,
|
||||
const char* ops_db);
|
||||
|
||||
// ---- Table node overlay (issue 0010) ------------------------------------
|
||||
|
||||
// Dibuja un overlay rectangulo redondeado sobre cada nodo `Table` del grafo
|
||||
|
||||
Reference in New Issue
Block a user