From f29c739e4908944debea4c3f79120f74eeb66503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Calder=C3=B3n?= <150750774+Johnccg@users.noreply.github.com> Date: Sun, 22 Jun 2025 16:00:48 -0600 Subject: [PATCH 1/5] =?UTF-8?q?Agregar=20input=20para=20color=20de=20gr?= =?UTF-8?q?=C3=A1fica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../css/paginas/analisis/generarReporte.css | 106 +++++++++--------- .../paginas/analisis/agregarGrafica.js | 23 ++-- 2 files changed, 63 insertions(+), 66 deletions(-) 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 5d2bd8bc..ce76034c 100644 --- a/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css +++ b/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css @@ -144,8 +144,7 @@ body, position: relative; width: 362px; } -.titulo-grafica, -.titulo-texto { +.titulo-grafica { background-color: #fafafa; padding: 10px; display: flex; @@ -315,20 +314,28 @@ body, resize: vertical; } .titulo-texto { - position: relative; background-color: #fafafa; - border-radius: 10px; padding: 10px; display: flex; + flex-direction: row; align-items: center; justify-content: space-between; - background-image: none; + align-self: stretch; + flex-shrink: 0; + position: relative; + color: var(--negro, #000000); + text-align: left; + font-family: 'SegoeUi-Regular', sans-serif; + font-size: 18px; + line-height: 100%; + letter-spacing: -0.02em; + font-weight: 400; + border-radius: 10px; } .titulo-texto select.tipo-texto { appearance: none; -webkit-appearance: none; -moz-appearance: none; - background-color: transparent; border: none; padding: 8px 32px 8px 12px; font-family: 'SegoeUi-Regular', sans-serif; @@ -339,9 +346,17 @@ body, box-sizing: border-box; cursor: pointer; transition: background-color 0.2s ease, box-shadow 0.2s ease; + background-image: + linear-gradient(45deg, transparent 50%, #000 50%), + linear-gradient(135deg, #000 50%, transparent 50%); + background-position: + calc(100% - 20px) calc(50% - 3px), + calc(100% - 14px) calc(50% - 3px); + background-size: 6px 6px; + background-repeat: no-repeat; } .titulo-texto::after { - content: ''; + content: none; position: absolute; right: 20px; top: 50%; @@ -358,6 +373,24 @@ body, outline: none; box-shadow: 0 0 0 2px rgba(166,25,48,0.5); } +.titulo-texto select.tipo-texto:active { + background-color: #ececec; +} +.titulo-texto select.tipo-texto option:hover { + background-color: #f5f5f5; +} +.titulo-texto select.tipo-texto option:checked { + background-color: #a61930; + color: #fff; +} +.titulo-texto input[type="color"] { + appearance: none; + border: none; + background: none; + padding: 0; + height: 100%; + cursor: pointer; +} .tarjeta-texto .eliminar { display: flex; align-items: center; @@ -370,51 +403,6 @@ body, .tarjeta-texto .eliminar:hover { background-color: rgba(255,255,255,0.1); } -.titulo-texto::after { - content: none; -} -.titulo-texto select.tipo-texto { - appearance: none; - -webkit-appearance: none; - -moz-appearance: none; - - background-color: #fafafa; - background-image: - linear-gradient(45deg, transparent 50%, #000 50%), - linear-gradient(135deg, #000 50%, transparent 50%); - background-position: - calc(100% - 20px) calc(50% - 3px), - calc(100% - 14px) calc(50% - 3px); - background-size: 6px 6px; - background-repeat: no-repeat; - - padding: 8px 40px 8px 12px; - - border: none; - border-radius: 8px; - width: 100%; - box-sizing: border-box; - - cursor: pointer; - transition: background-color 0.2s ease, box-shadow 0.2s ease; -} -.titulo-texto select.tipo-texto:hover { - background-color: #f0f0f0; -} -.titulo-texto select.tipo-texto:focus { - outline: none; - box-shadow: 0 0 0 2px rgba(166,25,48,0.5); -} -.titulo-texto select.tipo-texto:active { - background-color: #ececec; -} -.titulo-texto select.tipo-texto option:hover { - background-color: #f5f5f5; -} -.titulo-texto select.tipo-texto option:checked { - background-color: #a61930; - color: #fff; -} .tarjeta-texto .eliminar:hover { transform: translateX(2px); } @@ -991,4 +979,18 @@ body, color: #7f8c8d; margin: 4px 0; padding-right: 4px; +} + +.select-tractores{ + display: flex; + width: 100%; + gap: 10px +} + +#color-grafica{ + flex: 0 10 1000px +} + +#tractor-grafica{ + flex: 0 1 1000px } \ No newline at end of file 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 58111e7b..65359e58 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js @@ -85,11 +85,15 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos Icono Gráfica -
- - Icono Gráfica +
+
+ +
+
+ +
Fórmulas
@@ -100,15 +104,6 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos
Eliminar
- `; // Datos disponibles para fórmulas From 1ea8f6124bc90723f2ee44cb481a70bfbf603e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Calder=C3=B3n?= <150750774+Johnccg@users.noreply.github.com> Date: Sun, 22 Jun 2025 17:08:25 -0600 Subject: [PATCH 2/5] =?UTF-8?q?Cambiar=20color=20de=20gr=C3=A1fica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../paginas/analisis/agregarGrafica.js | 63 ++++++++----------- .../paginas/analisis/graficas/crearGrafica.js | 37 ++++++----- 2 files changed, 50 insertions(+), 50 deletions(-) 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 65359e58..0d072b58 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js @@ -9,7 +9,7 @@ const { mostrarAlerta } = require(`${rutaBase}/src/framework/vistas/includes/com const { eliminarCuadroFormulas } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/formulas/eliminarCuadroFormulas.js`); const { crearCuadroFormulas } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js`); const { procesarDatosUniversal } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/procesarDatosUniversal.js`); -const { crearGrafica, verificarExcesoEtiquetas } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js`) +const { crearGrafica, generarDegradadoHaciaBlanco, verificarExcesoEtiquetas } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js`) /* eslint-disable no-unused-vars */ @@ -92,7 +92,7 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos
- +
@@ -181,6 +181,11 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos modificarTipoGrafica(graficaDiv, selectorTipo, tituloGrafica); }) + const entradaColor = tarjetaGrafica.querySelector('#color-entrada') + entradaColor.addEventListener('change', () => { + modificarColor(entradaColor, grafico, 0) + }) + // Obtener el dato del tractor seleccionado para la gráfica const selectorTractor = tarjetaGrafica.querySelector('.tractor-grafica'); selectorTractor.addEventListener('input', async () => { @@ -204,40 +209,6 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos return tarjetaGrafica; } -/** - * Formateador universal para etiquetas de datos según el tipo de gráfica - * @param {*} value - Valor del dato - * @param {*} context - Contexto de Chart.js - * @param {string} tipo - Tipo de gráfica - * @returns {string} - Etiqueta formateada - */ -function formatearEtiquetaUniversal(value, context, tipo) { - const etiqueta = context.chart.data.labels[context.dataIndex]; - - // Para gráficas circulares Y DE BARRAS - SIEMPRE frecuencias con porcentajes/valores - if (tipo === 'pie' || tipo === 'doughnut' || tipo === 'polarArea') { - const datos = context.chart.data.datasets[0].data; - const valorTotal = datos.reduce((total, datapoint) => total + datapoint, 0); - - if (valorTotal === 0) return ''; - - const porcentaje = ((value / valorTotal) * 100).toFixed(1); - return `${etiqueta}\n${value} (${porcentaje}%)`; - } - - // Para gráficas de barras - solo mostrar categoría y frecuencia - if (tipo === 'bar') { - return `${etiqueta}: ${value}`; - } - - // Para gráficas lineales - Mostrar categoría y valor (aunque ya no se mostrarán las etiquetas) - if (etiqueta === 'Resultado') { - return `${etiqueta}\n${value}`; - } else { - return `${etiqueta}: ${value}`; - } -} - /** * Actualiza una gráfica aplicando los datos originales según el nuevo tipo * @param {number} graficaId - ID de la gráfica @@ -400,6 +371,26 @@ function agregarEnPosicion(tarjetaRef, elementoReporte, contenedores, posicion) } } +function modificarColor(entradaColor, grafica, dataset) { + const color = hexARGB(entradaColor.value); + const colores = generarDegradadoHaciaBlanco(color, 7); + + grafica.config.data.datasets[dataset].miColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + grafica.config.data.datasets[dataset].misColores = colores; + + grafica.update() +} + +function hexARGB(colorHex) { + colorHex = colorHex.replace(/^#/, ''); + + const rojo = parseInt(colorHex.substring(0, 2), 16); + const verde = parseInt(colorHex.substring(2, 4), 16); + const azul = parseInt(colorHex.substring(4, 6), 16); + + return [rojo, verde, azul]; +} + module.exports = { agregarGrafica, }; \ No newline at end of file diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js index 0950f35a..c0911107 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js @@ -30,20 +30,24 @@ function crearGrafica(contexto, tipo, color) { data: { labels: ['Sin datos'], // Etiqueta inicial más clara datasets: [{ + miColor: color, + misColores: colores, type: tipo, label: 'Datos', - backgroundColor: fondo => { + backgroundColor: (contexto) => { if (tipo == 'line' || tipo == 'radar') { - return color; + return contexto.dataset.miColor; } else { - return colores[fondo.dataIndex % colores.length]; // Evitar errores de índice + const colores = contexto.dataset.misColores; + return colores[contexto.dataIndex % colores.length]; // Evitar errores de índice } }, - borderColor: borde => { + borderColor: (contexto) => { if (tipo == 'line' || tipo == 'radar') { - return color; + return contexto.dataset.miColor; } else { - return colores[borde.dataIndex % colores.length]; // Evitar errores de índice + const colores = contexto.dataset.misColores; + return colores[contexto.dataIndex % colores.length]; // Evitar errores de índice } }, data: [0] // Dato inicial más claro @@ -68,14 +72,19 @@ function crearGrafica(contexto, tipo, color) { display: true, position: 'top', labels: { - generateLabels: chart => [ - { - text: chart.data.datasets[0].label || 'Datos', - fillStyle: color, - strokeStyle: color, - fontColor: '#333' - } - ], + generateLabels: (chart) => { + const labels = [] + const datasets = chart.data.datasets + datasets.forEach(dataset => { + labels.push({ + text: dataset.label || 'Datos', + fillStyle: dataset.miColor, + strokeStyle: dataset.miColor, + fontColor: '#333' + }) + }) + return labels + }, }, }, datalabels: { From 8ff9ebdd3e7a4743c1b1a41bd0ebe07ad3b7aeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Calder=C3=B3n?= <150750774+Johnccg@users.noreply.github.com> Date: Sun, 22 Jun 2025 17:16:01 -0600 Subject: [PATCH 3/5] Arreglar elementos de estilo --- .../framework/utils/css/paginas/analisis/generarReporte.css | 4 ++-- .../utils/scripts/paginas/analisis/agregarGrafica.js | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) 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 ce76034c..9d4b7041 100644 --- a/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css +++ b/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css @@ -259,7 +259,7 @@ body, position: relative; color: #ffffff; text-align: center; - font-family: "SegoeUi-Regular", sans-serif; + font-family: 'SegoeUi-Regular', sans-serif; font-size: 24px; font-weight: 400; position: relative; @@ -383,7 +383,7 @@ body, background-color: #a61930; color: #fff; } -.titulo-texto input[type="color"] { +.titulo-texto input[type='color'] { appearance: none; border: none; background: none; 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 0d072b58..17e49624 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js @@ -92,7 +92,7 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos
- +
@@ -234,7 +234,6 @@ function actualizarGraficaConTipo(graficaId, nuevoTipo, graficaExistente) { // Crear nueva gráfica const nuevaGrafica = crearGrafica(contexto, nuevoTipo); - console.log(nuevaGrafica.options.plugins.datalabels.display) // Si hay datos originales, reprocesarlos para el nuevo tipo if (datosOriginales) { From 568fb5ee5e5fbbd059b9b134903730e747d8cf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Calder=C3=B3n?= <150750774+Johnccg@users.noreply.github.com> Date: Mon, 23 Jun 2025 16:43:28 -0600 Subject: [PATCH 4/5] =?UTF-8?q?Mantener=20color=20cuando=20se=20cambia=20t?= =?UTF-8?q?ipo=20de=20gr=C3=A1fica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../paginas/analisis/agregarGrafica.js | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) 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 17e49624..ad7164bb 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js @@ -183,7 +183,7 @@ function agregarGrafica(contenedorId, previsualizacionId, tarjetaRef = null, pos const entradaColor = tarjetaGrafica.querySelector('#color-entrada') entradaColor.addEventListener('change', () => { - modificarColor(entradaColor, grafico, 0) + modificarColor(entradaColor, graficaDiv, 0) }) // Obtener el dato del tractor seleccionado para la gráfica @@ -220,22 +220,17 @@ function actualizarGraficaConTipo(graficaId, nuevoTipo, graficaExistente) { const canvasAntiguo = graficaExistente.canvas; const nuevoCanvas = document.createElement('canvas'); canvasAntiguo.parentNode.replaceChild(nuevoCanvas, canvasAntiguo); - const contexto = nuevoCanvas.getContext('2d'); - // Preservar información importante const tituloActual = graficaExistente.options.plugins.title.text; - - // Obtener datos originales si existen + const colorOriginal = graficaExistente.data.datasets[0].miColor + const arregloColor = colorOriginal.match(/\d+/g).map(Number); const datosOriginales = datosOriginalesFormulas.get(graficaId); - // Destruir gráfica actual graficaExistente.destroy(); - // Crear nueva gráfica - const nuevaGrafica = crearGrafica(contexto, nuevoTipo); + const nuevaGrafica = crearGrafica(contexto, nuevoTipo, arregloColor); - // Si hay datos originales, reprocesarlos para el nuevo tipo if (datosOriginales) { const datosRebuild = procesarDatosUniversal( datosOriginales.datos, @@ -249,10 +244,7 @@ function actualizarGraficaConTipo(graficaId, nuevoTipo, graficaExistente) { nuevaGrafica.data.datasets[0].type = nuevoTipo; } - // Restaurar título nuevaGrafica.options.plugins.title.text = tituloActual; - - // Actualizar nuevaGrafica.update(); verificarExcesoEtiquetas(nuevaGrafica); @@ -371,13 +363,15 @@ function agregarEnPosicion(tarjetaRef, elementoReporte, contenedores, posicion) } function modificarColor(entradaColor, grafica, dataset) { + const contexto = grafica.querySelector('canvas').getContext('2d'); + const graficaOriginal = Chart.getChart(contexto); const color = hexARGB(entradaColor.value); const colores = generarDegradadoHaciaBlanco(color, 7); - grafica.config.data.datasets[dataset].miColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; - grafica.config.data.datasets[dataset].misColores = colores; + graficaOriginal.config.data.datasets[dataset].miColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`; + graficaOriginal.config.data.datasets[dataset].misColores = colores; - grafica.update() + graficaOriginal.update() } function hexARGB(colorHex) { From caade6bb7fa7c3e94c0806e576b5852edf92d153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Calder=C3=B3n?= <150750774+Johnccg@users.noreply.github.com> Date: Tue, 24 Jun 2025 10:03:50 -0600 Subject: [PATCH 5/5] =?UTF-8?q?Agregar=20documentaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/paginas/analisis/agregarGrafica.js | 14 ++++++++++++++ .../paginas/analisis/graficas/crearGrafica.js | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) 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 ad7164bb..c156fd4b 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/agregarGrafica.js @@ -362,6 +362,14 @@ function agregarEnPosicion(tarjetaRef, elementoReporte, contenedores, posicion) } } +/** + * Modifica el color de un dataset en una gráfica Chart.js, actualizando su color principal + * y generando un degradado hacia blanco. + * + * @param {HTMLInputElement} entradaColor - Elemento input de tipo color del cual se obtiene el valor hexadecimal. + * @param {HTMLDivElement} grafica - Elemento HTML que contiene el canvas de la gráfica Chart.js. + * @param {number} dataset - Índice del dataset dentro de la gráfica que se desea modificar. + */ function modificarColor(entradaColor, grafica, dataset) { const contexto = grafica.querySelector('canvas').getContext('2d'); const graficaOriginal = Chart.getChart(contexto); @@ -374,6 +382,12 @@ function modificarColor(entradaColor, grafica, dataset) { graficaOriginal.update() } +/** + * Convierte un valor hexadecimal de color en un arreglo con los valores RGB correspondientes. + * + * @param {string} colorHex - Color en formato hexadecimal (por ejemplo: "#FF5733" o "FF5733"). + * @returns {number[]} Arreglo con tres números que representan los componentes R, G y B (en ese orden). + */ function hexARGB(colorHex) { colorHex = colorHex.replace(/^#/, ''); diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js index c0911107..ccd6d2c1 100644 --- a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js +++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js @@ -190,7 +190,13 @@ function crearGrafica(contexto, tipo, color) { return grafico; } - +/** + * Verifica si una gráfica de tipo bar, pie, doughnut o polarArea + * tiene más de 20 etiquetas. En caso afirmativo, muestra una alerta advirtiendo + * que esto puede afectar la visualización o interpretación de la gráfica. + * + * @param {Chart} grafica - Instancia de una gráfica de Chart.js que se desea verificar. + */ function verificarExcesoEtiquetas(grafica) { const tipo = grafica.config.type; const etiquetas = grafica.data.labels || [];