b15106fc09
- CMakeLists.txt - app.md - appicon.ico - main.cpp - perf_tests.cpp - perf_tests.h - qa_panel.cpp - qa_panel.h - qa_state.cpp - qa_state.h - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
160 lines
5.9 KiB
C++
160 lines
5.9 KiB
C++
// tab_tql — TQL pipeline preset + Ask AI panel demo.
|
|
// Demuestra:
|
|
// - Tabla "events" (20 filas, 5 columnas) con renderers declarativos.
|
|
// - Preset buttons: filter errors only / group by service + count / reset.
|
|
// - TextDisabled explicando chips bar + Ask AI NL→TQL modal.
|
|
// Issue 0108 fase 2.
|
|
#include "tabs.h"
|
|
#include "qa_state.h"
|
|
#include "data_table/data_table.h"
|
|
#include <imgui.h>
|
|
|
|
namespace tables_qa::tabs {
|
|
|
|
namespace {
|
|
|
|
qa::TabState g_st;
|
|
|
|
// 20 filas x 5 columnas: timestamp, service, event_type, duration_ms, user_country
|
|
// Columnas: idx 0=timestamp, 1=service, 2=event_type, 3=duration_ms, 4=user_country
|
|
void seed() {
|
|
g_st.back = {
|
|
// timestamp service event_type duration_ms user_country
|
|
"2024-01-15T08:01:00Z", "auth", "login", "45", "ES",
|
|
"2024-01-15T08:01:12Z", "api", "success", "120", "US",
|
|
"2024-01-15T08:01:34Z", "db", "timeout", "1500", "FR",
|
|
"2024-01-15T08:02:01Z", "web", "error", "2300", "DE",
|
|
"2024-01-15T08:02:15Z", "auth", "login", "55", "JP",
|
|
"2024-01-15T08:02:45Z", "api", "error", "980", "ES",
|
|
"2024-01-15T08:03:00Z", "db", "success", "88", "US",
|
|
"2024-01-15T08:03:22Z", "web", "login", "210", "FR",
|
|
"2024-01-15T08:03:50Z", "auth", "timeout", "3200", "DE",
|
|
"2024-01-15T08:04:10Z", "api", "success", "67", "JP",
|
|
"2024-01-15T08:04:30Z", "db", "error", "4100", "ES",
|
|
"2024-01-15T08:04:55Z", "web", "success", "155", "US",
|
|
"2024-01-15T08:05:15Z", "auth", "error", "1900", "FR",
|
|
"2024-01-15T08:05:40Z", "api", "login", "38", "DE",
|
|
"2024-01-15T08:06:05Z", "db", "success", "95", "JP",
|
|
"2024-01-15T08:06:30Z", "web", "timeout", "2750", "ES",
|
|
"2024-01-15T08:07:00Z", "auth", "success", "72", "US",
|
|
"2024-01-15T08:07:25Z", "api", "error", "1100", "FR",
|
|
"2024-01-15T08:07:50Z", "db", "login", "41", "DE",
|
|
"2024-01-15T08:08:15Z", "web", "success", "180", "JP",
|
|
};
|
|
qa::rebuild_ptrs(g_st);
|
|
}
|
|
|
|
} // anon
|
|
|
|
void render_tql() {
|
|
if (g_st.back.empty()) seed();
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Controls row: preset buttons + reset
|
|
// -------------------------------------------------------------------------
|
|
if (ImGui::SmallButton("Preset: filter errors only")) {
|
|
// Ensure stage 0 exists
|
|
g_st.dt.ensure_stage0();
|
|
// Clear existing filters on stage 0 and add error filter
|
|
// event_type is column index 2
|
|
g_st.dt.stages[0].filters.clear();
|
|
data_table::Filter f;
|
|
f.col = 2;
|
|
f.op = data_table::Op::Eq;
|
|
f.value = "error";
|
|
g_st.dt.stages[0].filters.push_back(f);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::SmallButton("Preset: group by service + count")) {
|
|
// Stage 1 aggregates stage 0 output: breakout by "service", count rows
|
|
g_st.dt.ensure_stage0();
|
|
// Remove any existing stage 1+ and add a fresh aggregation stage
|
|
if ((int)g_st.dt.stages.size() > 1)
|
|
g_st.dt.stages.resize(1);
|
|
data_table::Stage agg;
|
|
agg.breakouts.push_back("service");
|
|
data_table::Aggregation cnt;
|
|
cnt.fn = data_table::AggFn::Count;
|
|
cnt.alias = "count";
|
|
agg.aggregations.push_back(cnt);
|
|
g_st.dt.stages.push_back(std::move(agg));
|
|
// Activate the aggregation stage
|
|
g_st.dt.active_stage = (int)g_st.dt.stages.size() - 1;
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::SmallButton("Reset pipeline")) {
|
|
g_st.dt.stages.clear();
|
|
g_st.dt.active_stage = 0;
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
ImGui::TextDisabled("Use chips bar to build pipeline interactively. "
|
|
"Ask AI button in chips bar opens NL\xe2\x86\x92TQL modal "
|
|
"(requires ANTHROPIC_API_KEY env).");
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Table
|
|
// -------------------------------------------------------------------------
|
|
data_table::TableInput tbl;
|
|
tbl.name = "events";
|
|
tbl.headers = {"timestamp", "service", "event_type", "duration_ms", "user_country"};
|
|
tbl.types = {
|
|
data_table::ColumnType::Date,
|
|
data_table::ColumnType::String,
|
|
data_table::ColumnType::String,
|
|
data_table::ColumnType::Float,
|
|
data_table::ColumnType::String,
|
|
};
|
|
tbl.cells = g_st.ptrs.data();
|
|
tbl.rows = 20;
|
|
tbl.cols = 5;
|
|
|
|
tbl.column_specs.resize(tbl.cols);
|
|
for (int i = 0; i < tbl.cols; i++) tbl.column_specs[i].id = tbl.headers[i];
|
|
|
|
// service (col 1) → CategoricalChip
|
|
{
|
|
auto& cs = tbl.column_specs[1];
|
|
cs.renderer = data_table::CellRenderer::CategoricalChip;
|
|
cs.chips = {
|
|
{"auth", "#3b82f6"},
|
|
{"api", "#22c55e"},
|
|
{"db", "#a855f7"},
|
|
{"web", "#f59e0b"},
|
|
};
|
|
}
|
|
|
|
// event_type (col 2) → Badge
|
|
{
|
|
auto& cs = tbl.column_specs[2];
|
|
cs.renderer = data_table::CellRenderer::Badge;
|
|
cs.badges = {
|
|
{"login", "#3b82f6", ""},
|
|
{"success", "#22c55e", ""},
|
|
{"timeout", "#f59e0b", ""},
|
|
{"error", "#ef4444", "ERR"},
|
|
};
|
|
}
|
|
|
|
// duration_ms (col 3) → Duration with warn=200, error=1000
|
|
{
|
|
auto& cs = tbl.column_specs[3];
|
|
cs.renderer = data_table::CellRenderer::Duration;
|
|
cs.duration_warn_ms = 200.0f;
|
|
cs.duration_error_ms = 1000.0f;
|
|
}
|
|
|
|
ImGui::BeginChild("##tql_host", ImVec2(-1, -1));
|
|
g_st.last_events.clear();
|
|
data_table::render("##tql_tbl", {tbl}, g_st.dt,
|
|
&g_st.last_events, qa::toggles().show_chrome);
|
|
ImGui::EndChild();
|
|
qa::consume_events(g_st.last_events);
|
|
}
|
|
|
|
} // namespace tables_qa::tabs
|