diff --git a/harvester-app/src/backend/casosUso/plantillas/consultarPlantilla.js b/harvester-app/src/backend/casosUso/plantillas/consultarPlantilla.js new file mode 100644 index 00000000..c8253b8a --- /dev/null +++ b/harvester-app/src/backend/casosUso/plantillas/consultarPlantilla.js @@ -0,0 +1,22 @@ + +const { consultarPlantilla: consultarPlantillaAPI} = require('../../domain/plantillasAPI/consultarPlantilla.js'); + +/** + * Crea una plantilla a través de la API y retorna la respuesta obtenida. + * @async + * @function consultarPlantillas + * @param {string} token - Token de autenticación. + * @returns {Promise} Respuesta del servidor. + * @throws {Error} Si no se pudo consultar las plantillas. + */ +async function consultarPlantilla(nombrePlantilla){ + try{ + const respuesta = await consultarPlantillaAPI(nombrePlantilla, localStorage.getItem('token')); + return respuesta; + } catch(error){ + throw new Error('No se pudo consultar la plantilla', error); + } +} +module.exports = { + consultarPlantilla +}; \ No newline at end of file diff --git a/harvester-app/src/backend/casosUso/plantillas/consultarPlantillas.js b/harvester-app/src/backend/casosUso/plantillas/consultarPlantillas.js new file mode 100644 index 00000000..36f4b027 --- /dev/null +++ b/harvester-app/src/backend/casosUso/plantillas/consultarPlantillas.js @@ -0,0 +1,22 @@ + +const { consultarPlantillas: consultarPlantillasAPI} = require('../../domain/plantillasAPI/consultarPlantillas.js'); + +/** + * Crea una plantilla a través de la API y retorna la respuesta obtenida. + * @async + * @function consultarPlantillas + * @param {string} token - Token de autenticación. + * @returns {Promise} Respuesta del servidor. + * @throws {Error} Si no se pudo consultar las plantillas. + */ +async function consultarPlantillas(){ + try{ + const respuesta = await consultarPlantillasAPI(localStorage.getItem('token')); + return respuesta; + } catch(error){ + throw new Error('No se pudieron consultar las plantillas', error); + } +} +module.exports = { + consultarPlantillas +}; \ No newline at end of file diff --git a/harvester-app/src/backend/casosUso/plantillas/crearPlantilla.js b/harvester-app/src/backend/casosUso/plantillas/crearPlantilla.js new file mode 100644 index 00000000..5d41f90f --- /dev/null +++ b/harvester-app/src/backend/casosUso/plantillas/crearPlantilla.js @@ -0,0 +1,23 @@ + +const { crearPlantilla: crearPlantillaAPI} = require('../../domain/plantillasAPI/crearPlantilla.js'); + +/** + * Crea una plantilla a través de la API y retorna la respuesta obtenida. + * @async + * @function crearPlantilla + * @param {string} nombre - Nombre de la plantilla. + * @param {string} datos - Contenido de la plantilla. + * @returns {Promise} Respuesta del servidor. + * @throws {Error} Si no se pudo crear la plantilla. + */ +async function crearPlantilla(nombre, datos){ + try{ + const respuesta = await crearPlantillaAPI(nombre, datos, localStorage.getItem('token')); + return respuesta; + } catch(error){ + throw new Error('No se pudo crear la plantilla', error); + } +} +module.exports = { + crearPlantilla +}; \ No newline at end of file diff --git a/harvester-app/src/backend/casosUso/plantillas/eliminarPlantilla.js b/harvester-app/src/backend/casosUso/plantillas/eliminarPlantilla.js new file mode 100644 index 00000000..87bb5473 --- /dev/null +++ b/harvester-app/src/backend/casosUso/plantillas/eliminarPlantilla.js @@ -0,0 +1,22 @@ + +const { eliminarPlantilla: eliminarPlantillaAPI} = require('../../domain/plantillasAPI/eliminarPlantilla.js'); + +/** + * Crea una plantilla a través de la API y retorna la respuesta obtenida. + * @async + * @function eliminarPlantilla + * @param {string} token - Token de autenticación. + * @returns {Promise} Respuesta del servidor. + * @throws {Error} Si no se pudo eliminar la plantilla. + */ +async function eliminarPlantilla(nombrePlantilla){ + try{ + const respuesta = await eliminarPlantillaAPI(nombrePlantilla, localStorage.getItem('token')); + return respuesta; + } catch(error){ + throw new Error('No se pudo eliminar la plantilla', error); + } +} +module.exports = { + eliminarPlantilla +}; \ No newline at end of file diff --git a/harvester-app/src/backend/domain/plantillasAPI/consultarPlantilla.js b/harvester-app/src/backend/domain/plantillasAPI/consultarPlantilla.js new file mode 100644 index 00000000..38873f6d --- /dev/null +++ b/harvester-app/src/backend/domain/plantillasAPI/consultarPlantilla.js @@ -0,0 +1,19 @@ +const { URL_BASE } = require(`${rutaBase}src/framework/utils/scripts/constantes.js`); + +async function consultarPlantilla(nombrePlantilla, token) { + const respuesta = await fetch(`${URL_BASE}/plantillas/consultarPlantilla/${nombrePlantilla}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + }); + + const datos = await respuesta.json(); + + return { ok: respuesta.ok, ...datos }; + } + + module.exports = { + consultarPlantilla, + }; \ No newline at end of file diff --git a/harvester-app/src/backend/domain/plantillasAPI/plantillasAPI.js b/harvester-app/src/backend/domain/plantillasAPI/consultarPlantillas.js similarity index 56% rename from harvester-app/src/backend/domain/plantillasAPI/plantillasAPI.js rename to harvester-app/src/backend/domain/plantillasAPI/consultarPlantillas.js index 3648e5cd..34e84d7a 100644 --- a/harvester-app/src/backend/domain/plantillasAPI/plantillasAPI.js +++ b/harvester-app/src/backend/domain/plantillasAPI/consultarPlantillas.js @@ -1,10 +1,11 @@ -const { URL_BASE } = require('../../../framework/utils/js/constantes'); +const { URL_BASE } = require(`${rutaBase}src/framework/utils/scripts/constantes.js`); -async function plantillas() { - const respuesta = await fetch(`${URL_BASE}/plantillas/consultar`, { +async function consultarPlantillas(token) { + const respuesta = await fetch(`${URL_BASE}/plantillas/consultarPlantillas`, { method: 'GET', headers: { 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` } }); @@ -14,5 +15,5 @@ async function plantillas() { } module.exports = { - plantillas, + consultarPlantillas, }; \ No newline at end of file diff --git a/harvester-app/src/backend/domain/plantillasAPI/crearPlantilla.js b/harvester-app/src/backend/domain/plantillasAPI/crearPlantilla.js new file mode 100644 index 00000000..e9864e82 --- /dev/null +++ b/harvester-app/src/backend/domain/plantillasAPI/crearPlantilla.js @@ -0,0 +1,28 @@ +const { URL_BASE } = require(`${rutaBase}src/framework/utils/scripts/constantes.js`); +/** + * + * @module formulaApi + * @description Módulo para interactuar con la API de fórmulas. + * @param {string} nombre + * @param {string} datos + * @param {string} token + * @returns {Promise} Respuesta de la API. + * @throws {Error} Si no se pudo guardar la fórmula. + */ +async function crearPlantilla(titulo, contenido, token) { + const respuesta = await fetch(`${URL_BASE}/plantillas/guardarPlantilla`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({titulo, contenido}), + }); + + const datos = await respuesta.json(); + return { ok: respuesta.ok, ...datos }; +} + +module.exports = { + crearPlantilla, +}; \ No newline at end of file diff --git a/harvester-app/src/backend/domain/plantillasAPI/eliminarPlantilla.js b/harvester-app/src/backend/domain/plantillasAPI/eliminarPlantilla.js new file mode 100644 index 00000000..5ed2664f --- /dev/null +++ b/harvester-app/src/backend/domain/plantillasAPI/eliminarPlantilla.js @@ -0,0 +1,19 @@ +const { URL_BASE } = require(`${rutaBase}src/framework/utils/scripts/constantes.js`); + +async function eliminarPlantilla(nombrePlantilla, token) { + const respuesta = await fetch(`${URL_BASE}/plantillas/eliminarPlantilla/${nombrePlantilla}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + }); + + const datos = await respuesta.json(); + + return { ok: respuesta.ok, ...datos }; + } + + module.exports = { + eliminarPlantilla, + }; \ No newline at end of file diff --git a/harvester-app/src/backend/domain/plantillasAPI/eliminarPlantillasAPI.js b/harvester-app/src/backend/domain/plantillasAPI/eliminarPlantillasAPI.js deleted file mode 100644 index 11ed1745..00000000 --- a/harvester-app/src/backend/domain/plantillasAPI/eliminarPlantillasAPI.js +++ /dev/null @@ -1,19 +0,0 @@ -const { URL_BASE } = require('../../../framework/utils/js/constantes'); - -async function eliminarPlantillas(idPlantilla) { - const respuesta = await fetch(`${URL_BASE}/plantillas/eliminar`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({idPlantilla}) - }); - - const datos = await respuesta.json(); - - return { ok: respuesta.ok, ...datos }; - } - - module.exports = { - eliminarPlantillas, - }; \ No newline at end of file diff --git a/harvester-app/src/backend/domain/plantillasAPI/seleccionarPlantillaAPI.js b/harvester-app/src/backend/domain/plantillasAPI/seleccionarPlantillaAPI.js deleted file mode 100644 index 9c2d81cf..00000000 --- a/harvester-app/src/backend/domain/plantillasAPI/seleccionarPlantillaAPI.js +++ /dev/null @@ -1,19 +0,0 @@ -const { URL_BASE } = require('../../../framework/utils/js/constantes'); - -async function seleccionarPlantillas(idPlantilla) { - const respuesta = await fetch(`${URL_BASE}/plantillas/seleccionar`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({idPlantilla}) - }); - - const datos = await respuesta.json(); - - return { ok: respuesta.ok, ...datos }; - } - - module.exports = { - seleccionarPlantillas, - }; \ No newline at end of file diff --git a/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css b/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css index ccdd6780..1a309efb 100644 --- a/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css +++ b/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css @@ -35,6 +35,9 @@ body, overflow-x: auto; } +.ventana-principal{ + width: 100%; +} .seccion-elemento-reporte { display: grid; grid-template-rows: auto, 1fr auto; diff --git a/harvester-app/src/framework/utils/css/paginas/formulas/moduloFormulas.css b/harvester-app/src/framework/utils/css/paginas/formulas/moduloFormulas.css index e86a75b7..d8d482de 100644 --- a/harvester-app/src/framework/utils/css/paginas/formulas/moduloFormulas.css +++ b/harvester-app/src/framework/utils/css/paginas/formulas/moduloFormulas.css @@ -1,5 +1,6 @@ .ventana-principal { - width: 100% + width: 100%; + height: 100%; } diff --git a/harvester-app/src/framework/utils/css/paginas/plantillas/moduloPlantillas.css b/harvester-app/src/framework/utils/css/paginas/plantillas/moduloPlantillas.css deleted file mode 100644 index 48ccceca..00000000 --- a/harvester-app/src/framework/utils/css/paginas/plantillas/moduloPlantillas.css +++ /dev/null @@ -1,766 +0,0 @@ -.frame-plantillas, -.frame-plantillas * { - box-sizing: border-box; -} -.frame-plantillas { - display: flex; - flex-direction: row; - gap: 125px; - align-items: center; - justify-content: center; - flex-wrap: wrap; - align-content: flex-start; - flex-shrink: 0; - position: relative; -} -.plantilla { - background: var(--box-light, #ffffff); - border-radius: 8px; - border-style: solid; - border-color: rgba(0, 0, 0, 0.2); - border-width: 4px; - padding: 10px; - display: flex; - flex-direction: column; - align-items: flex-end; - justify-content: space-between; - flex-shrink: 0; - width: 369px; - height: 517px; - position: relative; -} -.boton-opciones { - display: flex; - align-items: center; - justify-content: flex-end; - flex-shrink: 0; - position: relative; - border: none; - background: transparent; - border-radius: 8px; - cursor: pointer; - font-size: 18px; - color: #6d6c6c; - width: 100%; - transition: background 0.2s; -} - -.more-horizontal { - display: flex; - align-items: center; - gap: 10px; - padding: 10px; - border: none; - background: blue; - border-radius: 8px; - cursor: pointer; - font-size: 18px; - color: #969696; - width: 100%; - transition: background 0.2s; - flex-shrink: 0; - width: 38px; - height: 38px; - position: relative; -} -.nombre-plantilla { - display: flex; - flex-direction: column; - gap: 10px; - align-items: center; - justify-content: center; - align-self: stretch; - flex-shrink: 0; - position: relative; - overflow: hidden; -} -.nombre-de-plantilla { - color: var(#000000); - text-align: center; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 24px; - line-height: 112%; - letter-spacing: -0.02em; - font-weight: 400; - position: relative; - display: flex; - align-items: center; - justify-content: center; -} - -scroll-container { - display: block; - width: 100%; - height: 100%; - overflow-y: scroll; - scroll-behavior: smooth; - padding: px; -} - - -.ejemplo-preview, -.ejemplo-preview * { - box-sizing: border-box; - scroll-behavior: auto; -} -.ejemplo-preview { - background: var(--blanco, #ffffff); - border-radius: 8px; - border-style: solid; - padding: 10px; - display: flex; - flex-direction: column; - gap: 25px; - align-items: center; - justify-content: flex-start; - position: relative; -} -.titlulo-ejemplo { - color: var(--texto-light, #000000); - text-align: center; - font-family: "Inter-Regular", sans-serif; - font-size: 24px; - line-height: 100%; - font-weight: 400; - position: relative; - align-self: stretch; - display: flex; - align-items: center; - justify-content: center; -} -.primer-texto { - color: var(--texto-light, #000000); - text-align: left; - font-family: "Inter-Regular", sans-serif; - font-size: 18px; - line-height: 100%; - font-weight: 400; - position: relative; - align-self: stretch; -} -.preview-grafica { - background: var(--iconos-claro, #6d6c6c); - border-radius: 8px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: center; - align-self: stretch; - flex-shrink: 0; - height: 400px; - position: relative; -} -.bar-chart { - flex-shrink: 0; - width: 25px; - height: 25px; - position: relative; - overflow: visible; -} -.sengundo-texto { - color: var(--texto-light, #000000); - text-align: left; - font-family: "Inter-Regular", sans-serif; - font-size: 18px; - line-height: 100%; - font-weight: 400; - position: relative; - align-self: stretch; -} - -.frame-btn-Editar, -.frame-btn-Editar * { - box-sizing: border-box; -} -.frame-btn-Editar { - padding: 5px; - display: flex; - flex-direction: row; - gap: 0px; - align-items: center; - justify-content: center; - flex-shrink: 0; - height: 25.75px; - position: relative; - border: none; - background: transparent; -} - -.frame-btn-Editar:hover, .cancelar:hover{ - background: rgb(175, 174, 174); -} -.eliminar:hover{ - background: #700303; -} - -.boton-modificar { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - flex-shrink: 0; - width: 112.5px; - position: relative; -} -.edit-2 { - flex-shrink: 0; - width: 24px; - height: 24px; - position: relative; - overflow: visible; -} -.modificar { - color: var(--texto-light, #000000); - text-align: center; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 20px; - line-height: 112%; - letter-spacing: -0.02em; - font-weight: 400; - position: relative; - width: 81px; - height: 17px; - display: flex; - align-items: center; - justify-content: center; -} - - -/* The container
- needed to position the dropdown content */ -.dropdown { - position: relative; - display: inline-block; -} - -/* Dropdown Content (Hidden by Default) */ -.dropdown-content { - display: none; - position: absolute; - background-color: #f1f1f1; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 1; -} - -/* Links inside the dropdown */ -.dropdown-content.frame-modificar { - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; -} - -/* Change color of dropdown links on hover */ -.dropdown-content .frame-modificar:hover {background-color: #ddd;} - -/* Show the dropdown menu on hover */ -.dropdown.active .dropdown-content {display: block;} - -/* Change the background color of the dropdown button when the dropdown content is shown */ -.dropdown.active .dropbtn {background-color: #3e8e41;} - -#modalBorrar::backdrop{ - background-color: rgba(0, 0, 0, 0.55); -} -#modalBorrar{ - padding: 0px; -} - -dialog.modal-borrar { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - border: none; - border-radius: 8px; - padding: 2rem; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); - - background-color: white; - z-index: 999; -} - - -.borrar-plantilla { - background: var(--box-light, #ffffff); - padding: 25px; - display: flex; - flex-direction: column; - gap: 19px; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 410px; - position: relative; -} -.titulo { - display: flex; - flex-direction: row; - gap: 0px; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; -} -.eliminar-la-plantila { - color: var(--texto-light, #000000); - text-align: left; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 32px; - line-height: 100%; - font-weight: 400; - position: relative; -} -.texto { - display: flex; - flex-direction: row; - row-gap: 11px; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - align-content: center; - flex-shrink: 0; - width: 383px; - max-width: 409px; - position: relative; -} -.eliminartexto { - color: var(--texto-light, #000000); - text-align: center; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 20px; - line-height: 100%; - font-weight: 400; - position: relative; - width: 383px; -} -.botones { - padding: 10px; - display: flex; - flex-direction: row; - gap: 20px; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; -} -.eliminar { - background: var(--primario, #a61930); - border-radius: 8px; - border-style: solid; - border-color: rgba(255, 255, 255, 0.2); - border-width: 2px; - padding: 10px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; -} -.texto2 { - color: var(--texto-dark, #ffffff); - text-align: center; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 24px; - line-height: 112%; - font-weight: 400; - position: relative; - display: flex; - align-items: center; - justify-content: center; -} -.cancelar { - background: var(--box-light, #ffffff); - border-radius: 8px; - border-style: solid; - border-color: #262b40; - border-width: 2px; - padding: 10px; - display: flex; - flex-direction: row; - gap: 0px; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; -} -.cancelar2 { - color: var(--texto-light, #000000); - text-align: center; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 24px; - line-height: 112%; - letter-spacing: -0.02em; - font-weight: 400; - position: relative; - display: flex; - align-items: center; - justify-content: center; -} - -.menu-opciones, -.menu-opciones * { - box-sizing: border-box; -} -.menu-opciones { - border-radius: 8px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: center; - align-self: stretch; - flex-shrink: 0; - max-height: 127px; - position: relative; -} - -.divisorPlantilla { - align-self: stretch; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - padding-top: 10px; - padding-bottom: 10px; -} -.nombre-de-plantilla { - color: var(--texto-light, #000000); - text-align: center; - font-family: "SegoeUi-Regular", sans-serif; - font-size: 24px; - line-height: 112%; - letter-spacing: -0.02em; - font-weight: 400; - position: relative; - width: 235px; - max-width: 235px; - display: flex; - align-items: center; - justify-content: flex-start; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} -.maximize-2 { - flex-shrink: 0; - width: 24px; - height: 24px; - position: relative; - overflow: visible; -} -.edit-2 { - flex-shrink: 0; - width: 24px; - height: 24px; - position: relative; - overflow: visible; -} -.trash { - flex-shrink: 0; - width: 27.5px; - height: 27.5px; - position: relative; - overflow: visible; -} - -button { - border: none; - background: transparent; - border-radius: 8px; - cursor: pointer; -} -button:hover{ - background: rgba(0, 0, 0, 0.25); - border-radius: 8px; -} - -.error-sin-plantillas, -.error-sin-plantillas * { - box-sizing: border-box; -} -.error-sin-plantillas { - color: #000000; - text-align: center; - font-family: var(--hero-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--hero-font-size, 52px); - line-height: var(--hero-line-height, 120%); - letter-spacing: var(--hero-letter-spacing, -0.02em); - font-weight: var(--hero-font-weight, 400); - position: relative; - display: flex; - align-items: center; - justify-content: center; -} - -.previsualizador-maximizado, -.previsualizador-maximizado * { - box-sizing: border-box; -} -.previsualizador-maximizado { - display: flex; - flex-direction: column; - gap: 51px; - align-items: flex-start; - justify-content: flex-start; - flex-shrink: 0; - height: 939px; - position: relative; -} -.maximizado-nombre-plantilla { - border-radius: 8px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: center; - align-self: stretch; - flex-shrink: 0; - max-height: 127px; - position: relative; -} -.nombre-plantilla { - color: var(--texto-light, #000000); - text-align: center; - font-family: var(--hero-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--hero-font-size, 52px); - line-height: var(--hero-line-height, 120%); - letter-spacing: var(--hero-letter-spacing, -0.02em); - font-weight: var(--hero-font-weight, 400); - position: relative; - flex: 1; - display: flex; - align-items: center; - justify-content: center; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} -.seccion-preview-grafica-preview { - border-radius: 8px; - border-style: solid; - border-color: #000000; - border-width: 2px; - padding: 25px; - display: flex; - flex-direction: column; - gap: 25px; - align-items: center; - justify-content: flex-start; - flex: 1; - position: relative; -} -.preview-gr-fica-preview { - color: #000000; - text-align: left; - font-family: var(--titulo-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--titulo-font-size, 32px); - line-height: var(--titulo-line-height, 120%); - letter-spacing: var(--titulo-letter-spacing, -0.02em); - font-weight: var(--titulo-font-weight, 400); - position: relative; -} -.primer-texto-prewview { - color: var(--texto-light, #000000); - text-align: left; - font-family: var(--parrafo-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--parrafo-font-size, 18px); - line-height: var(--parrafo-line-height, 120%); - letter-spacing: var(--parrafo-letter-spacing, -0.02em); - font-weight: var(--parrafo-font-weight, 400); - position: relative; - align-self: stretch; -} -.preview-grafica-preview { - background: #9e9e9e; - border-radius: 8px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 750px; - height: 396px; - position: relative; -} -.bar-chart { - flex-shrink: 0; - width: 55px; - height: 55px; - position: relative; - overflow: visible; -} -.primer-texto-preview { - color: var(--texto-light, #000000); - text-align: left; - font-family: var(--parrafo-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--parrafo-font-size, 18px); - line-height: var(--parrafo-line-height, 120%); - letter-spacing: var(--parrafo-letter-spacing, -0.02em); - font-weight: var(--parrafo-font-weight, 400); - position: relative; - align-self: stretch; -} -.botones-fondo { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - align-self: stretch; - flex-shrink: 0; - position: relative; -} -.botones-ediar-eliminar { - display: flex; - flex-direction: row; - gap: 25px; - align-items: center; - justify-content: flex-start; - flex-shrink: 0; - position: relative; -} -.btn-editar { - border-radius: 8px; - border-style: solid; - border-color: var(--negro, #000000); - border-width: 2px; - padding: 10px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: flex-start; - flex-shrink: 0; - min-width: 150px; - position: relative; -} -.editar-maximizado { - flex-shrink: 0; - width: 24px; - height: 24px; - position: relative; - overflow: visible; -} -.editar-maximizaddo { - color: #000000; - text-align: center; - font-family: var(--encabezado-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--encabezado-font-size, 24px); - line-height: var(--encabezado-line-height, 120%); - letter-spacing: var(--encabezado-letter-spacing, -0.02em); - font-weight: var(--encabezado-font-weight, 400); - position: relative; - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} -.btn-eliminar { - background: var(--primario, #a61930); - border-radius: 8px; - border-style: solid; - border-color: var(--bordeblanco, rgba(255, 255, 255, 0.2)); - border-width: 1px; - padding: 10px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: flex-start; - flex-shrink: 0; - min-width: 150px; - position: relative; -} -.eliminar-maximizado { - flex-shrink: 0; - width: 27.5px; - height: 27.5px; - position: relative; - overflow: visible; -} -.eliminar-maximizado2 { - color: var(--blanco, #ffffff); - text-align: center; - font-family: var(--encabezado-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--encabezado-font-size, 24px); - line-height: var(--encabezado-line-height, 120%); - letter-spacing: var(--encabezado-letter-spacing, -0.02em); - font-weight: var(--encabezado-font-weight, 400); - position: relative; - width: 82px; - display: flex; - align-items: center; - justify-content: center; -} -.botones-usar-cancelar { - display: flex; - flex-direction: row; - gap: 25px; - align-items: flex-start; - justify-content: center; - flex-shrink: 0; - position: relative; -} -.btn-usar { - background: var(--secundario, #a61930); - border-radius: 8px; - border-style: solid; - border-color: rgba(255, 255, 255, 0.2); - border-width: 2px; - padding: 10px; - display: flex; - flex-direction: row; - gap: 10px; - align-items: center; - justify-content: center; - flex-shrink: 0; - min-width: 150px; - position: relative; -} -.uasr-maximizado { - color: var(--texto-dark, #ffffff); - text-align: center; - font-family: var(--encabezado-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--encabezado-font-size, 24px); - line-height: var(--encabezado-line-height, 120%); - letter-spacing: var(--encabezado-letter-spacing, -0.02em); - font-weight: var(--encabezado-font-weight, 400); - position: relative; - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} -.btn-cancelar { - background: var(--box-light, #ffffff); - border-radius: 8px; - border-style: solid; - border-color: #262b40; - border-width: 2px; - padding: 10px; - display: flex; - flex-direction: row; - gap: 0px; - align-items: center; - justify-content: center; - flex-shrink: 0; - min-width: 150px; - position: relative; -} -.cancelar-maximizado { - color: var(--texto-light, #000000); - text-align: center; - font-family: var(--encabezado-font-family, "SegoeUi-Regular", sans-serif); - font-size: var(--encabezado-font-size, 24px); - line-height: var(--encabezado-line-height, 120%); - letter-spacing: var(--encabezado-letter-spacing, -0.02em); - font-weight: var(--encabezado-font-weight, 400); - position: relative; - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} diff --git a/harvester-app/src/framework/utils/css/paginas/plantillas/plantillas.css b/harvester-app/src/framework/utils/css/paginas/plantillas/plantillas.css new file mode 100644 index 00000000..31faf52f --- /dev/null +++ b/harvester-app/src/framework/utils/css/paginas/plantillas/plantillas.css @@ -0,0 +1,59 @@ +.frame-plantillas{ + display: flex; + flex-direction: row; + justify-content: flex-start; + align-content: baseline; + width: 100%; + height: 100%; + border-radius: 0.33em; + background-color: #ededed; + margin-bottom: 1em; + padding: 0.5em; +} + +.frame-plantillas-izquierda { + display: flex; + flex-direction: row; + justify-content: flex-start; + width: 100%; + height: 3em; + +} + +.frame-plantillas-derecha { + display: flex; + flex-direction: row; + justify-content: flex-end; + width: 100%; + height: 3em; + /* padding: 0.5em; */ +} + +.boton-principal, .selector-plantilla, .input-nombre-plantilla { + font-family: "SegoeUi-Regular", sans-serif; + font-size: medium; + border-radius: 0.33em; + border: none; + padding: 0.5em 1em; + margin: 0.5em 0 0 0.5em; + background-color: #ffffff; +} + +.boton-principal:hover { + background-color: #f9f9f9; +} + +.boton-secundario { + font-family: "SegoeUi-Regular", sans-serif; + font-size: medium; + border-radius: 0.33em; + border: none; + padding: 0.5em 1em; + margin: 0.5em 0 0 0.5em; + background-color: #a61930; + color: #ffffff; +} + +.boton-secundario:hover { + background-color: #7d1425; +} diff --git a/harvester-app/src/framework/utils/scripts/iniciarSesion.js b/harvester-app/src/framework/utils/scripts/iniciarSesion.js index 9f5bbd9f..6dca1e74 100644 --- a/harvester-app/src/framework/utils/scripts/iniciarSesion.js +++ b/harvester-app/src/framework/utils/scripts/iniciarSesion.js @@ -90,14 +90,17 @@ async function manejarInicioSesion() { // Reiniciar verificación periódica después del login exitoso await ipcRenderer.invoke('reiniciar-verificacion-periodica'); - const rutaInicio = `${rutaBase}src/framework/vistas/paginas/inicio/inicio.ejs`; + // Guardar bandera para saber que vienes de login + localStorage.setItem('cargando-desde-login', 'true'); + + // Redirigir a pantallaCarga.ejs en vez de inicio.ejs directamente + const rutaPantallaCarga = `${rutaBase}src/framework/vistas/paginas/pantallaCarga.ejs`; try { - const vista = await ipcRenderer.invoke('precargar-ejs', rutaInicio,{Seccion: 'Inicio', Icono: 'Casa', permisos: listaPermisos}); + const vista = await ipcRenderer.invoke('precargar-ejs', rutaPantallaCarga, { rutaBase, permisos: listaPermisos }); window.location.href = vista; } catch (err) { return ('Error al cargar vista:', err); } - } else { mostrarAlerta('Verifica tus datos', respuesta.mensaje, 'warning'); } diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js index c156fd4b..0dbe1be3 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js @@ -143,8 +143,10 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos } // Actualizar la llamada en el event listener del botón de fórmulas - tarjetaGrafica.querySelector('.boton-formulas').addEventListener('click', async () => - await crearCuadroFormulas(nuevaId, formulasDisponibles, datosOriginalesFormulas, tractorSeleccionado)); + tarjetaGrafica.querySelector('.boton-formulas').addEventListener('click', async () => { + tractorSeleccionado = selectorTractor.value; + await crearCuadroFormulas(nuevaId, formulasDisponibles, datosOriginalesFormulas, tractorSeleccionado); + }); const graficaDiv = document.createElement('div'); graficaDiv.className = 'previsualizacion-grafica'; @@ -400,4 +402,7 @@ function hexARGB(colorHex) { module.exports = { agregarGrafica, + modificarTipoGrafica, + modificarColor, + modificarTitulo }; \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarTexto.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarTexto.js index 03bc19ec..4daa0f77 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarTexto.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarTexto.js @@ -289,5 +289,8 @@ function configurarObservadorLimite(contenedor) { } module.exports = { - agregarTexto + agregarTexto, + actualizarTexto, + actualizarCaracteres, + validarBotonAlinear }; \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js index 53125a40..fbf869a9 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js @@ -143,19 +143,26 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal // Obtener los datos directamente de las propiedades del elemento const nombreFormula = inputRadio.formulaNombre; - const datosFormula = inputRadio.formulaDatos; + + const datosFormula = inputRadio.formulaDatos; + // Verificar que los datos están completos if (!datosFormula || datosFormula.trim() === '') { mostrarAlerta('Error', 'Los datos de la fórmula están vacíos o incompletos.', 'error'); if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula'; return; } - + // Obtener la gráfica asociada const graficaId = cuadroFormulas.dataset.graficaId; const graficaDiv = document.getElementById(`previsualizacion-grafica-${graficaId}`); + const graficaDiv2 = document.querySelector(`#\\3${graficaId}.tarjeta-grafica`); + if (graficaDiv2) { + graficaDiv2.dataset.formulaActual = nombreFormula; + } + if (!graficaDiv) { mostrarAlerta('Error', 'No se encontró la gráfica asociada.', 'error'); if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula'; diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js index c0113d89..c2fe004f 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js @@ -25,6 +25,14 @@ function crearMenuFiltros(contenedor, filtros, graficaId, contenedorParametros, // Agregar evento de cambio para actualizar la gráfica seleccionValores.addEventListener('change', () => { // Si se deselecciona, resetear la gráfica a estado inicial + // const element = document.querySelector('.tarjeta-grafica#\\31'); + const graficaDiv = document.querySelector(`#\\3${graficaId}.tarjeta-grafica`); + if (graficaDiv) { + graficaDiv.dataset.filtroActual = seleccionValores.value; + } + + + const selectorParametro = contenedorParametros.querySelector('select'); const filtroAplicado = filtros.filter(filtro => { diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js index a13ff7fe..ce0133df 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js @@ -25,6 +25,11 @@ function crearMenuParametros(contenedor, columnas, graficaId, datosOriginalesFor // Agregar evento de cambio para actualizar la gráfica seleccionValores.addEventListener('change', (evento) => { + const graficaDiv = document.querySelector(`#\\3${graficaId}.tarjeta-grafica`); + if (graficaDiv) { + graficaDiv.dataset.parametroActual = seleccionValores.value; + } + const filtroAplicado = filtrosDisponibles.filter(filtro => { return contenedorFiltros.querySelector('.opcion-texto').value == filtro.Nombre; }); diff --git a/harvester-app/src/framework/utils/scripts/paginas/plantillas/cargarPlantilla.js b/harvester-app/src/framework/utils/scripts/paginas/plantillas/cargarPlantilla.js new file mode 100644 index 00000000..9c33ad78 --- /dev/null +++ b/harvester-app/src/framework/utils/scripts/paginas/plantillas/cargarPlantilla.js @@ -0,0 +1,353 @@ +/*eslint-disable*/ +const { consultarPlantilla } = require(`${rutaBase}src/backend/casosUso/plantillas/consultarPlantilla.js`); +// const { consultarPlantillas } = require(`${rutaBase}src/framework/utils/scripts/paginas/plantillas/consultarPlantillas.js`); +// const { configurarTexto } = require(`${rutaBase}src/framework/utils/scripts/paginas/analisis/agregarTexto.js`); +// const { agregarGrafica } = require(`${rutaBase}src/framework/utils/scripts/paginas/analisis/agregarGrafica.js`); +const { actualizarTexto, actualizarCaracteres, validarBotonAlinear } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/agregarTexto.js`); +const { modificarTipoGrafica, modificarColor, modificarTitulo } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js`); +const { ElementoNuevo, Contenedores } = require(`${rutaBase}/src/backend/data/analisisModelos/elementoReporte.js`); +const { aplicarFormula } = require(`${rutaBase}/src/backend/casosUso/formulas/aplicarFormula.js`); +const { filtrarDatos } = require(`${rutaBase}/src/backend/casosUso/formulas/filtrarDatos.js`); +const { procesarDatosUniversal } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/procesarDatosUniversal.js`); +const Chart = require(`${rutaBase}/node_modules/chart.js/auto`); + +// const { configurarTexto, configurarGrafica } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/botonesAgregar.js`); + +function cargarPlantillaScript(){ + const nombrePlantilla = document.getElementById('selectorPlantilla'); + const botonCargarPlantilla = document.getElementById('botonCargarPlantilla'); + + botonCargarPlantilla.addEventListener('click', async () => { + try { + const respuesta = await consultarPlantilla(nombrePlantilla.value); + + if (!respuesta.ok) { + mostrarAlerta('Error', `Error al cargar la plantilla: ${respuesta.error}`, 'error'); + return; + } + + const contenido = JSON.parse(respuesta.datos.contenido); + const idContenedor = 'contenedorElementos'; + const idContenedorPrevisualizacion = 'contenedor-elementos-previsualizacion'; + + // Cargar la plantilla y verificar si fue exitosa + const cargaExitosa = await cargarPlantillaDesdeJSON(contenido, idContenedor, idContenedorPrevisualizacion); + + // Solo mostrar alerta de éxito si la carga fue exitosa + if (cargaExitosa) { + mostrarAlerta('Correcto', 'Plantilla cargada correctamente', 'success'); + } + + } catch (error) { + console.error('Error en cargarPlantillaScript:', error); + mostrarAlerta('Error', 'Error inesperado al cargar la plantilla', 'error'); + } + }); +} + +async function cargarPlantillaDesdeJSON(json, contenedorId, idContenedorPrevisualizacion) { + try { + const componentes = json; + + // Obtener datos de Excel desde localStorage + const datosExcel = JSON.parse(localStorage.getItem('datosFiltradosExcel') || '{}'); + + // Verificar que existan datos de Excel cargados + if (!datosExcel.hojas || Object.keys(datosExcel.hojas).length === 0) { + mostrarAlerta('Error', 'No hay datos de Excel cargados. Carga un archivo Excel primero.', 'warning'); + return false; // Retornar false para indicar que la carga falló + } + + // Verificar columnas requeridas antes de cargar la plantilla + const verificacionResultado = verificarColumnasRequeridas(componentes, datosExcel); + if (!verificacionResultado.valido) { + // Formatear el mensaje igual que en aplicarFormula.js + const columnasFaltantesTexto = verificacionResultado.columnasFaltantes + .map(item => item.split(': ')[1]) // Extraer solo el nombre de la columna + .filter((valor, indice, array) => array.indexOf(valor) === indice) // Eliminar duplicados + .join(', '); + const verificarFormulaOColumna = verificacionResultado.columnasFaltantes + .map(item =>item.split(': ')[0]) + .filter((valor, indice, array) => array.indexOf(valor) === indice) // Eliminar duplicados + .join(', '); + + if (verificarFormulaOColumna.includes('Fórmula no encontrada')) { + mostrarAlerta( + `Fórmulas no encontradas: ${columnasFaltantesTexto}`, + 'Asegúrate de que existan las fórmulas de esta plantilla.', + 'error' + ); + return false; + } + + // Verificar si hay columnas no encontradas (de filtros) + if (verificarFormulaOColumna.includes('Columna no encontrada')) { + mostrarAlerta( + `Columna no encontrada: ${columnasFaltantesTexto}`, + 'Asegúrate de seleccionar todas las columnas necesarias para aplicar este filtro.', + 'error' + ); + return false; + } + + mostrarAlerta( + `Columnas no encontradas: ${columnasFaltantesTexto}`, + 'Asegúrate de haber seleccionado todas las columnas necesarias para aplicar las fórmulas de esta plantilla.', + 'error' + ); + return false; // Retornar false para indicar que la carga falló + } + + const contenedor = document.querySelector(`#${contenedorId}`); + const contenedorPrevisualizacion = document.querySelector(`#${idContenedorPrevisualizacion}`); + + // Limpiar el contenedor + contenedor.innerHTML = ''; + contenedorPrevisualizacion.innerHTML = ''; + + // Iterar sobre cada componente + for (const componente of componentes) { + if (componente.componente == "texto") { + // Crear tarjeta de texto + configurarTexto(contenedorId, idContenedorPrevisualizacion); + + const tarjetaTexto = contenedor.querySelector(`.tarjeta-texto:last-child`); + const previsualizacionTexto = contenedorPrevisualizacion.querySelector(`.previsualizacion-texto.preview-titulo:last-child`); + + if (tarjetaTexto) { + // Configurar propiedades + const tipoTexto = tarjetaTexto.querySelector('.tipo-texto'); + const areaEscritura = tarjetaTexto.querySelector('.area-escritura'); + const iconoAlign = tarjetaTexto.querySelector('.icono-align'); + const botonAlinear = tarjetaTexto.querySelector('.alinear'); + + if (tipoTexto) { + tipoTexto.value = componente.tipo; + previsualizacionTexto.classList.remove('preview-titulo', 'preview-subtitulo', 'preview-contenido'); + previsualizacionTexto.classList.add(`preview-${componente.tipo}`); + }; + + if (areaEscritura) areaEscritura.value = componente.contenido; + + // Configurar alineamiento + if (iconoAlign) { + iconoAlign.classList.remove('align-left', 'align-center', 'align-right'); + iconoAlign.classList.add(componente.alineamiento); + const alineaciones = ['left', 'center', 'right']; + previsualizacionTexto.alignIndex = (previsualizacionTexto.alignIndex + 1) % alineaciones.length; + const alineado = alineaciones[previsualizacionTexto.alignIndex]; + previsualizacionTexto.style.textAlign = alineado; + iconoAlign.className = `icono-align align-${alineado}`; + } + + // const vistaPrevia = tarjetaTexto.querySelector('.previsualizacion-texto.preview-titulo'); + actualizarTexto(previsualizacionTexto, areaEscritura); + + // Actualizar el contador de caracteres después de cargar el contenido + if (areaEscritura) { + actualizarCaracteres(tarjetaTexto, areaEscritura); + } + + // Validar el botón alinear después de cargar el contenido + if (areaEscritura && botonAlinear) { + validarBotonAlinear(areaEscritura, botonAlinear); + } + } + + + } else if (componente.componente == "grafica") { + // Crear tarjeta de gráfica + configurarGrafica(contenedorId, idContenedorPrevisualizacion); + + const tarjetaGrafica = contenedor.querySelector(`.tarjeta-grafica:last-child`); + + if (tarjetaGrafica) { + // Configurar propiedades + const elementos = { + titulo: tarjetaGrafica.querySelector('.titulo-grafica'), + tipo: tarjetaGrafica.querySelector('.tipo-grafica'), + tractor: tarjetaGrafica.querySelector('.tractor-grafica'), + color: tarjetaGrafica.querySelector('#color-entrada') + }; + + const previsualizacionGrafica = contenedorPrevisualizacion.querySelector(`.previsualizacion-grafica:last-child`); + + empaquetador = {value: componente.tipo} //estos empaquetamientos sirven para que al usar las funciones piense que le estas pasando un componente de html, ya que dentro de la función solo usa el componente para sacarle el valor. + empaquetador2 = {value: componente.color} + + if (elementos.titulo) elementos.titulo.value = componente.nombre; + + if (elementos.tipo){ + elementos.tipo.value = componente.tipo; + modificarTipoGrafica(previsualizacionGrafica, empaquetador, componente.nombre); + } + + if (elementos.color) { + elementos.color.value = componente.color; + modificarColor(empaquetador2, previsualizacionGrafica, 0) + } + + // Actualizar el contador de caracteres del título de la gráfica + if (elementos.titulo) { + modificarTitulo(previsualizacionGrafica, elementos.titulo, tarjetaGrafica); + } + + const tractorSeleccionado = componente.tractor; + + tarjetaGrafica.dataset.filtroActual = componente.filtro || ''; + tarjetaGrafica.dataset.parametroActual = componente.parametro || ''; + tarjetaGrafica.dataset.formulaActual = componente.formula || ''; + + + if(componente.parametro && !componente.formula) { + + } + if (componente.formula){ + if(componente.filtro){ + const filtro = [JSON.parse(localStorage.getItem('formulasDisponibles')).filter(formula => formula.Nombre === componente.filtro)[0]]; + + const datosFiltrados = filtrarDatos(filtro, JSON.parse(localStorage.getItem('datosFiltradosExcel')), tractorSeleccionado); + for(const formula of JSON.parse(localStorage.formulasDisponibles)){ + if (formula.Nombre == componente.formula) { + const resultadoFormula = aplicarFormula(formula.Nombre, formula.Datos, tractorSeleccionado, datosFiltrados.resultados); + const canvas = previsualizacionGrafica.querySelector('canvas'); + + const contexto = canvas.getContext('2d'); + const graficaExistente = Chart.getChart(contexto); + + if (graficaExistente && resultadoFormula.resultados) { + const resultados = resultadoFormula.resultados; + const tipoGrafica = graficaExistente.config.type; + + // Usar el procesamiento universal + const datosRebuild = procesarDatosUniversal(resultados, tipoGrafica, formula.Nombre); + + // Actualizar la gráfica + graficaExistente.options.plugins.title.text = formula.Nombre; + graficaExistente.data.labels = datosRebuild.labels; + graficaExistente.data.datasets[0].data = datosRebuild.valores; + + // CORRECCIÓN: Actualizar también la etiqueta del dataset + graficaExistente.data.datasets[0].label = formula.Nombre; + + graficaExistente.update(); + } + } + } + + } + } + + } + } + } + + return true; // Retornar true para indicar que la carga fue exitosa + + } catch (error) { + console.error('Error al cargar la plantilla:', error); + mostrarAlerta('Error', 'No se pudo cargar la plantilla correctamente', 'error'); + return false; // Retornar false para indicar que la carga falló + } +} + +/** + * Verifica que todas las columnas requeridas por las fórmulas y filtros de la plantilla estén disponibles + * @param {Array} componentes - Componentes de la plantilla + * @param {Object} datosExcel - Datos de Excel disponibles + * @returns {Object} Resultado de la verificación + */ +function verificarColumnasRequeridas(componentes, datosExcel) { + const columnasFaltantes = []; + const formulasDisponibles = JSON.parse(localStorage.getItem('formulasDisponibles') || '[]'); + + // Obtener encabezados disponibles de todas las hojas + const encabezadosDisponibles = new Set(); + + // Verificar que datosExcel tenga la estructura correcta + if (datosExcel && datosExcel.hojas) { + Object.values(datosExcel.hojas).forEach(hoja => { + if (Array.isArray(hoja) && hoja.length > 0) { + // La primera fila contiene los encabezados + if (Array.isArray(hoja[0])) { + hoja[0].forEach(encabezado => { + if (encabezado && typeof encabezado === 'string') { + encabezadosDisponibles.add(encabezado.trim()); + } + }); + } + } + }); + } + + for (const componente of componentes) { + if (componente.componente === "grafica") { + // Verificar fórmula + if (componente.formula) { + const formula = formulasDisponibles.find(f => f.Nombre === componente.formula); + if (formula) { + const columnasRequeridas = extraerColumnasDeFormula(formula.Datos); + + for (const columna of columnasRequeridas) { + if (!encabezadosDisponibles.has(columna)) { + columnasFaltantes.push(`${componente.formula}: ${columna}`); + } + } + } else { + columnasFaltantes.push(`Fórmula no encontrada: ${componente.formula}`); + } + } + + // Verificar filtro + if (componente.filtro) { + const filtro = formulasDisponibles.find(f => f.Nombre === componente.filtro); + if (filtro) { + const columnasRequeridas = extraerColumnasDeFormula(filtro.Datos); + + for (const columna of columnasRequeridas) { + if (!encabezadosDisponibles.has(columna)) { + columnasFaltantes.push(`Columna no encontrada: ${columna}`); + } + } + } else { + columnasFaltantes.push(`Filtro no encontrado: ${componente.filtro}`); + } + } + } + } + + return { + valido: columnasFaltantes.length === 0, + columnasFaltantes + }; +} + +/** + * Extrae las columnas requeridas de una fórmula estructurada + * @param {string} formulaEstructurada - Fórmula en formato estructurado + * @returns {Array} Array de nombres de columnas requeridas + */ +function extraerColumnasDeFormula(formulaEstructurada) { + const columnas = []; + + if (!formulaEstructurada || typeof formulaEstructurada !== 'string') { + console.warn('Fórmula estructurada inválida:', formulaEstructurada); + return columnas; + } + + // Usar la misma expresión regular que en aplicarFormula.js + const regex = /\[@([^\]]+)\]/g; + let match; + + while ((match = regex.exec(formulaEstructurada)) !== null) { + const nombreColumna = match[1].trim(); // Limpiar espacios + if (!columnas.includes(nombreColumna)) { + columnas.push(nombreColumna); + } + } + + return columnas; +} + +cargarPlantillaScript(); + diff --git a/harvester-app/src/framework/utils/scripts/paginas/plantillas/consultarPlantillas.js b/harvester-app/src/framework/utils/scripts/paginas/plantillas/consultarPlantillas.js new file mode 100644 index 00000000..2f9d4e73 --- /dev/null +++ b/harvester-app/src/framework/utils/scripts/paginas/plantillas/consultarPlantillas.js @@ -0,0 +1,25 @@ +const { consultarPlantillas } = require(`${rutaBase}src/backend/casosUso/plantillas/consultarPlantillas.js`); + +function vaciarSelectorPlantillas() { + const selectorPlantilla = document.getElementById('selectorPlantilla'); + selectorPlantilla.innerHTML = ''; // Limpiar el contenido del selector +} + + +async function consultarPlantillasScript(){ + const plantillas = await consultarPlantillas(); + const selectorPlantilla = document.getElementById('selectorPlantilla'); + vaciarSelectorPlantillas(); // Limpiar el selector antes de agregar nuevas opciones + plantillas.datos.forEach(plantilla => { + const option = document.createElement('option'); + option.value = plantilla.titulo; + option.textContent = plantilla.titulo; + selectorPlantilla.appendChild(option); + }) +} + +consultarPlantillasScript(); + +// module.exports = { +// consultarPlantillas, +// }; \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/paginas/plantillas/crearPlantilla.js b/harvester-app/src/framework/utils/scripts/paginas/plantillas/crearPlantilla.js new file mode 100644 index 00000000..ab6a4da7 --- /dev/null +++ b/harvester-app/src/framework/utils/scripts/paginas/plantillas/crearPlantilla.js @@ -0,0 +1,72 @@ +/*eslint-disable*/ +const { crearPlantilla } = require(`${rutaBase}src/backend/casosUso/plantillas/crearPlantilla.js`); +// const { consultarPlantillas } = require(`${rutaBase}src/framework/utils/scripts/paginas/plantillas/consultarPlantillas.js`); +// const { mostrarAlerta } = require(`${rutaBase}/src/framework/vistas/includes/componentes/moleculas/alertaSwal/alertaSwal`); + +function crearPlantillaScript(){ + const nombrePlantilla = document.getElementById('nombrePlantilla'); + const botonGuardarPlantilla = document.getElementById('botonGuardarPlantilla'); + botonGuardarPlantilla.addEventListener('click', async () => { + if (nombrePlantilla.value.trim().length > 50) { + mostrarAlerta('Error', 'El nombre de la plantilla no debe exceder 50 caracteres', 'error'); + return; + } + const contenidoPlantilla = obtenerJsonPlantillaDesdeDOM(); + const respuesta = await crearPlantilla(nombrePlantilla.value, contenidoPlantilla); + if (respuesta.ok) { + mostrarAlerta('Correcto', 'Plantilla guardada correctamente', 'success'); + vaciarSelectorPlantillas + await consultarPlantillasScript(); // Actualizar el selector de plantillas + } else { + mostrarAlerta('Error', `Error al guardar la plantilla`, 'error'); + } + }); +} + +crearPlantillaScript(); +verificarCaracteresTitulo(); + + +function obtenerJsonPlantillaDesdeDOM(){ + const componentes = []; + + const contenedorComponentes = document.getElementById('contenedorElementos') + + Array.from(contenedorComponentes.children).forEach(componente => { + + if(componente.classList.contains('tarjeta-texto')){ + componentes.push({ + componente: "texto", + tipo: componente.querySelector('.tipo-texto').value, + contenido: componente.querySelector('.area-escritura').value, + alineamiento: componente.querySelector('.icono-align').classList[1] + }); + + } else if(componente.classList.contains('tarjeta-grafica')){ + + componentes.push({ + componente: "grafica", + nombre : componente.querySelector('.titulo-grafica').value, + tipo : componente.querySelector('.tipo-grafica').value, + tractor : componente.querySelector('.tractor-grafica').value, + color: componente.querySelector('#color-entrada').value, + parametro : componente.dataset.parametroActual, + filtro : componente.dataset.filtroActual, + formula : componente.dataset.formulaActual, + }) + + } + }); + + return JSON.stringify(componentes); +} + +function verificarCaracteresTitulo(){ + const nombrePlantilla = document.getElementById('nombrePlantilla'); + nombrePlantilla.addEventListener('input', () => { + if (nombrePlantilla.value.length >= 50) { + mostrarAlerta('Advertencia', 'Has alcanzado el límite máximo de 50 caracteres', 'warning'); + nombrePlantilla.value = nombrePlantilla.value.substring(0, 50); + } + }); +} \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/paginas/plantillas/eliminarPlantilla.js b/harvester-app/src/framework/utils/scripts/paginas/plantillas/eliminarPlantilla.js new file mode 100644 index 00000000..9606f0d7 --- /dev/null +++ b/harvester-app/src/framework/utils/scripts/paginas/plantillas/eliminarPlantilla.js @@ -0,0 +1,21 @@ +/*eslint-disable*/ +const { eliminarPlantilla } = require(`${rutaBase}src/backend/casosUso/plantillas/eliminarPlantilla.js`); +// const { consultarPlantillas } = require(`${rutaBase}src/framework/utils/scripts/paginas/plantillas/consultarPlantillas.js`); + +function eliminarPlantillaScript(){ + const nombrePlantilla = document.getElementById('selectorPlantilla'); + const botonEliminarPlantilla = document.getElementById('botonEliminarPlantilla'); + + botonEliminarPlantilla.addEventListener('click', async () => { + const respuesta = await eliminarPlantilla(nombrePlantilla.value); + if (respuesta.ok) { + mostrarAlerta('Correcto', 'Plantilla eliminada correctamente', 'success'); + vaciarSelectorPlantillas(); + await consultarPlantillasScript(); // Actualizar el selector de plantillas + } else { + mostrarAlerta('Error', `Error al eliminar la plantilla: ${respuesta.error}`, 'error'); + } + }); +} + +eliminarPlantillaScript(); \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/paginas/plantillas/jsonPlantilla.js b/harvester-app/src/framework/utils/scripts/paginas/plantillas/jsonPlantilla.js new file mode 100644 index 00000000..55c964b7 --- /dev/null +++ b/harvester-app/src/framework/utils/scripts/paginas/plantillas/jsonPlantilla.js @@ -0,0 +1,22 @@ + + +{ + [ + { + componente : "texto", + tipo : "titulo", + contenido : "Reporte trimestral de CASE 110 A", + alineamiento : "izquierda", + }, + { + componente : "grafica", + nombre : "Litros de gasolina consumidos", + tipo : "linea", + tractor : "CASE 110 A (TEC)", + parametro : '', + filtro : 'Filtro encendido', + formula : 'Exceso de Gasolina' + + } + ] +} \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/pantallaCarga.js b/harvester-app/src/framework/utils/scripts/pantallaCarga.js index 81d351a4..a0847e92 100644 --- a/harvester-app/src/framework/utils/scripts/pantallaCarga.js +++ b/harvester-app/src/framework/utils/scripts/pantallaCarga.js @@ -1,6 +1,5 @@ - -const { verificarToken } = require(`${rutaBase}/src/backend/servicios/verificarToken`); // Importar la función verificarToken -const { verificarPermisos } = require(`${rutaBase}/src/backend/servicios/verificarPermisos`); // Importar la función verificarPermisos +const { verificarToken } = require(`${rutaBase}/src/backend/servicios/verificarToken`); +const { verificarPermisos } = require(`${rutaBase}/src/backend/servicios/verificarPermisos`); const { ipcRenderer } = require('electron'); /** @@ -8,9 +7,31 @@ const { ipcRenderer } = require('electron'); * Verifica la validez del token almacenado y redirige según corresponda. */ document.addEventListener('DOMContentLoaded', async () => { - const token = obtenerToken(); // Llamamos a la función para obtener el token al cargar la página - try { + const desdeLogin = localStorage.getItem('cargando-desde-login') === 'true'; + + if (desdeLogin) { + // Solo mostrar loader y redirigir sin verificar token/permiso + setTimeout(async () => { + localStorage.removeItem('cargando-desde-login'); + const permisos = JSON.parse(localStorage.getItem('permisos') || '[]'); + const rutaInicio = `${rutaBase}src/framework/vistas/paginas/inicio/inicio.ejs`; + try { + localStorage.setItem('seccion-activa', 'inicio'); + const vista = await ipcRenderer.invoke('precargar-ejs', rutaInicio, { Seccion : 'Inicio', Icono : 'Casa', permisos}); + window.location.href = vista; + } catch { + // Si ocurre un error al cargar inicio, redirigir a iniciarSesion + const rutaIniciarSesion = `${rutaBase}src/framework/vistas/paginas/iniciarSesion.ejs`; + const vista = await ipcRenderer.invoke('precargar-ejs', rutaIniciarSesion); + window.location.href = vista; + } + }, 2000); + return; + } + + const token = obtenerToken(); // Llamamos a la función para obtener el token al cargar la página + // Verificar si el token es válido const tokenValido = await verificarToken(token); @@ -27,28 +48,22 @@ document.addEventListener('DOMContentLoaded', async () => { localStorage.setItem('seccion-activa', 'inicio'); const vista = await ipcRenderer.invoke('precargar-ejs', rutaInicio, { Seccion : 'Inicio', Icono : 'Casa', permisos}); window.location.href = vista; - } catch (err) { - return ('Error al cargar vista:', err); + } catch { + const rutaIniciarSesion = `${rutaBase}src/framework/vistas/paginas/iniciarSesion.ejs`; + const vista = await ipcRenderer.invoke('precargar-ejs', rutaIniciarSesion); + window.location.href = vista; } } else { const rutaIniciarSesion = `${rutaBase}src/framework/vistas/paginas/iniciarSesion.ejs`; - try { - const vista = await ipcRenderer.invoke('precargar-ejs', rutaIniciarSesion); - window.location.href = vista; - } catch (err) { - return ('Error al cargar vista:', err); - } + const vista = await ipcRenderer.invoke('precargar-ejs', rutaIniciarSesion); + window.location.href = vista; } } catch { - // En caso de error, mostrar la pantalla de carga y luego redirigir a inicio de sesión + // Si ocurre cualquier error, redirigir a iniciarSesion const rutaIniciarSesion = `${rutaBase}src/framework/vistas/paginas/iniciarSesion.ejs`; - try { - const vista = await ipcRenderer.invoke('precargar-ejs', rutaIniciarSesion); - window.location.href = vista; - } catch (err) { - return ('Error al cargar vista:', err); - } + const vista = await ipcRenderer.invoke('precargar-ejs', rutaIniciarSesion); + window.location.href = vista; } }); diff --git a/harvester-app/src/framework/vistas/paginas/analisis/generarReporte.ejs b/harvester-app/src/framework/vistas/paginas/analisis/generarReporte.ejs index c928715d..232d96d0 100644 --- a/harvester-app/src/framework/vistas/paginas/analisis/generarReporte.ejs +++ b/harvester-app/src/framework/vistas/paginas/analisis/generarReporte.ejs @@ -2,7 +2,28 @@ + +
+
+ + + +
+
+ + +
+
+ +
@@ -24,5 +45,9 @@
+ + + + <%- include ('../../includes/piePagina.ejs')%> \ No newline at end of file diff --git a/harvester-app/src/main.js b/harvester-app/src/main.js index 88b09503..0749945c 100644 --- a/harvester-app/src/main.js +++ b/harvester-app/src/main.js @@ -27,7 +27,7 @@ const createWindow = async () => { webPreferences: { nodeIntegration: true, contextIsolation: false, - devTools: false, + //devTools: true, }, });