feat: initial scaffold kanban_cpp v0.1.0
C++ ImGui kanban for steering LLM agents. Six panels (Board, Calendar, Dashboard, Agent runs, Worktrees, DoD inspector) wired to registry functions http_request, kpi_card, sparkline, agent_runs_timeline, dod_evidence_panel. Backend Go on :8403 (independent operations.db from kanban_web).
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// panel_dashboard.cpp — KPI grid using kpi_card + sparkline from the registry.
|
||||
#include "panels.h"
|
||||
#include "core/icons_tabler.h"
|
||||
#include "viz/kpi_card.h"
|
||||
#include "viz/sparkline.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace kanban_cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
float pct_by_status(const std::vector<Card>& cards, const std::string& status) {
|
||||
if (cards.empty()) return 0.0f;
|
||||
int hits = 0;
|
||||
for (const auto& c : cards) if (c.status == status) ++hits;
|
||||
return 100.0f * static_cast<float>(hits) / static_cast<float>(cards.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void draw_dashboard(AppState& s, bool* p_open) {
|
||||
if (!ImGui::Begin(TI_DASHBOARD " Dashboard", p_open)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::TextDisabled("KPIs sinteticos (TODO: backend /api/stats endpoint)");
|
||||
ImGui::Separator();
|
||||
|
||||
// Snapshot counts
|
||||
int total = static_cast<int>(s.cards.size());
|
||||
std::map<std::string, int> by_priority;
|
||||
std::map<std::string, int> by_status;
|
||||
for (const auto& c : s.cards) {
|
||||
if (!c.priority.empty()) by_priority[c.priority]++;
|
||||
if (!c.status.empty()) by_status[c.status]++;
|
||||
}
|
||||
|
||||
// Fake history for sparkline — until backend wires real time-series.
|
||||
static float hist_total[12] = {3,4,5,5,7,8,9,8,10,11,12,13};
|
||||
static float hist_doing[12] = {1,1,2,2,3,3,4,4,5,5,6,6};
|
||||
|
||||
// KPI grid (use Columns for a quick 3-up layout)
|
||||
ImGui::Columns(3, "##kpi_cols", false);
|
||||
|
||||
kpi_card("Total cards", static_cast<float>(total), 0.0f,
|
||||
hist_total, 12, "%.0f", TI_LAYOUT_KANBAN);
|
||||
ImGui::NextColumn();
|
||||
|
||||
kpi_card("Doing now", static_cast<float>(by_status["doing"]), 0.0f,
|
||||
hist_doing, 12, "%.0f", TI_PLAYER_PLAY);
|
||||
ImGui::NextColumn();
|
||||
|
||||
kpi_card("Critical", static_cast<float>(by_priority["critical"]), 0.0f,
|
||||
nullptr, 0, "%.0f", TI_FLAG);
|
||||
|
||||
ImGui::Columns(1);
|
||||
ImGui::Separator();
|
||||
|
||||
// Status breakdown
|
||||
ImGui::Text("Status breakdown");
|
||||
for (const auto& kv : by_status) {
|
||||
ImGui::Text(" %-12s %d", kv.first.c_str(), kv.second);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace kanban_cpp
|
||||
Reference in New Issue
Block a user