// 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 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