7eb7b3d0c8
Snapshot de WIP acumulado de sesiones previas antes de merge wave 1 del flow 0008 (kanban_cpp + agent_runner_api + DoD schema). Incluye: - dev/flows/0008-kanban-cpp-and-agent-workflows.md - dev/issues/0112-0119*.md (7 sub-issues) - WIP previo en cmd/fn/doctor.go, registry/*, modules/, cpp/, etc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
564 lines
25 KiB
Markdown
564 lines
25 KiB
Markdown
# data_table integration audit — 8 apps
|
|
|
|
Canonical pattern (from modules/data_table/data_table.md):
|
|
|
|
```cpp
|
|
static data_table::State g_table_state; // PERSISTENT entre frames
|
|
data_table::TableInput tbl;
|
|
tbl.name = "my_table";
|
|
tbl.headers = {"col1","col2"};
|
|
tbl.types = {data_table::ColumnType::String, data_table::ColumnType::Int};
|
|
tbl.cells = cells_ptr; // row-major flat array
|
|
tbl.rows = N;
|
|
tbl.cols = 2;
|
|
|
|
std::vector<data_table::TableEvent> events;
|
|
ImGui::BeginChild("##tbl_host");
|
|
data_table::render("##my_tbl_id", { tbl }, g_table_state, &events);
|
|
ImGui::EndChild();
|
|
|
|
for (const auto& ev : events) {
|
|
if (ev.kind == data_table::TableEventKind::RowDoubleClick) { ... }
|
|
}
|
|
```
|
|
|
|
Anti-patterns the audit flags:
|
|
|
|
- inline_begintable [warn]: app calls ImGui::BeginTable directly instead of data_table::render. Migrar la tabla a data_table::render con un TableInput.
|
|
- state_not_persistent [error]: data_table::State declarado dentro de funcion sin `static`. Mover a `static` local o miembro global; sino se pierde drill/sort/filtros cada frame.
|
|
- no_child_host [warn]: data_table::render se llama sin BeginChild/Begin en las ~30 lineas previas. Envolver con `ImGui::BeginChild("##host");` … `ImGui::EndChild();`.
|
|
- no_event_sink [info]: app declara uses_modules data_table_cpp pero no captura events_out. Pasar `&events` para reaccionar a double-click / right-click / ButtonClick.
|
|
- cmake_missing_link [error]: app.md declara `uses_modules: [data_table_cpp]` pero CMakeLists.txt no enlaza `fn_module_data_table`.
|
|
|
|
---
|
|
|
|
|
|
## app_gestion [warn] (apps/app_gestion)
|
|
|
|
### inline_begintable [warn] apps/app_gestion/main.cpp:722
|
|
snippet: if (ImGui::BeginTable("##linked_tbl", 4,
|
|
```
|
|
717 ? "?" : a->linked_build.c_str());
|
|
718 if (a->linked_modules.empty()) {
|
|
719 ImGui::TextDisabled("(sin info — la app no se ha buildeado todavia,"
|
|
720 " o no genera _modules_generated.cpp)");
|
|
721 } else {
|
|
>> 722 if (ImGui::BeginTable("##linked_tbl", 4,
|
|
723 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
|
724 ImGui::TableSetupColumn("module");
|
|
725 ImGui::TableSetupColumn("linked");
|
|
726 ImGui::TableSetupColumn("registry");
|
|
727 ImGui::TableSetupColumn("status");
|
|
```
|
|
|
|
|
|
## dag_engine_ui [warn] (apps/dag_engine_ui)
|
|
|
|
### inline_begintable [warn] apps/dag_engine_ui/tabs.cpp:382
|
|
snippet: if (ImGui::BeginTable("##dt_run_steps", 6, steps_flags)) {
|
|
```
|
|
377 ImGui::BeginChild("##run_steps_wrap", ImVec2(-1, ImGui::GetContentRegionAvail().y * 0.5f));
|
|
378 const ImGuiTableFlags steps_flags =
|
|
379 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
|
380 ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp |
|
|
381 ImGuiTableFlags_ScrollY;
|
|
>> 382 if (ImGui::BeginTable("##dt_run_steps", 6, steps_flags)) {
|
|
383 ImGui::TableSetupScrollFreeze(0, 1);
|
|
384 ImGui::TableSetupColumn("Step", ImGuiTableColumnFlags_WidthStretch, 1.6f);
|
|
385 ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 2.2f);
|
|
386 ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthStretch, 0.8f);
|
|
387 ImGui::TableSetupColumn("Exit", ImGuiTableColumnFlags_WidthStretch, 0.4f);
|
|
```
|
|
|
|
### inline_begintable [warn] apps/dag_engine_ui/tabs.cpp:731
|
|
snippet: if (ImGui::BeginTable("##health_kpis", 4,
|
|
```
|
|
726 "Trigger a DAG to populate health metrics.");
|
|
727 ImGui::End();
|
|
728 return;
|
|
729 }
|
|
730
|
|
>> 731 if (ImGui::BeginTable("##health_kpis", 4,
|
|
732 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchSame))
|
|
733 {
|
|
734 ImGui::TableNextRow();
|
|
735
|
|
736 ImGui::TableNextColumn();
|
|
```
|
|
|
|
|
|
## data_factory [warn] (apps/data_factory)
|
|
|
|
### no_child_host [warn] apps/data_factory/tabs.cpp:291
|
|
snippet: data_table::render(dt_id, {tbl}, *st, &events);
|
|
```
|
|
286 }
|
|
287 cells_to_ptrs(*backing, *ptrs);
|
|
288 tbl.cells = ptrs->data();
|
|
289
|
|
290 std::vector<data_table::TableEvent> events;
|
|
>> 291 data_table::render(dt_id, {tbl}, *st, &events);
|
|
292
|
|
293 for (auto& ev : events) {
|
|
294 if (ev.kind == data_table::TableEventKind::RowDoubleClick &&
|
|
295 ev.row >= 0 && ev.row < static_cast<int>(filtered.size()))
|
|
296 {
|
|
```
|
|
|
|
### no_child_host [warn] apps/data_factory/tabs.cpp:454
|
|
snippet: data_table::render("##dt_tables", {tbl}, g_st_tables, &tbl_events);
|
|
```
|
|
449 }
|
|
450 cells_to_ptrs(g_back_tables, g_ptrs_tables);
|
|
451 tbl.cells = g_ptrs_tables.data();
|
|
452
|
|
453 std::vector<data_table::TableEvent> tbl_events;
|
|
>> 454 data_table::render("##dt_tables", {tbl}, g_st_tables, &tbl_events);
|
|
455 for (auto& ev : tbl_events) {
|
|
456 if (ev.kind == data_table::TableEventKind::RowDoubleClick &&
|
|
457 ev.row >= 0 && ev.row < static_cast<int>(tables.size()))
|
|
458 {
|
|
459 const auto& t = tables[ev.row];
|
|
```
|
|
|
|
### no_child_host [warn] apps/data_factory/tabs.cpp:531
|
|
snippet: data_table::render("##dt_databases", {tbl}, g_st_databases);
|
|
```
|
|
526 g_back_databases.push_back(d.last_seen_at.empty() ? "-" : d.last_seen_at);
|
|
527 }
|
|
528 cells_to_ptrs(g_back_databases, g_ptrs_databases);
|
|
529 tbl.cells = g_ptrs_databases.data();
|
|
530
|
|
>> 531 data_table::render("##dt_databases", {tbl}, g_st_databases);
|
|
532 }
|
|
533 ImGui::End();
|
|
534 }
|
|
535
|
|
536 // ---------------------------------------------------------------------------
|
|
```
|
|
|
|
### no_child_host [warn] apps/data_factory/tabs.cpp:619
|
|
snippet: data_table::render("##dt_kpis", {tbl}, g_st_kpis);
|
|
```
|
|
614 std::snprintf(buf, sizeof(buf), "%lld KB", kb_24h); g_back_kpis.push_back(buf);
|
|
615
|
|
616 cells_to_ptrs(g_back_kpis, g_ptrs_kpis);
|
|
617 tbl.cells = g_ptrs_kpis.data();
|
|
618
|
|
>> 619 data_table::render("##dt_kpis", {tbl}, g_st_kpis);
|
|
620 }
|
|
621
|
|
622 ImGui::Separator();
|
|
623 ImGui::TextDisabled("Computed client-side from %zu runs in cache.", runs_all.size());
|
|
624 ImGui::End();
|
|
```
|
|
|
|
### no_child_host [warn] apps/data_factory/tabs.cpp:883
|
|
snippet: data_table::render("##dt_node_runs", {tbl}, g_st_node_runs, &events);
|
|
```
|
|
878 }
|
|
879 cells_to_ptrs(g_back_node_runs, g_ptrs_node_runs);
|
|
880 tbl.cells = g_ptrs_node_runs.data();
|
|
881
|
|
882 std::vector<data_table::TableEvent> events;
|
|
>> 883 data_table::render("##dt_node_runs", {tbl}, g_st_node_runs, &events);
|
|
884
|
|
885 for (auto& ev : events) {
|
|
886 if (ev.kind == data_table::TableEventKind::RowDoubleClick &&
|
|
887 ev.row >= 0 && ev.row < static_cast<int>(shown_runs.size()))
|
|
888 {
|
|
```
|
|
|
|
### no_child_host [warn] apps/data_factory/tabs.cpp:992
|
|
snippet: data_table::render("##dt_preview", {tbl}, g_st_preview, nullptr, true);
|
|
```
|
|
987 }
|
|
988 }
|
|
989 cells_to_ptrs(g_back_preview, g_ptrs_preview);
|
|
990 tbl.cells = g_ptrs_preview.data();
|
|
991
|
|
>> 992 data_table::render("##dt_preview", {tbl}, g_st_preview, nullptr, true);
|
|
993 }
|
|
994
|
|
995 // Pagination controls.
|
|
996 ImGui::Separator();
|
|
997 {
|
|
```
|
|
|
|
|
|
## graph_explorer [warn] (projects/osint_graph/apps/graph_explorer)
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/extract_panel.cpp:981
|
|
snippet: if (ImGui::BeginTable("##ents", 5,
|
|
```
|
|
976 }
|
|
977
|
|
978 // Tabla de entidades.
|
|
979 if (!res->entities.empty() &&
|
|
980 ImGui::CollapsingHeader("Entities", ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
>> 981 if (ImGui::BeginTable("##ents", 5,
|
|
982 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
|
983 ImGuiTableFlags_ScrollY,
|
|
984 ImVec2(0.0f, 200.0f))) {
|
|
985 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 28.0f);
|
|
986 ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 120.0f);
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/extract_panel.cpp:1027
|
|
snippet: if (ImGui::BeginTable("##rels", 5,
|
|
```
|
|
1022 }
|
|
1023
|
|
1024 // Tabla de relaciones.
|
|
1025 if (!res->relations.empty() &&
|
|
1026 ImGui::CollapsingHeader("Relations", ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
>> 1027 if (ImGui::BeginTable("##rels", 5,
|
|
1028 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
|
1029 ImGuiTableFlags_ScrollY,
|
|
1030 ImVec2(0.0f, 160.0f))) {
|
|
1031 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 28.0f);
|
|
1032 ImGui::TableSetupColumn("From", ImGuiTableColumnFlags_WidthFixed, 100.0f);
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/main.cpp:1127
|
|
snippet: if (ImGui::BeginTable("##enr_params", 2,
|
|
```
|
|
1122 // con mas params de los que llenamos al abrir la ventana.
|
|
1123 if (g_app.enr_modal_param_bufs.size() < spec->params.size()) {
|
|
1124 g_app.enr_modal_param_bufs.resize(spec->params.size());
|
|
1125 }
|
|
1126
|
|
>> 1127 if (ImGui::BeginTable("##enr_params", 2,
|
|
1128 ImGuiTableFlags_SizingStretchProp |
|
|
1129 ImGuiTableFlags_NoBordersInBody)) {
|
|
1130 ImGui::TableSetupColumn("name", ImGuiTableColumnFlags_WidthFixed, 110.0f);
|
|
1131 ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
|
1132
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/views.cpp:885
|
|
snippet: if (ImGui::BeginTable("##insp_id", 2,
|
|
```
|
|
880 // Layout label-izquierda / input-derecha via 2-col table. El label
|
|
881 // alineado al frame del input y el input estirado al ancho restante.
|
|
882 ImGui::TextUnformatted("Identity");
|
|
883 ImGui::Separator();
|
|
884
|
|
>> 885 if (ImGui::BeginTable("##insp_id", 2,
|
|
886 ImGuiTableFlags_SizingStretchProp |
|
|
887 ImGuiTableFlags_NoBordersInBody)) {
|
|
888 ImGui::TableSetupColumn("k", ImGuiTableColumnFlags_WidthFixed, 90.0f);
|
|
889 ImGui::TableSetupColumn("v", ImGuiTableColumnFlags_WidthStretch);
|
|
890
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/views.cpp:958
|
|
snippet: if (ImGui::BeginTable("##insp_fields", 2,
|
|
```
|
|
953 ImGui::TextUnformatted("Fields");
|
|
954 ImGui::Separator();
|
|
955 const EntitySpec* spec = find_entity_spec(app.parsed_types,
|
|
956 app.insp_type_buf);
|
|
957
|
|
>> 958 if (ImGui::BeginTable("##insp_fields", 2,
|
|
959 ImGuiTableFlags_SizingStretchProp |
|
|
960 ImGuiTableFlags_NoBordersInBody)) {
|
|
961 ImGui::TableSetupColumn("k", ImGuiTableColumnFlags_WidthFixed, 90.0f);
|
|
962 ImGui::TableSetupColumn("v", ImGuiTableColumnFlags_WidthStretch);
|
|
963
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/views.cpp:1546
|
|
snippet: // OLD: ImGui::BeginTable("##tablev", 6, ...) with manual sort/filter/clipper.
|
|
```
|
|
1541 }
|
|
1542
|
|
1543 // ----------------------------------------------------------------------------
|
|
1544 // Table view (issue 0004) — migrated to data_table::render (issue 0081-J).
|
|
1545 //
|
|
>> 1546 // OLD: ImGui::BeginTable("##tablev", 6, ...) with manual sort/filter/clipper.
|
|
1547 // Per-column filter popups + chips toolbar + TabBar per type.
|
|
1548 // Click on row selected node in graph viewport.
|
|
1549 //
|
|
1550 // NEW: data_table::render() provides sort + filter + viz + stages.
|
|
1551 // AppState::table_dt_state persists the UI state between frames.
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/views.cpp:1854
|
|
snippet: if (col_count > 0 && ImGui::BeginTable("##te_rows", col_count, tflags,
|
|
```
|
|
1849 : (int)m.columns.size() + 2;
|
|
1850 ImGuiTableFlags tflags =
|
|
1851 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
|
1852 ImGuiTableFlags_ScrollY | ImGuiTableFlags_Resizable |
|
|
1853 ImGuiTableFlags_SizingStretchProp;
|
|
>> 1854 if (col_count > 0 && ImGui::BeginTable("##te_rows", col_count, tflags,
|
|
1855 ImVec2(0, -ImGui::GetFrameHeightWithSpacing()))) {
|
|
1856 ImGui::TableSetupScrollFreeze(0, 1);
|
|
1857 if (is_group) {
|
|
1858 for (size_t i = 0; i < m.columns.size(); ++i) {
|
|
1859 bool is_id = (i == 0);
|
|
```
|
|
|
|
### inline_begintable [warn] projects/osint_graph/apps/graph_explorer/views.cpp:2292
|
|
snippet: if (ImGui::BeginTable("##te_fields", 5,
|
|
```
|
|
2287 // Fields table
|
|
2288 ImGui::Spacing();
|
|
2289 ImGui::TextUnformatted("Fields");
|
|
2290 ImGui::Separator();
|
|
2291
|
|
>> 2292 if (ImGui::BeginTable("##te_fields", 5,
|
|
2293 ImGuiTableFlags_BordersInnerV
|
|
2294 | ImGuiTableFlags_RowBg
|
|
2295 | ImGuiTableFlags_SizingStretchProp)) {
|
|
2296 ImGui::TableSetupColumn("name");
|
|
2297 ImGui::TableSetupColumn("type", ImGuiTableColumnFlags_WidthFixed, 90.0f);
|
|
```
|
|
|
|
### no_child_host [warn] projects/osint_graph/apps/graph_explorer/views.cpp:1632
|
|
snippet: data_table::render("##tablev_dt", {tbl}, app.table_dt_state);
|
|
```
|
|
1627 tbl.rows = s_rows_cached;
|
|
1628 tbl.cols = k_ncols;
|
|
1629
|
|
1630 // Render con chrome completo (barra de chips + breadcrumb).
|
|
1631 // app.table_dt_state persiste entre frames.
|
|
>> 1632 data_table::render("##tablev_dt", {tbl}, app.table_dt_state);
|
|
1633
|
|
1634 ImGui::End();
|
|
1635 }
|
|
1636
|
|
1637 // ----------------------------------------------------------------------------
|
|
```
|
|
|
|
|
|
## navegator_dashboard [warn] (projects/navegator/apps/navegator_dashboard)
|
|
|
|
### inline_begintable [warn] projects/navegator/apps/navegator_dashboard/autoextract_panel.cpp:528
|
|
snippet: if (ImGui::BeginTable("##ax_schema", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
|
```
|
|
523 {
|
|
524 std::lock_guard<std::mutex> lk(g_ax.mu);
|
|
525 sc_copy = g_ax.schema;
|
|
526 }
|
|
527
|
|
>> 528 if (ImGui::BeginTable("##ax_schema", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
|
529 ImGui::TableSetupColumn("field");
|
|
530 ImGui::TableSetupColumn("selector");
|
|
531 ImGui::TableSetupColumn("sample");
|
|
532 ImGui::TableSetupColumn("type");
|
|
533 ImGui::TableSetupColumn("keep");
|
|
```
|
|
|
|
### no_child_host [warn] projects/navegator/apps/navegator_dashboard/panels.cpp:234
|
|
snippet: data_table::render("##dt_browsers", {tbl}, g_browsers.dt_state, &dt_events, /*show_chrome=*/false);
|
|
```
|
|
229 data_table::BadgeRule{"visible", "#22c55e", "visible"},
|
|
230 };
|
|
231 }
|
|
232
|
|
233 std::vector<data_table::TableEvent> dt_events;
|
|
>> 234 data_table::render("##dt_browsers", {tbl}, g_browsers.dt_state, &dt_events, /*show_chrome=*/false);
|
|
235 for (auto& ev : dt_events) {
|
|
236 if (ev.kind == data_table::TableEventKind::RowDoubleClick &&
|
|
237 ev.row >= 0 && ev.row < static_cast<int>(g_browsers.instances.size())) {
|
|
238 g_session().select_browser(g_browsers.instances[ev.row].port);
|
|
239 }
|
|
```
|
|
|
|
### no_child_host [warn] projects/navegator/apps/navegator_dashboard/panels.cpp:456
|
|
snippet: data_table::render("##dt_tabs", {tbl}, g_tabs_ui.dt_state, &dt_events, /*show_chrome=*/false);
|
|
```
|
|
451 data_table::BadgeRule{"no", "#6b7280", "no"},
|
|
452 };
|
|
453 }
|
|
454
|
|
455 std::vector<data_table::TableEvent> dt_events;
|
|
>> 456 data_table::render("##dt_tabs", {tbl}, g_tabs_ui.dt_state, &dt_events, /*show_chrome=*/false);
|
|
457 for (auto& ev : dt_events) {
|
|
458 if (ev.kind == data_table::TableEventKind::RowDoubleClick &&
|
|
459 ev.row >= 0 && ev.row < static_cast<int>(visible_tabs.size())) {
|
|
460 const CdpTab* tp = visible_tabs[ev.row];
|
|
461 if (tp && !tp->ws_url.empty()) {
|
|
```
|
|
|
|
### no_child_host [warn] projects/navegator/apps/navegator_dashboard/panels.cpp:1016
|
|
snippet: data_table::render("##dt_wsframes", {ws_tbl}, g_dt_wsframes, false);
|
|
```
|
|
1011 data_table::BadgeRule{"ping", "#6b7280", "ping"},
|
|
1012 data_table::BadgeRule{"pong", "#6b7280", "pong"},
|
|
1013 };
|
|
1014 }
|
|
1015
|
|
>> 1016 data_table::render("##dt_wsframes", {ws_tbl}, g_dt_wsframes, false);
|
|
1017 ImGui::EndTabItem();
|
|
1018 }
|
|
1019 ImGui::EndTabBar();
|
|
1020 }
|
|
1021 }
|
|
```
|
|
|
|
### no_child_host [warn] projects/navegator/apps/navegator_dashboard/panels.cpp:1322
|
|
snippet: data_table::render("##dt_requests", {req_tbl}, g_net_ui.dt_state, &dt_events, /*show_chrome=*/true);
|
|
```
|
|
1317 cs.duration_warn_ms = 1000.0f;
|
|
1318 cs.duration_error_ms = 5000.0f;
|
|
1319 }
|
|
1320
|
|
1321 std::vector<data_table::TableEvent> dt_events;
|
|
>> 1322 data_table::render("##dt_requests", {req_tbl}, g_net_ui.dt_state, &dt_events, /*show_chrome=*/true);
|
|
1323 for (auto& ev : dt_events) {
|
|
1324 if (ev.kind == data_table::TableEventKind::RowDoubleClick &&
|
|
1325 ev.row >= 0 && ev.row < static_cast<int>(filtered.size())) {
|
|
1326 g_net_ui.selected_id = filtered[ev.row]->id;
|
|
1327 g_net_ui.selected_index = ev.row;
|
|
```
|
|
|
|
### inline_begintable [warn] projects/navegator/apps/navegator_dashboard/recipes_panel.cpp:238
|
|
snippet: } else if (ImGui::BeginTable("##recipes_tbl", 6,
|
|
```
|
|
233 }
|
|
234
|
|
235 if (rows_copy.empty()) {
|
|
236 ImGui::TextDisabled("No recipes in projects/navegator/profiles/default/recipes/.");
|
|
237 ImGui::TextDisabled("Use AutoExtract panel to create one.");
|
|
>> 238 } else if (ImGui::BeginTable("##recipes_tbl", 6,
|
|
239 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
|
240 ImGui::TableSetupColumn("name");
|
|
241 ImGui::TableSetupColumn("url_pattern");
|
|
242 ImGui::TableSetupColumn("last_status");
|
|
243 ImGui::TableSetupColumn("last_at");
|
|
```
|
|
|
|
|
|
## odr_console [ok] (projects/online_data_recopilation/apps/odr_console)
|
|
|
|
### no_event_sink [info] projects/online_data_recopilation/apps/odr_console:0
|
|
snippet: no TableEvent / events_out found in any source file
|
|
|
|
|
|
## registry_dashboard [warn] (projects/fn_monitoring/apps/registry_dashboard)
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/views.cpp:380
|
|
snippet: if (ImGui::BeginTable("##kpi_grid", 4, flags)) {
|
|
```
|
|
375 // del registry). Si no hay datos cargados, queda vacio y el card mostrara
|
|
376 // solo valor + delta placeholder.
|
|
377 const float* spark_data = data.date_values.empty() ? nullptr : data.date_values.data();
|
|
378 const int spark_count = static_cast<int>(data.date_values.size());
|
|
379
|
|
>> 380 if (ImGui::BeginTable("##kpi_grid", 4, flags)) {
|
|
381 struct KPI { const char* label; float value; const char* fmt; const char* icon; };
|
|
382 const KPI cards[8] = {
|
|
383 {"Functions", static_cast<float>(stats.total_functions), "%.0f", TI_FUNCTION},
|
|
384 {"Types", static_cast<float>(stats.total_types), "%.0f", TI_HEXAGON},
|
|
385 {"Apps", static_cast<float>(stats.total_apps), "%.0f", TI_APPS},
|
|
```
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/views.cpp:436
|
|
snippet: if (ImGui::BeginTable("##chart_grid", 4, flags)) {
|
|
```
|
|
431 void draw_charts(RegistryData& data, float height) {
|
|
432 const ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame
|
|
433 | ImGuiTableFlags_NoPadOuterX;
|
|
434 const float plot_h = height - 48.0f;
|
|
435
|
|
>> 436 if (ImGui::BeginTable("##chart_grid", 4, flags)) {
|
|
437 ImGui::TableNextRow();
|
|
438
|
|
439 ImGui::TableSetColumnIndex(0);
|
|
440 {
|
|
441 ImVec2 sz(ImGui::GetContentRegionAvail().x, height);
|
|
```
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/views.cpp:648
|
|
snippet: if (ImGui::BeginTable("##monitor_kpi", 7, flags)) {
|
|
```
|
|
643
|
|
644 // 7 KPI cards: Calls / MCP / Reg% / Errors / Violations / Copies / Versions
|
|
645 // "MCP" = calls Claude lanza via tools registry-aware (mcp / fn_cli_run /
|
|
646 // heredoc). "Reg %" = porcentaje del total con function_id no vacio.
|
|
647 const ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_NoPadOuterX;
|
|
>> 648 if (ImGui::BeginTable("##monitor_kpi", 7, flags)) {
|
|
649 struct KPI { const char* label; float value; const char* icon; const char* fmt; };
|
|
650 const KPI cards[7] = {
|
|
651 {"Calls", static_cast<float>(cu.total_calls), TI_ACTIVITY, "%.0f"},
|
|
652 {"MCP", static_cast<float>(cu.total_mcp), TI_PLUG_CONNECTED, "%.0f"},
|
|
653 {"Reg %", static_cast<float>(cu.registry_pct), TI_PERCENTAGE, "%.1f%%"},
|
|
```
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/views.cpp:1110
|
|
snippet: if (!ImGui::BeginTable("##proj_layout", 2, flags)) return;
|
|
```
|
|
1105 }
|
|
1106
|
|
1107 // Dos columnas: izquierda arbol, derecha detalle.
|
|
1108 const ImGuiTableFlags flags = ImGuiTableFlags_Resizable
|
|
1109 | ImGuiTableFlags_SizingStretchProp;
|
|
>> 1110 if (!ImGui::BeginTable("##proj_layout", 2, flags)) return;
|
|
1111
|
|
1112 ImGui::TableSetupColumn("tree", ImGuiTableColumnFlags_WidthStretch, 1.0f);
|
|
1113 ImGui::TableSetupColumn("detail", ImGuiTableColumnFlags_WidthStretch, 2.5f);
|
|
1114 ImGui::TableNextRow();
|
|
1115
|
|
```
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/views.cpp:1448
|
|
snippet: if (!ImGui::BeginTable("##explorer_layout", 2, flags)) return;
|
|
```
|
|
1443 return;
|
|
1444 }
|
|
1445
|
|
1446 const ImGuiTableFlags flags = ImGuiTableFlags_Resizable
|
|
1447 | ImGuiTableFlags_SizingStretchProp;
|
|
>> 1448 if (!ImGui::BeginTable("##explorer_layout", 2, flags)) return;
|
|
1449
|
|
1450 ImGui::TableSetupColumn("list", ImGuiTableColumnFlags_WidthStretch, 1.0f);
|
|
1451 ImGui::TableSetupColumn("detail", ImGuiTableColumnFlags_WidthStretch, 2.4f);
|
|
1452 ImGui::TableNextRow();
|
|
1453
|
|
```
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/work_tab.cpp:239
|
|
snippet: if (ImGui::BeginTable("##flows_work", 8,
|
|
```
|
|
234 // Flows table
|
|
235 ImGui::PushStyleColor(ImGuiCol_Text, fn_tokens::colors::text_muted);
|
|
236 ImGui::TextUnformatted("Flows");
|
|
237 ImGui::PopStyleColor();
|
|
238
|
|
>> 239 if (ImGui::BeginTable("##flows_work", 8,
|
|
240 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
|
|
241 ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_Resizable)) {
|
|
242 ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 50.0f);
|
|
243 ImGui::TableSetupColumn("Name");
|
|
244 ImGui::TableSetupColumn("Pattern", ImGuiTableColumnFlags_WidthFixed, 110.0f);
|
|
```
|
|
|
|
### inline_begintable [warn] projects/fn_monitoring/apps/registry_dashboard/work_tab.cpp:272
|
|
snippet: if (ImGui::BeginTable("##top_issues_work", 7,
|
|
```
|
|
267 ImGui::Spacing();
|
|
268 ImGui::PushStyleColor(ImGuiCol_Text, fn_tokens::colors::text_muted);
|
|
269 ImGui::TextUnformatted("Top issues (priority alta, not done)");
|
|
270 ImGui::PopStyleColor();
|
|
271
|
|
>> 272 if (ImGui::BeginTable("##top_issues_work", 7,
|
|
273 ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders |
|
|
274 ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_Resizable)) {
|
|
275 ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 70.0f);
|
|
276 ImGui::TableSetupColumn("Title");
|
|
277 ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 80.0f);
|
|
```
|
|
|
|
### no_event_sink [info] projects/fn_monitoring/apps/registry_dashboard:0
|
|
snippet: no TableEvent / events_out found in any source file
|
|
|
|
|
|
## services_monitor [ok] (apps/services_monitor)
|
|
|
|
### no_event_sink [info] apps/services_monitor:0
|
|
snippet: no TableEvent / events_out found in any source file
|
|
|