migrate collectors + results tables to data_table::render (issue 0081-J)

- Include viz/data_table.h; add g_dt_collectors + g_dt_results State members
- ##collectors (3 cols): flat cells array -> data_table::render, Text renderers
- ##results (4 cols): flat cells array -> data_table::render, Badge on Kind col
  (function=#3b82f6, pipeline=#8b5cf6, component=#f59e0b)
- CMakeLists.txt: add fn_table_viz guard link block
- app.md: populate uses_functions with Wave-1 stack IDs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 16:53:58 +02:00
parent af0efc7315
commit 5c7871dc86
3 changed files with 85 additions and 46 deletions
+5
View File
@@ -31,6 +31,11 @@ target_include_directories(odr_console PRIVATE
target_link_libraries(odr_console PRIVATE SQLite::SQLite3)
# fn_table_viz: declarative table rendering stack (issue 0081-J).
if(TARGET fn_table_viz)
target_link_libraries(odr_console PRIVATE fn_table_viz)
endif()
if(WIN32)
set_target_properties(odr_console PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
+6 -1
View File
@@ -4,7 +4,12 @@ lang: cpp
domain: tools
description: "Lanzador GUI de funciones del registry para recolectar datos online. Panel de busqueda FTS5, jobs queue async (workers concurrentes), pipeline builder DAG, browser DuckDB, assertions/proposals. Aplica bucle reactivo de 5 pasos sobre operations.db propia."
tags: [imgui, data-collection, scraping, duckdb, jobs, cdp]
uses_functions: []
uses_functions:
- data_table_cpp_viz
- viz_render_cpp_viz
- compute_stage_cpp_core
- tql_to_sql_cpp_core
- llm_anthropic_cpp_core
uses_types: []
framework: "imgui"
entry_point: "main.cpp"
+74 -45
View File
@@ -10,6 +10,7 @@
#include "core/icons_tabler.h"
#include "core/tokens.h"
#include "core/logger.h"
#include "viz/data_table.h"
#include "data_registry.h"
#include "data_collectors.h"
@@ -40,6 +41,10 @@ static int g_coll_param_limit = 30;
static std::string g_last_run_summary; // texto status del ultimo run
static bool g_running = false;
// data_table::State persistentes (issue 0081-J: migration from inline BeginTable).
static data_table::State g_dt_collectors;
static data_table::State g_dt_results;
static void do_search() {
g_results.clear();
g_selected = -1;
@@ -111,29 +116,36 @@ static void draw_collectors() {
return;
}
if (ImGui::BeginTable("##collectors", 3,
ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
ImGuiTableFlags_Resizable)) {
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 180);
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 200);
ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableHeadersRow();
// Build flat cells array for data_table::render (row-major, 3 cols).
{
static std::vector<std::string> coll_cell_backing;
static std::vector<const char*> coll_cells;
for (int i = 0; i < (int)g_collectors.size(); ++i) {
const auto& c = g_collectors[i];
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
bool sel = (i == g_coll_selected);
if (ImGui::Selectable(c.id.c_str(), sel,
ImGuiSelectableFlags_SpanAllColumns)) {
g_coll_selected = i;
}
ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted(c.name.c_str());
ImGui::TableSetColumnIndex(2);
ImGui::TextUnformatted(c.description.c_str());
coll_cell_backing.clear();
coll_cell_backing.reserve(g_collectors.size() * 3);
for (const auto& c : g_collectors) {
coll_cell_backing.push_back(c.id);
coll_cell_backing.push_back(c.name);
coll_cell_backing.push_back(c.description);
}
ImGui::EndTable();
coll_cells.resize(coll_cell_backing.size());
for (size_t i = 0; i < coll_cell_backing.size(); ++i)
coll_cells[i] = coll_cell_backing[i].c_str();
data_table::TableInput tbl;
tbl.name = "collectors";
tbl.headers = {"ID", "Name", "Description"};
tbl.types = {data_table::ColumnType::String,
data_table::ColumnType::String,
data_table::ColumnType::String};
tbl.cells = coll_cells.empty() ? nullptr : coll_cells.data();
tbl.rows = (int)g_collectors.size();
tbl.cols = 3;
// All columns use default Text renderer — no column_specs needed.
ImGui::BeginChild("##collectors_dt", ImVec2(0, 200), false);
data_table::render("##dt_collectors", {tbl}, g_dt_collectors);
ImGui::EndChild();
}
if (g_coll_selected >= 0 &&
@@ -192,32 +204,49 @@ static void draw_launcher() {
ImGui::Separator();
if (ImGui::BeginTable("##results", 4,
ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
ImGuiTableFlags_ScrollY | ImGuiTableFlags_Resizable)) {
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Kind", ImGuiTableColumnFlags_WidthFixed, 80);
ImGui::TableSetupColumn("Domain", ImGuiTableColumnFlags_WidthFixed, 100);
ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableHeadersRow();
// Build flat cells array for data_table::render (row-major, 4 cols).
{
static std::vector<std::string> res_cell_backing;
static std::vector<const char*> res_cells;
for (int i = 0; i < (int)g_results.size(); ++i) {
const auto& r = g_results[i];
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
bool sel = (i == g_selected);
if (ImGui::Selectable(r.id.c_str(), sel,
ImGuiSelectableFlags_SpanAllColumns)) {
g_selected = i;
}
ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted(r.kind.c_str());
ImGui::TableSetColumnIndex(2);
ImGui::TextUnformatted(r.domain.c_str());
ImGui::TableSetColumnIndex(3);
ImGui::TextUnformatted(r.description.c_str());
res_cell_backing.clear();
res_cell_backing.reserve(g_results.size() * 4);
for (const auto& r : g_results) {
res_cell_backing.push_back(r.id);
res_cell_backing.push_back(r.kind);
res_cell_backing.push_back(r.domain);
res_cell_backing.push_back(r.description);
}
ImGui::EndTable();
res_cells.resize(res_cell_backing.size());
for (size_t i = 0; i < res_cell_backing.size(); ++i)
res_cells[i] = res_cell_backing[i].c_str();
// Column spec for Kind (col 1): Badge per kind value.
data_table::ColumnSpec cs_kind;
cs_kind.id = "kind";
cs_kind.renderer = data_table::CellRenderer::Badge;
cs_kind.badges = {
data_table::BadgeRule{"function", "#3b82f6", ""},
data_table::BadgeRule{"pipeline", "#8b5cf6", ""},
data_table::BadgeRule{"component", "#f59e0b", ""},
};
data_table::TableInput tbl;
tbl.name = "results";
tbl.headers = {"ID", "Kind", "Domain", "Description"};
tbl.types = {data_table::ColumnType::String,
data_table::ColumnType::String,
data_table::ColumnType::String,
data_table::ColumnType::String};
tbl.cells = res_cells.empty() ? nullptr : res_cells.data();
tbl.rows = (int)g_results.size();
tbl.cols = 4;
tbl.column_specs.resize(4); // default Text for all
tbl.column_specs[1] = cs_kind; // Badge for Kind
ImGui::BeginChild("##results_dt", ImVec2(0, -1), false);
data_table::render("##dt_results", {tbl}, g_dt_results);
ImGui::EndChild();
}
if (g_selected >= 0 && g_selected < (int)g_results.size()) {