Add Servidor Dashboard with connection monitoring

- Created servidor_dashboard.html with beautiful visual dashboard
- Shows all servers in grid cards with basic info
- Click button opens detailed modal with:
  - Server full information (IP, CPU, RAM, Storage, OS, Expiration)
  - All connected databases in a clean diagram layout
  - Database connection status (active/inactive)
  - Connection details (Host, Port, User, Type)
  - Ping button to test connection with response time
  - View Connection button to open query-runner
- Backend updates:
  - Added ServidorDashboard() controller to render the dashboard view
  - Added GetServidorDashboard() API endpoint to fetch server + connections
  - Added PingConexion() endpoint to test database connections (TCP + DB test)
  - Color-coded status badges and database type indicators
  - Responsive design for mobile and desktop
- Routes:
  - GET /app/servidor-dashboard (render view)
  - GET /api/app/servidor-dashboard/:id (get server details API)
  - GET /api/app/conx-ping/:id (ping connection endpoint)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Lizandro Guarnizo
2026-05-21 08:49:18 -05:00
co-authored by Copilot
parent 0813dfca55
commit 29820c8706
3 changed files with 520 additions and 0 deletions
+106
View File
@@ -1,11 +1,16 @@
package controllers
import (
"fmt"
"math"
"net"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/app"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)
// RENDER
@@ -24,6 +29,22 @@ func Servidor(c *fiber.Ctx) error {
return nil
}
// ServidorDashboard renders the server dashboard view
func ServidorDashboard(c *fiber.Ctx) error {
data := fiber.Map{
"user": c.Locals("user").(map[string]interface{}),
"modules": c.Locals("userModules"),
}
if err := c.Render("servidor_dashboard", data, "layouts/main"); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Error rendering template",
"error": err.Error(),
})
}
return nil
}
func GetServidor(c *fiber.Ctx) error {
pageStr := c.Query("page", "1")
page, err := strconv.Atoi(pageStr)
@@ -138,3 +159,88 @@ func DeleteServidor(c *fiber.Ctx) error {
"message": "Servidor eliminado exitosamente",
})
}
// GetServidorDashboard retorna un servidor con todas sus conexiones de BD
func GetServidorDashboard(c *fiber.Ctx) error {
servidorID := c.Params("id")
uid, err := strconv.ParseUint(servidorID, 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "ID inválido",
})
}
// Obtener servidor
var servidor models.Servidor
db := app.Http.Database.DB
if err := db.Preload("ProvServidor").Preload("TipoServidor").First(&servidor, uid).Error; err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"error": "Servidor no encontrado",
})
}
// Obtener conexiones de BD asociadas
var conexiones []models.ConxDb
if err := db.Preload("Servidor").Preload("TipoDb").Where("servidor_id = ?", uid).Find(&conexiones).Error; err != nil {
conexiones = []models.ConxDb{}
}
return c.JSON(fiber.Map{
"servidor": servidor,
"conexiones": conexiones,
})
}
// PingConexion tests the connection to a database and returns the response time
func PingConexion(c *fiber.Ctx) error {
conexionID := c.Params("id")
uid, err := strconv.ParseUint(conexionID, 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"exitoso": false,
"error": "ID inválido",
})
}
// Obtener conexión de BD
var conexion models.ConxDb
db := app.Http.Database.DB
if err := db.Preload("TipoDb").Preload("Servidor").First(&conexion, uid).Error; err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"exitoso": false,
"error": "Conexión no encontrada",
})
}
// Realizar ping a la conexión
inicio := time.Now()
exitoso := false
var tiempoMs int64
// Intentar conexión TCP
addr := fmt.Sprintf("%s:%s", conexion.Servidor.IpServidor, conexion.Puerto)
conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err == nil {
conn.Close()
exitoso = true
tiempoMs = time.Since(inicio).Milliseconds()
}
// Si falla TCP, intentar con la BD específica
if !exitoso {
inicio = time.Now()
testErr := services.TestDBConnection(conexion)
if testErr == nil {
exitoso = true
tiempoMs = time.Since(inicio).Milliseconds()
}
}
return c.JSON(fiber.Map{
"exitoso": exitoso,
"tiempo": tiempoMs,
"host": conexion.Servidor.IpServidor,
"puerto": conexion.Puerto,
"tipo": conexion.TipoDb.Nombre,
})
}