#include "app_base.h" #include "imgui.h" #include "core/fullscreen_window.h" #include "core/app_menubar.h" #include "core/app_about.h" #include "core/app_settings.h" #include "core/tokens.h" #include "data.h" #include "data_http.h" #include "views.h" #include #include #include #include #include static RegistryData g_data; static std::string g_db_path; static std::string g_api_url; static bool g_loaded = false; static bool g_using_http = false; static void reload_data() { g_data = RegistryData{}; // Try HTTP API first if (!g_api_url.empty()) { g_loaded = load_registry_data_http(g_api_url, g_data); if (g_loaded) { g_using_http = true; return; } fprintf(stderr, "HTTP API failed, falling back to SQLite\n"); } // Fallback to direct SQLite g_using_http = false; if (!g_db_path.empty()) { g_loaded = load_registry_data(g_db_path.c_str(), g_data); if (!g_loaded) { fprintf(stderr, "Failed to load registry data from: %s\n", g_db_path.c_str()); } } } static void render() { if (ImGui::GetIO().UserData != nullptr) { ImGui::GetIO().UserData = nullptr; reload_data(); } if (!g_loaded) { fullscreen_window_begin("##error"); ImGui::TextColored(ImVec4(1, 0.3f, 0.3f, 1), "Could not load registry data"); ImGui::Spacing(); if (!g_api_url.empty()) ImGui::Text("API: %s (unreachable)", g_api_url.c_str()); if (!g_db_path.empty()) ImGui::Text("DB: %s", g_db_path.c_str()); ImGui::Spacing(); ImGui::TextWrapped( "Usage: registry_dashboard [--api URL] [db_path ...]\n" " --api URL Connect to sqlite_api (default: http://127.0.0.1:8484)\n" " db_path Direct SQLite path(s) as fallback"); ImGui::Spacing(); if (ImGui::Button("Retry")) { reload_data(); } fullscreen_window_end(); return; } draw_dashboard(g_data); } int main(int argc, char** argv) { // Parse --api flag std::vector db_candidates; bool api_explicit = false; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--api") == 0 && i + 1 < argc) { g_api_url = argv[++i]; api_explicit = true; } else if (strncmp(argv[i], "--api=", 6) == 0) { g_api_url = argv[i] + 6; api_explicit = true; } else { db_candidates.push_back(argv[i]); } } // Default: try localhost API if no --api given if (!api_explicit) { g_api_url = "http://127.0.0.1:8484"; } // Resolve SQLite fallback path for (auto& candidate : db_candidates) { if (std::ifstream(candidate).good()) { g_db_path = candidate; fprintf(stdout, "SQLite fallback: %s\n", g_db_path.c_str()); break; } fprintf(stderr, "Not found: %s\n", candidate.c_str()); } if (!db_candidates.empty()) { if (g_db_path.empty()) g_db_path = db_candidates.back(); } // Compartir el API URL con las vistas (para reindex/add desde la toolbar) views_set_api_url(g_api_url); // Info de la ventana About (submenu Settings → About...) fn_ui::about_window_set_info( "fn_registry Dashboard", "0.3.0", "Dashboard ImGui para visualizar el estado del fn_registry. " "Consume datos via sqlite_api HTTP (fallback a SQLite directo). " "KPIs con sparkline, charts con leyenda, tablas, altura responsive, " "Status panel en Settings, multi-viewport, dashboard_panel en views." ); // Seccion Status dentro de la ventana Settings (submenu Settings → Settings...). // Muestra fuente activa de datos, URL del API y path SQLite fallback. fn_ui::settings_window_add_section("status", "Status", []{ using namespace fn_tokens; ImGui::PushStyleColor(ImGuiCol_Text, colors::text_muted); ImGui::TextUnformatted("Source:"); ImGui::PopStyleColor(); ImGui::SameLine(); if (g_loaded) { ImGui::PushStyleColor(ImGuiCol_Text, colors::success); ImGui::TextUnformatted(g_using_http ? "HTTP API (connected)" : "SQLite (direct)"); ImGui::PopStyleColor(); } else { ImGui::PushStyleColor(ImGuiCol_Text, colors::error); ImGui::TextUnformatted("not connected"); ImGui::PopStyleColor(); } if (!g_api_url.empty()) { ImGui::PushStyleColor(ImGuiCol_Text, colors::text_muted); ImGui::TextUnformatted("API:"); ImGui::PopStyleColor(); ImGui::SameLine(); ImGui::TextUnformatted(g_api_url.c_str()); } if (!g_db_path.empty()) { ImGui::PushStyleColor(ImGuiCol_Text, colors::text_muted); ImGui::TextUnformatted("DB:"); ImGui::PopStyleColor(); ImGui::SameLine(); ImGui::TextUnformatted(g_db_path.c_str()); } ImGui::Spacing(); if (ImGui::Button("Reload")) { ImGui::GetIO().UserData = reinterpret_cast(1); } }); reload_data(); return fn::run_app( {.title = "fn_registry Dashboard", .width = 1600, .height = 1000, .viewports = true, .about = {"fn_registry Dashboard", "0.1.0", "Dashboard del registry: funciones, tipos, apps, drift."}, .log = {"registry_dashboard.log", 1}}, render ); }