Fix Boostrap y Try Cache
This commit is contained in:
@@ -1,24 +1,33 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
# Añadimos una ubicación específica para los archivos .mjs
|
# --- NUEVO BLOQUE ESPECÍFICO PARA BOOTSTRAP.JS ---
|
||||||
location ~ \.mjs$ {
|
location = /bootstrap.js {
|
||||||
# Incluimos los tipos MIME por defecto para que Nginx pueda inferir otros tipos si es necesario
|
# Esta cabecera le dice a los proxies que deben revalidar el archivo
|
||||||
include /etc/nginx/mime.types;
|
# con el servidor de origen antes de servirlo desde la caché.
|
||||||
# Forzamos explícitamente el tipo de contenido para esta ubicación
|
add_header Cache-Control "no-cache, must-revalidate";
|
||||||
default_type application/javascript;
|
|
||||||
|
# 'expires off' es otra capa de seguridad para evitar que se cachee
|
||||||
|
expires off;
|
||||||
|
|
||||||
|
# Intenta servir el archivo. Si no existe, devuelve 404.
|
||||||
|
try_files $uri =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Bloque para otros activos estáticos (con hash) que SÍ pueden ser cacheados agresivamente
|
||||||
|
location ~* \.(?:js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
||||||
|
# Estos archivos cambian de nombre en cada build, así que pueden
|
||||||
|
# ser cacheados por mucho tiempo sin riesgo.
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bloque para la SPA
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|svg|woff|woff2)$ {
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
25
Elecciones-Web/frontend/package-lock.json
generated
25
Elecciones-Web/frontend/package-lock.json
generated
@@ -21,7 +21,8 @@
|
|||||||
"react-pdf": "^10.1.0",
|
"react-pdf": "^10.1.0",
|
||||||
"react-select": "^5.10.2",
|
"react-select": "^5.10.2",
|
||||||
"react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support",
|
"react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support",
|
||||||
"react-tooltip": "^5.29.1"
|
"react-tooltip": "^5.29.1",
|
||||||
|
"topojson-client": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.33.0",
|
"@eslint/js": "^9.33.0",
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
"@types/react": "^19.1.10",
|
"@types/react": "^19.1.10",
|
||||||
"@types/react-dom": "^19.1.7",
|
"@types/react-dom": "^19.1.7",
|
||||||
"@types/react-select": "^5.0.0",
|
"@types/react-select": "^5.0.0",
|
||||||
|
"@types/topojson-client": "^3.1.5",
|
||||||
"@vitejs/plugin-react": "^5.0.0",
|
"@vitejs/plugin-react": "^5.0.0",
|
||||||
"eslint": "^9.33.0",
|
"eslint": "^9.33.0",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
@@ -2215,6 +2217,27 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/topojson-client": {
|
||||||
|
"version": "3.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz",
|
||||||
|
"integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*",
|
||||||
|
"@types/topojson-specification": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/topojson-specification": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.40.0",
|
"version": "8.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz",
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
"react-pdf": "^10.1.0",
|
"react-pdf": "^10.1.0",
|
||||||
"react-select": "^5.10.2",
|
"react-select": "^5.10.2",
|
||||||
"react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support",
|
"react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support",
|
||||||
"react-tooltip": "^5.29.1"
|
"react-tooltip": "^5.29.1",
|
||||||
|
"topojson-client": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.33.0",
|
"@eslint/js": "^9.33.0",
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
"@types/react": "^19.1.10",
|
"@types/react": "^19.1.10",
|
||||||
"@types/react-dom": "^19.1.7",
|
"@types/react-dom": "^19.1.7",
|
||||||
"@types/react-select": "^5.0.0",
|
"@types/react-select": "^5.0.0",
|
||||||
|
"@types/topojson-client": "^3.1.5",
|
||||||
"@vitejs/plugin-react": "^5.0.0",
|
"@vitejs/plugin-react": "^5.0.0",
|
||||||
"eslint": "^9.33.0",
|
"eslint": "^9.33.0",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
|
|||||||
13
Elecciones-Web/frontend/public/bootstrap.js
vendored
13
Elecciones-Web/frontend/public/bootstrap.js
vendored
@@ -63,12 +63,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. Una vez cargado, llamar a la función de renderizado
|
// 5. Una vez cargado, llamar a la función de renderizado
|
||||||
// 5. Una vez cargado, llamar a la función de renderizado
|
|
||||||
console.log('Bootstrap: JS principal cargado. Buscando EleccionesWidgets.render...');
|
|
||||||
|
|
||||||
if (window.EleccionesWidgets && typeof window.EleccionesWidgets.render === 'function') {
|
if (window.EleccionesWidgets && typeof window.EleccionesWidgets.render === 'function') {
|
||||||
console.log('Bootstrap: La función render() FUE ENCONTRADA. Se procederá a llamarla.');
|
console.log('Bootstrap: La función render existe. Llamando ahora.');
|
||||||
window.EleccionesWidgets.render();
|
// Encontramos los contenedores aquí y pasamos sus props.
|
||||||
|
const widgetContainers = document.querySelectorAll('[data-elecciones-widget]');
|
||||||
|
widgetContainers.forEach(container => {
|
||||||
|
// 'dataset' es un objeto que contiene todos los atributos data-*
|
||||||
|
// container.dataset = { eleccionesWidget: 'mapa-municipios', focoMunicipio: 'LA PLATA' }
|
||||||
|
window.EleccionesWidgets.render(container, container.dataset);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('Bootstrap: ERROR CRÍTICO - La función render() NO SE ENCONTRÓ en window.EleccionesWidgets.');
|
console.error('Bootstrap: ERROR CRÍTICO - La función render() NO SE ENCONTRÓ en window.EleccionesWidgets.');
|
||||||
console.log('Bootstrap: Contenido de window.EleccionesWidgets:', window.EleccionesWidgets);
|
console.log('Bootstrap: Contenido de window.EleccionesWidgets:', window.EleccionesWidgets);
|
||||||
|
|||||||
@@ -5,19 +5,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 6em;
|
|
||||||
padding: 1.5em;
|
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.react:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-spin {
|
@keyframes logo-spin {
|
||||||
from {
|
from {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
|
|||||||
@@ -45,6 +45,42 @@ export const DevApp = () => {
|
|||||||
<TelegramaWidget />
|
<TelegramaWidget />
|
||||||
<ResultadosTablaDetalladaWidget />
|
<ResultadosTablaDetalladaWidget />
|
||||||
<ResultadosRankingMunicipioWidget />
|
<ResultadosRankingMunicipioWidget />
|
||||||
|
|
||||||
|
<hr className="border-gray-300 my-8" />
|
||||||
|
|
||||||
|
<h2>Mapa - Vista General (Por Defecto)</h2>
|
||||||
|
<p>Carga la vista provincial completa para Diputados.</p>
|
||||||
|
<MapaBsAs />
|
||||||
|
|
||||||
|
<hr className="border-gray-300 my-8" />
|
||||||
|
|
||||||
|
<h2>Mapa - Foco en La Plata (Diputados por defecto)</h2>
|
||||||
|
<p>Carga el mapa y automáticamente hace zoom en La Plata.</p>
|
||||||
|
<MapaBsAs focoMunicipio="LA PLATA" />
|
||||||
|
|
||||||
|
<hr className="border-gray-300 my-8" />
|
||||||
|
|
||||||
|
<h2>Mapa - Foco en Campana</h2>
|
||||||
|
<p>Carga el mapa y automáticamente hace zoom en Campana.</p>
|
||||||
|
<MapaBsAs focoMunicipio="CAMPANA" focoCategoria="senadores" />
|
||||||
|
|
||||||
|
<hr className="border-gray-300 my-8" />
|
||||||
|
|
||||||
|
<h2>Mapa - Vista General de Senadores</h2>
|
||||||
|
<p>Carga la vista provincial completa para la categoría Senadores.</p>
|
||||||
|
<MapaBsAs focoCategoria="senadores" />
|
||||||
|
|
||||||
|
<hr className="border-gray-300 my-8" />
|
||||||
|
|
||||||
|
<h2>Mapa - Foco en Bahía Blanca para Concejales</h2>
|
||||||
|
<p>Carga el mapa enfocado en Bahía Blanca y con la categoría Concejales seleccionada.</p>
|
||||||
|
<MapaBsAs focoMunicipio="BAHIA BLANCA" focoCategoria="concejales" />
|
||||||
|
|
||||||
|
<hr className="border-gray-300 my-8" />
|
||||||
|
|
||||||
|
<h2>Mapa - Foco Inválido (La Plata para Senadores)</h2>
|
||||||
|
<p>Debería mostrar la vista provincial de Senadores y un warning en la consola del navegador.</p>
|
||||||
|
<MapaBsAs focoMunicipio="LA PLATA" focoCategoria="senadores" />
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simp
|
|||||||
import { Tooltip } from 'react-tooltip';
|
import { Tooltip } from 'react-tooltip';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { feature } from 'topojson-client';
|
||||||
import type { Feature, Geometry } from 'geojson';
|
import type { Feature, Geometry } from 'geojson';
|
||||||
import { geoCentroid } from 'd3-geo';
|
import { geoCentroid } from 'd3-geo';
|
||||||
import { API_BASE_URL, assetBaseUrl } from '../apiService';
|
import { API_BASE_URL, assetBaseUrl } from '../apiService';
|
||||||
@@ -12,6 +13,11 @@ import './MapaBsAs.css';
|
|||||||
// --- Interfaces y Tipos ---
|
// --- Interfaces y Tipos ---
|
||||||
type PointTuple = [number, number];
|
type PointTuple = [number, number];
|
||||||
|
|
||||||
|
interface MapaBsAsProps {
|
||||||
|
focoMunicipio?: string;
|
||||||
|
focoCategoria?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface ResultadoMapa {
|
interface ResultadoMapa {
|
||||||
ambitoId: number;
|
ambitoId: number;
|
||||||
departamentoNombre: string;
|
departamentoNombre: string;
|
||||||
@@ -33,15 +39,8 @@ interface Agrupacion {
|
|||||||
nombre: string;
|
nombre: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Categoria {
|
interface Categoria { id: number; nombre: string; }
|
||||||
id: number;
|
interface PartidoProperties { departamento: string; }
|
||||||
nombre: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PartidoProperties {
|
|
||||||
departamento: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type PartidoGeography = Feature<Geometry, PartidoProperties> & { rsmKey: string };
|
type PartidoGeography = Feature<Geometry, PartidoProperties> & { rsmKey: string };
|
||||||
|
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
@@ -52,19 +51,43 @@ const INITIAL_POSITION = { center: [-60.5, -37.2] as PointTuple, zoom: MIN_ZOOM
|
|||||||
const DEFAULT_MAP_COLOR = '#E0E0E0';
|
const DEFAULT_MAP_COLOR = '#E0E0E0';
|
||||||
|
|
||||||
const CATEGORIAS: Categoria[] = [
|
const CATEGORIAS: Categoria[] = [
|
||||||
{ id: 5, nombre: 'Senadores' },
|
|
||||||
{ id: 6, nombre: 'Diputados' },
|
{ id: 6, nombre: 'Diputados' },
|
||||||
|
{ id: 5, nombre: 'Senadores' },
|
||||||
{ id: 7, nombre: 'Concejales' }
|
{ id: 7, nombre: 'Concejales' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// --- Helper de Normalización ---
|
||||||
|
const normalizarTexto = (texto: string = ''): string => {
|
||||||
|
return texto
|
||||||
|
.trim()
|
||||||
|
.toUpperCase()
|
||||||
|
.normalize("NFD") // Separa los acentos de las letras
|
||||||
|
.replace(/[\u0300-\u036f]/g, ""); // Elimina los acentos
|
||||||
|
};
|
||||||
|
|
||||||
// --- Componente Principal ---
|
// --- Componente Principal ---
|
||||||
const MapaBsAs = () => {
|
const MapaBsAs = ({ focoMunicipio, focoCategoria }: MapaBsAsProps) => {
|
||||||
|
// --- LÓGICA DE ESTADO SIMPLIFICADA ---
|
||||||
|
const categoriaInicial = useMemo(() => {
|
||||||
|
const catNorm = focoCategoria?.toLowerCase();
|
||||||
|
if (catNorm === 'senadores') return 5;
|
||||||
|
if (catNorm === 'concejales') return 7;
|
||||||
|
return 6;
|
||||||
|
}, [focoCategoria]);
|
||||||
|
|
||||||
const [position, setPosition] = useState(INITIAL_POSITION);
|
const [position, setPosition] = useState(INITIAL_POSITION);
|
||||||
const [selectedAmbitoId, setSelectedAmbitoId] = useState<number | null>(null);
|
const [selectedAmbitoId, setSelectedAmbitoId] = useState<number | null>(null);
|
||||||
const [selectedCategoriaId, setSelectedCategoriaId] = useState<number>(6);
|
const [selectedCategoriaId, setSelectedCategoriaId] = useState<number>(categoriaInicial);
|
||||||
const [tooltipContent, setTooltipContent] = useState('');
|
const [tooltipContent, setTooltipContent] = useState('');
|
||||||
const [isPanning, setIsPanning] = useState(false);
|
const [isPanning, setIsPanning] = useState(false);
|
||||||
|
|
||||||
|
// Sincroniza el estado si la prop cambia. Esto es para cuando el widget ya está montado
|
||||||
|
// y recibe nuevas props (no ocurrirá en tu caso actual, pero es buena práctica).
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedCategoriaId(categoriaInicial);
|
||||||
|
}, [categoriaInicial]);
|
||||||
|
|
||||||
|
// --- QUERIES ---
|
||||||
const { data: resultadosData, isLoading: isLoadingResultados } = useQuery<ResultadoMapa[]>({
|
const { data: resultadosData, isLoading: isLoadingResultados } = useQuery<ResultadoMapa[]>({
|
||||||
queryKey: ['mapaResultadosPorMunicipio', selectedCategoriaId],
|
queryKey: ['mapaResultadosPorMunicipio', selectedCategoriaId],
|
||||||
queryFn: async () => (await axios.get(`${API_BASE_URL}/Resultados/mapa-por-municipio?categoriaId=${selectedCategoriaId}`)).data,
|
queryFn: async () => (await axios.get(`${API_BASE_URL}/Resultados/mapa-por-municipio?categoriaId=${selectedCategoriaId}`)).data,
|
||||||
@@ -80,21 +103,16 @@ const MapaBsAs = () => {
|
|||||||
queryFn: async () => (await axios.get(`${API_BASE_URL}/Catalogos/agrupaciones`)).data,
|
queryFn: async () => (await axios.get(`${API_BASE_URL}/Catalogos/agrupaciones`)).data,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { nombresAgrupaciones, resultadosPorDepartamento } = useMemo<{
|
const { nombresAgrupaciones, resultadosPorDepartamento } = useMemo(() => {
|
||||||
nombresAgrupaciones: Map<string, string>;
|
|
||||||
resultadosPorDepartamento: Map<string, ResultadoMapa>;
|
|
||||||
}>(() => {
|
|
||||||
const nombresMap = new Map<string, string>();
|
const nombresMap = new Map<string, string>();
|
||||||
const resultadosMap = new Map<string, ResultadoMapa>();
|
const resultadosMap = new Map<string, ResultadoMapa>();
|
||||||
if (agrupacionesData) {
|
if (agrupacionesData) {
|
||||||
agrupacionesData.forEach((agrupacion) => {
|
agrupacionesData.forEach((a) => nombresMap.set(a.id, a.nombre));
|
||||||
nombresMap.set(agrupacion.id, agrupacion.nombre);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (resultadosData) {
|
if (resultadosData) {
|
||||||
resultadosData.forEach(r => {
|
resultadosData.forEach(r => {
|
||||||
if (r.departamentoNombre) {
|
if (r.departamentoNombre) {
|
||||||
resultadosMap.set(r.departamentoNombre.toUpperCase(), r)
|
resultadosMap.set(normalizarTexto(r.departamentoNombre), r);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -108,20 +126,105 @@ const MapaBsAs = () => {
|
|||||||
setPosition(INITIAL_POSITION);
|
setPosition(INITIAL_POSITION);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// --- LÓGICA DE CLIC Y FOCO ---
|
||||||
const handleGeographyClick = useCallback((geo: PartidoGeography) => {
|
const handleGeographyClick = useCallback((geo: PartidoGeography) => {
|
||||||
const departamentoNombre = geo.properties.departamento.toUpperCase();
|
const departamentoNombreNormalizado = normalizarTexto(geo.properties.departamento);
|
||||||
const resultado = resultadosPorDepartamento.get(departamentoNombre);
|
const resultado = resultadosPorDepartamento.get(departamentoNombreNormalizado);
|
||||||
if (!resultado) return;
|
if (!resultado) return;
|
||||||
const ambitoIdParaSeleccionar = resultado.ambitoId;
|
|
||||||
if (selectedAmbitoId === ambitoIdParaSeleccionar) {
|
if (selectedAmbitoId === resultado.ambitoId) {
|
||||||
handleReset();
|
handleReset();
|
||||||
} else {
|
} else {
|
||||||
const centroid = geoCentroid(geo) as PointTuple;
|
const centroid = geoCentroid(geo) as PointTuple;
|
||||||
setPosition({ center: centroid, zoom: 5 });
|
setPosition({ center: centroid, zoom: 5 });
|
||||||
setSelectedAmbitoId(ambitoIdParaSeleccionar);
|
setSelectedAmbitoId(resultado.ambitoId);
|
||||||
}
|
}
|
||||||
}, [selectedAmbitoId, handleReset, resultadosPorDepartamento]);
|
}, [selectedAmbitoId, handleReset, resultadosPorDepartamento]);
|
||||||
|
|
||||||
|
// --- useEffect DE INICIALIZACIÓN (Ligeramente refinado) ---
|
||||||
|
useEffect(() => {
|
||||||
|
if (isLoading || !focoMunicipio || selectedAmbitoId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const geometries = geoData?.objects?.['departamentos-buenos_aires']?.geometries;
|
||||||
|
if (!geometries) return;
|
||||||
|
|
||||||
|
const nombreFocoNormalizado = normalizarTexto(focoMunicipio);
|
||||||
|
const geoTargetTopo = geometries.find(
|
||||||
|
(g: any) => normalizarTexto(g.properties.departamento) === nombreFocoNormalizado
|
||||||
|
);
|
||||||
|
|
||||||
|
if (geoTargetTopo) {
|
||||||
|
if (resultadosPorDepartamento.has(nombreFocoNormalizado)) {
|
||||||
|
const geoTargetGeoJSON = feature(geoData, geoTargetTopo);
|
||||||
|
handleGeographyClick(geoTargetGeoJSON as unknown as PartidoGeography);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Deshabilitamos la regla para que solo se ejecute cuando isLoading cambia a false.
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [isLoading]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categoriaInicial !== selectedCategoriaId) {
|
||||||
|
setSelectedCategoriaId(categoriaInicial);
|
||||||
|
handleReset();
|
||||||
|
}
|
||||||
|
}, [categoriaInicial, selectedCategoriaId, handleReset]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => e.key === 'Escape' && handleReset();
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
|
}, [handleReset]);
|
||||||
|
|
||||||
|
const renderGeography = useCallback((geo: PartidoGeography, isSelectedGeo: boolean = false) => {
|
||||||
|
const departamentoNombreNormalizado = normalizarTexto(geo.properties.departamento);
|
||||||
|
const resultado = resultadosPorDepartamento.get(departamentoNombreNormalizado);
|
||||||
|
const isClickable = !!resultado;
|
||||||
|
const isSelected = isSelectedGeo || (selectedAmbitoId !== null && selectedAmbitoId === resultado?.ambitoId);
|
||||||
|
const isFaded = !isSelectedGeo && selectedAmbitoId !== null && !isSelected;
|
||||||
|
|
||||||
|
const nombreAgrupacionGanadora = resultado
|
||||||
|
? nombresAgrupaciones.get(resultado.agrupacionGanadoraId)
|
||||||
|
: 'Sin datos';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Geography
|
||||||
|
key={geo.rsmKey + (isSelectedGeo ? '-selected' : '')}
|
||||||
|
geography={geo}
|
||||||
|
className={`rsm-geography ${isSelected ? 'selected' : ''} ${isFaded ? 'faded' : ''} ${!isClickable ? 'no-results' : ''}`}
|
||||||
|
fill={resultado?.colorGanador || DEFAULT_MAP_COLOR}
|
||||||
|
onClick={isClickable ? () => handleGeographyClick(geo) : undefined}
|
||||||
|
onMouseEnter={() => {
|
||||||
|
if (isClickable) {
|
||||||
|
setTooltipContent(`${geo.properties.departamento}: ${nombreAgrupacionGanadora}`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => setTooltipContent("")}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}, [resultadosPorDepartamento, selectedAmbitoId, nombresAgrupaciones, handleGeographyClick]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isLoading || !focoMunicipio || selectedAmbitoId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const geometries = geoData?.objects?.['departamentos-buenos_aires']?.geometries;
|
||||||
|
if (!geometries) return;
|
||||||
|
|
||||||
|
const nombreFocoNormalizado = normalizarTexto(focoMunicipio);
|
||||||
|
const geoTargetTopo = geometries.find(
|
||||||
|
(g: any) => normalizarTexto(g.properties.departamento) === nombreFocoNormalizado
|
||||||
|
);
|
||||||
|
|
||||||
|
if (geoTargetTopo && resultadosPorDepartamento.has(nombreFocoNormalizado)) {
|
||||||
|
const geoTargetGeoJSON = feature(geoData, geoTargetTopo);
|
||||||
|
handleGeographyClick(geoTargetGeoJSON as unknown as PartidoGeography);
|
||||||
|
}
|
||||||
|
}, [isLoading, focoMunicipio, selectedCategoriaId]);
|
||||||
|
|
||||||
const handleMoveEnd = (newPosition: { coordinates: PointTuple; zoom: number }) => {
|
const handleMoveEnd = (newPosition: { coordinates: PointTuple; zoom: number }) => {
|
||||||
if (newPosition.zoom <= MIN_ZOOM) {
|
if (newPosition.zoom <= MIN_ZOOM) {
|
||||||
if (position.zoom > MIN_ZOOM || selectedAmbitoId !== null) {
|
if (position.zoom > MIN_ZOOM || selectedAmbitoId !== null) {
|
||||||
@@ -147,35 +250,6 @@ const MapaBsAs = () => {
|
|||||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
}, [handleReset]);
|
}, [handleReset]);
|
||||||
|
|
||||||
const getPartyFillColor = (departamentoNombre: string) => {
|
|
||||||
const resultado = resultadosPorDepartamento.get(departamentoNombre.toUpperCase());
|
|
||||||
return resultado?.colorGanador || DEFAULT_MAP_COLOR;
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Helper de Renderizado ---
|
|
||||||
const renderGeography = (geo: PartidoGeography, isSelectedGeo: boolean = false) => {
|
|
||||||
const departamentoNombre = geo.properties.departamento.toUpperCase();
|
|
||||||
const resultado = resultadosPorDepartamento.get(departamentoNombre);
|
|
||||||
const isClickable = !!resultado;
|
|
||||||
const isSelected = isSelectedGeo || (selectedAmbitoId !== null && selectedAmbitoId === resultado?.ambitoId);
|
|
||||||
const isFaded = !isSelectedGeo && selectedAmbitoId !== null && !isSelected;
|
|
||||||
const nombreAgrupacionGanadora = resultado ? nombresAgrupaciones.get(resultado.agrupacionGanadoraId) : 'Sin datos';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Geography
|
|
||||||
key={geo.rsmKey + (isSelectedGeo ? '-selected' : '')}
|
|
||||||
geography={geo}
|
|
||||||
data-tooltip-id="partido-tooltip"
|
|
||||||
data-tooltip-content={`${geo.properties.departamento}: ${nombreAgrupacionGanadora}`}
|
|
||||||
className={`rsm-geography ${isSelected ? 'selected' : ''} ${isFaded ? 'faded' : ''} ${!isClickable ? 'no-results' : ''}`}
|
|
||||||
fill={getPartyFillColor(geo.properties.departamento)}
|
|
||||||
onClick={isClickable ? () => handleGeographyClick(geo) : undefined}
|
|
||||||
onMouseEnter={() => setTooltipContent(`${geo.properties.departamento}: ${nombreAgrupacionGanadora}`)}
|
|
||||||
onMouseLeave={() => setTooltipContent("")}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mapa-wrapper">
|
<div className="mapa-wrapper">
|
||||||
<div className="mapa-container">
|
<div className="mapa-container">
|
||||||
@@ -213,7 +287,7 @@ const MapaBsAs = () => {
|
|||||||
{({ geographies }: { geographies: PartidoGeography[] }) => {
|
{({ geographies }: { geographies: PartidoGeography[] }) => {
|
||||||
const selectedGeo = selectedAmbitoId
|
const selectedGeo = selectedAmbitoId
|
||||||
? geographies.find(geo => {
|
? geographies.find(geo => {
|
||||||
const resultado = resultadosPorDepartamento.get(geo.properties.departamento.toUpperCase());
|
const resultado = resultadosPorDepartamento.get(normalizarTexto(geo.properties.departamento));
|
||||||
return resultado?.ambitoId === selectedAmbitoId;
|
return resultado?.ambitoId === selectedAmbitoId;
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
@@ -239,14 +313,15 @@ const MapaBsAs = () => {
|
|||||||
className="mapa-categoria-combobox"
|
className="mapa-categoria-combobox"
|
||||||
value={selectedCategoriaId}
|
value={selectedCategoriaId}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
// --- LÓGICA DE CAMBIO DE CATEGORÍA ---
|
||||||
|
// Limpiamos el foco de municipio al cambiar de categoría
|
||||||
|
setSelectedAmbitoId(null);
|
||||||
|
setPosition(INITIAL_POSITION);
|
||||||
setSelectedCategoriaId(Number(e.target.value));
|
setSelectedCategoriaId(Number(e.target.value));
|
||||||
handleReset();
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{CATEGORIAS.map(cat => (
|
{CATEGORIAS.map(cat => (
|
||||||
<option key={cat.id} value={cat.id}>
|
<option key={cat.id} value={cat.id}>{cat.nombre}</option>
|
||||||
{cat.nombre}
|
|
||||||
</option>
|
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -259,6 +334,7 @@ const MapaBsAs = () => {
|
|||||||
|
|
||||||
// --- Sub-componentes ---
|
// --- Sub-componentes ---
|
||||||
const ControlesMapa = ({ onReset }: { onReset: () => void }) => (
|
const ControlesMapa = ({ onReset }: { onReset: () => void }) => (
|
||||||
|
|
||||||
<div className="map-controls">
|
<div className="map-controls">
|
||||||
<button onClick={onReset}>← VOLVER</button>
|
<button onClick={onReset}>← VOLVER</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -299,10 +375,10 @@ const DetalleMunicipio = ({ ambitoId, onReset, categoriaId }: { ambitoId: number
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li >
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul >
|
||||||
</div>
|
</div >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -321,6 +397,7 @@ const Legend = ({ resultados, nombresAgrupaciones }: { resultados: Map<string, R
|
|||||||
});
|
});
|
||||||
|
|
||||||
return Array.from(ganadoresUnicos.values());
|
return Array.from(ganadoresUnicos.values());
|
||||||
|
|
||||||
}, [resultados, nombresAgrupaciones]);
|
}, [resultados, nombresAgrupaciones]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -63,32 +63,29 @@ if (import.meta.env.DEV) {
|
|||||||
} else {
|
} else {
|
||||||
// --- MODO PRODUCCIÓN ---
|
// --- MODO PRODUCCIÓN ---
|
||||||
// Exponemos la función de renderizado para el bootstrap.js
|
// Exponemos la función de renderizado para el bootstrap.js
|
||||||
const renderWidgets = () => {
|
// La función de renderizado acepta el contenedor y las props
|
||||||
const widgetContainers = document.querySelectorAll('[data-elecciones-widget]');
|
const renderWidgets = (container: HTMLElement, props: DOMStringMap) => {
|
||||||
|
const widgetName = props.eleccionesWidget;
|
||||||
if (widgetContainers.length === 0) {
|
|
||||||
console.warn('React: ADVERTENCIA - No se encontró ningún elemento en el DOM para renderizar un widget. Verifica que el HTML contenga <div data-elecciones-widget="...">.');
|
|
||||||
}
|
|
||||||
|
|
||||||
widgetContainers.forEach(container => {
|
|
||||||
const widgetName = (container as HTMLElement).dataset.eleccionesWidget;
|
|
||||||
|
|
||||||
if (widgetName && WIDGET_MAP[widgetName]) {
|
if (widgetName && WIDGET_MAP[widgetName]) {
|
||||||
const WidgetComponent = WIDGET_MAP[widgetName];
|
const WidgetComponent = WIDGET_MAP[widgetName];
|
||||||
const root = ReactDOM.createRoot(container);
|
const root = ReactDOM.createRoot(container);
|
||||||
|
|
||||||
|
// Pasamos todas las props (ej. { eleccionesWidget: '...', focoMunicipio: '...' })
|
||||||
|
// al componente que se va a renderizar.
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<WidgetComponent />
|
<WidgetComponent {...props} />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.error(`React: ERROR - No se encontró un componente para el nombre de widget: "${widgetName}"`);
|
console.error(`React: ERROR - No se encontró un componente para el nombre de widget: "${widgetName}"`);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// La función expuesta ahora se llamará por cada widget, no una sola vez.
|
||||||
(window as any).EleccionesWidgets = {
|
(window as any).EleccionesWidgets = {
|
||||||
render: renderWidgets
|
render: renderWidgets
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6309003536b4278315dbe89abb0a8fe79e3320a9")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[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=","DJ3OEGlGm0XqehqAshsJPdHddx35xQrKqTYPlJ\u002BmgK0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","VC4RrsY3drpYvDr8ENTx68n\u002BklPRBIIs4arkXFsPT3E="],"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=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","/f\u002B\u002BdIRysg7dipW05N4RtxXuPBXZZIhhi3aMiCZ\u002BB2w="],"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=","DJ3OEGlGm0XqehqAshsJPdHddx35xQrKqTYPlJ\u002BmgK0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","VC4RrsY3drpYvDr8ENTx68n\u002BklPRBIIs4arkXFsPT3E="],"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=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","/f\u002B\u002BdIRysg7dipW05N4RtxXuPBXZZIhhi3aMiCZ\u002BB2w="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6309003536b4278315dbe89abb0a8fe79e3320a9")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6309003536b4278315dbe89abb0a8fe79e3320a9")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d5168e1d175a8b1944d6009066d13f9b99cba1d0")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6309003536b4278315dbe89abb0a8fe79e3320a9")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
Reference in New Issue
Block a user