diff --git a/tabs.cpp b/tabs.cpp index 750e1cf..dac4bab 100644 --- a/tabs.cpp +++ b/tabs.cpp @@ -95,7 +95,7 @@ void draw_dag_list(const std::string& api_url, dag_list_request_refresh(); } ImGui::SameLine(); - ImGui::TextDisabled("Double-click row -> inspect. R1..R5 = last 5 runs."); + ImGui::TextDisabled("Double-click row -> inspect. Recent = last 5 runs inline."); if (dags.empty()) { empty_state("( no DAGs )", "Empty registry", @@ -104,47 +104,48 @@ void draw_dag_list(const std::string& api_url, return; } - // Build TableInput. Columnas R1..R5 muestran status de las ultimas 5 runs - // como badges coloreadas (verde/rojo/amarillo/gris) — issue 0095. + // Build TableInput. 6 columns (was 10 with R1..R5 as separate Badge cols — + // that was an antipattern fixed in issue 0081-O.5). "Recent" uses CellRenderer::Dots + // to show up to 5 inline colored dots from a comma-separated status string. data_table::TableInput ti; ti.name = "dags"; - ti.headers = {"Name", "Schedule", "Last Status", - "R1", "R2", "R3", "R4", "R5", - "Tags", "Valid"}; + ti.headers = {"Name", "Schedule", "Status", "Recent", "Tags", "Valid"}; ti.types = { data_table::ColumnType::String, // Name data_table::ColumnType::String, // Schedule - data_table::ColumnType::String, // Last Status - data_table::ColumnType::String, // R1 - data_table::ColumnType::String, // R2 - data_table::ColumnType::String, // R3 - data_table::ColumnType::String, // R4 - data_table::ColumnType::String, // R5 + data_table::ColumnType::String, // Status (last run) + data_table::ColumnType::String, // Recent (dots: up to 5 runs) data_table::ColumnType::String, // Tags data_table::ColumnType::String, // Valid }; ti.rows = static_cast(dags.size()); ti.cols = static_cast(ti.headers.size()); - // BadgeRule por status: misma config para R1..R5. + // BadgeRule set: shared by Status (Badge) and Recent (Dots). auto run_status_badges = [](){ std::vector rules; - rules.push_back({"success", "#22c55e", "●"}); // verde - rules.push_back({"failed", "#ef4444", "●"}); // rojo - rules.push_back({"running", "#eab308", "●"}); // amarillo - rules.push_back({"pending", "#94a3b8", "●"}); // gris azulado - rules.push_back({"cancelled", "#6b7280", "●"}); // gris - rules.push_back({"-", "#1f2937", "·"}); // dot tenue cuando no hay run + rules.push_back({"success", "#22c55e", ""}); // verde — uses default glyph ● for Dots + rules.push_back({"failed", "#ef4444", ""}); // rojo + rules.push_back({"running", "#eab308", ""}); // amarillo + rules.push_back({"pending", "#94a3b8", ""}); // gris azulado + rules.push_back({"cancelled", "#6b7280", ""}); // gris return rules; }; - // ColumnSpec por columna. Solo R1..R5 (indices 3..7) son Badge. + // ColumnSpec per column. ti.column_specs.resize(ti.cols); for (int i = 0; i < ti.cols; i++) ti.column_specs[i].id = ti.headers[i]; - for (int i = 3; i <= 7; i++) { - ti.column_specs[i].renderer = data_table::CellRenderer::Badge; - ti.column_specs[i].badges = run_status_badges(); - } + + // idx 2 — "Status": Badge renderer for the single last-run status string. + ti.column_specs[2].renderer = data_table::CellRenderer::Badge; + ti.column_specs[2].badges = run_status_badges(); + + // idx 3 — "Recent": Dots renderer — each dot = one of the last 5 runs. + ti.column_specs[3].renderer = data_table::CellRenderer::Dots; + ti.column_specs[3].badges = run_status_badges(); + ti.column_specs[3].dots_max = 5; + ti.column_specs[3].dots_show_count = false; + ti.column_specs[3].tooltip_on_hover = true; // hover each dot -> show status string g_back_dag_list.clear(); g_back_dag_list.reserve(dags.size() * ti.cols); @@ -152,13 +153,16 @@ void draw_dag_list(const std::string& api_url, g_back_dag_list.push_back(d.name); g_back_dag_list.push_back(d.schedule.empty() ? "-" : d.schedule[0]); g_back_dag_list.push_back(status_for_dag(d.name, d, live_runs)); - // R1..R5 — most recent first; "-" si menos de 5 runs. - for (int i = 0; i < 5; i++) { - if (i < static_cast(d.last_runs_status.size())) { - g_back_dag_list.push_back(d.last_runs_status[i]); - } else { - g_back_dag_list.push_back("-"); + // "Recent": join up to 5 last run statuses as comma-separated string. + // Most-recent first. Only include runs that exist (no padding with "-"). + { + std::string recent; + int n = std::min(5, static_cast(d.last_runs_status.size())); + for (int i = 0; i < n; i++) { + if (i) recent += ','; + recent += d.last_runs_status[i]; } + g_back_dag_list.push_back(recent); } std::string tags_csv; for (size_t i = 0; i < d.tags.size(); i++) {