feat(0036d): promote kind-aware (Group → clear group_id)
NodeGroups window kind=Group ahora expone un boton SmallButton(TI_ARROW_UP) por fila que saca la entidad del grupo (group_id = NULL) y dispara reload del grafo. kind=Table mantiene el comportamiento de issue 0011. - entity_ops: nueva op `entity_clear_group_id(db, id)` idempotente. Si la columna group_id no existe (BD pre-0035a) retorna true como no-op. Falla solo si la entidad no existe o SQLite revienta. - views.cpp: extra columna "promote" en kind=Group, tooltip header diferenciado por kind, boton conectado a app.want_clear_group_id_entity. - main.cpp: handler que ejecuta entity_clear_group_id, marca windows como dirty, llama reload_after_mutation y loguea `[node_groups] promoted X out of group`. - gx-cli: flag `node update --clear-group-id` (booleano) y exposicion MCP en inputSchema + MCP_DISPATCH defaults para que el agente Echo pueda promover via tool calls. - tests: 3 nuevos CLI (clear, idempotente, combinable con --name) y 4 MCP (defaults, schema, dispatch end-to-end, idempotente). WSL: 102 passed (95 base + 7). Windows: 91 passed, 11 skipped (84 base + 7). Refs: issues/0036d-promote-kind-aware.md
This commit is contained in:
@@ -2025,6 +2025,13 @@ void views_node_groups_window(AppState& app) {
|
||||
m.duckdb_path.c_str(), m.table_name.c_str(),
|
||||
(long long)w.total_rows);
|
||||
}
|
||||
// Issue 0036d: tooltip suave que explica el promote segun kind.
|
||||
if (is_group) {
|
||||
ImGui::TextDisabled("Promote: saca el nodo del grupo");
|
||||
} else {
|
||||
ImGui::TextDisabled(
|
||||
"Promote: convierte fila DuckDB en entidad del grafo");
|
||||
}
|
||||
if (!w.last_error.empty()) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
|
||||
"ERROR: %s", w.last_error.c_str());
|
||||
@@ -2033,10 +2040,11 @@ void views_node_groups_window(AppState& app) {
|
||||
|
||||
// Tabla — layout depende del kind:
|
||||
// Table: [id_column] + columns[] + [promoted] (col_count = N+2)
|
||||
// Group: columns[] (id, name, type_ref, status, updated_at)
|
||||
// (col_count = N)
|
||||
// Group: columns[] + [promote] (col_count = N+1)
|
||||
// (issue 0036d: ultima columna lleva un boton TI_ARROW_UP
|
||||
// para sacar la entidad del grupo.)
|
||||
const int col_count = is_group
|
||||
? (int)m.columns.size()
|
||||
? (int)m.columns.size() + 1
|
||||
: (int)m.columns.size() + 2;
|
||||
ImGuiTableFlags tflags =
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
||||
@@ -2053,6 +2061,9 @@ void views_node_groups_window(AppState& app) {
|
||||
: ImGuiTableColumnFlags_WidthStretch,
|
||||
is_id ? 160.0f : 0.0f);
|
||||
}
|
||||
// 0036d: columna extra para el boton Promote-out-of-group.
|
||||
ImGui::TableSetupColumn("promote",
|
||||
ImGuiTableColumnFlags_WidthFixed, 60.0f);
|
||||
} else {
|
||||
ImGui::TableSetupColumn(m.id_column.empty() ? "id" : m.id_column.c_str(),
|
||||
ImGuiTableColumnFlags_WidthFixed, 100.0f);
|
||||
@@ -2101,6 +2112,15 @@ void views_node_groups_window(AppState& app) {
|
||||
if (c < row.values.size())
|
||||
ImGui::TextUnformatted(row.values[c].c_str());
|
||||
}
|
||||
// 0036d: boton Promote-out-of-group en la ultima columna.
|
||||
ImGui::TableSetColumnIndex(col_count - 1);
|
||||
if (ImGui::SmallButton(TI_ARROW_UP "##promote_grp")) {
|
||||
app.want_clear_group_id_entity = true;
|
||||
app.clear_group_id_entity_id = row.id;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Promote out of group (move to canvas)");
|
||||
}
|
||||
} else {
|
||||
// kind=Table — comportamiento original (DuckDB-backed).
|
||||
bool is_promoted = !row.promoted_entity_id.empty();
|
||||
|
||||
Reference in New Issue
Block a user