From d8522b49af535f6ddc1e96c7222f8f76304bb236 Mon Sep 17 00:00:00 2001 From: Trabajo Date: Tue, 5 May 2026 10:05:21 +0200 Subject: [PATCH] Controladores rutas y vistas del dashboard --- src/application/monitor-controller.ts | 67 ++++++- src/index.ts | 25 ++- src/infrastructure/monitor-routes-http.ts | 12 +- src/views/add-project.ejs | 33 ++++ src/views/error.ejs | 2 +- src/views/index.ejs | 207 ++++++++++++++++++---- 6 files changed, 286 insertions(+), 60 deletions(-) create mode 100644 src/views/add-project.ejs diff --git a/src/application/monitor-controller.ts b/src/application/monitor-controller.ts index e69ecff..cc7de57 100644 --- a/src/application/monitor-controller.ts +++ b/src/application/monitor-controller.ts @@ -1,21 +1,74 @@ import { type Request, type Response, type NextFunction } from 'express'; +import { MonitorScheduler } from './monitor-scheduler.js'; import { MonitorUsecases } from './monitor-usecases.js'; -import ejs from 'ejs'; -import path from 'path'; +import { AppError } from '../domain/common.js'; export class MonitorController { - constructor(private usecases: MonitorUsecases) {} + constructor( + private usecases: MonitorUsecases, + private scheduler: MonitorScheduler + ) {} renderDashboard = async (_req: Request, res: Response, next: NextFunction) => { try { const proyectos = await this.usecases.getDashboardData(); - const filePath = path.join(process.cwd(), 'src/views/index.ejs'); - ejs.renderFile(filePath, { proyectos }, (err, str) => { - if (err) return next(err); - res.send(str); + res.render('index', { + proyectos, + monitorIntervalSeconds: this.scheduler.getIntervalSeconds() }); } catch (err) { next(err); } } + + renderAddProject = async (_req: Request, res: Response, next: NextFunction) => { + try { + res.render('add-project'); + } catch (err) { + next(err); + } + } + + saveProject = async (req: Request, res: Response, next: NextFunction) => { + try { + const { nombre, url_health } = req.body; + await this.usecases.createNewProject(nombre, url_health); + res.redirect('/'); + } catch (err) { + next(err); + } + } + + checkAllProjects = async (_req: Request, res: Response, next: NextFunction) => { + try { + await this.usecases.checkAllProjectsHealth(); + res.sendStatus(204); + } catch (err) { + next(err); + } + } + + checkProject = async (req: Request, res: Response, next: NextFunction) => { + try { + const projectId = Number(req.params['id']); + if (!Number.isInteger(projectId) || projectId <= 0) { + throw new AppError('Id de proyecto invalido', 400); + } + + await this.usecases.checkProjectHealth(projectId); + res.sendStatus(204); + } catch (err) { + next(err); + } + } + + updateMonitorInterval = async (req: Request, res: Response, next: NextFunction) => { + try { + const seconds = Number(req.body.seconds); + this.scheduler.setIntervalSeconds(seconds); + res.json({ seconds: this.scheduler.getIntervalSeconds() }); + } catch (err) { + next(err); + } + } } diff --git a/src/index.ts b/src/index.ts index 88da15e..fcb64d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,33 +2,28 @@ import express from "express"; import type { Request, Response, NextFunction } from "express"; import path from "path"; import { createRouter } from "./infrastructure/monitor-routes-http.js"; +import { MonitorScheduler } from "./application/monitor-scheduler.js"; import { MonitorUsecases } from "./application/monitor-usecases.js"; -import { pool } from "./config/postgreConfig.js"; +import { MonitorRepository } from "./repository/monitor-repository.js"; +import { pool } from "./config/postgres-config.js"; import { AppError } from "./domain/common.js"; const app = express(); -const port = 3000; +const port = Number(process.env.PORT) || 3000; app.use(express.json()); +app.use(express.urlencoded({ extended: false })); app.set("view engine", "ejs"); app.set("views", path.join(process.cwd(), "src/views")); -const monitorJob = new MonitorUsecases(pool); +const monitorRepository = new MonitorRepository(pool); +const monitorJob = new MonitorUsecases(monitorRepository); +const monitorScheduler = new MonitorScheduler(monitorJob, 300000); -app.use("/", createRouter(monitorJob)); +app.use("/", createRouter(monitorJob, monitorScheduler)); -const poll = async () => { - try { - await monitorJob.checkAllProjectsHealth(); - } catch (err) { - console.error(`[Background Job Error]: ${err instanceof Error ? err.message : String(err)}`); - } finally { - setTimeout(poll, 300000); - } -}; - -void poll(); +monitorScheduler.start(); app.use((err: Error, req: Request, res: Response, _next: NextFunction) => { const status = err instanceof AppError ? err.status : 500; diff --git a/src/infrastructure/monitor-routes-http.ts b/src/infrastructure/monitor-routes-http.ts index 2ff66f6..bfdc44c 100644 --- a/src/infrastructure/monitor-routes-http.ts +++ b/src/infrastructure/monitor-routes-http.ts @@ -1,10 +1,18 @@ import { Router } from 'express'; import { MonitorController } from '../application/monitor-controller.js'; +import { MonitorScheduler } from '../application/monitor-scheduler.js'; import { MonitorUsecases } from '../application/monitor-usecases.js'; -export function createRouter(usecases: MonitorUsecases): Router { +export function createRouter(usecases: MonitorUsecases, scheduler: MonitorScheduler): Router { const router = Router(); - const controller = new MonitorController(usecases); + const controller = new MonitorController(usecases, scheduler); + router.get('/', controller.renderDashboard); + router.get('/nuevo', controller.renderAddProject); + router.post('/proyectos', controller.saveProject); + router.post('/check-all', controller.checkAllProjects); + router.post('/check/:id', controller.checkProject); + router.post('/monitor-interval', controller.updateMonitorInterval); + return router; } diff --git a/src/views/add-project.ejs b/src/views/add-project.ejs new file mode 100644 index 0000000..da94afb --- /dev/null +++ b/src/views/add-project.ejs @@ -0,0 +1,33 @@ + + + + + Nuevo Proyecto + + + +
+

Añadir Proyecto

+
+ + + + + + +
+ Volver + +
+
+
+ + \ No newline at end of file diff --git a/src/views/error.ejs b/src/views/error.ejs index 3a180a1..2785ad8 100644 --- a/src/views/error.ejs +++ b/src/views/error.ejs @@ -11,7 +11,7 @@ - <%# Vista genérica para captura de rrores mediante el middleware de Express %> + <%# Vista genérica para captura de errores mediante el middleware de Express %>

Error

<%= message %>

Volver al inicio diff --git a/src/views/index.ejs b/src/views/index.ejs index 028e84b..af1db89 100644 --- a/src/views/index.ejs +++ b/src/views/index.ejs @@ -5,52 +5,189 @@ Monitor de Salud -

Monitor de Salud

- - - - - - - - - - - <%# Iteración de la lista de proyectos inyectada de desde el controlador. %> - <% proyectos.forEach(function(p) { %> - - - - <%# La clase CSS coincide con el estado_codigo para aplicar el color correspondiente %> - - - - <% }) %> - -
ProyectoURLEstadoÚltima comprobación
<%= p.nombre %> - - <%= p.url_health %> - - <%= p.estado_codigo || 'PENDIENTE' %> - - <%# Formateo de fecha en servidor antes de renderizar %> - <%= p.fecha ? new Date(p.fecha).toLocaleString('es-ES') : '—' %> -
+

Monitor de Salud

+ +
+ + +
+ + + segundos + + +
+
+ + + + + + + + + + + + + <% proyectos.forEach(function(p) { %> + + + + + + + + <% }) %> + +
ProyectoURLEstadoUltima comprobacionAcciones
<%= p.nombre %> + + <%= p.url_health %> + + + <%= p.estado_codigo || 'PENDIENTE' %> + + <%= p.fecha ? new Date(p.fecha).toLocaleString('es-ES') : '-' %> + + +
+ +