Primer commit de los tres flujos: Raspipeso, Servidor y Gestor de semaforos
This commit is contained in:
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,540 @@
|
||||
/* =============================== BASE GLOBAL =============================== */
|
||||
|
||||
|
||||
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Segoe UI", sans-serif;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 400px;
|
||||
margin: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
#pantalla-tabla-general .container {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 10px 0 20px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
/* =============================== ENCABEZADO =============================== */
|
||||
|
||||
.header,
|
||||
.encabezado {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.titulo,
|
||||
h3 {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* =============================== PANTALLAS SPA =============================== */
|
||||
|
||||
.pantalla {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pantalla.visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* =============================== BOTONES =============================== */
|
||||
|
||||
.btn {
|
||||
padding: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn.big {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* Colores */
|
||||
.btn.yellow,
|
||||
.btn.amarillo {
|
||||
background: #f1c40f;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.btn.orange,
|
||||
.btn.naranja {
|
||||
background: #e67e22;
|
||||
}
|
||||
|
||||
.btn.green,
|
||||
.btn.verde {
|
||||
background: #28a745;
|
||||
}
|
||||
|
||||
.btn.teal,
|
||||
.btn.verde-oscuro {
|
||||
background: #049a81;
|
||||
}
|
||||
|
||||
.btn.red,
|
||||
.btn.rojo {
|
||||
background: firebrick;
|
||||
}
|
||||
|
||||
.btn.blue,
|
||||
.btn.azul {
|
||||
background: #3498db;
|
||||
}
|
||||
.btn.darkblue,
|
||||
.btn.azuloscuro {
|
||||
background: #0567a9;
|
||||
}
|
||||
.btn.aqua,
|
||||
.btn.celeste {
|
||||
background: #04fbc7;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.btn.purple,
|
||||
.btn.morado {
|
||||
background: #9b59b6;
|
||||
}
|
||||
|
||||
.btn.gray,
|
||||
.btn.gris {
|
||||
background: #707b7c;
|
||||
}
|
||||
|
||||
.btn.gold,
|
||||
.btn.mostaza {
|
||||
background: #DAB957;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
/* =============================== BOTONERAS / GRID =============================== */
|
||||
|
||||
.grid-vertical {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.grid-2col {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.botonera-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
max-width: 400px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.botonera-vertical {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
max-width: 400px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* =============================== COMPONENTES VISUALES =============================== */
|
||||
|
||||
.circle {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 20px auto;
|
||||
border-radius: 50%;
|
||||
background: #239b56;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.imagen {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
.imagen img {
|
||||
max-width: 85vw;
|
||||
max-height: 43vh;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.matricula-nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.placa {
|
||||
background: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 10px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fecha {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.camara-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-weight: bold;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.desarrollo {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* =============================== TABLA EDITABLE =============================== */
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
table-layout: fixed;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #007acc;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
td[contenteditable="true"] {
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.btn-actualizar,
|
||||
.btn-cancelar {
|
||||
padding: 12px 24px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-actualizar {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-actualizar:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
|
||||
.btn-cancelar {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-cancelar:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
/*----------------------------------------------- MODAL -------------------------------------*/
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fff;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
max-width: 300px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.modal-buttons {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/*----------------------------------------------- PANTALLA PRINCIPAL DEL TOTEM -------------------------------------*/
|
||||
.peso-section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
font-weight: bold;
|
||||
margin: 5px 0 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.peso-display {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
font-size: 44px;
|
||||
font-weight: bold;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.peso-label {
|
||||
margin-right: 10px;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.peso-valor {
|
||||
font-size: 90px;
|
||||
color: #2c3e50;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.peso-unidad {
|
||||
margin-left: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.status-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 16px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.status-line .label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-line.small {
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
}
|
||||
.led-semaforo {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
background-color: #ccc;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||
margin-left: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
.semaforo-display {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.led-semaforo.led {
|
||||
box-shadow: 0 0 12px currentColor, 0 0 3px currentColor inset;
|
||||
}
|
||||
|
||||
.etiqueta {
|
||||
min-width: 90px;
|
||||
}
|
||||
.labelMat{
|
||||
font-size: 24px;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
.labelPE {
|
||||
font-size: 18px;
|
||||
color: blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
.labelValue {
|
||||
font-size: 18px;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
#pantalla-barrera .container {
|
||||
text-align: center;
|
||||
}
|
||||
/*-------------------------------------------------- PANTALLA DE LA BARRERA ---------------------------------------------------------------------*/
|
||||
.barrera-icono {
|
||||
margin: 20px auto;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.barrera-icono img {
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------- TIPOS DE CONFIGURACION ---------------------------------------------------------------------*/
|
||||
#tipo-configuracion .parametro-row {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#tipo-configuracion input {
|
||||
flex: 1;
|
||||
padding: 6px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.parametro-row button {
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.botonera-tipo {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
/* Estilo base para la fila */
|
||||
.parametro-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-bottom: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.parametro-row input.parametro {
|
||||
flex: 1 1 50%;
|
||||
min-width: 100px;
|
||||
max-width: 300px;
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.parametro-row input.valor {
|
||||
flex: 0 0 30%;
|
||||
min-width: 60px;
|
||||
max-width: 150px;
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.parametro-row input[type="checkbox"].valor {
|
||||
flex: 0 0 30px;
|
||||
transform: scale(1.8);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.parametro-row button {
|
||||
flex: 0 0 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.parametro-row input.parametro {
|
||||
flex: 1 1 40%;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.parametro-row input.valor {
|
||||
flex: 1 1 30%;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.parametro-row input[type="checkbox"].valor {
|
||||
flex: 0 0 30px;
|
||||
/*zoom: 1.5; */
|
||||
transform: scale(1.5) ;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.parametro-row button {
|
||||
flex: 0 0 25px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------- IMAGEN INICIAL DEL SNAPSHOT ---------------------------------------------------------------------*/
|
||||
/*
|
||||
#foto {
|
||||
width: 65vw;
|
||||
height: 30vh;
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
margin: auto;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
*/
|
||||
@import url("../uibuilder/uib-brand.min.css");
|
||||
@@ -0,0 +1,317 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Interfaz Totem</title>
|
||||
|
||||
<script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
|
||||
<script src="../uibuilder/uibuilder.iife.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="./index.css">
|
||||
<script src="./index.js" defer></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- ********************************************* PANTALLA INICIAL DEL TOTEM ******************************************************* -->
|
||||
<div id="pantalla-principal" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" alt="Logo" class="logo" />
|
||||
<h1 class="titulo">Sistema de Pesaje</h1>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="peso-display">
|
||||
<span id="peso" class="peso-valor">0</span>
|
||||
<span class="peso-unidad">Kg</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="semaforo-display">
|
||||
<span id="semaforo-color" class="led-semaforo led"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="status-line"><span class="label">Matrícula:</span> <span class="labelMat" id="matricula">----</span></div>
|
||||
<div class="status-line"><span class="label">Peso Estable:</span> <span class="labelPE" id="peso-estable">----</span></div>
|
||||
<div class="status-line"><span class="label">Vial:</span> <span class="labelValue" id="vial">--</span></div>
|
||||
<div class="status-line"><span class="label">ID:</span> <span class="labelValue" id="totem-id">--</span></div>
|
||||
<div class="status-line small"><span class="label">IP LAN:</span> <span class="labelValue" id="iplan">----</span></div>
|
||||
<div class="status-line small"><span class="label">IP Supervisor:</span> <span class="labelValue" id="ipsupervisor">----</span></div>
|
||||
|
||||
<div class="botonera-grid">
|
||||
<button class="btn verde big" data-action="menu-principal">CONFIG</button>
|
||||
<button class="btn celeste big" data-action="menu-sistema">SISTEMA</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ************************************** MENU PRINCIPAL DE CONFIGURACION ******************************************* -->
|
||||
<div id="pantalla-menu-principal" class="pantalla visible">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Trypton Software</h2>
|
||||
</div>
|
||||
<h3 class="titulo">CONFIGURACIÓN GESTOR SEMAFOROS</h3>
|
||||
<hr>
|
||||
<div class="grid-vertical">
|
||||
<button class="btn blue" data-action="editar">EDITAR CONFIGURACION</button>
|
||||
<button class="btn green" data-action="aplicar">APLICAR CONFIGURACION</button>
|
||||
<!--
|
||||
<button class="btn orange" data-action="pruebas">PRUEBAS DEL SISTEMA</button>
|
||||
<button class="btn purple" data-action="otras">OTRAS ACCIONES</button>
|
||||
-->
|
||||
<button class="btn teal" data-action="salir">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ******************************************* MENU EDITAR CONFIGURACION ****************************************** -->
|
||||
<div id="pantalla-editar" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" alt="Logo" class="logo" />
|
||||
<h2>Trypton Software</h2>
|
||||
</div>
|
||||
|
||||
<h3 class="titulo">EDITAR CONFIGURACION</h3>
|
||||
<hr />
|
||||
|
||||
<div class="botonera-grid">
|
||||
<button data-action="general" class="btn amarillo">GENERAL</button>
|
||||
|
||||
<button data-action="conexion" class="btn celeste">CONEXIONES</button>
|
||||
<!--
|
||||
<button data-action="sensores" class="btn morado">SENSORES</button>
|
||||
<button data-action="mensajes" class="btn gris">MENSAJES</button>
|
||||
-->
|
||||
<button data-action="tiempos" class="btn azul">TIEMPOS</button>
|
||||
</div>
|
||||
|
||||
<div class="botonera-vertical">
|
||||
|
||||
<button data-action="salvar" class="btn verde">SALVAR MODIFICACIONES</button>
|
||||
<button data-action="ayuda" class="btn mostaza">AYUDA</button>
|
||||
<button data-action="cancelar" class="btn verde-oscuro">CANCELAR Y SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ****************************************MENU PRUEBAS DEL SISTEMA ****************************************** -->
|
||||
<div id="pantalla-pruebas" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Trypton Software</h2>
|
||||
</div>
|
||||
<h3 class="titulo">PRUEBAS DEL TOTEM</h3>
|
||||
<hr>
|
||||
<div class="grid-vertical">
|
||||
<button class="btn yellow" data-action="semaforo">ENCENDER SEMAFORO</button>
|
||||
<button class="btn aqua" data-action="barrera">ACTIVAR BARRERA</button>
|
||||
<button class="btn orange" data-action="snapshot">PEDIR SNAPSHOT</button>
|
||||
<button class="btn green" data-action="escuchar">ESCUCHAR CAMARA</button>
|
||||
<button class="btn teal" data-action="regresar">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- -------------------------------------- MENU OTRAS ACCIONES --------------------------------------------------- -->
|
||||
<div id="pantalla-otras" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Trypton Software</h2>
|
||||
</div>
|
||||
<h3 class="titulo">OTRAS ACCIONES</h3>
|
||||
<hr>
|
||||
<div class="desarrollo">
|
||||
<h3 style="color:#2e86c1;">EN DESARROLLO</h3>
|
||||
</div>
|
||||
<div class="grid-vertical">
|
||||
<button class="btn blue" data-action="enviar">ENVIAR SNAPSHOT</button>
|
||||
<button class="btn aqua" data-action="reboot">REBOOT RPi</button>
|
||||
<button class="btn red" data-action="apagar">APAGAR RPi</button>
|
||||
<button class="btn teal" data-action="regresar">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- -------------------------------------- PRUEBA DEL SEMAFORO --------------------------------------------------- -->
|
||||
<div id="pantalla-semaforo" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Trypton Software</h2>
|
||||
</div>
|
||||
<h3 class="titulo">PRUEBA DEL SEMAFORO</h3>
|
||||
<hr>
|
||||
<div class="circle" id="estado"></div>
|
||||
<div class="grid-2col">
|
||||
<button class="btn red" data-action="semaforo_on">ON</button>
|
||||
<button class="btn green" data-action="semaforo_off">OFF</button>
|
||||
</div>
|
||||
<button class="btn teal big" data-action="salir-semaforo">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- -------------------------------------- PANTALLA DE SNAPSHOT DE LA CAMARA -------------------------------------------------- -->
|
||||
<div id="pantalla-snapshot" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Snapshot Recibido</h2>
|
||||
</div>
|
||||
<div class="camara-row">
|
||||
<span>Camara: <strong id="camara">---</strong></span>
|
||||
</div>
|
||||
<div class="imagen"><img id="foto" src="" alt="Foto"></div>
|
||||
<div class="matricula-nav">
|
||||
|
||||
<div class="placa" id="placa">----</div>
|
||||
|
||||
</div>
|
||||
<div class="fecha" id="fecha">----</div>
|
||||
<button class="btn teal big" data-action="salir-snapshot">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- -------------------------------------- PANTALLA DE ACTIVACION DE LA BARRERA -------------------------------------------------- -->
|
||||
<div id="pantalla-barrera" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>ACTIVACION DE BARRERA</h2>
|
||||
</div>
|
||||
<!-- ICONO BARRERA -->
|
||||
<div class="barrera-icono" id="barrera-icono">
|
||||
<img id="icono-barrera" src="/barrera_cerrada.png" alt="Barrera" />
|
||||
</div>
|
||||
|
||||
<!-- BOTONES -->
|
||||
<div class="botonera-vertical">
|
||||
<button class="btn verde big" data-action="activar-barrera">ACTIVAR BARRERA</button>
|
||||
<button class="btn teal big" data-action="salir-barrera">SALIR</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- -------------------------------------- PANTALLA PARA ESCUCHAR LA CAMARA -------------------------------------------------- -->
|
||||
<div id="pantalla-escuchar" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Snapshot Recibido</h2>
|
||||
</div>
|
||||
<div class="camara-row">
|
||||
<span>Camara: <strong id="camara_escuchar">---</strong></span>
|
||||
<span id="contador">0 / 0</span>
|
||||
</div>
|
||||
<div class="imagen"><img id="foto_escuchar" src="" alt="Foto"></div>
|
||||
<div class="matricula-nav">
|
||||
<button class="btn green" data-action="left"><</button>
|
||||
<div class="placa" id="placa_escuchar">----</div>
|
||||
<button class="btn blue" data-action="right">></button>
|
||||
</div>
|
||||
<div class="fecha" id="fecha_escuchar">----</div>
|
||||
<button class="btn teal big" data-action="salir-escuchar">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ------------------------------- PANTALLA DE TABLA DINAMICA PARA MOSTRAR PARAMETROS DE CONFIGURACION------------------------------------------------->
|
||||
<div id="pantalla-tabla-general" class="pantalla">
|
||||
<div class="container">
|
||||
<h2 style="text-align:center;">Parámetros del Sistema</h2>
|
||||
|
||||
<div class="button-container">
|
||||
<table id="table2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center;">Parámetro</th>
|
||||
<th style="text-align:center;">Valor</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="config-table-body">
|
||||
<!-- Se rellena dinámicamente -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<button class="custom-btn btn-actualizar" onclick="sendRow()">ACTUALIZAR</button>
|
||||
<button class="custom-btn btn-cancelar" onclick="sendCancel()">CANCELAR</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ------------------------------------- PANTALLA TIPOS DE CONFIGURACION ---------------------------------------------------- -->
|
||||
<div id="pantalla-tipos" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>Tipos de Configuración</h2>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div class="botonera-grid">
|
||||
<button class="btn blue" onclick="seleccionarTipo(1)">TIPO 1</button>
|
||||
<button class="btn orange" onclick="seleccionarTipo(2)">TIPO 2</button>
|
||||
<button class="btn yellow" onclick="seleccionarTipo(3)">TIPO 3</button>
|
||||
<button class="btn celeste" onclick="seleccionarTipo(4)">TIPO 4</button>
|
||||
<button class="btn purple" onclick="seleccionarTipo(5)">TIPO 5</button>
|
||||
<button class="btn gris" onclick="seleccionarTipo(6)">TIPO 6</button>
|
||||
|
||||
</div>
|
||||
<div class="botonera-vertical">
|
||||
<button class="btn green" id="btn-volver-tipos">REGRESAR</button>
|
||||
</div>
|
||||
<div id="tipo-configuracion" style="margin-top:20px; display:none;">
|
||||
<h3 id="titulo-tipo"></h3>
|
||||
<div id="parametros"></div>
|
||||
|
||||
<div class="botonera-tipo">
|
||||
<button id="btn-add-param" class="btn azul">+</button>
|
||||
<button class="btn verde" id="btn-guardar-tipo">Guardar</button>
|
||||
<button class="btn rojo" id="btn-cancelar-tipo">Cancelar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ------------------------------------- PANTALLA DE AYUDA ---------------------------------------------------- -->
|
||||
<div id="pantalla-ayuda" class="pantalla">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="/logo-trypton2.png" class="logo" alt="Logo">
|
||||
<h2>AYUDA</h2>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<iframe src="./ayuda.pdf" style="width:100%; height:600px; border:none;"></iframe>
|
||||
<div style="margin-top: 20px; text-align: center;">
|
||||
<button class="btn rojo" data-action="salir-ayuda">SALIR</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ------------------------------------- MODAL PARA POPUP ---------------------------------------------------- -->
|
||||
<div id="confirm-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<p id="modal-text">¿Deseas guardar los cambios?</p>
|
||||
<div class="modal-buttons">
|
||||
<button id="btn-modal-si" class="btn verde" onclick="confirmGuardar()">Sí</button>
|
||||
<button id="btn-modal-no" class="btn rojo" onclick="cancelarGuardar()">No</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,494 @@
|
||||
/* global uibuilder */
|
||||
uibuilder.start();
|
||||
|
||||
// Navegación entre pantallas
|
||||
function mostrarPantalla(id) {
|
||||
document.querySelectorAll('.pantalla').forEach(div =>
|
||||
div.classList.toggle('visible', div.id === id)
|
||||
);
|
||||
}
|
||||
let currentTopic = "";
|
||||
let result = [];
|
||||
|
||||
//****************************************************RECEPCION DE MENSAJES DESDE NODE_RED ***************************************************************** */
|
||||
|
||||
uibuilder.onChange('msg', msg => {
|
||||
if (msg.payload && msg.payload.pantalla) {
|
||||
mostrarPantalla('pantalla-' + msg.payload.pantalla);
|
||||
}
|
||||
|
||||
if (msg.semaforo) {
|
||||
document.getElementById('estado').style.backgroundColor = msg.semaforo;
|
||||
}
|
||||
if (msg.payload && msg.payload.pantalla === 'snapshot') {
|
||||
// Limpiar datos visibles
|
||||
document.getElementById('camara').textContent = '---';
|
||||
document.getElementById('placa').textContent = '----';
|
||||
document.getElementById('fecha').textContent = '----';
|
||||
// Mostrar imagen vacía
|
||||
document.getElementById('foto').src = "";
|
||||
|
||||
}
|
||||
|
||||
if (msg.payload && msg.payload.pantalla === 'escuchar' && msg.buttons != true) {
|
||||
// Limpiar datos visibles
|
||||
document.getElementById('camara_escuchar').textContent = '---';
|
||||
document.getElementById('placa_escuchar').textContent = '----';
|
||||
document.getElementById('fecha_escuchar').textContent = '----';
|
||||
document.getElementById('contador').textContent = `0 / 0`;
|
||||
// Mostrar imagen vacía
|
||||
document.getElementById('foto_escuchar').src = "";
|
||||
}
|
||||
|
||||
if (msg.hasOwnProperty("picture")) {
|
||||
//uibuilder.send({ payload: msg.payload.Picture.Plate.PlateNumber, topic: msg.payload.Picture.SnapInfo.DeviceID });
|
||||
if (msg.snapshot_cam) {
|
||||
document.getElementById('foto').src = msg.picture;
|
||||
document.getElementById('placa').textContent = msg.plate || '----';
|
||||
document.getElementById('fecha').textContent = msg.plate_time || '';
|
||||
document.getElementById('camara').textContent = msg.camera_id || '---';
|
||||
}
|
||||
|
||||
else if (msg.escuchar_cam){
|
||||
document.getElementById('foto_escuchar').src = msg.picture;
|
||||
document.getElementById('placa_escuchar').textContent = msg.plate || '----';
|
||||
document.getElementById('fecha_escuchar').textContent = msg.plate_time || '';
|
||||
document.getElementById('camara_escuchar').textContent = msg.camera_id || '---';
|
||||
const total = msg.snapshot_indexmax || 0;
|
||||
const actual = (msg.snapshot_readindex || 0) + 1;
|
||||
document.getElementById('contador').textContent = `${actual} / ${total}`;
|
||||
}
|
||||
}
|
||||
|
||||
else if (msg.payload?.pantalla === 'tipos') {
|
||||
mostrarPantalla('pantalla-tipos');
|
||||
if (msg.payload.tiposDatos) {
|
||||
tiposDatos = msg.payload.tiposDatos;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.barrera) {
|
||||
mostrarBarreraAbierta()
|
||||
}
|
||||
else{
|
||||
mostrarBarreraCerrada()
|
||||
}
|
||||
// tabla dinamica
|
||||
if (msg.topic == "general" || msg.topic == "conexion" || msg.topic == "camara" || msg.topic == "sensores" || msg.topic == "mensajes" || msg.topic == "tiempos"){
|
||||
if (!msg.tabla || !Array.isArray(msg.tabla)) return;
|
||||
|
||||
const tbody = document.getElementById('config-table-body');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
currentTopic = msg.topic || 'general';
|
||||
|
||||
msg.tabla.forEach(item => { //generamos dinamixamente la tabla que vera el usuario en el dispositivo (PC o smartphone).
|
||||
// notese que la celda 2 de cada fila es del tipo editable.
|
||||
const row = document.createElement('tr');
|
||||
|
||||
const cell1 = document.createElement('td');
|
||||
cell1.textContent = item.parametro;
|
||||
|
||||
const cell2 = document.createElement('td');
|
||||
cell2.contentEditable = true;
|
||||
//cell2.textContent = item.valor;
|
||||
cell2.textContent = formatForCell(item.valor);
|
||||
|
||||
row.appendChild(cell1);
|
||||
row.appendChild(cell2);
|
||||
|
||||
tbody.appendChild(row); // enviamos la tabla al elemento html (config-table-body)
|
||||
});
|
||||
}
|
||||
|
||||
// configuracion del pop up de notificaciones
|
||||
if (msg.modalText) {
|
||||
document.getElementById('modal-text').textContent = msg.modalText;
|
||||
|
||||
const btnSi = document.getElementById('btn-modal-si');
|
||||
const btnNo = document.getElementById('btn-modal-no');
|
||||
|
||||
if (msg.modalType === "notificacion") {
|
||||
btnSi.textContent = 'OK';
|
||||
btnNo.style.display = 'none';
|
||||
window.modalCallback = null;
|
||||
} else {
|
||||
btnSi.textContent = 'Sí';
|
||||
btnNo.style.display = 'inline-block';
|
||||
window.modalCallback = msg.modalCallback || null;
|
||||
}
|
||||
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
}
|
||||
|
||||
// ======================================== Datos para la Pantalla Principal ========================================================================
|
||||
if (msg.hasOwnProperty("peso")) document.getElementById('peso').textContent = msg.peso || 0;
|
||||
//if (msg.semaforo_color) document.getElementById('semaforo-color').style.backgroundColor = msg.semaforo_color;
|
||||
const led = document.getElementById('semaforo-color');
|
||||
if (msg.semaforo_color) {
|
||||
led.style.backgroundColor = msg.semaforo_color;
|
||||
led.classList.add('led');
|
||||
} else {
|
||||
led.style.backgroundColor = '#ccc';
|
||||
led.classList.remove('led');
|
||||
}
|
||||
if (msg.hasOwnProperty("matricula")) document.getElementById('matricula').textContent = msg.matricula;
|
||||
if (msg.hasOwnProperty("peso_estable_flag")) document.getElementById('peso-estable').textContent = msg.peso_estable_flag ? 'SI' : 'NO';
|
||||
if (msg.hasOwnProperty("vial")) document.getElementById('vial').textContent = msg.vial;
|
||||
if (msg.hasOwnProperty("totem_id")) document.getElementById('totem-id').textContent = msg.totem_id;
|
||||
if (msg.hasOwnProperty("iplan")) document.getElementById('iplan').textContent = msg.iplan;
|
||||
if (msg.hasOwnProperty("ipsupervisor")) document.getElementById('ipsupervisor').textContent = msg.ipsupervisor;
|
||||
|
||||
});
|
||||
|
||||
//****************************************************************************************************************************************************** */
|
||||
// Detectar clics en botones
|
||||
document.addEventListener('click', ev => {
|
||||
if (ev.target.matches('button[data-action]')) {
|
||||
const action = ev.target.getAttribute('data-action');
|
||||
console.log('⏺ Acción botón:', action);
|
||||
uibuilder.send({ payload: { seccion: action } });
|
||||
}
|
||||
});
|
||||
|
||||
// Mostrar pantalla tipos
|
||||
document.addEventListener('click', ev => {
|
||||
if (ev.target.matches('button[data-action="tipos"]')) {
|
||||
mostrarPantalla('pantalla-tipos');
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('btn-add-param').addEventListener('click', agregarParametro);
|
||||
document.getElementById('btn-guardar-tipo').addEventListener('click', () => {
|
||||
window.modalCallback = guardarTipo;
|
||||
document.getElementById('modal-text').textContent = `¿Deseas guardar los cambios de Tipo ${tipoActual}?`;
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
});
|
||||
|
||||
document.getElementById('btn-cancelar-tipo').addEventListener('click', () => {
|
||||
uibuilder.send({ payload: { accion: "cancelar_tipo", tipo: tipoActual } });
|
||||
volverATipos();
|
||||
});
|
||||
|
||||
document.getElementById('btn-volver-tipos').addEventListener('click', () => {
|
||||
volverATipos(); // esto limpia la tabla con los parametros del Tipo en el que estemos
|
||||
uibuilder.send({ payload: { seccion: "volver_tipos" } });
|
||||
});
|
||||
|
||||
let tipoActual = null;
|
||||
let tiposDatos = {}; // aquí se guarda la configuración temporal
|
||||
|
||||
//******************************************* FUNCIONES ******************************************************** */
|
||||
// Funcion para asegurar que se vea el array en la pantalla de configuracion. Si no se hace esto se ve los numeros sin los []
|
||||
// y luego al pasarlo al archivo no se puede identificar si es un array
|
||||
function formatForCell(v) {
|
||||
if (v === null || v === undefined) return '';
|
||||
if (typeof v === 'object') return JSON.stringify(v); // arrays y objetos
|
||||
return String(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Acciones a partir de botones en html
|
||||
function sendRow() {// Aqui llega cuando se hace click en el boton Actualizar de las tablas dinamicas
|
||||
// recoge el contenido de la tabla en ese instante y saca Notificacion de guardar con opcion Si o No
|
||||
const rows = document.querySelectorAll('#config-table-body tr');
|
||||
result = []; // inicializamos result para poner exactamente la tabla actual
|
||||
|
||||
/*
|
||||
rows.forEach(row => {
|
||||
const parametro = row.cells[0].textContent.trim();
|
||||
let valor = row.cells[1].textContent.trim();
|
||||
|
||||
// normaliza a booleano si corresponde
|
||||
if (valor === "true") valor = true;
|
||||
if (valor === "false") valor = false;
|
||||
|
||||
result.push({ parametro, valor });
|
||||
});
|
||||
*/
|
||||
//Modificacion de la lectura de la tabla para asegurar que los numeros son mantenidos como numeros y no como texto
|
||||
// al igual que los valores booleanos.
|
||||
rows.forEach(row => {
|
||||
const parametro = row.cells[0].textContent.trim();
|
||||
let valor = row.cells[1].textContent.trim();
|
||||
// 1) Boolean
|
||||
if (/^(true|false)$/i.test(valor)) {
|
||||
valor = valor.toLowerCase() === "true";
|
||||
|
||||
// 2) JSON Array u Object: "[3,1,2]" o {"a":1}
|
||||
} else if (
|
||||
(valor.startsWith("[") && valor.endsWith("]")) ||
|
||||
(valor.startsWith("{") && valor.endsWith("}"))
|
||||
) {
|
||||
try {
|
||||
valor = JSON.parse(valor);
|
||||
|
||||
// Opcional: si es array, intenta convertir strings numéricas a números
|
||||
if (Array.isArray(valor)) {
|
||||
valor = valor.map(v => {
|
||||
if (typeof v === "string" && /^-?\d+$/.test(v)) return parseInt(v, 10);
|
||||
if (typeof v === "string" && /^-?\d+\.\d+$/.test(v)) return parseFloat(v);
|
||||
return v;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// Si no es JSON válido, se queda como string
|
||||
}
|
||||
|
||||
// 3) Int
|
||||
} else if (/^-?\d+$/.test(valor)) {
|
||||
valor = parseInt(valor, 10);
|
||||
|
||||
// // 4) Float
|
||||
} else if (/^-?\d+\.\d+$/.test(valor)) {
|
||||
valor = parseFloat(valor);
|
||||
}
|
||||
|
||||
result.push({ parametro, valor });
|
||||
});
|
||||
|
||||
|
||||
// Mostramos directamente la confirmación y definimos la callback. "topic" contiene el nombre de la tabla donde se guardan los valores que vienen en "result"
|
||||
mostrarConfirmacion("¿Deseas guardar los cambios?", () => {
|
||||
uibuilder.send({
|
||||
payload: { table: result, seccion: "respuesta" },
|
||||
topic: currentTopic,
|
||||
origen: "actualizar"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function sendCancel() { // boton Cancelar de las tablas dinamicas
|
||||
uibuilder.send({ payload: {seccion:'cancel-table'}, topic: currentTopic });
|
||||
}
|
||||
|
||||
function confirmGuardar() { // Respuesta Afirmativa del Modal de tabla dinamica
|
||||
document.getElementById('confirm-modal').style.display = 'none';
|
||||
|
||||
if (typeof window.modalCallback === 'function') {
|
||||
const cb = window.modalCallback;
|
||||
window.modalCallback = null; // limpia para la siguiente vez
|
||||
cb(); // ejecuta
|
||||
} else if (typeof window.modalCallback === 'string') {
|
||||
uibuilder.send({ payload: { table: result }, modalCallback: window.modalCallback, origen: "modal" });
|
||||
}
|
||||
}
|
||||
/*
|
||||
function confirmGuardar() { // Respuesta Afirmativa del Modal de tabla dinamica
|
||||
uibuilder.send({ payload: { table: result }, topic: currentTopic, origen: "modal-tabla" });
|
||||
document.getElementById('confirm-modal').style.display = 'none';
|
||||
}
|
||||
*/
|
||||
|
||||
function cancelarGuardar() { // Respuesta Negativa del Modal de tabla dinamica
|
||||
result = [];
|
||||
document.getElementById('confirm-modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Funciones para icono barrera
|
||||
function mostrarBarreraAbierta() {
|
||||
const icono = document.getElementById('icono-barrera');
|
||||
icono.src = "/barrera_abierta.png";
|
||||
/*
|
||||
setTimeout(() => {
|
||||
mostrarBarreraCerrada();
|
||||
}, 1000); // 1 segundo
|
||||
*/
|
||||
}
|
||||
|
||||
function mostrarBarreraCerrada() {
|
||||
const icono = document.getElementById('icono-barrera');
|
||||
icono.src = "/barrera_cerrada.png";
|
||||
}
|
||||
|
||||
//************************* FUNCIONES DE TIPOS DE CONFIGURACION *****************************/
|
||||
function seleccionarTipo(n) {
|
||||
tipoActual = n;
|
||||
document.getElementById('titulo-tipo').textContent = `TIPO ${n}`;
|
||||
document.getElementById('tipo-configuracion').style.display = 'block';
|
||||
|
||||
const contenedor = document.getElementById('parametros');
|
||||
contenedor.innerHTML = '';
|
||||
|
||||
const datos = tiposDatos[n] || []; // ya es un array
|
||||
|
||||
datos.forEach(d => {
|
||||
const row = crearFilaParametro(d.parametro, d.valor);
|
||||
contenedor.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function agregarParametro() {
|
||||
const contenedor = document.getElementById('parametros');
|
||||
if (contenedor.children.length >= 8) return;
|
||||
|
||||
const row = crearFilaParametro('', '');
|
||||
contenedor.appendChild(row);
|
||||
}
|
||||
function crearFilaParametro(parametro, valor) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'parametro-row';
|
||||
|
||||
// Input para el nombre del parámetro
|
||||
const inputParam = document.createElement('input');
|
||||
inputParam.placeholder = 'Parámetro';
|
||||
inputParam.value = parametro;
|
||||
|
||||
// Input para el valor: checkbox o texto
|
||||
let inputValor;
|
||||
if (valor === true || valor === false || valor === "true" || valor === "false") {
|
||||
inputValor = document.createElement('input');
|
||||
inputValor.type = 'checkbox';
|
||||
inputValor.checked = (valor === true || valor === "true");
|
||||
} else {
|
||||
inputValor = document.createElement('input');
|
||||
inputValor.placeholder = 'Valor';
|
||||
inputValor.value = valor;
|
||||
}
|
||||
inputParam.classList.add('parametro');
|
||||
inputValor.classList.add('valor');
|
||||
// Botón para eliminar la fila
|
||||
const btnDelete = document.createElement('button');
|
||||
btnDelete.textContent = '-';
|
||||
btnDelete.className = 'btn rojo';
|
||||
btnDelete.style.flex = '0 0 40px';
|
||||
btnDelete.style.width = '40px';
|
||||
btnDelete.style.height = '40px';
|
||||
btnDelete.style.marginLeft = '4px';
|
||||
btnDelete.style.zIndex = '1';
|
||||
|
||||
btnDelete.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
window.modalCallback = () => div.remove();
|
||||
|
||||
document.getElementById('modal-text').textContent = '¿Deseas eliminar este parámetro?';
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
return false;
|
||||
});
|
||||
|
||||
// Añadir los elementos a la fila
|
||||
div.appendChild(inputParam);
|
||||
div.appendChild(inputValor);
|
||||
div.appendChild(btnDelete);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
function crearFilaParametro_viejo(parametro, valor) { // Crea un nuevo elemento en la tabla del Tipo que estemos trabajando con dos campos y un boton de borrado
|
||||
const div = document.createElement('div');
|
||||
div.className = 'parametro-row';
|
||||
|
||||
const inputParam = document.createElement('input');
|
||||
inputParam.placeholder = 'Parámetro';
|
||||
inputParam.value = parametro;
|
||||
|
||||
const inputValor = document.createElement('input');
|
||||
inputValor.placeholder = 'Valor';
|
||||
inputValor.value = valor;
|
||||
|
||||
const btnDelete = document.createElement('button');
|
||||
btnDelete.textContent = '-';
|
||||
btnDelete.className = 'btn rojo';
|
||||
btnDelete.style.width = '40px';
|
||||
btnDelete.style.height = '40px';
|
||||
btnDelete.onclick = () => { // gestion de la alerta para el borrado, haciendo uso del modal que tenemos en html
|
||||
window.modalCallback = () => div.remove();
|
||||
|
||||
document.getElementById('modal-text').textContent = '¿Deseas eliminar este parámetro?';
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
};
|
||||
|
||||
div.appendChild(inputParam);
|
||||
div.appendChild(inputValor);
|
||||
div.appendChild(btnDelete);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
function guardarTipo() {
|
||||
const contenedor = document.getElementById('parametros');
|
||||
const filas = contenedor.querySelectorAll('.parametro-row');
|
||||
const datos = [];
|
||||
filas.forEach(fila => {
|
||||
const [param, val] = fila.querySelectorAll('input');
|
||||
let valor;
|
||||
if (val.type === 'checkbox') {
|
||||
valor = val.checked;
|
||||
} else {
|
||||
valor = val.value.trim();
|
||||
}
|
||||
if (param.value.trim()) {
|
||||
datos.push({ parametro: param.value.trim(), valor });
|
||||
}
|
||||
});
|
||||
/*
|
||||
filas.forEach(fila => {
|
||||
const [param, val] = fila.querySelectorAll('input');
|
||||
if (param.value.trim()) {
|
||||
datos.push({ parametro: param.value.trim(), valor: val.value.trim() });
|
||||
}
|
||||
});
|
||||
*/
|
||||
tiposDatos[tipoActual] = datos;
|
||||
|
||||
uibuilder.send({ payload: { tipo: tipoActual, datos }, topic: "tipoconfig" }); // el topic nos sirve para seleccionar en el proximo nodo la funcion de guardar los datos
|
||||
|
||||
volverATipos(); // 🔷 salimos de la pantalla del tipo actual
|
||||
}
|
||||
|
||||
function volverATipos() {
|
||||
document.getElementById('tipo-configuracion').style.display = 'none';
|
||||
tipoActual = null;
|
||||
}
|
||||
|
||||
//==========================================FUNCIONES PARA MANEJAR LAS NOTIFICACIONES ======================================================
|
||||
function mostrarConfirmacion(texto, callback) {
|
||||
document.getElementById('modal-text').textContent = texto;
|
||||
|
||||
// Restablece estado normal del modal
|
||||
const btnSi = document.getElementById('btn-modal-si');
|
||||
const btnNo = document.getElementById('btn-modal-no');
|
||||
|
||||
btnSi.textContent = 'Sí';
|
||||
btnNo.style.display = 'inline-block';
|
||||
|
||||
window.modalCallback = callback;
|
||||
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
}
|
||||
|
||||
function mostrarNotificacion(texto) {
|
||||
document.getElementById('modal-text').textContent = texto;
|
||||
|
||||
const btnSi = document.getElementById('btn-modal-si');
|
||||
const btnNo = document.getElementById('btn-modal-no');
|
||||
|
||||
btnSi.textContent = 'OK';
|
||||
btnNo.style.display = 'none';
|
||||
|
||||
window.modalCallback = null;
|
||||
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Cuando necesitemos un modal clásico (Sí/No), por ejemplo para confirmar actualización:
|
||||
|
||||
mostrarConfirmacion("¿Deseas guardar los cambios?", () => {
|
||||
uibuilder.send({ payload: { table: result, seccion:"respuesta" }, topic: currentTopic, origen: "actualizar" });
|
||||
});
|
||||
|
||||
Cuando necesitemos simplemente notificar un error:
|
||||
|
||||
mostrarNotificacion("La IP introducida es inválida, por favor corrígela.");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user