Compare commits
4 Commits
0d1b0ba439
...
6777bf363b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6777bf363b | ||
|
|
5221b6fb19 | ||
|
|
99264aba3d | ||
|
|
b3d6471018 |
90
README.md
90
README.md
@ -44,48 +44,6 @@ Por ello, es que decimos adaptar y desarrollar software, con licencias libres y
|
|||||||
|
|
||||||
### Nuevas características !
|
### Nuevas características !
|
||||||
|
|
||||||
|
|
||||||
#### Versión 2.0.0: (Septiembre 27, 2026)
|
|
||||||
+ Se actualiza la versión de NWJS → 0.107.0
|
|
||||||
+ Node-hid ahora no necesita nw-gyp, se actualiza la compilación
|
|
||||||
+ Se migra escritorio y web a Bootstrap 5 con Popper incluido en el bundle.
|
|
||||||
+ Se actualiza bootstrap-select a 1.14.0-beta3 y se reconstruyen selects conservando el valor para evitar opciones duplicadas.
|
|
||||||
+ Se integran DataTables 1.13.11 y Buttons 2.4.3 con estilos Bootstrap 5.
|
|
||||||
+ Se corrigen atributos, clases, rutas de imágenes y estilos de tablas/formularios.
|
|
||||||
+ Se agrega desktop:dev y test:ui (requiere un binario NW.js SDK como argumento).
|
|
||||||
+ Se actualizó RGraph 7.01 → 7.21
|
|
||||||
+ NW.js 0.117.0 centralizado en runtime.json para desarrollo y empaquetado x64.
|
|
||||||
+ Formulario compartido con controles nativos, validación y aviso de cambios sin guardar.
|
|
||||||
+ Guardado atómico y POST con confirmación; el núcleo recibe la configuración nueva.
|
|
||||||
+ Tablas y controles de estado compartidos entre escritorio y web.
|
|
||||||
+ Diseño adaptable sin zoom automático, con notificaciones ajustadas a pantallas pequeñas.
|
|
||||||
+ Estados separados para conexión, última lectura y publicación, con motivos y acciones.
|
|
||||||
+ Pruebas de configuración, interfaz y arranque aisladas de la estación real.
|
|
||||||
+ El empaquetador ARM histórico queda bloqueado: su Node/NW.js no soportan esta versión.
|
|
||||||
+ Se mejora el iconizado.
|
|
||||||
+ Se mejora el boton de guardado.
|
|
||||||
|
|
||||||
#### Versión 1.36: (Enero 10 , 2026)
|
|
||||||
+ Se incorporó recolectar por WIFI/IP.
|
|
||||||
+ Mejoras menores de estilo(ej:iconos en logs).
|
|
||||||
+ Mejoras en el empaquetador.
|
|
||||||
+ Se actualizó la funcion de registrar logs para que solo registre en el nivel parametrizado (1-9), los 0 se registran siempre.
|
|
||||||
+ Se mantiene la versión de nwjs por compatibilidad con node-hid.
|
|
||||||
+ Se incorporó la opcion para ir al sitio oficial de la red, en el menu de redes.
|
|
||||||
+ Se actualizó la versión de :
|
|
||||||
RGraph 6.20 → 7.01
|
|
||||||
bootstrap 4.5.3 → 4.6.2
|
|
||||||
express 4.21.2 → 5.1.0
|
|
||||||
forever 3.0.4 → 4.0.3
|
|
||||||
node 15.10.0 → 24.4.0
|
|
||||||
node-hid 1.3.1 → 2.2.0
|
|
||||||
nodemailer 6.10.1 → 7.0.5
|
|
||||||
terminal-kit 2.11.7 → 3.1.2
|
|
||||||
+ Se realizo un fix a la red WINDY(https://stations.windy.com/) para su publicación.
|
|
||||||
-Usuario/ID: es la API KEY del usuario.
|
|
||||||
-Password: Es numero de estaciones dada de alta en windy(ej: la primera->0, la segunda->1, la X->X).
|
|
||||||
|
|
||||||
|
|
||||||
#### Versión 1.35: (Diciembre 10, 2024)
|
#### Versión 1.35: (Diciembre 10, 2024)
|
||||||
|
|
||||||
+ Se actualizó la versión de nwjs → 0.94.0
|
+ Se actualizó la versión de nwjs → 0.94.0
|
||||||
@ -190,3 +148,51 @@ Si deseas realizar consultas, sugerencias o simplemente tenes alguna duda sobre
|
|||||||
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
[](https://www.gugler.com.ar)[](http://fcyt.uader.edu.ar/web/)
|
[](https://www.gugler.com.ar)[](http://fcyt.uader.edu.ar/web/)
|
||||||
|
|
||||||
|
|
||||||
|
## Desarrollo y pruebas de la interfaz
|
||||||
|
|
||||||
|
Usar Node.js 20 o posterior (las pruebas se ejecutaron con Node.js 24 y NW.js 0.117.0).
|
||||||
|
La versión de NW.js está en `src/runtime.json`; los launchers, recompilaciones y
|
||||||
|
empaquetadores x64 la leen desde ese archivo. `npm run desktop` obtiene el SDK
|
||||||
|
exacto mediante npm si no está en caché. Para usar un SDK ya instalado, establecer
|
||||||
|
`NW_BINARY` con la ruta completa a su ejecutable. El arranque comprueba la versión.
|
||||||
|
|
||||||
|
Desde `src/`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm ci
|
||||||
|
npm run desktop
|
||||||
|
npm run desktop:dev
|
||||||
|
npm run web
|
||||||
|
```
|
||||||
|
|
||||||
|
`web` respeta la configuración de inicio automático existente. Las siguientes
|
||||||
|
pruebas usan configuración ficticia y archivos temporales; no activan la estación
|
||||||
|
ni publican registros:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run test:config
|
||||||
|
npm run test:ui -- /ruta/al/sdk/nw
|
||||||
|
npm run test:startup -- /ruta/al/sdk/nw
|
||||||
|
```
|
||||||
|
|
||||||
|
Las pruebas gráficas necesitan una sesión de escritorio. `test:ui` comprueba ambos
|
||||||
|
juegos de recursos (escritorio/web), formularios, navegación, guardado, recarga,
|
||||||
|
tablas y estados. `test:startup` abre una copia temporal de la aplicación completa
|
||||||
|
con el recolector desactivado. Los resultados quedan en el directorio temporal
|
||||||
|
indicado por cada comando.
|
||||||
|
|
||||||
|
El formulario único está en `src/gui_common/view/modelo_configuracion.html`.
|
||||||
|
Su modelo, controlador, tablas y estados compartidos están en
|
||||||
|
`src/gui_common/js/`. No se necesita bootstrap-select: todos los selects usan
|
||||||
|
controles nativos. La configuración web se guarda con `POST /GuardarConf`,
|
||||||
|
valida en servidor y responde después de la escritura. El GET de escritura
|
||||||
|
anterior fue retirado.
|
||||||
|
|
||||||
|
Los instaladores se generan con `node empaquetarLinux.js` o
|
||||||
|
`node empaquetarWindows.js` desde la raíz, después de instalar las dependencias
|
||||||
|
de raíz y `src/`. No se ejecutaron empaquetados ni instalaciones del sistema
|
||||||
|
como parte de las pruebas de interfaz. El script ARM histórico incluía Node 14
|
||||||
|
y otro NW.js; ahora se detiene antes de modificar el sistema. Linux ARM puede
|
||||||
|
usar el modo web con Node.js moderno; no hay una GUI ARM validada para este runtime.
|
||||||
|
|||||||
@ -1,18 +1,10 @@
|
|||||||
import nwbuild from 'nw-builder';
|
import nwbuild from 'nw-builder';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
const runtime = JSON.parse(readFileSync(new URL('./src/runtime.json', import.meta.url)));
|
||||||
// 3. Configurar nw-builder para usar el directorio temporal como appDir
|
await nwbuild({
|
||||||
await nwbuild({
|
mode: 'build', srcDir: './src', glob: false,
|
||||||
srcDir: './src', // Usamos el directorio temporal como fuente
|
platform: 'linux', arch: 'x64', version: runtime.nw, flavor: 'normal',
|
||||||
file: './src/package.json',
|
outDir: './build/emalibre', zip: false,
|
||||||
platforms: ['linux64'],
|
app: {name: 'emalibre'}
|
||||||
glob: false,
|
});
|
||||||
version: '0.94.0',
|
console.log('Correcto!');
|
||||||
flavor: 'normal',
|
|
||||||
buildDir: './build/emalibre',
|
|
||||||
outDir: './build/emalibre',
|
|
||||||
zip: false,
|
|
||||||
appName: 'emalibre'
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('Correcto!');
|
|
||||||
|
|||||||
@ -1,26 +1,10 @@
|
|||||||
var NwBuilder = require('nw-builder');
|
import nwbuild from 'nw-builder';
|
||||||
var nw = new NwBuilder({
|
import {readFileSync} from 'node:fs';
|
||||||
appDir: './build/emalibre', // COMPILADOR: Directorio de la Aplicacion
|
const runtime = JSON.parse(readFileSync(new URL('./src/runtime.json', import.meta.url)));
|
||||||
files: ['./build/emalibre/**'], // COMPILADOR: Directorio de Codigo Fuente a compilar
|
await nwbuild({
|
||||||
platforms: ['win64'], // COMPILADOR: Plataformas Windows a compilar ['win32','win64']
|
mode: 'build', srcDir: './src', glob: false,
|
||||||
version: '0.94.0', // COMPILADOR: Version del Compilador
|
platform: 'win', arch: 'x64', version: runtime.nw, flavor: 'normal',
|
||||||
flavor: 'normal', // opciones sdk, normal
|
outDir: './build/debs/emalibre-win64', zip: false,
|
||||||
buildDir: 'build/debs', // COMPILADOR: Destino de la compilacion.
|
app: {name: 'emalibre', company: 'Laboratorio de Investigación Gugler', fileDescription: 'EMA Libre Cliente', legalCopyright: 'GPL v3'}
|
||||||
zip: false, // COMPILADOR: No comprimir (False)
|
});
|
||||||
appName: 'emalibre', // APLICACION: Nombre de la aplicacion.
|
console.log('Se terminó el empaquetado de EMA Libre para Windows.');
|
||||||
winIco: './build/emalibre/gui_common/iconos/icono_app.ico', // APLICACION: Icono (Solo Windows)
|
|
||||||
winVersionString: {
|
|
||||||
'CompanyName': 'Laboratorio De Investigación Gugler',
|
|
||||||
'FileDescription': 'Ema Libre Cliente',
|
|
||||||
'ProductName': 'Ema Libre',
|
|
||||||
'LegalCopyright': 'GPL v3'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nw.onLog = console.log;
|
|
||||||
|
|
||||||
nw.build().then(function () {
|
|
||||||
console.log('Se termino el armado de EmaLibre Para Windows, correctamente!');
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ function spinner() {
|
|||||||
# VERSIONES
|
# VERSIONES
|
||||||
# =======================
|
# =======================
|
||||||
VERSION=$(grep Version src/conf/ConfiguracionGlobal.js | sed -e "s/'Version': //g" | sed -e "s/,//g" | sed -e "s/^[ \t]*//")
|
VERSION=$(grep Version src/conf/ConfiguracionGlobal.js | sed -e "s/'Version': //g" | sed -e "s/,//g" | sed -e "s/^[ \t]*//")
|
||||||
NWJS_VERSION='0.94.0'
|
NWJS_VERSION=$(node src/tools/nw.cjs version)
|
||||||
|
|
||||||
# =======================
|
# =======================
|
||||||
# INICIO
|
# INICIO
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Este empaquetador histórico incluye Node 14 y un NW.js incompatible con la GUI actual.
|
||||||
|
echo "ARM: usá el modo web con Node.js moderno. El empaquetador histórico no está habilitado para esta versión." >&2
|
||||||
|
exit 1
|
||||||
|
|
||||||
#PARAMETRIA
|
#PARAMETRIA
|
||||||
VERSION=`grep Version src/conf/ConfiguracionGlobal.js | sed -e "s/'Version': //g" | sed -e "s/,//g" | sed -e "s/^[ \t]*//"`
|
VERSION=`grep Version src/conf/ConfiguracionGlobal.js | sed -e "s/'Version': //g" | sed -e "s/,//g" | sed -e "s/^[ \t]*//"`
|
||||||
NWJS_VERSION='0.28.4' # Es la ultima compilada para ARM, siempre mirar la url https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases
|
NWJS_VERSION='0.28.4' # Es la ultima compilada para ARM, siempre mirar la url https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases
|
||||||
|
|||||||
7148
package-lock.json
generated
7148
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
68
package.json
68
package.json
@ -1,35 +1,39 @@
|
|||||||
{
|
{
|
||||||
"main": "CompilarEmaLibreWindows.js",
|
"main": "CompilarEmaLibreWindows.js",
|
||||||
"name": "emalibre",
|
"name": "emalibre",
|
||||||
"description": "EMA Compilador",
|
"description": "EMA Compilador",
|
||||||
"version": "1.36.0",
|
"version": "1.36.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "Laboratorio de Investigacion Gugler",
|
"author": "Laboratorio de Investigacion Gugler",
|
||||||
"homepage": "https://ema.gugler.com.ar",
|
"homepage": "https://ema.gugler.com.ar",
|
||||||
"window": {
|
"window": {
|
||||||
"frame": false,
|
"frame": false,
|
||||||
"toolbar": false
|
"toolbar": false
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"CompiladorEMA",
|
"CompiladorEMA",
|
||||||
"EMACompiler"
|
"EMACompiler"
|
||||||
],
|
],
|
||||||
"licenses": [
|
"licenses": [
|
||||||
{
|
{
|
||||||
"type": "GPLv3",
|
"type": "GPLv3",
|
||||||
"url": "https://www.gnu.org/licenses/gpl-3.0.html"
|
"url": "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha --exit|| true",
|
||||||
|
"nw_rebuild_linux": "node src/tools/nw.cjs rebuild",
|
||||||
|
"nw_rebuild_windows": "node src/tools/nw.cjs rebuild",
|
||||||
|
"nw_rebuild_arm": "node src/tools/nw.cjs rebuild-arm",
|
||||||
|
"desktop": "node src/tools/nw.cjs start",
|
||||||
|
"desktop:dev": "node src/tools/nw.cjs dev",
|
||||||
|
"test:config": "node --test test/configuracion.test.cjs",
|
||||||
|
"test:ui": "node test/ui-smoke.cjs",
|
||||||
|
"test:startup": "node test/ui-startup.cjs"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"mocha": "^8.3.2",
|
||||||
|
"nw-builder": "^4.13.16"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"test": "mocha --exit|| true",
|
|
||||||
"global": "npm i -g nw-gyp nw@0.101.0-sdk",
|
|
||||||
"nw_rebuild_linux": "nw-gyp rebuild --target=0.101.0 --verbose --arch=x64 --directory=src/node_modules/node-hid",
|
|
||||||
"nw_rebuild_windows": "nw-gyp rebuild --target=0.101.0 --verbose --arch=x64 --directory=src/node_modules/node-hid",
|
|
||||||
"nw_rebuild_arm": "nw-gyp rebuild --target=0.28.4 --verbose --arch=arm --directory=src/node_modules/node-hid"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"chai": "^4.3.4",
|
|
||||||
"mocha": "^8.3.2",
|
|
||||||
"nw-builder": "^4.13.16"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
+ Mejoras menores de estilo(ej:iconos en logs).
|
+ Mejoras menores de estilo(ej:iconos en logs).
|
||||||
+ Mejoras en el empaquetador.
|
+ Mejoras en el empaquetador.
|
||||||
+ Se actualizó la funcion de registrar logs para que solo registre en el nivel parametrizado (1-9), los 0 se registran siempre.
|
+ Se actualizó la funcion de registrar logs para que solo registre en el nivel parametrizado (1-9), los 0 se registran siempre.
|
||||||
|
|
||||||
+ Se mantiene la versión de nwjs por compatibilidad con node-hid.
|
+ Se mantiene la versión de nwjs por compatibilidad con node-hid.
|
||||||
+ Se incorporó la opcion para ir al sitio oficial de la red, en el menu de redes.
|
+ Se incorporó la opcion para ir al sitio oficial de la red, en el menu de redes.
|
||||||
+ Se actualizó la versión de :
|
+ Se actualizó la versión de :
|
||||||
|
|||||||
16
src/conf/ConfiguracionGeneral.js
Executable file → Normal file
16
src/conf/ConfiguracionGeneral.js
Executable file → Normal file
@ -1,5 +1,4 @@
|
|||||||
// Configuraciones generales de EMA RECOLECTOR
|
// Configuración de EMA Libre
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"ConfGeneral": {
|
"ConfGeneral": {
|
||||||
"Tiempo_de_Recoleccion": 40,
|
"Tiempo_de_Recoleccion": 40,
|
||||||
@ -7,21 +6,20 @@ module.exports = {
|
|||||||
"SistemaMetrico": "SI",
|
"SistemaMetrico": "SI",
|
||||||
"debug": 3,
|
"debug": 3,
|
||||||
"debugTamanio": 10,
|
"debugTamanio": 10,
|
||||||
"NombreEstacion": "-",
|
"NombreEstacion": "Mi estación",
|
||||||
"Modo": "Recolector",
|
"Modo": "Visor",
|
||||||
"Llave_R": "e5303ab3-2a8b-4d42-90ab-1c8367d8521d",
|
"Llave_R": "e5303ab3-2a8b-4d42-90ab-1c8367d8521d",
|
||||||
"inicio_automatico": false,
|
"inicio_automatico": false,
|
||||||
"Audio": true,
|
"Audio": false,
|
||||||
"notificar_cambios": true,
|
"notificar_cambios": true,
|
||||||
"audioVoces": "Spanish_(Latin_America) espeak-ng",
|
"audioVoces": "Spanish_(Latin_America) espeak-ng",
|
||||||
"IP": "192.168.1.220",
|
"IP": "192.168.1.220",
|
||||||
"Puerto": "5000",
|
"Puerto": "5000",
|
||||||
"Ruta": "/datos"
|
"Ruta": "/datos"
|
||||||
|
|
||||||
},
|
},
|
||||||
"ConfEmail": {
|
"ConfEmail": {
|
||||||
"ActivarCorreos": false,
|
"ActivarCorreos": false,
|
||||||
"ReceptorEmail": "-",
|
"ReceptorEmail": "xxx@xx.com",
|
||||||
"Servicio": "Deshabilitado",
|
"Servicio": "Deshabilitado",
|
||||||
"Usuario": "",
|
"Usuario": "",
|
||||||
"Password": "",
|
"Password": "",
|
||||||
@ -29,4 +27,4 @@ module.exports = {
|
|||||||
"Puerto": ""
|
"Puerto": ""
|
||||||
},
|
},
|
||||||
"ConfPublicador": []
|
"ConfPublicador": []
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'ConfGlobal': {
|
'ConfGlobal': {
|
||||||
'Version': 1.36,
|
'Version': 1.37,
|
||||||
'Nombre': 'EMA Libre Cliente'
|
'Nombre': 'EMA Libre Cliente'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
26
src/core/configuracion-store.js
Normal file
26
src/core/configuracion-store.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const fs = require('node:fs/promises');
|
||||||
|
const path = require('node:path');
|
||||||
|
const { randomUUID } = require('node:crypto');
|
||||||
|
const model = require('../gui_common/js/configuracion-modelo.js');
|
||||||
|
|
||||||
|
async function guardarConfiguracion(config, file = path.join(__dirname, '../conf/ConfiguracionGeneral.js'), validate = true) {
|
||||||
|
if (!config || typeof config !== 'object' || !config.ConfGeneral || !config.ConfEmail) {
|
||||||
|
throw new Error('La configuración está incompleta.');
|
||||||
|
}
|
||||||
|
if (validate) {
|
||||||
|
const errors = model.validate(model.read(config));
|
||||||
|
if (Object.keys(errors).length) {
|
||||||
|
const error = new Error('Revisá los campos de configuración.');
|
||||||
|
error.fields = errors;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const temporary = `${file}.${randomUUID()}.tmp`;
|
||||||
|
try {
|
||||||
|
await fs.writeFile(temporary, '// Configuración de EMA Libre\nmodule.exports = ' + JSON.stringify(config, null, 2) + ';\n', {mode: 0o600});
|
||||||
|
await fs.rename(temporary, file);
|
||||||
|
} finally {
|
||||||
|
await fs.rm(temporary, {force: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = {guardarConfiguracion};
|
||||||
@ -167,7 +167,11 @@ APP = module.exports = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Reconfigurar: function () {
|
Reconfigurar: function (nuevaConfiguracion) {
|
||||||
|
// Keep the shared object used by the collector and publishers up to date.
|
||||||
|
if (nuevaConfiguracion) Object.assign(configGeneralEMA, nuevaConfiguracion);
|
||||||
|
APP.Configuracion.Modo = configGeneralEMA.ConfGeneral.Modo;
|
||||||
|
APP.Configuracion.utc = configGeneralEMA.ConfGeneral.UTC;
|
||||||
APP.RegistrarLog('0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.');
|
APP.RegistrarLog('0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.');
|
||||||
if (configGeneralEMA.ConfEmail.ActivarCorreos === true) Correo.EnviarEmail(configGeneralEMA,'EMA - CONFIG', '<b>Estimado</b>,<br><br> Le informamos que se modificó la configuración de la estación <b>' + configGeneralEMA.ConfGeneral.NombreEstacion + '</b>.<br><br>Saludos Cordiales.');
|
if (configGeneralEMA.ConfEmail.ActivarCorreos === true) Correo.EnviarEmail(configGeneralEMA,'EMA - CONFIG', '<b>Estimado</b>,<br><br> Le informamos que se modificó la configuración de la estación <b>' + configGeneralEMA.ConfGeneral.NombreEstacion + '</b>.<br><br>Saludos Cordiales.');
|
||||||
APP.Configuracion.TiempoContinuo = configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion;
|
APP.Configuracion.TiempoContinuo = configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion;
|
||||||
|
|||||||
@ -118,8 +118,8 @@ function DespliegeRecursivo (src, dest) {
|
|||||||
} else { // Listo
|
} else { // Listo
|
||||||
$('#nombreArchivo').html(cantidadArchivosActualizados + ' (' + cantidadDirecotirosTotalActualizados + ' Directorios )');
|
$('#nombreArchivo').html(cantidadArchivosActualizados + ' (' + cantidadDirecotirosTotalActualizados + ' Directorios )');
|
||||||
if ((cantidadArchivosActualizados) >= cantidadArchivosTotal - 5) {
|
if ((cantidadArchivosActualizados) >= cantidadArchivosTotal - 5) {
|
||||||
$('#botonreiniciar').removeClass('hidden');
|
$('#botonreiniciar').removeClass('d-none');
|
||||||
$('#botonactualizar').addClass('hidden');
|
$('#botonactualizar').addClass('d-none');
|
||||||
$('#texto').html('Actualización realizada con exito!!');
|
$('#texto').html('Actualización realizada con exito!!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -304,7 +304,7 @@ async function EstadoMenuInicio()
|
|||||||
// Se guarda el registro anterior
|
// Se guarda el registro anterior
|
||||||
Ant_UltimoReg = UltimoReg;
|
Ant_UltimoReg = UltimoReg;
|
||||||
// Se actualiza los ToolTips
|
// Se actualiza los ToolTips
|
||||||
//$(document).ready(function(){$('[data-toggle="tooltip"]').tooltip();});
|
//$(document).ready(function(){$('[data-bs-toggle="tooltip"]').tooltip();});
|
||||||
}
|
}
|
||||||
result=null;parpadeo=null;texto_uv=null;ST=null;
|
result=null;parpadeo=null;texto_uv=null;ST=null;
|
||||||
TEMP_S = null; TEMP_MULT = null;TEMP_POND = null;
|
TEMP_S = null; TEMP_MULT = null;TEMP_POND = null;
|
||||||
@ -319,17 +319,17 @@ async function RegistroPublicado()
|
|||||||
for (var key in redesPub)
|
for (var key in redesPub)
|
||||||
{
|
{
|
||||||
if(redesPub[key].estado === true){
|
if(redesPub[key].estado === true){
|
||||||
redespublicadashtml += "<span class='badge badge-pill badge-success' title='Publicado Correctamente'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
redespublicadashtml += "<span class='badge badge-pill text-bg-success' title='Publicado Correctamente'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{
|
}else{
|
||||||
if(redesPub[key].estado == 'No enviado'){
|
if(redesPub[key].estado == 'No enviado'){
|
||||||
redespublicadashtml += "<span class='badge badge-noinformado' title='No se envia, la red informa 5 minutos de espera.'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
redespublicadashtml += "<span class='badge badge-noinformado' title='No se envia, la red informa 5 minutos de espera.'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{
|
}else{
|
||||||
if(redesPub[key].estado == 'Esperar'){
|
if(redesPub[key].estado == 'Esperar'){
|
||||||
redespublicadashtml += "<span class='badge badge-light parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +" "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
redespublicadashtml += "<span class='badge text-bg-light parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +" "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{
|
}else{
|
||||||
if(redesPub[key].error == "Detenido")
|
if(redesPub[key].error == "Detenido")
|
||||||
{redespublicadashtml += "<span class='badge badge-warning parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
{redespublicadashtml += "<span class='badge text-bg-warning parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{redespublicadashtml += "<span class='badge badge-danger parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";}
|
}else{redespublicadashtml += "<span class='badge text-bg-danger parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -594,16 +594,16 @@ function ListarRedes()
|
|||||||
TablaHTML += " <thead><th>Nombre Local</th><th> Tipo de Red</th><th>Clave</th><th>LLave_W</th><th>Puerto</th><th>Publicar</th><th></th></thead>";
|
TablaHTML += " <thead><th>Nombre Local</th><th> Tipo de Red</th><th>Clave</th><th>LLave_W</th><th>Puerto</th><th>Publicar</th><th></th></thead>";
|
||||||
for (i = 0, t = Cantidad; i < t; ++i)
|
for (i = 0, t = Cantidad; i < t; ++i)
|
||||||
{
|
{
|
||||||
var publicar = "<span class='badge badge-success'>"+Publicar[i].Publicar +"</span>";
|
var publicar = "<span class='badge text-bg-success'>"+Publicar[i].Publicar +"</span>";
|
||||||
if(Publicar[i].Publicar == false) {publicar = "<span class='badge badge-danger'>"+Publicar[i].Publicar +"</span>";}
|
if(Publicar[i].Publicar == false) {publicar = "<span class='badge text-bg-danger'>"+Publicar[i].Publicar +"</span>";}
|
||||||
if((Publicar[i].TipoRed != "emacenter") && (Publicar[i].TipoRed != "emacentergugler"))
|
if((Publicar[i].TipoRed != "emacenter") && (Publicar[i].TipoRed != "emacentergugler"))
|
||||||
{
|
{
|
||||||
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge badge-success'>SI</span></td><td><span class='badge badge-danger'>NO</span></td><td><span class='badge badge-default'>N/A</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='selectpicker show-tick' data-width='fit' data-style='btn-primary'>";
|
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge text-bg-success'>SI</span></td><td><span class='badge text-bg-danger'>NO</span></td><td><span class='badge text-bg-secondary'>N/A</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='form-select'>";
|
||||||
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
||||||
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
||||||
}else{
|
}else{
|
||||||
if(Publicar[i].Llave_W != ''){var tienellave = "SI";}else{var tienellave ="NO";}
|
if(Publicar[i].Llave_W != ''){var tienellave = "SI";}else{var tienellave ="NO";}
|
||||||
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge badge-default'>N/A</span></td><td><span class='badge badge-success'>"+tienellave+"</span></td><td><span class='badge badge-default'>"+(Publicar[i].Puerto || "N/A")+"</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='selectpicker show-tick' data-width='fit' data-style='btn-primary'>";
|
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge text-bg-secondary'>N/A</span></td><td><span class='badge text-bg-success'>"+tienellave+"</span></td><td><span class='badge text-bg-secondary'>"+(Publicar[i].Puerto || "N/A")+"</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='form-select'>";
|
||||||
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
||||||
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
||||||
}
|
}
|
||||||
@ -613,8 +613,6 @@ function ListarRedes()
|
|||||||
BotonHTML = '<button id="botonguardar" type="button" class="btn btn-sm btn-success" onclick="MenuGUI(\'redes_alta\')" role="button">Alta de una Red</button>';
|
BotonHTML = '<button id="botonguardar" type="button" class="btn btn-sm btn-success" onclick="MenuGUI(\'redes_alta\')" role="button">Alta de una Red</button>';
|
||||||
$('#redesconfiguradas').html(TablaHTML);
|
$('#redesconfiguradas').html(TablaHTML);
|
||||||
$('#BotonRed').html(BotonHTML);
|
$('#BotonRed').html(BotonHTML);
|
||||||
for (i = 0, t = Cantidad; i < t; ++i)
|
|
||||||
{$('#Red_activa_'+i).selectpicker('render');}
|
|
||||||
Publicar=null;Cantidad=null;TablaHTML=null;tieneusuario=null;tienellave=null;
|
Publicar=null;Cantidad=null;TablaHTML=null;tieneusuario=null;tienellave=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,7 +885,7 @@ function FormModificar(red)
|
|||||||
TablaHTML += "<table class='table table-striped'>";
|
TablaHTML += "<table class='table table-striped'>";
|
||||||
TablaHTML += "<thead><tr align='center'><th colspan='6'>Tipo de Red</th></tr></thead>";
|
TablaHTML += "<thead><tr align='center'><th colspan='6'>Tipo de Red</th></tr></thead>";
|
||||||
TablaHTML += "<tr><td colspan='6' align='left'>";
|
TablaHTML += "<tr><td colspan='6' align='left'>";
|
||||||
TablaHTML += "<select id='Tipo_Red' name='Tipo_Red' onchange='MenuSelectRed();' class='selectpicker show-tick' data-width='fit' data-style='btn-primary'>";
|
TablaHTML += "<select id='Tipo_Red' name='Tipo_Red' onchange='MenuSelectRed();' class='form-select'>";
|
||||||
TablaHTML += "<optgroup label='RED EMACENTER'>";
|
TablaHTML += "<optgroup label='RED EMACENTER'>";
|
||||||
TablaHTML += "<option value='emacentergugler'>Gugler EmaCenter - Gugler</option>";
|
TablaHTML += "<option value='emacentergugler'>Gugler EmaCenter - Gugler</option>";
|
||||||
TablaHTML += "<option value='emacenter'>Emacenter Personalizada</option></optgroup>";
|
TablaHTML += "<option value='emacenter'>Emacenter Personalizada</option></optgroup>";
|
||||||
@ -909,7 +907,6 @@ function FormModificar(red)
|
|||||||
$('#BotonRed').html(BotonHTML);
|
$('#BotonRed').html(BotonHTML);
|
||||||
$('#Tipo_Red').val(configGeneralEMA.ConfPublicador[red].TipoRed);
|
$('#Tipo_Red').val(configGeneralEMA.ConfPublicador[red].TipoRed);
|
||||||
MenuSelectRed();
|
MenuSelectRed();
|
||||||
$('#Tipo_Red').selectpicker('render');
|
|
||||||
TablaHTML=null;
|
TablaHTML=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -931,51 +928,23 @@ function VerHistoricoT(lugar)
|
|||||||
|
|
||||||
// FUNCIONES DE ESCRITURA EN DISCO
|
// FUNCIONES DE ESCRITURA EN DISCO
|
||||||
|
|
||||||
function GuardarConf(origen)
|
async function GuardarConf(origen) {
|
||||||
{
|
const persist = async draft => {
|
||||||
if (origen == 'conf'){
|
await require('../core/configuracion-store.js').guardarConfiguracion(draft);
|
||||||
//Se Setean los campos
|
try { EMA.Reconfigurar(draft); } catch (error) { console.warn('Configuración guardada; reiniciá el recolector para aplicarla.'); }
|
||||||
HABLA(0,"Se almacenó correctamente la configuración", "success");
|
configGeneralEMA = draft;
|
||||||
configGeneralEMA.ConfGeneral.NombreEstacion = $('#NombreEstacion').val();
|
};
|
||||||
configGeneralEMA.ConfEmail.Servicio = $('#Tipo_SMTP').val();
|
if (origen === 'conf') return ConfigUI.save(persist);
|
||||||
if($('#Tipo_SMTP').val() == "Deshabilitado"){configGeneralEMA.ConfEmail.ActivarCorreos = false;}else{configGeneralEMA.ConfEmail.ActivarCorreos = true;}
|
try {
|
||||||
configGeneralEMA.ConfEmail.Usuario = $('#Usuario_SMTP').val();
|
await persist(configGeneralEMA);
|
||||||
configGeneralEMA.ConfEmail.Password = $('#Contrasenia_SMTP').val();
|
HABLA(0, 'Configuración guardada.', 'success');
|
||||||
configGeneralEMA.ConfEmail.Server = $('#Server_SMTP').val();
|
return true;
|
||||||
configGeneralEMA.ConfEmail.Puerto = $('#Puerto_SMTP').val();
|
} catch (error) {
|
||||||
configGeneralEMA.ConfEmail.ReceptorEmail = $('#Email_receptor').val();
|
HABLA(0, 'No se pudo guardar la configuración: ' + error.message, 'warn');
|
||||||
configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion = parseInt($('#Tiempo_de_Recoleccion').val());
|
return false;
|
||||||
configGeneralEMA.ConfGeneral.debug = parseInt($('#Debug').val());
|
}
|
||||||
configGeneralEMA.ConfGeneral.UTC = parseInt($('#utc').val());
|
}
|
||||||
configGeneralEMA.ConfGeneral.SistemaMetrico = $('#SistemaMetrico').val();
|
|
||||||
configGeneralEMA.ConfGeneral.Modo = $('#Modo').val();
|
|
||||||
configGeneralEMA.ConfGeneral.IP = $('#r_ip').val();
|
|
||||||
configGeneralEMA.ConfGeneral.Puerto = $('#r_puerto').val();
|
|
||||||
configGeneralEMA.ConfGeneral.Ruta = $('#r_path').val();
|
|
||||||
configGeneralEMA.ConfGeneral.Llave_R = $('#Llave_R').val();
|
|
||||||
configGeneralEMA.ConfGeneral.debugTamanio = parseInt($('#debugMB').val());
|
|
||||||
if($('#inicio_auto').val() == "Activado"){configGeneralEMA.ConfGeneral.inicio_automatico = true;}else{configGeneralEMA.ConfGeneral.inicio_automatico = false;}
|
|
||||||
if($('#notificar_cambios').val() == "Activado"){configGeneralEMA.ConfGeneral.notificar_cambios = true;}else{configGeneralEMA.ConfGeneral.notificar_cambios = false;}
|
|
||||||
if($('#audio').val() == "Activado"){configGeneralEMA.ConfGeneral.Audio = true;}else{configGeneralEMA.ConfGeneral.Audio = false;}
|
|
||||||
configGeneralEMA.ConfGeneral.audioVoces = $('#vocesAudio').val();
|
|
||||||
}
|
|
||||||
//Se almacenan los campos
|
|
||||||
var configuracion_nueva = '// Configuraciones generales de EMA RECOLECTOR' + '\n\n';
|
|
||||||
configuracion_nueva += 'module.exports = ';
|
|
||||||
configuracion_nueva += JSON.stringify(configGeneralEMA, null, ' ');
|
|
||||||
configuracion_nueva += ';';
|
|
||||||
fsconf.writeFile('./conf/ConfiguracionGeneral.js', configuracion_nueva, function(err) {
|
|
||||||
if( err ){
|
|
||||||
HABLA(0,"Upps, existió un problema intentando almacenar la configuración", "warn");
|
|
||||||
EMA.RegistrarLog("0|CORE|Upps, existió un problema intentando almacenar la configuración.");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
EMA.Reconfigurar();
|
|
||||||
EMA.RegistrarLog("0|CORE|Se almaceno correctamente la configuración");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function PurgarP(origen)
|
function PurgarP(origen)
|
||||||
{
|
{
|
||||||
fsconf.writeFile('./logs/TanquePendientes.log', JSON.stringify([], null, 4),{encoding: 'utf8', autoClose: true}, function(err)
|
fsconf.writeFile('./logs/TanquePendientes.log', JSON.stringify([], null, 4),{encoding: 'utf8', autoClose: true}, function(err)
|
||||||
@ -1013,7 +982,7 @@ function VerHistorico(lugar)
|
|||||||
fsconf.readFile('./logs/registro_diario.log', {encoding: 'utf8', autoClose: true},function (err, data)
|
fsconf.readFile('./logs/registro_diario.log', {encoding: 'utf8', autoClose: true},function (err, data)
|
||||||
{ if (err) throw err;
|
{ if (err) throw err;
|
||||||
var TablaHTML = '';
|
var TablaHTML = '';
|
||||||
TablaHTML += '<table id="MiTablaH" class="display" style="width:100%" >';
|
TablaHTML += '<table id="MiTablaH" class="table table-bordered" style="width:100%" >';
|
||||||
TablaHTML += '<thead>';
|
TablaHTML += '<thead>';
|
||||||
TablaHTML += '<tr>';
|
TablaHTML += '<tr>';
|
||||||
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
||||||
@ -1083,7 +1052,7 @@ function VerHistorico(lugar)
|
|||||||
});
|
});
|
||||||
}else{ //MODO Visor
|
}else{ //MODO Visor
|
||||||
var TablaHTML = '';
|
var TablaHTML = '';
|
||||||
TablaHTML += '<table id="MiTablaH" class="display" style="width:100%" >';
|
TablaHTML += '<table id="MiTablaH" class="table table-bordered" style="width:100%" >';
|
||||||
TablaHTML += '<thead>';
|
TablaHTML += '<thead>';
|
||||||
TablaHTML += '<tr>';
|
TablaHTML += '<tr>';
|
||||||
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
||||||
@ -1128,7 +1097,7 @@ function VerHistorico(lugar)
|
|||||||
if(lugar == 0) {
|
if(lugar == 0) {
|
||||||
$('#MiTablaH').DataTable( {
|
$('#MiTablaH').DataTable( {
|
||||||
dom: 'Bfrtip',
|
dom: 'Bfrtip',
|
||||||
buttons: ['copy','csv'],
|
buttons: TablaUI.buttons(),
|
||||||
pageLength: 5,
|
pageLength: 5,
|
||||||
scrollX: true,
|
scrollX: true,
|
||||||
scrollCollapse: true,
|
scrollCollapse: true,
|
||||||
@ -1184,7 +1153,7 @@ function VerHistorico(lugar)
|
|||||||
}else{
|
}else{
|
||||||
$('#MiTablaH').DataTable( {
|
$('#MiTablaH').DataTable( {
|
||||||
dom: 'Bfrtip',
|
dom: 'Bfrtip',
|
||||||
buttons: ['copy','csv'],
|
buttons: TablaUI.buttons(),
|
||||||
pageLength: 5,
|
pageLength: 5,
|
||||||
scrollCollapse: true,
|
scrollCollapse: true,
|
||||||
lengthChange: false,
|
lengthChange: false,
|
||||||
@ -1243,7 +1212,7 @@ function VerRegistrosLog(select)
|
|||||||
fsconf.readFile('./logs/debug.log', {encoding: 'utf8', autoClose: true}, function (err, data)
|
fsconf.readFile('./logs/debug.log', {encoding: 'utf8', autoClose: true}, function (err, data)
|
||||||
{ if (err) throw err;
|
{ if (err) throw err;
|
||||||
var TablaHTML = '';
|
var TablaHTML = '';
|
||||||
TablaHTML += '<table id="MiTabla" class="display" style="width:100%;" >';
|
TablaHTML += '<table id="MiTabla" class="table table-bordered" style="width:100%;" >';
|
||||||
TablaHTML += '<thead>';
|
TablaHTML += '<thead>';
|
||||||
TablaHTML += '<tr> ';
|
TablaHTML += '<tr> ';
|
||||||
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
||||||
@ -1303,47 +1272,6 @@ function VerRegistrosLog(select)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function MostrarTabla(DATOS,DIV,TABLA)
|
|
||||||
{
|
|
||||||
$('#'+DIV).empty();
|
|
||||||
$('#'+DIV).html(DATOS);
|
|
||||||
const tabla = $('#'+TABLA).DataTable(
|
|
||||||
{
|
|
||||||
dom: 'Bfrtip',
|
|
||||||
buttons: ['copy','csv'],
|
|
||||||
pageLength: 8,
|
|
||||||
scrollX: true,
|
|
||||||
responsive:true,
|
|
||||||
autoWidth: false,
|
|
||||||
//scrollCollapse: true,
|
|
||||||
//lengthChange: false,
|
|
||||||
//ordering: true,
|
|
||||||
destroy:true,
|
|
||||||
//order: [[ 0, "desc" ]],
|
|
||||||
/*fixedHeader: {
|
|
||||||
header: true,
|
|
||||||
footer: true
|
|
||||||
},*/
|
|
||||||
initComplete: function(settings, json) {
|
|
||||||
//console.log('Termino datatable');
|
|
||||||
document.getElementById(DIV).style.display = "block";
|
|
||||||
document.getElementById("actualizando").style.display = "none";
|
|
||||||
$('.buttons-csv').removeClass('btn-default').addClass('btn-primary');
|
|
||||||
$('.buttons-csv span').text('💾 Exportar CSV');
|
|
||||||
$('.buttons-copy').removeClass('btn-default').addClass('btn-secondary');
|
|
||||||
$('.buttons-copy span').text(' 📋 Copiar al portapeles');
|
|
||||||
// Ajusta las columnas después de mostrar la tabla
|
|
||||||
setTimeout(function() {
|
|
||||||
tabla.columns.adjust();
|
|
||||||
}, 300);
|
|
||||||
},
|
|
||||||
language: {url: "../gui_common/css/Spanish.json"}
|
|
||||||
});
|
|
||||||
DATOS = null;
|
|
||||||
TABLA = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function graficoEstadisticas()
|
async function graficoEstadisticas()
|
||||||
{
|
{
|
||||||
// GRAFICO DEL TIEMPO CHARTJS
|
// GRAFICO DEL TIEMPO CHARTJS
|
||||||
|
|||||||
@ -31,6 +31,12 @@
|
|||||||
|
|
||||||
// Requiere el módulo NWJS
|
// Requiere el módulo NWJS
|
||||||
const gui = require('nw.gui');
|
const gui = require('nw.gui');
|
||||||
|
const runtime = require(require('path').join(gui.App.startPath, 'runtime.json'));
|
||||||
|
if (process.versions.nw !== runtime.nw) {
|
||||||
|
window.alert('Esta versión requiere NW.js ' + runtime.nw + '. Iniciá con npm run desktop.');
|
||||||
|
gui.App.quit();
|
||||||
|
throw new Error('Versión NW.js incompatible');
|
||||||
|
}
|
||||||
|
|
||||||
// Obtener los parámetros pasados a la aplicación
|
// Obtener los parámetros pasados a la aplicación
|
||||||
const str = gui.App.argv;
|
const str = gui.App.argv;
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
<title>EMA Libre Cliente (Carpincho)</title>
|
<title>EMA Libre Cliente (Carpincho)</title>
|
||||||
|
|
||||||
<!-- Estilos CSS -->
|
<!-- Estilos CSS -->
|
||||||
<link rel="stylesheet" href="../node_modules/datatables/media/css/jquery.dataTables.min.css" />
|
|
||||||
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="../node_modules/bootstrap-select/dist/css/bootstrap-select.min.css">
|
<link rel="stylesheet" href="../node_modules/datatables.net-bs5/css/dataTables.bootstrap5.min.css">
|
||||||
|
<link rel="stylesheet" href="../node_modules/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css">
|
||||||
<link rel="stylesheet" href="../node_modules/nprogress/nprogress.css">
|
<link rel="stylesheet" href="../node_modules/nprogress/nprogress.css">
|
||||||
<link rel="stylesheet" href="../gui_common/css/style.css">
|
<link rel="stylesheet" href="../gui_common/css/style.css">
|
||||||
|
|
||||||
@ -18,15 +18,18 @@
|
|||||||
|
|
||||||
<!-- Libreria bootstrap/jquery para graficos -->
|
<!-- Libreria bootstrap/jquery para graficos -->
|
||||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||||
<script src="../node_modules/popper.js/dist/umd/popper.min.js"></script>
|
<script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
|
<script src="../gui_common/js/configuracion-modelo.js"></script>
|
||||||
|
<script src="../gui_common/js/configuracion.js"></script>
|
||||||
|
<script src="../gui_common/js/tablas.js"></script>
|
||||||
|
<script src="../gui_common/js/estado.js"></script>
|
||||||
<!-- Libreria bootstrap select para graficos -->
|
<!-- Libreria bootstrap select para graficos -->
|
||||||
<script src="../node_modules/bootstrap-select/dist/js/bootstrap-select.min.js"></script>
|
|
||||||
<!-- Datable - Para las tablas dinamicas -->
|
<!-- Datable - Para las tablas dinamicas -->
|
||||||
<script src="../node_modules/datatables/media/js/jquery.dataTables.min.js"></script>
|
<script src="../node_modules/datatables.net/js/jquery.dataTables.min.js"></script>
|
||||||
<script src="../node_modules/datatables-buttons/js/dataTables.buttons.js"></script>
|
<script src="../node_modules/datatables.net-bs5/js/dataTables.bootstrap5.min.js"></script>
|
||||||
<script src="../node_modules/datatables-buttons/js/buttons.html5.js"></script>
|
<script src="../node_modules/datatables.net-buttons/js/dataTables.buttons.js"></script>
|
||||||
<script src="../node_modules/datatables-buttons/js/buttons.bootstrap.js"></script>
|
<script src="../node_modules/datatables.net-buttons/js/buttons.html5.js"></script>
|
||||||
|
<script src="../node_modules/datatables.net-buttons-bs5/js/buttons.bootstrap5.min.js"></script>
|
||||||
<!-- Libreria RGraph/css para graficos -->
|
<!-- Libreria RGraph/css para graficos -->
|
||||||
<script src="../gui_common/libs/RGraph/RGraph.common.core.js"></script>
|
<script src="../gui_common/libs/RGraph/RGraph.common.core.js"></script>
|
||||||
<script src="../gui_common/libs/RGraph/RGraph.thermometer.js"></script>
|
<script src="../gui_common/libs/RGraph/RGraph.thermometer.js"></script>
|
||||||
@ -44,8 +47,8 @@
|
|||||||
<script src="../gui_common/controlador/admingui.js"></script>
|
<script src="../gui_common/controlador/admingui.js"></script>
|
||||||
<style>
|
<style>
|
||||||
.text-center { text-align: center !important; }
|
.text-center { text-align: center !important; }
|
||||||
.text-right { text-align: right !important; }
|
.text-end { text-align: right !important; }
|
||||||
.text-left { text-align: left !important; }
|
.text-start { text-align: left !important; }
|
||||||
.vertical-align-top { vertical-align: top !important; }
|
.vertical-align-top { vertical-align: top !important; }
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@ -64,23 +67,23 @@
|
|||||||
|
|
||||||
|
|
||||||
<div id="principal" style="display: none;">
|
<div id="principal" style="display: none;">
|
||||||
<nav style="-webkit-app-region: drag;cursor: all-scroll" class="navbar stylish-color fixed-top scrolling-navbar ">
|
<nav style="-webkit-app-region: drag;cursor: all-scroll" class="navbar stylish-color sticky-top scrolling-navbar ">
|
||||||
<span style="-webkit-app-region: no-drag;color: #ffffff;" data-toggle="tooltip" data-placement="bottom" style="font-size: 15px;"><img id="signal" class="" src="../gui_common/img/signal.webp" height="16px" width="16px" data-toggle="tooltip"
|
<span style="-webkit-app-region: no-drag;color: #ffffff;" data-bs-toggle="tooltip" data-bs-placement="bottom" style="font-size: 15px;"><img id="signal" class="" src="../gui_common/img/signal.webp" height="16px" width="16px" data-bs-toggle="tooltip"
|
||||||
data-placement="right" data-html="true" title="Señal RF de la estación"> EMA Libre Cliente </span>
|
data-bs-placement="right" data-bs-html="true" title="Señal RF de la estación"> EMA Libre Cliente </span>
|
||||||
<spam id="mensajebarra" class="float-center" style="color:white"></spam>
|
<spam id="mensajebarra" class="float-center" style="color:white"></spam>
|
||||||
<span style="-webkit-app-region: no-drag" class="float-right">
|
<span style="-webkit-app-region: no-drag" class="float-end">
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wzoomout" style="font-size: 15px;" title="Disminuir"><img id="Wzoomout" height="16px" width="16px" src="../gui_common/iconos/zoomout.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wzoomout" style="font-size: 15px;" title="Disminuir"><img id="Wzoomout" height="16px" width="16px" src="../gui_common/iconos/zoomout.webp"></i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wzoomin" style="font-size: 15px;" title="Aumentar" ><img id="Wzoomin" height="16px" width="16px" src="../gui_common/iconos/zoomin.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wzoomin" style="font-size: 15px;" title="Aumentar" ><img id="Wzoomin" height="16px" width="16px" src="../gui_common/iconos/zoomin.webp"></i>
|
||||||
<i class="custom-controls menu">|</i>
|
<i class="custom-controls menu">|</i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wfull" style="font-size: 15px;" title="Pantalla Completa"><img id="Wfull" height="16px" width="16px" src="../gui_common/iconos/fullscreen.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wfull" style="font-size: 15px;" title="Pantalla Completa"><img id="Wfull" height="16px" width="16px" src="../gui_common/iconos/fullscreen.webp"></i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wmaxun" style="font-size: 15px" title="Tamaño normal"><img id="Wmaxun" height="16px" width="16px" src="../gui_common/iconos/unmax.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wmaxun" style="font-size: 15px" title="Tamaño normal"><img id="Wmaxun" height="16px" width="16px" src="../gui_common/iconos/unmax.webp"></i>
|
||||||
<i class="custom-controls menu">|</i>
|
<i class="custom-controls menu">|</i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wmin" style="font-size: 15px;" title="Minimizar"><img id="Wmin" height="16px" width="16px" src="../gui_common/iconos/minimizar.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wmin" style="font-size: 15px;" title="Minimizar"><img id="Wmin" height="16px" width="16px" src="../gui_common/iconos/minimizar.webp"></i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wmax" style="font-size: 15px" title="Maximizar"><img id="Wmax" height="16px" width="16px" src="../gui_common/iconos/maximizar.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wmax" style="font-size: 15px" title="Maximizar"><img id="Wmax" height="16px" width="16px" src="../gui_common/iconos/maximizar.webp"></i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wclo" style="font-size: 15px" title="Cerrar"><img id="Wclo" height="16px" width="16px" src="../gui_common/iconos/close.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wclo" style="font-size: 15px" title="Cerrar"><img id="Wclo" height="16px" width="16px" src="../gui_common/iconos/close.webp"></i>
|
||||||
</span>
|
</span>
|
||||||
</nav>
|
</nav>
|
||||||
<br><br>
|
<section id="estado-estacion" class="estado-estacion" aria-label="Estado de la estación"></section>
|
||||||
<div id="superior" class="container">
|
<div id="superior" class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-2 text-center vertical-align-top">
|
<div class="col-2 text-center vertical-align-top">
|
||||||
@ -104,46 +107,46 @@
|
|||||||
<div class="col-2 text-center">
|
<div class="col-2 text-center">
|
||||||
<div id="DIVModo" class="vertical-align-top" style="visibility: hidden"></div>
|
<div id="DIVModo" class="vertical-align-top" style="visibility: hidden"></div>
|
||||||
<div id="DIVPendientes" class="vertical-align-top" style="visibility: hidden">
|
<div id="DIVPendientes" class="vertical-align-top" style="visibility: hidden">
|
||||||
<span class='badge badge-warning'>Registros Pendientes</span>
|
<span class='badge text-bg-warning'>Registros Pendientes</span>
|
||||||
<span id="Pendientes" class='badge badge-warning'></span>
|
<span id="Pendientes" class='badge text-bg-warning'></span>
|
||||||
<span id="Destanqueo" class="parpadea texttanque vertical-align-top" style="visibility: hidden"><strong>Destanqueando</strong></span>
|
<span id="Destanqueo" class="parpadea texttanque vertical-align-top" style="visibility: hidden"><strong>Destanqueando</strong></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3 text-right" id="RedesMet" class="list-group row" style="vertical-align: top;"></div>
|
<div class="col-3 text-end" id="RedesMet" class="list-group row" style="vertical-align: top;"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container container-fluid">
|
<div class="container container-fluid">
|
||||||
<ul class="nav nav-tabs nav-inverse nav-pills nav-fill" id="list-tab" role="tablist">
|
<ul class="nav nav-tabs nav-inverse nav-pills nav-fill" id="list-tab" role="tablist">
|
||||||
<li class="nav-item active ">
|
<li class="nav-item active ">
|
||||||
<a class="nav-link active show" id="inicio-tab" data-toggle="tab" data-target="#inicio" role="tab" aria-controls="inicio" aria-selected="true"><img height="24px" width="24px" src="../gui_common/img/home.webp" aria-controls="inicio"> INICIO</a>
|
<a class="nav-link active show" id="inicio-tab" data-bs-toggle="tab" data-bs-target="#inicio" role="tab" aria-controls="inicio" aria-selected="true"><img height="24px" width="24px" src="../gui_common/img/home.webp" aria-controls="inicio"> INICIO</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="interior-tab" data-toggle="tab" data-target="#interior" role="tab" aria-controls="interior" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/interior.webp" aria-controls="interior"> INTERIOR</a>
|
<a class="nav-link" id="interior-tab" data-bs-toggle="tab" data-bs-target="#interior" role="tab" aria-controls="interior" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/interior.webp" aria-controls="interior"> INTERIOR</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="exterior-tab" data-toggle="tab" data-target="#exterior" role="tab" aria-controls="exterior" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/exterior.webp" aria-controls="exterior"> EXTERIOR</a>
|
<a class="nav-link" id="exterior-tab" data-bs-toggle="tab" data-bs-target="#exterior" role="tab" aria-controls="exterior" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/exterior.webp" aria-controls="exterior"> EXTERIOR</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- <li class="nav-item">
|
<!-- <li class="nav-item">
|
||||||
<a class="nav-link" id="estadisticas-tab" data-toggle="tab" data-target="#estadisticas" role="tab" aria-controls="estadisticas" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/estadistica.png" aria-controls="estadisticas"> ESTADISTICAS</a>
|
<a class="nav-link" id="estadisticas-tab" data-bs-toggle="tab" data-bs-target="#estadisticas" role="tab" aria-controls="estadisticas" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/estadistica.png" aria-controls="estadisticas"> ESTADISTICAS</a>
|
||||||
</li> -->
|
</li> -->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="redes-tab" data-toggle="tab" data-target="#redes" role="tab" aria-controls="redes" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/redes.webp" aria-controls="redes"> REDES</a>
|
<a class="nav-link" id="redes-tab" data-bs-toggle="tab" data-bs-target="#redes" role="tab" aria-controls="redes" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/redes.webp" aria-controls="redes"> REDES</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="configuracion-tab" data-toggle="tab" data-target="#configuracion" role="tab" aria-controls="configuracion" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/config.webp" aria-controls="configuracion"> CONFIGURACIÓN</a>
|
<a class="nav-link" id="configuracion-tab" data-bs-toggle="tab" data-bs-target="#configuracion" role="tab" aria-controls="configuracion" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/config.webp" aria-controls="configuracion"> CONFIGURACIÓN</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="contacto-tab" data-toggle="tab" data-target="#contacto" target="_self" role="tab" aria-controls="contacto" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/about.webp" aria-controls="contacto"> CONTACTO</a>
|
<a class="nav-link" id="contacto-tab" data-bs-toggle="tab" data-bs-target="#contacto" target="_self" role="tab" aria-controls="contacto" aria-selected="false"><img height="24px" width="24px" src="../gui_common/img/about.webp" aria-controls="contacto"> CONTACTO</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content jumbotron" id="" style="padding: 15px;padding-bottom:15px;margin-bottom:15px">
|
<div class="tab-content ema-panel" id="" style="padding: 15px;padding-bottom:15px;margin-bottom:15px">
|
||||||
<div id="actualizando_inicio" style="display:none" class="text-center"><br><br><br><br><img src='../gui_common/img/animadas/cargando2.gif' width='100' height='100' /> <br><br><br><br> </div>
|
<div id="actualizando_inicio" style="display:none" class="text-center"><br><br><br><br><img src='../gui_common/img/animadas/cargando2.gif' width='100' height='100' /> <br><br><br><br> </div>
|
||||||
<div class="tab-pane fade show active" id="inicio" role="tabpanel" aria-badgeledby="inicio-tab"></div>
|
<div class="tab-pane fade show active" id="inicio" role="tabpanel" aria-labelledby="inicio-tab"></div>
|
||||||
<div class="tab-pane fade text-center" id="interior" role="tabpanel" aria-badgeledby="interior-tab"></div>
|
<div class="tab-pane fade text-center" id="interior" role="tabpanel" aria-labelledby="interior-tab"></div>
|
||||||
<div class="tab-pane fade text-center" id="exterior" role="tabpanel" aria-badgeledby="exterior-tab"></div>
|
<div class="tab-pane fade text-center" id="exterior" role="tabpanel" aria-labelledby="exterior-tab"></div>
|
||||||
<!-- <div class="tab-pane fade text-center" id="estadisticas" role="tabpanel" aria-badgeledby="estadisticas-tab"></div>-->
|
<!-- <div class="tab-pane fade text-center" id="estadisticas" role="tabpanel" aria-labelledby="estadisticas-tab"></div>-->
|
||||||
<div class="tab-pane fade text-center" id="configuracion" role="tabpanel" aria-badgeledby="configuracion-tab"></div>
|
<div class="tab-pane fade text-center" id="configuracion" role="tabpanel" aria-labelledby="configuracion-tab"></div>
|
||||||
<div class="tab-pane fade text-center" id="redes" role="tabpanel" aria-badgeledby="redes-tab"></div>
|
<div class="tab-pane fade text-center" id="redes" role="tabpanel" aria-labelledby="redes-tab"></div>
|
||||||
<div class="tab-pane fade" id="contacto" role="tabpanel" aria-badgeledby="contacto-tab"></div>
|
<div class="tab-pane fade" id="contacto" role="tabpanel" aria-labelledby="contacto-tab"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="fixed-bottom">
|
<footer class="fixed-bottom">
|
||||||
@ -157,7 +160,7 @@
|
|||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('.menu').on('click', function(evnt) {
|
$('.menu').on('click', function(evnt) {
|
||||||
var obj = $(evnt.target);
|
var obj = $(evnt.currentTarget);
|
||||||
$('#' + obj.attr('aria-controls')).empty();
|
$('#' + obj.attr('aria-controls')).empty();
|
||||||
let screens = gui.Screen.screens;
|
let screens = gui.Screen.screens;
|
||||||
let winX = win.x;
|
let winX = win.x;
|
||||||
@ -175,7 +178,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//nw.Window.get().moveTo(0);
|
//nw.Window.get().moveTo(0);
|
||||||
switch (obj.attr('id')) {
|
switch (obj.attr('aria-controls')) {
|
||||||
case 'Wzoomin':
|
case 'Wzoomin':
|
||||||
win.zoomLevel += 0.3;
|
win.zoomLevel += 0.3;
|
||||||
break;
|
break;
|
||||||
@ -187,9 +190,7 @@
|
|||||||
nw.Window.get().resizeTo(currentScreen.bounds.width, currentScreen.bounds.height);
|
nw.Window.get().resizeTo(currentScreen.bounds.width, currentScreen.bounds.height);
|
||||||
break;
|
break;
|
||||||
case 'Wmin':
|
case 'Wmin':
|
||||||
nw.Window.get().minimize();
|
ocultarVentana();
|
||||||
//win.hide(); // Oculta completamente la ventana
|
|
||||||
//win.setShowInTaskbar(false); // Quita el icono del taskbar
|
|
||||||
break;
|
break;
|
||||||
case 'Wmax':
|
case 'Wmax':
|
||||||
nw.Window.get().moveTo(currentScreen.bounds.x, currentScreen.bounds.y);
|
nw.Window.get().moveTo(currentScreen.bounds.x, currentScreen.bounds.y);
|
||||||
@ -208,8 +209,7 @@
|
|||||||
obj = null;
|
obj = null;
|
||||||
});
|
});
|
||||||
$('.nav-link').on('click', function(evnt) {
|
$('.nav-link').on('click', function(evnt) {
|
||||||
var obj = $(evnt.target);
|
var obj = $(evnt.currentTarget);
|
||||||
$('#' + obj.attr('aria-controls')).empty();
|
|
||||||
MenuGUI(obj.attr('aria-controls'));
|
MenuGUI(obj.attr('aria-controls'));
|
||||||
obj = null;
|
obj = null;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,12 +7,11 @@
|
|||||||
<META http-equiv="CACHE-CONTROL" content="Public">
|
<META http-equiv="CACHE-CONTROL" content="Public">
|
||||||
<title>EMA Libre - Actualizar</title>
|
<title>EMA Libre - Actualizar</title>
|
||||||
<!-- Estilos varios css -->
|
<!-- Estilos varios css -->
|
||||||
<link rel="stylesheet" type="text/css" href="../gui_common/css/style.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
<link rel="stylesheet" type="text/css" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="../node_modules/bootstrap-select/dist/css/bootstrap-select.min.css">
|
<link rel="stylesheet" href="../gui_common/css/style.css">
|
||||||
<!-- Libreria bootstrap/jquery para graficos -->
|
<!-- Libreria bootstrap/jquery para graficos -->
|
||||||
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.min.js"></script>
|
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
|
<script type="text/javascript" src="../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- Libreria del Controlador -->
|
<!-- Libreria del Controlador -->
|
||||||
<script type="text/javascript" src="controlador/admin_update.js"></script>
|
<script type="text/javascript" src="controlador/admin_update.js"></script>
|
||||||
</head>
|
</head>
|
||||||
@ -24,7 +23,7 @@
|
|||||||
<label id='barra_label'>-</label>
|
<label id='barra_label'>-</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="table borderless">
|
<table class="table table-borderless">
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<td rowspan="3" style="background-color:red"></td>
|
<td rowspan="3" style="background-color:red"></td>
|
||||||
<td style="display:table-cell; vertical-align:middle; text-align:center">
|
<td style="display:table-cell; vertical-align:middle; text-align:center">
|
||||||
@ -42,11 +41,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<td colspan="3" style="display:table-cell; vertical-align:middle; text-align:center">
|
<td colspan="3" style="display:table-cell; vertical-align:middle; text-align:center">
|
||||||
<h4 align='center'><span id="texto" class="label label-success">-</span></h4>
|
<h4 align='center'><span id="texto" class="badge text-bg-success">-</span></h4>
|
||||||
|
|
||||||
<div id='BotonRed' align="center">
|
<div id='BotonRed' align="center">
|
||||||
<a id="botonactualizar" class="btn btn-lg btn-danger" onclick="ActualizarAPP()" role="button">Actualizar</a>
|
<a id="botonactualizar" class="btn btn-lg btn-danger" onclick="ActualizarAPP()" role="button">Actualizar</a>
|
||||||
<a id="botonreiniciar" class="btn btn-lg btn-success disabled hidden" onclick="ReiniciarAPP()" role="button">Reiniciar EMA</a>
|
<a id="botonreiniciar" class="btn btn-lg btn-success disabled d-none" onclick="ReiniciarAPP()" role="button">Reiniciar EMA</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -1,264 +0,0 @@
|
|||||||
<head>
|
|
||||||
<!-- ...código existente... -->
|
|
||||||
<style>
|
|
||||||
hr {
|
|
||||||
height: 4px;
|
|
||||||
border: none;
|
|
||||||
background-color: #bbb;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.hr-suave {
|
|
||||||
height: 1px;
|
|
||||||
border: none;
|
|
||||||
background-color: #ccc;
|
|
||||||
opacity: 0.5;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.text-right { text-align: right !important; }
|
|
||||||
.text-left { text-align: left !important; }
|
|
||||||
.text-center { text-align: center !important; }
|
|
||||||
.vertical-align-top { vertical-align: top !important; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="col-centered">
|
|
||||||
<h1>Configuración General</h1>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 text-right" style="vertical-align:top;"><button class="btn btn-sm btn-success" onclick="MenuGUI('logs');" role="button">Ver Logs</button> </div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">Ema Modo</label><br>
|
|
||||||
<select id='Modo' name="Modo" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Recolector">
|
|
||||||
<option value="Recolector_USB">Recolector USB</option>
|
|
||||||
<option value="Recolector_IP">Recolector IP/WIFI</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Visor">
|
|
||||||
<option value="Visor">Visor Llave</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">Nombre de tu estación</label><br>
|
|
||||||
<input type="text" class="btn btn-primary" id="NombreEstacion" autocomplete='name' placeholder="Ingrese el nombre" maxlength="20" size="30"></br></br>
|
|
||||||
</div>
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label for="inputEmail" class="control-label">Correo del Administrador</label><br>
|
|
||||||
<input type="email" class="btn btn-primary" id="Email_receptor" autocomplete='email' placeholder="Email" maxlength="50" size="35">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Inicio Automático</label><br>
|
|
||||||
<select id='inicio_auto' name="inicio_auto" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Iniciar el recolector/visor con el aplicativo">
|
|
||||||
<option value="Activado">Activado</option>
|
|
||||||
<option value="Desactivado">Desactivado</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Notificar Cambios</label><br>
|
|
||||||
<select id='notificar_cambios' name="notificar_cambios" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Notificar de carpincho">
|
|
||||||
<option value="Activado">Activado</option>
|
|
||||||
<option value="Desactivado">Desactivado</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Audio</label><br>
|
|
||||||
<select id='audio' name="audio" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Audio de carpincho">
|
|
||||||
<option value="Activado">Activado</option>
|
|
||||||
<option value="Desactivado">Desactivado</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered" id="vocesAudioDiv">
|
|
||||||
<label class="control-label">Voz del Audio</label></br>
|
|
||||||
<select id='vocesAudio' name="vocesAudio" class="selectpicker show-tick" data-width="fit" data-style="btn-primary" size="100">
|
|
||||||
<optgroup label="Lista de Voces">
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Recolección</label><br>
|
|
||||||
<select id='Tiempo_de_Recoleccion' name="Tiempo_de_Recoleccion" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Muy Rapido">
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="20">20</option>
|
|
||||||
<option value="30">30</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Medio">
|
|
||||||
<option value="40">40</option>
|
|
||||||
<option value="50">50</option>
|
|
||||||
<option value="60">60</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Normal">
|
|
||||||
<option value="70">70</option>
|
|
||||||
<option value="80">80</option>
|
|
||||||
<option value="90">90</option>
|
|
||||||
<option value="100">100</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Despacio">
|
|
||||||
<option value="110">110</option>
|
|
||||||
<option value="120">120</option>
|
|
||||||
<option value="130">130</option>
|
|
||||||
<option value="140">140</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">Debug y Tamaño</label><br>
|
|
||||||
<select id='Debug' name="Debug" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Normal">
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Alto">
|
|
||||||
<option value="4">4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="6">6</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Muy Alto">
|
|
||||||
<option value="7">7</option>
|
|
||||||
<option value="8">8</option>
|
|
||||||
<option value="9">9</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
<input type="text" class="btn btn-primary" id="debugMB" placeholder="MB Debug" maxlength="4" size="5">
|
|
||||||
<label class="control-label">MB</label>
|
|
||||||
</div>
|
|
||||||
<div class="col-1 col-centered">
|
|
||||||
<label class="control-label">UTC</label><br>
|
|
||||||
<select id='utc' name="utc" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Negativo">
|
|
||||||
<option value="-1">-1</option>
|
|
||||||
<option value="-2">-2</option>
|
|
||||||
<option value="-3">-3</option>
|
|
||||||
<option value="-4">-4</option>
|
|
||||||
<option value="-5">-5</option>
|
|
||||||
<option value="-6">-6</option>
|
|
||||||
<option value="-7">-7</option>
|
|
||||||
<option value="-8">-8</option>
|
|
||||||
<option value="-9">-9</option>
|
|
||||||
<option value="-10">-10</option>
|
|
||||||
<option value="-11">-11</option>
|
|
||||||
<option value="-12">-12</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Neutro">
|
|
||||||
<option value="0">0</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Positivo">
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
<option value="4">4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="6">6</option>
|
|
||||||
<option value="7">7</option>
|
|
||||||
<option value="8">8</option>
|
|
||||||
<option value="9">9</option>
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="11">11</option>
|
|
||||||
<option value="12">12</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Unidades</label><br>
|
|
||||||
<select id='SistemaMetrico' name="SistemaMetrico" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Sistema Internacional de Unidades(SI)">
|
|
||||||
<option value="SI">º C</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Sistema Anglosajón de Unidades(SA)">
|
|
||||||
<option value="SA">º F</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">SMTP TIPO</label><br>
|
|
||||||
<select id='Tipo_SMTP' name="Tipo_SMTP" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="SMTP Deshabilitado">
|
|
||||||
<option value="Deshabilitado">Deshabilitado</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="SMTP Proveedor">
|
|
||||||
<option value="Gmail">GMAIL</option>
|
|
||||||
<option value="Yahoo">YAHOO</option>
|
|
||||||
<option value="Hotmail">OUTLOOK</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="SMTP Manual">
|
|
||||||
<option value="Manual">SMTP CONFIG</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">Cuenta</label><br>
|
|
||||||
<input type="email" class="btn btn-primary" id="Usuario_SMTP" placeholder="Cuenta" maxlength="40" size="16">
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">Contraseña</label><br>
|
|
||||||
<input type="password" class="btn btn-primary" id="Contrasenia_SMTP" placeholder="Contraseña" maxlength="40" size="16">
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered" id="Server">
|
|
||||||
<label class="control-label">Server</label><br>
|
|
||||||
<input type="text" class="btn btn-primary" id="Server_SMTP" placeholder="Server" maxlength="40" size="15">
|
|
||||||
</div>
|
|
||||||
<div class="col-1 col-centered" id="puerto">
|
|
||||||
<label class="control-label">Puerto</label><br>
|
|
||||||
<input type="text" class="btn btn-primary" id="Puerto_SMTP" placeholder="Puerto" maxlength="4" size="5">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Segun seleccion cambia debajo el bloque secundario -->
|
|
||||||
<div id="bloque_secundario">
|
|
||||||
<hr>
|
|
||||||
<label class="control-label">Configuración específica para el Modo</label>
|
|
||||||
<div class="col-centered">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6 col-centered" id="LlaveR">
|
|
||||||
<label class="control-label">Llave de Lectura</label></br>
|
|
||||||
<input type="text" class="btn btn-primary" id="Llave_R" placeholder="Ingrese LLave" maxlength="40" size="44"></br></br>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="bloque_por_IP_WIFI" class="row">
|
|
||||||
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">IP</label><br>
|
|
||||||
<select id='r_ip' name="IP" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="IP's" id="ipGroup">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Puerto</label></br>
|
|
||||||
<input type="text" class="btn btn-primary" id="r_puerto" placeholder="Puerto" maxlength="4" size="5" value="5000">
|
|
||||||
</div>
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">Path</label></br>
|
|
||||||
<input type="text" class="btn btn-primary" id="r_path" placeholder="Puerto" maxlength="15" size="25" value="/datos">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 col-centered">
|
|
||||||
<button type="button" id="botonguardar" class="btn btn-sm btn-success" onclick="GuardarConf('conf')" role="button">Guardar</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
@ -75,8 +75,3 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
|
||||||
$(document).ready(function(){
|
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<div class="col-12"><h2>Tipo de Red</h2></div>
|
<div class="col-12"><h2>Tipo de Red</h2></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row ">
|
<div class="row ">
|
||||||
<select id='Tipo_Red' name="Tipo_Red" onchange="MenuSelectRed();" class="form-control form-control-sm" data-width="fit" data-style="btn-primary">
|
<select id='Tipo_Red' name="Tipo_Red" onchange="MenuSelectRed();" class="form-control form-control-sm">
|
||||||
<optgroup label='Red EMA Libre Center'>
|
<optgroup label='Red EMA Libre Center'>
|
||||||
<option value='emacentergugler'>EMA Libre Center - Gugler</option>
|
<option value='emacentergugler'>EMA Libre Center - Gugler</option>
|
||||||
<option value='emacenter'>EMA Libre Center - Particular</option>
|
<option value='emacenter'>EMA Libre Center - Particular</option>
|
||||||
@ -25,10 +25,10 @@
|
|||||||
<div class="col-12"><br><h2>Configuracion de la Red</h2></div>
|
<div class="col-12"><br><h2>Configuracion de la Red</h2></div>
|
||||||
</div>
|
</div>
|
||||||
<form class="needs-validation" novalidate>
|
<form class="needs-validation" novalidate>
|
||||||
<div class="form-row ">
|
<div class="row g-2 ">
|
||||||
<div class="col-12"> <label class="control-label">Nombre</label><br><input type="text" class="form-control btn btn-primary" id="Nombre" placeholder="Nombre" maxlength="15" size="18" ></div>
|
<div class="col-12"> <label class="control-label">Nombre</label><br><input type="text" class="form-control btn btn-primary" id="Nombre" placeholder="Nombre" maxlength="15" size="18" ></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="row g-2">
|
||||||
<div class="col-6 .d-none" id="EmaConfAlta2" style="display: none;"> <label class="control-label">Usuario </label><br><input type="text" class="form-control btn btn-primary" id="Usuario" placeholder="Usuario" maxlength="130" size="20" required><br></div>
|
<div class="col-6 .d-none" id="EmaConfAlta2" style="display: none;"> <label class="control-label">Usuario </label><br><input type="text" class="form-control btn btn-primary" id="Usuario" placeholder="Usuario" maxlength="130" size="20" required><br></div>
|
||||||
<div class="col-6 .d-none" id="EmaConfAlta3" style="display: none;"> <label class="control-label">Contraseña </label><br><input type="text" class="form-control btn btn-primary" id="Password" placeholder="Password" maxlength="40" size="20" required></div>
|
<div class="col-6 .d-none" id="EmaConfAlta3" style="display: none;"> <label class="control-label">Contraseña </label><br><input type="text" class="form-control btn btn-primary" id="Password" placeholder="Password" maxlength="40" size="20" required></div>
|
||||||
<div class="col-8 .d-none" id="EmaConfAlta4" style="display: none;"> <label class="control-label">Servidor</label><br><input type="text" class="form-control btn btn-primary" id="Servidor" placeholder="Servidor" maxlength="50" size="30" required></div>
|
<div class="col-8 .d-none" id="EmaConfAlta4" style="display: none;"> <label class="control-label">Servidor</label><br><input type="text" class="form-control btn btn-primary" id="Servidor" placeholder="Servidor" maxlength="50" size="30" required></div>
|
||||||
|
|||||||
@ -32,6 +32,8 @@
|
|||||||
// y exporta las variables necesarias para el resto del archivo.
|
// y exporta las variables necesarias para el resto del archivo.
|
||||||
var configGeneralEMA, configGlobalEMA, funcionesActualizar, EMA, gui, os, win;
|
var configGeneralEMA, configGlobalEMA, funcionesActualizar, EMA, gui, os, win;
|
||||||
var _IS_NW = false;
|
var _IS_NW = false;
|
||||||
|
let tray = null;
|
||||||
|
let ventanaMinimizada = false;
|
||||||
const iconoEncendido = './gui_common/iconos/icono_enc.png'; // Imagen del Icono Encendido
|
const iconoEncendido = './gui_common/iconos/icono_enc.png'; // Imagen del Icono Encendido
|
||||||
const iconoApagado = './gui_common/iconos/icono_off.png'; // Imagen del Icono Apagado
|
const iconoApagado = './gui_common/iconos/icono_off.png'; // Imagen del Icono Apagado
|
||||||
const iconoPublicado = './gui_common/iconos/icono_pub.png'; // Imagen del Icono Prublicado --> no utilizada
|
const iconoPublicado = './gui_common/iconos/icono_pub.png'; // Imagen del Icono Prublicado --> no utilizada
|
||||||
@ -54,100 +56,71 @@ if (_IS_NW) {
|
|||||||
gui = require('nw.gui'); // Libreria Grafica
|
gui = require('nw.gui'); // Libreria Grafica
|
||||||
os = require('os'); // Libreria del sistema operativo
|
os = require('os'); // Libreria del sistema operativo
|
||||||
win = gui.Window.get(); // ventana actual
|
win = gui.Window.get(); // ventana actual
|
||||||
|
win.on('close', function () { if (ConfigUI.canLeave()) this.close(true); });
|
||||||
// **********************Iconizado / Menu Superior *********************************************************
|
// **********************Iconizado / Menu Superior *********************************************************
|
||||||
gui.App.clearCache(); // Se limpia cache
|
gui.App.clearCache(); // Se limpia cache
|
||||||
win = gui.Window.get(); // Se obtiene la ventana actual
|
win = gui.Window.get(); // Se obtiene la ventana actual
|
||||||
// Crear el icono en el tray
|
// Mantener el icono y su menú durante toda la vida de la ventana.
|
||||||
function createTray() {
|
function mostrarVentana() {
|
||||||
if (tray) return; // Evitar duplicados
|
win.setShowInTaskbar(true);
|
||||||
|
win.show();
|
||||||
|
if (ventanaMinimizada) {
|
||||||
|
win.restore();
|
||||||
|
ventanaMinimizada = false;
|
||||||
|
}
|
||||||
|
win.focus();
|
||||||
|
}
|
||||||
|
|
||||||
// Crear menú contextual (sin 'menubar')
|
function ocultarVentana() {
|
||||||
const menu = new nw.Menu();
|
createTray();
|
||||||
menu.append(new nw.MenuItem({ type: 'checkbox', label: 'box1' }));
|
win.hide();
|
||||||
menu.append(new nw.MenuItem({
|
win.setShowInTaskbar(false);
|
||||||
label: 'Iniciar',
|
}
|
||||||
click: () => { if (typeof INICIAR === 'function') INICIAR(); }
|
|
||||||
}));
|
function createTray() {
|
||||||
menu.append(new nw.MenuItem({
|
if (tray) return;
|
||||||
label: 'Detener',
|
|
||||||
click: () => { if (typeof DETENER === 'function') DETENER(); }
|
const menu = new gui.Menu();
|
||||||
}));
|
menu.append(new gui.MenuItem({
|
||||||
menu.append(new nw.MenuItem({ type: 'separator' }));
|
|
||||||
menu.append(new nw.MenuItem({
|
|
||||||
label: 'Mostrar ventana',
|
label: 'Mostrar ventana',
|
||||||
click: () => {
|
click: mostrarVentana
|
||||||
win.show();
|
|
||||||
win.restore();
|
|
||||||
win.focus();
|
|
||||||
win.setShowInTaskbar(true);
|
|
||||||
removeTray();
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
menu.append(new nw.MenuItem({
|
menu.append(new gui.MenuItem({
|
||||||
label: 'Ocultar ventana',
|
label: 'Ocultar ventana',
|
||||||
click: () => {
|
click: ocultarVentana
|
||||||
win.hide();
|
|
||||||
win.setShowInTaskbar(false);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
menu.append(new nw.MenuItem({ type: 'separator' }));
|
menu.append(new gui.MenuItem({ type: 'separator' }));
|
||||||
menu.append(new nw.MenuItem({
|
menu.append(new gui.MenuItem({ label: 'Iniciar', click: INICIAR }));
|
||||||
|
menu.append(new gui.MenuItem({ label: 'Detener', click: DETENER }));
|
||||||
|
menu.append(new gui.MenuItem({ type: 'separator' }));
|
||||||
|
menu.append(new gui.MenuItem({
|
||||||
label: 'Salir',
|
label: 'Salir',
|
||||||
click: () => {
|
click: () => {
|
||||||
if (typeof EMA !== 'undefined' && typeof EMA.Salir === 'function') EMA.Salir();
|
if (!ConfigUI.canLeave()) return;
|
||||||
nw.App.closeAllWindows();
|
if (typeof EMA.Salir === 'function') EMA.Salir();
|
||||||
nw.App.quit();
|
gui.App.closeAllWindows();
|
||||||
|
gui.App.quit();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Crear tray icon
|
// Entregar el menú al crear el indicador, también en Linux.
|
||||||
tray = new nw.Tray({
|
tray = new gui.Tray({
|
||||||
title: 'EmaLibre Carpincho',
|
title: 'EmaLibre Carpincho',
|
||||||
icon: iconoApagado,
|
icon: iconoApagado,
|
||||||
|
menu: menu
|
||||||
});
|
});
|
||||||
tray.menu = menu;
|
tray.tooltip = 'Ema Libre Carpincho';
|
||||||
|
// NW.js abre el menú nativo con clic derecho; solo emite clic izquierdo.
|
||||||
// Click izquierdo: mostrar ventana
|
tray.on('click', mostrarVentana);
|
||||||
tray.on('click', () => {
|
|
||||||
console.log('Tray icon clicked');
|
|
||||||
win.show();
|
|
||||||
win.restore();
|
|
||||||
win.focus();
|
|
||||||
win.setShowInTaskbar(true);
|
|
||||||
removeTray();
|
|
||||||
if (typeof MuestraRegistroActual === 'function') MuestraRegistroActual(false);
|
|
||||||
if (typeof Graficos === 'function') Graficos();
|
|
||||||
if (typeof ClimaActual === 'function') ClimaActual();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Click derecho: abrir menú manualmente si el entorno no lo hace
|
|
||||||
tray.on('right-click', () => {
|
|
||||||
console.log('Tray icon right-clicked');
|
|
||||||
tray.menu.popup();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Doble click: también mostrar
|
|
||||||
tray.on('double-click', () => {
|
|
||||||
win.show();
|
|
||||||
win.focus();
|
|
||||||
win.setShowInTaskbar(true);
|
|
||||||
removeTray();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
nw.Window.get().on('loaded', createTray);
|
win.on('loaded', createTray);
|
||||||
|
win.on('minimize', () => {
|
||||||
// Captura el redimencionamiento de la ventana
|
ventanaMinimizada = true;
|
||||||
win.on('resize', (width, height) => {
|
ocultarVentana();
|
||||||
if (width < 775 && height < 555) { win.zoomLevel = -2.4; }
|
|
||||||
if (width > 775 && height > 555) { win.zoomLevel = -1.8; }
|
|
||||||
if (width > 800 && height > 600) { win.zoomLevel = -1.5; }
|
|
||||||
if (width > 850 && height > 690) { win.zoomLevel = -0.6; }
|
|
||||||
if (width > 1000 && height > 800) { win.zoomLevel = 0; }
|
|
||||||
if (width > 1200 && height > 820) { win.zoomLevel = 0.3; }
|
|
||||||
if (width > 1200 && height > 900) { win.zoomLevel = 0.9; }
|
|
||||||
if (width > 1400 && height > 1000) { win.zoomLevel = 1.2; }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Window resizing is handled by responsive CSS; preserve manual zoom.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Entorno Web: cargamos la configuración vía HTTP y exponemos wrappers mínimos
|
// Entorno Web: cargamos la configuración vía HTTP y exponemos wrappers mínimos
|
||||||
configGeneralEMA = undefined;
|
configGeneralEMA = undefined;
|
||||||
@ -179,7 +152,6 @@ if (_IS_NW) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
// **********************Vairales Generales*********************
|
// **********************Vairales Generales*********************
|
||||||
let tray = null;
|
|
||||||
var UltimoReg;
|
var UltimoReg;
|
||||||
var Ant_UltimoReg;
|
var Ant_UltimoReg;
|
||||||
var ModeloVisor; // Variables Generales - Registros recolectados
|
var ModeloVisor; // Variables Generales - Registros recolectados
|
||||||
@ -212,7 +184,7 @@ function INICIAR () {
|
|||||||
HABLA(0, 'Se inicio en modo Recolector', 'success');
|
HABLA(0, 'Se inicio en modo Recolector', 'success');
|
||||||
$('#signal').addClass('parpadea');
|
$('#signal').addClass('parpadea');
|
||||||
}
|
}
|
||||||
if (_IS_NW) tray.icon = iconoEncendido;
|
if (_IS_NW) { createTray(); tray.icon = iconoEncendido; }
|
||||||
$('td#barralateral').css('background-color', '#11881161');
|
$('td#barralateral').css('background-color', '#11881161');
|
||||||
$('#estado').html('En Linea');
|
$('#estado').html('En Linea');
|
||||||
$('#mensaje').html('Encendido');
|
$('#mensaje').html('Encendido');
|
||||||
@ -276,7 +248,7 @@ function killAllTimers() {
|
|||||||
function DETENER () {
|
function DETENER () {
|
||||||
clearInterval(intervaloBarra);
|
clearInterval(intervaloBarra);
|
||||||
killAllTimers();
|
killAllTimers();
|
||||||
if (_IS_NW) tray.icon = iconoApagado;
|
if (_IS_NW) { createTray(); tray.icon = iconoApagado; }
|
||||||
$('td#barralateral').css('background-color', '#ff000030');
|
$('td#barralateral').css('background-color', '#ff000030');
|
||||||
$('#estado').html('Fuera de Linea');
|
$('#estado').html('Fuera de Linea');
|
||||||
$('#img_estado').attr('src', iconoNeutro);
|
$('#img_estado').attr('src', iconoNeutro);
|
||||||
@ -304,6 +276,7 @@ async function redimensionarInicio ()
|
|||||||
$('#cargador').empty();
|
$('#cargador').empty();
|
||||||
$('#cargador').remove();
|
$('#cargador').remove();
|
||||||
$('#principal').show();
|
$('#principal').show();
|
||||||
|
EstadoUI.start();
|
||||||
if (_IS_NW) {
|
if (_IS_NW) {
|
||||||
win.setMinimumSize(700, 500);
|
win.setMinimumSize(700, 500);
|
||||||
win.setMaximumSize(4000, 2000);
|
win.setMaximumSize(4000, 2000);
|
||||||
@ -833,7 +806,7 @@ async function BarradeProgreso () {
|
|||||||
cant++;
|
cant++;
|
||||||
if(cant == 1){ RegistroActualW(true);} else{return true;};
|
if(cant == 1){ RegistroActualW(true);} else{return true;};
|
||||||
// solo si esta en modo visor
|
// solo si esta en modo visor
|
||||||
if (configGeneralEMA.ConfGeneral.Modo === 'Visor') {document.getElementById('RedesMet').innerHTML = "<span class='badge badge-success' title='Obtenido Correctamente'>" + ModeloVisor + ': ' + UltimoReg.fecha.substring(10, 20) + '</span><br>';}
|
if (configGeneralEMA.ConfGeneral.Modo === 'Visor') {document.getElementById('RedesMet').innerHTML = "<span class='badge text-bg-success' title='Obtenido Correctamente'>" + ModeloVisor + ': ' + UltimoReg.fecha.substring(10, 20) + '</span><br>';}
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
}
|
}
|
||||||
}else{ if(cant > 0){enEjecucion = false;return false;}
|
}else{ if(cant > 0){enEjecucion = false;return false;}
|
||||||
@ -860,7 +833,7 @@ async function BarradeProgreso () {
|
|||||||
cant++;
|
cant++;
|
||||||
if(cant == 1){ RegistroActual(true);} else{return true;};
|
if(cant == 1){ RegistroActual(true);} else{return true;};
|
||||||
// solo si esta en modo visor
|
// solo si esta en modo visor
|
||||||
if (configGeneralEMA.ConfGeneral.Modo === 'Visor') {document.getElementById('RedesMet').innerHTML = "<span class='badge badge-success' title='Obtenido Correctamente'>" + ModeloVisor + ': ' + UltimoReg.fecha.substring(10, 20) + '</span><br>';}
|
if (configGeneralEMA.ConfGeneral.Modo === 'Visor') {document.getElementById('RedesMet').innerHTML = "<span class='badge text-bg-success' title='Obtenido Correctamente'>" + ModeloVisor + ': ' + UltimoReg.fecha.substring(10, 20) + '</span><br>';}
|
||||||
if (win.x > -10000)
|
if (win.x > -10000)
|
||||||
{ // Solo si no esta minimizado
|
{ // Solo si no esta minimizado
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
@ -899,98 +872,10 @@ async function BarradeProgreso () {
|
|||||||
|
|
||||||
|
|
||||||
// ********************** Menu Acciones *******************************************************************
|
// ********************** Menu Acciones *******************************************************************
|
||||||
async function MenuConfig () {
|
function MenuConfig () { ConfigUI.visibility(); }
|
||||||
|
|
||||||
$('#bloque_secundario').hide();
|
|
||||||
$('#LlaveR').hide();
|
|
||||||
$('#bloque_por_IP_WIFI').hide();
|
|
||||||
|
|
||||||
if (['Recolector_USB', 'Recolector_IP'].includes($('#Modo').val())) {
|
|
||||||
$('#LlaveR').attr('disabled', true);
|
|
||||||
$('#LlaveR').val('');
|
|
||||||
if ($('#Modo').val() === 'Recolector_USB') {
|
|
||||||
//nada por ahora :).
|
|
||||||
}else{ //esta en modo Recolector_IP
|
|
||||||
//console.log("entro en modo IP");
|
|
||||||
$('#bloque_secundario').show();
|
|
||||||
$('#bloque_por_IP_WIFI').show();
|
|
||||||
let interfaces;
|
|
||||||
if (_IS_NW) {
|
|
||||||
interfaces = os.networkInterfaces();
|
|
||||||
} else {interfaces = await $.get('/interfaces');}
|
|
||||||
|
|
||||||
// Limpiar las opciones previas (excepto la de "Seleccionar IP")
|
|
||||||
const $ipGroup = $('#ipGroup');
|
|
||||||
$ipGroup.find('option:not([value=""])').remove();
|
|
||||||
// Recorremos las interfaces de red
|
|
||||||
let ipEncontrada = false;
|
|
||||||
for (const name in interfaces) {
|
|
||||||
for (const iface of interfaces[name]) {
|
|
||||||
if (iface.family === 'IPv4' && !iface.internal) {
|
|
||||||
const $option = $('<option>', {
|
|
||||||
value: iface.address,
|
|
||||||
text: iface.address
|
|
||||||
});
|
|
||||||
$ipGroup.append($option);
|
|
||||||
ipEncontrada = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ipEncontrada) { const $option = $('<option>', {
|
|
||||||
value: "false",
|
|
||||||
text: "No se encontraron interfaces"
|
|
||||||
});
|
|
||||||
$ipGroup.append($option);
|
|
||||||
}
|
|
||||||
$('#r_ip').selectpicker('refresh');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$('#bloque_secundario').show();
|
|
||||||
$('#LlaveR').attr('disabled', false);
|
|
||||||
$('#LlaveR').show();
|
|
||||||
$('#Llave_R').val(configGeneralEMA.ConfGeneral.Llave_R);
|
|
||||||
}
|
|
||||||
if ($('#Tipo_SMTP').val() === 'Deshabilitado') {
|
|
||||||
$('#Usuario_SMTP').attr('disabled', true);
|
|
||||||
$('#Contrasenia_SMTP').attr('disabled', true);
|
|
||||||
$('#Puerto_SMTP').attr('disabled', true);
|
|
||||||
$('#Server_SMTP').attr('disabled', true);
|
|
||||||
$('#Puerto_SMTP').val('');
|
|
||||||
$('#puerto').hide();
|
|
||||||
$('#Server_SMTP').val('');
|
|
||||||
$('#Server').hide();
|
|
||||||
} else {
|
|
||||||
$('#Usuario_SMTP').attr('disabled', false);
|
|
||||||
$('#Contrasenia_SMTP').attr('disabled', false);
|
|
||||||
if ($('#Tipo_SMTP').val() === 'Manual') {
|
|
||||||
$('#Puerto_SMTP').attr('disabled', false);
|
|
||||||
$('#puerto').show();
|
|
||||||
$('#Server_SMTP').attr('disabled', false);
|
|
||||||
$('#Server').show();
|
|
||||||
} else {
|
|
||||||
$('#Puerto_SMTP').attr('disabled', true);
|
|
||||||
$('#puerto').hide();
|
|
||||||
$('#Server_SMTP').attr('disabled', true);
|
|
||||||
$('#Server').hide();
|
|
||||||
}
|
|
||||||
$('#Usuario_SMTP').val(configGeneralEMA.ConfEmail.Usuario);
|
|
||||||
$('#Contrasenia_SMTP').val(configGeneralEMA.ConfEmail.Password);
|
|
||||||
$('#Server_SMTP').val(configGeneralEMA.ConfEmail.Server);
|
|
||||||
$('#Puerto_SMTP').val(configGeneralEMA.ConfEmail.Puerto);
|
|
||||||
}
|
|
||||||
if ($('#audio').val() === 'Desactivado') {
|
|
||||||
$('#vocesAudioDiv').attr('disabled', true);
|
|
||||||
$('#vocesAudioDiv').val('');
|
|
||||||
$('#vocesAudioDiv').hide();
|
|
||||||
} else {
|
|
||||||
$('#vocesAudioDiv').attr('disabled', false);
|
|
||||||
$('#vocesAudioDiv').show();
|
|
||||||
$('#vocesAudio').val(configGeneralEMA.ConfGeneral.audioVoces);
|
|
||||||
$('#vocesAudio').selectpicker('render');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function MenuGUI (elemento) {
|
async function MenuGUI (elemento) {
|
||||||
|
if (!ConfigUI.canLeave()) return;
|
||||||
try {
|
try {
|
||||||
document.getElementById("actualizando_inicio").hidden = false;
|
document.getElementById("actualizando_inicio").hidden = false;
|
||||||
document.getElementById("actualizando_inicio").style.display = "block";
|
document.getElementById("actualizando_inicio").style.display = "block";
|
||||||
@ -999,7 +884,9 @@ async function MenuGUI (elemento) {
|
|||||||
else {seleccion = document.getElementById(elemento);}
|
else {seleccion = document.getElementById(elemento);}
|
||||||
$(seleccion).empty();
|
$(seleccion).empty();
|
||||||
$(seleccion).hide();
|
$(seleccion).hide();
|
||||||
$(seleccion).load('./view/modelo_' + elemento + '.html', async function (datosArchivo) {
|
const vista = elemento === 'configuracion' ? (_IS_NW ? '../gui_common/view/modelo_configuracion.html' : '/gui_common/view/modelo_configuracion.html') : './view/modelo_' + elemento + '.html';
|
||||||
|
$(seleccion).load(vista, async function (datosArchivo, status) {
|
||||||
|
if (status === 'error') { $(seleccion).text('No se pudo cargar esta pantalla. Volvé a intentarlo.').show(); $('#actualizando_inicio').hide(); return; }
|
||||||
switch (elemento) {
|
switch (elemento) {
|
||||||
case 'logs':
|
case 'logs':
|
||||||
VerRegistrosLog();
|
VerRegistrosLog();
|
||||||
@ -1045,140 +932,25 @@ async function MenuGUI (elemento) {
|
|||||||
$('#versioncontacto').html(NombreVersion);
|
$('#versioncontacto').html(NombreVersion);
|
||||||
$('#interior').empty();$('#exterior').empty();$('#inicio').empty();$('#configuracion').empty();$('#redes').empty();$('#estadisticas').empty();
|
$('#interior').empty();$('#exterior').empty();$('#inicio').empty();$('#configuracion').empty();$('#redes').empty();$('#estadisticas').empty();
|
||||||
break;
|
break;
|
||||||
case 'configuracion':
|
case 'configuracion':
|
||||||
$('#interior').empty();$('#exterior').empty();$('#contacto').empty();$('#inicio').empty();$('#redes').empty();$('#estadisticas').empty();
|
$('#interior,#exterior,#contacto,#inicio,#redes,#estadisticas').empty();
|
||||||
// Se obtienen las voces del sistema
|
try {
|
||||||
var synth = window.speechSynthesis;
|
if (!_IS_NW) configGeneralEMA = await $.get('/configGeneralEMA');
|
||||||
const voice = synth.getVoices();
|
let interfaces = {};
|
||||||
var voiceSelect = document.getElementById('vocesAudio');
|
try { interfaces = await cargarInterfaces(); } catch (error) { console.warn('No se pudieron consultar las interfaces.'); }
|
||||||
var cantidadVoces = voice.length;
|
ConfigUI.mount(configGeneralEMA, interfaces, window.speechSynthesis?.getVoices() || []);
|
||||||
if( cantidadVoces > 0){
|
} catch (error) {
|
||||||
for (var i = 0; i < cantidadVoces; i++)
|
$(seleccion).text('No se pudo leer la configuración. Volvé a intentarlo.');
|
||||||
{
|
}
|
||||||
var option = document.createElement('option');
|
break;
|
||||||
option.textContent = voice[i].name;
|
|
||||||
option.setAttribute('value', voice[i].name);
|
|
||||||
voiceSelect.appendChild(option);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
var option = document.createElement('option');
|
|
||||||
voice[0] = 'Sin Voces';
|
|
||||||
option.textContent = 'Sin voces, verifique el SO';
|
|
||||||
option.setAttribute('value', 'Sin Voces');
|
|
||||||
voiceSelect.appendChild(option);
|
|
||||||
voiceSelect.selectedIndex = "0";
|
|
||||||
}
|
|
||||||
let interfaces = await cargarInterfaces();
|
|
||||||
// Limpiar las opciones previas (excepto la de "Seleccionar IP")
|
|
||||||
const $ipGroup = $('#ipGroup');
|
|
||||||
$ipGroup.find('option:not([value=""])').remove();
|
|
||||||
// Recorremos las interfaces de red
|
|
||||||
let ipEncontrada = false;
|
|
||||||
for (const name in interfaces) {
|
|
||||||
for (const iface of interfaces[name]) {
|
|
||||||
if (iface.family === 'IPv4' && !iface.internal) {
|
|
||||||
const $option = $('<option>', {
|
|
||||||
value: iface.address,
|
|
||||||
text: iface.address
|
|
||||||
});
|
|
||||||
$ipGroup.append($option);
|
|
||||||
ipEncontrada = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ipEncontrada) { const $option = $('<option>', {
|
|
||||||
value: "false",
|
|
||||||
text: "No se encontraron interfaces"
|
|
||||||
});
|
|
||||||
$ipGroup.append($option);
|
|
||||||
}
|
|
||||||
$('#r_ip').selectpicker('refresh');
|
|
||||||
$('#NombreEstacion').val(configGeneralEMA.ConfGeneral.NombreEstacion);
|
|
||||||
$('#Modo').val(configGeneralEMA.ConfGeneral.Modo);
|
|
||||||
$('#Modo').selectpicker('render');
|
|
||||||
$('#SistemaMetrico').val(configGeneralEMA.ConfGeneral.SistemaMetrico);
|
|
||||||
$('#SistemaMetrico').selectpicker('render');
|
|
||||||
$('#Llave_R').val(configGeneralEMA.ConfGeneral.Llave_R);
|
|
||||||
$('#Tiempo_de_Recoleccion').val(configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion);
|
|
||||||
$('#Email_receptor').val(configGeneralEMA.ConfEmail.ReceptorEmail);
|
|
||||||
$('#Tipo_SMTP').val(configGeneralEMA.ConfEmail.Servicio);
|
|
||||||
$('#Tipo_SMTP').selectpicker('render');
|
|
||||||
$('#Tiempo_de_Recoleccion').selectpicker('render');
|
|
||||||
$('#r_ip').val(configGeneralEMA.ConfGeneral.IP);
|
|
||||||
$('#r_ip').selectpicker('render');
|
|
||||||
$('#r_puerto').val(configGeneralEMA.ConfGeneral.Puerto);
|
|
||||||
$('#r_path').val(configGeneralEMA.ConfGeneral.Ruta);
|
|
||||||
$('#Debug').val(configGeneralEMA.ConfGeneral.debug);
|
|
||||||
$('#debugMB').val(configGeneralEMA.ConfGeneral.debugTamanio);
|
|
||||||
$('#Debug').selectpicker('render');
|
|
||||||
var automatico;
|
|
||||||
if (configGeneralEMA.ConfGeneral.inicio_automatico) { automatico = 'Activado'; } else { automatico = 'Desactivado'; }
|
|
||||||
$('#inicio_auto').val(automatico);
|
|
||||||
$('#inicio_auto').selectpicker('render');
|
|
||||||
var cambios;
|
|
||||||
if (configGeneralEMA.ConfGeneral.notificar_cambios) { cambios = 'Activado'; } else { cambios = 'Desactivado'; }
|
|
||||||
$('#notificar_cambios').val(cambios);
|
|
||||||
$('#notificar_cambios').selectpicker('render');
|
|
||||||
var Audio;
|
|
||||||
if (configGeneralEMA.ConfGeneral.Audio) { Audio = 'Activado'; } else { Audio = 'Desactivado'; }
|
|
||||||
$('#audio').val(Audio);
|
|
||||||
$('#audio').selectpicker('render');
|
|
||||||
$('#utc').val(configGeneralEMA.ConfGeneral.UTC);
|
|
||||||
$('#utc').selectpicker('render');
|
|
||||||
// Control para el audio
|
|
||||||
if (configGeneralEMA.ConfGeneral.Audio === false) {
|
|
||||||
$('#vocesAudioDiv').attr('disabled', true);
|
|
||||||
$('#vocesAudioDiv').val('');
|
|
||||||
$('#vocesAudioDiv').hide();
|
|
||||||
} else {
|
|
||||||
$('#vocesAudioDiv').attr('disabled', false);
|
|
||||||
$('#vocesAudioDiv').show();
|
|
||||||
if (configGeneralEMA.ConfGeneral.audioVoces === null || typeof configGeneralEMA.ConfGeneral.audioVoces === 'undefined') { $('#vocesAudio').val(voice[0].name); } else { $('#vocesAudio').val(configGeneralEMA.ConfGeneral.audioVoces); }
|
|
||||||
}
|
|
||||||
$('#vocesAudio').selectpicker('render');
|
|
||||||
// Control para el modo
|
|
||||||
if (['Recolector_USB', 'Recolector_IP'].includes($('#Modo').val())) {
|
|
||||||
$('#LlaveR').attr('disabled', true);
|
|
||||||
$('#LlaveR').val('');
|
|
||||||
$('#LlaveR').hide();
|
|
||||||
} else {
|
|
||||||
$('#LlaveR').attr('disabled', false);
|
|
||||||
$('#LlaveR').show();
|
|
||||||
$('#Llave_R').val(configGeneralEMA.ConfGeneral.Llave_R);
|
|
||||||
}
|
|
||||||
// Control para el SMTP
|
|
||||||
if ($('#Tipo_SMTP').val() === 'Deshabilitado') {
|
|
||||||
$('#Usuario_SMTP').attr('disabled', true);
|
|
||||||
$('#Contrasenia_SMTP').attr('disabled', true);
|
|
||||||
$('#Puerto_SMTP').attr('disabled', true);
|
|
||||||
$('#Server_SMTP').attr('disabled', true);
|
|
||||||
$('#Server').hide();
|
|
||||||
$('#puerto').hide();
|
|
||||||
} else {
|
|
||||||
$('#Usuario_SMTP').attr('disabled', false);
|
|
||||||
$('#Contrasenia_SMTP').attr('disabled', false);
|
|
||||||
$('#Server_SMTP').attr('disabled', false);
|
|
||||||
$('#Puerto_SMTP').attr('disabled', false);
|
|
||||||
$('#Usuario_SMTP').val(configGeneralEMA.ConfEmail.Usuario);
|
|
||||||
$('#Contrasenia_SMTP').val(configGeneralEMA.ConfEmail.Password);
|
|
||||||
$('#Server_SMTP').val(configGeneralEMA.ConfEmail.Server);
|
|
||||||
$('#Puerto_SMTP').val(configGeneralEMA.ConfEmail.Puerto);
|
|
||||||
if ($('#Tipo_SMTP').val() === 'Manual') {
|
|
||||||
$('#Server_SMTP').attr('disabled', false);
|
|
||||||
$('#Puerto_SMTP').attr('disabled', false);
|
|
||||||
$('#puerto').show();
|
|
||||||
$('#Server').show();
|
|
||||||
} else {
|
|
||||||
$('#puerto').hide();
|
|
||||||
$('#Server').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
console.log('No existe el menu seleccionado: ' + elemento);
|
console.log('No existe el menu seleccionado: ' + elemento);
|
||||||
}
|
}
|
||||||
document.getElementById("actualizando_inicio").hidden = true;
|
document.getElementById("actualizando_inicio").hidden = true;
|
||||||
document.getElementById("actualizando_inicio").style.display = "none";
|
document.getElementById("actualizando_inicio").style.display = "none";
|
||||||
|
$('[data-bs-toggle="tooltip"]').each(function () {
|
||||||
|
bootstrap.Tooltip.getOrCreateInstance(this);
|
||||||
|
});
|
||||||
$(seleccion).fadeIn('fast');
|
$(seleccion).fadeIn('fast');
|
||||||
seleccion = null;datosArchivo = null;
|
seleccion = null;datosArchivo = null;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/* Para Distintas resoluciones */
|
/* Para Distintas resoluciones */
|
||||||
@media (min-width: 350px) {
|
@media (min-width: 350px) {
|
||||||
html {
|
html {
|
||||||
overflow-y: hidden;
|
overflow-y: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@ -44,8 +44,8 @@
|
|||||||
|
|
||||||
@media (min-width: 800px) {
|
@media (min-width: 800px) {
|
||||||
html {
|
html {
|
||||||
overflow-x: hidden;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
@ -91,12 +91,12 @@
|
|||||||
|
|
||||||
@media (min-width: 1199px) {
|
@media (min-width: 1199px) {
|
||||||
html {
|
html {
|
||||||
overflow-x: hidden;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 1800px !important;
|
max-width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@ -137,41 +137,41 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.zoom {
|
.zoom {
|
||||||
padding: -5px;
|
padding: 0;
|
||||||
transition: transform .2s;
|
transition: transform .2s;
|
||||||
/* Animation */
|
/* Animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom:hover {
|
.zoom:hover {
|
||||||
opacity: 4.7;
|
opacity: 1;
|
||||||
transform: scale(2.1);
|
transform: scale(2.1);
|
||||||
/* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
|
/* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dia {
|
body.dia {
|
||||||
font-family: monospace !important;
|
font-family: monospace !important;
|
||||||
background-image: url('/gui_common/img/fondo/dia.webp');
|
background-image: url('../img/fondo/dia.webp');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dia_lluvia {
|
body.dia_lluvia {
|
||||||
font-family: monospace !important;
|
font-family: monospace !important;
|
||||||
background-image: url('/gui_common/img/fondo/lluvia_dia.webp');
|
background-image: url('../img/fondo/lluvia_dia.webp');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.noche {
|
body.noche {
|
||||||
font-family: monospace !important;
|
font-family: monospace !important;
|
||||||
background-image: url('/gui_common/img/fondo/noche.webp');
|
background-image: url('../img/fondo/noche.webp');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.noche_lluvia {
|
body.noche_lluvia {
|
||||||
font-family: monospace !important;
|
font-family: monospace !important;
|
||||||
background-image: url('/gui_common/img/fondo/lluvia_noche.webp');
|
background-image: url('../img/fondo/lluvia_noche.webp');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ body.noche_lluvia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
|
table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
|
||||||
color: black !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*GENERALES */
|
/*GENERALES */
|
||||||
@ -213,7 +213,7 @@ h6,
|
|||||||
.h4,
|
.h4,
|
||||||
.h5,
|
.h5,
|
||||||
.h6 {
|
.h6 {
|
||||||
font-family: ari !important;
|
font-family: Arial, sans-serif !important;
|
||||||
color: #ffffff !important;
|
color: #ffffff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,14 +245,12 @@ h6,
|
|||||||
|
|
||||||
.notifyjs-foo-base .title {
|
.notifyjs-foo-base .title {
|
||||||
width: 500px;
|
width: 500px;
|
||||||
float: center;
|
|
||||||
margin: 10px 0 0 10px;
|
margin: 10px 0 0 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notifyjs-foo-base .buttons {
|
.notifyjs-foo-base .buttons {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
float: center;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 20px 0 0 0px;
|
margin: 20px 0 0 0px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
@ -335,7 +333,7 @@ hr.style17:after {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
padding: 0 -1px;
|
padding: 0;
|
||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
color: #8c8b8b;
|
color: #8c8b8b;
|
||||||
font-size: 1px;
|
font-size: 1px;
|
||||||
@ -442,7 +440,8 @@ hr.style18:before {
|
|||||||
color: #FF8800
|
color: #FF8800
|
||||||
}
|
}
|
||||||
|
|
||||||
.jumbotron {
|
.ema-panel {
|
||||||
|
border-radius: 0.3rem;
|
||||||
background-color: #224a728a !important;
|
background-color: #224a728a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +499,6 @@ hr.style18:before {
|
|||||||
z-index: 1031;
|
z-index: 1031;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
}
|
}
|
||||||
@ -510,3 +508,63 @@ div.btn-group, div.btn-group-vertical{
|
|||||||
text-align: unset !important;
|
text-align: unset !important;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bootstrap 5 uses variables for table cell backgrounds and text. */
|
||||||
|
.table, table.dataTable {
|
||||||
|
--bs-table-color: #fff;
|
||||||
|
--bs-table-bg: transparent;
|
||||||
|
--bs-table-striped-color: #fff;
|
||||||
|
--bs-table-striped-bg: rgba(255, 255, 255, 0.05);
|
||||||
|
--bs-table-hover-color: #fff;
|
||||||
|
--bs-table-hover-bg: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
table.dataTable.table-bordered {
|
||||||
|
--bs-table-border-color: rgba(255, 255, 255, 0.65);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTables_wrapper .page-link {
|
||||||
|
color: var(--bs-pagination-color) !important;
|
||||||
|
}
|
||||||
|
.dataTables_wrapper .active > .page-link {
|
||||||
|
color: var(--bs-pagination-active-color) !important;
|
||||||
|
}
|
||||||
|
.dataTables_wrapper .disabled > .page-link {
|
||||||
|
color: var(--bs-pagination-disabled-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout stays readable at narrow widths without automatic zoom. */
|
||||||
|
#principal { width: 100%; padding-bottom: 2rem; }
|
||||||
|
#principal > .navbar { gap: .5rem; flex-wrap: wrap; }
|
||||||
|
#principal .container { width: 100%; max-width: 1800px; }
|
||||||
|
#config-form .row { row-gap: 1rem; }
|
||||||
|
#config-form input, #config-form select { max-width: 100%; min-width: 0; }
|
||||||
|
#config-form label { display: inline-block; margin-bottom: .35rem; }
|
||||||
|
#config-form .invalid-feedback { text-align: start; color: #ffb4b4; }
|
||||||
|
#config-status { margin-top: 1rem; }
|
||||||
|
.ema-panel { overflow-wrap: anywhere; }
|
||||||
|
.estado-estacion { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; margin: 1rem; }
|
||||||
|
.estado-tarjeta { display: flex; flex-direction: column; gap: .4rem; padding: .75rem; border: 1px solid #ffffff60; border-radius: .4rem; background: #102d4bd9; color: white; }
|
||||||
|
.estado-tarjeta .badge { white-space: normal; text-align: start; }
|
||||||
|
.estado-tarjeta small { overflow-wrap: anywhere; }
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.estado-estacion { grid-template-columns: 1fr; }
|
||||||
|
#principal .nav-link { padding: .5rem; font-size: .85rem; }
|
||||||
|
#principal .nav-tabs { flex-wrap: wrap; }
|
||||||
|
#principal .row > [class*="col-"] { min-width: 0; }
|
||||||
|
#principal > .container > .row > [class*="col-"] { width: 100%; }
|
||||||
|
.pre-scrollable-m { max-height: none; overflow-y: visible; }
|
||||||
|
}
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.notifyjs-container {
|
||||||
|
position: fixed !important;
|
||||||
|
inset: auto .75rem .75rem !important;
|
||||||
|
width: auto !important;
|
||||||
|
max-width: calc(100vw - 1.5rem);
|
||||||
|
}
|
||||||
|
.notifyjs-container > div {
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: normal;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
.notifyjs-arrow { display: none !important; }
|
||||||
|
}
|
||||||
|
|||||||
63
src/gui_common/js/configuracion-modelo.js
Normal file
63
src/gui_common/js/configuracion-modelo.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
(function (root, factory) {
|
||||||
|
const api = factory();
|
||||||
|
if (typeof module === 'object' && module.exports) module.exports = api;
|
||||||
|
if (root) root.ConfiguracionModelo = api;
|
||||||
|
})(typeof window !== 'undefined' ? window : null, function () {
|
||||||
|
const fields = {
|
||||||
|
NombreEstacion: ['ConfGeneral', 'NombreEstacion'], Modo: ['ConfGeneral', 'Modo'],
|
||||||
|
Tiempo_de_Recoleccion: ['ConfGeneral', 'Tiempo_de_Recoleccion', 'number'],
|
||||||
|
Debug: ['ConfGeneral', 'debug', 'number'], debugMB: ['ConfGeneral', 'debugTamanio', 'number'],
|
||||||
|
utc: ['ConfGeneral', 'UTC', 'number'], SistemaMetrico: ['ConfGeneral', 'SistemaMetrico'],
|
||||||
|
r_ip: ['ConfGeneral', 'IP'], r_puerto: ['ConfGeneral', 'Puerto'], r_path: ['ConfGeneral', 'Ruta'],
|
||||||
|
Llave_R: ['ConfGeneral', 'Llave_R'], inicio_auto: ['ConfGeneral', 'inicio_automatico', 'boolean'],
|
||||||
|
notificar_cambios: ['ConfGeneral', 'notificar_cambios', 'boolean'], audio: ['ConfGeneral', 'Audio', 'boolean'],
|
||||||
|
vocesAudio: ['ConfGeneral', 'audioVoces'], Tipo_SMTP: ['ConfEmail', 'Servicio'],
|
||||||
|
Usuario_SMTP: ['ConfEmail', 'Usuario'], Contrasenia_SMTP: ['ConfEmail', 'Password'],
|
||||||
|
Server_SMTP: ['ConfEmail', 'Server'], Puerto_SMTP: ['ConfEmail', 'Puerto'], Email_receptor: ['ConfEmail', 'ReceptorEmail']
|
||||||
|
};
|
||||||
|
function read(config) {
|
||||||
|
return Object.fromEntries(Object.entries(fields).map(([id, [section, key, type]]) => {
|
||||||
|
let value = config[section]?.[key];
|
||||||
|
if (id === 'Modo' && value === 'Recolector') value = 'Recolector_USB';
|
||||||
|
return [id, type === 'boolean' ? (value ? 'Activado' : 'Desactivado') : String(value ?? '')];
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function build(config, values) {
|
||||||
|
const result = JSON.parse(JSON.stringify(config));
|
||||||
|
for (const [id, [section, key, type]] of Object.entries(fields)) {
|
||||||
|
result[section] ||= {};
|
||||||
|
result[section][key] = type === 'boolean' ? values[id] === 'Activado' : type === 'number' ? Number(values[id]) : values[id];
|
||||||
|
}
|
||||||
|
result.ConfEmail.ActivarCorreos = values.Tipo_SMTP !== 'Deshabilitado';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function validate(values) {
|
||||||
|
const errors = {};
|
||||||
|
const text = id => String(values[id] ?? '').trim();
|
||||||
|
const required = (id, label) => { if (!text(id)) errors[id] = `Ingresá ${label}.`; };
|
||||||
|
const number = (id, min, max) => { const n = Number(values[id]); if (!text(id) || !Number.isInteger(n) || n < min || n > max) errors[id] = `Ingresá un número entero entre ${min} y ${max}.`; };
|
||||||
|
const email = id => { if (text(id) && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(text(id))) errors[id] = 'Ingresá un correo válido.'; };
|
||||||
|
required('NombreEstacion', 'el nombre de la estación');
|
||||||
|
if (text('NombreEstacion').length > 20) errors.NombreEstacion = 'Usá hasta 20 caracteres.';
|
||||||
|
if (!['Recolector_USB', 'Recolector_IP', 'Visor'].includes(values.Modo)) errors.Modo = 'Seleccioná un modo válido.';
|
||||||
|
if (!['SI', 'SA'].includes(values.SistemaMetrico)) errors.SistemaMetrico = 'Seleccioná las unidades.';
|
||||||
|
number('Tiempo_de_Recoleccion', 1, 86400); number('Debug', 0, 9); number('debugMB', 1, 10000); number('utc', -12, 14);
|
||||||
|
for (const id of ['inicio_auto', 'notificar_cambios', 'audio']) if (!['Activado', 'Desactivado'].includes(values[id])) errors[id] = 'Seleccioná Activado o Desactivado.';
|
||||||
|
email('Email_receptor');
|
||||||
|
if (values.Modo === 'Visor') required('Llave_R', 'la llave de lectura');
|
||||||
|
if (values.Modo === 'Recolector_IP') {
|
||||||
|
required('r_ip', 'la dirección IP');
|
||||||
|
if (text('r_ip') === 'false') errors.r_ip = 'Seleccioná una interfaz de red disponible.';
|
||||||
|
number('r_puerto', 1, 65535);
|
||||||
|
if (!/^\/[^\s]*$/.test(text('r_path'))) errors.r_path = 'La ruta debe comenzar con / y no contener espacios.';
|
||||||
|
}
|
||||||
|
if (!['Deshabilitado', 'Gmail', 'Yahoo', 'Hotmail', 'Manual'].includes(values.Tipo_SMTP)) errors.Tipo_SMTP = 'Seleccioná un servicio de correo.';
|
||||||
|
if (values.Tipo_SMTP !== 'Deshabilitado') {
|
||||||
|
required('Usuario_SMTP', 'la cuenta de correo'); email('Usuario_SMTP');
|
||||||
|
required('Contrasenia_SMTP', 'la contraseña'); required('Email_receptor', 'el correo del administrador');
|
||||||
|
if (values.Tipo_SMTP === 'Manual') { required('Server_SMTP', 'el servidor SMTP'); number('Puerto_SMTP', 1, 65535); }
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
return { fields, read, build, validate };
|
||||||
|
});
|
||||||
141
src/gui_common/js/configuracion.js
Normal file
141
src/gui_common/js/configuracion.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/* Shared configuration form. Persistence is supplied by the desktop/web adapter. */
|
||||||
|
const ConfigUI = (() => {
|
||||||
|
let original, baseline = '', saving = false;
|
||||||
|
const form = () => document.getElementById('config-form');
|
||||||
|
const values = () => Object.fromEntries(Object.keys(ConfiguracionModelo.fields).map(id => [id, document.getElementById(id)?.value ?? '']));
|
||||||
|
const snapshot = () => JSON.stringify(values());
|
||||||
|
const dirty = () => !!form() && baseline !== snapshot();
|
||||||
|
let notification;
|
||||||
|
function notify(text, error) {
|
||||||
|
if (notification) {
|
||||||
|
bootstrap.Toast.getInstance(notification)?.dispose();
|
||||||
|
notification.remove();
|
||||||
|
}
|
||||||
|
const toast = document.createElement('div');
|
||||||
|
toast.className = 'toast position-fixed top-0 end-0 m-3 border-0 shadow text-bg-' + (error ? 'danger' : 'success');
|
||||||
|
toast.style.zIndex = '1090';
|
||||||
|
toast.style.maxWidth = 'calc(100vw - 2rem)';
|
||||||
|
toast.setAttribute('role', error ? 'alert' : 'status');
|
||||||
|
toast.setAttribute('aria-live', error ? 'assertive' : 'polite');
|
||||||
|
toast.setAttribute('aria-atomic', 'true');
|
||||||
|
const row = document.createElement('div');
|
||||||
|
row.className = 'd-flex';
|
||||||
|
const body = document.createElement('div');
|
||||||
|
body.className = 'toast-body';
|
||||||
|
const title = document.createElement('strong');
|
||||||
|
title.className = 'd-block mb-1';
|
||||||
|
title.textContent = error ? 'No se pudo guardar' : 'Configuración guardada';
|
||||||
|
const detail = document.createElement('div');
|
||||||
|
detail.textContent = text;
|
||||||
|
body.append(title, detail);
|
||||||
|
const close = document.createElement('button');
|
||||||
|
close.type = 'button';
|
||||||
|
close.className = 'btn-close btn-close-white me-2 m-auto';
|
||||||
|
close.setAttribute('aria-label', 'Cerrar notificación');
|
||||||
|
close.setAttribute('data-bs-dismiss', 'toast');
|
||||||
|
row.append(body, close);
|
||||||
|
toast.append(row);
|
||||||
|
document.body.append(toast);
|
||||||
|
notification = toast;
|
||||||
|
toast.addEventListener('hidden.bs.toast', () => {
|
||||||
|
bootstrap.Toast.getInstance(toast)?.dispose();
|
||||||
|
toast.remove();
|
||||||
|
if (notification === toast) notification = null;
|
||||||
|
});
|
||||||
|
new bootstrap.Toast(toast, {autohide: !error, delay: 5000}).show();
|
||||||
|
}
|
||||||
|
function message(text, error = false, floating = false) {
|
||||||
|
const status = document.getElementById('config-status');
|
||||||
|
if (status) { status.textContent = text; status.className = error ? 'text-danger' : 'text-white'; }
|
||||||
|
if (floating) notify(text, error);
|
||||||
|
}
|
||||||
|
function canLeave() {
|
||||||
|
if (saving) { message('Esperá a que termine el guardado.'); return false; }
|
||||||
|
if (!dirty()) return true;
|
||||||
|
if (!window.confirm('Tenés cambios sin guardar. ¿Querés descartarlos y salir?')) return false;
|
||||||
|
baseline = snapshot();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function visibility() {
|
||||||
|
const v = values();
|
||||||
|
for (const [id, visible] of Object.entries({bloque_secundario: v.Modo !== 'Recolector_USB', LlaveR: v.Modo === 'Visor', bloque_por_IP_WIFI: v.Modo === 'Recolector_IP', vocesAudioDiv: v.audio === 'Activado', Server: v.Tipo_SMTP === 'Manual', puerto: v.Tipo_SMTP === 'Manual'})) {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (element) element.hidden = !visible;
|
||||||
|
}
|
||||||
|
for (const id of ['Usuario_SMTP', 'Contrasenia_SMTP']) document.getElementById(id).disabled = v.Tipo_SMTP === 'Deshabilitado' || saving;
|
||||||
|
for (const id of ['Server_SMTP', 'Puerto_SMTP']) document.getElementById(id).disabled = v.Tipo_SMTP !== 'Manual' || saving;
|
||||||
|
}
|
||||||
|
function errors(fields) {
|
||||||
|
for (const id of Object.keys(ConfiguracionModelo.fields)) {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (!element) continue;
|
||||||
|
element.classList.toggle('is-invalid', !!fields[id]);
|
||||||
|
element.setAttribute('aria-invalid', String(!!fields[id]));
|
||||||
|
document.getElementById(id + '-error').textContent = fields[id] || '';
|
||||||
|
}
|
||||||
|
const first = Object.keys(fields)[0];
|
||||||
|
if (first) document.getElementById(first)?.focus();
|
||||||
|
}
|
||||||
|
function mount(config, interfaces = {}, voices = []) {
|
||||||
|
original = config;
|
||||||
|
const f = form();
|
||||||
|
if (!f) return;
|
||||||
|
const selected = ConfiguracionModelo.read(config);
|
||||||
|
const ip = document.getElementById('r_ip');
|
||||||
|
ip.replaceChildren();
|
||||||
|
const addresses = new Set(Object.values(interfaces).flat().filter(i => i.family === 'IPv4' && !i.internal).map(i => i.address));
|
||||||
|
if (selected.r_ip && selected.r_ip !== 'false') addresses.add(selected.r_ip);
|
||||||
|
for (const value of addresses) ip.add(new Option(value, value));
|
||||||
|
if (!ip.options.length) ip.add(new Option('Sin interfaces disponibles', ''));
|
||||||
|
const voice = document.getElementById('vocesAudio');
|
||||||
|
voice.replaceChildren();
|
||||||
|
const names = new Set(voices.map(v => v.name));
|
||||||
|
if (selected.vocesAudio) names.add(selected.vocesAudio);
|
||||||
|
for (const value of names) voice.add(new Option(value, value));
|
||||||
|
if (!voice.options.length) voice.add(new Option('Sin voces disponibles', ''));
|
||||||
|
for (const [id, value] of Object.entries(selected)) {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (element.tagName === 'SELECT' && value && ![...element.options].some(o => o.value === value)) element.add(new Option(value, value));
|
||||||
|
element.value = value;
|
||||||
|
element.setAttribute('aria-describedby', id + '-error');
|
||||||
|
if (!document.getElementById(id + '-error')) {
|
||||||
|
const feedback = document.createElement('div');
|
||||||
|
feedback.id = id + '-error'; feedback.className = 'invalid-feedback'; element.after(feedback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visibility(); baseline = snapshot(); errors({}); message('Sin cambios pendientes.');
|
||||||
|
f.oninput = f.onchange = () => { visibility(); message(dirty() ? 'Cambios sin guardar.' : 'Sin cambios pendientes.'); };
|
||||||
|
f.onsubmit = event => { event.preventDefault(); GuardarConf('conf'); };
|
||||||
|
}
|
||||||
|
async function save(persist) {
|
||||||
|
if (saving || !form()) return false;
|
||||||
|
const data = values();
|
||||||
|
const invalid = ConfiguracionModelo.validate(data);
|
||||||
|
errors(invalid);
|
||||||
|
if (Object.keys(invalid).length) { message('Revisá los campos marcados en el formulario.', true, true); return false; }
|
||||||
|
const draft = ConfiguracionModelo.build(original, data);
|
||||||
|
saving = true;
|
||||||
|
const controls = [...form().querySelectorAll('input, select, button')];
|
||||||
|
const disabled = controls.map(e => e.disabled);
|
||||||
|
controls.forEach(e => { e.disabled = true; });
|
||||||
|
message('Guardando…');
|
||||||
|
try {
|
||||||
|
await persist(draft);
|
||||||
|
original = draft; baseline = snapshot(); message('Configuración guardada.', false, true);
|
||||||
|
return draft;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.fields) errors(error.fields);
|
||||||
|
message(error.message || 'Tus cambios siguen en el formulario. Volvé a intentarlo.', true, true);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
saving = false;
|
||||||
|
controls.forEach((e, i) => { e.disabled = disabled[i]; });
|
||||||
|
visibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('click', event => {
|
||||||
|
if (event.target.closest('[data-bs-toggle="tab"], #Wclo') && !canLeave()) { event.preventDefault(); event.stopImmediatePropagation(); }
|
||||||
|
}, true);
|
||||||
|
window.addEventListener('beforeunload', event => { if (dirty() || saving) { event.preventDefault(); event.returnValue = ''; } });
|
||||||
|
return {mount, save, dirty, canLeave, visibility};
|
||||||
|
})();
|
||||||
60
src/gui_common/js/estado.js
Normal file
60
src/gui_common/js/estado.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
const EstadoUI = (() => {
|
||||||
|
let timer, started = false;
|
||||||
|
function date(value, utc) {
|
||||||
|
const match = String(value || '').match(/^(\d{2})\/(\d{2})\/(\d{4})[ T](\d{2}):(\d{2}):(\d{2})/);
|
||||||
|
if (!match) return Date.parse(value);
|
||||||
|
if (Number.isFinite(Number(utc))) return Date.UTC(+match[3], +match[2] - 1, +match[1], +match[4], +match[5], +match[6]) - Number(utc) * 3600000;
|
||||||
|
return new Date(+match[3], +match[2] - 1, +match[1], +match[4], +match[5], +match[6]).getTime();
|
||||||
|
}
|
||||||
|
function render(data) {
|
||||||
|
const target = document.getElementById('estado-estacion');
|
||||||
|
if (!target) return;
|
||||||
|
target.replaceChildren();
|
||||||
|
const card = (title, text, detail, level = 'secondary', action) => {
|
||||||
|
const box = document.createElement('div'); box.className = 'estado-tarjeta';
|
||||||
|
const heading = document.createElement('strong'); heading.textContent = title;
|
||||||
|
const badge = document.createElement('span'); badge.className = 'badge text-bg-' + level; badge.textContent = text;
|
||||||
|
const help = document.createElement('small'); help.textContent = detail;
|
||||||
|
box.append(heading, badge, help);
|
||||||
|
if (action) {
|
||||||
|
const button = document.createElement('button'); button.className = 'btn btn-sm btn-outline-light'; button.textContent = action.label; button.onclick = action.run; box.append(button);
|
||||||
|
}
|
||||||
|
target.append(box);
|
||||||
|
};
|
||||||
|
if (data.error) {card('Conexión', 'Sin respuesta', data.error, 'danger', {label:'Reintentar', run: refresh}); return;}
|
||||||
|
const visor = data.mode === 'Visor';
|
||||||
|
const running = data.state?.[0] === true;
|
||||||
|
const sensorFault = data.sensors?.lost_sensor_contact || data.sensors?.rain_overflow;
|
||||||
|
const reason = data.state?.[1];
|
||||||
|
card('Conexión', visor ? 'Fuente remota' : running ? 'Recolector activo' : 'Recolector detenido',
|
||||||
|
reason || (sensorFault ? 'La estación informa un problema de sensores. Revisá alimentación y señal.' : visor ? 'La fecha de lectura indica la vigencia del dato recibido.' : running ? 'El proceso está activo; revisá la última lectura para confirmar recepción.' : 'Iniciá el recolector desde Inicio o revisá la configuración.'),
|
||||||
|
reason || sensorFault ? 'warning' : running ? 'success' : 'secondary');
|
||||||
|
const record = data.record;
|
||||||
|
const age = Date.now() - date(record?.fecha, data.utc);
|
||||||
|
const stale = Number.isFinite(age) && age > Math.max(120, Number(data.interval || 60) * 3) * 1000;
|
||||||
|
card('Última lectura', record?.fecha || 'Sin lecturas', stale ? 'La lectura no es reciente. Revisá conexión, sensores y horario de la estación.' : record?.fecha ? 'Último registro recibido.' : 'Esperando el primer registro.', stale ? 'warning' : record?.fecha ? 'success' : 'secondary');
|
||||||
|
const publications = Object.values(data.publications || {}).filter(p => p && p.fecha);
|
||||||
|
publications.sort((a,b) => (date(b.fecha, data.utc) || 0) - (date(a.fecha, data.utc) || 0));
|
||||||
|
const last = publications[0];
|
||||||
|
const failed = publications.find(p => p.estado !== true && !['Esperar', 'No enviado'].includes(p.estado));
|
||||||
|
card('Última publicación', last ? `${last.red}: ${last.fecha}` : visor ? 'No corresponde al modo visor' : 'Sin publicaciones',
|
||||||
|
failed ? `${failed.red}: ${failed.error || 'No se pudo publicar'}. Revisá la red y las credenciales.` : last ? (last.estado === true ? 'Envío confirmado por la red.' : 'La red indica que hay que esperar antes de enviar.') : 'Todavía no hay un envío confirmado.',
|
||||||
|
failed ? 'danger' : last?.estado === true ? 'success' : 'secondary');
|
||||||
|
}
|
||||||
|
async function refresh() {
|
||||||
|
clearTimeout(timer);
|
||||||
|
try {
|
||||||
|
const local = typeof _IS_NW !== 'undefined' && _IS_NW;
|
||||||
|
const config = typeof configGeneralEMA !== 'undefined' ? configGeneralEMA : null;
|
||||||
|
if (!config) throw new Error('Todavía no se pudo leer la configuración.');
|
||||||
|
let state, record, publications, sensors;
|
||||||
|
if (local) { state = EMA.Estado(); record = EMA.UltimoRegistro(); publications = EMA.UltimoPublicado(); sensors = EMA.EstadoSensores(); }
|
||||||
|
else [state, record, publications, sensors] = await Promise.all(['/EMA_Estado','/UltimoRegistro','/UltimoPublicado','/EstadoSensores'].map(url => $.ajax({url, timeout:5000})));
|
||||||
|
if (config.ConfGeneral.Modo === 'Visor' && typeof UltimoReg !== 'undefined') record = UltimoReg;
|
||||||
|
render({mode:config.ConfGeneral.Modo, interval:config.ConfGeneral.Tiempo_de_Recoleccion, utc:config.ConfGeneral.UTC, state, record, publications, sensors});
|
||||||
|
} catch (error) {render({error:'No se pudo consultar el estado. Comprobá que el servicio esté disponible.'});}
|
||||||
|
if (started) timer = setTimeout(refresh, 10000);
|
||||||
|
}
|
||||||
|
function start() { if (!started) {started = true; refresh();} }
|
||||||
|
return {start, refresh, render};
|
||||||
|
})();
|
||||||
23
src/gui_common/js/tablas.js
Normal file
23
src/gui_common/js/tablas.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const TablaUI = (() => {
|
||||||
|
const languageURL = new URL('../css/Spanish.json', document.currentScript.src).href;
|
||||||
|
function buttons() {
|
||||||
|
// The Bootstrap adapter defaults to btn-secondary; allow each action to choose its colour.
|
||||||
|
$.fn.dataTable.Buttons.defaults.dom.button.className = 'btn';
|
||||||
|
return [
|
||||||
|
{extend: 'copy', text: '📋 Copiar al portapapeles', className: 'btn-secondary'},
|
||||||
|
{extend: 'csv', text: '💾 Exportar CSV', className: 'btn-primary'}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
function options() { return {dom: 'Bfrtip', buttons: buttons(), language: {url: languageURL}, pageLength: 8, scrollX: true, autoWidth: false, destroy: true}; }
|
||||||
|
return {buttons, options};
|
||||||
|
})();
|
||||||
|
function MostrarTabla(datos, div, tabla) {
|
||||||
|
const container = $('#' + div);
|
||||||
|
const existing = container.find('table');
|
||||||
|
if (existing.length && $.fn.dataTable.isDataTable(existing[0])) existing.DataTable().destroy();
|
||||||
|
container.html(datos).show();
|
||||||
|
return $('#' + tabla).DataTable({...TablaUI.options(), initComplete() {
|
||||||
|
$('#actualizando').hide();
|
||||||
|
this.api().columns.adjust();
|
||||||
|
}});
|
||||||
|
}
|
||||||
@ -1,15 +1,16 @@
|
|||||||
'version:2025-10-08 (7.01)';
|
'version:2026-08-11 (7.21)';
|
||||||
//
|
//
|
||||||
// o---------------------------------------------------------------------------------o
|
// o---------------------------------------------------------------------------o
|
||||||
// | This file is part of the RGraph package - you can learn more at: |
|
// | This file is part of the RGraph package - you can learn more at: |
|
||||||
// | |
|
// | |
|
||||||
// | https://www.rgraph.net/license.html |
|
// | https://www.rgraph.net |
|
||||||
// | |
|
// | |
|
||||||
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
|
// | RGraph is dual-licensed under the Open Source GPL license. This means |
|
||||||
// | free to use and there are no restrictions on what you can use RGraph for! |
|
// | that it's free to use for any purpose. The GPL license does have |
|
||||||
// | If the GPL license does not suit you however, then there's an inexpensive |
|
// | consequences on the license of the software that you include it in, |
|
||||||
// | commercial license option available. See the URL above for more details. |
|
// | however. If this is not desirable, then there's an inexpensive commercial |
|
||||||
// o---------------------------------------------------------------------------------o
|
// | license option available. See the RGraph website for more details. |
|
||||||
|
// o---------------------------------------------------------------------------o
|
||||||
|
|
||||||
RGraph = window.RGraph || {isrgraph:true,isRGraph: true,rgraph:true};
|
RGraph = window.RGraph || {isrgraph:true,isRGraph: true,rgraph:true};
|
||||||
|
|
||||||
@ -47,16 +48,16 @@
|
|||||||
this.properties =
|
this.properties =
|
||||||
{
|
{
|
||||||
backgroundBarsCount: null,
|
backgroundBarsCount: null,
|
||||||
backgroundBarsColor1: 'rgba(0,0,0,0)',
|
backgroundBarsColor1: 'transparent',
|
||||||
backgroundBarsColor2: 'rgba(0,0,0,0)',
|
backgroundBarsColor2: 'transparent',
|
||||||
backgroundGrid: true,
|
backgroundGrid: true,
|
||||||
backgroundGridColor: '#ddd',
|
backgroundGridColor: '#eee',
|
||||||
backgroundGridLinewidth: 1,
|
backgroundGridLinewidth: 1,
|
||||||
backgroundGridHsize: 20,
|
backgroundGridHsize: 20,
|
||||||
backgroundGridVsize: 20,
|
backgroundGridVsize: 20,
|
||||||
backgroundGridVlines: true,
|
backgroundGridVlines: false,
|
||||||
backgroundGridHlines: true,
|
backgroundGridHlines: true,
|
||||||
backgroundGridBorder: true,
|
backgroundGridBorder: false,
|
||||||
backgroundGridAutofit: true,
|
backgroundGridAutofit: true,
|
||||||
backgroundGridAutofitAlign: true,
|
backgroundGridAutofitAlign: true,
|
||||||
backgroundGridHlinesCount: 5,
|
backgroundGridHlinesCount: 5,
|
||||||
@ -115,7 +116,7 @@
|
|||||||
labelsAboveUnitsPost:'',
|
labelsAboveUnitsPost:'',
|
||||||
labelsAboveFormatter:null,
|
labelsAboveFormatter:null,
|
||||||
|
|
||||||
yaxis: true,
|
yaxis: false,
|
||||||
yaxisLinewidth: 1,
|
yaxisLinewidth: 1,
|
||||||
yaxisColor: 'black',
|
yaxisColor: 'black',
|
||||||
yaxisTickmarks: true,
|
yaxisTickmarks: true,
|
||||||
@ -162,7 +163,8 @@
|
|||||||
yaxisTitleValign: null,
|
yaxisTitleValign: null,
|
||||||
yaxisTitleAccessible: null,
|
yaxisTitleAccessible: null,
|
||||||
|
|
||||||
xaxis: true,
|
xaxis: false,
|
||||||
|
xaxisPosition: 'bottom',
|
||||||
xaxisLinewidth: 1,
|
xaxisLinewidth: 1,
|
||||||
xaxisColor: 'black',
|
xaxisColor: 'black',
|
||||||
xaxisTickmarks: true,
|
xaxisTickmarks: true,
|
||||||
@ -235,22 +237,28 @@
|
|||||||
titleSubtitleOffsetx: 0,
|
titleSubtitleOffsetx: 0,
|
||||||
titleSubtitleOffsety: 0,
|
titleSubtitleOffsety: 0,
|
||||||
|
|
||||||
colorsStroke: 'rgba(0,0,0,0)',
|
colorsStroke: 'transparent',
|
||||||
colors: ['red','#0f0','blue','pink','orange','cyan','black','white','green','magenta'],
|
colors: RGraph.getColors(),
|
||||||
colorsSequential: false,
|
colorsSequential: false,
|
||||||
colorsReverse: false,
|
colorsReverse: false,
|
||||||
|
|
||||||
grouping: 'grouped',
|
grouping: 'grouped',
|
||||||
|
|
||||||
variant: 'bar',
|
variant: 'bar',
|
||||||
variantSketchVerticals: true,
|
variantSketchVerticals: true,
|
||||||
variantThreedXaxis: true,
|
variantThreedXaxis: true,
|
||||||
variantThreedYaxis: true,
|
variantThreedYaxis: true,
|
||||||
variantThreedAngle: 0.1,
|
variantThreedAngle: 0.1,
|
||||||
variantThreedOffsetx: 10,
|
variantThreedOffsetx: 10,
|
||||||
variantThreedOffsety: 5,
|
variantThreedOffsety: 5,
|
||||||
variantThreedXaxisColor: '#ddd',
|
variantThreedXaxisColor: '#ddd',
|
||||||
variantThreedYaxisColor: '#ddd',
|
variantThreedYaxisColor: '#ddd',
|
||||||
|
variantDumbbellLinewidth: 8,
|
||||||
|
variantDumbbellEndTop: true,
|
||||||
|
variantDumbbellEndBottom: true,
|
||||||
|
variantDumbbellEndRadius: 13,
|
||||||
|
variantDumbbellEndTopRadius: null,
|
||||||
|
variantDumbbellEndBottomRadius: null,
|
||||||
|
|
||||||
shadow: false,
|
shadow: false,
|
||||||
shadowColor: '#aaa',
|
shadowColor: '#aaa',
|
||||||
@ -284,8 +292,9 @@
|
|||||||
tooltipsPointerOffsety: 0,
|
tooltipsPointerOffsety: 0,
|
||||||
tooltipsPositionStatic: true,
|
tooltipsPositionStatic: true,
|
||||||
|
|
||||||
highlightStroke: 'rgba(0,0,0,0)',
|
highlightStroke: 'transparent',
|
||||||
highlightFill: 'rgba(255,255,255,0.7)',
|
highlightFill: 'rgba(255,255,255,0.7)',
|
||||||
|
highlightFade: true,
|
||||||
|
|
||||||
key: null,
|
key: null,
|
||||||
keyBackground: 'white',
|
keyBackground: 'white',
|
||||||
@ -345,17 +354,17 @@
|
|||||||
beveled: false,
|
beveled: false,
|
||||||
|
|
||||||
errorbars: false,
|
errorbars: false,
|
||||||
errorbarsColor: 'black',
|
errorbarsColor: 'black',
|
||||||
errorbarsCapped: true,
|
errorbarsCapped: true,
|
||||||
errorbarsCappedWidth: 14,
|
errorbarsCappedWidth: 14,
|
||||||
errorbarsLinewidth: 1,
|
errorbarsLinewidth: 1,
|
||||||
|
|
||||||
combinedEffect: null,
|
combinedEffect: null,
|
||||||
combinedEffectOptions: null,
|
combinedEffectOptions: null,
|
||||||
combinedEffectCallback: null,
|
combinedEffectCallback: null,
|
||||||
|
|
||||||
corners: 'square',
|
corners: 'round',
|
||||||
cornersRoundRadius: 10,
|
cornersRoundRadius: 5,
|
||||||
cornersRoundLeft: true,
|
cornersRoundLeft: true,
|
||||||
cornersRoundRight: true,
|
cornersRoundRight: true,
|
||||||
cornersRoundLeftRadius: null,
|
cornersRoundLeftRadius: null,
|
||||||
@ -363,13 +372,18 @@
|
|||||||
|
|
||||||
responsive: null,
|
responsive: null,
|
||||||
|
|
||||||
clearto: 'rgba(0,0,0,0)',
|
clearto: 'transparent',
|
||||||
|
|
||||||
|
style: null,
|
||||||
|
|
||||||
events: {},
|
events: {},
|
||||||
|
clip: null,
|
||||||
|
|
||||||
scale: true,
|
scale: true,
|
||||||
scaleFactor: 2,
|
scaleFactor: 2,
|
||||||
antialiasTranslate: false
|
antialiasTranslate: false,
|
||||||
|
|
||||||
|
style: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -434,6 +448,10 @@
|
|||||||
'titleSubtitleOffsety',
|
'titleSubtitleOffsety',
|
||||||
'variantThreedOffsetx',
|
'variantThreedOffsetx',
|
||||||
'variantThreedOffsety',
|
'variantThreedOffsety',
|
||||||
|
'variantDumbbellLinewidth',
|
||||||
|
'variantDumbbellEndRadius',
|
||||||
|
'variantDumbbellEndTopRadius',
|
||||||
|
'variantDumbbellEndBottomRadius',
|
||||||
'shadowOffsetx',
|
'shadowOffsetx',
|
||||||
'shadowOffsety',
|
'shadowOffsety',
|
||||||
'shadowBlur',
|
'shadowBlur',
|
||||||
@ -674,7 +692,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any CSS that has been specified to the document.
|
||||||
|
// This is general CSS and does not necessarily have to
|
||||||
|
// pertain to the canvas tag. It only gets added once
|
||||||
|
// to the document no matter how many times this draw
|
||||||
|
// function is called.
|
||||||
|
//
|
||||||
|
// Add the CSS to a <style> block in the <head>.
|
||||||
|
RGraph.addConfigurationBasedCSS(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -693,8 +719,40 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MUST be the THIRD thing done!
|
// MUST be the THIRD thing done!
|
||||||
if (typeof properties.backgroundImage === 'string') {
|
if (typeof properties.backgroundImage === 'string' && properties.backgroundImage) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install clipping for the background image. This
|
||||||
|
// is not the main installation of clipping - it's
|
||||||
|
// just for the background image.
|
||||||
|
//
|
||||||
|
// The this.scale2 check means that clipping is only
|
||||||
|
// installed if that variable is present - ie this
|
||||||
|
// is most likely a redraw and the necessary things
|
||||||
|
// have been calculated so clipping can be
|
||||||
|
// installed correctly.
|
||||||
|
//
|
||||||
|
if (!RGraph.isNullish(this.properties.clip) && this.scale2) {
|
||||||
|
RGraph.clipTo.start(this, this.properties.clip);
|
||||||
|
}
|
||||||
|
|
||||||
RGraph.drawBackgroundImage(this);
|
RGraph.drawBackgroundImage(this);
|
||||||
|
|
||||||
|
if (!RGraph.isNullish(this.properties.clip) && this.scale2) {
|
||||||
|
RGraph.clipTo.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// If 3D is enabled then turn off rounded corners
|
||||||
|
// because it doesn't look correct.
|
||||||
|
if (this.properties.variant === '3d' && this.properties.corners === 'round') {
|
||||||
|
this.properties.corners = 'square'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -797,10 +855,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// If a dumbbell chart is being drawn then a few
|
||||||
|
// properties need to be massaged
|
||||||
|
if (!this.properties.colorsDumbbell && this.properties.variant === 'dumbbell') {
|
||||||
|
this.set({
|
||||||
|
colorsDumbbell: this.get('colors')
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.set({
|
||||||
|
colors: ['#0000']
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Work out the max value
|
// Work out the max value
|
||||||
//
|
//
|
||||||
if (properties.yaxisScaleMax) {
|
if (this.properties.yaxisScaleMax) {
|
||||||
|
|
||||||
this.scale2 = RGraph.getScale({object: this, options: {
|
this.scale2 = RGraph.getScale({object: this, options: {
|
||||||
'scale.max': properties.yaxisScaleMax,
|
'scale.max': properties.yaxisScaleMax,
|
||||||
@ -878,6 +950,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.scale2 = RGraph.getScale({object: this, options: {
|
this.scale2 = RGraph.getScale({object: this, options: {
|
||||||
'scale.max': this.max,
|
'scale.max': this.max,
|
||||||
'scale.min': properties.yaxisScaleMin,
|
'scale.min': properties.yaxisScaleMin,
|
||||||
@ -928,9 +1006,19 @@
|
|||||||
// this.drawAxes();
|
// this.drawAxes();
|
||||||
// this.drawbars();
|
// this.drawbars();
|
||||||
//} else {
|
//} else {
|
||||||
this.drawbars();
|
this.drawbars();
|
||||||
this.drawAxes();
|
this.drawAxes();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Draw the dumbbell bars variant Draw this here
|
||||||
|
// so that the dumbells are drawn over the axes.
|
||||||
|
//
|
||||||
|
if (this.properties.variant === 'dumbbell') {
|
||||||
|
this.drawdumbbell();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.drawLabels();
|
this.drawLabels();
|
||||||
|
|
||||||
|
|
||||||
@ -1092,11 +1180,11 @@
|
|||||||
//
|
//
|
||||||
if (properties.xaxisLabels && properties.xaxisLabels.length) {
|
if (properties.xaxisLabels && properties.xaxisLabels.length) {
|
||||||
if (typeof properties.xaxisLabels === 'string') {
|
if (typeof properties.xaxisLabels === 'string') {
|
||||||
properties.xaxisLabels = RGraph.arrayPad({
|
properties.xaxisLabels = RGraph.arrayPad(
|
||||||
array: [],
|
[],
|
||||||
length: this.data.length,
|
this.data.length,
|
||||||
value: properties.xaxisLabels
|
properties.xaxisLabels
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label substitution
|
// Label substitution
|
||||||
@ -1164,7 +1252,7 @@
|
|||||||
RGraph.drawBars(this);
|
RGraph.drawBars(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var variant = properties.variant;
|
var variant = this.properties.variant;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Draw the 3D axes is necessary
|
// Draw the 3D axes is necessary
|
||||||
@ -1300,7 +1388,7 @@
|
|||||||
this.context.fillStyle = colors[i];
|
this.context.fillStyle = colors[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (variant == 'sketch') {
|
if (variant === 'sketch') {
|
||||||
|
|
||||||
this.context.lineCap = 'round';
|
this.context.lineCap = 'round';
|
||||||
|
|
||||||
@ -1360,21 +1448,21 @@
|
|||||||
this.context.stroke();
|
this.context.stroke();
|
||||||
|
|
||||||
// Regular bar
|
// Regular bar
|
||||||
} else if (variant == 'bar' || variant == '3d' || variant == 'glass' || variant == 'bevel') {
|
} else if (variant === 'bar' || variant === '3d' || variant === 'glass' || variant === 'bevel' || variant === 'dumbbell') {
|
||||||
|
|
||||||
if (variant == 'glass') {
|
if (variant == 'glass') {
|
||||||
RGraph.roundedRect({
|
RGraph.roundedRect(
|
||||||
context: this.context,
|
this.context,
|
||||||
x: x + hmargin,
|
x + hmargin,
|
||||||
y: y,
|
y,
|
||||||
width: barWidth,
|
barWidth,
|
||||||
height: height,
|
height,
|
||||||
radius: RGraph.isNumber(properties.cornersRoundRadius) ? properties.cornersRoundRadius : 5,
|
RGraph.isNumber(properties.cornersRoundRadius) ? properties.cornersRoundRadius : 5,
|
||||||
roundtl: this.data[i] > 0,
|
this.data[i] > 0,
|
||||||
roundtr: this.data[i] > 0,
|
this.data[i] > 0,
|
||||||
roundbl: this.data[i] < 0,
|
this.data[i] < 0,
|
||||||
roundbr: this.data[i] < 0
|
this.data[i] < 0
|
||||||
});
|
);
|
||||||
this.context.stroke();
|
this.context.stroke();
|
||||||
this.context.fill();
|
this.context.fill();
|
||||||
} else {
|
} else {
|
||||||
@ -1546,7 +1634,7 @@ this.context.lineTo(
|
|||||||
|
|
||||||
|
|
||||||
// Dot chart
|
// Dot chart
|
||||||
} else if (variant == 'dot') {
|
} else if (variant === 'dot') {
|
||||||
|
|
||||||
|
|
||||||
var scaleFactor = RGraph.getScaleFactor(this);
|
var scaleFactor = RGraph.getScaleFactor(this);
|
||||||
@ -2439,66 +2527,101 @@ this.context.lineTo(
|
|||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Each object type has its own Highlight() function which highlights the appropriate shape
|
// Each object type has its own Highlight() function which
|
||||||
|
// highlights the appropriate shape.
|
||||||
//
|
//
|
||||||
// @param object shape The shape to highlight
|
// @param object shape The shape to highlight.
|
||||||
//
|
//
|
||||||
this.highlight = function (shape)
|
this.highlight = function (shape)
|
||||||
{
|
{
|
||||||
if (typeof properties.highlightStyle === 'function') {
|
// If the highlightFade property is not set then call
|
||||||
(properties.highlightStyle)(shape);
|
// the highlight function multiple times when the
|
||||||
|
// globalAlpha is set at varying levels of transparency
|
||||||
|
// to fade the highlight in. If the variable is set,
|
||||||
|
// however, then this call is probably a part of said
|
||||||
|
// highlighting process so don't call ourselves
|
||||||
|
// again - just highlight the chart.
|
||||||
|
if (this.properties.highlightFade && !this.highlight.highlighting) {
|
||||||
|
|
||||||
// Highlight all of the rects except this one - essentially
|
// Add a variable to the highlight function (this
|
||||||
// an inverted highlight
|
// function) to indicate that we're currently in
|
||||||
} else if (typeof properties.highlightStyle === 'string' && properties.highlightStyle === 'invert') {
|
// the process of highlighting.
|
||||||
for (var i=0; i<this.coords.length; ++i) {
|
this.highlight.highlighting = true;
|
||||||
if (i !== shape.sequentialIndex) {
|
|
||||||
this.path(
|
|
||||||
'b r % % % % s % f %',
|
|
||||||
this.coords[i][0],this.coords[i][1],this.coords[i][2],this.coords[i][3],
|
|
||||||
properties.highlightStroke,
|
|
||||||
properties.highlightFill
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redraw the X axis so the highlight doesn't
|
var obj = this;
|
||||||
// appear over the X axis. But not the X axis
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 20);
|
||||||
// labels or the title. This is new in
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 40);
|
||||||
// September 2024.
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 60);
|
||||||
RGraph.drawXAxis(this, {
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 80);
|
||||||
labels: false,
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 100);
|
||||||
title: false
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 120);
|
||||||
});
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 140);
|
||||||
} else {
|
setTimeout(function() {obj.highlight.highlighting = false;}, 400);
|
||||||
if (properties.grouping === 'stacked' && shape.index === 0 && properties.xaxisPosition === 'bottom') {
|
|
||||||
|
return;
|
||||||
this.context.beginPath();
|
}
|
||||||
this.context.strokeStyle = properties.highlightStroke;
|
|
||||||
this.context.fillStyle = properties.highlightFill;
|
|
||||||
|
|
||||||
if (properties.corners === 'round') {
|
|
||||||
this.roundedCornersRect(shape.x,shape.y,shape.width,shape.height);
|
|
||||||
} else {
|
|
||||||
this.context.rect(shape.x, shape.y, shape.width, shape.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.context.stroke();
|
RGraph.clipTo.callback(this, function (obj)
|
||||||
this.context.fill();
|
{
|
||||||
} else {
|
if (typeof obj.properties.highlightStyle === 'function') {
|
||||||
// Add the new highlight
|
(obj.properties.highlightStyle)(shape);
|
||||||
RGraph.Highlight.rect(this, shape);
|
|
||||||
|
// Highlight all of the rects except this one - essentially
|
||||||
|
// an inverted highlight
|
||||||
|
} else if (typeof obj.properties.highlightStyle === 'string' && obj.properties.highlightStyle === 'invert') {
|
||||||
|
for (var i=0; i<obj.coords.length; ++i) {
|
||||||
|
if (i !== shape.sequentialIndex) {
|
||||||
|
obj.path(
|
||||||
|
'b r % % % % s % f %',
|
||||||
|
obj.coords[i][0],obj.coords[i][1],obj.coords[i][2],obj.coords[i][3],
|
||||||
|
obj.properties.highlightStroke,
|
||||||
|
obj.properties.highlightFill
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Redraw the X axis so the highlight doesn't
|
// Redraw the X axis so the highlight doesn't
|
||||||
// appear over the X axis. But not the X axis
|
// appear over the X axis. But not the X axis
|
||||||
// labels or the title. This is new in
|
// labels or the title. This is new in
|
||||||
// September 2024.
|
// September 2024.
|
||||||
RGraph.drawXAxis(this, {
|
if (obj.properties.variant !== 'dumbbell') {
|
||||||
labels: false,
|
RGraph.drawXAxis(obj, {
|
||||||
title: false
|
labels: false,
|
||||||
});
|
title: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (properties.grouping === 'stacked' && shape.index === 0 && obj.properties.xaxisPosition === 'bottom') {
|
||||||
|
|
||||||
|
obj.context.beginPath();
|
||||||
|
obj.context.strokeStyle = obj.properties.highlightStroke;
|
||||||
|
obj.context.fillStyle = obj.properties.highlightFill;
|
||||||
|
|
||||||
|
if (obj.properties.corners === 'round') {
|
||||||
|
obj.roundedCornersRect(shape.x,shape.y,shape.width,shape.height);
|
||||||
|
} else {
|
||||||
|
obj.context.rect(shape.x, shape.y, shape.width, shape.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.context.stroke();
|
||||||
|
obj.context.fill();
|
||||||
|
} else {
|
||||||
|
// Add the new highlight
|
||||||
|
RGraph.Highlight.rect(obj, shape);
|
||||||
|
|
||||||
|
// Redraw the X axis so the highlight doesn't
|
||||||
|
// appear over the X axis. But not the X axis
|
||||||
|
// labels or the title. This is new in
|
||||||
|
// September 2024.
|
||||||
|
if (obj.properties.variant !== 'dumbbell') {
|
||||||
|
RGraph.drawXAxis(obj, {
|
||||||
|
labels: false,
|
||||||
|
title: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}); // End of clipping callback function.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2523,13 +2646,19 @@ this.context.lineTo(
|
|||||||
mouseXY[1] -= adjustment;
|
mouseXY[1] -= adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dbEndTopradius = 0;
|
||||||
|
var dbEndBottomradius = 0;
|
||||||
|
|
||||||
|
if (this.properties.variant === 'dumbbell') {
|
||||||
|
dbEndTopradius = this.properties.variantDumbbellEndTopRadius || this.properties.variantDumbbellEndRadius;
|
||||||
|
dbEndBottomradius = this.properties.variantDumbbellEndBottomRadius || this.properties.variantDumbbellEndRadius;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
mouseXY[0] >= properties.marginLeft
|
mouseXY[0] >= this.properties.marginLeft
|
||||||
&& mouseXY[0] <= (this.canvas.width - properties.marginRight)
|
&& mouseXY[0] <= (this.canvas.width - this.properties.marginRight)
|
||||||
&& mouseXY[1] >= properties.marginTop
|
&& mouseXY[1] >= this.properties.marginTop - dbEndTopradius
|
||||||
&& mouseXY[1] <= (this.canvas.height - properties.marginBottom)
|
&& mouseXY[1] <= (this.canvas.height - this.properties.marginBottom + dbEndBottomradius)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@ -2679,7 +2808,10 @@ this.context.lineTo(
|
|||||||
|
|
||||||
// Allow for JSON gradients
|
// Allow for JSON gradients
|
||||||
if (color.match(/^gradient\(({.*})\)$/i)) {
|
if (color.match(/^gradient\(({.*})\)$/i)) {
|
||||||
return RGraph.parseJSONGradient({object: this, def: RegExp.$1});
|
return RGraph.parseJSONGradient({
|
||||||
|
object: this,
|
||||||
|
def: RegExp.$1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3409,7 +3541,7 @@ this.context.lineTo(
|
|||||||
|
|
||||||
// Callback
|
// Callback
|
||||||
var opt = arguments[0] || {},
|
var opt = arguments[0] || {},
|
||||||
frames = opt.frames || 30,
|
frames = opt.frames || 60,
|
||||||
frame = 0,
|
frame = 0,
|
||||||
callback = arguments[1] || function () {},
|
callback = arguments[1] || function () {},
|
||||||
obj = this,
|
obj = this,
|
||||||
@ -3796,7 +3928,35 @@ this.context.lineTo(
|
|||||||
{
|
{
|
||||||
var indexes = RGraph.sequentialIndexToGrouped(opt.index, this.data);
|
var indexes = RGraph.sequentialIndexToGrouped(opt.index, this.data);
|
||||||
var values = this.data[indexes[0]];
|
var values = this.data[indexes[0]];
|
||||||
|
|
||||||
|
|
||||||
|
// This makes dumbbell charts work correctly
|
||||||
|
//
|
||||||
|
// Match the current index with the correct group/index
|
||||||
|
// values by looking through the coords2 array using the
|
||||||
|
// current mouse position.
|
||||||
|
if (this.properties.variant === 'dumbbell') {
|
||||||
|
|
||||||
|
var mouseXY = RGraph.getMouseXY(window.event);
|
||||||
|
|
||||||
|
outer:
|
||||||
|
for (var i=0; i<this.coords2.length; ++i) {
|
||||||
|
for (var j=0; j<this.coords2[i].length; ++j) {
|
||||||
|
if (
|
||||||
|
mouseXY[0] > this.coords2[i][j][0]
|
||||||
|
&& mouseXY[0] < (this.coords2[i][j][0] + this.coords2[i][j][2])
|
||||||
|
&& mouseXY[1] > this.coords2[i][j][1]
|
||||||
|
&& mouseXY[1] < (this.coords2[i][j][1] + this.coords2[i][j][3])
|
||||||
|
) {
|
||||||
|
|
||||||
|
indexes = [i, j];
|
||||||
|
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof values === 'number') {
|
if (typeof values === 'number') {
|
||||||
values = [values];
|
values = [values];
|
||||||
}
|
}
|
||||||
@ -4323,6 +4483,261 @@ this.context.lineTo(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Draw a dumbbell chart
|
||||||
|
//
|
||||||
|
this.drawdumbbell = function ()
|
||||||
|
{
|
||||||
|
var dumbbellCoords = [];
|
||||||
|
var obj = this;
|
||||||
|
var seq = 0;
|
||||||
|
//var y = obj.getYCoord(this.data[0]);
|
||||||
|
|
||||||
|
this.coords = [];
|
||||||
|
this.coords2 = [];
|
||||||
|
|
||||||
|
this.data.forEach(function (v, k, arr)
|
||||||
|
{
|
||||||
|
var section = ((obj.canvas.width - obj.properties.marginLeft - obj.properties.marginRight) / obj.data.length);
|
||||||
|
var coordX = (section * k) + obj.properties.marginLeft + (section / 2);
|
||||||
|
var coordW = obj.properties.variantDumbbellEndRadius;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (obj.properties.shadow) {
|
||||||
|
RGraph.setShadow(
|
||||||
|
obj,
|
||||||
|
obj.properties.shadowColor,
|
||||||
|
obj.properties.shadowOffsetx,
|
||||||
|
obj.properties.shadowOffsety,
|
||||||
|
obj.properties.shadowBlur
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO Need to convert this if condition
|
||||||
|
//
|
||||||
|
if (v.length > 2) {
|
||||||
|
|
||||||
|
obj.coords2[k] = [];
|
||||||
|
|
||||||
|
for (var j=1; j<v.length; ++j) {
|
||||||
|
|
||||||
|
var coordY = obj.getYCoord(v[j]);
|
||||||
|
var coordH = obj.getYCoord(v[j - 1]) - obj.getYCoord(v[j]);
|
||||||
|
|
||||||
|
obj.path('b r % % % %',
|
||||||
|
coordX,
|
||||||
|
coordY,
|
||||||
|
coordW,
|
||||||
|
coordH//(coordH * 2) + (2 * obj.properties.shadowOffsety)
|
||||||
|
);
|
||||||
|
|
||||||
|
obj.pathDumbbell(
|
||||||
|
coordX,
|
||||||
|
coordY,
|
||||||
|
coordW,
|
||||||
|
coordH,
|
||||||
|
j === (v.length - 1) && (RGraph.isNull(obj.properties.variantDumbbellEndTop) || obj.properties.variantDumbbellEndTop),
|
||||||
|
j === 1 && (RGraph.isNull(obj.properties.variantDumbbellEndBottom) || obj.properties.variantDumbbellEndBottom)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the rect to the canvas
|
||||||
|
if (obj.properties.colorsSequential) {
|
||||||
|
obj.path('f ' + obj.properties.colorsDumbbell[seq]);
|
||||||
|
} else {
|
||||||
|
obj.path('f ' + obj.properties.colorsDumbbell[j - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Determine the height of the
|
||||||
|
// hotspot
|
||||||
|
var radius = Math.max(
|
||||||
|
(obj.properties.variantDumbbellEndTopRadius || obj.properties.variantDumbbellEndTopRadius || 0),
|
||||||
|
(obj.properties.variantDumbbellEndBottomRadius || obj.properties.variantDumbbellEndBottomRadius || 0)
|
||||||
|
);
|
||||||
|
radius = Math.max(coordW, radius);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate the shadowOffset so that the
|
||||||
|
// highlight covers the shadow as well.
|
||||||
|
//
|
||||||
|
var shadowOffset = Math.max(
|
||||||
|
Math.abs(obj.properties.shadowOffsetx),
|
||||||
|
Math.abs(obj.properties.shadowOffsety)
|
||||||
|
);
|
||||||
|
|
||||||
|
var coords = [
|
||||||
|
coordX - radius,
|
||||||
|
coordY - (j === (v.length - 1) ? radius : 0),
|
||||||
|
coordW + (2 * radius),
|
||||||
|
coordH + (j === 1 || (j === v.length - 1) ? radius : 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Modify the coords so that the
|
||||||
|
// shadowOffset is taken into account when
|
||||||
|
// the highlight is added.
|
||||||
|
/*
|
||||||
|
// First segment
|
||||||
|
if (j === 1) {
|
||||||
|
|
||||||
|
// Horizontal offset manglement
|
||||||
|
if (obj.properties.shadowOffsetx < 0) {
|
||||||
|
coords[0] -= shadowOffset;
|
||||||
|
coords[2] += shadowOffset;
|
||||||
|
} else {
|
||||||
|
coords[2] += shadowOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical offset manglement
|
||||||
|
if (obj.properties.shadowOffsety > 0) {
|
||||||
|
coords[3] += shadowOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last segment
|
||||||
|
} else if (j === (v.length - 1) ) {
|
||||||
|
|
||||||
|
// Horizontal offset manglement
|
||||||
|
if (obj.properties.shadowOffsetx > 0) {
|
||||||
|
coords[2] += shadowOffset;
|
||||||
|
} else {
|
||||||
|
coords[0] -= shadowOffset;
|
||||||
|
coords[2] += shadowOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical offset manglement
|
||||||
|
if (obj.properties.shadowOffsety > 0) {
|
||||||
|
//coords[3] += shadowOffset;
|
||||||
|
} else if (obj.properties.shadowOffsety < 0) {
|
||||||
|
coords[1] -= shadowOffset;
|
||||||
|
coords[3] += shadowOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middle segments
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Vertical offset manglement
|
||||||
|
if (obj.properties.shadowOffsetx > 0) {
|
||||||
|
coords[2] += shadowOffset;
|
||||||
|
} else {
|
||||||
|
coords[0] -= shadowOffset;
|
||||||
|
coords[2] += shadowOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
obj.coords.push(coords);
|
||||||
|
obj.coords2[k].push(coords);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
seq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// //
|
||||||
|
// Need this so that the colors are
|
||||||
|
// used in the coorect order
|
||||||
|
//
|
||||||
|
seq--;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Only TWO Y values - so a minimum and a
|
||||||
|
// maximum.
|
||||||
|
} else {
|
||||||
|
|
||||||
|
obj.coords2[k] = [];
|
||||||
|
|
||||||
|
var coordH = obj.getYCoord(v[0]) - obj.getYCoord(v[1]);
|
||||||
|
var coordY = obj.getYCoord(v[0]) - coordH;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
obj.pathDumbbell(
|
||||||
|
coordX,
|
||||||
|
coordY,
|
||||||
|
coordW,
|
||||||
|
coordH
|
||||||
|
);
|
||||||
|
|
||||||
|
if (obj.properties.colorsSequential) {
|
||||||
|
obj.path('f ' + obj.properties.colorsDumbbell[k]);
|
||||||
|
} else {
|
||||||
|
obj.path('f ' + obj.properties.colorsDumbbell[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Store the dumbbell coordinates
|
||||||
|
var coords = [
|
||||||
|
coordX - obj.properties.variantDumbbellEndRadius - obj.properties.shadowOffsetx,
|
||||||
|
coordY - obj.properties.shadowOffsety - obj.properties.variantDumbbellEndRadius,
|
||||||
|
coordW + (2 * obj.properties.variantDumbbellEndRadius) + (2 * obj.properties.shadowOffsetx),
|
||||||
|
coordH + (2 * obj.properties.variantDumbbellEndRadius) + (2 * obj.properties.shadowOffsety)
|
||||||
|
];
|
||||||
|
|
||||||
|
obj.coords.push(coords);
|
||||||
|
obj.coords2[k].push(coords);
|
||||||
|
}
|
||||||
|
seq++;
|
||||||
|
RGraph.noShadow(obj);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Paths a dumbbell bar
|
||||||
|
//
|
||||||
|
this.pathDumbbell = function (x, y, w, h, topEnd = true, bottomEnd = true)
|
||||||
|
{
|
||||||
|
this.path(
|
||||||
|
'b r % % % %',
|
||||||
|
x + (this.properties.variantDumbbellLinewidth / 2) - 2,
|
||||||
|
y,
|
||||||
|
this.properties.variantDumbbellLinewidth,
|
||||||
|
h
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (this.properties.variantDumbbellEndTop && topEnd) {
|
||||||
|
this.path(
|
||||||
|
'm % % a % % % 0 6.29 false',
|
||||||
|
x + (w/2), y,
|
||||||
|
x + (w/2), y, (RGraph.isNumber(this.properties.variantDumbbellEndTopRadius) ? this.properties.variantDumbbellEndTopRadius : this.properties.variantDumbbellEndRadius)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (this.properties.variantDumbbellEndBottom && bottomEnd) {
|
||||||
|
this.path(
|
||||||
|
'm % % a % % % 0 6.29 false',
|
||||||
|
x + (w/2), y+h,
|
||||||
|
x + (w/2), y+h, (RGraph.isNumber(this.properties.variantDumbbellEndBottomRadius) ? this.properties.variantDumbbellEndBottomRadius : this.properties.variantDumbbellEndRadius)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,16 @@
|
|||||||
'version:2025-10-08 (7.01)';
|
'version:2026-08-11 (7.21)';
|
||||||
//
|
//
|
||||||
// o---------------------------------------------------------------------------------o
|
// o---------------------------------------------------------------------------o
|
||||||
// | This file is part of the RGraph package - you can learn more at: |
|
// | This file is part of the RGraph package - you can learn more at: |
|
||||||
// | |
|
// | |
|
||||||
// | https://www.rgraph.net/license.html |
|
// | https://www.rgraph.net |
|
||||||
// | |
|
// | |
|
||||||
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
|
// | RGraph is dual-licensed under the Open Source GPL license. This means |
|
||||||
// | free to use and there are no restrictions on what you can use RGraph for! |
|
// | that it's free to use for any purpose. The GPL license does have |
|
||||||
// | If the GPL license does not suit you however, then there's an inexpensive |
|
// | consequences on the license of the software that you include it in, |
|
||||||
// | commercial license option available. See the URL above for more details. |
|
// | however. If this is not desirable, then there's an inexpensive commercial |
|
||||||
// o---------------------------------------------------------------------------------o
|
// | license option available. See the RGraph website for more details. |
|
||||||
|
// o---------------------------------------------------------------------------o
|
||||||
|
|
||||||
//
|
//
|
||||||
// Having this here means that the RGraph libraries can be included in any order, instead of you having
|
// Having this here means that the RGraph libraries can be included in any order, instead of you having
|
||||||
@ -93,7 +94,6 @@
|
|||||||
|
|
||||||
width: null,
|
width: null,
|
||||||
height: null,
|
height: null,
|
||||||
|
|
||||||
halign: 'left',
|
halign: 'left',
|
||||||
valign: 'top',
|
valign: 'top',
|
||||||
|
|
||||||
@ -121,9 +121,12 @@
|
|||||||
tooltipsPointerOffsetx: 0,
|
tooltipsPointerOffsetx: 0,
|
||||||
tooltipsPointerOffsety: 0,
|
tooltipsPointerOffsety: 0,
|
||||||
tooltipsPositionStatic: true,
|
tooltipsPositionStatic: true,
|
||||||
|
tooltipsOffsetx: 0,
|
||||||
|
tooltipsOffsety: 0,
|
||||||
|
|
||||||
highlightStroke: 'rgba(0,0,0,0)',
|
highlightStroke: 'transparent',
|
||||||
highlightFill: 'rgba(255,255,255,0.7)',
|
highlightFill: 'rgba(255,255,255,0.7)',
|
||||||
|
highlightFade: true,
|
||||||
|
|
||||||
colorsAlpha: 1,
|
colorsAlpha: 1,
|
||||||
|
|
||||||
@ -132,19 +135,20 @@
|
|||||||
borderLinewidth: 1,
|
borderLinewidth: 1,
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
|
|
||||||
backgroundColor: 'rgba(0,0,0,0)',
|
backgroundColor: 'transparent',
|
||||||
|
|
||||||
text: null,
|
text: null,
|
||||||
|
|
||||||
clearto: 'rgba(0,0,0,0)',
|
clearto: 'transparent',
|
||||||
|
|
||||||
clip: null,
|
clip: null,
|
||||||
|
|
||||||
events: {},
|
events: {},
|
||||||
|
responsive: null,
|
||||||
scale: true,
|
scale: true,
|
||||||
scaleFactor: 2,
|
scaleFactor: 2,
|
||||||
antialiasTranslate: false
|
antialiasTranslate: false,
|
||||||
|
|
||||||
|
style: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -323,6 +327,18 @@
|
|||||||
// Fire the onbeforedraw event
|
// Fire the onbeforedraw event
|
||||||
//
|
//
|
||||||
RGraph.fireCustomEvent(this, 'onbeforedraw');
|
RGraph.fireCustomEvent(this, 'onbeforedraw');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any CSS that has been specified to the document.
|
||||||
|
// This is general CSS and does not necessarily have to
|
||||||
|
// pertain to the canvas tag. It only gets added once
|
||||||
|
// to the document no matter how many times this draw
|
||||||
|
// function is called.
|
||||||
|
//
|
||||||
|
// Add the CSS to a <style> block in the <head>.
|
||||||
|
RGraph.addConfigurationBasedCSS(this);
|
||||||
|
|
||||||
var scaleFactor = RGraph.getScaleFactor(this);
|
var scaleFactor = RGraph.getScaleFactor(this);
|
||||||
|
|
||||||
@ -406,7 +422,7 @@
|
|||||||
obj.alignmentProcessed = true;
|
obj.alignmentProcessed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -439,12 +455,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Need this to stop a rectangle being drawn around
|
||||||
|
// the llast path that was added to the canvas.
|
||||||
|
this.context.beginPath();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Draw a border around the image
|
// Draw a border around the image
|
||||||
//
|
//
|
||||||
/// !!!!!!
|
|
||||||
if (properties.border) {
|
if (properties.border) {
|
||||||
|
|
||||||
this.context.strokeStyle = properties.borderColor;
|
this.context.strokeStyle = properties.borderColor;
|
||||||
@ -478,7 +495,8 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.context.stroke();
|
this.context.stroke();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (borderRadius) {
|
if (borderRadius) {
|
||||||
this.context.save();
|
this.context.save();
|
||||||
@ -722,33 +740,62 @@
|
|||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Each object type has its own Highlight() function which highlights the appropriate shape
|
// Each object type has its own Highlight() function
|
||||||
|
// which highlights the appropriate shape.
|
||||||
//
|
//
|
||||||
// @param object shape The shape to highlight
|
// @param object shape The shape to highlight.
|
||||||
//
|
//
|
||||||
this.highlight = function (shape)
|
this.highlight = function (shape)
|
||||||
{
|
{
|
||||||
if (properties.tooltipsHighlight) {
|
// If the highlightFade property is not set then call
|
||||||
if (typeof properties.highlightStyle === 'function') {
|
// the highlight function multiple times when the
|
||||||
(properties.highlightStyle)(shape);
|
// globalAlpha is set at varying levels of transparency
|
||||||
} else {
|
// to fade the highlight in. If the variable is set,
|
||||||
this.path('b');
|
// however, then this call is probably a part of said
|
||||||
|
// highlighting process so don't call ourselves
|
||||||
|
// again - just highlight the chart.
|
||||||
|
if (this.properties.highlightFade && !this.highlight.highlighting) {
|
||||||
|
|
||||||
|
// Add a variable to the highlight function (this
|
||||||
|
// function) to indicate that we're currently in
|
||||||
|
// the process of highlighting.
|
||||||
|
this.highlight.highlighting = true;
|
||||||
|
|
||||||
|
var obj = this;
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 20);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 40);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 60);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 80);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 100);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 120);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 140);
|
||||||
|
setTimeout(function() {obj.highlight.highlighting = false;}, 400);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.roundedRect(
|
RGraph.clipTo.callback(this, function (obj)
|
||||||
this.coords[0][0],
|
{
|
||||||
this.coords[0][1],
|
if (typeof obj.properties.highlightStyle === 'function') {
|
||||||
this.coords[0][2],
|
(obj.properties.highlightStyle)(shape);
|
||||||
this.coords[0][3],
|
} else {
|
||||||
this.properties.borderRadius
|
obj.path('b');
|
||||||
|
|
||||||
|
obj.roundedRect(
|
||||||
|
obj.coords[0][0],
|
||||||
|
obj.coords[0][1],
|
||||||
|
obj.coords[0][2],
|
||||||
|
obj.coords[0][3],
|
||||||
|
obj.properties.borderRadius
|
||||||
);
|
);
|
||||||
|
|
||||||
this.path(
|
obj.path(
|
||||||
'f % s %',
|
'f % s %',
|
||||||
properties.highlightFill,
|
obj.properties.highlightFill,
|
||||||
properties.highlightStroke
|
obj.properties.highlightStroke
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
});// End of clipping callback.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
'version:2025-10-08 (7.01)';
|
'version:2026-08-11 (7.21)';
|
||||||
//
|
//
|
||||||
// o---------------------------------------------------------------------------------o
|
// o---------------------------------------------------------------------------o
|
||||||
// | This file is part of the RGraph package - you can learn more at: |
|
// | This file is part of the RGraph package - you can learn more at: |
|
||||||
// | |
|
// | |
|
||||||
// | https://www.rgraph.net/license.html |
|
// | https://www.rgraph.net |
|
||||||
// | |
|
// | |
|
||||||
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
|
// | RGraph is dual-licensed under the Open Source GPL license. This means |
|
||||||
// | free to use and there are no restrictions on what you can use RGraph for! |
|
// | that it's free to use for any purpose. The GPL license does have |
|
||||||
// | If the GPL license does not suit you however, then there's an inexpensive |
|
// | consequences on the license of the software that you include it in, |
|
||||||
// | commercial license option available. See the URL above for more details. |
|
// | however. If this is not desirable, then there's an inexpensive commercial |
|
||||||
// o---------------------------------------------------------------------------------o
|
// | license option available. See the RGraph website for more details. |
|
||||||
|
// o---------------------------------------------------------------------------o
|
||||||
|
|
||||||
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
|
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
|
||||||
|
|
||||||
@ -100,7 +101,6 @@
|
|||||||
titleTopPos: null,
|
titleTopPos: null,
|
||||||
titleTopOffsetx: 0,
|
titleTopOffsetx: 0,
|
||||||
titleTopOffsety: 0,
|
titleTopOffsety: 0,
|
||||||
|
|
||||||
titleTopSubtitle: null,
|
titleTopSubtitle: null,
|
||||||
titleTopSubtitleFont: null,
|
titleTopSubtitleFont: null,
|
||||||
titleTopSubtitleSize: null,
|
titleTopSubtitleSize: null,
|
||||||
@ -129,27 +129,26 @@
|
|||||||
scaleThousand: ',',
|
scaleThousand: ',',
|
||||||
scaleUnitsPre: '',
|
scaleUnitsPre: '',
|
||||||
scaleUnitsPost: '',
|
scaleUnitsPost: '',
|
||||||
scalePoint: '.',
|
|
||||||
scaleThousand: ',',
|
|
||||||
|
|
||||||
labelsCount: 5,
|
labelsCount: 5,
|
||||||
labelsCentered: false,
|
labelsCentered: false,
|
||||||
labelsOffsetRadius: 0,
|
labelsOffsetRadius: 0,
|
||||||
labelsOffsetAngle: 0,
|
labelsOffsetAngle: 0,
|
||||||
|
labelsOffsetx: 0,
|
||||||
|
labelsOffsety: 0,
|
||||||
labelsSpecific: null,
|
labelsSpecific: null,
|
||||||
labelsSpecificFormattedDecimals: 0,
|
labelsSpecificFormattedDecimals: 0,
|
||||||
labelsSpecificFormattedPoint: '.',
|
labelsSpecificFormattedPoint: '.',
|
||||||
labelsSpecificFormattedThousand: ',',
|
labelsSpecificFormattedThousand: ',',
|
||||||
labelsSpecificFormattedUnitsPre: '',
|
labelsSpecificFormattedUnitsPre: '',
|
||||||
labelsSpecificFormattedUnitsPost: '',
|
labelsSpecificFormattedUnitsPost: '',
|
||||||
labelsOffsetx: 0,
|
|
||||||
labelsOffsety: 0,
|
|
||||||
labelsFont: null,
|
labelsFont: null,
|
||||||
labelsSize: null,
|
labelsSize: null,
|
||||||
labelsColor: null,
|
labelsColor: null,
|
||||||
labelsBold: null,
|
labelsBold: null,
|
||||||
labelsItalic: null,
|
labelsItalic: null,
|
||||||
labelsValue: false,
|
|
||||||
|
labelsValue: false,
|
||||||
labelsValueYPos: 0.5,
|
labelsValueYPos: 0.5,
|
||||||
labelsValueUnitsPre: '',
|
labelsValueUnitsPre: '',
|
||||||
labelsValueUnitsPost: '',
|
labelsValueUnitsPost: '',
|
||||||
@ -167,12 +166,12 @@
|
|||||||
|
|
||||||
|
|
||||||
colorsRedStart: 0.9 * this.max,
|
colorsRedStart: 0.9 * this.max,
|
||||||
colorsRedColor: '#DC3912',
|
colorsRedColor: '#dc3912',
|
||||||
colorsRedWidth: 5,
|
colorsRedWidth: 5,
|
||||||
colorsYellowColor: '#FF9900',
|
colorsYellowColor: '#ff9900',
|
||||||
colorsYellowWidth: 5,
|
colorsYellowWidth: 5,
|
||||||
colorsGreenEnd: 0.7 * this.max,
|
colorsGreenEnd: 0.7 * this.max,
|
||||||
colorsGreenColor: 'rgba(0,0,0,0)',
|
colorsGreenColor: 'transparent',
|
||||||
colorsGreenWidth: 5,
|
colorsGreenWidth: 5,
|
||||||
colorsRanges: null,
|
colorsRanges: null,
|
||||||
|
|
||||||
@ -187,8 +186,9 @@
|
|||||||
borderOutline: 'black',
|
borderOutline: 'black',
|
||||||
borderGradient: false,
|
borderGradient: false,
|
||||||
|
|
||||||
centerpinColor: 'blue',
|
centerpinColor: 'black',
|
||||||
centerpinRadius: null,
|
centerpinGradient: false,
|
||||||
|
centerpinRadius: null,
|
||||||
|
|
||||||
tickmarksSmall: 25,
|
tickmarksSmall: 25,
|
||||||
tickmarksSmallColor: 'black',
|
tickmarksSmallColor: 'black',
|
||||||
@ -203,19 +203,22 @@
|
|||||||
annotatableLinewidth: 1,
|
annotatableLinewidth: 1,
|
||||||
annotatableColor: 'black',
|
annotatableColor: 'black',
|
||||||
|
|
||||||
shadow: true,
|
shadow: false,
|
||||||
shadowColor: 'gray',
|
shadowColor: 'gray',
|
||||||
shadowOffsetx: 0,
|
shadowOffsetx: 0,
|
||||||
shadowOffsety: 0,
|
shadowOffsety: 0,
|
||||||
shadowBlur: 15,
|
shadowBlur: 15,
|
||||||
|
|
||||||
clearto: 'rgba(0,0,0,0)',
|
clearto: 'transparent',
|
||||||
|
|
||||||
events: {},
|
|
||||||
|
|
||||||
|
events: {},
|
||||||
|
clip: null,
|
||||||
|
responsive: null,
|
||||||
scale: true,
|
scale: true,
|
||||||
scaleFactor: 2,
|
scaleFactor: 2,
|
||||||
antialiasTranslate: false
|
antialiasTranslate: false,
|
||||||
|
|
||||||
|
style: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -428,6 +431,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any CSS that has been specified to the document.
|
||||||
|
// This is general CSS and does not necessarily have to
|
||||||
|
// pertain to the canvas tag. It only gets added once
|
||||||
|
// to the document no matter how many times this draw
|
||||||
|
// function is called.
|
||||||
|
//
|
||||||
|
// Add the CSS to a <style> block in the <head>.
|
||||||
|
RGraph.addConfigurationBasedCSS(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -932,17 +947,24 @@
|
|||||||
var scaleFactor = RGraph.getScaleFactor(this);
|
var scaleFactor = RGraph.getScaleFactor(this);
|
||||||
|
|
||||||
var offset = (6 * scaleFactor);
|
var offset = (6 * scaleFactor);
|
||||||
|
|
||||||
var grad = this.context.createRadialGradient(
|
//
|
||||||
this.centerx + offset,
|
// Gradient or not
|
||||||
this.centery - offset,
|
//
|
||||||
0,
|
if (this.properties.centerpinGradient) {
|
||||||
this.centerx + offset,
|
var grad = this.context.createRadialGradient(
|
||||||
this.centery - offset,
|
this.centerx + offset,
|
||||||
(25 * scaleFactor)
|
this.centery - offset,
|
||||||
);
|
0,
|
||||||
grad.addColorStop(0, '#ddf');
|
this.centerx + offset,
|
||||||
grad.addColorStop(1, properties.centerpinColor);
|
this.centery - offset,
|
||||||
|
(25 * scaleFactor)
|
||||||
|
);
|
||||||
|
grad.addColorStop(0, '#ddf');
|
||||||
|
grad.addColorStop(1, this.properties.centerpinColor);
|
||||||
|
} else {
|
||||||
|
grad = this.properties.centerpinColor;
|
||||||
|
}
|
||||||
|
|
||||||
this.context.beginPath();
|
this.context.beginPath();
|
||||||
this.context.fillStyle = grad;
|
this.context.fillStyle = grad;
|
||||||
@ -997,11 +1019,7 @@
|
|||||||
// If the labelsSpecific option is a string then turn it
|
// If the labelsSpecific option is a string then turn it
|
||||||
// into an array.
|
// into an array.
|
||||||
if (typeof properties.labelsSpecific === 'string' ) {
|
if (typeof properties.labelsSpecific === 'string' ) {
|
||||||
properties.labelsSpecific = RGraph.arrayPad({
|
properties.labelsSpecific = RGraph.arrayPad([], properties.labelsCount, properties.labelsSpecific);
|
||||||
array: [],
|
|
||||||
length: properties.labelsCount,
|
|
||||||
value: properties.labelsSpecific
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1090,11 +1108,7 @@
|
|||||||
valign: vAlign,
|
valign: vAlign,
|
||||||
tag: properties.labelsSpecific ? 'labels.specific' : 'labels',
|
tag: properties.labelsSpecific ? 'labels.specific' : 'labels',
|
||||||
cssClass: properties.labelsSpecific
|
cssClass: properties.labelsSpecific
|
||||||
? RGraph.getLabelsCSSClassName({
|
? RGraph.getLabelsCSSClassName(this, 'labelsClass', i)
|
||||||
object: this,
|
|
||||||
name: 'labelsClass',
|
|
||||||
index: i
|
|
||||||
})
|
|
||||||
: ''
|
: ''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1207,13 +1221,13 @@
|
|||||||
|
|
||||||
// Move the Y coord up if there's a subtitle
|
// Move the Y coord up if there's a subtitle
|
||||||
if (typeof properties.titleTopSubtitle === 'string' || typeof properties.titleTopSubtitle === 'number') {
|
if (typeof properties.titleTopSubtitle === 'string' || typeof properties.titleTopSubtitle === 'number') {
|
||||||
var titleTopSubtitleDim = RGraph.measureText({
|
var titleTopSubtitleDim = RGraph.measureText(
|
||||||
bold: properties.titleTopSubtitleBold,
|
'Mg',
|
||||||
italic: properties.titleTopSubtitleItalic,
|
properties.titleTopSubtitleItalic,
|
||||||
size: properties.titleTopSubtitleSize,
|
properties.titleTopSubtitleBold,
|
||||||
font: properties.titleTopSubtitleFont,
|
properties.titleTopSubtitleFont,
|
||||||
text: 'Mg'
|
properties.titleTopSubtitleSize
|
||||||
});
|
);
|
||||||
|
|
||||||
y -= titleTopSubtitleDim[1];
|
y -= titleTopSubtitleDim[1];
|
||||||
}
|
}
|
||||||
@ -1906,7 +1920,7 @@
|
|||||||
var obj = this,
|
var obj = this,
|
||||||
opt = arguments[0] ? arguments[0] : {},
|
opt = arguments[0] ? arguments[0] : {},
|
||||||
callback = arguments[1] ? arguments[1] : function () {},
|
callback = arguments[1] ? arguments[1] : function () {},
|
||||||
frames = opt.frames || 30,
|
frames = opt.frames || 60,
|
||||||
frame = 0;
|
frame = 0;
|
||||||
|
|
||||||
// Don't want any strings
|
// Don't want any strings
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
'version:2025-10-08 (7.01)';
|
'version:2026-08-11 (7.21)';
|
||||||
//
|
//
|
||||||
// o---------------------------------------------------------------------------------o
|
// o---------------------------------------------------------------------------o
|
||||||
// | This file is part of the RGraph package - you can learn more at: |
|
// | This file is part of the RGraph package - you can learn more at: |
|
||||||
// | |
|
// | |
|
||||||
// | https://www.rgraph.net/license.html |
|
// | https://www.rgraph.net |
|
||||||
// | |
|
// | |
|
||||||
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
|
// | RGraph is dual-licensed under the Open Source GPL license. This means |
|
||||||
// | free to use and there are no restrictions on what you can use RGraph for! |
|
// | that it's free to use for any purpose. The GPL license does have |
|
||||||
// | If the GPL license does not suit you however, then there's an inexpensive |
|
// | consequences on the license of the software that you include it in, |
|
||||||
// | commercial license option available. See the URL above for more details. |
|
// | however. If this is not desirable, then there's an inexpensive commercial |
|
||||||
// o---------------------------------------------------------------------------------o
|
// | license option available. See the RGraph website for more details. |
|
||||||
|
// o---------------------------------------------------------------------------o
|
||||||
|
|
||||||
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
|
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
|
||||||
|
|
||||||
@ -49,13 +50,14 @@
|
|||||||
this.properties =
|
this.properties =
|
||||||
{
|
{
|
||||||
backgroundBorder: 'black',
|
backgroundBorder: 'black',
|
||||||
backgroundColor: '#eee',
|
backgroundColor: 'white',
|
||||||
backgroundLinesColor: '#ddd',
|
backgroundLinesColor: '#ddd',
|
||||||
|
|
||||||
centerx: null,
|
centerx: null,
|
||||||
centery: null,
|
centery: null,
|
||||||
radius: null,
|
radius: null,
|
||||||
|
|
||||||
|
labels: null,
|
||||||
labelsMargin: 35,
|
labelsMargin: 35,
|
||||||
labelsFont: null,
|
labelsFont: null,
|
||||||
labelsSize: null,
|
labelsSize: null,
|
||||||
@ -81,7 +83,7 @@
|
|||||||
needleLength: null,
|
needleLength: null,
|
||||||
needleWidth: 2,
|
needleWidth: 2,
|
||||||
needleHead: true,
|
needleHead: true,
|
||||||
needleTail: true,
|
needleTail: false,
|
||||||
needleType: 'pointer',
|
needleType: 'pointer',
|
||||||
needleTriangleBorder: '#aaa',
|
needleTriangleBorder: '#aaa',
|
||||||
|
|
||||||
@ -96,10 +98,10 @@
|
|||||||
text: null,
|
text: null,
|
||||||
|
|
||||||
colorsGreenMax: max * 0.75,
|
colorsGreenMax: max * 0.75,
|
||||||
colorsGreenColor: '#0c0',
|
colorsGreenColor: '#00cc0088',
|
||||||
colorsYellowColor: '#cc0',
|
colorsYellowColor: '#ffff0088',
|
||||||
colorsRedMin: max * 0.9,
|
colorsRedMin: max * 0.9,
|
||||||
colorsRedColor: '#c00',
|
colorsRedColor: '#ff000088',
|
||||||
|
|
||||||
marginLeft: 35,
|
marginLeft: 35,
|
||||||
marginRight: 35,
|
marginRight: 35,
|
||||||
@ -144,6 +146,7 @@
|
|||||||
|
|
||||||
annotatable: false,
|
annotatable: false,
|
||||||
annotatableColor: 'black',
|
annotatableColor: 'black',
|
||||||
|
annotatableLinewidth: 1,
|
||||||
|
|
||||||
scaleDecimals: 0,
|
scaleDecimals: 0,
|
||||||
scalePoint: '.',
|
scalePoint: '.',
|
||||||
@ -152,7 +155,7 @@
|
|||||||
scaleUnitsPost: '',
|
scaleUnitsPost: '',
|
||||||
scaleZerostart: false,
|
scaleZerostart: false,
|
||||||
|
|
||||||
border: true,
|
border: false,
|
||||||
borderColor1: '#BEBCB0',
|
borderColor1: '#BEBCB0',
|
||||||
borderColor2: '#F0EFEA',
|
borderColor2: '#F0EFEA',
|
||||||
borderColor3: '#BEBCB0',
|
borderColor3: '#BEBCB0',
|
||||||
@ -161,8 +164,6 @@
|
|||||||
tickmarksHighlighted: true,
|
tickmarksHighlighted: true,
|
||||||
tickmarksLargeColor: '#999',
|
tickmarksLargeColor: '#999',
|
||||||
|
|
||||||
labels: null,
|
|
||||||
|
|
||||||
key: null,
|
key: null,
|
||||||
keyBackground: 'white',
|
keyBackground: 'white',
|
||||||
keyPosition: 'graph',
|
keyPosition: 'graph',
|
||||||
@ -196,13 +197,16 @@
|
|||||||
|
|
||||||
adjustable: false,
|
adjustable: false,
|
||||||
|
|
||||||
clearto: 'rgba(0,0,0,0)',
|
clearto: 'transparent',
|
||||||
|
|
||||||
events: {},
|
events: {},
|
||||||
|
clip: null,
|
||||||
|
responsive: null,
|
||||||
scale: true,
|
scale: true,
|
||||||
scaleFactor: 2,
|
scaleFactor: 2,
|
||||||
antialiasTranslate: false
|
antialiasTranslate: false,
|
||||||
|
|
||||||
|
style: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -385,6 +389,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any CSS that has been specified to the document.
|
||||||
|
// This is general CSS and does not necessarily have to
|
||||||
|
// pertain to the canvas tag. It only gets added once
|
||||||
|
// to the document no matter how many times this draw
|
||||||
|
// function is called.
|
||||||
|
//
|
||||||
|
// Add the CSS to a <style> block in the <head>.
|
||||||
|
RGraph.addConfigurationBasedCSS(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Translate half a pixel for antialiasing purposes - but
|
// Translate half a pixel for antialiasing purposes - but
|
||||||
// only if it hasn't been done already
|
// only if it hasn't been done already
|
||||||
//
|
//
|
||||||
@ -1593,7 +1609,7 @@
|
|||||||
|
|
||||||
var obj = this;
|
var obj = this;
|
||||||
var opt = arguments[0] || {};
|
var opt = arguments[0] || {};
|
||||||
var frames = opt.frames || 30;
|
var frames = opt.frames || 60;
|
||||||
var frame = 0;
|
var frame = 0;
|
||||||
var current = this.currentValue || 0;
|
var current = this.currentValue || 0;
|
||||||
var origValue = Number(obj.currentValue);
|
var origValue = Number(obj.currentValue);
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
'version:2025-10-08 (7.01)';
|
'version:2026-08-11 (7.21)';
|
||||||
//
|
//
|
||||||
// o---------------------------------------------------------------------------------o
|
// o---------------------------------------------------------------------------o
|
||||||
// | This file is part of the RGraph package - you can learn more at: |
|
// | This file is part of the RGraph package - you can learn more at: |
|
||||||
// | |
|
// | |
|
||||||
// | https://www.rgraph.net/license.html |
|
// | https://www.rgraph.net |
|
||||||
// | |
|
// | |
|
||||||
// | RGraph is dual-licensed under the Open Source GPL license. That means that it's |
|
// | RGraph is dual-licensed under the Open Source GPL license. This means |
|
||||||
// | free to use and there are no restrictions on what you can use RGraph for! |
|
// | that it's free to use for any purpose. The GPL license does have |
|
||||||
// | If the GPL license does not suit you however, then there's an inexpensive |
|
// | consequences on the license of the software that you include it in, |
|
||||||
// | commercial license option available. See the URL above for more details. |
|
// | however. If this is not desirable, then there's an inexpensive commercial |
|
||||||
// o---------------------------------------------------------------------------------o
|
// | license option available. See the RGraph website for more details. |
|
||||||
|
// o---------------------------------------------------------------------------o
|
||||||
|
|
||||||
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
|
RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
|
||||||
|
|
||||||
@ -47,8 +48,8 @@
|
|||||||
|
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
|
|
||||||
colorsStroke: 'black',
|
colorsStroke: '#666',
|
||||||
colors: ['red'],
|
colors: RGraph.getColors(),
|
||||||
|
|
||||||
marginLeft: 35,
|
marginLeft: 35,
|
||||||
marginRight: 35,
|
marginRight: 35,
|
||||||
@ -56,7 +57,7 @@
|
|||||||
marginBottom: 35,
|
marginBottom: 35,
|
||||||
|
|
||||||
tickmarksSize: 2,
|
tickmarksSize: 2,
|
||||||
tickmarksCount: 10,
|
tickmarksCount: 0,
|
||||||
|
|
||||||
textColor: 'black',
|
textColor: 'black',
|
||||||
textFont: 'Arial, Verdana, sans-serif',
|
textFont: 'Arial, Verdana, sans-serif',
|
||||||
@ -102,14 +103,11 @@
|
|||||||
titleSideOffsetx: 0,
|
titleSideOffsetx: 0,
|
||||||
titleSideOffsety: 0,
|
titleSideOffsety: 0,
|
||||||
|
|
||||||
shadow: true,
|
shadow: false,
|
||||||
shadowOffsetx: 0,
|
shadowOffsetx: 0,
|
||||||
shadowOffsety: 0,
|
shadowOffsety: 0,
|
||||||
shadowBlur: 15,
|
shadowBlur: 15,
|
||||||
shadowColor: '#ddd',
|
shadowColor: '#ddd',
|
||||||
|
|
||||||
resizable: false,
|
|
||||||
resizableHandleBackground: null,
|
|
||||||
|
|
||||||
contextmenu: null,
|
contextmenu: null,
|
||||||
|
|
||||||
@ -172,19 +170,23 @@
|
|||||||
tooltipsPositionStatic: true,
|
tooltipsPositionStatic: true,
|
||||||
tooltipsHotspotIgnore: null,
|
tooltipsHotspotIgnore: null,
|
||||||
|
|
||||||
highlightStroke: 'rgba(0,0,0,0)',
|
highlightStroke: 'transparent',
|
||||||
highlightFill: 'rgba(255,255,255,0.7)',
|
highlightFill: 'rgba(255,255,255,0.7)',
|
||||||
|
highlightFade: true,
|
||||||
|
|
||||||
clearto: 'rgba(0,0,0,0)',
|
clearto: 'transparent',
|
||||||
|
|
||||||
bulbBottomRadiusAdjust: 0,
|
bulbBottomRadiusAdjust: 0,
|
||||||
bulbBottomRadius: null,
|
bulbBottomRadius: null,
|
||||||
|
|
||||||
events: {},
|
events: {},
|
||||||
|
clip: null,
|
||||||
|
responsive: null,
|
||||||
scale: true,
|
scale: true,
|
||||||
scaleFactor: 2,
|
scaleFactor: 2,
|
||||||
antialiasTranslate: false
|
antialiasTranslate: false,
|
||||||
|
|
||||||
|
style: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -407,6 +409,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any CSS that has been specified to the document.
|
||||||
|
// This is general CSS and does not necessarily have to
|
||||||
|
// pertain to the canvas tag. It only gets added once
|
||||||
|
// to the document no matter how many times this draw
|
||||||
|
// function is called.
|
||||||
|
//
|
||||||
|
// Add the CSS to a <style> block in the <head>.
|
||||||
|
RGraph.addConfigurationBasedCSS(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Translate half a pixel for antialiasing purposes - but
|
// Translate half a pixel for antialiasing purposes - but
|
||||||
// only if it hasn't been done already
|
// only if it hasn't been done already
|
||||||
//
|
//
|
||||||
@ -1124,20 +1138,50 @@
|
|||||||
//
|
//
|
||||||
this.highlight = function (shape)
|
this.highlight = function (shape)
|
||||||
{
|
{
|
||||||
if (properties.tooltipsHighlight) {
|
// If the highlightFade property is not set then call
|
||||||
|
// the highlight function multiple times when the
|
||||||
|
// globalAlpha is set at varying levels of transparency
|
||||||
|
// to fade the highlight in. If the variable is set,
|
||||||
|
// however, then this call is probably a part of said
|
||||||
|
// highlighting process so don't call ourselves
|
||||||
|
// again - just highlight the chart.
|
||||||
|
if (this.properties.highlightFade && !this.highlight.highlighting) {
|
||||||
|
|
||||||
if (typeof properties.highlightStyle === 'function') {
|
// Add a variable to the highlight function (this
|
||||||
(properties.highlightStyle)(shape);
|
// function) to indicate that we're currently in
|
||||||
return;
|
// the process of highlighting.
|
||||||
}
|
this.highlight.highlighting = true;
|
||||||
|
|
||||||
this.pathBar();
|
var obj = this;
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 20);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 40);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 60);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 80);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 100);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 120);
|
||||||
|
setTimeout(function() {obj.context.globalAlpha = 0.2; obj.highlight(shape); obj.context.globalAlpha = 1;}, 140);
|
||||||
|
setTimeout(function() {obj.highlight.highlighting = false;}, 400);
|
||||||
|
|
||||||
this.path(
|
return;
|
||||||
's % f %',
|
|
||||||
properties.highlightStroke, properties.highlightFill
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RGraph.clipTo.callback(this, function (obj)
|
||||||
|
{
|
||||||
|
if (obj.properties.tooltipsHighlight) {
|
||||||
|
|
||||||
|
if (typeof obj.properties.highlightStyle === 'function') {
|
||||||
|
(obj.properties.highlightStyle)(shape);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.pathBar();
|
||||||
|
|
||||||
|
obj.path(
|
||||||
|
's % f %',
|
||||||
|
obj.properties.highlightStroke, obj.properties.highlightFill
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
246
src/gui_common/view/modelo_configuracion.html
Normal file
246
src/gui_common/view/modelo_configuracion.html
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
|
||||||
|
<form id="config-form" novalidate>
|
||||||
|
<div class="col-centered">
|
||||||
|
<h1>Configuración General</h1>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 text-end" style="vertical-align:top;"><button type="button" class="btn btn-sm btn-success" onclick="MenuGUI('logs');" role="button">Ver Logs</button> </div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6 col-lg-4 col-centered">
|
||||||
|
<label class="control-label" for="Modo">Ema Modo</label><br>
|
||||||
|
<select id='Modo' name="Modo" class="form-select">
|
||||||
|
<optgroup label="Recolector">
|
||||||
|
<option value="Recolector_USB">Recolector USB</option>
|
||||||
|
<option value="Recolector_IP">Recolector IP/WIFI</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Visor">
|
||||||
|
<option value="Visor">Visor Llave</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-4 col-centered">
|
||||||
|
<label class="control-label" for="NombreEstacion">Nombre de tu estación</label><br>
|
||||||
|
<input type="text" class="form-control" id="NombreEstacion" autocomplete='name' placeholder="Ingrese el nombre" maxlength="20" size="30"></br></br>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-4 col-centered">
|
||||||
|
<label for="Email_receptor" class="control-label">Correo del Administrador</label><br>
|
||||||
|
<input type="email" class="form-control" id="Email_receptor" autocomplete='email' placeholder="Email" maxlength="50" size="35">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="hr-suave">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered">
|
||||||
|
<label class="control-label" for="inicio_auto">Inicio Automático</label><br>
|
||||||
|
<select id='inicio_auto' name="inicio_auto" class="form-select">
|
||||||
|
<optgroup label="Iniciar el recolector/visor con el aplicativo">
|
||||||
|
<option value="Activado">Activado</option>
|
||||||
|
<option value="Desactivado">Desactivado</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered">
|
||||||
|
<label class="control-label" for="notificar_cambios">Notificar Cambios</label><br>
|
||||||
|
<select id='notificar_cambios' name="notificar_cambios" class="form-select">
|
||||||
|
<optgroup label="Notificar de carpincho">
|
||||||
|
<option value="Activado">Activado</option>
|
||||||
|
<option value="Desactivado">Desactivado</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered">
|
||||||
|
<label class="control-label" for="audio">Audio</label><br>
|
||||||
|
<select id='audio' name="audio" class="form-select">
|
||||||
|
<optgroup label="Audio de carpincho">
|
||||||
|
<option value="Activado">Activado</option>
|
||||||
|
<option value="Desactivado">Desactivado</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-3 col-centered" id="vocesAudioDiv">
|
||||||
|
<label class="control-label" for="vocesAudio">Voz del Audio</label></br>
|
||||||
|
<select id='vocesAudio' name="vocesAudio" class="form-select">
|
||||||
|
<optgroup label="Lista de Voces">
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="hr-suave">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered">
|
||||||
|
<label class="control-label" for="Tiempo_de_Recoleccion">Recolección</label><br>
|
||||||
|
<select id='Tiempo_de_Recoleccion' name="Tiempo_de_Recoleccion" class="form-select">
|
||||||
|
<optgroup label="Muy Rapido">
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="20">20</option>
|
||||||
|
<option value="30">30</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Medio">
|
||||||
|
<option value="40">40</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
<option value="60">60</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Normal">
|
||||||
|
<option value="70">70</option>
|
||||||
|
<option value="80">80</option>
|
||||||
|
<option value="90">90</option>
|
||||||
|
<option value="100">100</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Despacio">
|
||||||
|
<option value="110">110</option>
|
||||||
|
<option value="120">120</option>
|
||||||
|
<option value="130">130</option>
|
||||||
|
<option value="140">140</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-3 col-centered">
|
||||||
|
<label class="control-label" for="Debug">Debug y Tamaño</label><br>
|
||||||
|
<div class="input-group flex-nowrap">
|
||||||
|
<select id='Debug' name="Debug" class="form-select">
|
||||||
|
<optgroup label="Normal">
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Alto">
|
||||||
|
<option value="4">4</option>
|
||||||
|
<option value="5">5</option>
|
||||||
|
<option value="6">6</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Muy Alto">
|
||||||
|
<option value="7">7</option>
|
||||||
|
<option value="8">8</option>
|
||||||
|
<option value="9">9</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
<input type="text" class="form-control" id="debugMB" aria-label="Tamaño máximo del debug en MB" placeholder="MB Debug" maxlength="5" size="5">
|
||||||
|
<span class="input-group-text">MB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-1 col-centered">
|
||||||
|
<label class="control-label" for="utc">UTC</label><br>
|
||||||
|
<select id='utc' name="utc" class="form-select">
|
||||||
|
<optgroup label="Negativo">
|
||||||
|
<option value="-1">-1</option>
|
||||||
|
<option value="-2">-2</option>
|
||||||
|
<option value="-3">-3</option>
|
||||||
|
<option value="-4">-4</option>
|
||||||
|
<option value="-5">-5</option>
|
||||||
|
<option value="-6">-6</option>
|
||||||
|
<option value="-7">-7</option>
|
||||||
|
<option value="-8">-8</option>
|
||||||
|
<option value="-9">-9</option>
|
||||||
|
<option value="-10">-10</option>
|
||||||
|
<option value="-11">-11</option>
|
||||||
|
<option value="-12">-12</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Neutro">
|
||||||
|
<option value="0">0</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Positivo">
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="4">4</option>
|
||||||
|
<option value="5">5</option>
|
||||||
|
<option value="6">6</option>
|
||||||
|
<option value="7">7</option>
|
||||||
|
<option value="8">8</option>
|
||||||
|
<option value="9">9</option>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="11">11</option>
|
||||||
|
<option value="12">12</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered">
|
||||||
|
<label class="control-label" for="SistemaMetrico">Unidades</label><br>
|
||||||
|
<select id='SistemaMetrico' name="SistemaMetrico" class="form-select">
|
||||||
|
<optgroup label="Sistema Internacional de Unidades(SI)">
|
||||||
|
<option value="SI">º C</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Sistema Anglosajón de Unidades(SA)">
|
||||||
|
<option value="SA">º F</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="hr-suave">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6 col-lg-3 col-centered">
|
||||||
|
<label class="control-label" for="Tipo_SMTP">SMTP TIPO</label><br>
|
||||||
|
<select id='Tipo_SMTP' name="Tipo_SMTP" class="form-select">
|
||||||
|
<optgroup label="SMTP Deshabilitado">
|
||||||
|
<option value="Deshabilitado">Deshabilitado</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="SMTP Proveedor">
|
||||||
|
<option value="Gmail">GMAIL</option>
|
||||||
|
<option value="Yahoo">YAHOO</option>
|
||||||
|
<option value="Hotmail">OUTLOOK</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="SMTP Manual">
|
||||||
|
<option value="Manual">SMTP CONFIG</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-3 col-centered">
|
||||||
|
<label class="control-label" for="Usuario_SMTP">Cuenta</label><br>
|
||||||
|
<input type="email" class="form-control" id="Usuario_SMTP" placeholder="Cuenta" maxlength="40" size="16">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-3 col-centered">
|
||||||
|
<label class="control-label" for="Contrasenia_SMTP">Contraseña</label><br>
|
||||||
|
<input type="password" class="form-control" id="Contrasenia_SMTP" placeholder="Contraseña" maxlength="40" size="16">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered" id="Server">
|
||||||
|
<label class="control-label" for="Server_SMTP">Server</label><br>
|
||||||
|
<input type="text" class="form-control" id="Server_SMTP" placeholder="Server" maxlength="40" size="15">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-1 col-centered" id="puerto">
|
||||||
|
<label class="control-label" for="Puerto_SMTP">Puerto</label><br>
|
||||||
|
<input type="text" class="form-control" id="Puerto_SMTP" placeholder="Puerto" maxlength="5" size="5">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Segun seleccion cambia debajo el bloque secundario -->
|
||||||
|
<div id="bloque_secundario">
|
||||||
|
<hr>
|
||||||
|
<label class="control-label">Configuración específica para el Modo</label>
|
||||||
|
<div class="col-centered">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6 col-lg-6 col-centered" id="LlaveR">
|
||||||
|
<label class="control-label" for="Llave_R">Llave de Lectura</label></br>
|
||||||
|
<input type="text" class="form-control" id="Llave_R" placeholder="Ingrese LLave" maxlength="40" size="44"></br></br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="bloque_por_IP_WIFI" class="row">
|
||||||
|
|
||||||
|
<div class="col-12 col-md-6 col-lg-4 col-centered">
|
||||||
|
<label class="control-label" for="r_ip">IP</label><br>
|
||||||
|
<select id='r_ip' name="IP" class="form-select">
|
||||||
|
<optgroup label="IP's" id="ipGroup">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-6 col-lg-2 col-centered">
|
||||||
|
<label class="control-label" for="r_puerto">Puerto</label></br>
|
||||||
|
<input type="text" class="form-control" id="r_puerto" placeholder="Puerto" maxlength="5" size="5" value="5000">
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-4 col-centered">
|
||||||
|
<label class="control-label" for="r_path">Path</label></br>
|
||||||
|
<input type="text" class="form-control" id="r_path" placeholder="Puerto" maxlength="15" size="25" value="/datos">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="hr-suave">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-centered">
|
||||||
|
<button type="submit" id="botonguardar" class="btn btn-sm btn-success" role="button">Guardar</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p id="config-status" role="status" aria-live="polite"></p>
|
||||||
|
</form>
|
||||||
18
src/gui_web/configuracion-api.js
Normal file
18
src/gui_web/configuracion-api.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Injectable storage keeps the real HTTP contract testable without station hardware.
|
||||||
|
function registrarConfiguracion(app, {guardar, reconfigurar}) {
|
||||||
|
app.post('/GuardarConf', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await guardar(req.body?.configuracion);
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(error.fields ? 400 : 500).json({ok: false, error: error.fields ? error.message : 'No se pudo guardar la configuración.', fields: error.fields});
|
||||||
|
}
|
||||||
|
// Persistence succeeded even if the running collector cannot reload immediately.
|
||||||
|
try {
|
||||||
|
await reconfigurar(req.body.configuracion);
|
||||||
|
res.json({ok: true});
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ok: true, warning: 'La configuración se guardó. Reiniciá el recolector para aplicarla.'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
module.exports = {registrarConfiguracion};
|
||||||
@ -295,7 +295,7 @@ async function EstadoMenuInicio()
|
|||||||
// Se guarda el registro anterior
|
// Se guarda el registro anterior
|
||||||
Ant_UltimoReg = UltimoReg;
|
Ant_UltimoReg = UltimoReg;
|
||||||
// Se actualiza los ToolTips
|
// Se actualiza los ToolTips
|
||||||
//$(document).ready(function(){$('[data-toggle="tooltip"]').tooltip();});
|
//$(document).ready(function(){$('[data-bs-toggle="tooltip"]').tooltip();});
|
||||||
}
|
}
|
||||||
result=null;parpadeo=null;texto_uv=null;ST=null;
|
result=null;parpadeo=null;texto_uv=null;ST=null;
|
||||||
TEMP_S = null; TEMP_MULT = null;TEMP_POND = null;
|
TEMP_S = null; TEMP_MULT = null;TEMP_POND = null;
|
||||||
@ -311,17 +311,17 @@ async function RegistroPublicado()
|
|||||||
for (var key in redesPub)
|
for (var key in redesPub)
|
||||||
{
|
{
|
||||||
if(redesPub[key].estado === true){
|
if(redesPub[key].estado === true){
|
||||||
redespublicadashtml += "<span class='badge badge-success' title='Publicado Correctamente'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
redespublicadashtml += "<span class='badge text-bg-success' title='Publicado Correctamente'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{
|
}else{
|
||||||
if(redesPub[key].estado == 'No enviado'){
|
if(redesPub[key].estado == 'No enviado'){
|
||||||
redespublicadashtml += "<span class='badge badge-noinformado' title='No se envia, la red informa 5 minutos de espera.'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
redespublicadashtml += "<span class='badge badge-noinformado' title='No se envia, la red informa 5 minutos de espera.'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{
|
}else{
|
||||||
if(redesPub[key].estado == 'Esperar'){
|
if(redesPub[key].estado == 'Esperar'){
|
||||||
redespublicadashtml += "<span class='badge badge-light parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
redespublicadashtml += "<span class='badge text-bg-light parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{
|
}else{
|
||||||
if(redesPub[key].error == "Detenido")
|
if(redesPub[key].error == "Detenido")
|
||||||
{redespublicadashtml += "<span class='badge badge-warning parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
{redespublicadashtml += "<span class='badge text-bg-warning parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";
|
||||||
}else{redespublicadashtml += "<span class='badge badge-danger parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";}
|
}else{redespublicadashtml += "<span class='badge text-bg-danger parpadea' title='"+redesPub[key].error+"'>"+redesPub[key].red +": "+redesPub[key].fecha.substring(10,19)+"</span><br>";}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,16 +584,16 @@ function ListarRedes()
|
|||||||
TablaHTML += " <thead><th>Nombre Local</th><th> Tipo de Red</th><th>Clave</th><th>LLave_W</th><th>Puerto</th><th>Publicar</th><th></th></thead>";
|
TablaHTML += " <thead><th>Nombre Local</th><th> Tipo de Red</th><th>Clave</th><th>LLave_W</th><th>Puerto</th><th>Publicar</th><th></th></thead>";
|
||||||
for (i = 0, t = Cantidad; i < t; ++i)
|
for (i = 0, t = Cantidad; i < t; ++i)
|
||||||
{
|
{
|
||||||
var publicar = "<span class='badge badge-success'>"+Publicar[i].Publicar +"</span>";
|
var publicar = "<span class='badge text-bg-success'>"+Publicar[i].Publicar +"</span>";
|
||||||
if(Publicar[i].Publicar == false) {publicar = "<span class='badge badge-danger'>"+Publicar[i].Publicar +"</span>";}
|
if(Publicar[i].Publicar == false) {publicar = "<span class='badge text-bg-danger'>"+Publicar[i].Publicar +"</span>";}
|
||||||
if((Publicar[i].TipoRed != "emacenter") && (Publicar[i].TipoRed != "emacentergugler"))
|
if((Publicar[i].TipoRed != "emacenter") && (Publicar[i].TipoRed != "emacentergugler"))
|
||||||
{
|
{
|
||||||
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge badge-success'>SI</span></td><td><span class='badge badge-danger'>NO</span></td><td><span class='badge badge-default'>N/A</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='selectpicker show-tick' data-width='fit' data-style='btn-primary'>";
|
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge text-bg-success'>SI</span></td><td><span class='badge text-bg-danger'>NO</span></td><td><span class='badge text-bg-secondary'>N/A</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='form-select'>";
|
||||||
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
||||||
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
||||||
}else{
|
}else{
|
||||||
if(Publicar[i].Llave_W != ''){var tienellave = "SI";}else{var tienellave ="NO";}
|
if(Publicar[i].Llave_W != ''){var tienellave = "SI";}else{var tienellave ="NO";}
|
||||||
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge badge-default'>N/A</span></td><td><span class='badge badge-success'>"+tienellave+"</span></td><td><span class='badge badge-default'>"+(Publicar[i].Puerto || "N/A")+"</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='selectpicker show-tick' data-width='fit' data-style='btn-primary'>";
|
TablaHTML += "<tr><td><b>"+Publicar[i].Nombre+"</b></td><td>"+Publicar[i].TipoRed+"</td><td><span class='badge text-bg-secondary'>N/A</span></td><td><span class='badge text-bg-success'>"+tienellave+"</span></td><td><span class='badge text-bg-secondary'>"+(Publicar[i].Puerto || "N/A")+"</span></td><td>"+publicar+"</td><td><select onchange='MenuRedes("+i+")' title='Accion' id='Red_activa_"+i+"' name='Red_activa' class='form-select'>";
|
||||||
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
if(Publicar[i].Publicar == true) {TablaHTML += "<option value='NoPublicar'>No Publicar</option>"}else{TablaHTML += "<option value='Publicar'>Publicar</option>"};
|
||||||
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
TablaHTML += "<option value='Modificar'>Modificar</option><option value='Eliminar'>Eliminar</option><option value='SitioOficial'>Sitio Oficial</option></select></td></tr>";
|
||||||
}
|
}
|
||||||
@ -603,8 +603,6 @@ function ListarRedes()
|
|||||||
BotonHTML = '<button id="botonguardar" type="button" class="btn btn-sm btn-success" onclick="MenuGUI(\'redes_alta\')" role="button">Alta de una Red</button>';
|
BotonHTML = '<button id="botonguardar" type="button" class="btn btn-sm btn-success" onclick="MenuGUI(\'redes_alta\')" role="button">Alta de una Red</button>';
|
||||||
$('#redesconfiguradas').html(TablaHTML);
|
$('#redesconfiguradas').html(TablaHTML);
|
||||||
$('#BotonRed').html(BotonHTML);
|
$('#BotonRed').html(BotonHTML);
|
||||||
for (i = 0, t = Cantidad; i < t; ++i)
|
|
||||||
{$('#Red_activa_'+i).selectpicker('render');}
|
|
||||||
Publicar=null;Cantidad=null;TablaHTML=null;tieneusuario=null;tienellave=null;
|
Publicar=null;Cantidad=null;TablaHTML=null;tieneusuario=null;tienellave=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -876,7 +874,7 @@ function FormModificar(red)
|
|||||||
TablaHTML += "<table class='table table-striped'>";
|
TablaHTML += "<table class='table table-striped'>";
|
||||||
TablaHTML += "<thead><tr align='center'><th colspan='6'>Tipo de Red</th></tr></thead>";
|
TablaHTML += "<thead><tr align='center'><th colspan='6'>Tipo de Red</th></tr></thead>";
|
||||||
TablaHTML += "<tr><td colspan='6' align='left'>";
|
TablaHTML += "<tr><td colspan='6' align='left'>";
|
||||||
TablaHTML += "<select id='Tipo_Red' name='Tipo_Red' onchange='MenuSelectRed();' class='selectpicker show-tick' data-width='fit' data-style='btn-primary'>";
|
TablaHTML += "<select id='Tipo_Red' name='Tipo_Red' onchange='MenuSelectRed();' class='form-select'>";
|
||||||
TablaHTML += "<optgroup label='RED EMACENTER'>";
|
TablaHTML += "<optgroup label='RED EMACENTER'>";
|
||||||
TablaHTML += "<option value='emacentergugler'>Gugler EmaCenter - Gugler</option>";
|
TablaHTML += "<option value='emacentergugler'>Gugler EmaCenter - Gugler</option>";
|
||||||
TablaHTML += "<option value='emacenter'>Emacenter Personalizada</option></optgroup>";
|
TablaHTML += "<option value='emacenter'>Emacenter Personalizada</option></optgroup>";
|
||||||
@ -898,7 +896,6 @@ function FormModificar(red)
|
|||||||
$('#BotonRed').html(BotonHTML);
|
$('#BotonRed').html(BotonHTML);
|
||||||
$('#Tipo_Red').val(configGeneralEMA.ConfPublicador[red].TipoRed);
|
$('#Tipo_Red').val(configGeneralEMA.ConfPublicador[red].TipoRed);
|
||||||
MenuSelectRed();
|
MenuSelectRed();
|
||||||
$('#Tipo_Red').selectpicker('render');
|
|
||||||
TablaHTML=null;
|
TablaHTML=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,43 +917,30 @@ function VerHistoricoT(lugar)
|
|||||||
|
|
||||||
// FUNCIONES DE ESCRITURA EN DISCO
|
// FUNCIONES DE ESCRITURA EN DISCO
|
||||||
|
|
||||||
function GuardarConf(origen)
|
async function GuardarConf(origen) {
|
||||||
{
|
const persist = async draft => {
|
||||||
if (origen == 'conf'){
|
try {
|
||||||
//Se Setean los campos
|
const result = await $.ajax({url: '/GuardarConf', method: 'POST', contentType: 'application/json', data: JSON.stringify({configuracion: draft})});
|
||||||
HABLA(0,"Se almacenó correctamente la configuración", "success");
|
if (!result.ok) throw new Error('No se pudo guardar la configuración.');
|
||||||
configGeneralEMA.ConfGeneral.NombreEstacion = $('#NombreEstacion').val();
|
if (result.warning) HABLA(0, result.warning, 'warn');
|
||||||
configGeneralEMA.ConfEmail.Servicio = $('#Tipo_SMTP').val();
|
} catch (request) {
|
||||||
if($('#Tipo_SMTP').val() == "Deshabilitado"){configGeneralEMA.ConfEmail.ActivarCorreos = false;}else{configGeneralEMA.ConfEmail.ActivarCorreos = true;}
|
const error = new Error(request.responseJSON?.error || request.message || 'No se pudo conectar con el servidor. Reintentá el guardado.');
|
||||||
configGeneralEMA.ConfEmail.Usuario = $('#Usuario_SMTP').val();
|
error.fields = request.responseJSON?.fields;
|
||||||
configGeneralEMA.ConfEmail.Password = $('#Contrasenia_SMTP').val();
|
throw error;
|
||||||
configGeneralEMA.ConfEmail.Server = $('#Server_SMTP').val();
|
}
|
||||||
configGeneralEMA.ConfEmail.Puerto = $('#Puerto_SMTP').val();
|
configGeneralEMA = draft;
|
||||||
configGeneralEMA.ConfEmail.ReceptorEmail = $('#Email_receptor').val();
|
};
|
||||||
configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion = parseInt($('#Tiempo_de_Recoleccion').val());
|
if (origen === 'conf') return ConfigUI.save(persist);
|
||||||
configGeneralEMA.ConfGeneral.debug = parseInt($('#Debug').val());
|
try {
|
||||||
configGeneralEMA.ConfGeneral.UTC = parseInt($('#utc').val());
|
await persist(configGeneralEMA);
|
||||||
configGeneralEMA.ConfGeneral.SistemaMetrico = $('#SistemaMetrico').val();
|
HABLA(0, 'Configuración guardada.', 'success');
|
||||||
configGeneralEMA.ConfGeneral.Modo = $('#Modo').val();
|
return true;
|
||||||
configGeneralEMA.ConfGeneral.IP = $('#r_ip').val();
|
} catch (error) {
|
||||||
configGeneralEMA.ConfGeneral.Puerto = $('#r_puerto').val();
|
HABLA(0, 'No se pudo guardar la configuración: ' + error.message, 'warn');
|
||||||
configGeneralEMA.ConfGeneral.Ruta = $('#r_path').val();
|
return false;
|
||||||
configGeneralEMA.ConfGeneral.Llave_R = $('#Llave_R').val();
|
}
|
||||||
configGeneralEMA.ConfGeneral.debugTamanio = parseInt($('#debugMB').val());
|
}
|
||||||
if($('#inicio_auto').val() == "Activado"){configGeneralEMA.ConfGeneral.inicio_automatico = true;}else{configGeneralEMA.ConfGeneral.inicio_automatico = false;}
|
|
||||||
if($('#notificar_cambios').val() == "Activado"){configGeneralEMA.ConfGeneral.notificar_cambios = true;}else{configGeneralEMA.ConfGeneral.notificar_cambios = false;}
|
|
||||||
if($('#audio').val() == "Activado"){configGeneralEMA.ConfGeneral.Audio = true;}else{configGeneralEMA.ConfGeneral.Audio = false;}
|
|
||||||
configGeneralEMA.ConfGeneral.audioVoces = $('#vocesAudio').val();
|
|
||||||
}
|
|
||||||
//Se almacenan los campos
|
|
||||||
// var configuracion_nueva = '// Configuraciones generales de EMA RECOLECTOR' + '\n\n';
|
|
||||||
var configuracion_nueva = 'module.exports = ';
|
|
||||||
configuracion_nueva += JSON.stringify(configGeneralEMA, null, ' ');
|
|
||||||
configuracion_nueva += ';';
|
|
||||||
|
|
||||||
$.get("/GuardarConf/{"+configuracion_nueva+"}", function(data, status){console.log('Guardo la Configuracion'); });
|
|
||||||
};
|
|
||||||
|
|
||||||
function PurgarP(origen)
|
function PurgarP(origen)
|
||||||
{
|
{
|
||||||
$.get("/purgarPendiente", function(data, status){console.log('Purgar Pendiente'); });
|
$.get("/purgarPendiente", function(data, status){console.log('Purgar Pendiente'); });
|
||||||
@ -984,7 +968,7 @@ function VerHistorico(lugar)
|
|||||||
{
|
{
|
||||||
$.get("/verHistorico", function(data, status){
|
$.get("/verHistorico", function(data, status){
|
||||||
var TablaHTML = '';
|
var TablaHTML = '';
|
||||||
TablaHTML += '<table id="MiTablaH" class="display" style="width:100%" >';
|
TablaHTML += '<table id="MiTablaH" class="table table-bordered" style="width:100%" >';
|
||||||
TablaHTML += '<thead>';
|
TablaHTML += '<thead>';
|
||||||
TablaHTML += '<tr>';
|
TablaHTML += '<tr>';
|
||||||
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
||||||
@ -1054,7 +1038,7 @@ function VerHistorico(lugar)
|
|||||||
});
|
});
|
||||||
}else{ //MODO Visor
|
}else{ //MODO Visor
|
||||||
var TablaHTML = '';
|
var TablaHTML = '';
|
||||||
TablaHTML += '<table id="MiTablaH" class="display" style="width:100%" >';
|
TablaHTML += '<table id="MiTablaH" class="table table-bordered" style="width:100%" >';
|
||||||
TablaHTML += '<thead>';
|
TablaHTML += '<thead>';
|
||||||
TablaHTML += '<tr>';
|
TablaHTML += '<tr>';
|
||||||
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
||||||
@ -1099,7 +1083,7 @@ function VerHistorico(lugar)
|
|||||||
if(lugar == 0) {
|
if(lugar == 0) {
|
||||||
$('#MiTablaH').DataTable( {
|
$('#MiTablaH').DataTable( {
|
||||||
dom: 'Bfrtip',
|
dom: 'Bfrtip',
|
||||||
buttons: ['copy','csv'],
|
buttons: TablaUI.buttons(),
|
||||||
pageLength: 5,
|
pageLength: 5,
|
||||||
scrollX: true,
|
scrollX: true,
|
||||||
scrollCollapse: true,
|
scrollCollapse: true,
|
||||||
@ -1155,7 +1139,7 @@ function VerHistorico(lugar)
|
|||||||
}else{
|
}else{
|
||||||
$('#MiTablaH').DataTable( {
|
$('#MiTablaH').DataTable( {
|
||||||
dom: 'Bfrtip',
|
dom: 'Bfrtip',
|
||||||
buttons: ['copy','csv'],
|
buttons: TablaUI.buttons(),
|
||||||
pageLength: 5,
|
pageLength: 5,
|
||||||
scrollCollapse: true,
|
scrollCollapse: true,
|
||||||
lengthChange: false,
|
lengthChange: false,
|
||||||
@ -1213,7 +1197,7 @@ function VerRegistrosLog(select)
|
|||||||
document.getElementById("mostrarregistrosLogs").style.display = "none";
|
document.getElementById("mostrarregistrosLogs").style.display = "none";
|
||||||
$.get("/verLogs", function(data, status){
|
$.get("/verLogs", function(data, status){
|
||||||
var TablaHTML = '';
|
var TablaHTML = '';
|
||||||
TablaHTML += '<table id="MiTabla" class="display" style="width:100%;" >';
|
TablaHTML += '<table id="MiTabla" class="table table-bordered" style="width:100%;" >';
|
||||||
TablaHTML += '<thead>';
|
TablaHTML += '<thead>';
|
||||||
TablaHTML += '<tr> ';
|
TablaHTML += '<tr> ';
|
||||||
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
TablaHTML += '<th style="text-align:center;">Nº</th>';
|
||||||
@ -1273,28 +1257,6 @@ function VerRegistrosLog(select)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function MostrarTabla(DATOS,DIV,TABLA)
|
|
||||||
{
|
|
||||||
$('#'+DIV).empty();
|
|
||||||
$('#'+DIV).html(DATOS);
|
|
||||||
$('#'+TABLA).DataTable(
|
|
||||||
{
|
|
||||||
dom: 'Bfrtip',
|
|
||||||
buttons: ['copy','csv'],
|
|
||||||
pageLength: 8,
|
|
||||||
scrollX: true,
|
|
||||||
destroy:true,
|
|
||||||
initComplete: function(settings, json) {
|
|
||||||
document.getElementById(DIV).style.display = "block";
|
|
||||||
document.getElementById("actualizando").style.display = "none";
|
|
||||||
},
|
|
||||||
language: {url: "./css/Spanish.json"}
|
|
||||||
});
|
|
||||||
DATOS = null;
|
|
||||||
TABLA = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function graficoEstadisticas()
|
async function graficoEstadisticas()
|
||||||
{
|
{
|
||||||
// GRAFICO DEL TIEMPO CHARTJS
|
// GRAFICO DEL TIEMPO CHARTJS
|
||||||
|
|||||||
@ -157,43 +157,9 @@ app.get('/purgarPendiente', function (req, res)
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
app.get('/GuardarConf/:configuracion_nueva', function (req, res)
|
require('./configuracion-api.js').registrarConfiguracion(app, {
|
||||||
{
|
guardar: require('../core/configuracion-store.js').guardarConfiguracion,
|
||||||
var configuracion_nueva = '// Configuraciones generales de EMA RECOLECTOR\n\n' + req.params.configuracion_nueva;
|
reconfigurar: config => EMA.Reconfigurar(config)
|
||||||
fsconf.writeFile('./conf/ConfiguracionGeneral.js', configuracion_nueva, function(err) {
|
|
||||||
if( err ){
|
|
||||||
EMA.RegistrarLog("0|CORE|Upps, existió un problema intentando almacenar la configuración.");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
EMA.Reconfigurar();
|
|
||||||
EMA.RegistrarLog("0|CORE|Se almaceno correctamente la configuración");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
res.json('ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post('/GuardarConf', function (req, res) {
|
|
||||||
|
|
||||||
if (!req.body || !req.body.configuracion) {
|
|
||||||
return res.status(400).json({ ok: false, error: 'Configuración no recibida' });
|
|
||||||
}
|
|
||||||
|
|
||||||
const configuracion_nueva =
|
|
||||||
'// Configuraciones generales de EMA RECOLECTOR\n\n' +
|
|
||||||
'module.exports = ' +
|
|
||||||
JSON.stringify(req.body.configuracion, null, 2) +
|
|
||||||
';\n';
|
|
||||||
|
|
||||||
fsconf.writeFile('./conf/ConfiguracionGeneral.js', configuracion_nueva, function (err) {
|
|
||||||
if (err) {
|
|
||||||
EMA.RegistrarLog("0|CORE|❌ Error al guardar configuración");
|
|
||||||
return res.status(500).json({ ok: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
EMA.Reconfigurar();
|
|
||||||
EMA.RegistrarLog("0|CORE|✅ Configuración guardada correctamente");
|
|
||||||
res.json({ ok: true });
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/VerHistorico', function (req, res)
|
app.get('/VerHistorico', function (req, res)
|
||||||
@ -216,27 +182,31 @@ app.get('/interfaces', (req, res) => {
|
|||||||
app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); next();});
|
app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); next();});
|
||||||
app.use(express.static('gui_web'));
|
app.use(express.static('gui_web'));
|
||||||
|
|
||||||
// Bootstrap 4 y librerías necesarias
|
// Bootstrap 5 y librerías necesarias
|
||||||
// CSS
|
// CSS
|
||||||
app.use('/css', express.static(__dirname + '/../node_modules/bootstrap/dist/css'));
|
app.use('/css', express.static(__dirname + '/../node_modules/bootstrap/dist/css'));
|
||||||
app.use('/css', express.static(__dirname + '/../node_modules/datatables/media/css'));
|
app.use('/css', express.static(__dirname + '/../node_modules/datatables.net-bs5/css'));
|
||||||
|
app.use('/css', express.static(__dirname + '/../node_modules/datatables.net-buttons-bs5/css'));
|
||||||
app.use('/css', express.static(__dirname + '/../node_modules/nprogress'));
|
app.use('/css', express.static(__dirname + '/../node_modules/nprogress'));
|
||||||
app.use('/css', express.static(__dirname + '/../node_modules/bootstrap-select/dist/css'));
|
|
||||||
app.use('/css', express.static(__dirname + '/../gui_common/css'));
|
app.use('/css', express.static(__dirname + '/../gui_common/css'));
|
||||||
|
|
||||||
|
app.use('/gui_common/css', express.static(__dirname + '/../gui_common/css'));
|
||||||
|
|
||||||
|
app.use('/gui_common/view', express.static(__dirname + '/../gui_common/view'));
|
||||||
|
|
||||||
// IMG
|
// IMG
|
||||||
app.use('/images', express.static(__dirname + '/../node_modules/datatables/media/images'));
|
|
||||||
app.use('/gui_common/iconos', express.static(__dirname + '/../gui_common/iconos'));
|
app.use('/gui_common/iconos', express.static(__dirname + '/../gui_common/iconos'));
|
||||||
app.use('/gui_common/img', express.static(__dirname + '/../gui_common/img'));
|
app.use('/gui_common/img', express.static(__dirname + '/../gui_common/img'));
|
||||||
// JS
|
// JS
|
||||||
|
app.use('/js', express.static(__dirname + '/../gui_common/js'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/jquery/dist'));
|
app.use('/js', express.static(__dirname + '/../node_modules/jquery/dist'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/popper.js/dist/umd'));
|
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/bootstrap/dist/js'));
|
app.use('/js', express.static(__dirname + '/../node_modules/bootstrap/dist/js'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/bootstrap-select/dist/js'));
|
app.use('/js', express.static(__dirname + '/../node_modules/datatables.net/js'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/datatables/media/js'));
|
app.use('/js', express.static(__dirname + '/../node_modules/datatables.net-bs5/js'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/notify-js-lib/dist'));
|
app.use('/js', express.static(__dirname + '/../node_modules/notify-js-lib/dist'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/nprogress'));
|
app.use('/js', express.static(__dirname + '/../node_modules/nprogress'));
|
||||||
app.use('/js', express.static(__dirname + '/../node_modules/datatables-buttons/js'));
|
app.use('/js', express.static(__dirname + '/../node_modules/datatables.net-buttons/js'));
|
||||||
|
app.use('/js', express.static(__dirname + '/../node_modules/datatables.net-buttons-bs5/js'));
|
||||||
app.use('/js', express.static(__dirname + '/../gui_common/libs/RGraph'));
|
app.use('/js', express.static(__dirname + '/../gui_common/libs/RGraph'));
|
||||||
app.use('/controlador', express.static(__dirname + '/../gui_common/controlador'));
|
app.use('/controlador', express.static(__dirname + '/../gui_common/controlador'));
|
||||||
|
|
||||||
|
|||||||
@ -7,27 +7,30 @@
|
|||||||
<title>EMA Libre Cliente (Carpincho)</title>
|
<title>EMA Libre Cliente (Carpincho)</title>
|
||||||
<link rel="icon" type="image/png" href="gui_common/iconos/icono_app.png" sizes="16x16">
|
<link rel="icon" type="image/png" href="gui_common/iconos/icono_app.png" sizes="16x16">
|
||||||
<!-- Estilos varios css -->
|
<!-- Estilos varios css -->
|
||||||
<link rel="stylesheet" type="text/css" href="/css/jquery.dataTables.min.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
|
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap-select.min.css">
|
<link rel="stylesheet" href="/css/dataTables.bootstrap5.min.css">
|
||||||
|
<link rel="stylesheet" href="/css/buttons.bootstrap5.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="css/nprogress.css">
|
<link rel="stylesheet" type="text/css" href="css/nprogress.css">
|
||||||
|
|
||||||
<!-- Estilo principal css -->
|
<!-- Estilo principal css -->
|
||||||
<link rel="stylesheet" type="text/css" href="css/style.css">
|
<link rel="stylesheet" type="text/css" href="gui_common/css/style.css">
|
||||||
<!-- Libreria bootstrap/jquery para graficos -->
|
<!-- Libreria bootstrap/jquery para graficos -->
|
||||||
<script type="text/javascript" src="js/jquery.min.js"></script>
|
<script type="text/javascript" src="js/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="js/popper.min.js"></script>
|
<script type="text/javascript" src="js/bootstrap.bundle.min.js"></script>
|
||||||
<script type="text/javascript" src="js/bootstrap.min.js"></script>
|
<script src="js/configuracion-modelo.js"></script>
|
||||||
|
<script src="js/configuracion.js"></script>
|
||||||
|
<script src="js/tablas.js"></script>
|
||||||
|
<script src="js/estado.js"></script>
|
||||||
<!-- Libreria bootstrap select para graficos -->
|
<!-- Libreria bootstrap select para graficos -->
|
||||||
<script type="text/javascript" src="js/bootstrap-select.min.js"></script>
|
|
||||||
<!-- Datable - Para las tablas dinamicas -->
|
<!-- Datable - Para las tablas dinamicas -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="js/jquery.dataTables.min.js"></script>
|
<script type="text/javascript" src="js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="js/dataTables.bootstrap5.min.js"></script>
|
||||||
<script type="text/javascript" src="js/dataTables.buttons.js"></script>
|
<script type="text/javascript" src="js/dataTables.buttons.js"></script>
|
||||||
<script type="text/javascript" src="js/buttons.html5.js"></script>
|
<script type="text/javascript" src="js/buttons.html5.js"></script>
|
||||||
<script type="text/javascript" src="js/buttons.bootstrap.js"></script>
|
<script type="text/javascript" src="js/buttons.bootstrap5.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
<!-- Libreria RGraph/css para graficos -->
|
<!-- Libreria RGraph/css para graficos -->
|
||||||
@ -57,17 +60,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="principal" style="display: none;">
|
<div id="principal" style="display: none;">
|
||||||
<nav style="-webkit-app-region: drag;cursor: all-scroll" class="navbar stylish-color fixed-top scrolling-navbar ">
|
<nav style="-webkit-app-region: drag;cursor: all-scroll" class="navbar stylish-color sticky-top scrolling-navbar ">
|
||||||
<span style="-webkit-app-region: no-drag;color: #ffffff;" data-toggle="tooltip" data-placement="bottom" style="font-size: 15px;"><img id="signal" class="" src="gui_common/img/signal.webp" height="16px" width="16px" data-toggle="tooltip"
|
<span style="-webkit-app-region: no-drag;color: #ffffff;" data-bs-toggle="tooltip" data-bs-placement="bottom" style="font-size: 15px;"><img id="signal" class="" src="gui_common/img/signal.webp" height="16px" width="16px" data-bs-toggle="tooltip"
|
||||||
data-placement="right" data-html="true" title="Señal RF de la estación"> EMA Libre Cliente </span>
|
data-bs-placement="right" data-bs-html="true" title="Señal RF de la estación"> EMA Libre Cliente </span>
|
||||||
<spam id="mensajebarra" class="float-center" style="color:white"></spam>
|
<spam id="mensajebarra" class="float-center" style="color:white"></spam>
|
||||||
<span style="-webkit-app-region: no-drag" class="float-right">
|
<span style="-webkit-app-region: no-drag" class="float-end">
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wzoomout" style="font-size: 15px;" title="Disminuir"><img id="Wzoomout" height="16px" width="16px" src="gui_common/iconos/zoomout.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wzoomout" style="font-size: 15px;" title="Disminuir"><img id="Wzoomout" height="16px" width="16px" src="gui_common/iconos/zoomout.webp"></i>
|
||||||
<i class="custom-controls menu" data-toggle="tooltip" data-placement="bottom" role="menusup" aria-controls="Wzoomin" style="font-size: 15px;" title="Aumentar" ><img id="Wzoomin" height="16px" width="16px" src="gui_common/iconos/zoomin.webp"></i>
|
<i class="custom-controls menu" data-bs-toggle="tooltip" data-bs-placement="bottom" role="menusup" aria-controls="Wzoomin" style="font-size: 15px;" title="Aumentar" ><img id="Wzoomin" height="16px" width="16px" src="gui_common/iconos/zoomin.webp"></i>
|
||||||
</span>
|
</span>
|
||||||
</nav>
|
</nav>
|
||||||
<br><br>
|
<section id="estado-estacion" class="estado-estacion" aria-label="Estado de la estación"></section>
|
||||||
|
|
||||||
<div id="superior" class="container">
|
<div id="superior" class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-2" align="center" style="vertical-align:top;">
|
<div class="col-2" align="center" style="vertical-align:top;">
|
||||||
@ -87,8 +89,8 @@
|
|||||||
<div class="col-2" align="center">
|
<div class="col-2" align="center">
|
||||||
<div id="DIVModo" style="vertical-align:top;visibility: hidden"> </div>
|
<div id="DIVModo" style="vertical-align:top;visibility: hidden"> </div>
|
||||||
<div id="DIVPendientes" style="vertical-align:top;visibility: hidden">
|
<div id="DIVPendientes" style="vertical-align:top;visibility: hidden">
|
||||||
<span class='badge badge-warning'>Registros Pendientes</span>
|
<span class='badge text-bg-warning'>Registros Pendientes</span>
|
||||||
<span id="Pendientes" class='badge badge-warning'></span>
|
<span id="Pendientes" class='badge text-bg-warning'></span>
|
||||||
<span id="Destanqueo" class="parpadea texttanque" style="vertical-align:top;visibility: hidden"><strong>Destanqueando</strong></span>
|
<span id="Destanqueo" class="parpadea texttanque" style="vertical-align:top;visibility: hidden"><strong>Destanqueando</strong></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -98,36 +100,36 @@
|
|||||||
<div class="container container-fluid">
|
<div class="container container-fluid">
|
||||||
<ul class="nav nav-tabs nav-inverse nav-pills nav-fill" id="list-tab" role="tablist">
|
<ul class="nav nav-tabs nav-inverse nav-pills nav-fill" id="list-tab" role="tablist">
|
||||||
<li class="nav-item active ">
|
<li class="nav-item active ">
|
||||||
<a class="nav-link active show" id="inicio-tab" data-toggle="tab" data-target="#inicio" role="tab" aria-controls="inicio" aria-selected="true"><img height="24px" width="24px" src="gui_common/img/home.webp" aria-controls="inicio"> INICIO</a>
|
<a class="nav-link active show" id="inicio-tab" data-bs-toggle="tab" data-bs-target="#inicio" role="tab" aria-controls="inicio" aria-selected="true"><img height="24px" width="24px" src="gui_common/img/home.webp" aria-controls="inicio"> INICIO</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="interior-tab" data-toggle="tab" data-target="#interior" role="tab" aria-controls="interior" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/interior.webp" aria-controls="interior"> INTERIOR</a>
|
<a class="nav-link" id="interior-tab" data-bs-toggle="tab" data-bs-target="#interior" role="tab" aria-controls="interior" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/interior.webp" aria-controls="interior"> INTERIOR</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="exterior-tab" data-toggle="tab" data-target="#exterior" role="tab" aria-controls="exterior" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/exterior.webp" aria-controls="exterior"> EXTERIOR</a>
|
<a class="nav-link" id="exterior-tab" data-bs-toggle="tab" data-bs-target="#exterior" role="tab" aria-controls="exterior" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/exterior.webp" aria-controls="exterior"> EXTERIOR</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- <li class="nav-item">
|
<!-- <li class="nav-item">
|
||||||
<a class="nav-link" id="estadisticas-tab" data-toggle="tab" data-target="#estadisticas" role="tab" aria-controls="estadisticas" aria-selected="false"><img height="24px" width="24px" src="img/estadistica.png" aria-controls="estadisticas"> ESTADISTICAS</a>
|
<a class="nav-link" id="estadisticas-tab" data-bs-toggle="tab" data-bs-target="#estadisticas" role="tab" aria-controls="estadisticas" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/estadistica.png" aria-controls="estadisticas"> ESTADISTICAS</a>
|
||||||
</li> -->
|
</li> -->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="redes-tab" data-toggle="tab" data-target="#redes" role="tab" aria-controls="redes" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/redes.webp" aria-controls="redes"> REDES</a>
|
<a class="nav-link" id="redes-tab" data-bs-toggle="tab" data-bs-target="#redes" role="tab" aria-controls="redes" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/redes.webp" aria-controls="redes"> REDES</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="configuracion-tab" data-toggle="tab" data-target="#configuracion" role="tab" aria-controls="configuracion" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/config.webp" aria-controls="configuracion"> CONFIGURACIÓN</a>
|
<a class="nav-link" id="configuracion-tab" data-bs-toggle="tab" data-bs-target="#configuracion" role="tab" aria-controls="configuracion" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/config.webp" aria-controls="configuracion"> CONFIGURACIÓN</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="contacto-tab" data-toggle="tab" data-target="#contacto" target="_self" role="tab" aria-controls="contacto" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/about.webp" aria-controls="contacto"> CONTACTO</a>
|
<a class="nav-link" id="contacto-tab" data-bs-toggle="tab" data-bs-target="#contacto" target="_self" role="tab" aria-controls="contacto" aria-selected="false"><img height="24px" width="24px" src="gui_common/img/about.webp" aria-controls="contacto"> CONTACTO</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content jumbotron" id="" style="padding: 15px;padding-bottom:15px;margin-bottom:15px">
|
<div class="tab-content ema-panel" id="" style="padding: 15px;padding-bottom:15px;margin-bottom:15px">
|
||||||
<div id="actualizando_inicio" style="display:none" align="center"><br><br><br><br><img src='gui_common/img/animadas/cargando2.gif' width='100' height='100' /> <br><br><br><br> </div>
|
<div id="actualizando_inicio" style="display:none" align="center"><br><br><br><br><img src='gui_common/img/animadas/cargando2.gif' width='100' height='100' /> <br><br><br><br> </div>
|
||||||
<div class="tab-pane fade show active" id="inicio" role="tabpanel" aria-badgeledby="inicio-tab"></div>
|
<div class="tab-pane fade show active" id="inicio" role="tabpanel" aria-labelledby="inicio-tab"></div>
|
||||||
<div class="tab-pane fade text-center" id="interior" role="tabpanel" aria-badgeledby="interior-tab"></div>
|
<div class="tab-pane fade text-center" id="interior" role="tabpanel" aria-labelledby="interior-tab"></div>
|
||||||
<div class="tab-pane fade text-center" id="exterior" role="tabpanel" aria-badgeledby="exterior-tab"></div>
|
<div class="tab-pane fade text-center" id="exterior" role="tabpanel" aria-labelledby="exterior-tab"></div>
|
||||||
<!-- <div class="tab-pane fade text-center" id="estadisticas" role="tabpanel" aria-badgeledby="estadisticas-tab"></div>-->
|
<!-- <div class="tab-pane fade text-center" id="estadisticas" role="tabpanel" aria-labelledby="estadisticas-tab"></div>-->
|
||||||
<div class="tab-pane fade text-center" id="configuracion" role="tabpanel" aria-badgeledby="configuracion-tab"></div>
|
<div class="tab-pane fade text-center" id="configuracion" role="tabpanel" aria-labelledby="configuracion-tab"></div>
|
||||||
<div class="tab-pane fade text-center" id="redes" role="tabpanel" aria-badgeledby="redes-tab"></div>
|
<div class="tab-pane fade text-center" id="redes" role="tabpanel" aria-labelledby="redes-tab"></div>
|
||||||
<div class="tab-pane fade" id="contacto" role="tabpanel" aria-badgeledby="contacto-tab"></div>
|
<div class="tab-pane fade" id="contacto" role="tabpanel" aria-labelledby="contacto-tab"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="fixed-bottom">
|
<footer class="fixed-bottom">
|
||||||
@ -147,10 +149,7 @@
|
|||||||
if(zoom_level>=120 && step>0 || zoom_level<=80 && step<0) return;
|
if(zoom_level>=120 && step>0 || zoom_level<=80 && step<0) return;
|
||||||
if(step==0) zoom_level=100;
|
if(step==0) zoom_level=100;
|
||||||
else zoom_level=zoom_level+step;
|
else zoom_level=zoom_level+step;
|
||||||
$('body').css({
|
document.body.style.zoom = zoom_level / 100;
|
||||||
transform: 'scale('+(zoom_level/100)+')', // set zoom
|
|
||||||
transformOrigin: '50% 0' // set transform scale base
|
|
||||||
});
|
|
||||||
if(zoom_level>100) $('#Wzoomin').addClass('invisible');
|
if(zoom_level>100) $('#Wzoomin').addClass('invisible');
|
||||||
else $('#Wzoomin').removeClass('invisible');
|
else $('#Wzoomin').removeClass('invisible');
|
||||||
}
|
}
|
||||||
@ -170,8 +169,7 @@
|
|||||||
obj = null;
|
obj = null;
|
||||||
});
|
});
|
||||||
$('.nav-link').on('click', function(evnt) {
|
$('.nav-link').on('click', function(evnt) {
|
||||||
var obj = $(evnt.target);
|
var obj = $(evnt.currentTarget);
|
||||||
$('#' + obj.attr('aria-controls')).empty();
|
|
||||||
MenuGUI(obj.attr('aria-controls'));
|
MenuGUI(obj.attr('aria-controls'));
|
||||||
obj = null;
|
obj = null;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,239 +0,0 @@
|
|||||||
<div class="col-centered">
|
|
||||||
<h1>Configuración General</h1>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 text-right" style="vertical-align:top;"><button class="btn btn-sm btn-success" onclick="MenuGUI('logs');" role="button">Ver Logs</button> </div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">Ema Modo</label><br>
|
|
||||||
<select id='Modo' name="Modo" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Recolector">
|
|
||||||
<option value="Recolector_USB">Recolector USB</option>
|
|
||||||
<option value="Recolector_IP">Recolector IP/WIFI</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Visor">
|
|
||||||
<option value="Visor">Visor Llave</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">Nombre de tu estación</label><br>
|
|
||||||
<input type="text" class="btn btn-primary" id="NombreEstacion" autocomplete='name' placeholder="Ingrese el nombre" maxlength="20" size="30"></br></br>
|
|
||||||
</div>
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label for="inputEmail" class="control-label">Correo del Administrador</label><br>
|
|
||||||
<input type="email" class="btn btn-primary" id="Email_receptor" autocomplete='email' placeholder="Email" maxlength="50" size="35">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Inicio Automático</label><br>
|
|
||||||
<select id='inicio_auto' name="inicio_auto" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Iniciar el recolector/visor con el aplicativo">
|
|
||||||
<option value="Activado">Activado</option>
|
|
||||||
<option value="Desactivado">Desactivado</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Notificar Cambios</label><br>
|
|
||||||
<select id='notificar_cambios' name="notificar_cambios" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Notificar de carpincho">
|
|
||||||
<option value="Activado">Activado</option>
|
|
||||||
<option value="Desactivado">Desactivado</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Audio</label><br>
|
|
||||||
<select id='audio' name="audio" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Audio de carpincho">
|
|
||||||
<option value="Activado">Activado</option>
|
|
||||||
<option value="Desactivado">Desactivado</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered" id="vocesAudioDiv">
|
|
||||||
<label class="control-label">Voz del Audio</label></br>
|
|
||||||
<select id='vocesAudio' name="vocesAudio" class="selectpicker show-tick" data-width="fit" data-style="btn-primary" size="100">
|
|
||||||
<optgroup label="Lista de Voces">
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Recolección</label><br>
|
|
||||||
<select id='Tiempo_de_Recoleccion' name="Tiempo_de_Recoleccion" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Muy Rapido">
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="20">20</option>
|
|
||||||
<option value="30">30</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Medio">
|
|
||||||
<option value="40">40</option>
|
|
||||||
<option value="50">50</option>
|
|
||||||
<option value="60">60</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Normal">
|
|
||||||
<option value="70">70</option>
|
|
||||||
<option value="80">80</option>
|
|
||||||
<option value="90">90</option>
|
|
||||||
<option value="100">100</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Despacio">
|
|
||||||
<option value="110">110</option>
|
|
||||||
<option value="120">120</option>
|
|
||||||
<option value="130">130</option>
|
|
||||||
<option value="140">140</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">Debug y Tamaño</label><br>
|
|
||||||
<select id='Debug' name="Debug" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Normal">
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Alto">
|
|
||||||
<option value="4">4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="6">6</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Muy Alto">
|
|
||||||
<option value="7">7</option>
|
|
||||||
<option value="8">8</option>
|
|
||||||
<option value="9">9</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
<input type="text" class="btn btn-primary" id="debugMB" placeholder="MB Debug" maxlength="4" size="5">
|
|
||||||
<label class="control-label">MB</label>
|
|
||||||
</div>
|
|
||||||
<div class="col-1 col-centered">
|
|
||||||
<label class="control-label">UTC</label><br>
|
|
||||||
<select id='utc' name="utc" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Negativo">
|
|
||||||
<option value="-1">-1</option>
|
|
||||||
<option value="-2">-2</option>
|
|
||||||
<option value="-3">-3</option>
|
|
||||||
<option value="-4">-4</option>
|
|
||||||
<option value="-5">-5</option>
|
|
||||||
<option value="-6">-6</option>
|
|
||||||
<option value="-7">-7</option>
|
|
||||||
<option value="-8">-8</option>
|
|
||||||
<option value="-9">-9</option>
|
|
||||||
<option value="-10">-10</option>
|
|
||||||
<option value="-11">-11</option>
|
|
||||||
<option value="-12">-12</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Neutro">
|
|
||||||
<option value="0">0</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Positivo">
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
<option value="4">4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="6">6</option>
|
|
||||||
<option value="7">7</option>
|
|
||||||
<option value="8">8</option>
|
|
||||||
<option value="9">9</option>
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="11">11</option>
|
|
||||||
<option value="12">12</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Unidades</label><br>
|
|
||||||
<select id='SistemaMetrico' name="SistemaMetrico" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="Sistema Internacional de Unidades(SI)">
|
|
||||||
<option value="SI">º C</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Sistema Anglosajón de Unidades(SA)">
|
|
||||||
<option value="SA">º F</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">SMTP TIPO</label><br>
|
|
||||||
<select id='Tipo_SMTP' name="Tipo_SMTP" onchange="MenuConfig();" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="SMTP Deshabilitado">
|
|
||||||
<option value="Deshabilitado">Deshabilitado</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="SMTP Proveedor">
|
|
||||||
<option value="Gmail">GMAIL</option>
|
|
||||||
<option value="Yahoo">YAHOO</option>
|
|
||||||
<option value="Hotmail">OUTLOOK</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="SMTP Manual">
|
|
||||||
<option value="Manual">SMTP CONFIG</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">Cuenta</label><br>
|
|
||||||
<input type="email" class="btn btn-primary" id="Usuario_SMTP" placeholder="Cuenta" maxlength="40" size="16">
|
|
||||||
</div>
|
|
||||||
<div class="col-3 col-centered">
|
|
||||||
<label class="control-label">Contraseña</label><br>
|
|
||||||
<input type="password" class="btn btn-primary" id="Contrasenia_SMTP" placeholder="Contraseña" maxlength="40" size="16">
|
|
||||||
</div>
|
|
||||||
<div class="col-2 col-centered" id="Server">
|
|
||||||
<label class="control-label">Server</label><br>
|
|
||||||
<input type="text" class="btn btn-primary" id="Server_SMTP" placeholder="Server" maxlength="40" size="15">
|
|
||||||
</div>
|
|
||||||
<div class="col-1 col-centered" id="puerto">
|
|
||||||
<label class="control-label">Puerto</label><br>
|
|
||||||
<input type="text" class="btn btn-primary" id="Puerto_SMTP" placeholder="Puerto" maxlength="4" size="5">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Segun seleccion cambia debajo el bloque secundario -->
|
|
||||||
<div id="bloque_secundario">
|
|
||||||
<hr>
|
|
||||||
<label class="control-label">Configuración específica para el Modo</label>
|
|
||||||
<div class="col-centered">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6 col-centered" id="LlaveR">
|
|
||||||
<label class="control-label">Llave de Lectura</label></br>
|
|
||||||
<input type="text" class="btn btn-primary" id="Llave_R" placeholder="Ingrese LLave" maxlength="40" size="44"></br></br>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="bloque_por_IP_WIFI" class="row">
|
|
||||||
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">IP</label><br>
|
|
||||||
<select id='r_ip' name="IP" class="selectpicker show-tick" data-width="fit" data-style="btn-primary">
|
|
||||||
<optgroup label="IP's" id="ipGroup">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-2 col-centered">
|
|
||||||
<label class="control-label">Puerto</label></br>
|
|
||||||
<input type="text" class="btn btn-primary" id="r_puerto" placeholder="Puerto" maxlength="4" size="5" value="5000">
|
|
||||||
</div>
|
|
||||||
<div class="col-4 col-centered">
|
|
||||||
<label class="control-label">Path</label></br>
|
|
||||||
<input type="text" class="btn btn-primary" id="r_path" placeholder="Puerto" maxlength="15" size="25" value="/datos">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="hr-suave">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 col-centered">
|
|
||||||
<button type="button" id="botonguardar" class="btn btn-sm btn-success" onclick="GuardarConf('conf')" role="button">Guardar</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@ -4,7 +4,7 @@
|
|||||||
<button id="boton_volver" class="btn btn-sm btn-success" onclick="Volver()" role="button">Volver</button>
|
<button id="boton_volver" class="btn btn-sm btn-success" onclick="Volver()" role="button">Volver</button>
|
||||||
<br><br>
|
<br><br>
|
||||||
<div id="actualizando" style="display:block">
|
<div id="actualizando" style="display:block">
|
||||||
<br><br> <img src='./img/animadas/cargando2.gif' width='40' height='40' /> <br> <small>Cargando Gráfico...</small>
|
<br><br> <img src='gui_common/img/animadas/cargando2.gif' width='40' height='40' /> <br> <small>Cargando Gráfico...</small>
|
||||||
</div>
|
</div>
|
||||||
<div id="inicio_estadisticas">
|
<div id="inicio_estadisticas">
|
||||||
<canvas id="graph_inicio" style="width:100%; height:400px; max-width:80vw; max-height:50vh;"></canvas>
|
<canvas id="graph_inicio" style="width:100%; height:400px; max-width:80vw; max-height:50vh;"></canvas>
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
<canvas style="margin-right: auto;margin-left: auto;" id="gviento_vel" width="260" height="260"></canvas>
|
<canvas style="margin-right: auto;margin-left: auto;" id="gviento_vel" width="260" height="260"></canvas>
|
||||||
<div class="d-block d-md-none d-lg-block zoom"><b>Viento Velocidad</b>
|
<div class="d-block d-md-none d-lg-block zoom"><b>Viento Velocidad</b>
|
||||||
<h1>
|
<h1>
|
||||||
<span id='viento_vel_rafag' class="badge badge-danger" data-toggle="tooltip" data-placement="left" title="Viento Vel. Rafaga">-</span>
|
<span id='viento_vel_rafag' class="badge text-bg-danger" data-bs-toggle="tooltip" data-bs-placement="left" title="Viento Vel. Rafaga">-</span>
|
||||||
<span id='viento_vel' class="badge badge-info" data-toggle="tooltip" data-placement="right" title="Viento Velocidad">-</span>
|
<span id='viento_vel' class="badge badge-info" data-bs-toggle="tooltip" data-bs-placement="right" title="Viento Velocidad">-</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -13,14 +13,14 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-centered align-self-center ">
|
<div class="col-12 col-centered align-self-center ">
|
||||||
<h1>Datos del Exterior<h1><button class="btn btn-sm btn-success" onclick="VerHistoricoT(0)" role="button">Ver Histórico</button> <br>
|
<h1>Datos del Exterior<h1><button class="btn btn-sm btn-success" onclick="VerHistoricoT(0)" role="button">Ver Histórico</button> <br>
|
||||||
<h2 id='escala_vientos' data-toggle="tooltip" data-placement="right" title="Escala de Beaufort">-</h2><br>
|
<h2 id='escala_vientos' data-bs-toggle="tooltip" data-bs-placement="right" title="Escala de Beaufort">-</h2><br>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 col-centered align-self-center ">
|
<div class="col-6 col-centered align-self-center ">
|
||||||
<div class="short-div col-centered ">
|
<div class="short-div col-centered ">
|
||||||
<h3 align="center"><img src="gui_common/img/clima/temperatura.webp" width="13" height="13"> Temperatura</h3>
|
<h3 align="center"><img src="gui_common/img/clima/temperatura.webp" width="13" height="13"> Temperatura</h3>
|
||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h1><span id='temp_ext' class="badge badge-success">- </span></h1>
|
<h1><span id='temp_ext' class="badge text-bg-success">- </span></h1>
|
||||||
<h4><span id='temp_ext_max' class="badge badge-danger" title="Maxíma Diaria">-</span>
|
<h4><span id='temp_ext_max' class="badge text-bg-danger" title="Maxíma Diaria">-</span>
|
||||||
<span id='temp_ext_min' class="badge badge-info" title="Mínima Diaria">-</span></h4>
|
<span id='temp_ext_min' class="badge badge-info" title="Mínima Diaria">-</span></h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
<h4 align="center"><img src="gui_common/img/clima/luxer.webp" width="13" height="13"> Iluminancia </h4>
|
<h4 align="center"><img src="gui_common/img/clima/luxer.webp" width="13" height="13"> Iluminancia </h4>
|
||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h1><span id='luxer_ext' class="badge badge-primary">-</span></h1>
|
<h1><span id='luxer_ext' class="badge badge-primary">-</span></h1>
|
||||||
<h4><span id='luxer_ext_max' class="badge badge-danger" title="Maxíma Diaria">-</span>
|
<h4><span id='luxer_ext_max' class="badge text-bg-danger" title="Maxíma Diaria">-</span>
|
||||||
<span id='luxer_ext_min' class="badge badge-info" title="Mínima Diaria">-</span></h4>
|
<span id='luxer_ext_min' class="badge badge-info" title="Mínima Diaria">-</span></h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -37,9 +37,9 @@
|
|||||||
<div class="short-div col-centered">
|
<div class="short-div col-centered">
|
||||||
<h3 align="center"><img src="gui_common/img/clima/humedad.webp" width="13" height="13">Humedad</h3>
|
<h3 align="center"><img src="gui_common/img/clima/humedad.webp" width="13" height="13">Humedad</h3>
|
||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h1><span id='hum_ext' class="badge badge-success">-</span></h1>
|
<h1><span id='hum_ext' class="badge text-bg-success">-</span></h1>
|
||||||
<h4>
|
<h4>
|
||||||
<span id='hum_ext_max' class="badge badge-danger" title="Maxíma Diaria">-</span>
|
<span id='hum_ext_max' class="badge text-bg-danger" title="Maxíma Diaria">-</span>
|
||||||
<span id='hum_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
<span id='hum_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h1><span id='punto_ext' class="badge badge-primary">-</span></h1>
|
<h1><span id='punto_ext' class="badge badge-primary">-</span></h1>
|
||||||
<h4>
|
<h4>
|
||||||
<span id='punto_ext_max' class="badge badge-danger" title="Maxíma Diaria">-</span>
|
<span id='punto_ext_max' class="badge text-bg-danger" title="Maxíma Diaria">-</span>
|
||||||
<span id='punto_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
<span id='punto_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
<div class="d-block d-md-none d-lg-block zoom">
|
<div class="d-block d-md-none d-lg-block zoom">
|
||||||
<b>Viento Dirección</b>
|
<b>Viento Dirección</b>
|
||||||
<h1>
|
<h1>
|
||||||
<span id='viento_dir' class="badge badge-danger" title="Dirección Del Viento">-</span>
|
<span id='viento_dir' class="badge text-bg-danger" title="Dirección Del Viento">-</span>
|
||||||
<span id='viento_dir_nom' class="badge badge-info" title="Nombre de la Dirección">-</span>
|
<span id='viento_dir_nom' class="badge badge-info" title="Nombre de la Dirección">-</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@ -75,8 +75,8 @@
|
|||||||
<h6> Rafagas / Vientos</h6>
|
<h6> Rafagas / Vientos</h6>
|
||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h2>
|
<h2>
|
||||||
<span id='viento_rafag_max' class="badge badge-danger" title="Maxíma Rafaga Diaria">-</span> <b>/</b>
|
<span id='viento_rafag_max' class="badge text-bg-danger" title="Maxíma Rafaga Diaria">-</span> <b>/</b>
|
||||||
<span id='viento_vel_max' class="badge badge-danger" title="Maxímo Viento Diario">-</span>
|
<span id='viento_vel_max' class="badge text-bg-danger" title="Maxímo Viento Diario">-</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -85,7 +85,7 @@
|
|||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h1><span id='rayos_ext' class="badge badge-primary">-</span></h1>
|
<h1><span id='rayos_ext' class="badge badge-primary">-</span></h1>
|
||||||
<h4>
|
<h4>
|
||||||
<span id='rayos_ext_max' class="badge badge-danger" title="Maxíma Diaria">-</span>
|
<span id='rayos_ext_max' class="badge text-bg-danger" title="Maxíma Diaria">-</span>
|
||||||
<span id='rayos_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
<span id='rayos_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h1><span id='presionr_ext' class="badge badge-primary">-</span></h1>
|
<h1><span id='presionr_ext' class="badge badge-primary">-</span></h1>
|
||||||
<h4>
|
<h4>
|
||||||
<span id='presionr_ext_max' class="badge badge-danger" title="Maxíma Diaria">-</span>
|
<span id='presionr_ext_max' class="badge text-bg-danger" title="Maxíma Diaria">-</span>
|
||||||
<span id='presionr_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
<span id='presionr_ext_min' class="badge badge-info" title="Mínima Diaria">-</span>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
@ -105,7 +105,7 @@
|
|||||||
<h6>Dirección / Nombre</h6>
|
<h6>Dirección / Nombre</h6>
|
||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
<h2>
|
<h2>
|
||||||
<span id='viento_dir_prom' class="badge badge-danger" title="Dirección Promedio del Dia">-</span> /
|
<span id='viento_dir_prom' class="badge text-bg-danger" title="Dirección Promedio del Dia">-</span> /
|
||||||
<span id='viento_dir_nom_prom' class="badge badge-info" title="Nombre">-</span>
|
<span id='viento_dir_nom_prom' class="badge badge-info" title="Nombre">-</span>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,15 +9,15 @@
|
|||||||
<h5><img src="gui_common/img/informacion.png" id="img_nombre" height="25" width="25"> Nombre: <span class="badge badge-info" style="font-size:small" id="inombre">-</span></h5>
|
<h5><img src="gui_common/img/informacion.png" id="img_nombre" height="25" width="25"> Nombre: <span class="badge badge-info" style="font-size:small" id="inombre">-</span></h5>
|
||||||
<h5><img src="gui_common/img/informacion.png" id="img_so" height="25" width="25"> S.O: <span class="badge badge-info" style="font-size:small" id="iso">-</span></h5>
|
<h5><img src="gui_common/img/informacion.png" id="img_so" height="25" width="25"> S.O: <span class="badge badge-info" style="font-size:small" id="iso">-</span></h5>
|
||||||
<h5><img src="gui_common/img/informacion.png" id="img_modo" height="25" width="25"> Modo: <span class="badge badge-info" style="font-size:small" id="imodo">-</span></h5>
|
<h5><img src="gui_common/img/informacion.png" id="img_modo" height="25" width="25"> Modo: <span class="badge badge-info" style="font-size:small" id="imodo">-</span></h5>
|
||||||
<h5><img src="gui_common/img/informacion.png" height="25" width="25"> Node.js: <span id='versiones' class="badge badge-info" style="font-size:small" data-toggle="tooltip" data-placement="right" data-html="true" title="-"><span id="nwjs_v">-</span></h5>
|
<h5><img src="gui_common/img/informacion.png" height="25" width="25"> Node.js: <span id='versiones' class="badge badge-info" style="font-size:small" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true" title="-"><span id="nwjs_v">-</span></h5>
|
||||||
</td>
|
</td>
|
||||||
<td WIDTH = "1%" rowspan="2"></td>
|
<td WIDTH = "1%" rowspan="2"></td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<h5><b>Tanques del Sistema</b></h5>
|
<h5><b>Tanques del Sistema</b></h5>
|
||||||
<h5><img src="gui_common/img/archive.webp" height="25" width="25"><b>Diario: </b> <span class="badge badge-info" style="font-size:small" id="tamanio_diario">-</span> </h5>
|
<h5><img src="gui_common/img/archive.webp" height="25" width="25"><b>Diario: </b> <span class="badge badge-info" style="font-size:small" id="tamanio_diario">-</span> </h5>
|
||||||
<h5><img src="gui_common/img/archive.webp" height="25" width="25"><b>Pendiente:</b> <span class="badge badge-info" style="font-size:small" id="tamanio_pendiente">-</span> <button type="button" class="btn btn-sm btn-warning" onclick="PurgarP()" data-toggle="tooltip" data-placement="right" title="Si presiona este botón de purgar, usted vaciará el archivo que almacena los registros pendientes de enviar, esto solo aplica para registros pendientes de enviar de redes de tipo 'emacenter'.">Purgar</button ></h5>
|
<h5><img src="gui_common/img/archive.webp" height="25" width="25"><b>Pendiente:</b> <span class="badge badge-info" style="font-size:small" id="tamanio_pendiente">-</span> <button type="button" class="btn btn-sm btn-warning" onclick="PurgarP()" data-bs-toggle="tooltip" data-bs-placement="right" title="Si presiona este botón de purgar, usted vaciará el archivo que almacena los registros pendientes de enviar, esto solo aplica para registros pendientes de enviar de redes de tipo 'emacenter'.">Purgar</button ></h5>
|
||||||
<h5><img src="gui_common/img/archive.webp" height="25" width="25"><b>Debug: </b> <span class="badge badge-info" style="font-size:small" id="tamanio_debug">-</span> <button type="button" class="btn btn-sm btn-warning" onclick="PurgarD()" data-toggle="tooltip" data-placement="right" title="Si presiona este botón de purgar, usted vaciará el archivo que almacena los registros de logs del sistema." >Purgar</button > </h5>
|
<h5><img src="gui_common/img/archive.webp" height="25" width="25"><b>Debug: </b> <span class="badge badge-info" style="font-size:small" id="tamanio_debug">-</span> <button type="button" class="btn btn-sm btn-warning" onclick="PurgarD()" data-bs-toggle="tooltip" data-bs-placement="right" title="Si presiona este botón de purgar, usted vaciará el archivo que almacena los registros de logs del sistema." >Purgar</button > </h5>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@ -36,10 +36,10 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<h5><b>Información de Ejecución</b> </h5>
|
<h5><b>Información de Ejecución</b> </h5>
|
||||||
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>Audio: </b> <span class="badge badge-info" id="audiomenu" data-toggle="tooltip" data-placement="right" title="Indica si esta activado el audio" style="font-size:small">-</span> </h5>
|
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>Audio: </b> <span class="badge badge-info" id="audiomenu" data-bs-toggle="tooltip" data-bs-placement="right" title="Indica si esta activado el audio" style="font-size:small">-</span> </h5>
|
||||||
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>AutoInicio: </b> <span class="badge badge-info" id="autoactivado" data-toggle="tooltip" data-placement="right" title="Indica si el inicio automatico esta activado." style="font-size:small">-</span> </h5>
|
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>AutoInicio: </b> <span class="badge badge-info" id="autoactivado" data-bs-toggle="tooltip" data-bs-placement="right" title="Indica si el inicio automatico esta activado." style="font-size:small">-</span> </h5>
|
||||||
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>PID: </b> <span class="badge badge-info" id="node_pid" data-toggle="tooltip" data-placement="right" title="Numero del Identificado de Proceso (PID) de la aplicación Ema Libre." style="font-size:small">-</span> </h5>
|
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>PID: </b> <span class="badge badge-info" id="node_pid" data-bs-toggle="tooltip" data-bs-placement="right" title="Numero del Identificado de Proceso (PID) de la aplicación Ema Libre." style="font-size:small">-</span> </h5>
|
||||||
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>PPID: </b> <span class="badge badge-info" id="node_ppid" data-toggle="tooltip" data-placement="right" title="Numero del Identificado de Proceso Padre (PPID) de la aplicación Ema Libre." style="font-size:small">-</span> </h5>
|
<h5><img src="gui_common/img/sistema.webp" height="25" width="25"><b>PPID: </b> <span class="badge badge-info" id="node_ppid" data-bs-toggle="tooltip" data-bs-placement="right" title="Numero del Identificado de Proceso Padre (PPID) de la aplicación Ema Libre." style="font-size:small">-</span> </h5>
|
||||||
</td>
|
</td>
|
||||||
<td style="display:table-cell; vertical-align:middle; text-align:center">
|
<td style="display:table-cell; vertical-align:middle; text-align:center">
|
||||||
<button id="botondetener" class="btn btn-lg btn-danger" onclick="DETENER()" role="button">Detener</button >
|
<button id="botondetener" class="btn btn-lg btn-danger" onclick="DETENER()" role="button">Detener</button >
|
||||||
@ -47,8 +47,3 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
|
||||||
$(document).ready(function(){
|
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|||||||
@ -11,10 +11,10 @@
|
|||||||
<div class="col-6 col-centered">
|
<div class="col-6 col-centered">
|
||||||
<div class="short-div col-centered">
|
<div class="short-div col-centered">
|
||||||
<h1>Temperatura</h1>
|
<h1>Temperatura</h1>
|
||||||
<h1 class="zoom"><span id='temp_int' class="badge badge-success">-</span></h1>
|
<h1 class="zoom"><span id='temp_int' class="badge text-bg-success">-</span></h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="short-div col-centered"><br><br><b>MAX</b>
|
<div class="short-div col-centered"><br><br><b>MAX</b>
|
||||||
<h2 class="zoom"><span id='temp_int_max' class="badge badge-danger" title="Temperatura Maxíma Diaria">-</span></h2>
|
<h2 class="zoom"><span id='temp_int_max' class="badge text-bg-danger" title="Temperatura Maxíma Diaria">-</span></h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="short-div col-centered"><br><b>MIN</b>
|
<div class="short-div col-centered"><br><b>MIN</b>
|
||||||
<h2 class="zoom"><span id='temp_int_min' class="badge badge-info" title="Temperatura Mínima Diaria">-</span></h2>
|
<h2 class="zoom"><span id='temp_int_min' class="badge badge-info" title="Temperatura Mínima Diaria">-</span></h2>
|
||||||
@ -23,10 +23,10 @@
|
|||||||
<div class="col-6 col-centered">
|
<div class="col-6 col-centered">
|
||||||
<div class="short-div col-centered">
|
<div class="short-div col-centered">
|
||||||
<h1>Humedad</h1>
|
<h1>Humedad</h1>
|
||||||
<h1 class="zoom"><span id='hum_int' class="badge badge-success">-</span></h1>
|
<h1 class="zoom"><span id='hum_int' class="badge text-bg-success">-</span></h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="short-div col-centered"><br><br><b>MAX</b>
|
<div class="short-div col-centered"><br><br><b>MAX</b>
|
||||||
<h2 class="zoom"><span id='hum_int_max' class="badge badge-danger" title="Humedad Maxíma Diaria">-</span></h2>
|
<h2 class="zoom"><span id='hum_int_max' class="badge text-bg-danger" title="Humedad Maxíma Diaria">-</span></h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="short-div col-centered"><br><b>MIN</b>
|
<div class="short-div col-centered"><br><b>MIN</b>
|
||||||
<h2 class="zoom"><span id='hum_int_min' class="badge badge-info" title="Humedad Mínima Diaria">-</span></h2>
|
<h2 class="zoom"><span id='hum_int_min' class="badge badge-info" title="Humedad Mínima Diaria">-</span></h2>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<div class="col-12"><h2>Tipo de Red</h2></div>
|
<div class="col-12"><h2>Tipo de Red</h2></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row ">
|
<div class="row ">
|
||||||
<select id='Tipo_Red' name="Tipo_Red" onchange="MenuSelectRed();" class="form-control form-control-sm" data-width="fit" data-style="btn-primary">
|
<select id='Tipo_Red' name="Tipo_Red" onchange="MenuSelectRed();" class="form-control form-control-sm">
|
||||||
<optgroup label='Red EMA Libre Center'>
|
<optgroup label='Red EMA Libre Center'>
|
||||||
<option value='emacentergugler'>EMA Libre Center - Gugler</option>
|
<option value='emacentergugler'>EMA Libre Center - Gugler</option>
|
||||||
<option value='emacenter'>EMA Libre Center - Particular</option>
|
<option value='emacenter'>EMA Libre Center - Particular</option>
|
||||||
@ -25,10 +25,10 @@
|
|||||||
<div class="col-12"><br><h2>Configuracion de la Red</h2></div>
|
<div class="col-12"><br><h2>Configuracion de la Red</h2></div>
|
||||||
</div>
|
</div>
|
||||||
<form class="needs-validation" novalidate>
|
<form class="needs-validation" novalidate>
|
||||||
<div class="form-row ">
|
<div class="row g-2 ">
|
||||||
<div class="col-12"> <label class="control-label">Nombre</label><br><input type="text" class="form-control btn btn-primary" id="Nombre" placeholder="Nombre" maxlength="15" size="18" ></div>
|
<div class="col-12"> <label class="control-label">Nombre</label><br><input type="text" class="form-control btn btn-primary" id="Nombre" placeholder="Nombre" maxlength="15" size="18" ></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="row g-2">
|
||||||
<div class="col-6 .d-none" id="EmaConfAlta2" style="display: none;"> <label class="control-label">Usuario </label><br><input type="text" class="form-control btn btn-primary" id="Usuario" placeholder="Usuario" maxlength="130" size="20" required><br></div>
|
<div class="col-6 .d-none" id="EmaConfAlta2" style="display: none;"> <label class="control-label">Usuario </label><br><input type="text" class="form-control btn btn-primary" id="Usuario" placeholder="Usuario" maxlength="130" size="20" required><br></div>
|
||||||
<div class="col-6 .d-none" id="EmaConfAlta3" style="display: none;"> <label class="control-label">Contraseña </label><br><input type="text" class="form-control btn btn-primary" id="Password" placeholder="Password" maxlength="40" size="20" required></div>
|
<div class="col-6 .d-none" id="EmaConfAlta3" style="display: none;"> <label class="control-label">Contraseña </label><br><input type="text" class="form-control btn btn-primary" id="Password" placeholder="Password" maxlength="40" size="20" required></div>
|
||||||
<div class="col-8 .d-none" id="EmaConfAlta4" style="display: none;"> <label class="control-label">Servidor</label><br><input type="text" class="form-control btn btn-primary" id="Servidor" placeholder="Servidor" maxlength="50" size="30" required></div>
|
<div class="col-8 .d-none" id="EmaConfAlta4" style="display: none;"> <label class="control-label">Servidor</label><br><input type="text" class="form-control btn btn-primary" id="Servidor" placeholder="Servidor" maxlength="50" size="30" required></div>
|
||||||
|
|||||||
26814
src/logs/debug.log
26814
src/logs/debug.log
File diff suppressed because it is too large
Load Diff
701
src/package-lock.json
generated
701
src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -2,10 +2,10 @@
|
|||||||
"name": "emalibre",
|
"name": "emalibre",
|
||||||
"description": "EMA Libre Cliente (Carpincho)",
|
"description": "EMA Libre Cliente (Carpincho)",
|
||||||
"main": "gui/controlador/inicio.js",
|
"main": "gui/controlador/inicio.js",
|
||||||
"version": "1.36.0",
|
"version": "2.0.0",
|
||||||
"author": "Laboratorio de Investigacion Gugler",
|
"author": "Laboratorio de Investigacion Gugler",
|
||||||
"homepage": "https://www.gugler.com.ar",
|
"homepage": "https://www.gugler.com.ar",
|
||||||
"chromium-args": "--enable-speech-dispatcher --disable-logging --disable-gpu --disable-gpu-compositing --no-sandbox --ignore-gpu-blacklist --disable-dev-shm-usage --disable-accelerated-2d-canvas --disable-accelerated-compositing --disable-gpu-rasterization",
|
"chromium-args": "--enable-speech-dispatcher --disable-gpu --disable-gpu-compositing --no-sandbox --ignore-gpu-blacklist --disable-dev-shm-usage --disable-accelerated-2d-canvas --disable-accelerated-compositing --disable-gpu-rasterization",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ema",
|
"ema",
|
||||||
"estacion",
|
"estacion",
|
||||||
@ -32,29 +32,35 @@
|
|||||||
"url": "https://ema.gugler.com.ar"
|
"url": "https://ema.gugler.com.ar"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"desktop": "nw . --disable-logging",
|
"desktop": "node tools/nw.cjs start",
|
||||||
"web": "node gui_web/express.js iniciar",
|
"web": "node gui_web/express.js iniciar",
|
||||||
"reporte": "node core/reporte.js",
|
"reporte": "node core/reporte.js",
|
||||||
"cleanBuild": "nw-gyp clean --directory=node_modules/node-hid",
|
"cleanBuild": "rm -rf node_modules/node-hid/build",
|
||||||
"postLINUX": "nw-gyp rebuild --target=0.94.0 --verbose --arch=x64 --directory=node_modules/node-hid",
|
"postLINUX": "node tools/nw.cjs rebuild",
|
||||||
"postWIN": "nw-gyp rebuild --target=0.94.0 --verbose --arch=x64 --directory=node_modules/node-hid",
|
"postWIN": "node tools/nw.cjs rebuild",
|
||||||
"postARM": "nw-gyp rebuild --target=0.28.3 --verbose --arch=arm --directory=node_modules/node-hid"
|
"postARM": "node tools/nw.cjs rebuild-arm",
|
||||||
|
"desktop:dev": "node tools/nw.cjs dev",
|
||||||
|
"test:ui": "node ../test/ui-smoke.cjs",
|
||||||
|
"test:config": "node --test ../test/configuracion.test.cjs",
|
||||||
|
"test:startup": "node ../test/ui-startup.cjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "4.6.2",
|
"bootstrap": "^5.3.8",
|
||||||
"bootstrap-select": "1.13.18",
|
"express": "^5.2.1",
|
||||||
"datatables": "1.10.18",
|
|
||||||
"datatables-buttons": "1.0.3",
|
|
||||||
"express": "5.1.0",
|
|
||||||
"forever": "^4.0.3",
|
"forever": "^4.0.3",
|
||||||
"jquery": "3.7.1",
|
"jquery": "^3.7.1",
|
||||||
"node": "^24.11.0",
|
"node-hid": "^3.4.0",
|
||||||
"node-hid": "^2.2.0",
|
"nodemailer": "^10.0.11",
|
||||||
"nodemailer": "7.0.5",
|
|
||||||
"notify-js-lib": "1.0.0",
|
"notify-js-lib": "1.0.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"popper.js": "1.16.1",
|
|
||||||
"targz": "1.0.1",
|
"targz": "1.0.1",
|
||||||
"terminal-kit": "3.1.2"
|
"terminal-kit": "^3.1.4",
|
||||||
|
"datatables.net": "1.13.11",
|
||||||
|
"datatables.net-bs5": "1.13.11",
|
||||||
|
"datatables.net-buttons": "2.4.3",
|
||||||
|
"datatables.net-buttons-bs5": "2.4.3"
|
||||||
|
},
|
||||||
|
"allowScripts": {
|
||||||
|
"node-hid@3.4.0": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/runtime.json
Normal file
9
src/runtime.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"nw": "0.117.0",
|
||||||
|
"flavor": "sdk",
|
||||||
|
"targets": {
|
||||||
|
"linux": ["x64"],
|
||||||
|
"win32": ["x64"],
|
||||||
|
"darwin": ["x64", "arm64"]
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/tools/nw.cjs
Normal file
25
src/tools/nw.cjs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const path = require('node:path');
|
||||||
|
const {spawnSync} = require('node:child_process');
|
||||||
|
const runtime = require('../runtime.json');
|
||||||
|
const app = path.resolve(__dirname, '..');
|
||||||
|
const action = process.argv[2] || 'start';
|
||||||
|
if (action === 'version') {console.log(runtime.nw); process.exit(0);}
|
||||||
|
if (!runtime.targets[process.platform]?.includes(process.arch) || action === 'rebuild-arm') {
|
||||||
|
console.error('No hay un runtime NW.js validado para esta plataforma. En Linux ARM usá el modo web con Node.js moderno.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const npm = process.env.npm_execpath;
|
||||||
|
function runNpm(args) {
|
||||||
|
return npm ? spawnSync(process.execPath, [npm, ...args], {cwd:app, stdio:'inherit'}) : spawnSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, {cwd:app, stdio:'inherit', shell:process.platform === 'win32'});
|
||||||
|
}
|
||||||
|
let result;
|
||||||
|
if (action === 'rebuild') {
|
||||||
|
result = runNpm(['rebuild','node-hid',`--target=${runtime.nw}`,'--disturl=https://dl.nwjs.io/']);
|
||||||
|
} else if (['start','dev'].includes(action)) {
|
||||||
|
const args = [app, action === 'dev' ? '--enable-logging=stderr' : '--disable-logging'];
|
||||||
|
result = process.env.NW_BINARY ? spawnSync(process.env.NW_BINARY,args,{cwd:app,stdio:'inherit'}) : runNpm(['exec','--yes',`--package=nw@${runtime.nw}-${runtime.flavor}`,'--','nw',...args]);
|
||||||
|
} else {
|
||||||
|
console.error('Acción desconocida. Usá start, dev, rebuild o version.'); process.exit(1);
|
||||||
|
}
|
||||||
|
if (result.error) console.error(result.error.message);
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
84
test/configuracion.test.cjs
Normal file
84
test/configuracion.test.cjs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
const {test} = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const fs = require('node:fs/promises');
|
||||||
|
const path = require('node:path');
|
||||||
|
const os = require('node:os');
|
||||||
|
const vm = require('node:vm');
|
||||||
|
const model = require('../src/gui_common/js/configuracion-modelo.js');
|
||||||
|
const {guardarConfiguracion} = require('../src/core/configuracion-store.js');
|
||||||
|
const {registrarConfiguracion} = require('../src/gui_web/configuracion-api.js');
|
||||||
|
const express = require('../src/node_modules/express');
|
||||||
|
const fixture = require('./fixtures/configuracion.cjs');
|
||||||
|
|
||||||
|
test('el formulario conserva propiedades ajenas y no modifica el objeto original', () => {
|
||||||
|
const old = fixture(), fields = model.read(old);
|
||||||
|
fields.NombreEstacion = 'Nuevo'; fields.inicio_auto = 'Activado';
|
||||||
|
const next = model.build(old, fields);
|
||||||
|
assert.equal(old.ConfGeneral.NombreEstacion, 'Estación prueba');
|
||||||
|
assert.equal(next.ConfGeneral.inicio_automatico, true);
|
||||||
|
assert.deepEqual(next.Redes, old.Redes);
|
||||||
|
assert.equal(next.ConfGeneral.conservar, old.ConfGeneral.conservar);
|
||||||
|
assert.deepEqual(model.validate(fields), {});
|
||||||
|
});
|
||||||
|
test('validación condicional de visor, IP y SMTP', () => {
|
||||||
|
const fields = model.read(fixture());
|
||||||
|
fields.Modo = 'Visor'; assert(model.validate(fields).Llave_R);
|
||||||
|
fields.Llave_R = 'llave'; assert.deepEqual(model.validate(fields), {});
|
||||||
|
fields.Modo = 'Recolector_IP'; fields.r_puerto = '65536'; fields.r_path = 'datos';
|
||||||
|
assert(model.validate(fields).r_puerto); assert(model.validate(fields).r_path);
|
||||||
|
fields.r_puerto = '65535'; fields.r_path = '/datos'; assert.deepEqual(model.validate(fields), {});
|
||||||
|
fields.Tipo_SMTP = 'Manual'; fields.Usuario_SMTP = 'invalido';
|
||||||
|
const errors = model.validate(fields);
|
||||||
|
assert(errors.Usuario_SMTP && errors.Contrasenia_SMTP && errors.Server_SMTP && errors.Email_receptor);
|
||||||
|
});
|
||||||
|
test('guardar y volver a leer, rechazo sin alterar el archivo y limpieza de temporales', async t => {
|
||||||
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'carpincho-config-'));
|
||||||
|
t.after(() => fs.rm(dir, {recursive: true, force: true}));
|
||||||
|
const file = path.join(dir, 'ConfiguracionGeneral.js');
|
||||||
|
const config = fixture(); config.ConfGeneral.NombreEstacion = 'Prueba " especial';
|
||||||
|
await guardarConfiguracion(config, file);
|
||||||
|
const previous = await fs.readFile(file, 'utf8');
|
||||||
|
const sandbox = {module: {exports: {}}}; vm.runInNewContext(previous, sandbox);
|
||||||
|
assert.deepEqual(JSON.parse(JSON.stringify(sandbox.module.exports)), config);
|
||||||
|
config.ConfGeneral.debugTamanio = -1;
|
||||||
|
await assert.rejects(guardarConfiguracion(config, file));
|
||||||
|
assert.equal(await fs.readFile(file, 'utf8'), previous);
|
||||||
|
await assert.rejects(guardarConfiguracion(fixture(), dir));
|
||||||
|
assert.deepEqual(await fs.readdir(dir), ['ConfiguracionGeneral.js']);
|
||||||
|
});
|
||||||
|
test('HTTP espera la escritura, informa rechazos y permite reintentar', async t => {
|
||||||
|
const app = express(); app.use(express.json());
|
||||||
|
let release, fail = false, reload = 0;
|
||||||
|
registrarConfiguracion(app, {guardar: async config => {
|
||||||
|
assert(config.ConfGeneral);
|
||||||
|
if (fail) throw new Error('disco no disponible');
|
||||||
|
await new Promise(resolve => {release = resolve;});
|
||||||
|
}, reconfigurar: () => {reload++;}});
|
||||||
|
const server = await new Promise(resolve => {const s = app.listen(0,'127.0.0.1',()=>resolve(s));});
|
||||||
|
t.after(() => server.close());
|
||||||
|
const url = `http://127.0.0.1:${server.address().port}/GuardarConf`;
|
||||||
|
const request = () => fetch(url,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({configuracion:fixture()})});
|
||||||
|
let replied = false;
|
||||||
|
const pending = request().then(response => {replied = true; return response.json();});
|
||||||
|
while (!release) await new Promise(resolve => setTimeout(resolve, 5));
|
||||||
|
assert.equal(replied, false); assert.equal(reload, 0);
|
||||||
|
release(); assert.deepEqual(await pending,{ok:true}); assert.equal(reload,1);
|
||||||
|
fail = true; const failed = await request(); assert.equal(failed.status,500); assert.equal((await failed.json()).ok,false);
|
||||||
|
fail = false; release = null; const retry = request();
|
||||||
|
while (!release) await new Promise(resolve => setTimeout(resolve,5));
|
||||||
|
release(); assert.equal((await (await retry).json()).ok,true);
|
||||||
|
});
|
||||||
|
test('la reconfiguración actualiza el objeto compartido y los parámetros del recolector', async () => {
|
||||||
|
const source = await fs.readFile(path.join(__dirname,'../src/core/ema.js'),'utf8');
|
||||||
|
const start = source.indexOf(' Reconfigurar: function');
|
||||||
|
const end = source.indexOf(' Iniciar: function',start);
|
||||||
|
const current = fixture();
|
||||||
|
const context = {configGeneralEMA:current, APP:{Configuracion:{},RegistrarLog() {}},recolector:{conf:{}},Correo:{EnviarEmail(){throw new Error('Unexpected email');}}};
|
||||||
|
vm.runInNewContext('handler = ({'+source.slice(start,end)+'}).Reconfigurar;',context);
|
||||||
|
const next = fixture(); next.ConfGeneral.Tiempo_de_Recoleccion=30;next.ConfGeneral.UTC=2;next.ConfGeneral.Modo='Recolector_IP';
|
||||||
|
context.handler(next);
|
||||||
|
assert.equal(current.ConfGeneral.Tiempo_de_Recoleccion,30);
|
||||||
|
assert.equal(context.APP.Configuracion.TiempoContinuo,30);
|
||||||
|
assert.equal(context.APP.Configuracion.Modo,'Recolector_IP');
|
||||||
|
assert.equal(context.APP.Configuracion.utc,2);
|
||||||
|
});
|
||||||
9
test/fixtures/configuracion.cjs
vendored
Normal file
9
test/fixtures/configuracion.cjs
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports = () => ({
|
||||||
|
ConfGeneral: {
|
||||||
|
NombreEstacion: 'Estación prueba', Modo: 'Recolector_USB', Tiempo_de_Recoleccion: 60,
|
||||||
|
debug: 1, debugTamanio: 20, UTC: -3, SistemaMetrico: 'SI', IP: '127.0.0.1', Puerto: '5000', Ruta: '/datos', Llave_R: '',
|
||||||
|
inicio_automatico: false, notificar_cambios: false, Audio: false, audioVoces: '', conservar: 'propiedad ajena al formulario'
|
||||||
|
},
|
||||||
|
ConfEmail: {Servicio: 'Deshabilitado', ActivarCorreos: false, Usuario: '', Password: '', Server: '', Puerto: '587', ReceptorEmail: ''},
|
||||||
|
Redes: [{Nombre: 'Prueba', Publicar: false}]
|
||||||
|
});
|
||||||
176
test/ui-smoke.cjs
Normal file
176
test/ui-smoke.cjs
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// Run with Node >= 20 and an NW.js SDK binary: node test/ui-smoke.cjs /path/to/nw
|
||||||
|
// Uses production library order, views and static mounts without starting the collector.
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const path = require('node:path');
|
||||||
|
const os = require('node:os');
|
||||||
|
const { pathToFileURL } = require('node:url');
|
||||||
|
const { spawn } = require('node:child_process');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const root = path.resolve(__dirname, '..');
|
||||||
|
const src = path.join(root, 'src');
|
||||||
|
const express = require(path.join(src, 'node_modules/express'));
|
||||||
|
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'carpincho-ui-'));
|
||||||
|
const read = name => fs.readFileSync(path.join(src, name), 'utf8');
|
||||||
|
const clean = html => html.replace(/<!--[\s\S]*?-->/g, '');
|
||||||
|
const app = express();
|
||||||
|
app.use(express.json());
|
||||||
|
const testConfigFile = path.join(temp, 'web-config.js');
|
||||||
|
const {guardarConfiguracion} = require('../src/core/configuracion-store.js');
|
||||||
|
require('../src/gui_web/configuracion-api.js').registrarConfiguracion(app, {guardar: config => guardarConfiguracion(config, testConfigFile), reconfigurar() {}});
|
||||||
|
// Read actual mounts so a stale web route also fails this test.
|
||||||
|
const routes = [...read('gui_web/express.js').matchAll(/app.use\('([^']+)', express.static\(__dirname \+ '([^']+)'\)\)/g)];
|
||||||
|
app.use(express.static(path.join(src, 'gui_web')));
|
||||||
|
for (const [, url, dir] of routes) app.use(url, express.static(path.join(src, 'gui_web', dir)));
|
||||||
|
|
||||||
|
async function probe() {
|
||||||
|
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
const check = (value, message) => { if (!value) throw new Error(message); };
|
||||||
|
const tests = [];
|
||||||
|
try {
|
||||||
|
await wait(200);
|
||||||
|
check($.fn.jquery.startsWith('3.'), 'Expected jQuery 3');
|
||||||
|
check(bootstrap.Tooltip.VERSION.startsWith('5.'), 'Expected Bootstrap 5');
|
||||||
|
for (const tab of document.querySelectorAll('[data-bs-toggle="tab"]')) {
|
||||||
|
tab.click();
|
||||||
|
await wait(200);
|
||||||
|
check(document.querySelector(tab.dataset.bsTarget)?.classList.contains('active'), 'Tab failed: ' + tab.id);
|
||||||
|
}
|
||||||
|
tests.push('all navigation tabs');
|
||||||
|
$('#settings').html(window.settingsHTML);
|
||||||
|
const fixture = window.configFixture;
|
||||||
|
const interfaces = {eth0: [{family:'IPv4',internal:false,address:'127.0.0.1'}]};
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
ConfigUI.mount(fixture, interfaces, [{name:'Voz de prueba'}]);
|
||||||
|
check(!ConfigUI.dirty(), 'Mount marked the form dirty');
|
||||||
|
check(document.querySelectorAll('#r_ip option').length === 1, 'Duplicated IP options');
|
||||||
|
check(document.querySelectorAll('#vocesAudio option').length === 1, 'Duplicated voice options');
|
||||||
|
}
|
||||||
|
check(!document.querySelector('.bootstrap-select'), 'Plugin is still used');
|
||||||
|
check(document.getElementById('inicio_auto').selectedOptions[0].textContent === 'Desactivado', 'Duplicated selected text');
|
||||||
|
const set = (id, value) => {const e=document.getElementById(id); e.value=value; e.dispatchEvent(new Event('change',{bubbles:true}));};
|
||||||
|
set('Modo','Visor');
|
||||||
|
check(!document.getElementById('LlaveR').hidden && document.getElementById('bloque_por_IP_WIFI').hidden, 'Visor visibility failed');
|
||||||
|
let writes = 0;
|
||||||
|
check(await ConfigUI.save(async () => {writes++;}) === false && writes === 0, 'Invalid visor config saved');
|
||||||
|
check(document.getElementById('Llave_R').getAttribute('aria-invalid') === 'true', 'No field validation message');
|
||||||
|
set('Llave_R','llave-prueba'); set('Modo','Recolector_IP');
|
||||||
|
check(!document.getElementById('bloque_por_IP_WIFI').hidden && document.getElementById('LlaveR').hidden, 'IP visibility failed');
|
||||||
|
set('r_puerto','65536');
|
||||||
|
check(await ConfigUI.save(async () => {writes++;}) === false && writes === 0, 'Invalid port saved');
|
||||||
|
set('r_puerto','5000'); set('Modo','Recolector_USB'); set('NombreEstacion','Nombre nuevo');
|
||||||
|
const confirm = window.confirm;
|
||||||
|
window.confirm = () => false;
|
||||||
|
check(!ConfigUI.canLeave(), 'Unsaved changes did not block navigation');
|
||||||
|
const active = document.querySelector('.nav-link.active');
|
||||||
|
document.getElementById('inicio-tab').click();
|
||||||
|
check(document.querySelector('.nav-link.active') === active, 'Tab changed despite cancel');
|
||||||
|
check(await ConfigUI.save(async () => {throw new Error('Fallo simulado');}) === false, 'Save failure not reported');
|
||||||
|
check(ConfigUI.dirty() && document.getElementById('config-status').textContent.includes('Fallo simulado'), 'Failed save lost dirty state');
|
||||||
|
window.confirm = confirm;
|
||||||
|
const saved = await ConfigUI.save(window.persistConfiguration);
|
||||||
|
check(saved && !ConfigUI.dirty(), 'Successful save did not clear dirty state');
|
||||||
|
const loaded = window.readConfiguration();
|
||||||
|
check(loaded.ConfGeneral.NombreEstacion === 'Nombre nuevo', 'Saved config was not persisted');
|
||||||
|
check(loaded.ConfGeneral.Llave_R === 'llave-prueba', 'Mode switch discarded entered values');
|
||||||
|
ConfigUI.mount(loaded, interfaces, [{name:'Voz de prueba'}]);
|
||||||
|
check(document.getElementById('NombreEstacion').value === 'Nombre nuevo', 'Reload lost saved value');
|
||||||
|
set('NombreEstacion','Cambio descartado'); window.confirm = () => true;
|
||||||
|
check(ConfigUI.canLeave(), 'Discard did not permit navigation'); window.confirm = confirm;
|
||||||
|
ConfigUI.mount(loaded, interfaces, []);
|
||||||
|
tests.push('native selects, repeated mount, mode changes, validation, unsaved changes, failed save, disk save and reload');
|
||||||
|
EstadoUI.render({state:[false,'Sin conexión USB'], mode:'Recolector_USB',record:false,publications:[]});
|
||||||
|
check(document.getElementById('estado-estacion').textContent.includes('Sin conexión USB'), 'Missing connection reason');
|
||||||
|
EstadoUI.render({state:[true,''],record:{fecha:'01/01/2000 00:00:00'},publications:[{red:'Prueba',fecha:'01/01/2000 00:00:00',estado:false,error:'Llave inválida'}]});
|
||||||
|
check(document.getElementById('estado-estacion').textContent.includes('no es reciente'), 'Stale reading not flagged');
|
||||||
|
check(document.getElementById('estado-estacion').textContent.includes('Llave inválida'), 'Publication failure missing');
|
||||||
|
tests.push('separate connection, stale reading and publication error');
|
||||||
|
$('#tip').tooltip('show');
|
||||||
|
check(!!document.querySelector('.tooltip'), 'Tooltip did not open');
|
||||||
|
$('#tip').tooltip('dispose');
|
||||||
|
tests.push('tooltip show/dispose');
|
||||||
|
const table = await new Promise(resolve => {
|
||||||
|
$('#table').DataTable({...TablaUI.options(), pageLength: 1,
|
||||||
|
language: {url: window.languageURL}, initComplete() { resolve(this.api()); }});
|
||||||
|
});
|
||||||
|
check(table.rows().count() === 2, 'Missing table rows');
|
||||||
|
table.search('Beta').draw();
|
||||||
|
check(table.rows({search: 'applied'}).count() === 1, 'Table search failed');
|
||||||
|
check(table.buttons.exportData().body[0][0] === 'Beta', 'CSV/copy data failed');
|
||||||
|
check(document.querySelectorAll('.dt-buttons .btn').length === 2, 'Missing export buttons');
|
||||||
|
check(!document.querySelector('.dt-buttons .btn-default'), 'Legacy button class');
|
||||||
|
check(document.querySelector('.dataTables_info').textContent.includes('Mostrando'), 'Spanish language failed');
|
||||||
|
table.destroy();
|
||||||
|
tests.push('table initialization, filtering, export data, buttons, translation, destroy');
|
||||||
|
check(window.failures.length === 0, window.failures.join('\n'));
|
||||||
|
} catch (error) { window.failures.push(error.stack); }
|
||||||
|
document.getElementById('settings').replaceChildren();
|
||||||
|
require('fs').writeFileSync(window.resultFile, JSON.stringify({versions: process.versions, tests, failures: window.failures}, null, 2));
|
||||||
|
nw.App.quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run(mode, origin) {
|
||||||
|
const folder = path.join(temp, mode);
|
||||||
|
fs.mkdirSync(folder);
|
||||||
|
const html = clean(read(mode + '/index.html'));
|
||||||
|
const base = mode === 'gui' ? pathToFileURL(path.join(src, 'gui/index.html')).href : origin + '/';
|
||||||
|
// Verify every resource in the entry point and dynamic HTML against its document base.
|
||||||
|
const pages = ['index.html', ...(mode === 'gui' ? ['index_actualizar.html'] : []), ...fs.readdirSync(path.join(src, mode, 'view')).filter(n => n.endsWith('.html')).map(n => 'view/' + n)];
|
||||||
|
for (const file of pages) {
|
||||||
|
for (const [, resource] of clean(read(mode + '/' + file)).matchAll(/(?:src|href)=["']([^"']+)["']/g)) {
|
||||||
|
if (/^(#|https?:|mailto:|javascript:)/.test(resource)) continue;
|
||||||
|
const url = new URL(resource, base);
|
||||||
|
if (url.protocol === 'file:') assert(fs.existsSync(url), `${file}: missing ${url}`);
|
||||||
|
else assert((await fetch(url)).ok, `${file}: missing ${url}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const styleURL = new URL(mode === 'gui' ? '../gui_common/css/style.css' : 'gui_common/css/style.css', base);
|
||||||
|
for (const [, resource] of read('gui_common/css/style.css').matchAll(/url\(['"]?([^)'"]+)/g)) {
|
||||||
|
const url = new URL(resource, styleURL);
|
||||||
|
if (url.protocol === 'file:') assert(fs.existsSync(url), 'Missing CSS image: ' + url);
|
||||||
|
else assert((await fetch(url)).ok, 'Missing CSS image: ' + url);
|
||||||
|
}
|
||||||
|
const head = [...html.matchAll(/<link\b[^>]*>|<script\b[^>]*src="([^"]+)"[^>]*><\/script>/g)]
|
||||||
|
.filter(m => !m[1] || !m[1].includes('controlador')).map(m => m[0]).join('\n');
|
||||||
|
const tabs = [...html.matchAll(/<a\b[^>]*data-bs-toggle="tab"[^>]*>[\s\S]*?<\/a>/g)].map(m => m[0]);
|
||||||
|
const panes = tabs.map(tab => {
|
||||||
|
const id = tab.match(/data-bs-target="#([^"]+)"/)[1];
|
||||||
|
assert(html.includes('id="' + id + '"'), 'Missing production tab pane: ' + id);
|
||||||
|
return `<div class="tab-pane ${id === 'inicio' ? 'active show' : ''}" id="${id}"></div>`;
|
||||||
|
}).join('');
|
||||||
|
const resultFile = path.join(folder, 'result.json');
|
||||||
|
const settings = read('gui_common/view/modelo_configuracion.html').replace(/<script\b[\s\S]*?<\/script>/g, '').replace(/\son\w+="[^"]*"/g, '');
|
||||||
|
const language = new URL(mode === 'gui' ? '../gui_common/css/Spanish.json' : 'css/Spanish.json', base).href;
|
||||||
|
const configFile = mode === 'gui' ? path.join(folder,'config.js') : testConfigFile;
|
||||||
|
const fixture = require('./fixtures/configuracion.cjs')();
|
||||||
|
fs.writeFileSync(path.join(folder, 'index.html'), `<!doctype html><meta charset="utf-8"><base href="${base}">
|
||||||
|
<script>window.failures=[];addEventListener('error',e=>failures.push(e.message||'Resource: '+e.target.src),true);addEventListener('unhandledrejection',e=>failures.push(String(e.reason)));</script>
|
||||||
|
${head}<body class="dia"><ul class="nav nav-tabs">${tabs.join('')}</ul>${panes}<section id="estado-estacion" class="estado-estacion"></section><div id="settings"></div>
|
||||||
|
<button id="tip" title="Prueba" class="btn btn-primary">Tooltip</button>
|
||||||
|
<table id="table" class="table table-bordered"><thead><tr><th>Nombre</th></tr></thead><tbody><tr><td>Alpha</td></tr><tr><td>Beta</td></tr></tbody></table>
|
||||||
|
<script>
|
||||||
|
window.configFixture=${JSON.stringify(fixture)};
|
||||||
|
window.persistConfiguration=async draft => {
|
||||||
|
if (${JSON.stringify(mode)} === 'gui') await require(${JSON.stringify(path.join(src,'core/configuracion-store.js'))}).guardarConfiguracion(draft, ${JSON.stringify(configFile)});
|
||||||
|
else {const response=await $.ajax({url:'/GuardarConf',method:'POST',contentType:'application/json',data:JSON.stringify({configuracion:draft})});if(!response.ok)throw new Error('Save failed');}
|
||||||
|
};
|
||||||
|
window.readConfiguration=()=>{const sandbox={module:{exports:{}}};require('vm').runInNewContext(require('fs').readFileSync(${JSON.stringify(configFile)},'utf8'),sandbox);return sandbox.module.exports;};
|
||||||
|
window.settingsHTML=${JSON.stringify(settings)};window.languageURL=${JSON.stringify(language)};window.resultFile=${JSON.stringify(resultFile)};addEventListener('load',${probe.toString()});</script>`);
|
||||||
|
const args = JSON.parse(read('package.json'))['chromium-args'].replace('--disable-logging', '');
|
||||||
|
fs.writeFileSync(path.join(folder, 'package.json'), JSON.stringify({name:'carpincho-ui-test',main:'index.html','chromium-args':args,window:{show:false,width:1200,height:900}}));
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const child = spawn(process.argv[2] || process.env.NW_BINARY || 'nw', [folder, '--user-data-dir=' + path.join(folder, 'profile')], {stdio: ['ignore', 'ignore', 'pipe']});
|
||||||
|
let log = '';
|
||||||
|
child.stderr.on('data', data => {log += data;});
|
||||||
|
const timer = setTimeout(() => {child.kill(); reject(new Error('NW.js timed out: ' + folder));}, 30000);
|
||||||
|
child.on('error', error => {clearTimeout(timer); reject(error);});
|
||||||
|
child.on('exit', () => {clearTimeout(timer); fs.writeFileSync(path.join(folder,'stderr.log'),log); resolve();});
|
||||||
|
});
|
||||||
|
const result = JSON.parse(fs.readFileSync(resultFile));
|
||||||
|
assert.deepEqual(result.failures, [], JSON.stringify(result, null, 2));
|
||||||
|
console.log(`${mode}: ${result.tests.length} checks passed (NW ${result.versions.nw}, Chromium ${result.versions.chromium})`);
|
||||||
|
}
|
||||||
|
(async () => {
|
||||||
|
const server = await new Promise(resolve => {const s=app.listen(0,'127.0.0.1',()=>resolve(s));});
|
||||||
|
try {for (const mode of ['gui','gui_web']) await run(mode, 'http://127.0.0.1:' + server.address().port);}
|
||||||
|
finally {server.close(); console.log('Results: ' + temp);}
|
||||||
|
})().catch(error => {console.error(error);process.exitCode=1;});
|
||||||
34
test/ui-startup.cjs
Normal file
34
test/ui-startup.cjs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Full desktop startup test; uses a temporary copy and disables collection/publication.
|
||||||
|
const fs=require('fs'),path=require('path'),os=require('os'),{spawn}=require('child_process');
|
||||||
|
const root=path.resolve(__dirname,'..');
|
||||||
|
const dir=fs.mkdtempSync(path.join(os.tmpdir(),'carpincho-startup-'));
|
||||||
|
fs.cpSync(path.join(root,'src'),dir,{recursive:true,filter:p=>!p.includes('/node_modules')&&!p.includes('/logs')&&!p.endsWith('/ConfiguracionGeneral.js')});
|
||||||
|
fs.symlinkSync(path.join(root,'src/node_modules'),path.join(dir,'node_modules'),'dir');
|
||||||
|
fs.mkdirSync(path.join(dir,'logs'));
|
||||||
|
for(const f of ['debug.log','TanquePendientes.log','registro_diario.log']) fs.writeFileSync(path.join(dir,'logs',f),f==='debug.log'?'':'[]');
|
||||||
|
const conf=require(path.join(root,'test/fixtures/configuracion.cjs'))();conf.ConfPublicador=[];
|
||||||
|
fs.writeFileSync(path.join(dir,'conf/ConfiguracionGeneral.js'),'module.exports='+JSON.stringify(conf));
|
||||||
|
const probe=`<script>
|
||||||
|
window.startupErrors=[];addEventListener('error',e=>startupErrors.push(e.message||e.target.src),true);addEventListener('unhandledrejection',e=>startupErrors.push(String(e.reason)));
|
||||||
|
addEventListener('load',()=>setTimeout(async()=>{
|
||||||
|
try{
|
||||||
|
await MenuGUI('configuracion');await new Promise(r=>setTimeout(r,700));
|
||||||
|
if(!document.getElementById('config-form'))throw new Error('No configuration form');
|
||||||
|
if(document.getElementById('NombreEstacion').value!=='Estación prueba')throw new Error('Configuration not initialized');
|
||||||
|
document.getElementById('NombreEstacion').value='Prueba arranque';
|
||||||
|
document.getElementById('Tiempo_de_Recoleccion').value='30';
|
||||||
|
const saved=await GuardarConf('conf');if(!saved)throw new Error('Save did not succeed');
|
||||||
|
if(EMA.Configuracion.TiempoContinuo!==30)throw new Error('Collector retained old config');
|
||||||
|
await MenuGUI('inicio');await new Promise(r=>setTimeout(r,300));
|
||||||
|
await MenuGUI('configuracion');await new Promise(r=>setTimeout(r,300));
|
||||||
|
if(document.getElementById('NombreEstacion').value!=='Prueba arranque')throw new Error('Reload failed');
|
||||||
|
}catch(e){startupErrors.push(e.stack);}
|
||||||
|
require('fs').writeFileSync(${JSON.stringify(path.join(dir,'result.json'))},JSON.stringify({errors:startupErrors,version:process.versions.nw},null,2));
|
||||||
|
window.confirm=()=>true;if(typeof ConfigUI!=='undefined')ConfigUI.canLeave();nw.App.quit();
|
||||||
|
},2000));</script>`;
|
||||||
|
const html=path.join(dir,'gui/index.html');fs.writeFileSync(html,fs.readFileSync(html,'utf8').replace('<head>','<head>'+probe));
|
||||||
|
const pkgPath=path.join(dir,'package.json');let pkg=JSON.parse(fs.readFileSync(pkgPath));pkg['chromium-args']+=' --enable-logging=stderr';fs.writeFileSync(pkgPath,JSON.stringify(pkg));
|
||||||
|
const nw=process.argv[2]||process.env.NW_BINARY||'nw';
|
||||||
|
const child=spawn(nw,[dir,'--user-data-dir='+path.join(dir,'profile')],{cwd:dir,stdio:['ignore','ignore','pipe']});let log='';child.stderr.on('data',d=>log+=d);const timer=setTimeout(()=>child.kill(),20000);
|
||||||
|
child.on('error',error=>{clearTimeout(timer);console.error(error.message);process.exitCode=1;});
|
||||||
|
child.on('exit',()=>{clearTimeout(timer);fs.writeFileSync(path.join(dir,'stderr.log'),log);console.log(dir);if(fs.existsSync(path.join(dir,'result.json'))) {const result=JSON.parse(fs.readFileSync(path.join(dir,'result.json'),'utf8'));console.log(result);if(result.errors.length)process.exitCode=1;}else {console.log(log.slice(-4500));process.exitCode=1;}});
|
||||||
Loading…
Reference in New Issue
Block a user