mirror of
https://github.com/KeymonSoft/jRDC-MultiDB-Hikari.git
synced 2026-04-17 21:06:23 +00:00
Commit inicial
This commit is contained in:
29
Files/config.DB2.properties
Normal file
29
Files/config.DB2.properties
Normal file
@@ -0,0 +1,29 @@
|
||||
#Lines starting with '#' are comments.
|
||||
#Backslash character at the end of line means that the command continues in the next line.
|
||||
|
||||
#DATABASE CONFIGURATION
|
||||
DriverClass=com.mysql.jdbc.Driver
|
||||
JdbcUrl=jdbc:mysql://localhost/$DB$?characterEncoding=utf8
|
||||
User=root
|
||||
Password=
|
||||
#Java server port
|
||||
ServerPort=17178
|
||||
|
||||
#example of MS SQL Server configuration:
|
||||
#DriverClass=net.sourceforge.jtds.jdbc.Driver
|
||||
#JdbcUrl=jdbc:jtds:sqlserver://<server address>/<database>
|
||||
|
||||
#example of postegres configuration:
|
||||
#JdbcUrl=jdbc:postgresql://localhost/test
|
||||
#DriverClass=org.postgresql.Driver
|
||||
|
||||
#SQL COMMANDS
|
||||
sql.create_table=CREATE TABLE IF NOT EXISTS animals (\
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,\
|
||||
name CHAR(30) NOT NULL,\
|
||||
image BLOB)
|
||||
sql.insert_animal=INSERT INTO animals VALUES (null, ?,?)
|
||||
sql.select_animal=SELECT name, image, id FROM animals WHERE id = ?;
|
||||
sql.create_table=CREATE TABLE article (col1 numeric(10,4) ,col2 text);
|
||||
sql.select=select * from article
|
||||
sql.insert=INSERT INTO article VALUES(?, ?)
|
||||
29
Files/config.DB3.properties
Normal file
29
Files/config.DB3.properties
Normal file
@@ -0,0 +1,29 @@
|
||||
#Lines starting with '#' are comments.
|
||||
#Backslash character at the end of line means that the command continues in the next line.
|
||||
|
||||
#DATABASE CONFIGURATION
|
||||
DriverClass=com.mysql.jdbc.Driver
|
||||
JdbcUrl=jdbc:mysql://localhost/$DB$?characterEncoding=utf8
|
||||
User=root
|
||||
Password=
|
||||
#Java server port
|
||||
ServerPort=17178
|
||||
|
||||
#example of MS SQL Server configuration:
|
||||
#DriverClass=net.sourceforge.jtds.jdbc.Driver
|
||||
#JdbcUrl=jdbc:jtds:sqlserver://<server address>/<database>
|
||||
|
||||
#example of postegres configuration:
|
||||
#JdbcUrl=jdbc:postgresql://localhost/test
|
||||
#DriverClass=org.postgresql.Driver
|
||||
|
||||
#SQL COMMANDS
|
||||
sql.create_table=CREATE TABLE IF NOT EXISTS animals (\
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,\
|
||||
name CHAR(30) NOT NULL,\
|
||||
image BLOB)
|
||||
sql.insert_animal=INSERT INTO animals VALUES (null, ?,?)
|
||||
sql.select_animal=SELECT name, image, id FROM animals WHERE id = ?;
|
||||
sql.create_table=CREATE TABLE article (col1 numeric(10,4) ,col2 text);
|
||||
sql.select=select * from article
|
||||
sql.insert=INSERT INTO article VALUES(?, ?)
|
||||
29
Files/config.DB4.properties
Normal file
29
Files/config.DB4.properties
Normal file
@@ -0,0 +1,29 @@
|
||||
#Lines starting with '#' are comments.
|
||||
#Backslash character at the end of line means that the command continues in the next line.
|
||||
|
||||
#DATABASE CONFIGURATION
|
||||
DriverClass=com.mysql.jdbc.Driver
|
||||
JdbcUrl=jdbc:mysql://localhost/$DB$?characterEncoding=utf8
|
||||
User=root
|
||||
Password=
|
||||
#Java server port
|
||||
ServerPort=17178
|
||||
|
||||
#example of MS SQL Server configuration:
|
||||
#DriverClass=net.sourceforge.jtds.jdbc.Driver
|
||||
#JdbcUrl=jdbc:jtds:sqlserver://<server address>/<database>
|
||||
|
||||
#example of postegres configuration:
|
||||
#JdbcUrl=jdbc:postgresql://localhost/test
|
||||
#DriverClass=org.postgresql.Driver
|
||||
|
||||
#SQL COMMANDS
|
||||
sql.create_table=CREATE TABLE IF NOT EXISTS animals (\
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,\
|
||||
name CHAR(30) NOT NULL,\
|
||||
image BLOB)
|
||||
sql.insert_animal=INSERT INTO animals VALUES (null, ?,?)
|
||||
sql.select_animal=SELECT name, image, id FROM animals WHERE id = ?;
|
||||
sql.create_table=CREATE TABLE article (col1 numeric(10,4) ,col2 text);
|
||||
sql.select=select * from article
|
||||
sql.insert=INSERT INTO article VALUES(?, ?)
|
||||
29
Files/config.properties
Normal file
29
Files/config.properties
Normal file
@@ -0,0 +1,29 @@
|
||||
#Lines starting with '#' are comments.
|
||||
#Backslash character at the end of line means that the command continues in the next line.
|
||||
|
||||
#DATABASE CONFIGURATION
|
||||
DriverClass=com.mysql.jdbc.Driver
|
||||
JdbcUrl=jdbc:mysql://localhost/$DB$?characterEncoding=utf8
|
||||
User=root
|
||||
Password=
|
||||
#Java server port
|
||||
ServerPort=17178
|
||||
|
||||
#example of MS SQL Server configuration:
|
||||
#DriverClass=net.sourceforge.jtds.jdbc.Driver
|
||||
#JdbcUrl=jdbc:jtds:sqlserver://<server address>/<database>
|
||||
|
||||
#example of postegres configuration:
|
||||
#JdbcUrl=jdbc:postgresql://localhost/test
|
||||
#DriverClass=org.postgresql.Driver
|
||||
|
||||
#SQL COMMANDS
|
||||
sql.create_table=CREATE TABLE IF NOT EXISTS animals (\
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,\
|
||||
name CHAR(30) NOT NULL,\
|
||||
image BLOB)
|
||||
sql.insert_animal=INSERT INTO animals VALUES (null, ?,?)
|
||||
sql.select_animal=SELECT name, image, id FROM animals WHERE id = ?;
|
||||
sql.create_table=CREATE TABLE article (col1 numeric(10,4) ,col2 text);
|
||||
sql.select=select * from article
|
||||
sql.insert=INSERT INTO article VALUES(?, ?)
|
||||
9
Files/reiniciaProcesoBow.bat
Normal file
9
Files/reiniciaProcesoBow.bat
Normal file
@@ -0,0 +1,9 @@
|
||||
@rem Este script reinicia el proceso en PM2 del servidor de jRDC2
|
||||
|
||||
@rem estas lineas sirven para que el archivo bat corra en modo administrador.
|
||||
set "params=%*"
|
||||
cd /d "%~dp0" && ( if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs" ) && fsutil dirty query %systemdrive% 1>nul 2>nul || ( echo Set UAC = CreateObject^("Shell.Application"^) : UAC.ShellExecute "cmd.exe", "/k cd ""%~sdp0"" && ""%~s0"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" && "%temp%\getadmin.vbs" && exit /B )
|
||||
|
||||
pm2 restart BotSoporte_4.0
|
||||
|
||||
exit
|
||||
9
Files/reiniciaProcesoPM2.bat
Normal file
9
Files/reiniciaProcesoPM2.bat
Normal file
@@ -0,0 +1,9 @@
|
||||
@rem Este script reinicia el proceso en PM2 del servidor de jRDC2
|
||||
|
||||
@rem estas lineas sirven para que el archivo bat corra en modo administrador.
|
||||
set "params=%*"
|
||||
cd /d "%~dp0" && ( if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs" ) && fsutil dirty query %systemdrive% 1>nul 2>nul || ( echo Set UAC = CreateObject^("Shell.Application"^) : UAC.ShellExecute "cmd.exe", "/k cd ""%~sdp0"" && ""%~s0"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs" && "%temp%\getadmin.vbs" && exit /B )
|
||||
|
||||
pm2 restart jRDC-Multi
|
||||
|
||||
exit
|
||||
8
Files/start.bat
Normal file
8
Files/start.bat
Normal file
@@ -0,0 +1,8 @@
|
||||
@rem Este script mata el proceso del servidor y despues lo reinicia, necesita los archivos stop.bat y start2.bat
|
||||
|
||||
start cmd.exe /c stop.bat
|
||||
timeout 2
|
||||
|
||||
start cmd.exe /c start2.bat %1
|
||||
|
||||
exit
|
||||
3
Files/start2.bat
Normal file
3
Files/start2.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
@TITLE -== DBR Server %1 %2 ==-
|
||||
|
||||
"C:\Program Files (x86)\Java\jdk-14\bin\java.exe" -jar jRDC_Multi.jar
|
||||
1
Files/stop.bat
Normal file
1
Files/stop.bat
Normal file
@@ -0,0 +1 @@
|
||||
wmic Path win32_process Where "CommandLine Like '%%jRDC_Multi.jar%%'" Call Terminate
|
||||
21
Files/www/login.html
Normal file
21
Files/www/login.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Login jRDC Server</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f0f0; }
|
||||
form { background: white; padding: 2em; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
|
||||
input { display: block; margin-bottom: 1em; padding: 0.5em; width: 200px; }
|
||||
button { padding: 0.7em; width: 100%; border: none; background-color: #007bff; color: white; cursor: pointer; border-radius: 4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<form action="/dologin" method="post">
|
||||
<h2>Acceso al Manager</h2>
|
||||
<input type="text" name="username" placeholder="Usuario" required>
|
||||
<input type="password" name="password" placeholder="Contraseña" required>
|
||||
<button type="submit">Entrar</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
392
Files/www/manager.html
Normal file
392
Files/www/manager.html
Normal file
@@ -0,0 +1,392 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>jRDC2-Multi - Panel de Administración</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
color: #212529;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.admin-menu {
|
||||
background-color: #e9ecef;
|
||||
padding: 1.5em 2em;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
.admin-menu h2 {
|
||||
margin: 0 0 0.2em 0;
|
||||
color: #343a40;
|
||||
}
|
||||
.admin-menu p {
|
||||
margin: 0 0 1em 0;
|
||||
color: #495057;
|
||||
}
|
||||
.admin-menu a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
margin-right: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
border-right: 1px solid #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
.admin-menu a:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
.admin-menu a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.main-content {
|
||||
padding: 2em;
|
||||
}
|
||||
#output-container {
|
||||
background: #fff;
|
||||
padding: 1em;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 8px;
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
min-height: 200px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 1.5em;
|
||||
font-family: sans-serif;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 10px 12px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
thead {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
th {
|
||||
font-weight: 600;
|
||||
cursor: help;
|
||||
}
|
||||
tbody td:first-child {
|
||||
font-weight: bold;
|
||||
color: #0056b3;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* --- ESTILOS PARA EL INDICADOR SSE --- */
|
||||
.sse-status-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 1em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.sse-status {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
min-width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
.sse-connected {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
}
|
||||
.sse-disconnected {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
.sse-connecting {
|
||||
background-color: #ffc107;
|
||||
color: #212529;
|
||||
}
|
||||
.cell-update {
|
||||
animation: flash 0.7s ease-out;
|
||||
}
|
||||
@keyframes flash {
|
||||
0% {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
100% {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="admin-menu">
|
||||
<h2>Panel de Administración jRDC</h2>
|
||||
<p>Bienvenido, <strong>admin</strong></p>
|
||||
<nav id="main-nav">
|
||||
<a data-command="test">Test</a>
|
||||
<a data-command="ping">Ping</a>
|
||||
<a data-command="reload">Reload</a>
|
||||
<a data-command="slowqueries">Queries Lentas</a>
|
||||
<a data-command="getstats">Estadísticas Pool</a>
|
||||
<a data-command="rpm2">Reiniciar (pm2)</a>
|
||||
<a data-command="reviveBow">Revive Bow</a>
|
||||
<a data-command="getconfiginfo">Info</a>
|
||||
</nav>
|
||||
<div class="sse-status-container">
|
||||
<span>Estado de Estadísticas en Tiempo Real:</span>
|
||||
<span id="sse-status" class="sse-status sse-disconnected"
|
||||
>Desconectado</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<h1 id="content-title">Bienvenido</h1>
|
||||
<div id="output-container">
|
||||
<p style="font-family: sans-serif">
|
||||
Selecciona una opción del menú para comenzar.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const outputContainer = document.getElementById("output-container");
|
||||
const contentTitle = document.getElementById("content-title");
|
||||
const sseStatus = document.getElementById("sse-status");
|
||||
let sseConnection = null;
|
||||
|
||||
// --- CONFIGURACIÓN PARA LA TABLA DE ESTADÍSTICAS ---
|
||||
const COLUMN_ORDER = [
|
||||
"InitialPoolSize",
|
||||
"MinPoolSize",
|
||||
"MaxPoolSize",
|
||||
"AcquireIncrement",
|
||||
"TotalConnections",
|
||||
"BusyConnections",
|
||||
"IdleConnections",
|
||||
"CheckoutTimeout",
|
||||
"MaxIdleTime",
|
||||
"MaxConnectionAge",
|
||||
];
|
||||
const HEADER_TOOLTIPS = {
|
||||
InitialPoolSize:
|
||||
"Número de conexiones que el pool intenta adquirir al arrancar.",
|
||||
MinPoolSize: "Número mínimo de conexiones que el pool mantendrá.",
|
||||
MaxPoolSize: "Número máximo de conexiones que el pool puede mantener.",
|
||||
AcquireIncrement:
|
||||
"Número de conexiones a adquirir cuando el pool se queda sin conexiones.",
|
||||
TotalConnections: "Número total de conexiones (ocupadas + libres).",
|
||||
BusyConnections: "Número de conexiones activamente en uso.",
|
||||
IdleConnections: "Número de conexiones disponibles en el pool.",
|
||||
CheckoutTimeout: "Tiempo máximo de espera por una conexión (ms).",
|
||||
MaxIdleTime:
|
||||
"Tiempo máximo que una conexión puede estar inactiva (segundos).",
|
||||
MaxConnectionAge: "Tiempo máximo de vida de una conexión (segundos).",
|
||||
};
|
||||
|
||||
// --- MANEJO DE LA CONEXIÓN SSE ---
|
||||
|
||||
function connectSSE() {
|
||||
if (sseConnection && sseConnection.readyState !== EventSource.CLOSED) {
|
||||
return; // Ya está conectado o conectando
|
||||
}
|
||||
|
||||
outputContainer.innerHTML =
|
||||
'<p style="font-family: sans-serif;">Esperando datos del pool de conexiones...</p>';
|
||||
updateSSEStatus("connecting");
|
||||
|
||||
// La ruta debe coincidir con la que registraste en srvr.AddHandler
|
||||
const SSE_ENDPOINT = "/stats-stream";
|
||||
sseConnection = new EventSource(SSE_ENDPOINT);
|
||||
|
||||
sseConnection.onopen = () => {
|
||||
console.log("Conexión SSE establecida.");
|
||||
updateSSEStatus("connected");
|
||||
};
|
||||
|
||||
// Escucha el evento específico "stats_update"
|
||||
sseConnection.addEventListener("stats_update", (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
renderOrUpdateStatsTable(data);
|
||||
} catch (e) {
|
||||
console.error("Error al parsear datos SSE:", e);
|
||||
}
|
||||
});
|
||||
|
||||
sseConnection.onerror = () => {
|
||||
console.error("Error en la conexión SSE. Reintentando...");
|
||||
updateSSEStatus("disconnected");
|
||||
sseConnection.close();
|
||||
// El navegador reintentará automáticamente la conexión
|
||||
};
|
||||
}
|
||||
|
||||
function disconnectSSE() {
|
||||
if (sseConnection) {
|
||||
sseConnection.close();
|
||||
sseConnection = null;
|
||||
console.log("Conexión SSE cerrada.");
|
||||
updateSSEStatus("disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
function updateSSEStatus(status) {
|
||||
switch (status) {
|
||||
case "connected":
|
||||
sseStatus.textContent = "Conectado";
|
||||
sseStatus.className = "sse-status sse-connected";
|
||||
break;
|
||||
case "connecting":
|
||||
sseStatus.textContent = "Conectando";
|
||||
sseStatus.className = "sse-status sse-connecting";
|
||||
break;
|
||||
case "disconnected":
|
||||
sseStatus.textContent = "Desconectado";
|
||||
sseStatus.className = "sse-status sse-disconnected";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// --- RENDERIZADO Y ACTUALIZACIÓN DE LA TABLA ---
|
||||
|
||||
function renderOrUpdateStatsTable(data) {
|
||||
const table = document.getElementById("stats-table");
|
||||
// Si la tabla no existe, la crea
|
||||
if (!table) {
|
||||
outputContainer.innerHTML = createStatsTableHTML(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Si la tabla ya existe, solo actualiza las celdas
|
||||
for (const dbKey in data) {
|
||||
const poolData = data[dbKey];
|
||||
COLUMN_ORDER.forEach((metric) => {
|
||||
const cell = document.getElementById(`${dbKey}_${metric}`);
|
||||
if (cell && cell.textContent != poolData[metric]) {
|
||||
cell.textContent = poolData[metric];
|
||||
cell.classList.add("cell-update");
|
||||
setTimeout(() => cell.classList.remove("cell-update"), 700);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createStatsTableHTML(data) {
|
||||
let tableHtml = `<table id="stats-table"><thead><tr><th title="Nombre de la Base de Datos">DB Key</th>`;
|
||||
COLUMN_ORDER.forEach((key) => {
|
||||
tableHtml += `<th title="${HEADER_TOOLTIPS[key] || ""}">${key}</th>`;
|
||||
});
|
||||
tableHtml += `</tr></thead><tbody>`;
|
||||
for (const dbKey in data) {
|
||||
const poolData = data[dbKey];
|
||||
tableHtml += `<tr><td>${dbKey}</td>`;
|
||||
COLUMN_ORDER.forEach((metric) => {
|
||||
// Se añade un ID único a cada celda: "DB1_TotalConnections"
|
||||
tableHtml += `<td id="${dbKey}_${metric}">${
|
||||
poolData[metric] ?? "N/A"
|
||||
}</td>`;
|
||||
});
|
||||
tableHtml += `</tr>`;
|
||||
}
|
||||
tableHtml += `</tbody></table>`;
|
||||
return tableHtml;
|
||||
}
|
||||
|
||||
// --- MANEJO DE COMANDOS ESTÁTICOS (SIN CAMBIOS) ---
|
||||
|
||||
async function loadStaticContent(command) {
|
||||
contentTitle.textContent = `Resultado del Comando: '${command}'`;
|
||||
outputContainer.innerHTML = "Cargando...";
|
||||
try {
|
||||
const response = await fetch(`/manager?command=${command}`);
|
||||
const responseText = await response.text();
|
||||
if (!response.ok)
|
||||
throw new Error(
|
||||
`Error del servidor (${response.status}): ${responseText}`
|
||||
);
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (contentType && contentType.includes("application/json")) {
|
||||
const data = JSON.parse(responseText);
|
||||
if (command === "slowqueries") {
|
||||
outputContainer.innerHTML = data.message
|
||||
? `<p>${data.message}</p>`
|
||||
: createTableFromJSON(data.data);
|
||||
} else {
|
||||
outputContainer.textContent = JSON.stringify(data, null, 2);
|
||||
}
|
||||
} else {
|
||||
outputContainer.textContent = responseText;
|
||||
}
|
||||
} catch (error) {
|
||||
outputContainer.textContent = `Error al procesar la respuesta:\n${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
function createTableFromJSON(data) {
|
||||
if (!data || data.length === 0)
|
||||
return "<p>No se encontraron queries lentas.</p>";
|
||||
const headers = Object.keys(data[0]);
|
||||
let table = "<table><thead><tr>";
|
||||
headers.forEach((h) => (table += `<th>${h.replace(/_/g, " ")}</th>`));
|
||||
table += "</tr></thead><tbody>";
|
||||
data.forEach((row) => {
|
||||
table += "<tr>";
|
||||
headers.forEach((h) => (table += `<td>${row[h]}</td>`));
|
||||
table += "</tr>";
|
||||
});
|
||||
table += "</tbody></table>";
|
||||
return table;
|
||||
}
|
||||
|
||||
// --- EVENT LISTENER PRINCIPAL ---
|
||||
|
||||
document.getElementById("main-nav").addEventListener("click", (event) => {
|
||||
if (event.target.tagName === "A") {
|
||||
const command = event.target.dataset.command;
|
||||
if (!command) return;
|
||||
|
||||
if (command === "reload") {
|
||||
// Pedimos al usuario la DB Key. Si la deja vacía, se asume recarga total.
|
||||
const dbKey = prompt(
|
||||
"Ingrese la llave de la DB a recargar (ej: DB2, DB3). Deje vacío para recargar TODAS:",
|
||||
""
|
||||
);
|
||||
if (dbKey === null) {
|
||||
// El usuario presionó Cancelar o cerró la ventana. NO HACER NADA.
|
||||
outputContainer.textContent = "Recarga cancelada por el usuario.";
|
||||
contentTitle.textContent = "Administración";
|
||||
return;
|
||||
}
|
||||
let finalCommand = "reload";
|
||||
if (dbKey && dbKey.trim() !== "") {
|
||||
// Si el usuario especificó una DB (ej. DB2), construimos el comando con el parámetro 'db'.
|
||||
const key = dbKey.toUpperCase().trim();
|
||||
finalCommand = `reload&db=${key}`;
|
||||
outputContainer.innerHTML = `<p style="font-family: sans-serif;">Intentando recargar: <b>${key}</b> (Hot-Swap)...</p>`;
|
||||
} else {
|
||||
// Recarga total.
|
||||
outputContainer.innerHTML = `<p style="font-family: sans-serif;">Intentando recargar: <b>TODAS</b> (Hot-Swap)...</p>`;
|
||||
}
|
||||
disconnectSSE();
|
||||
// Llamamos a la función loadStaticContent con el comando completo (ej: 'reload&db=DB2' o 'reload')
|
||||
loadStaticContent(finalCommand);
|
||||
} else if (command === "getstats") {
|
||||
contentTitle.textContent = `Estadísticas del Pool en Tiempo Real`;
|
||||
connectSSE();
|
||||
} else {
|
||||
// Si se selecciona cualquier otro comando, se desconecta del SSE
|
||||
disconnectSSE();
|
||||
loadStaticContent(command);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user