Feat Selector Modo Tabla
This commit is contained in:
		| @@ -2,9 +2,20 @@ import { useState, useMemo, useEffect } from 'react'; | ||||
| import { useQuery } from '@tanstack/react-query'; | ||||
| import Select from 'react-select'; | ||||
| import { getSeccionesElectorales, getRankingMunicipiosPorSeccion } from '../apiService'; | ||||
| import type { MunicipioSimple, ApiResponseRankingMunicipio } from '../types/types'; | ||||
| import './ResultadosTablaSeccionWidget.css'; // Reutilizamos el mismo estilo | ||||
| import React from 'react'; | ||||
| import type { MunicipioSimple, ApiResponseRankingMunicipio, RankingPartido } from '../types/types'; | ||||
| import './ResultadosTablaSeccionWidget.css';  | ||||
|  | ||||
| type DisplayMode = 'porcentaje' | 'votos' | 'ambos'; | ||||
| type DisplayOption = { | ||||
|     value: DisplayMode; | ||||
|     label: string; | ||||
| }; | ||||
|  | ||||
| const displayModeOptions: readonly DisplayOption[] = [ | ||||
|     { value: 'porcentaje', label: 'Ver Porcentajes' }, | ||||
|     { value: 'votos', label: 'Ver Votos' }, | ||||
|     { value: 'ambos', label: 'Ver Ambos' }, | ||||
| ]; | ||||
|  | ||||
| const customSelectStyles = { | ||||
|   control: (base: any) => ({ ...base, minWidth: '200px', border: '1px solid #ced4da', boxShadow: 'none', '&:hover': { borderColor: '#86b7fe' } }), | ||||
| @@ -12,10 +23,36 @@ const customSelectStyles = { | ||||
| }; | ||||
|  | ||||
| const formatPercent = (porcentaje: number) => `${porcentaje.toFixed(2).replace('.', ',')}%`; | ||||
| // Nueva función para formatear votos con separador de miles | ||||
| const formatVotos = (votos: number) => votos.toLocaleString('es-AR'); | ||||
|  | ||||
| // --- NUEVO COMPONENTE HELPER PARA RENDERIZAR CELDAS --- | ||||
| const CellRenderer = ({ partido, mode }: { partido?: RankingPartido, mode: DisplayMode }) => { | ||||
|     if (!partido) { | ||||
|         return <span>-</span>; | ||||
|     } | ||||
|  | ||||
|     switch (mode) { | ||||
|         case 'votos': | ||||
|             return <span>{formatVotos(partido.votos)}</span>; | ||||
|         case 'ambos': | ||||
|             return ( | ||||
|                 <div className="cell-ambos"> | ||||
|                     <span>{formatVotos(partido.votos)}</span> | ||||
|                     <small>{formatPercent(partido.porcentaje)}</small> | ||||
|                 </div> | ||||
|             ); | ||||
|         case 'porcentaje': | ||||
|         default: | ||||
|             return <span>{formatPercent(partido.porcentaje)}</span>; | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| export const ResultadosRankingMunicipioWidget = () => { | ||||
|   const [secciones, setSecciones] = useState<MunicipioSimple[]>([]); | ||||
|   const [selectedSeccion, setSelectedSeccion] = useState<{ value: string; label: string } | null>(null); | ||||
|   const [displayMode, setDisplayMode] = useState<DisplayOption>(displayModeOptions[0]); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const fetchSecciones = async () => { | ||||
| @@ -48,91 +85,79 @@ export const ResultadosRankingMunicipioWidget = () => { | ||||
|   }); | ||||
|  | ||||
|   return ( | ||||
|     <div className="tabla-resultados-widget"> | ||||
|       <div className="tabla-header"> | ||||
|         <h3>Resultados por Municipio</h3> | ||||
|         <Select | ||||
|           options={seccionOptions} | ||||
|           value={selectedSeccion} | ||||
|           onChange={(option) => setSelectedSeccion(option)} | ||||
|           isLoading={secciones.length === 0} | ||||
|           styles={customSelectStyles} | ||||
|           isSearchable={false} | ||||
|         /> | ||||
|       </div> | ||||
|         <div className="tabla-resultados-widget"> | ||||
|             <div className="tabla-header"> | ||||
|                 <h3>Resultados por Municipio</h3> | ||||
|                 <div className="header-filters"> | ||||
|                     <Select | ||||
|                         options={displayModeOptions} | ||||
|                         value={displayMode} | ||||
|                          | ||||
|                         // --- CORRECCIÓN EN ONCHANGE --- | ||||
|                         // 'option' ahora es del tipo correcto, por lo que no necesitamos aserción. | ||||
|                         onChange={(option) => setDisplayMode(option as DisplayOption)} | ||||
|                          | ||||
|                         styles={customSelectStyles} | ||||
|                         isSearchable={false} | ||||
|                     /> | ||||
|                     <Select | ||||
|                         options={seccionOptions} | ||||
|                         value={selectedSeccion} | ||||
|                         onChange={(option) => setSelectedSeccion(option)} | ||||
|                         isLoading={secciones.length === 0} | ||||
|                         styles={customSelectStyles} | ||||
|                         isSearchable={false} | ||||
|                     /> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|       <div className="tabla-container"> | ||||
|         {isLoading ? <p>Cargando...</p> : !rankingData || rankingData.categorias.length === 0 ? <p>No hay datos.</p> : ( | ||||
|           <table> | ||||
|             <thead> | ||||
|               {/* --- Fila 1: Nombres de Categorías --- */} | ||||
|               <tr> | ||||
|                 <th rowSpan={2} className="sticky-col municipio-header">Municipio</th> | ||||
|                 {rankingData.categorias.map(cat => ( | ||||
|                   // Cada categoría ahora ocupa 4 columnas (1° Partido, 1° %, 2° Partido, 2° %) | ||||
|                   <th key={cat.id} colSpan={4} className="categoria-header"> | ||||
|                     {cat.nombre} | ||||
|                   </th> | ||||
|                 ))} | ||||
|               </tr> | ||||
|               {/* --- Fila 2: Puestos y % --- */} | ||||
|               <tr> | ||||
|                 {rankingData.categorias.flatMap(cat => [ | ||||
|                   <th key={`${cat.id}-p1`} colSpan={2} className="puesto-header">1° Puesto</th>, | ||||
|                   <th key={`${cat.id}-p2`} colSpan={2} className="puesto-header category-divider-header">2° Puesto</th> | ||||
|                 ])} | ||||
|               </tr> | ||||
|               {/* Fila 3: Sub-cabeceras (Partido, %) */} | ||||
|               <tr> | ||||
|                 <th  className="sub-header-init" /> | ||||
|                 { | ||||
|                   // Usamos un bucle map simple en lugar de flatMap. | ||||
|                   // React manejará la creación de un array de nodos sin problemas. | ||||
|                   rankingData.categorias.map(cat => ( | ||||
|                     // Usamos un Fragmento (<>) para agrupar los 4 <th> de cada categoría | ||||
|                     // sin añadir un nodo extra al DOM. | ||||
|                     <React.Fragment key={`subheaders-${cat.id}`}> | ||||
|                       <th className="sub-header">Partido</th> | ||||
|                       <th className="sub-header">%</th> | ||||
|                       <th className="sub-header category-divider-header">Partido</th> | ||||
|                       <th className="sub-header">%</th> | ||||
|                     </React.Fragment> | ||||
|                   )) | ||||
|                 } | ||||
|               </tr> | ||||
|             </thead> | ||||
|             <tbody> | ||||
|               {rankingData.resultados.map(municipio => ( | ||||
|                 <tr key={municipio.municipioId}> | ||||
|                   <td className="sticky-col">{municipio.municipioNombre}</td> | ||||
|                   {rankingData.categorias.flatMap(cat => { | ||||
|                     const resCategoria = municipio.resultadosPorCategoria[cat.id]; | ||||
|                     const primerPuesto = resCategoria?.ranking[0]; | ||||
|                     const segundoPuesto = resCategoria?.ranking[1]; | ||||
|             <div className="tabla-container"> | ||||
|                 {isLoading ? <p>Cargando...</p> : !rankingData || rankingData.categorias.length === 0 ? <p>No hay datos.</p> : ( | ||||
|                     <table> | ||||
|                         <thead> | ||||
|                             <tr> | ||||
|                                 <th rowSpan={2} className="sticky-col municipio-header">Municipio</th> | ||||
|                                 {rankingData.categorias.map(cat => ( | ||||
|                                     <th key={cat.id} colSpan={2} className="categoria-header">{cat.nombre}</th> | ||||
|                                 ))} | ||||
|                             </tr> | ||||
|                             <tr> | ||||
|                                 {rankingData.categorias.flatMap(cat => [ | ||||
|                                     <th key={`${cat.id}-1`} className="partido-header">1° Puesto</th>, | ||||
|                                     <th key={`${cat.id}-2`} className="partido-header category-divider-header">2° Puesto</th> | ||||
|                                 ])} | ||||
|                             </tr> | ||||
|                         </thead> | ||||
|                         <tbody> | ||||
|                             {rankingData.resultados.map(municipio => ( | ||||
|                                 <tr key={municipio.municipioId}> | ||||
|                                     <td className="sticky-col">{municipio.municipioNombre}</td> | ||||
|                                     {rankingData.categorias.flatMap(cat => { | ||||
|                                         const resCategoria = municipio.resultadosPorCategoria[cat.id]; | ||||
|                                         const primerPuesto = resCategoria?.ranking[0]; | ||||
|                                         const segundoPuesto = resCategoria?.ranking[1]; | ||||
|  | ||||
|                     return [ | ||||
|                       // --- Celdas para el 1° Puesto --- | ||||
|                       <td key={`${municipio.municipioId}-${cat.id}-p1-partido`} className="cell-partido"> | ||||
|                         {primerPuesto?.nombreCorto || '-'} | ||||
|                       </td>, | ||||
|                       <td key={`${municipio.municipioId}-${cat.id}-p1-porc`} className="cell-porcentaje"> | ||||
|                         {primerPuesto ? formatPercent(primerPuesto.porcentaje) : '-'} | ||||
|                       </td>, | ||||
|                       // --- Celdas para el 2° Puesto --- | ||||
|                       <td key={`${municipio.municipioId}-${cat.id}-p2-partido`} className="cell-partido category-divider"> | ||||
|                         {segundoPuesto?.nombreCorto || '-'} | ||||
|                       </td>, | ||||
|                       <td key={`${municipio.municipioId}-${cat.id}-p2-porc`} className="cell-porcentaje"> | ||||
|                         {segundoPuesto ? formatPercent(segundoPuesto.porcentaje) : '-'} | ||||
|                       </td> | ||||
|                     ]; | ||||
|                   })} | ||||
|                 </tr> | ||||
|               ))} | ||||
|             </tbody> | ||||
|           </table> | ||||
|         )} | ||||
|       </div> | ||||
|     </div> | ||||
|   ); | ||||
|                                         return [ | ||||
|                                             <td key={`${municipio.municipioId}-${cat.id}-1`} className="category-divider"> | ||||
|                                                 <div className="cell-content"> | ||||
|                                                     <span className="cell-partido-nombre">{primerPuesto?.nombreCorto || '-'}</span> | ||||
|                                                     <CellRenderer partido={primerPuesto} mode={displayMode.value} /> | ||||
|                                                 </div> | ||||
|                                             </td>, | ||||
|                                             <td key={`${municipio.municipioId}-${cat.id}-2`}> | ||||
|                                                 <div className="cell-content"> | ||||
|                                                     <span className="cell-partido-nombre">{segundoPuesto?.nombreCorto || '-'}</span> | ||||
|                                                     <CellRenderer partido={segundoPuesto} mode={displayMode.value} /> | ||||
|                                                 </div> | ||||
|                                             </td> | ||||
|                                         ]; | ||||
|                                     })} | ||||
|                                 </tr> | ||||
|                             ))} | ||||
|                         </tbody> | ||||
|                     </table> | ||||
|                 )} | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
| @@ -23,6 +23,11 @@ | ||||
|     border-bottom: 1px solid #dee2e6; | ||||
| } | ||||
|  | ||||
| .header-filters { | ||||
|     display: flex; | ||||
|     gap: 1rem; | ||||
| } | ||||
|  | ||||
| .tabla-header h3 { | ||||
|     margin: 0; | ||||
|     font-size: 1.25rem; | ||||
| @@ -173,4 +178,32 @@ | ||||
| } | ||||
| .tabla-container tbody tr:nth-of-type(even) td.sticky-col { | ||||
|     background-color: #f8f9fa; /* Para que coincida con el fondo de la fila */ | ||||
| } | ||||
|  | ||||
| /* Contenedor principal de la celda para alinear contenido */ | ||||
| .cell-content { | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|     align-items: baseline; | ||||
| } | ||||
|  | ||||
| /* Nombre del partido dentro de la celda */ | ||||
| .cell-partido-nombre { | ||||
|     text-align: left; | ||||
|     font-size: 0.85rem; | ||||
|     padding-right: 1rem; | ||||
| } | ||||
|  | ||||
| /* Contenedor para la vista "ambos" (votos y porcentaje) */ | ||||
| .cell-ambos { | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     align-items: flex-end; | ||||
|     text-align: right; | ||||
|     line-height: 1.2; | ||||
| } | ||||
|  | ||||
| .cell-ambos small { | ||||
|     font-size: 0.8em; | ||||
|     color: #6c757d; | ||||
| } | ||||
| @@ -188,6 +188,7 @@ export interface TablaDetalladaResultadoMunicipio { | ||||
| export interface RankingPartido { | ||||
|   nombreCorto: string; | ||||
|   porcentaje: number; | ||||
|   votos: number; | ||||
| } | ||||
|  | ||||
| export interface RankingCategoria { | ||||
|   | ||||
| @@ -965,43 +965,37 @@ public class ResultadosController : ControllerBase | ||||
|  | ||||
|         // 3. Procesar los datos por cada municipio | ||||
|         var resultadosPorMunicipio = municipios.Select(municipio => | ||||
|         { | ||||
|             // Filtramos los resultados solo para el municipio actual | ||||
|             var resultadosDelMunicipio = resultadosCrudos.Where(r => r.AmbitoGeograficoId == municipio.Id); | ||||
|     { | ||||
|         var resultadosDelMunicipio = resultadosCrudos.Where(r => r.AmbitoGeograficoId == municipio.Id); | ||||
|  | ||||
|             // Agrupamos por categoría (Senadores, Concejales, etc.) | ||||
|             var resultadosPorCategoria = resultadosDelMunicipio | ||||
|                 .GroupBy(r => r.CategoriaId) | ||||
|                 .Select(g => | ||||
|                 { | ||||
|                     var totalVotosCategoria = (decimal)g.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|                     // Obtenemos los 2 partidos con más votos para esta categoría EN ESTE MUNICIPIO | ||||
|                     var ranking = g | ||||
|                         .OrderByDescending(r => r.CantidadVotos) | ||||
|                         .Take(2) | ||||
|                         .Select(r => new | ||||
|                         { | ||||
|                             NombreCorto = r.AgrupacionPolitica.NombreCorto ?? r.AgrupacionPolitica.Nombre, | ||||
|                             Porcentaje = totalVotosCategoria > 0 ? (r.CantidadVotos / totalVotosCategoria) * 100 : 0 | ||||
|                         }) | ||||
|                         .ToList(); | ||||
|  | ||||
|                     return new | ||||
|                     { | ||||
|                         CategoriaId = g.Key, | ||||
|                         Ranking = ranking | ||||
|                     }; | ||||
|                 }) | ||||
|                 .ToDictionary(r => r.CategoriaId); // Lo convertimos a diccionario para fácil acceso | ||||
|  | ||||
|             return new | ||||
|         var resultadosPorCategoria = resultadosDelMunicipio | ||||
|             .GroupBy(r => r.CategoriaId) | ||||
|             .Select(g => | ||||
|             { | ||||
|                 MunicipioId = municipio.Id, | ||||
|                 MunicipioNombre = municipio.Nombre, | ||||
|                 ResultadosPorCategoria = resultadosPorCategoria | ||||
|             }; | ||||
|         }).ToList(); | ||||
|                 var totalVotosCategoria = (decimal)g.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|                 var ranking = g | ||||
|                     .OrderByDescending(r => r.CantidadVotos) | ||||
|                     .Take(2) | ||||
|                     .Select(r => new | ||||
|                     { | ||||
|                         NombreCorto = r.AgrupacionPolitica.NombreCorto ?? r.AgrupacionPolitica.Nombre, | ||||
|                         Porcentaje = totalVotosCategoria > 0 ? (r.CantidadVotos / totalVotosCategoria) * 100 : 0, | ||||
|                         Votos = r.CantidadVotos // <-- AÑADIR ESTE CAMPO | ||||
|                     }) | ||||
|                     .ToList(); | ||||
|  | ||||
|                 return new { CategoriaId = g.Key, Ranking = ranking }; | ||||
|             }) | ||||
|             .ToDictionary(r => r.CategoriaId); // Lo convertimos a diccionario para fácil acceso | ||||
|  | ||||
|         return new | ||||
|         { | ||||
|             MunicipioId = municipio.Id, | ||||
|             MunicipioNombre = municipio.Nombre, | ||||
|             ResultadosPorCategoria = resultadosPorCategoria | ||||
|         }; | ||||
|     }).ToList(); | ||||
|  | ||||
|         // Devolvemos las categorías que tuvieron resultados en esta sección para construir la cabecera | ||||
|         var categoriasMap = await _dbContext.CategoriasElectorales.AsNoTracking().ToDictionaryAsync(c => c.Id); | ||||
|   | ||||
| @@ -14,7 +14,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+c105106f3b420a1c1c19b125cdf5c31e59bfbe3b")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","Mo7tdPQiZw6/WSnll8t7xy4SU1EoFW4N6EN7JftvBYs=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","eix/dR870pRbtIGVeoF7YpZlG47M4PrBntvgxdO1oDM="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DJ3OEGlGm0XqehqAshsJPdHddx35xQrKqTYPlJ\u002BmgK0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","VC4RrsY3drpYvDr8ENTx68n\u002BklPRBIIs4arkXFsPT3E="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","Mo7tdPQiZw6/WSnll8t7xy4SU1EoFW4N6EN7JftvBYs=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","eix/dR870pRbtIGVeoF7YpZlG47M4PrBntvgxdO1oDM="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DJ3OEGlGm0XqehqAshsJPdHddx35xQrKqTYPlJ\u002BmgK0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","VC4RrsY3drpYvDr8ENTx68n\u002BklPRBIIs4arkXFsPT3E="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -13,7 +13,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+c105106f3b420a1c1c19b125cdf5c31e59bfbe3b")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -13,7 +13,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+c105106f3b420a1c1c19b125cdf5c31e59bfbe3b")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -13,7 +13,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+c105106f3b420a1c1c19b125cdf5c31e59bfbe3b")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user