// tab_dots — CellRenderer::Dots demo (fase 2, issue 0108). // 8 servicios x 5 cols: service_name, environment, last_runs (Dots ','), // recent_24h (Dots '|'), uptime_pct (ColorScale). // UI controls: dots_max slider, show_count toggle, glyph_size slider. #include "tabs.h" #include "qa_state.h" #include "data_table/data_table.h" #include #include namespace tables_qa::tabs { namespace { qa::TabState g_st; // ----------------------------------------------------------------------- // Dynamic UI state — mutated by sliders/toggles each frame. // ----------------------------------------------------------------------- static int s_dots_max = 20; // both Dots columns static bool s_show_count = true; // last_runs " (N)" suffix static float s_glyph_size = 0.0f; // 0 = default font size // ----------------------------------------------------------------------- // Backing data: 8 services, 5 cols each. // Cols: service_name | environment | last_runs | recent_24h | uptime_pct // ----------------------------------------------------------------------- void seed() { g_st.back = { // service_name env last_runs (comma-sep) recent_24h (pipe-sep) uptime_pct "api-gateway", "prod", "ok,ok,ok,error,ok,ok,ok,ok,error,ok", "ok|ok|error|ok|ok|ok|ok|ok", "99.1", "auth-service", "prod", "ok,ok,ok,ok,ok,ok,ok,ok,ok,ok", "ok|ok|ok|ok|ok|ok|ok|ok", "100.0", "billing-worker", "prod", "ok,error,error,ok,timeout,ok,ok,error,ok,ok","ok|error|timeout|ok|ok|ok|ok", "94.7", "data-pipeline", "staging", "ok,ok,ok,ok,error,ok", "ok|ok|ok|error|ok", "98.3", "report-gen", "staging", "timeout,ok,ok,ok,error,ok,ok,ok", "timeout|ok|ok|ok|ok", "97.5", "ml-inference", "dev", "ok,ok,error,ok,ok", "ok|error|ok", "96.2", "cache-warmer", "dev", "ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok,ok", "ok|ok|ok|ok|ok|ok", "99.9", "event-consumer", "prod", "error,error,ok,ok,timeout,ok,ok,ok,error,ok","error|ok|ok|timeout|ok|ok", "91.4", }; qa::rebuild_ptrs(g_st); } // ----------------------------------------------------------------------- // Shared BadgeRule map for both Dots columns. // ----------------------------------------------------------------------- std::vector make_status_badges() { return { {"ok", "#22c55e", ""}, {"error", "#ef4444", ""}, {"timeout", "#f59e0b", ""}, {"unknown", "#6b7280", ""}, }; } } // anon // ----------------------------------------------------------------------- // render_dots — called every frame from qa_panel. // ----------------------------------------------------------------------- void render_dots() { if (g_st.back.empty()) seed(); // ----------------------------------------------------------------------- // UI controls bar. // ----------------------------------------------------------------------- ImGui::PushItemWidth(180.0f); ImGui::SliderInt("dots_max", &s_dots_max, 5, 30); ImGui::SameLine(0, 20); ImGui::Checkbox("show_count (last_runs)", &s_show_count); ImGui::SameLine(0, 20); ImGui::SliderFloat("glyph_size", &s_glyph_size, 0.0f, 12.0f, "%.1f px"); ImGui::PopItemWidth(); ImGui::Separator(); // ----------------------------------------------------------------------- // TableInput: 8 rows x 5 cols, row-major. // ----------------------------------------------------------------------- data_table::TableInput tbl; tbl.name = "dots_demo"; tbl.headers = {"service_name", "environment", "last_runs", "recent_24h", "uptime_pct"}; tbl.types = { data_table::ColumnType::String, // service_name data_table::ColumnType::String, // environment → CategoricalChip data_table::ColumnType::String, // last_runs → Dots ',' data_table::ColumnType::String, // recent_24h → Dots '|' data_table::ColumnType::Float, // uptime_pct → ColorScale }; tbl.cells = g_st.ptrs.data(); tbl.rows = 8; tbl.cols = 5; // ----------------------------------------------------------------------- // Column specs. // ----------------------------------------------------------------------- tbl.column_specs.resize(tbl.cols); for (int i = 0; i < tbl.cols; ++i) tbl.column_specs[i].id = tbl.headers[i]; // col 0: service_name — default Text, no spec needed. // col 1: environment — CategoricalChip { auto& cs = tbl.column_specs[1]; cs.renderer = data_table::CellRenderer::CategoricalChip; cs.chips = { {"prod", "#ef4444"}, // red {"staging", "#f59e0b"}, // amber {"dev", "#3b82f6"}, // blue }; } // col 2: last_runs — Dots with ',' separator, show_count dynamic. { auto& cs = tbl.column_specs[2]; cs.renderer = data_table::CellRenderer::Dots; cs.badges = make_status_badges(); cs.dots_separator = ','; cs.dots_max = s_dots_max; cs.dots_show_count = s_show_count; cs.dots_glyph_size = s_glyph_size; } // col 3: recent_24h — Dots with '|' separator, no count suffix. { auto& cs = tbl.column_specs[3]; cs.renderer = data_table::CellRenderer::Dots; cs.badges = make_status_badges(); cs.dots_separator = '|'; cs.dots_max = s_dots_max; cs.dots_show_count = false; cs.dots_glyph_size = s_glyph_size; } // col 4: uptime_pct — ColorScale 0..100. { auto& cs = tbl.column_specs[4]; cs.renderer = data_table::CellRenderer::ColorScale; cs.range_min = 0.0; cs.range_max = 100.0; cs.range_alpha = 0.30f; // Default green→amber→red gradient (empty range_stops). } // ----------------------------------------------------------------------- // Render. // ----------------------------------------------------------------------- ImGui::BeginChild("##dots_host", ImVec2(-1, -1)); g_st.last_events.clear(); data_table::render("##dots_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