Feat Workers Prioridades y Nivel Serilog
This commit is contained in:
		| @@ -7,6 +7,7 @@ import { ConfiguracionGeneral } from './ConfiguracionGeneral'; | ||||
| import { BancasManager } from './BancasManager'; | ||||
| import { LogoOverridesManager } from './LogoOverridesManager'; | ||||
| import { CandidatoOverridesManager } from './CandidatoOverridesManager'; | ||||
| import { WorkerManager } from './WorkerManager'; | ||||
|  | ||||
| export const DashboardPage = () => { | ||||
|     const { logout } = useAuth(); | ||||
| @@ -35,6 +36,8 @@ export const DashboardPage = () => { | ||||
|                 </div> | ||||
|                 <ConfiguracionGeneral /> | ||||
|                 <BancasManager /> | ||||
|                 <hr style={{ margin: '2rem 0' }}/> | ||||
|                 <WorkerManager /> | ||||
|             </main> | ||||
|         </div> | ||||
|     ); | ||||
|   | ||||
							
								
								
									
										140
									
								
								Elecciones-Web/frontend-admin/src/components/WorkerManager.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Elecciones-Web/frontend-admin/src/components/WorkerManager.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { useQuery, useQueryClient } from '@tanstack/react-query'; | ||||
| import { getConfiguracion, updateConfiguracion, updateLoggingLevel } from '../services/apiService'; | ||||
| import type { ConfiguracionResponse } from '../services/apiService'; | ||||
|  | ||||
| // --- Componente de Switch reutilizable para la UI --- | ||||
| const Switch = ({ label, isChecked, onChange }: { label: string, isChecked: boolean, onChange: (checked: boolean) => void }) => ( | ||||
|     <label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer' }}> | ||||
|         <input type="checkbox" checked={isChecked} onChange={e => onChange(e.target.checked)} /> | ||||
|         {label} | ||||
|     </label> | ||||
| ); | ||||
|  | ||||
| export const WorkerManager = () => { | ||||
|     const queryClient = useQueryClient(); | ||||
|  | ||||
|     // Estados locales para manejar los valores de la UI | ||||
|     const [resultadosActivado, setResultadosActivado] = useState(true); | ||||
|     const [bajasActivado, setBajasActivado] = useState(true); | ||||
|     const [prioridad, setPrioridad] = useState('Resultados'); | ||||
|     const [loggingLevel, setLoggingLevel] = useState('Information'); | ||||
|      | ||||
|     // Query para obtener la configuración actual desde la API | ||||
|     const { data: configData, isLoading } = useQuery<ConfiguracionResponse>({ | ||||
|         queryKey: ['configuracion'], | ||||
|         queryFn: getConfiguracion, | ||||
|     }); | ||||
|  | ||||
|     // useEffect para sincronizar el estado local con los datos de la API una vez cargados | ||||
|     useEffect(() => { | ||||
|         if (configData) { | ||||
|             setResultadosActivado(configData.Worker_Resultados_Activado === 'true'); | ||||
|             setBajasActivado(configData.Worker_Bajas_Activado === 'true'); | ||||
|             setPrioridad(configData.Worker_Prioridad || 'Resultados'); | ||||
|             setLoggingLevel(configData.Logging_Level || 'Information'); | ||||
|         } | ||||
|     }, [configData]); | ||||
|  | ||||
|     const handleSave = async () => { | ||||
|         try { | ||||
|             // Creamos dos promesas separadas, una para la config general y otra para el logging | ||||
|             const configPromise = updateConfiguracion({ | ||||
|                 ...configData, | ||||
|                 'Worker_Resultados_Activado': resultadosActivado.toString(), | ||||
|                 'Worker_Bajas_Activado': bajasActivado.toString(), | ||||
|                 'Worker_Prioridad': prioridad, | ||||
|                 'Logging_Level': loggingLevel, | ||||
|             }); | ||||
|              | ||||
|             // La llamada al endpoint de logging-level es la que cambia el nivel EN VIVO. | ||||
|             const loggingPromise = updateLoggingLevel({ level: loggingLevel }); | ||||
|  | ||||
|             // Ejecutamos ambas en paralelo | ||||
|             await Promise.all([configPromise, loggingPromise]); | ||||
|              | ||||
|             queryClient.invalidateQueries({ queryKey: ['configuracion'] }); | ||||
|             alert('Configuración de Workers y Logging guardada.'); | ||||
|  | ||||
|         } catch (error) { | ||||
|             console.error("Error al guardar la configuración:", error); | ||||
|             alert('Error al guardar la configuración.'); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     const isPrioridadDisabled = !resultadosActivado || !bajasActivado; | ||||
|  | ||||
|     if (isLoading) { | ||||
|         return <div className="admin-module"><h3>Gestión de Workers</h3><p>Cargando configuración...</p></div>; | ||||
|     } | ||||
|  | ||||
|     return ( | ||||
|         <div className="admin-module"> | ||||
|             <h3>Gestión de Workers</h3> | ||||
|             <p>Controla el comportamiento de los procesos de captura de datos.</p> | ||||
|             <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', borderTop: '1px solid #eee', paddingTop: '1rem' }}> | ||||
|                  | ||||
|                 {/* --- Switches On/Off --- */} | ||||
|                 <div style={{ display: 'flex', alignSelf: 'center', gap: '2rem' }}> | ||||
|                     <Switch  | ||||
|                         label="Activar Worker de Resultados" | ||||
|                         isChecked={resultadosActivado} | ||||
|                         onChange={setResultadosActivado} | ||||
|                     /> | ||||
|                     <Switch  | ||||
|                         label="Activar Worker de Bancas/Telegramas" | ||||
|                         isChecked={bajasActivado} | ||||
|                         onChange={setBajasActivado} | ||||
|                     /> | ||||
|                 </div> | ||||
|  | ||||
|                  {/* --- Contenedor para Selectores --- */} | ||||
|                 <div style={{ display: 'flex', gap: '2rem', alignSelf:'center', alignItems: 'flex-start' }}> | ||||
|                     {/* --- Selector de Prioridad --- */} | ||||
|                     <div> | ||||
|                         <label htmlFor="prioridad-select" style={{ display: 'block', marginBottom: '0.5rem', fontWeight: 500 }}> | ||||
|                             Prioridad (si ambos están activos) | ||||
|                         </label> | ||||
|                         <select  | ||||
|                             id="prioridad-select" | ||||
|                             value={prioridad}  | ||||
|                             onChange={e => setPrioridad(e.target.value)} | ||||
|                             disabled={isPrioridadDisabled} | ||||
|                             style={{ padding: '0.5rem', minWidth: '200px' }} | ||||
|                         > | ||||
|                             <option value="Resultados">Resultados (Noche Electoral)</option> | ||||
|                             <option value="Telegramas">Telegramas (Post-Escrutinio)</option> | ||||
|                         </select> | ||||
|                         {isPrioridadDisabled && <small style={{ display: 'block', marginTop: '0.5rem', color: '#666' }}>Activar ambos workers para elegir prioridad.</small>} | ||||
|                     </div> | ||||
|  | ||||
|                     {/* --- NUEVO: Selector de Nivel de Logging --- */} | ||||
|                     <div> | ||||
|                         <label htmlFor="logging-select" style={{ display: 'block', marginBottom: '0.5rem', fontWeight: 500 }}> | ||||
|                             Nivel de Logging (En vivo) | ||||
|                         </label> | ||||
|                         <select | ||||
|                             id="logging-select" | ||||
|                             value={loggingLevel} | ||||
|                             onChange={e => setLoggingLevel(e.target.value)} | ||||
|                             style={{ padding: '0.5rem', minWidth: '200px' }} | ||||
|                         > | ||||
|                             <option value="Verbose">Verbose (Máximo detalle)</option> | ||||
|                             <option value="Debug">Debug</option> | ||||
|                             <option value="Information">Information (Normal)</option> | ||||
|                             <option value="Warning">Warning (Advertencias)</option> | ||||
|                             <option value="Error">Error</option> | ||||
|                             <option value="Fatal">Fatal (Críticos)</option> | ||||
|                         </select> | ||||
|                         <small style={{ display: 'block', marginTop: '0.5rem', color: '#666' }}>Cambia el nivel de log en tiempo real.</small> | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|                 {/* --- Botón de Guardar --- */} | ||||
|                 <div style={{ marginTop: '1rem' }}> | ||||
|                     <button onClick={handleSave}>Guardar Toda la Configuración</button> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
| @@ -121,10 +121,10 @@ export const updateLogos = async (data: LogoAgrupacionCategoria[]): Promise<void | ||||
| }; | ||||
|  | ||||
| export const getMunicipiosForAdmin = async (): Promise<MunicipioSimple[]> => { | ||||
|     // Ahora usa adminApiClient, que apunta a /api/admin/ | ||||
|     // La URL final será /api/admin/catalogos/municipios | ||||
|     const response = await adminApiClient.get('/catalogos/municipios'); | ||||
|     return response.data; | ||||
|   // Ahora usa adminApiClient, que apunta a /api/admin/ | ||||
|   // La URL final será /api/admin/catalogos/municipios | ||||
|   const response = await adminApiClient.get('/catalogos/municipios'); | ||||
|   return response.data; | ||||
| }; | ||||
|  | ||||
| // 6. Overrides de Candidatos | ||||
| @@ -135,4 +135,14 @@ export const getCandidatos = async (): Promise<CandidatoOverride[]> => { | ||||
|  | ||||
| export const updateCandidatos = async (data: CandidatoOverride[]): Promise<void> => { | ||||
|   await adminApiClient.put('/candidatos', data); | ||||
| }; | ||||
|  | ||||
| // 7. Gestión de Logging | ||||
| export interface UpdateLoggingLevelData { | ||||
|   level: string; | ||||
| } | ||||
|  | ||||
| export const updateLoggingLevel = async (data: UpdateLoggingLevelData): Promise<void> => { | ||||
|   // Este endpoint es específico, no es parte de la configuración general | ||||
|   await adminApiClient.put(`/logging-level`, data); | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user