Primer push
24
Antifraude.Net/GestionaDenunciasAN/Components/App.razor
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="/" />
|
||||
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" />
|
||||
|
||||
<link rel="stylesheet" href="app.css" />
|
||||
<link rel="stylesheet" href="GestionaDenunciasAN.styles.css" />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<HeadOutlet />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Routes />
|
||||
<script src="Scripts/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="main">
|
||||
<div class="">
|
||||
@Body
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,95 @@
|
||||
@inherits LayoutComponentBase
|
||||
@inject GestionaDenunciasAN.Models.UserState userState
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
/* Barra superior con gradiente de azul: izquierda azul clarito, derecha azul oscuro */
|
||||
.top-row {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background: linear-gradient(to right, #5a9bd5, #1f497d);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Título del portal posicionado a la izquierda */
|
||||
.portal-title {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
/* Contenedor del enlace de usuario posicionado a la derecha */
|
||||
.logout-container {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
/* Enlace que luce como texto, sin decoraciones */
|
||||
.logout-link {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Icono SVG más grande */
|
||||
.logout-link img {
|
||||
height: 1.5em;
|
||||
width: auto;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
/* Al pasar el ratón, se pone en negrita y mantiene el color blanco */
|
||||
.logout-link:hover,
|
||||
.logout-link:focus,
|
||||
.logout-link:active {
|
||||
font-weight: bold;
|
||||
color: #fff !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<!-- Barra superior completa con gradiente de azul -->
|
||||
<div class="top-row">
|
||||
<div class="portal-title">
|
||||
Portal Gestion Denuncias
|
||||
</div>
|
||||
<div class="logout-container">
|
||||
<a class="logout-link" href="/">
|
||||
<img src="Content/icon/person-fill.svg" alt="User Icon" />
|
||||
<span>@userState?.NombreUsu</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<article class="content">
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
@@ -0,0 +1,96 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row.auth ::deep a:first-child {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<!-- NavMenu.razor -->
|
||||
<style>
|
||||
.nav-menu-container {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Parte superior con el logo */
|
||||
.nav-top {
|
||||
background-color: #5a9bd5 !important;
|
||||
padding: 0.5rem;
|
||||
height: 5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-top img {
|
||||
height: 4em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Sección scrollable para el contenido del menú */
|
||||
.nav-scrollable {
|
||||
background: linear-gradient(to bottom, #5a9bd5, #1f497d);
|
||||
height: calc(100vh - 5em);
|
||||
overflow-y: auto;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
/* Empujar el grupo inferior (Instrucciones) al fondo, con un margen inferior */
|
||||
.bottom-group {
|
||||
margin-top: auto;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Ajuste de los enlaces para icono y texto en la misma línea */
|
||||
.nav-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.nav-link .bi {
|
||||
display: inline-block;
|
||||
font-size: 1.25rem;
|
||||
margin-right: 0.5rem;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="nav-menu-container">
|
||||
<!-- Parte superior: logo -->
|
||||
<div class="nav-top">
|
||||
<div class="container-fluid" style="display: flex; justify-content: center; align-items: center;">
|
||||
<img src="Content/imagenes/logo-oaaf-negativo-transparente.svg" alt="logo" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Contenido scrollable: menú de navegación -->
|
||||
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
|
||||
<nav class="flex-column" style="display: flex; height: 100%;">
|
||||
<!-- Grupo superior: Pendientes y Finalizados -->
|
||||
<div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="GestionZip" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-list-task" aria-hidden="true"></span> Gestion ZIP
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Pendientes" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-list-task" aria-hidden="true"></span> Pendientes
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Gestiona" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-journal-check" aria-hidden="true"></span> Gestiona
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Rechazados" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-journal-x" aria-hidden="true"></span> Rechazados
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Grupo inferior: Instrucciones, empujado al fondo -->
|
||||
<div class="bottom-group">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Instrucciones">
|
||||
<span class="bi bi-book-half" aria-hidden="true"></span> Instrucciones
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,105 @@
|
||||
.navbar-toggler {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
width: 3.5rem;
|
||||
height: 2.5rem;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 1rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.navbar-toggler:checked {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.bi {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link {
|
||||
color: #d7d7d7;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-toggler:checked ~ .nav-scrollable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
@page "/Error"
|
||||
@using System.Diagnostics
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
@page "/GestionZip"
|
||||
@rendermode InteractiveServer
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using GestionaDenunciasAN.Models
|
||||
@using System.Globalization
|
||||
@inject IHostEnvironment HostEnvironment
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<PageTitle>Gestión de ZIP</PageTitle>
|
||||
|
||||
<h3>Gestión de ZIP</h3>
|
||||
|
||||
@if (string.IsNullOrEmpty(zipsPath))
|
||||
{
|
||||
<div class="alert alert-danger">
|
||||
La ruta para guardar los ZIP no se encuentra.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-primary mb-3" @onclick="TriggerFileInput">Subir nuevo ZIP</button>
|
||||
<InputFile id="hiddenFileInput" style="display:none;" OnChange="HandleFileSelected" multiple accept=".zip" />
|
||||
|
||||
@if (!string.IsNullOrEmpty(uploadMessage))
|
||||
{
|
||||
<div class="alert alert-info">@uploadMessage</div>
|
||||
}
|
||||
|
||||
<h4>Archivos ZIP existentes:</h4>
|
||||
@if (existingZips == null || !existingZips.Any())
|
||||
{
|
||||
<p>No hay archivos ZIP subidos.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre del ZIP</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var zipFileName in existingZips)
|
||||
{
|
||||
<tr>
|
||||
<td>@zipFileName</td>
|
||||
<td>
|
||||
<button class="btn btn-danger btn-sm" @onclick="() => DeleteZip(zipFileName)">Eliminar</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
private string zipsPath;
|
||||
private List<string> existingZips = new();
|
||||
private string uploadMessage;
|
||||
private const string FIXED_PATH = @"C:\ZipsDenuncias";
|
||||
private const string DENUNCIAS_JSON = @"C:\ZipsDenuncias\denuncias.json";
|
||||
private const string FICHEROS_JSON = @"C:\ZipsDenuncias\ficheros.json";
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (Directory.Exists(FIXED_PATH))
|
||||
{
|
||||
zipsPath = FIXED_PATH;
|
||||
}
|
||||
else
|
||||
{
|
||||
zipsPath = string.Empty;
|
||||
uploadMessage = "La ruta para guardar los ZIP no se encuentra.";
|
||||
}
|
||||
if (!string.IsNullOrEmpty(zipsPath))
|
||||
{
|
||||
LoadExistingZips();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TriggerFileInput()
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("triggerFileInput", "hiddenFileInput");
|
||||
}
|
||||
|
||||
private async Task HandleFileSelected(InputFileChangeEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(zipsPath))
|
||||
{
|
||||
uploadMessage = "No se pudo subir porque la ruta no se encuentra.";
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var file in e.GetMultipleFiles())
|
||||
{
|
||||
var fileName = file.Name;
|
||||
var finalPath = Path.Combine(zipsPath, fileName);
|
||||
using var stream = file.OpenReadStream(long.MaxValue);
|
||||
using var fs = new FileStream(finalPath, FileMode.Create);
|
||||
await stream.CopyToAsync(fs);
|
||||
count++;
|
||||
}
|
||||
uploadMessage = $"{count} archivo(s) ZIP subido(s) correctamente.";
|
||||
LoadExistingZips();
|
||||
await ActualizarJsonConZipsAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
uploadMessage = $"Error al subir: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadExistingZips()
|
||||
{
|
||||
existingZips = Directory.GetFiles(zipsPath, "*.zip")
|
||||
.Select(Path.GetFileName)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private void DeleteZip(string fileName)
|
||||
{
|
||||
var fullPath = Path.Combine(zipsPath, fileName);
|
||||
if (File.Exists(fullPath))
|
||||
{
|
||||
File.Delete(fullPath);
|
||||
}
|
||||
LoadExistingZips();
|
||||
}
|
||||
|
||||
// Procesa cada ZIP: extrae report.txt y ficheros adjuntos; actualiza o añade registros en los JSON.
|
||||
private async Task ActualizarJsonConZipsAsync()
|
||||
{
|
||||
var registros = new List<DenunciasGestiona>();
|
||||
var ficheros = new List<FicherosDenuncias>();
|
||||
|
||||
var zipFiles = Directory.GetFiles(zipsPath, "*.zip");
|
||||
foreach (var zipFile in zipFiles)
|
||||
{
|
||||
var folderName = Path.GetFileNameWithoutExtension(zipFile);
|
||||
var extractPath = Path.Combine(zipsPath, folderName);
|
||||
if (!Directory.Exists(extractPath))
|
||||
Directory.CreateDirectory(extractPath);
|
||||
|
||||
// Extraemos el ZIP (sobrescribe si es necesario)
|
||||
System.IO.Compression.ZipFile.ExtractToDirectory(zipFile, extractPath, overwriteFiles: true);
|
||||
|
||||
// Procesamos el reporte
|
||||
var reportPath = Path.Combine(extractPath, "report.txt");
|
||||
if (File.Exists(reportPath))
|
||||
{
|
||||
var lines = await File.ReadAllLinesAsync(reportPath);
|
||||
var denuncia = ParsearReportTxt(lines);
|
||||
if (string.IsNullOrEmpty(denuncia.Expediente_Gestiona))
|
||||
denuncia.Expediente_Gestiona = "Pendiente";
|
||||
registros.Add(denuncia);
|
||||
|
||||
// Procesamos ficheros adjuntos
|
||||
foreach (var subFolder in new[] { "files", "files_attached_from_recipients" })
|
||||
{
|
||||
var subPath = Path.Combine(extractPath, subFolder);
|
||||
if (Directory.Exists(subPath))
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(subPath))
|
||||
{
|
||||
var bytes = await File.ReadAllBytesAsync(file);
|
||||
var fichero = new FicherosDenuncias
|
||||
{
|
||||
Id_Fichero = 0,
|
||||
Id_Tipo = 1,
|
||||
Descripcion = null,
|
||||
Fecha = DateTime.Now,
|
||||
Observaciones = "",
|
||||
Id_Denuncia = denuncia.Id_Denuncia,
|
||||
NombreFichero = Path.GetFileName(file),
|
||||
Fichero = bytes
|
||||
};
|
||||
ficheros.Add(fichero);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Actualizamos el JSON de Denuncias
|
||||
List<DenunciasGestiona> existentesDenuncias = new List<DenunciasGestiona>();
|
||||
if (File.Exists(DENUNCIAS_JSON))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(DENUNCIAS_JSON);
|
||||
existentesDenuncias = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DenunciasGestiona>>(json) ?? new List<DenunciasGestiona>();
|
||||
}
|
||||
foreach (var reg in registros)
|
||||
{
|
||||
var existente = existentesDenuncias.FirstOrDefault(d => d.Id_Denuncia == reg.Id_Denuncia);
|
||||
if (existente != null)
|
||||
{
|
||||
if (existente.Expediente_Gestiona == "Pendiente")
|
||||
{
|
||||
existente.Fecha = reg.Fecha;
|
||||
existente.Etiqueta = reg.Etiqueta;
|
||||
existente.Estado = reg.Estado;
|
||||
existente.Tipo_Denuncia = reg.Tipo_Denuncia;
|
||||
existente.Asunto = reg.Asunto;
|
||||
existente.A_Quien_Denuncia = reg.A_Quien_Denuncia;
|
||||
existente.Descripcion_Denuncia = reg.Descripcion_Denuncia;
|
||||
existente.Denunciado_Ante_Inst = reg.Denunciado_Ante_Inst;
|
||||
existente.Lugar_Hechos = reg.Lugar_Hechos;
|
||||
existente.Fecha_Hechos = reg.Fecha_Hechos;
|
||||
existente.Condiciones = reg.Condiciones;
|
||||
existente.Comments = reg.Comments;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
existentesDenuncias.Add(reg);
|
||||
}
|
||||
}
|
||||
var newJsonDenuncias = Newtonsoft.Json.JsonConvert.SerializeObject(existentesDenuncias, Newtonsoft.Json.Formatting.Indented);
|
||||
await File.WriteAllTextAsync(DENUNCIAS_JSON, newJsonDenuncias);
|
||||
|
||||
// Actualizamos el JSON de Ficheros
|
||||
List<FicherosDenuncias> existentesFicheros = new List<FicherosDenuncias>();
|
||||
if (File.Exists(FICHEROS_JSON))
|
||||
{
|
||||
var jsonF = await File.ReadAllTextAsync(FICHEROS_JSON);
|
||||
existentesFicheros = Newtonsoft.Json.JsonConvert.DeserializeObject<List<FicherosDenuncias>>(jsonF) ?? new List<FicherosDenuncias>();
|
||||
}
|
||||
// Eliminamos los ficheros de denuncia que vamos a actualizar
|
||||
foreach (var reg in registros)
|
||||
{
|
||||
existentesFicheros.RemoveAll(f => f.Id_Denuncia == reg.Id_Denuncia);
|
||||
}
|
||||
// Añadimos los nuevos ficheros
|
||||
existentesFicheros.AddRange(ficheros);
|
||||
var newJsonFicheros = Newtonsoft.Json.JsonConvert.SerializeObject(existentesFicheros, Newtonsoft.Json.Formatting.Indented);
|
||||
await File.WriteAllTextAsync(FICHEROS_JSON, newJsonFicheros);
|
||||
}
|
||||
|
||||
private DenunciasGestiona ParsearReportTxt(string[] lines)
|
||||
{
|
||||
var denuncia = new DenunciasGestiona();
|
||||
bool leyendoComments = false;
|
||||
var commentsBuilder = new System.Text.StringBuilder();
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].Trim();
|
||||
|
||||
// Si se encuentra la marca de comentarios, todo lo siguiente se agrega a Comments
|
||||
if (line.StartsWith("Comments", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
leyendoComments = true;
|
||||
continue;
|
||||
}
|
||||
if (leyendoComments)
|
||||
{
|
||||
commentsBuilder.AppendLine(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Campos generales
|
||||
if (line.StartsWith("ID:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var idStr = line.Substring("ID:".Length).Trim();
|
||||
if (int.TryParse(idStr, out int idNum))
|
||||
denuncia.Id_Denuncia = idNum;
|
||||
}
|
||||
else if (line.StartsWith("Fecha:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var fechaStr = line.Substring("Fecha:".Length).Trim();
|
||||
if (fechaStr.EndsWith("(UTC)"))
|
||||
fechaStr = fechaStr.Substring(0, fechaStr.Length - "(UTC)".Length).Trim();
|
||||
// Intentamos primero con un formato específico
|
||||
string formato = "dddd dd MMMM yyyy HH:mm";
|
||||
if (DateTime.TryParseExact(fechaStr, formato, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTime fechaParsed))
|
||||
{
|
||||
denuncia.Fecha = fechaParsed;
|
||||
}
|
||||
else if (DateTime.TryParse(fechaStr, out DateTime fechaParsed2))
|
||||
{
|
||||
denuncia.Fecha = fechaParsed2;
|
||||
}
|
||||
else
|
||||
{
|
||||
denuncia.Fecha = DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
else if (line.StartsWith("Etiqueta:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
denuncia.Etiqueta = line.Substring("Etiqueta:".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("Estado:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
denuncia.Estado = line.Substring("Estado:".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("Expediente_Gestiona:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
denuncia.Expediente_Gestiona = line.Substring("Expediente_Gestiona:".Length).Trim();
|
||||
}
|
||||
else if (line.StartsWith("¿Qué tipo de denuncia desea realizar?", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Tipo_Denuncia = lines[i + 1].Trim();
|
||||
}
|
||||
// Sección "Datos de contacto"
|
||||
else if (line.Equals("Nombre", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Nombre = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.Equals("Apellidos", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Apellidos = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.Equals("Sexo", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Sexo = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.Equals("DNI", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Dni = lines[i + 1].Trim();
|
||||
}
|
||||
// Sección "Descripción"
|
||||
else if (line.StartsWith("Asunto", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Asunto = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.StartsWith("¿A quién denuncia?", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.A_Quien_Denuncia = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.StartsWith("Describa su denuncia", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Descripcion_Denuncia = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.StartsWith("¿Ha denunciado estos hechos ante otras instituciones", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Denunciado_Ante_Inst = lines[i + 1].Trim();
|
||||
}
|
||||
// Sección "Lugar y fecha de los hechos"
|
||||
else if (line.StartsWith("Lugar en la que ocurrieron los hechos", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Lugar_Hechos = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.StartsWith("Fecha de los hechos que denuncia", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
{
|
||||
var fechaHechosStr = lines[i + 1].Trim();
|
||||
// Si el valor es "ayer", se asume la fecha de ayer
|
||||
if (fechaHechosStr.Equals("ayer", StringComparison.OrdinalIgnoreCase))
|
||||
denuncia.Fecha_Hechos = DateTime.Now.AddDays(-1);
|
||||
else if (DateTime.TryParse(fechaHechosStr, out DateTime fechaHechosParsed))
|
||||
denuncia.Fecha_Hechos = fechaHechosParsed;
|
||||
}
|
||||
}
|
||||
// Sección "Notificaciones"
|
||||
else if (line.Equals("Correo electrónico", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Correo_Electronico = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.Equals("Notificaciones Electrónicas", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Notificacion_Electronica = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.Equals("Notificaciones mediante SMS", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Notificacion_Sms = lines[i + 1].Trim();
|
||||
}
|
||||
else if (line.Equals("Seleccione su preferencia de notificación y seguimiento de su denuncia", StringComparison.OrdinalIgnoreCase)
|
||||
|| line.Equals("Notificación Preferencia", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (i + 1 < lines.Length)
|
||||
denuncia.Notificacion_Preferencia = lines[i + 1].Trim();
|
||||
}
|
||||
// Sección "Condiciones y reglas de uso"
|
||||
else if (line.Contains("☑"))
|
||||
{
|
||||
denuncia.Condiciones = true;
|
||||
}
|
||||
}
|
||||
|
||||
denuncia.Comments = commentsBuilder.ToString();
|
||||
return denuncia;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
// Función JS que dispara el click en el elemento con el ID indicado.
|
||||
window.triggerFileInput = (elementId) => {
|
||||
document.getElementById(elementId).click();
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,383 @@
|
||||
@page "/Gestiona"
|
||||
@rendermode InteractiveServer
|
||||
@using GestionaDenunciasAN.Models
|
||||
@using System.Globalization
|
||||
@attribute [StreamRendering]
|
||||
@inject GestionaDenunciasAN.Models.UserState userState
|
||||
@inject NavigationManager Navigation
|
||||
@inject IHostEnvironment HostEnvironment
|
||||
|
||||
<PageTitle>Denuncias Gestión</PageTitle>
|
||||
|
||||
<style>
|
||||
/* Contenedor para la lista de denuncias */
|
||||
.gestion-list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
/* Estilo general para cada card */
|
||||
.collapse-card {
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.collapse-card:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
/* Aplicar fondo verde a toda la card */
|
||||
.Aceptada {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
/* Forzar fondo transparente en cabecera y cuerpo para que hereden el color de la card */
|
||||
.Aceptada .card-header,
|
||||
.Aceptada .card-body {
|
||||
background-color: transparent;
|
||||
}
|
||||
/* Estilos para la cabecera de la card */
|
||||
.card-header {
|
||||
padding: 0.75rem 1.25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-header h5 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.header-info {
|
||||
font-size: 0.9rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.header-info span {
|
||||
margin-right: 15px;
|
||||
}
|
||||
/* Estilos para el cuerpo de la card */
|
||||
.card-body {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
/* Estilos para los títulos de sección dentro de la card */
|
||||
.section-heading {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
font-size: 1.1em;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Denuncias en Gestión</h1>
|
||||
|
||||
<!-- Campo de búsqueda -->
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder="Buscar denuncias..."
|
||||
@bind="busqueda"
|
||||
@bind:event="oninput"
|
||||
style="margin-bottom:20px;" />
|
||||
|
||||
@if (!hasLoaded)
|
||||
{
|
||||
<div class="alert alert-info">Cargando datos...</div>
|
||||
}
|
||||
else if (denunciasGestiona == null || !denunciasGestiona.Any())
|
||||
{
|
||||
<p>No hay denuncias en gestión.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="gestion-list">
|
||||
@foreach (var denuncia in denunciasGestiona.Where(d =>
|
||||
string.IsNullOrWhiteSpace(busqueda) ||
|
||||
d.Id_Denuncia.ToString().Contains(busqueda) ||
|
||||
(!string.IsNullOrEmpty(d.NombreDenuncia) && d.NombreDenuncia.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||||
(!string.IsNullOrEmpty(d.ArchivoElegido) && d.ArchivoElegido.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||||
(!string.IsNullOrEmpty(d.Estado) && d.Estado.Contains(busqueda, StringComparison.OrdinalIgnoreCase))
|
||||
))
|
||||
{
|
||||
var collapseId = $"collapse{denuncia.Id_Denuncia}";
|
||||
<div class="card collapse-card Aceptada">
|
||||
<div class="card-header" data-bs-toggle="collapse" data-bs-target="#@collapseId" aria-expanded="false" aria-controls="@collapseId">
|
||||
<h5 class="mb-0">Denuncia ID: @denuncia.Id_Denuncia</h5>
|
||||
<div class="header-info">
|
||||
<span><strong>Estado:</strong> @denuncia.Estado</span>
|
||||
<span><strong>Nombre:</strong> @denuncia.NombreDenuncia</span>
|
||||
<span><strong>Archivo:</strong> @denuncia.ArchivoElegido</span>
|
||||
<span><strong>Fecha de Subida:</strong> @denuncia.FechaSubidaAGestiona.ToString("dd/MM/yyyy")</span>
|
||||
<span><strong>Hora de Subida:</strong> @denuncia.FechaSubidaAGestiona.ToString("HH:mm")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="@collapseId" class="collapse">
|
||||
<div class="card-body">
|
||||
<!-- Datos Generales -->
|
||||
<h5 class="section-heading">Datos Generales</h5>
|
||||
<dl class="row">
|
||||
@if (denuncia.Id_RegistroDenuncia != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Registro Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_RegistroDenuncia</dd>
|
||||
}
|
||||
@if (denuncia.Id_Denuncia != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_Denuncia</dd>
|
||||
}
|
||||
@if (denuncia.Fecha != DateTime.MinValue)
|
||||
{
|
||||
<dt class="col-sm-3">Fecha</dt>
|
||||
<dd class="col-sm-9">@denuncia.Fecha.ToString("dd/MM/yyyy HH:mm")</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Expediente_Gestiona))
|
||||
{
|
||||
<dt class="col-sm-3">Expediente Gestión</dt>
|
||||
<dd class="col-sm-9">@denuncia.Expediente_Gestiona</dd>
|
||||
}
|
||||
@if (denuncia.Id_Persona_Gestiona != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Persona Gestión</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_Persona_Gestiona</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Etiqueta))
|
||||
{
|
||||
<dt class="col-sm-3">Etiqueta</dt>
|
||||
<dd class="col-sm-9">@denuncia.Etiqueta</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Datos del Denunciante -->
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Nombre) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Apellidos) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Sexo) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Dni))
|
||||
{
|
||||
<h5 class="section-heading">Datos del Denunciante</h5>
|
||||
<dl class="row">
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Nombre))
|
||||
{
|
||||
<dt class="col-sm-3">Nombre</dt>
|
||||
<dd class="col-sm-9">@denuncia.Nombre</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Apellidos))
|
||||
{
|
||||
<dt class="col-sm-3">Apellidos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Apellidos</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Sexo))
|
||||
{
|
||||
<dt class="col-sm-3">Sexo</dt>
|
||||
<dd class="col-sm-9">@denuncia.Sexo</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Dni))
|
||||
{
|
||||
<dt class="col-sm-3">DNI</dt>
|
||||
<dd class="col-sm-9">@denuncia.Dni</dd>
|
||||
}
|
||||
</dl>
|
||||
}
|
||||
|
||||
<!-- Detalles de la Denuncia -->
|
||||
<h5 class="section-heading">Detalles de la Denuncia</h5>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-3">Asunto</dt>
|
||||
<dd class="col-sm-9">@denuncia.Asunto</dd>
|
||||
<dt class="col-sm-3">A Quien Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.A_Quien_Denuncia</dd>
|
||||
<dt class="col-sm-3">Descripción Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Descripcion_Denuncia</dd>
|
||||
<dt class="col-sm-3">Denunciado Ante Inst</dt>
|
||||
<dd class="col-sm-9">@denuncia.Denunciado_Ante_Inst</dd>
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Modalidad_Informacion))
|
||||
{
|
||||
<dt class="col-sm-3">Modalidad Información</dt>
|
||||
<dd class="col-sm-9">@denuncia.Modalidad_Informacion</dd>
|
||||
}
|
||||
<dt class="col-sm-3">Lugar Hechos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Lugar_Hechos</dd>
|
||||
@if (denuncia.Fecha_Hechos != DateTime.MinValue)
|
||||
{
|
||||
<dt class="col-sm-3">Fecha Hechos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Fecha_Hechos.ToString("dd/MM/yyyy")</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Datos de Notificación -->
|
||||
<h5 class="section-heading">Datos de Notificación</h5>
|
||||
<dl class="row">
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Preferencia))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación Preferencia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Preferencia</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Electronica))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación Electrónica</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Electronica</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Correo_Electronico))
|
||||
{
|
||||
<dt class="col-sm-3">Correo Electrónico</dt>
|
||||
<dd class="col-sm-9">@denuncia.Correo_Electronico</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Sms))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación SMS</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Sms</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Otros -->
|
||||
<h5 class="section-heading">Otros</h5>
|
||||
<dl class="row">
|
||||
@if (denuncia.Condiciones)
|
||||
{
|
||||
<dt class="col-sm-3">Condiciones</dt>
|
||||
<dd class="col-sm-9">Sí</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Comments))
|
||||
{
|
||||
<dt class="col-sm-3">Comentarios</dt>
|
||||
<dd class="col-sm-9"><pre>@denuncia.Comments</pre></dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Ficheros adjuntos -->
|
||||
@if (ficherosAdjuntos.ContainsKey(denuncia.Id_Denuncia) && ficherosAdjuntos[denuncia.Id_Denuncia].Any())
|
||||
{
|
||||
<h5 class="section-heading">Ficheros Adjuntos</h5>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Tamaño (bytes)</th>
|
||||
<th>Ver</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var fichero in ficherosAdjuntos[denuncia.Id_Denuncia])
|
||||
{
|
||||
<tr>
|
||||
<td>@fichero.NombreFichero</td>
|
||||
<td>@fichero.Fichero.Length</td>
|
||||
<td>
|
||||
<a class="btn btn-primary btn-sm" href="#"
|
||||
onclick="openFile(event, '@Convert.ToBase64String(fichero.Fichero)', '@GetContentType(fichero.NombreFichero)');">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<script>
|
||||
function createObjectUrl(base64, contentType) {
|
||||
const binaryString = window.atob(base64);
|
||||
const len = binaryString.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([bytes], { type: contentType });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
function openFile(event, base64, contentType) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const objectUrl = createObjectUrl(base64, contentType);
|
||||
window.open(objectUrl, '_blank');
|
||||
}
|
||||
</script>
|
||||
|
||||
@code {
|
||||
private List<DenunciasGestiona> denunciasGestiona = new();
|
||||
private Dictionary<int, List<FicherosDenuncias>> ficherosAdjuntos = new();
|
||||
|
||||
// Variable para la búsqueda
|
||||
private string busqueda = "";
|
||||
|
||||
private const string DENUNCIAS_JSON = @"C:\ZipsDenuncias\denuncias.json";
|
||||
private const string FICHEROS_JSON = @"C:\ZipsDenuncias\ficheros.json";
|
||||
private bool isLoading = false;
|
||||
private bool hasLoaded = false;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userState.Token))
|
||||
{
|
||||
Navigation.NavigateTo("/", true);
|
||||
return;
|
||||
}
|
||||
isLoading = true;
|
||||
StateHasChanged();
|
||||
await CargarGestionaAsync();
|
||||
await CargarFicherosAdjuntosAsync();
|
||||
isLoading = false;
|
||||
hasLoaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CargarGestionaAsync()
|
||||
{
|
||||
var todas = await CargarDenunciasJsonAsync();
|
||||
denunciasGestiona = todas.Where(d => d.Expediente_Gestiona == "Gestiona").ToList();
|
||||
}
|
||||
|
||||
private async Task<List<DenunciasGestiona>> CargarDenunciasJsonAsync()
|
||||
{
|
||||
if (File.Exists(DENUNCIAS_JSON))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(DENUNCIAS_JSON);
|
||||
var lista = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DenunciasGestiona>>(json);
|
||||
return lista ?? new List<DenunciasGestiona>();
|
||||
}
|
||||
return new List<DenunciasGestiona>();
|
||||
}
|
||||
|
||||
private async Task<List<FicherosDenuncias>> CargarFicherosJsonAsync()
|
||||
{
|
||||
if (File.Exists(FICHEROS_JSON))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(FICHEROS_JSON);
|
||||
var lista = Newtonsoft.Json.JsonConvert.DeserializeObject<List<FicherosDenuncias>>(json);
|
||||
return lista ?? new List<FicherosDenuncias>();
|
||||
}
|
||||
return new List<FicherosDenuncias>();
|
||||
}
|
||||
|
||||
private async Task CargarFicherosAdjuntosAsync()
|
||||
{
|
||||
var listaFicheros = await CargarFicherosJsonAsync();
|
||||
ficherosAdjuntos = listaFicheros.GroupBy(f => f.Id_Denuncia)
|
||||
.ToDictionary(g => g.Key, g => g.ToList());
|
||||
}
|
||||
|
||||
private string GetContentType(string fileName)
|
||||
{
|
||||
var ext = Path.GetExtension(fileName).ToLowerInvariant();
|
||||
return ext switch
|
||||
{
|
||||
".jpg" or ".jpeg" => "image/jpeg",
|
||||
".png" => "image/png",
|
||||
".gif" => "image/gif",
|
||||
".pdf" => "application/pdf",
|
||||
".txt" => "text/plain",
|
||||
_ => "application/octet-stream",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
@page "/Instrucciones"
|
||||
@attribute [StreamRendering]
|
||||
@inject GestionaDenunciasAN.Models.UserState userState
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<PageTitle>Instrucciones</PageTitle>
|
||||
|
||||
<div class="container mt-4">
|
||||
<h1 class="mb-4">Instrucciones de la Aplicación</h1>
|
||||
<p>
|
||||
Bienvenido a la aplicación de <strong>Gestión de Denuncias</strong>. Esta herramienta ha sido diseñada para
|
||||
cargar, procesar y gestionar denuncias que se reciben a través de archivos ZIP. A continuación, se explica el funcionamiento y las principales funcionalidades:
|
||||
</p>
|
||||
|
||||
<h2>1. Carga y Procesamiento de Denuncias</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Carga de archivos:</strong> Los archivos ZIP se encuentran en la carpeta <code>Ejemplos</code>. Cada ZIP contiene un archivo <code>report.txt</code> con los datos de la denuncia, y en algunos casos, ficheros asociados.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Descompresión y parseo:</strong> La aplicación descomprime cada ZIP y extrae la información del <code>report.txt</code> para crear una representación estructurada de la denuncia.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>2. Visualización y Gestión de Denuncias</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Pendientes:</strong> En esta pestaña se listan todas las denuncias recién cargadas. Cada denuncia se muestra en una tarjeta colapsable que permite ver sus detalles y los ficheros asociados. Además, se disponen de botones para <em>Enviar a gestiona</em> (verde) y <em>Rechazar denuncia</em> (rojo). Actualmente, estos botones no realizan ninguna acción, pero en futuras versiones registrarán el estado de la denuncia.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Finalizados:</strong> Una vez procesadas, las denuncias se trasladan a la pestaña <strong>Finalizados</strong>, donde se muestran diferenciadas:
|
||||
<ul>
|
||||
<li>Las denuncias aceptadas se destacan con un fondo verde.</li>
|
||||
<li>Las denuncias rechazadas se muestran con un fondo rojo.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Visualización de ficheros:</strong> En cada tarjeta, el botón <em>Ver</em> abre una nueva pestaña para mostrar el contenido del fichero asociado.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>3. Flujo de Trabajo</h2>
|
||||
<p>
|
||||
El flujo de trabajo de la aplicación es el siguiente:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Los archivos ZIP se depositan en la carpeta <code>Ejemplos</code>.
|
||||
</li>
|
||||
<li>
|
||||
La aplicación descomprime los ZIP y parsea el archivo <code>report.txt</code> para extraer la información de cada denuncia.
|
||||
</li>
|
||||
<li>
|
||||
Las denuncias se muestran en la pestaña <strong>Pendientes</strong> en forma de tarjetas colapsables, donde puedes ver detalles y ficheros asociados.
|
||||
</li>
|
||||
<li>
|
||||
Las acciones para enviar o rechazar la denuncia se registrarán y, en consecuencia, se reflejará su estado en la pestaña <strong>Finalizados</strong>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Esta aplicación está diseñada para facilitar la gestión de denuncias de forma intuitiva. Si tienes cualquier duda o sugerencia, no dudes en ponerte en contacto con el equipo de soporte.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// Si no hay token, redirige al login
|
||||
if (string.IsNullOrEmpty(userState.Token))
|
||||
{
|
||||
Navigation.NavigateTo("/", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
344
Antifraude.Net/GestionaDenunciasAN/Components/Pages/Login.razor
Normal file
@@ -0,0 +1,344 @@
|
||||
@using BlazorBootstrap
|
||||
@using Layout
|
||||
@using Microsoft.AspNetCore.Mvc
|
||||
@using Newtonsoft.Json
|
||||
@using Newtonsoft.Json.Linq
|
||||
@using GestionaDenunciasAN.Models
|
||||
@using System.Net.Http.Headers
|
||||
@using System.Text
|
||||
@using System.Linq.Expressions
|
||||
@using Serialize.Linq.Serializers
|
||||
@using System.Security.Cryptography.X509Certificates
|
||||
@using System.Security.Cryptography
|
||||
@using bdAntifraude.db
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@layout EmptyLayout
|
||||
@page "/"
|
||||
@inject IHttpClientFactory HttpClientFactory
|
||||
@inject IHttpContextAccessor HttpContextAccessor
|
||||
@inject NavigationManager Navigation
|
||||
@inject UserState UserState
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<PageTitle>Gestión Denuncias - Oficina Antifraude de Andalucía</PageTitle>
|
||||
|
||||
<style>
|
||||
/* Contenedor que ocupa toda la altura de la ventana */
|
||||
.full-height {
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Columna izquierda con un degradado en azul */
|
||||
.left-side {
|
||||
background: linear-gradient(135deg, #5a9bd5, #2A5298);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Columna derecha con fondo claro */
|
||||
.right-side {
|
||||
background: linear-gradient(135deg, #ffffff, #dddddd);
|
||||
}
|
||||
|
||||
/* Contenedor para centrar contenido en ambas columnas */
|
||||
.centered-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
.logo-img {
|
||||
max-width: 300px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Caja de login con degradado y sombra */
|
||||
.login-box {
|
||||
background: linear-gradient(135deg, #5a9bd5, #2A5298);
|
||||
padding: 2rem;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #fff; /* Para que el texto sea legible sobre el gradiente */
|
||||
}
|
||||
|
||||
.login-box label {
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
text-align: left;
|
||||
margin-bottom: 0.3rem;
|
||||
color: #fff; /* Aseguramos que la etiqueta se vea bien */
|
||||
}
|
||||
|
||||
.login-box .form-control {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: red;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Botones personalizados */
|
||||
.login-box .btnOAAFAzul {
|
||||
background-color: #fff !important; /* Fondo blanco */
|
||||
color: #000 !important; /* Texto negro */
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.login-box .btnOAAFAzul:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.btnOAAFBlack {
|
||||
background-color: #343334;
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btnOAAFBlack:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Estilos para el loading */
|
||||
.loadingFrame {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.loadingDiv {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loadingImg {
|
||||
background: url('Content/imagenes/loading.gif') no-repeat center center;
|
||||
background-size: contain;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="faviconParlamento.ico" />
|
||||
<link href="~/bootstrap/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="Content/Site.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bloque de loading que se muestra mientras 'mostrar' es true -->
|
||||
@if (mostrar)
|
||||
{
|
||||
<div id="cargando" class="loadingFrame">
|
||||
<div class="loadingDiv">
|
||||
<div class="loadingImg"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Estructura en dos columnas -->
|
||||
<div class="container-fluid full-height px-0">
|
||||
<div class="row no-gutters full-height">
|
||||
<!-- Columna izquierda (más ancha) -->
|
||||
<div class="col-md-7 left-side">
|
||||
<div class="centered-content">
|
||||
<!-- Tu logo en grande -->
|
||||
<img src="Content/imagenes/logo-oaaf-negativo-transparente.svg" alt="Logo Oficina Antifraude" class="logo-img" />
|
||||
<h1>Oficina Antifraude de Andalucía</h1>
|
||||
<p style="max-width: 500px; text-align: center;">
|
||||
Bienvenido/a a la plataforma de gestión de denuncias.
|
||||
Aquí podrás autenticarte para revisar y tramitar las denuncias recibidas.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Columna derecha (más estrecha) -->
|
||||
<div class="col-md-5 right-side">
|
||||
<div class="centered-content">
|
||||
<form class="login-box">
|
||||
<h3 class="mb-4">Iniciar Sesión</h3>
|
||||
|
||||
<p id="mensajeError" class="error-message">@mensaje</p>
|
||||
|
||||
<div class="form-group text-left">
|
||||
<label for="Usu">Usuario</label>
|
||||
<input id="Usu" type="text" class="form-control" @bind="Usu" />
|
||||
</div>
|
||||
|
||||
<div class="form-group text-left">
|
||||
<label for="Contrasena">Contraseña</label>
|
||||
<input id="Contrasena" type="password" class="form-control" @bind="pass" />
|
||||
</div>
|
||||
|
||||
<button class="btnOAAFAzul" type="button" @onclick="LogIn">ENTRAR</button>
|
||||
<button class="btnOAAFBlack" type="button" @onclick="IniciarSesionConCertificado">INICIAR SESIÓN CON CERTIFICADO</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Iframe oculto para la autenticación con certificado -->
|
||||
<iframe id="authCertIframe" style="display:none;"></iframe>
|
||||
|
||||
@code {
|
||||
public string? Usu { get; set; }
|
||||
public string? pass { get; set; }
|
||||
private string? mensaje { get; set; }
|
||||
public bool mostrar { get; set; } = false;
|
||||
private DotNetObjectReference<Login>? dotNetRef;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
// Se crea una referencia a este componente para que JS pueda invocar SetToken
|
||||
dotNetRef = DotNetObjectReference.Create(this);
|
||||
await JSRuntime.InvokeVoidAsync("registerTokenReceiver", dotNetRef);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
LimpiarEstadoUsuario();
|
||||
}
|
||||
|
||||
private void LimpiarEstadoUsuario()
|
||||
{
|
||||
UserState.Token = "";
|
||||
UserState.NombreUsu = "";
|
||||
HttpContextAccessor?.HttpContext?.Session?.Clear();
|
||||
}
|
||||
|
||||
public async Task LogIn()
|
||||
{
|
||||
mostrar = true;
|
||||
await Task.Delay(1);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Usu) || string.IsNullOrWhiteSpace(pass))
|
||||
{
|
||||
mostrar = false;
|
||||
mensaje = "Por favor, ingrese su usuario y contraseña.";
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var client = HttpClientFactory.CreateClient();
|
||||
client.BaseAddress = new Uri(Utilidades.urlSwagger());
|
||||
var loginPayload = new { NombreUsuario = Usu, Contraseña = pass, Origen = "Denuncias" };
|
||||
var loginContent = new StringContent(JsonConvert.SerializeObject(loginPayload), Encoding.UTF8, "application/json");
|
||||
var loginResponse = await client.PostAsync("Auth/login", loginContent);
|
||||
await ProcesarRespuesta(loginResponse);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
mostrar = false;
|
||||
mensaje = $"Error inesperado: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task IniciarSesionConCertificado()
|
||||
{
|
||||
mostrar = true;
|
||||
var url = Utilidades.urlSwagger() + "Auth/login-cert?iframe=true";
|
||||
await JSRuntime.InvokeVoidAsync("iniciarSesionConCertificado", url);
|
||||
}
|
||||
|
||||
private async Task ProcesarRespuesta(HttpResponseMessage response)
|
||||
{
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var parsedJson = JObject.Parse(responseContent);
|
||||
UserState.Token = parsedJson["token"]?.ToString() ?? "";
|
||||
// Actualizamos el nombre del usuario (formateado como "APELLIDOS, NOMBRE")
|
||||
UserState.NombreUsu = $"{parsedJson["user"]?["apellidos"]?.ToString()}, {parsedJson["user"]?["nombre"]?.ToString()}";
|
||||
Navigation.NavigateTo("/GestionZip", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mostrar = false;
|
||||
mensaje = "Error de autenticación. Verifique sus credenciales o el certificado.";
|
||||
}
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public Task SetToken(string token, string userJson)
|
||||
{
|
||||
// Actualizamos el token en UserState
|
||||
UserState.Token = token;
|
||||
try
|
||||
{
|
||||
var userObj = JObject.Parse(userJson);
|
||||
UserState.NombreUsu = $"{userObj["APELLIDOS"]?.ToString()}, {userObj["NOMBRE"]?.ToString()}";
|
||||
}
|
||||
catch
|
||||
{
|
||||
UserState.NombreUsu = "";
|
||||
}
|
||||
Navigation.NavigateTo("/GestionZip", true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
<script>
|
||||
function registerTokenReceiver(dotnetRef) {
|
||||
window.dotnetTokenReceiver = dotnetRef;
|
||||
}
|
||||
|
||||
window.iniciarSesionConCertificado = function(url) {
|
||||
console.log("Se llamó iniciarSesionConCertificado con URL:", url);
|
||||
var iframe = document.getElementById("authCertIframe");
|
||||
if (iframe) {
|
||||
iframe.src = url;
|
||||
} else {
|
||||
console.error("No se encontró el iframe con id 'authCertIframe'");
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", function(event) {
|
||||
var data = event.data;
|
||||
if (data && data.token) {
|
||||
console.log("Mensaje recibido con token:", data.token);
|
||||
if (window.dotnetTokenReceiver) {
|
||||
window.dotnetTokenReceiver.invokeMethodAsync("SetToken", data.token, JSON.stringify(data.user));
|
||||
} else {
|
||||
localStorage.setItem("token", data.token);
|
||||
localStorage.setItem("user", JSON.stringify(data.user));
|
||||
window.location.href = "/GestionZip";
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,664 @@
|
||||
@page "/Pendientes"
|
||||
@rendermode InteractiveServer
|
||||
@using GestionaDenunciasAN.Models
|
||||
@using System.Globalization
|
||||
@using System.IO
|
||||
@using System.Linq
|
||||
@using System.Text
|
||||
@using GestionaDenunciasAN.Helpers // Para PdfHelper
|
||||
@attribute [StreamRendering]
|
||||
@inject GestionaDenunciasAN.Models.UserState userState
|
||||
@inject NavigationManager Navigation
|
||||
@inject IHostEnvironment HostEnvironment
|
||||
|
||||
<PageTitle>Denuncias Pendientes</PageTitle>
|
||||
|
||||
<style>
|
||||
.seleccionar-col {
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Contenedor para la lista de denuncias */
|
||||
.pendientes-list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
/* Estilo general para cada card, con animaciones y transiciones */
|
||||
.collapse-card {
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.collapse-card:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
/* Estilos para la cabecera de la card */
|
||||
.card-header {
|
||||
padding: 0.75rem 1.25rem;
|
||||
cursor: pointer;
|
||||
background-color: #f7f7f7;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.card-header:hover {
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
/* Estilos para los títulos de sección */
|
||||
.section-heading {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
font-size: 1.1em;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
/* Estilos personalizados para el modal (envío a gestión y rechazo) */
|
||||
.custom-modal {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.custom-modal-dialog {
|
||||
max-width: 500px;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.custom-modal-content {
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.custom-modal-header {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-top-right-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.custom-modal-body {
|
||||
padding: 1.5rem;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.custom-modal-footer {
|
||||
border-top: none;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.modal-section-heading {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 0.5rem;
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.custom-file-list .list-group-item {
|
||||
transition: background-color 0.2s ease;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-file-list .list-group-item:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.custom-file-list .list-group-item.active {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
.preselect-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.preselect-btn i {
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.preselect-btn.selected i {
|
||||
color: #28a745;
|
||||
}
|
||||
|
||||
.preselect-btn:not(.selected) i {
|
||||
color: #6c757d;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Denuncias Pendientes</h1>
|
||||
|
||||
<!-- Campo de búsqueda en tiempo real -->
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder="Buscar denuncias..."
|
||||
@bind="busqueda"
|
||||
@bind:event="oninput"
|
||||
style="margin-bottom:20px;" />
|
||||
|
||||
@if (!hasLoaded)
|
||||
{
|
||||
<div class="alert alert-info">Cargando datos...</div>
|
||||
}
|
||||
else if (pendientes == null || !pendientes.Any())
|
||||
{
|
||||
<p>No hay denuncias pendientes.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="pendientes-list">
|
||||
@foreach (var denuncia in pendientes.Where(d =>
|
||||
string.IsNullOrWhiteSpace(busqueda) ||
|
||||
d.Id_Denuncia.ToString().Contains(busqueda) ||
|
||||
(!string.IsNullOrEmpty(d.Asunto) && d.Asunto.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||||
(!string.IsNullOrEmpty(d.Nombre) && d.Nombre.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||||
(!string.IsNullOrEmpty(d.Apellidos) && d.Apellidos.Contains(busqueda, StringComparison.OrdinalIgnoreCase))
|
||||
))
|
||||
{
|
||||
var collapseId = $"collapse{denuncia.Id_Denuncia}";
|
||||
<div class="card mb-2 collapse-card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#@collapseId"
|
||||
aria-expanded="false"
|
||||
aria-controls="@collapseId">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mb-0">Denuncia ID: @denuncia.Id_Denuncia</h5>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-success btn-sm me-2"
|
||||
@onclick:stopPropagation="true"
|
||||
@onclick="() => OpenEnviarAGestionaModal(denuncia)">
|
||||
Configurar subida
|
||||
</button>
|
||||
<button class="btn btn-danger btn-sm"
|
||||
@onclick:stopPropagation="true"
|
||||
@onclick="() => OpenRechazarModal(denuncia)">
|
||||
Rechazar denuncia
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="@collapseId" class="collapse">
|
||||
<div class="card-body">
|
||||
<!-- Datos Generales -->
|
||||
<h5 class="section-heading">Datos Generales</h5>
|
||||
<dl class="row">
|
||||
@if (denuncia.Id_RegistroDenuncia != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Registro Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_RegistroDenuncia</dd>
|
||||
}
|
||||
@if (denuncia.Id_Denuncia != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_Denuncia</dd>
|
||||
}
|
||||
@if (denuncia.Fecha != DateTime.MinValue)
|
||||
{
|
||||
<dt class="col-sm-3">Fecha</dt>
|
||||
<dd class="col-sm-9">@denuncia.Fecha.ToString("dd/MM/yyyy HH:mm")</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Expediente_Gestiona))
|
||||
{
|
||||
<dt class="col-sm-3">Expediente Gestiona</dt>
|
||||
<dd class="col-sm-9">@denuncia.Expediente_Gestiona</dd>
|
||||
}
|
||||
@if (denuncia.Id_Persona_Gestiona != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Persona Gestiona</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_Persona_Gestiona</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Etiqueta))
|
||||
{
|
||||
<dt class="col-sm-3">Etiqueta</dt>
|
||||
<dd class="col-sm-9">@denuncia.Etiqueta</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Estado))
|
||||
{
|
||||
<dt class="col-sm-3">Estado</dt>
|
||||
<dd class="col-sm-9">@denuncia.Estado</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Tipo_Denuncia))
|
||||
{
|
||||
<dt class="col-sm-3">Tipo Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Tipo_Denuncia</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Datos del Denunciante -->
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Nombre) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Apellidos) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Sexo) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Dni))
|
||||
{
|
||||
<h5 class="section-heading">Datos del Denunciante</h5>
|
||||
<dl class="row">
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Nombre))
|
||||
{
|
||||
<dt class="col-sm-3">Nombre</dt>
|
||||
<dd class="col-sm-9">@denuncia.Nombre</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Apellidos))
|
||||
{
|
||||
<dt class="col-sm-3">Apellidos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Apellidos</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Sexo))
|
||||
{
|
||||
<dt class="col-sm-3">Sexo</dt>
|
||||
<dd class="col-sm-9">@denuncia.Sexo</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Dni))
|
||||
{
|
||||
<dt class="col-sm-3">DNI</dt>
|
||||
<dd class="col-sm-9">@denuncia.Dni</dd>
|
||||
}
|
||||
</dl>
|
||||
}
|
||||
|
||||
<!-- Detalles de la Denuncia -->
|
||||
<h5 class="section-heading">Detalles de la Denuncia</h5>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-3">Asunto</dt>
|
||||
<dd class="col-sm-9">@denuncia.Asunto</dd>
|
||||
<dt class="col-sm-3">A Quien Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.A_Quien_Denuncia</dd>
|
||||
<dt class="col-sm-3">Descripción Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Descripcion_Denuncia</dd>
|
||||
<dt class="col-sm-3">Denunciado Ante Inst</dt>
|
||||
<dd class="col-sm-9">@denuncia.Denunciado_Ante_Inst</dd>
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Modalidad_Informacion))
|
||||
{
|
||||
<dt class="col-sm-3">Modalidad Información</dt>
|
||||
<dd class="col-sm-9">@denuncia.Modalidad_Informacion</dd>
|
||||
}
|
||||
<dt class="col-sm-3">Lugar Hechos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Lugar_Hechos</dd>
|
||||
@if (denuncia.Fecha_Hechos != DateTime.MinValue)
|
||||
{
|
||||
<dt class="col-sm-3">Fecha Hechos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Fecha_Hechos.ToString("dd/MM/yyyy")</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Datos de Notificación -->
|
||||
<h5 class="section-heading">Datos de Notificación</h5>
|
||||
<dl class="row">
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Preferencia))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación Preferencia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Preferencia</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Electronica))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación Electrónica</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Electronica</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Correo_Electronico))
|
||||
{
|
||||
<dt class="col-sm-3">Correo Electrónico</dt>
|
||||
<dd class="col-sm-9">@denuncia.Correo_Electronico</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Sms))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación SMS</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Sms</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Otros -->
|
||||
<h5 class="section-heading">Otros</h5>
|
||||
<dl class="row">
|
||||
@if (denuncia.Condiciones)
|
||||
{
|
||||
<dt class="col-sm-3">Condiciones</dt>
|
||||
<dd class="col-sm-9">Sí</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Comments))
|
||||
{
|
||||
<dt class="col-sm-3">Comentarios</dt>
|
||||
<dd class="col-sm-9"><pre>@denuncia.Comments</pre></dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Ficheros adjuntos (lista principal) -->
|
||||
@if (ficherosAdjuntos.ContainsKey(denuncia.Id_Denuncia) && ficherosAdjuntos[denuncia.Id_Denuncia].Any())
|
||||
{
|
||||
<h5 class="section-heading">Ficheros Adjuntos</h5>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="seleccionar-col">Seleccionar</th>
|
||||
<th>Nombre</th>
|
||||
<th>Tamaño (bytes)</th>
|
||||
<th>Ver</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var fichero in ficherosAdjuntos[denuncia.Id_Denuncia])
|
||||
{
|
||||
<tr>
|
||||
<td class="seleccionar-col">
|
||||
<button class="preselect-btn @(preselectedFicheros.ContainsKey(denuncia.Id_Denuncia) && preselectedFicheros[denuncia.Id_Denuncia] == fichero.NombreFichero ? "selected" : "")"
|
||||
@onclick="() => PreselectFichero(denuncia.Id_Denuncia, fichero.NombreFichero)">
|
||||
@if (preselectedFicheros.ContainsKey(denuncia.Id_Denuncia) && preselectedFicheros[denuncia.Id_Denuncia] == fichero.NombreFichero)
|
||||
{
|
||||
<i class="bi bi-check-circle-fill"></i>
|
||||
}
|
||||
else
|
||||
{
|
||||
<i class="bi bi-circle"></i>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
<td>@fichero.NombreFichero</td>
|
||||
<td>@fichero.Fichero.Length</td>
|
||||
<td>
|
||||
<a class="btn btn-primary btn-sm" href="#"
|
||||
onclick="openFile(event, '@Convert.ToBase64String(fichero.Fichero)', '@GetContentType(fichero.NombreFichero)');">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<script>
|
||||
function createObjectUrl(base64, contentType) {
|
||||
const binaryString = window.atob(base64);
|
||||
const len = binaryString.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([bytes], { type: contentType });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
function openFile(event, base64, contentType) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const objectUrl = createObjectUrl(base64, contentType);
|
||||
window.open(objectUrl, '_blank');
|
||||
}
|
||||
</script>
|
||||
|
||||
@* Modal para Configurar Subida a Gestión *@
|
||||
@if (showModal && selectedDenuncias != null)
|
||||
{
|
||||
<div class="modal custom-modal fade show" style="display:block;" tabindex="-1">
|
||||
<div class="modal-dialog custom-modal-dialog">
|
||||
<div class="modal-content custom-modal-content">
|
||||
<div class="modal-header custom-modal-header">
|
||||
<h5 class="modal-title">Enviar a Gestión</h5>
|
||||
<button type="button" class="btn-close" @onclick="CloseModal"></button>
|
||||
</div>
|
||||
<div class="modal-body custom-modal-body">
|
||||
<h6 class="modal-section-heading">Información de la Denuncia</h6>
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" @bind="nuevoNombre" placeholder="Ingrese el nombre de la denuncia" />
|
||||
</div>
|
||||
<h6 class="modal-section-heading">Selecciona el Fichero</h6>
|
||||
<div class="mb-3">
|
||||
<ul class="list-group custom-file-list">
|
||||
@if (ficherosAdjuntos.ContainsKey(selectedDenuncias.Id_Denuncia))
|
||||
{
|
||||
foreach (var fichero in ficherosAdjuntos[selectedDenuncias.Id_Denuncia])
|
||||
{
|
||||
<li class="list-group-item @(archivoSeleccionado == fichero.NombreFichero ? "active" : "")"
|
||||
@onclick="() => SelectArchivo(fichero.NombreFichero)">
|
||||
<span>@fichero.NombreFichero</span>
|
||||
<button class="btn btn-primary btn-sm"
|
||||
onclick="openFile(event, '@Convert.ToBase64String(fichero.Fichero)', '@GetContentType(fichero.NombreFichero)')">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</button>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
<li class="list-group-item @(archivoSeleccionado == reportTxt ? "active" : "")"
|
||||
@onclick="() => SelectArchivo(reportTxt)">
|
||||
<span>report.txt</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer custom-modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CloseModal">Cancelar</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="ConfirmarEnvio">Confirmar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-backdrop fade show"></div>
|
||||
}
|
||||
|
||||
@* Modal para Rechazar Denuncia *@
|
||||
@if (showModalRechazo && selectedDenuncias != null)
|
||||
{
|
||||
<div class="modal custom-modal fade show" style="display:block;" tabindex="-1">
|
||||
<div class="modal-dialog custom-modal-dialog">
|
||||
<div class="modal-content custom-modal-content">
|
||||
<div class="modal-header custom-modal-header">
|
||||
<h5 class="modal-title">Rechazar Denuncia</h5>
|
||||
<button type="button" class="btn-close" @onclick="CloseRechazoModal"></button>
|
||||
</div>
|
||||
<div class="modal-body custom-modal-body">
|
||||
<h6 class="modal-section-heading">Motivo de Rechazo</h6>
|
||||
<div class="mb-3">
|
||||
<input type="text" class="form-control" @bind="motivoRechazo" placeholder="Ingrese el motivo de rechazo" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer custom-modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CloseRechazoModal">Cancelar</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="ConfirmarRechazo">Confirmar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-backdrop fade show"></div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private const string reportTxt = "report.txt";
|
||||
private const string FIXED_PATH = @"C:\ZipsDenuncias";
|
||||
|
||||
private string busqueda = "";
|
||||
private List<DenunciasGestiona> pendientes = new();
|
||||
private Dictionary<int, List<FicherosDenuncias>> ficherosAdjuntos = new();
|
||||
private Dictionary<int, string> preselectedFicheros = new();
|
||||
|
||||
private const string DENUNCIAS_JSON = @"C:\ZipsDenuncias\denuncias.json";
|
||||
private const string FICHEROS_JSON = @"C:\ZipsDenuncias\ficheros.json";
|
||||
|
||||
private bool hasLoaded = false;
|
||||
private bool showModal = false;
|
||||
private bool showModalRechazo = false;
|
||||
|
||||
private DenunciasGestiona selectedDenuncias;
|
||||
private string nuevoNombre;
|
||||
private string archivoSeleccionado = reportTxt;
|
||||
private string motivoRechazo;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userState.Token))
|
||||
{
|
||||
Navigation.NavigateTo("/", true);
|
||||
return;
|
||||
}
|
||||
await CargarDatosAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CargarDatosAsync()
|
||||
{
|
||||
var todas = await CargarDenunciasJsonAsync();
|
||||
pendientes = todas.Where(d => d.Expediente_Gestiona == "Pendiente").ToList();
|
||||
|
||||
var listaF = await CargarFicherosJsonAsync();
|
||||
ficherosAdjuntos = listaF
|
||||
.GroupBy(f => f.Id_Denuncia)
|
||||
.ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
hasLoaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task<List<DenunciasGestiona>> CargarDenunciasJsonAsync()
|
||||
{
|
||||
if (!File.Exists(DENUNCIAS_JSON)) return new();
|
||||
var json = await File.ReadAllTextAsync(DENUNCIAS_JSON);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<List<DenunciasGestiona>>(json)
|
||||
?? new List<DenunciasGestiona>();
|
||||
}
|
||||
|
||||
private async Task<List<FicherosDenuncias>> CargarFicherosJsonAsync()
|
||||
{
|
||||
if (!File.Exists(FICHEROS_JSON)) return new();
|
||||
var json = await File.ReadAllTextAsync(FICHEROS_JSON);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<List<FicherosDenuncias>>(json)
|
||||
?? new List<FicherosDenuncias>();
|
||||
}
|
||||
|
||||
private async Task ConfirmarEnvio()
|
||||
{
|
||||
if (selectedDenuncias == null)
|
||||
return;
|
||||
|
||||
// 1) Recolectar todos los ficheros adjuntos
|
||||
var todos = new List<(string FileName, byte[] Content)>();
|
||||
if (ficherosAdjuntos.TryGetValue(selectedDenuncias.Id_Denuncia, out var listaAdjuntos))
|
||||
{
|
||||
todos.AddRange(listaAdjuntos.Select(f => (f.NombreFichero, f.Fichero)));
|
||||
}
|
||||
|
||||
// 2) Buscar y añadir report.txt correspondiente a esta denuncia
|
||||
// Se busca en todos los subdirectorios de FIXED_PATH los report.txt
|
||||
var reportFiles = Directory.GetFiles(FIXED_PATH, "report.txt", SearchOption.AllDirectories);
|
||||
foreach (var rpt in reportFiles)
|
||||
{
|
||||
// Leer encabezado para verificar que es el report de esta denuncia
|
||||
var contenido = await File.ReadAllTextAsync(rpt, Encoding.UTF8);
|
||||
if (contenido.Contains($"ID: {selectedDenuncias.Id_Denuncia}"))
|
||||
{
|
||||
todos.Add(("report.txt", Encoding.UTF8.GetBytes(contenido)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Fusionar todos los ficheros (incluyendo report.txt) en un único PDF
|
||||
var pdfBytes = PdfHelper.MergeFilesToPdf(todos);
|
||||
|
||||
// 4) Guardar el PDF combinado
|
||||
var outDir = Path.Combine(FIXED_PATH, "CombinedPdfs");
|
||||
Directory.CreateDirectory(outDir);
|
||||
var pdfName = $"Denuncia_{selectedDenuncias.Id_Denuncia}.pdf";
|
||||
var pdfPath = Path.Combine(outDir, pdfName);
|
||||
await File.WriteAllBytesAsync(pdfPath, pdfBytes);
|
||||
|
||||
// 5) Actualizar la denuncia
|
||||
selectedDenuncias.ArchivoElegido = pdfName;
|
||||
selectedDenuncias.NombreDenuncia = nuevoNombre;
|
||||
selectedDenuncias.Expediente_Gestiona = "Gestiona";
|
||||
selectedDenuncias.FechaSubidaAGestiona = DateTime.Now;
|
||||
await ActualizarDenunciaAsync(selectedDenuncias);
|
||||
|
||||
// 6) Refrescar UI
|
||||
pendientes.Remove(selectedDenuncias);
|
||||
CloseModal();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private async Task ConfirmarRechazo()
|
||||
{
|
||||
if (selectedDenuncias == null) return;
|
||||
|
||||
selectedDenuncias.Expediente_Gestiona = "Rechazada";
|
||||
selectedDenuncias.NombreDenuncia = motivoRechazo;
|
||||
selectedDenuncias.FechaSubidaAGestiona = DateTime.Now;
|
||||
await ActualizarDenunciaAsync(selectedDenuncias);
|
||||
|
||||
pendientes.Remove(selectedDenuncias);
|
||||
CloseRechazoModal();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ActualizarDenunciaAsync(DenunciasGestiona d)
|
||||
{
|
||||
var todas = await CargarDenunciasJsonAsync();
|
||||
var reg = todas.FirstOrDefault(x => x.Id_Denuncia == d.Id_Denuncia);
|
||||
if (reg != null)
|
||||
{
|
||||
reg.Expediente_Gestiona = d.Expediente_Gestiona;
|
||||
reg.ArchivoElegido = d.ArchivoElegido;
|
||||
reg.NombreDenuncia = d.NombreDenuncia;
|
||||
reg.FechaSubidaAGestiona = d.FechaSubidaAGestiona;
|
||||
}
|
||||
var json = Newtonsoft.Json.JsonConvert.SerializeObject(todas, Newtonsoft.Json.Formatting.Indented);
|
||||
await File.WriteAllTextAsync(DENUNCIAS_JSON, json);
|
||||
}
|
||||
|
||||
private void OpenEnviarAGestionaModal(DenunciasGestiona d)
|
||||
{
|
||||
selectedDenuncias = d;
|
||||
nuevoNombre = string.Empty;
|
||||
archivoSeleccionado = preselectedFicheros.GetValueOrDefault(d.Id_Denuncia, reportTxt);
|
||||
showModal = true;
|
||||
}
|
||||
|
||||
private void OpenRechazarModal(DenunciasGestiona d)
|
||||
{
|
||||
selectedDenuncias = d;
|
||||
motivoRechazo = string.Empty;
|
||||
showModalRechazo = true;
|
||||
}
|
||||
|
||||
private void CloseModal() =>
|
||||
(showModal, selectedDenuncias, nuevoNombre, archivoSeleccionado) =
|
||||
(false, null, string.Empty, reportTxt);
|
||||
|
||||
private void CloseRechazoModal() =>
|
||||
(showModalRechazo, selectedDenuncias, motivoRechazo) =
|
||||
(false, null, string.Empty);
|
||||
|
||||
private void SelectArchivo(string f) => archivoSeleccionado = f;
|
||||
private void PreselectFichero(int id, string f) => preselectedFicheros[id] = f;
|
||||
|
||||
private string GetContentType(string fileName)
|
||||
{
|
||||
return Path.GetExtension(fileName).ToLowerInvariant() switch
|
||||
{
|
||||
".jpg" or ".jpeg" => "image/jpeg",
|
||||
".png" => "image/png",
|
||||
".gif" => "image/gif",
|
||||
".pdf" => "application/pdf",
|
||||
".txt" => "text/plain",
|
||||
_ => "application/octet-stream",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
@page "/Rechazados"
|
||||
@rendermode InteractiveServer
|
||||
@using GestionaDenunciasAN.Models
|
||||
@using System.Globalization
|
||||
@attribute [StreamRendering]
|
||||
@inject GestionaDenunciasAN.Models.UserState userState
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<PageTitle>Denuncias Rechazadas</PageTitle>
|
||||
|
||||
<style>
|
||||
/* Contenedor para la lista de denuncias */
|
||||
.rechazados-list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
/* Estilo general para cada card */
|
||||
.collapse-card {
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.collapse-card:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
/* Aplicar fondo rojo a toda la card */
|
||||
.Rechazada {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
/* Forzar fondo transparente en cabecera y cuerpo para que hereden el color de la card */
|
||||
.Rechazada .card-header,
|
||||
.Rechazada .card-body {
|
||||
background-color: transparent;
|
||||
}
|
||||
/* Estilos para la cabecera de la card */
|
||||
.card-header {
|
||||
padding: 0.75rem 1.25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-header h5 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.header-info {
|
||||
font-size: 0.9rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.header-info span {
|
||||
margin-right: 15px;
|
||||
}
|
||||
/* Estilos para el cuerpo de la card */
|
||||
.card-body {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
/* Estilos para los títulos de sección dentro de la card */
|
||||
.section-heading {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
font-size: 1.1em;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Denuncias Rechazadas</h1>
|
||||
|
||||
<!-- Campo de búsqueda -->
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
placeholder="Buscar denuncias..."
|
||||
@bind="busqueda"
|
||||
@bind:event="oninput"
|
||||
style="margin-bottom:20px;" />
|
||||
|
||||
@if (!hasLoaded)
|
||||
{
|
||||
<div class="alert alert-info">Cargando datos...</div>
|
||||
}
|
||||
else if (denunciasRechazadas == null || !denunciasRechazadas.Any())
|
||||
{
|
||||
<p>No hay denuncias rechazadas.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="rechazados-list">
|
||||
@foreach (var denuncia in denunciasRechazadas.Where(d =>
|
||||
string.IsNullOrWhiteSpace(busqueda) ||
|
||||
d.Id_Denuncia.ToString().Contains(busqueda) ||
|
||||
(!string.IsNullOrEmpty(d.NombreDenuncia) && d.NombreDenuncia.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||||
(!string.IsNullOrEmpty(d.Estado) && d.Estado.Contains(busqueda, StringComparison.OrdinalIgnoreCase))
|
||||
))
|
||||
{
|
||||
var collapseId = $"collapse{denuncia.Id_Denuncia}";
|
||||
<div class="card collapse-card Rechazada">
|
||||
<div class="card-header" data-bs-toggle="collapse" data-bs-target="#@collapseId" aria-expanded="false" aria-controls="@collapseId">
|
||||
<h5 class="mb-0">Denuncia ID: @denuncia.Id_Denuncia</h5>
|
||||
<div class="header-info">
|
||||
<span><strong>Estado:</strong> @denuncia.Estado</span>
|
||||
<span><strong>Motivo de rechazo:</strong> @denuncia.NombreDenuncia</span>
|
||||
<span><strong>Fecha Rechazada:</strong> @denuncia.FechaSubidaAGestiona.ToString("dd/MM/yyyy")</span>
|
||||
<span><strong>Hora Rechazada:</strong> @denuncia.FechaSubidaAGestiona.ToString("HH:mm")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="@collapseId" class="collapse">
|
||||
<div class="card-body">
|
||||
<!-- Datos Generales -->
|
||||
<h5 class="section-heading">Datos Generales</h5>
|
||||
<dl class="row">
|
||||
@if (denuncia.Id_RegistroDenuncia != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Registro Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_RegistroDenuncia</dd>
|
||||
}
|
||||
@if (denuncia.Id_Denuncia != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_Denuncia</dd>
|
||||
}
|
||||
@if (denuncia.Fecha != DateTime.MinValue)
|
||||
{
|
||||
<dt class="col-sm-3">Fecha</dt>
|
||||
<dd class="col-sm-9">@denuncia.Fecha.ToString("dd/MM/yyyy HH:mm")</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Expediente_Gestiona))
|
||||
{
|
||||
<dt class="col-sm-3">Expediente Gestión</dt>
|
||||
<dd class="col-sm-9">@denuncia.Expediente_Gestiona</dd>
|
||||
}
|
||||
@if (denuncia.Id_Persona_Gestiona != 0)
|
||||
{
|
||||
<dt class="col-sm-3">ID Persona Gestión</dt>
|
||||
<dd class="col-sm-9">@denuncia.Id_Persona_Gestiona</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Etiqueta))
|
||||
{
|
||||
<dt class="col-sm-3">Etiqueta</dt>
|
||||
<dd class="col-sm-9">@denuncia.Etiqueta</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Datos del Denunciante -->
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Nombre) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Apellidos) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Sexo) ||
|
||||
!string.IsNullOrWhiteSpace(denuncia.Dni))
|
||||
{
|
||||
<h5 class="section-heading">Datos del Denunciante</h5>
|
||||
<dl class="row">
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Nombre))
|
||||
{
|
||||
<dt class="col-sm-3">Nombre</dt>
|
||||
<dd class="col-sm-9">@denuncia.Nombre</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Apellidos))
|
||||
{
|
||||
<dt class="col-sm-3">Apellidos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Apellidos</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Sexo))
|
||||
{
|
||||
<dt class="col-sm-3">Sexo</dt>
|
||||
<dd class="col-sm-9">@denuncia.Sexo</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Dni))
|
||||
{
|
||||
<dt class="col-sm-3">DNI</dt>
|
||||
<dd class="col-sm-9">@denuncia.Dni</dd>
|
||||
}
|
||||
</dl>
|
||||
}
|
||||
|
||||
<!-- Detalles de la Denuncia -->
|
||||
<h5 class="section-heading">Detalles de la Denuncia</h5>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-3">Asunto</dt>
|
||||
<dd class="col-sm-9">@denuncia.Asunto</dd>
|
||||
<dt class="col-sm-3">A Quien Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.A_Quien_Denuncia</dd>
|
||||
<dt class="col-sm-3">Descripción Denuncia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Descripcion_Denuncia</dd>
|
||||
<dt class="col-sm-3">Denunciado Ante Inst</dt>
|
||||
<dd class="col-sm-9">@denuncia.Denunciado_Ante_Inst</dd>
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Modalidad_Informacion))
|
||||
{
|
||||
<dt class="col-sm-3">Modalidad Información</dt>
|
||||
<dd class="col-sm-9">@denuncia.Modalidad_Informacion</dd>
|
||||
}
|
||||
<dt class="col-sm-3">Lugar Hechos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Lugar_Hechos</dd>
|
||||
@if (denuncia.Fecha_Hechos != DateTime.MinValue)
|
||||
{
|
||||
<dt class="col-sm-3">Fecha Hechos</dt>
|
||||
<dd class="col-sm-9">@denuncia.Fecha_Hechos.ToString("dd/MM/yyyy")</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Datos de Notificación -->
|
||||
<h5 class="section-heading">Datos de Notificación</h5>
|
||||
<dl class="row">
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Preferencia))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación Preferencia</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Preferencia</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Electronica))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación Electrónica</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Electronica</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Correo_Electronico))
|
||||
{
|
||||
<dt class="col-sm-3">Correo Electrónico</dt>
|
||||
<dd class="col-sm-9">@denuncia.Correo_Electronico</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Sms))
|
||||
{
|
||||
<dt class="col-sm-3">Notificación SMS</dt>
|
||||
<dd class="col-sm-9">@denuncia.Notificacion_Sms</dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Otros -->
|
||||
<h5 class="section-heading">Otros</h5>
|
||||
<dl class="row">
|
||||
@if (denuncia.Condiciones)
|
||||
{
|
||||
<dt class="col-sm-3">Condiciones</dt>
|
||||
<dd class="col-sm-9">Sí</dd>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(denuncia.Comments))
|
||||
{
|
||||
<dt class="col-sm-3">Comentarios</dt>
|
||||
<dd class="col-sm-9"><pre>@denuncia.Comments</pre></dd>
|
||||
}
|
||||
</dl>
|
||||
|
||||
<!-- Ficheros adjuntos -->
|
||||
@if (ficherosAdjuntos.ContainsKey(denuncia.Id_Denuncia) && ficherosAdjuntos[denuncia.Id_Denuncia].Any())
|
||||
{
|
||||
<h5 class="section-heading">Ficheros Adjuntos</h5>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Tamaño (bytes)</th>
|
||||
<th>Ver</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var fichero in ficherosAdjuntos[denuncia.Id_Denuncia])
|
||||
{
|
||||
<tr>
|
||||
<td>@fichero.NombreFichero</td>
|
||||
<td>@fichero.Fichero.Length</td>
|
||||
<td>
|
||||
<a class="btn btn-primary btn-sm" href="#"
|
||||
onclick="openFile(event, '@Convert.ToBase64String(fichero.Fichero)', '@GetContentType(fichero.NombreFichero)');">
|
||||
<i class="bi bi-eye"></i> Ver
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<script>
|
||||
function createObjectUrl(base64, contentType) {
|
||||
const binaryString = window.atob(base64);
|
||||
const len = binaryString.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([bytes], { type: contentType });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
function openFile(event, base64, contentType) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const objectUrl = createObjectUrl(base64, contentType);
|
||||
window.open(objectUrl, '_blank');
|
||||
}
|
||||
</script>
|
||||
|
||||
@code {
|
||||
private List<DenunciasGestiona> denunciasRechazadas = new();
|
||||
private Dictionary<int, List<FicherosDenuncias>> ficherosAdjuntos = new();
|
||||
|
||||
// Variable para la búsqueda
|
||||
private string busqueda = "";
|
||||
|
||||
private const string DENUNCIAS_JSON = @"C:\ZipsDenuncias\denuncias.json";
|
||||
private const string FICHEROS_JSON = @"C:\ZipsDenuncias\ficheros.json";
|
||||
private bool isLoading = false;
|
||||
private bool hasLoaded = false;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userState.Token))
|
||||
{
|
||||
Navigation.NavigateTo("/", true);
|
||||
return;
|
||||
}
|
||||
isLoading = true;
|
||||
StateHasChanged();
|
||||
await CargarRechazadasAsync();
|
||||
await CargarFicherosAdjuntosAsync();
|
||||
isLoading = false;
|
||||
hasLoaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CargarRechazadasAsync()
|
||||
{
|
||||
var todas = await CargarDenunciasJsonAsync();
|
||||
denunciasRechazadas = todas.Where(d => d.Expediente_Gestiona == "Rechazada").ToList();
|
||||
}
|
||||
|
||||
private async Task<List<DenunciasGestiona>> CargarDenunciasJsonAsync()
|
||||
{
|
||||
if (File.Exists(DENUNCIAS_JSON))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(DENUNCIAS_JSON);
|
||||
var lista = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DenunciasGestiona>>(json);
|
||||
return lista ?? new List<DenunciasGestiona>();
|
||||
}
|
||||
return new List<DenunciasGestiona>();
|
||||
}
|
||||
|
||||
private async Task<List<FicherosDenuncias>> CargarFicherosJsonAsync()
|
||||
{
|
||||
if (File.Exists(FICHEROS_JSON))
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(FICHEROS_JSON);
|
||||
var lista = Newtonsoft.Json.JsonConvert.DeserializeObject<List<FicherosDenuncias>>(json);
|
||||
return lista ?? new List<FicherosDenuncias>();
|
||||
}
|
||||
return new List<FicherosDenuncias>();
|
||||
}
|
||||
|
||||
private async Task CargarFicherosAdjuntosAsync()
|
||||
{
|
||||
var listaFicheros = await CargarFicherosJsonAsync();
|
||||
ficherosAdjuntos = listaFicheros.GroupBy(f => f.Id_Denuncia)
|
||||
.ToDictionary(g => g.Key, g => g.ToList());
|
||||
}
|
||||
|
||||
private string GetContentType(string fileName)
|
||||
{
|
||||
var ext = Path.GetExtension(fileName).ToLowerInvariant();
|
||||
return ext switch
|
||||
{
|
||||
".jpg" or ".jpeg" => "image/jpeg",
|
||||
".png" => "image/png",
|
||||
".gif" => "image/gif",
|
||||
".pdf" => "application/pdf",
|
||||
".txt" => "text/plain",
|
||||
_ => "application/octet-stream",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<Router AppAssembly="typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
10
Antifraude.Net/GestionaDenunciasAN/Components/_Imports.razor
Normal file
@@ -0,0 +1,10 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using GestionaDenunciasAN
|
||||
@using GestionaDenunciasAN.Components
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazor.Bootstrap" Version="3.3.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="PdfSharpCore" Version="1.3.67" />
|
||||
<PackageReference Include="Serialize.Linq" Version="4.0.167" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="10.0.0-preview.3.25173.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\bdAntifraude\bdAntifraude.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
157
Antifraude.Net/GestionaDenunciasAN/Helpers/PdfHelper.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using PdfSharpCore.Drawing;
|
||||
using PdfSharpCore.Pdf;
|
||||
using PdfSharpCore.Pdf.IO;
|
||||
|
||||
namespace GestionaDenunciasAN.Helpers
|
||||
{
|
||||
public static class PdfHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Fusiona varios ficheros (PDF, imágenes, TXT) en un único PDF.
|
||||
/// Los .txt se renderizan con márgenes iguales, alineación a la izquierda y ajuste de líneas,
|
||||
/// preservando líneas en blanco.
|
||||
/// </summary>
|
||||
/// <param name="files">Secuencia de tuplas (FileName, ContentBytes)</param>
|
||||
/// <returns>Bytes del PDF combinado</returns>
|
||||
public static byte[] MergeFilesToPdf(IEnumerable<(string FileName, byte[] Content)> files)
|
||||
{
|
||||
if (files == null) throw new ArgumentNullException(nameof(files));
|
||||
|
||||
var outputDoc = new PdfDocument();
|
||||
|
||||
foreach (var (fileName, content) in files)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fileName) || content == null || content.Length == 0)
|
||||
throw new InvalidOperationException($"El archivo '{fileName}' no tiene contenido.");
|
||||
|
||||
var ext = Path.GetExtension(fileName).ToLowerInvariant();
|
||||
switch (ext)
|
||||
{
|
||||
case ".pdf":
|
||||
using (var src = PdfReader.Open(new MemoryStream(content), PdfDocumentOpenMode.Import))
|
||||
foreach (var page in src.Pages)
|
||||
outputDoc.AddPage(page);
|
||||
break;
|
||||
|
||||
case ".jpg":
|
||||
case ".jpeg":
|
||||
case ".png":
|
||||
case ".gif":
|
||||
using (var img = XImage.FromStream(() => new MemoryStream(content)))
|
||||
{
|
||||
var page = outputDoc.AddPage();
|
||||
page.Width = XUnit.FromPoint(img.PointWidth);
|
||||
page.Height = XUnit.FromPoint(img.PointHeight);
|
||||
using var gfxImg = XGraphics.FromPdfPage(page);
|
||||
gfxImg.DrawImage(img, 0, 0, page.Width, page.Height);
|
||||
}
|
||||
break;
|
||||
|
||||
case ".txt":
|
||||
// Renderizado de TXT con margen y ajuste de líneas, preservando líneas en blanco
|
||||
var text = Encoding.UTF8.GetString(content);
|
||||
PdfPage pageTxt = outputDoc.AddPage();
|
||||
XGraphics gfxTxt = XGraphics.FromPdfPage(pageTxt);
|
||||
|
||||
const double marginLeft = 40;
|
||||
const double marginRight = 40;
|
||||
const double marginTop = 40;
|
||||
const double marginBottom = 40;
|
||||
var font = new XFont("Courier New", 10, XFontStyle.Regular);
|
||||
var sample = gfxTxt.MeasureString("Ay", font);
|
||||
var lineHeight = sample.Height * 1.2;
|
||||
|
||||
double y = marginTop;
|
||||
double pageWidth = pageTxt.Width.Point;
|
||||
double pageHeight = pageTxt.Height.Point;
|
||||
double maxWidth = pageWidth - marginLeft - marginRight;
|
||||
|
||||
foreach (var origLine in text.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n'))
|
||||
{
|
||||
// Línea en blanco: preservarla
|
||||
if (string.IsNullOrWhiteSpace(origLine))
|
||||
{
|
||||
y += lineHeight;
|
||||
if (y + lineHeight > pageHeight - marginBottom)
|
||||
{
|
||||
gfxTxt.Dispose();
|
||||
pageTxt = outputDoc.AddPage();
|
||||
gfxTxt = XGraphics.FromPdfPage(pageTxt);
|
||||
y = marginTop;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var words = origLine.Split(' ');
|
||||
string currentLine = string.Empty;
|
||||
|
||||
foreach (var word in words)
|
||||
{
|
||||
var testLine = string.IsNullOrEmpty(currentLine) ? word : currentLine + " " + word;
|
||||
var size = gfxTxt.MeasureString(testLine, font);
|
||||
if (size.Width <= maxWidth)
|
||||
{
|
||||
currentLine = testLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dibujar la línea acumulada
|
||||
gfxTxt.DrawString(
|
||||
currentLine,
|
||||
font,
|
||||
XBrushes.Black,
|
||||
new XRect(marginLeft, y, maxWidth, lineHeight),
|
||||
XStringFormats.TopLeft);
|
||||
y += lineHeight;
|
||||
currentLine = word;
|
||||
|
||||
// Paginación si se sale por abajo
|
||||
if (y + lineHeight > pageHeight - marginBottom)
|
||||
{
|
||||
gfxTxt.Dispose();
|
||||
pageTxt = outputDoc.AddPage();
|
||||
gfxTxt = XGraphics.FromPdfPage(pageTxt);
|
||||
y = marginTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dibujar la última línea del párrafo
|
||||
if (!string.IsNullOrEmpty(currentLine))
|
||||
{
|
||||
gfxTxt.DrawString(
|
||||
currentLine,
|
||||
font,
|
||||
XBrushes.Black,
|
||||
new XRect(marginLeft, y, maxWidth, lineHeight),
|
||||
XStringFormats.TopLeft);
|
||||
y += lineHeight;
|
||||
|
||||
if (y + lineHeight > pageHeight - marginBottom)
|
||||
{
|
||||
gfxTxt.Dispose();
|
||||
pageTxt = outputDoc.AddPage();
|
||||
gfxTxt = XGraphics.FromPdfPage(pageTxt);
|
||||
y = marginTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfxTxt.Dispose();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"Extensión no soportada: {ext}");
|
||||
}
|
||||
}
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
outputDoc.Save(ms);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Antifraude.Net/GestionaDenunciasAN/Models/DenunciasGestiona.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
|
||||
namespace GestionaDenunciasAN.Models
|
||||
{
|
||||
public class DenunciasGestiona
|
||||
{
|
||||
// Propiedades existentes
|
||||
public int Id_RegistroDenuncia { get; set; }
|
||||
public int Id_Denuncia { get; set; }
|
||||
public DateTime Fecha { get; set; }
|
||||
public string Expediente_Gestiona { get; set; }
|
||||
public int Id_Persona_Gestiona { get; set; }
|
||||
public string Etiqueta { get; set; }
|
||||
public string Estado { get; set; }
|
||||
public string Tipo_Denuncia { get; set; }
|
||||
public string? Nombre { get; set; }
|
||||
public string? Apellidos { get; set; }
|
||||
public string? Sexo { get; set; }
|
||||
public string? Dni { get; set; }
|
||||
public string Asunto { get; set; }
|
||||
public string A_Quien_Denuncia { get; set; }
|
||||
public string Descripcion_Denuncia { get; set; }
|
||||
public string Denunciado_Ante_Inst { get; set; }
|
||||
public string? Modalidad_Informacion { get; set; }
|
||||
public string Lugar_Hechos { get; set; }
|
||||
public DateTime Fecha_Hechos { get; set; }
|
||||
public string? Notificacion_Preferencia { get; set; }
|
||||
public string? Notificacion_Electronica { get; set; }
|
||||
public string? Correo_Electronico { get; set; }
|
||||
public string? Notificacion_Sms { get; set; }
|
||||
public bool Condiciones { get; set; }
|
||||
public string? Comments { get; set; }
|
||||
|
||||
// Nuevas propiedades
|
||||
public string NombreDenuncia { get; set; }
|
||||
public string EstadoDenuncia { get; set; }
|
||||
public string ArchivoElegido { get; set; }
|
||||
public DateTime FechaSubidaAGestiona { get; set; } // Nueva propiedad
|
||||
|
||||
// Constructor por defecto
|
||||
public DenunciasGestiona()
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor parametrizado que inicializa todos los campos, incluida la nueva propiedad
|
||||
public DenunciasGestiona(
|
||||
int idRegistroDenuncia,
|
||||
int idDenuncia,
|
||||
DateTime fecha,
|
||||
string expedienteGestiona,
|
||||
int idPersonaGestiona,
|
||||
string etiqueta,
|
||||
string estado,
|
||||
string tipoDenuncia,
|
||||
string? nombre,
|
||||
string? apellidos,
|
||||
string? sexo,
|
||||
string? dni,
|
||||
string asunto,
|
||||
string aQuienDenuncia,
|
||||
string descripcionDenuncia,
|
||||
string denunciadoAnteInst,
|
||||
string? modalidadInformacion,
|
||||
string lugarHechos,
|
||||
DateTime fechaHechos,
|
||||
string? notificacionPreferencia,
|
||||
string? notificacionElectronica,
|
||||
string? correoElectronico,
|
||||
string? notificacionSms,
|
||||
bool condiciones,
|
||||
string? comments,
|
||||
string nombreDenuncia,
|
||||
string estadoDenuncia,
|
||||
string archivoElegido,
|
||||
DateTime fechaSubidaAGestiona)
|
||||
{
|
||||
Id_RegistroDenuncia = idRegistroDenuncia;
|
||||
Id_Denuncia = idDenuncia;
|
||||
Fecha = fecha;
|
||||
Expediente_Gestiona = expedienteGestiona;
|
||||
Id_Persona_Gestiona = idPersonaGestiona;
|
||||
Etiqueta = etiqueta;
|
||||
Estado = estado;
|
||||
Tipo_Denuncia = tipoDenuncia;
|
||||
Nombre = nombre;
|
||||
Apellidos = apellidos;
|
||||
Sexo = sexo;
|
||||
Dni = dni;
|
||||
Asunto = asunto;
|
||||
A_Quien_Denuncia = aQuienDenuncia;
|
||||
Descripcion_Denuncia = descripcionDenuncia;
|
||||
Denunciado_Ante_Inst = denunciadoAnteInst;
|
||||
Modalidad_Informacion = modalidadInformacion;
|
||||
Lugar_Hechos = lugarHechos;
|
||||
Fecha_Hechos = fechaHechos;
|
||||
Notificacion_Preferencia = notificacionPreferencia;
|
||||
Notificacion_Electronica = notificacionElectronica;
|
||||
Correo_Electronico = correoElectronico;
|
||||
Notificacion_Sms = notificacionSms;
|
||||
Condiciones = condiciones;
|
||||
Comments = comments;
|
||||
NombreDenuncia = nombreDenuncia;
|
||||
EstadoDenuncia = estadoDenuncia;
|
||||
ArchivoElegido = archivoElegido;
|
||||
FechaSubidaAGestiona = fechaSubidaAGestiona;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
|
||||
namespace GestionaDenunciasAN.Models
|
||||
{
|
||||
public class FicherosDenuncias
|
||||
{
|
||||
// Id del fichero
|
||||
public int Id_Fichero { get; set; }
|
||||
|
||||
// Id del tipo de fichero
|
||||
public int Id_Tipo { get; set; }
|
||||
|
||||
// Descripción del fichero (puede ser nula)
|
||||
public string? Descripcion { get; set; }
|
||||
|
||||
// Fecha de creación del fichero
|
||||
public DateTime Fecha { get; set; }
|
||||
|
||||
// Observaciones
|
||||
public string Observaciones { get; set; }
|
||||
|
||||
// Id de la denuncia al que está asociado (FK)
|
||||
public int Id_Denuncia { get; set; }
|
||||
|
||||
// NombreCarpeta_NombreFichero
|
||||
public string NombreFichero { get; set; }
|
||||
|
||||
// Fichero completo en formato byte array (BLOB)
|
||||
public byte[] Fichero { get; set; }
|
||||
|
||||
// Constructor por defecto
|
||||
public FicherosDenuncias()
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor parametrizado que inicializa todos los campos
|
||||
public FicherosDenuncias(
|
||||
int id_Fichero,
|
||||
int id_Tipo,
|
||||
string? descripcion,
|
||||
DateTime fecha,
|
||||
string observaciones,
|
||||
int id_Denuncia,
|
||||
string nombreFichero,
|
||||
byte[] fichero)
|
||||
{
|
||||
Id_Fichero = id_Fichero;
|
||||
Id_Tipo = id_Tipo;
|
||||
Descripcion = descripcion;
|
||||
Fecha = fecha;
|
||||
Observaciones = observaciones;
|
||||
Id_Denuncia = id_Denuncia;
|
||||
NombreFichero = nombreFichero;
|
||||
Fichero = fichero;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Antifraude.Net/GestionaDenunciasAN/Models/UserState.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
namespace GestionaDenunciasAN.Models
|
||||
{
|
||||
public class UserState
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
private string _token;
|
||||
private string _NombreUsu;
|
||||
private bool _Mostrar;
|
||||
|
||||
public string Token
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _token;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_token = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public string NombreUsu
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _NombreUsu;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_NombreUsu = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool Mostrar
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _Mostrar;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_Mostrar = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
158
Antifraude.Net/GestionaDenunciasAN/Models/Utilidades.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq.Expressions;
|
||||
using Serialize.Linq.Serializers;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace GestionaDenunciasAN.Models
|
||||
{
|
||||
public class Utilidades
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static IConfiguration Conf { get; set; }
|
||||
public static string urlSwagger()
|
||||
{
|
||||
Conf = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
string swagger = Conf.GetSection("SwaggerCC").Value;
|
||||
return swagger;
|
||||
}
|
||||
public static string urlSwagger2()
|
||||
{
|
||||
Conf = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.Build();
|
||||
string swagger = Conf.GetSection("SwaggerVB").Value;
|
||||
return swagger;
|
||||
}
|
||||
|
||||
public static HttpClient ObtenerCliente(String token, IHttpClientFactory clientFactory)
|
||||
{
|
||||
var client = clientFactory.CreateClient();
|
||||
client.BaseAddress = new Uri(Utilidades.urlSwagger());
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
public static async Task<T> ObtenerObjeto<T>(HttpClient cliente, String uri)
|
||||
{
|
||||
var response = await cliente.GetAsync(uri);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var resultContent = await response.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<T>(resultContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
public static async Task<T> ObtenerObjeto<T>(HttpClient cliente, String uri, Expression filtro)
|
||||
{
|
||||
var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
|
||||
var serializedExpression = serializer.SerializeText(filtro);
|
||||
|
||||
var jsonContent = JsonConvert.SerializeObject(new { Expression = serializedExpression });
|
||||
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
||||
var response = await cliente.PostAsync(uri, content);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var resultContent = await response.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<T>(resultContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<T> NuevoObjeto<T>(HttpClient cliente, String uri, T objeto)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Limpiar propiedades de navegación
|
||||
VaciarPropiedadesDeNavegacion(objeto);
|
||||
|
||||
var response = await cliente.PostAsJsonAsync(uri, objeto);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var resultContent = await response.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<T>(resultContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var mess = ex.ToString();
|
||||
return default(T);
|
||||
}
|
||||
|
||||
}
|
||||
public static async Task<T> ActualizarObjeto<T>(HttpClient cliente, String uri, T objeto)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Limpiar propiedades de navegación
|
||||
VaciarPropiedadesDeNavegacion(objeto);
|
||||
|
||||
// Realizar la solicitud PUT
|
||||
var response = await cliente.PutAsJsonAsync(uri, objeto);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var resultContent = await response.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<T>(resultContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Error al actualizar: {response.StatusCode}, {await response.Content.ReadAsStringAsync()}");
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var mess = ex.ToString();
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
// Método para limpiar las propiedades de navegación
|
||||
private static void VaciarPropiedadesDeNavegacion<T>(T objeto)
|
||||
{
|
||||
// Obtener todas las propiedades del objeto
|
||||
var propiedades = typeof(T).GetProperties();
|
||||
|
||||
foreach (var propiedad in propiedades)
|
||||
{
|
||||
// Verificar si la propiedad es de tipo de navegación
|
||||
if (propiedad.PropertyType.IsClass && propiedad.PropertyType != typeof(string))
|
||||
{
|
||||
// Vaciar la propiedad estableciéndola en null
|
||||
if (propiedad.CanWrite)
|
||||
{
|
||||
propiedad.SetValue(objeto, null);
|
||||
Console.WriteLine($"Propiedad de navegación '{propiedad.Name}' vaciada.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
107
Antifraude.Net/GestionaDenunciasAN/Program.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using GestionaDenunciasAN.Components;
|
||||
using GestionaDenunciasAN.Models;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
||||
// Configurar servicios
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
builder.Services.AddHttpClient("DefaultClient", client =>
|
||||
{
|
||||
client.BaseAddress = new Uri(Utilidades.urlSwagger());
|
||||
});
|
||||
builder.Services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie(options =>
|
||||
{
|
||||
options.LoginPath = "/home";
|
||||
options.AccessDeniedPath = "/AccessDenied";
|
||||
});
|
||||
// Necesario para ver porqu<71> est<73> fallando ciertas cosas que dan el error Circuit
|
||||
builder.Services.AddServerSideBlazor().AddCircuitOptions(option => { option.DetailedErrors = true; });
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddDistributedMemoryCache();
|
||||
builder.Services.AddSession(options =>
|
||||
{
|
||||
options.IdleTimeout = TimeSpan.FromHours(1);
|
||||
options.Cookie.HttpOnly = true;
|
||||
options.Cookie.IsEssential = true;
|
||||
});
|
||||
|
||||
builder.Services.AddHttpClient("CertClient").ConfigurePrimaryHttpMessageHandler(() =>
|
||||
{
|
||||
return new HttpClientHandler
|
||||
{
|
||||
ClientCertificateOptions = ClientCertificateOption.Manual // Forzar la selecci<63>n del certificado
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
builder.Services.AddBlazorBootstrap();
|
||||
builder.Services.AddAntiforgery();
|
||||
builder.Services.AddSingleton<UserState>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
app.UseSession();
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var userState = context.RequestServices.GetService<UserState>();
|
||||
var path = context.Request.Path;
|
||||
|
||||
// Permitir solicitudes internas y recursos necesarios
|
||||
if (path == "/" ||
|
||||
path.StartsWithSegments("/_blazor") ||
|
||||
path.StartsWithSegments("/Content") ||
|
||||
path.StartsWithSegments("/Scripts") ||
|
||||
path.StartsWithSegments("/js") ||
|
||||
path.StartsWithSegments("/favicon.ico") ||
|
||||
path.StartsWithSegments("/_framework"))
|
||||
{
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
// Redirigir al home si no hay token y la ruta no es p<>blica
|
||||
if (userState?.Token == null)
|
||||
{
|
||||
Console.WriteLine($"Redirigiendo al home desde: {path}");
|
||||
context.Response.Redirect("/");
|
||||
return;
|
||||
}
|
||||
|
||||
// Continuar con la solicitud
|
||||
await next();
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
|
||||
app.Run();
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:39417",
|
||||
"sslPort": 44394
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5119",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7109;http://localhost:5119",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Antifraude.Net/GestionaDenunciasAN/appsettings.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
|
||||
//SWAGGER DESARROLLO
|
||||
//"SwaggerCC": "https://localhost:7135/api/",
|
||||
//SWAGGER PUBLICADO
|
||||
"SwaggerCC": "https://sw-antifraude.tecnosis.net/api/"
|
||||
}
|
||||
715
Antifraude.Net/GestionaDenunciasAN/wwwroot/Content/Site.css
Normal file
@@ -0,0 +1,715 @@
|
||||
:root {
|
||||
--AzulMuyOscuro: rgb(0, 45, 72);
|
||||
--AzulOscuro: rgb(0, 85, 135);
|
||||
--AzulMedio: rgb(0, 161, 191);
|
||||
--AzulClaro: rgb(95, 207, 228);
|
||||
/* --indigo-parlamento: #172073;
|
||||
--azul-parlamento: #5BA1BA;
|
||||
--verde-parlamento: #70A360;*/
|
||||
--AzulOAAF: #2291d0;
|
||||
--GrisOscuroOAAF: #343334;
|
||||
--AzulClaroOAAF: #6fafd3;
|
||||
--GrisClaroOAAF: #a4a3a4;
|
||||
--GrisNeutro: #e9e9e9 --blue: #007bff;
|
||||
--indigo: #6610f2;
|
||||
--purple: #6f42c1;
|
||||
--pink: #e83e8c;
|
||||
--red: #dc3545;
|
||||
--orange: #fd7e14;
|
||||
--yellow: #ffc107;
|
||||
--green: #28a745;
|
||||
--teal: #20c997;
|
||||
--cyan: #17a2b8;
|
||||
--white: #fff;
|
||||
--gray: #6c757d;
|
||||
--gray-dark: #343a40;
|
||||
--primary: #172073;
|
||||
--secondary: #5BA1BA;
|
||||
--success: #70A360;
|
||||
--info: #5BA1BA;
|
||||
--warning: #ffc107;
|
||||
--danger: #dc3545;
|
||||
--light: #f8f9fa;
|
||||
--dark: #343a40;
|
||||
--gray: #e9ecef;
|
||||
--gray400: #ced4da;
|
||||
--gray500: #adb5bd;
|
||||
--gray600: #6c757d;
|
||||
--breakpoint-xs: 0;
|
||||
--breakpoint-sm: 576px;
|
||||
--breakpoint-md: 768px;
|
||||
--breakpoint-lg: 992px;
|
||||
--breakpoint-xl: 1200px;
|
||||
--font-family-sans-serif: "Open Sans", sans-serif;
|
||||
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.gestionPropia {
|
||||
--AzulOAAF: #2291d0;
|
||||
--GrisOscuroOAAF: #343334;
|
||||
--AzulClaroOAAF: #6fafd3;
|
||||
--GrisClaroOAAF: #a4a3a4;
|
||||
}
|
||||
|
||||
.gestionPersonal {
|
||||
--AzulOAAF: #343334;
|
||||
--AzulClaroOAAD: #a4a3a4;
|
||||
--GrisOscuroOAAF: #2291d0;
|
||||
--GrisClaroOAAF: #6fafd3;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'RobotoB';
|
||||
src: url('FUENTES/Roboto-Bold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'RobotoI';
|
||||
src: url('FUENTES/Roboto-Italic.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
src: url('FUENTES/Roboto-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'SatoshiB';
|
||||
src: url('FUENTES/Satoshi-Black.otf') format('opentype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Satoshi';
|
||||
src: url('FUENTES/Satoshi-Regular.otf') format('opentype');
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
font-family: 'Satoshi';
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
box-shadow:none !important;
|
||||
}
|
||||
.falsoImput {
|
||||
border: 1px solid black;
|
||||
padding: 7px;
|
||||
border-radius: 2px;
|
||||
background-color: #efefef;
|
||||
}
|
||||
.hidden {
|
||||
display:none !important
|
||||
}
|
||||
.text-right {
|
||||
text-align:end;
|
||||
}
|
||||
.btnGris {
|
||||
background-color: #eeeeee;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
.btnGris:hover{
|
||||
background-color: #bfbfbf;
|
||||
}
|
||||
|
||||
#dropdownNavegador {
|
||||
left:-30px
|
||||
}
|
||||
.lblinputRP {
|
||||
margin: 0;
|
||||
font-weight: bold;
|
||||
/*margin-top: 30px;*/
|
||||
}
|
||||
.inputRP {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
color: white !important;
|
||||
background-color: var(--AzulMuyOscuro);
|
||||
}
|
||||
|
||||
.tituloLbl {
|
||||
padding-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.inputForm {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.navMov{
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
.tablaPicadas {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-height: 540px;
|
||||
/*overflow-y: scroll;*/
|
||||
/*overflow-x: hidden;*/
|
||||
position: relative;
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
width: 95%;
|
||||
background-color: #fafafa;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.tablaPicadas table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tablaPicadas td {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
width: auto;
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.tablaPicadas th {
|
||||
position: sticky;
|
||||
top: -1px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
background-color: var(--AzulOAAF);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
/*border: 1px solid white;*/
|
||||
border-collapse: collapse;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-striped > tbody > tr:nth-child(odd) > td,
|
||||
.table-striped > tbody > tr:nth-child(odd) > th {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.popupRP{
|
||||
width:100%;
|
||||
height:100vh;
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
background-color:#00000098;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
z-index:20;
|
||||
}
|
||||
.popupRPCard{
|
||||
max-width:800px;
|
||||
padding:10px;
|
||||
background-color:white;
|
||||
}
|
||||
.menuMovil{
|
||||
display:none;
|
||||
}
|
||||
.iconBtn {
|
||||
background-color: #172073;
|
||||
color: white;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
}
|
||||
.iconBtn:hover {
|
||||
opacity:1;
|
||||
}
|
||||
.dxbs-pager, .dxbs-gridview .dxbs-pager{
|
||||
gap:15px;
|
||||
}
|
||||
.dxbs-pager .page-size.form-inline{
|
||||
display:flex;
|
||||
}
|
||||
#mensajeDiv {
|
||||
z-index: 100;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #000000b2;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#mensajeCuerpo{
|
||||
background-color:white;
|
||||
padding:15px;
|
||||
min-width:300px;
|
||||
max-width:650px;
|
||||
min-height:150px;
|
||||
}
|
||||
#mensajeError{}
|
||||
#loadingDiv {
|
||||
z-index:100;
|
||||
position:fixed;
|
||||
width:100%;
|
||||
height:100vh;
|
||||
background-color:#000000b2;
|
||||
display:none;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
}
|
||||
#loading {
|
||||
background-image: url('imagenes/logo-parlamento-blanco@2x.png');
|
||||
height:50px;
|
||||
width:200px;
|
||||
background-position:center;
|
||||
background-size:cover;
|
||||
|
||||
}
|
||||
|
||||
.btnAzul {
|
||||
border-radius: 0;
|
||||
background-color: #172073;
|
||||
padding: 15px;
|
||||
padding-block: 5px;
|
||||
color: white;
|
||||
border: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.btnAzul:hover {
|
||||
opacity:1;
|
||||
}
|
||||
/*body {
|
||||
font-family:"Arial"
|
||||
}*/
|
||||
.pagina {
|
||||
padding: 50px;
|
||||
/* min-height:100vh;
|
||||
*/ /*background-color:lightgray*/
|
||||
}
|
||||
.tituloSeccion {
|
||||
font-size:30px;
|
||||
/*font-family:"Arial";*/
|
||||
font-weight:bold;
|
||||
color:var(--AzulMuyOscuro)
|
||||
}
|
||||
.navBar {
|
||||
position:fixed;
|
||||
left:0;
|
||||
width:300px;
|
||||
height:100vh;
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
background-color:var(--AzulOscuro) ;
|
||||
border-collapse:collapse
|
||||
}
|
||||
.nav-link {
|
||||
cursor:pointer
|
||||
}
|
||||
|
||||
|
||||
/*.navBarLink {
|
||||
cursor:pointer;
|
||||
text-decoration:none !important;
|
||||
height:50px;
|
||||
width:100%;*/
|
||||
/*text-align:center;*/
|
||||
/*padding-inline:20px;
|
||||
color:white;
|
||||
font-size:20px;
|
||||
line-height:50px;
|
||||
border-block:solid 1px white;
|
||||
border-collapse:collapse;
|
||||
}
|
||||
.navBarLink:hover {
|
||||
color:white;
|
||||
background-color:var(--AzulMuyOscuro)
|
||||
}
|
||||
.navBarLinkSecundario {
|
||||
padding-left:40px;
|
||||
padding-right:20px;
|
||||
font-size:15px;
|
||||
background-color: var(--AzulClaro);
|
||||
height:40px;
|
||||
line-height:40px;
|
||||
}
|
||||
.navBarLinkSecundario:hover {
|
||||
background-color: var(--AzulMedio)
|
||||
}*/
|
||||
.inputRegPers {
|
||||
border-radius: 5px;
|
||||
height: 50px;
|
||||
padding:10px;
|
||||
border: solid 1px var(--AzulMuyOscuro);
|
||||
}
|
||||
.cbdxbt input {
|
||||
border-radius: 5px;
|
||||
height: 50px;
|
||||
padding: 10px;
|
||||
border: solid 1px var(--AzulMuyOscuro);
|
||||
}
|
||||
|
||||
|
||||
.btnOAAFAzul {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
background-color: var(--AzulOAAF);
|
||||
border-radius: 15px;
|
||||
font-family: 'Satoshi';
|
||||
border: none;
|
||||
color: white !important;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btnOAAFAzul:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.btnOAAFBlack {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
background-color: var(--GrisOscuroOAAF);
|
||||
border-radius: 15px;
|
||||
font-family: 'Satoshi';
|
||||
border: none;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.btnOAAFBlack:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
|
||||
.cbdxbt .input-group-append {
|
||||
border-bottom-right-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
height: 50px;
|
||||
padding: 10px;
|
||||
border: solid 1px var(--AzulMuyOscuro);
|
||||
background-color: var(--AzulOscuro)
|
||||
}
|
||||
.cbdxbt .input-group-append::before {
|
||||
content: "";
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display:flex;
|
||||
background-image: url('imagenes/dropParlamento.svg');
|
||||
background-size:80% 80%;
|
||||
background-position:center;
|
||||
background-repeat:no-repeat;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.cbdxbt .input-group-append:hover {
|
||||
background-color: var(--AzulMuyOscuro)
|
||||
}
|
||||
.tabsRegPers {
|
||||
margin-top:50px !important;
|
||||
display:flex;
|
||||
gap:30px;
|
||||
}
|
||||
.tabsRegPers li a {
|
||||
text-decoration: none !important;
|
||||
color: var(--AzulOscuro) !important;
|
||||
/*font-family: "Open Sans" !important;*/
|
||||
}
|
||||
.tabsRegPers li .active a {
|
||||
font-weight:bold !important;
|
||||
}
|
||||
.btnRegPers {
|
||||
background-color: var(--AzulOscuro);
|
||||
border-radius: 10px;
|
||||
min-width: 100%;
|
||||
color: white;
|
||||
transition: all 0.2s
|
||||
}
|
||||
.btnRegPers:hover {
|
||||
color: white !important;
|
||||
background-color: var(--AzulMuyOscuro);
|
||||
}
|
||||
.filaInvisible {
|
||||
display: none;
|
||||
}
|
||||
.tablaRegPers {
|
||||
|
||||
margin-top:50px;
|
||||
width:100%;
|
||||
border-collapse:collapse
|
||||
}
|
||||
|
||||
|
||||
.camposficha {
|
||||
padding-left: 15px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.formatoCampos {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tablaRegPers th {
|
||||
text-align:center;
|
||||
background-color:var(--AzulOscuro);
|
||||
color:white !important;
|
||||
text-decoration:none !important;
|
||||
padding:20px;
|
||||
padding-inline:20px;
|
||||
overflow-inline:visible;
|
||||
border-inline:solid 1px white;
|
||||
width:auto;
|
||||
white-space:nowrap;
|
||||
|
||||
}
|
||||
.tablaRegPers th .btn-link {
|
||||
color:white;
|
||||
}
|
||||
.tablaRegPers th a {
|
||||
color: white !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.tablaRegPers th a:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.tablaRegPers td {
|
||||
padding: 15px !important;
|
||||
padding-inline: 30px !important;
|
||||
border: solid 1px black;
|
||||
}
|
||||
|
||||
.linkNavActivo {
|
||||
background-color: var(--AzulMuyOscuro) !important;
|
||||
}
|
||||
|
||||
|
||||
.table .card {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.table thead {
|
||||
text-align: left;
|
||||
color: var(--AzulOscuro);
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.table th {
|
||||
/*padding: 10px !important;*/
|
||||
border: none !important;
|
||||
}
|
||||
.table td {
|
||||
/*padding: 5px !important;*/
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.table a {
|
||||
color: var(--AzulOscuro) !important;
|
||||
}
|
||||
.table a:hover {
|
||||
color: var(--AzulMuyOscuro) !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
border:none !important;
|
||||
margin-top: 20px;
|
||||
border-collapse: collapse !important;
|
||||
|
||||
}
|
||||
.table-bordered > :not(caption) > * {
|
||||
border-width: 0px 0px !important;
|
||||
}
|
||||
|
||||
.table > thead > tr > th {
|
||||
/*padding: 10px !important;*/
|
||||
}
|
||||
|
||||
.table > tbody > tr > td {
|
||||
/*padding: 5px !important;*/
|
||||
border-bottom: 1px solid gray !important;
|
||||
}
|
||||
.table > tbody > tr {
|
||||
border-bottom: 1px solid gray !important;
|
||||
}
|
||||
|
||||
.table > thead > tr {
|
||||
border-bottom: 1px solid gray !important;
|
||||
}
|
||||
/*.table > tbody {
|
||||
border-collapse: collapse !important;
|
||||
}
|
||||
.table > thead {
|
||||
border-collapse: collapse !important;
|
||||
}*/
|
||||
table {
|
||||
border-collapse: unset;
|
||||
}
|
||||
|
||||
|
||||
.marTop {
|
||||
margin-top:25px !important;
|
||||
}
|
||||
.nuevaRPT p {
|
||||
margin-bottom:0;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
.lblInput {
|
||||
margin:0;
|
||||
font-size:12px;
|
||||
font-weight:bold;
|
||||
margin-top:30px;
|
||||
}
|
||||
|
||||
.barraArribaHeader {
|
||||
background-color: var(--azul-parlamento) !important;
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
padding-inline: 10px !important;
|
||||
}
|
||||
.barraArribaHeader .nav-link {
|
||||
padding: 5px !important;
|
||||
filter: invert(1);
|
||||
}
|
||||
.barraArribaHeader .nav-link :hover {
|
||||
filter: brightness(5);
|
||||
}
|
||||
#pa-main-menu {
|
||||
align-content: center !important;
|
||||
}
|
||||
|
||||
#pa-main-menu .nav-item {
|
||||
padding-left: 30px !important;
|
||||
padding-right: 30px !important;
|
||||
border-bottom: 3px solid white !important;
|
||||
}
|
||||
#pa-main-menu .nav-item:hover {
|
||||
color: var(--AzulMuyOscuro) !important;
|
||||
border-bottom: 3px solid var(--AzulMuyOscuro) !important;
|
||||
}
|
||||
.loadingFrame {
|
||||
display: flex;
|
||||
background-color: #000000e5;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
.loadingDiv{
|
||||
padding:20px;
|
||||
border-radius:5px;
|
||||
background-color:white;
|
||||
display:flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
}
|
||||
.loadingImg {
|
||||
background-image: url(imagenes/cargaOAAF.gif);
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
transform: scale(1);
|
||||
/*animation: pulse 2s infinite;*/
|
||||
}
|
||||
#loginImg {
|
||||
height: 80px;
|
||||
margin-inline: auto;
|
||||
margin-bottom: 30px
|
||||
}
|
||||
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(1);
|
||||
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.95);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
|
||||
.pagina {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.tablaRegPers {
|
||||
font-size: 10px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#cajaLogIn {
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
.loginImg {
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.navMov {
|
||||
display: flex;
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
background-color: white;
|
||||
}
|
||||
.page {
|
||||
margin-top:60px !important;
|
||||
}
|
||||
.menuMovil {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
flex-direction: column;
|
||||
margin-top: 11px;
|
||||
z-index: 100;
|
||||
}
|
||||
.btnNavMov {
|
||||
border-radius: 0;
|
||||
background-color: #172073;
|
||||
padding: 15px;
|
||||
padding-block: 5px;
|
||||
color: white;
|
||||
border: none;
|
||||
text-decoration:none;
|
||||
text-align:center;
|
||||
}
|
||||
.btnGrisNav {
|
||||
border-radius: 0;
|
||||
background-color: #eeeeee;
|
||||
padding: 15px;
|
||||
border-top: solid 1px darkgray;
|
||||
border-bottom: solid 1px darkgray;
|
||||
padding-block: 7px;
|
||||
color: black;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
margin-block: 1px;
|
||||
}
|
||||
.nav-tabs .nav-link {
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
/*header .pa-header-t1 .pa-header-row1 .navbar.navbar-dark .navbar-nav:after {
|
||||
content: "|";
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}*/
|
||||
9
Antifraude.Net/GestionaDenunciasAN/wwwroot/Content/all.min.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-facebook" viewBox="0 0 16 16">
|
||||
<path d="M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 436 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-instagram" viewBox="0 0 16 16">
|
||||
<path d="M8 0C5.829 0 5.556.01 4.703.048 3.85.088 3.269.222 2.76.42a3.917 3.917 0 0 0-1.417.923A3.927 3.927 0 0 0 .42 2.76C.222 3.268.087 3.85.048 4.7.01 5.555 0 5.827 0 8.001c0 2.172.01 2.444.048 3.297.04.852.174 1.433.372 1.942.205.526.478.972.923 1.417.444.445.89.719 1.416.923.51.198 1.09.333 1.942.372C5.555 15.99 5.827 16 8 16s2.444-.01 3.298-.048c.851-.04 1.434-.174 1.943-.372a3.916 3.916 0 0 0 1.416-.923c.445-.445.718-.891.923-1.417.197-.509.332-1.09.372-1.942C15.99 10.445 16 10.173 16 8s-.01-2.445-.048-3.299c-.04-.851-.175-1.433-.372-1.941a3.926 3.926 0 0 0-.923-1.417A3.911 3.911 0 0 0 13.24.42c-.51-.198-1.092-.333-1.943-.372C10.443.01 10.172 0 7.998 0h.003zm-.717 1.442h.718c2.136 0 2.389.007 3.232.046.78.035 1.204.166 1.486.275.373.145.64.319.92.599.28.28.453.546.598.92.11.281.24.705.275 1.485.039.843.047 1.096.047 3.231s-.008 2.389-.047 3.232c-.035.78-.166 1.203-.275 1.485a2.47 2.47 0 0 1-.599.919c-.28.28-.546.453-.92.598-.28.11-.704.24-1.485.276-.843.038-1.096.047-3.232.047s-2.39-.009-3.233-.047c-.78-.036-1.203-.166-1.485-.276a2.478 2.478 0 0 1-.92-.598 2.48 2.48 0 0 1-.6-.92c-.109-.281-.24-.705-.275-1.485-.038-.843-.046-1.096-.046-3.233 0-2.136.008-2.388.046-3.231.036-.78.166-1.204.276-1.486.145-.373.319-.64.599-.92.28-.28.546-.453.92-.598.282-.11.705-.24 1.485-.276.738-.034 1.024-.044 2.515-.045v.002zm4.988 1.328a.96.96 0 1 0 0 1.92.96.96 0 0 0 0-1.92zm-4.27 1.122a4.109 4.109 0 1 0 0 8.217 4.109 4.109 0 0 0 0-8.217zm0 1.441a2.667 2.667 0 1 1 0 5.334 2.667 2.667 0 0 1 0-5.334z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-linkedin" viewBox="0 0 16 16">
|
||||
<path d="M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 711 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-fill" viewBox="0 0 16 16">
|
||||
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3Zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 225 B |
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-rss" viewBox="0 0 16 16">
|
||||
<path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/>
|
||||
<path d="M5.5 12a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-3-8.5a1 1 0 0 1 1-1c5.523 0 10 4.477 10 10a1 1 0 1 1-2 0 8 8 0 0 0-8-8 1 1 0 0 1-1-1zm0 4a1 1 0 0 1 1-1 6 6 0 0 1 6 6 1 1 0 1 1-2 0 4 4 0 0 0-4-4 1 1 0 0 1-1-1z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 507 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search" viewBox="0 0 16 16">
|
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 331 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitter" viewBox="0 0 16 16">
|
||||
<path d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 640 B |
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-universal-access-circle" viewBox="0 0 16 16">
|
||||
<path d="M8 4.143A1.071 1.071 0 1 0 8 2a1.071 1.071 0 0 0 0 2.143Zm-4.668 1.47 3.24.316v2.5l-.323 4.585A.383.383 0 0 0 7 13.14l.826-4.017c.045-.18.301-.18.346 0L9 13.139a.383.383 0 0 0 .752-.125L9.43 8.43v-2.5l3.239-.316a.38.38 0 0 0-.047-.756H3.379a.38.38 0 0 0-.047.756Z"/>
|
||||
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0ZM1 8a7 7 0 1 1 14 0A7 7 0 0 1 1 8Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 509 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16">
|
||||
<path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 924 B |
|
After Width: | Height: | Size: 39 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="201" height="176" viewBox="0 0 201 176">
|
||||
<g id="Grupo_579" data-name="Grupo 579" transform="translate(-347.5 -588)">
|
||||
<path id="Trazado_526" data-name="Trazado 526" d="M181.25-162.5H18.75A18.755,18.755,0,0,0,0-143.75V-6.25A18.755,18.755,0,0,0,18.75,12.5h162.5A18.755,18.755,0,0,0,200-6.25v-137.5A18.755,18.755,0,0,0,181.25-162.5ZM12.5-143.75A6.268,6.268,0,0,1,18.75-150H37.5v25h-25Zm175,137.5A6.268,6.268,0,0,1,181.25,0H18.75A6.268,6.268,0,0,1,12.5-6.25V-112.5h175Zm0-118.75H50v-25H181.25a6.268,6.268,0,0,1,6.25,6.25Z" transform="translate(348 751)" fill="#172073" stroke="rgba(0,0,0,0)" stroke-width="1"/>
|
||||
<path id="Trazado_525" data-name="Trazado 525" d="M12.239,10.473V19.35l-1.611.615L10.53,21H21.312l.293-3.535-1.211-.146L19.2,19.525H15.013V15.512h2.119l.322,1.65,1.357-.225.332-4.141-1.406.264-.43,1.26H15.013v-4.18h3.975l.605,2.129,1.26.186.3-3.6H10.569l-.146,1.074Zm16.494,9.365-1.611-.576V16.137h1.211l1.211,2.246a6.46,6.46,0,0,0,1.67,2.109,3.668,3.668,0,0,0,2.334.742A5.345,5.345,0,0,0,35.2,21l.225-.977-.352-.1a3.412,3.412,0,0,1-1.118-.508,4.82,4.82,0,0,1-.874-.8q-.391-.454-1-1.274l-1.475-2.012a4.463,4.463,0,0,0,1.362-.767,4.051,4.051,0,0,0,1.006-1.2,2.9,2.9,0,0,0,.376-1.416A2.585,2.585,0,0,0,32,9.491a8.46,8.46,0,0,0-3.965-.737q-1.025,0-2.6.146t-2.734.332L22.6,10.395l1.768.371V19.35l-1.738.615L22.483,21h6.143Zm-1.611-9.766q.039,0,.249-.015t.493-.015a2.721,2.721,0,0,1,1.343.317,2.181,2.181,0,0,1,.874.869,2.525,2.525,0,0,1,.3,1.235,2.146,2.146,0,0,1-.425,1.357,2.794,2.794,0,0,1-1.128.85H27.122Zm15.469,9.766-1.611-.576V16.137H42.19L43.4,18.383a6.46,6.46,0,0,0,1.67,2.109,3.668,3.668,0,0,0,2.334.742A5.345,5.345,0,0,0,49.056,21l.225-.977-.352-.1a3.412,3.412,0,0,1-1.118-.508,4.82,4.82,0,0,1-.874-.8q-.391-.454-1-1.274l-1.475-2.012a4.463,4.463,0,0,0,1.362-.767,4.051,4.051,0,0,0,1.006-1.2,2.9,2.9,0,0,0,.376-1.416,2.585,2.585,0,0,0-1.348-2.466A8.46,8.46,0,0,0,41.9,8.754q-1.025,0-2.6.146t-2.734.332l-.107,1.162,1.768.371V19.35l-1.738.615L36.341,21h6.143Zm-1.611-9.766q.039,0,.249-.015t.493-.015a2.721,2.721,0,0,1,1.343.317,2.181,2.181,0,0,1,.874.869,2.525,2.525,0,0,1,.3,1.235,2.146,2.146,0,0,1-.425,1.357,2.794,2.794,0,0,1-1.128.85H40.979Zm15.2,11.191a7.692,7.692,0,0,0,3.574-.791,5.688,5.688,0,0,0,2.363-2.212,6.375,6.375,0,0,0,.83-3.276,7.549,7.549,0,0,0-.728-3.447,5.016,5.016,0,0,0-2.1-2.187A6.678,6.678,0,0,0,56.858,8.6a7.535,7.535,0,0,0-3.579.8A5.418,5.418,0,0,0,51,11.63a6.865,6.865,0,0,0-.781,3.325,7.619,7.619,0,0,0,.669,3.271A5.043,5.043,0,0,0,52.9,20.458,6.26,6.26,0,0,0,56.175,21.264ZM56.39,9.916a2.5,2.5,0,0,1,1.982.879,5.208,5.208,0,0,1,1.089,2.134,9.785,9.785,0,0,1,.327,2.476q0,4.414-3.115,4.414a2.5,2.5,0,0,1-1.958-.85,5,5,0,0,1-1.084-2.09,9.617,9.617,0,0,1-.327-2.461,6.54,6.54,0,0,1,.7-3.306A2.539,2.539,0,0,1,56.39,9.916Zm13.7,9.922-1.611-.576V16.137H69.69L70.9,18.383a6.46,6.46,0,0,0,1.67,2.109,3.668,3.668,0,0,0,2.334.742A5.345,5.345,0,0,0,76.556,21l.225-.977-.352-.1a3.412,3.412,0,0,1-1.118-.508,4.82,4.82,0,0,1-.874-.8q-.391-.454-1-1.274l-1.475-2.012a4.463,4.463,0,0,0,1.362-.767,4.051,4.051,0,0,0,1.006-1.2,2.9,2.9,0,0,0,.376-1.416,2.585,2.585,0,0,0-1.348-2.466A8.46,8.46,0,0,0,69.4,8.754q-1.025,0-2.6.146t-2.734.332l-.107,1.162,1.768.371V19.35l-1.738.615L63.841,21h6.143Zm-1.611-9.766q.039,0,.249-.015t.493-.015a2.721,2.721,0,0,1,1.343.317,2.181,2.181,0,0,1,.874.869,2.525,2.525,0,0,1,.3,1.235,2.146,2.146,0,0,1-.425,1.357,2.794,2.794,0,0,1-1.128.85H68.479ZM87.8,17.738v1.8l-2.363.586-.049.889h6.9l.1-1.006-2.109-.439v-1.8H92.61l.156-1.611h-2.49V14.34q0-1.289.029-2.686t.078-2.3l-.928-.244-6.777,7.52.234,1.113Zm-.02-5.176v3.594H85.12Zm10.322,8.7a4.07,4.07,0,0,0,2.095-.576,4.223,4.223,0,0,0,1.616-1.914,8.152,8.152,0,0,0,.635-3.477,7.393,7.393,0,0,0-1.157-4.619,3.738,3.738,0,0,0-3.071-1.445,4.065,4.065,0,0,0-2.163.62,4.455,4.455,0,0,0-1.65,1.982,8.158,8.158,0,0,0-.64,3.462q0,3.3,1.216,4.634A4.033,4.033,0,0,0,98.1,21.264ZM98.06,10.629a.97.97,0,0,1,.859.459,3.536,3.536,0,0,1,.43,1.45,22.388,22.388,0,0,1,.127,2.7,24.843,24.843,0,0,1-.117,2.71,4.145,4.145,0,0,1-.4,1.519.867.867,0,0,1-.781.5,1,1,0,0,1-.9-.488,3.6,3.6,0,0,1-.43-1.484,24.607,24.607,0,0,1-.117-2.725,24.491,24.491,0,0,1,.117-2.715,3.69,3.69,0,0,1,.405-1.46A.9.9,0,0,1,98.06,10.629ZM108.6,17.738v1.8l-2.363.586-.049.889h6.9l.1-1.006-2.109-.439v-1.8h2.334l.156-1.611h-2.49V14.34q0-1.289.029-2.686t.078-2.3l-.928-.244-6.777,7.52.234,1.113Zm-.02-5.176v3.594h-2.656Z" transform="translate(386 682)" fill="#172073" stroke="rgba(0,0,0,0)" stroke-width="1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
@@ -0,0 +1 @@
|
||||
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 335.08 121.82"><defs><style>.cls-1{fill:#343334;}.cls-2{fill:#fff;}</style></defs><title>Mesa de trabajo 1</title><path class="cls-1" d="M29.72,115c-3.7,0-6.22-2.81-6.22-6.75s2.54-6.77,6.22-6.77,6.22,2.85,6.22,6.77S33.4,115,29.72,115Zm0-12.23c-2.9,0-4.85,2.23-4.85,5.47s1.95,5.47,4.85,5.47,4.87-2.23,4.87-5.47S32.6,102.77,29.72,102.77Z"/><path class="cls-1" d="M39.69,109v5.75H38.38V101.72h7.7V103H39.7v4.89h5.36V109H39.69Z"/><path class="cls-1" d="M49.6,114.78H48.29V101.72H49.6Z"/><path class="cls-1" d="M51.93,108.25c0-4.07,2.57-6.77,6.2-6.77a5.42,5.42,0,0,1,5.51,4.29H62.22a4.13,4.13,0,0,0-4.14-3c-2.86,0-4.78,2.19-4.78,5.47s2,5.45,4.78,5.45a4.36,4.36,0,0,0,4.27-2.85h1.41A5.6,5.6,0,0,1,58.07,115C54.47,115,51.93,112.31,51.93,108.25Z"/><path class="cls-1" d="M67.36,114.78H66.05V101.72h1.31Z"/><path class="cls-1" d="M70.49,114.78V101.72h1.33L79,112.63V101.72h1.3v13.06H79l-7.19-10.87v10.87Z"/><path class="cls-1" d="M82.16,114.78,87,101.72h1.61l4.83,13.06H92l-1.24-3.47h-6l-1.28,3.47Zm3-4.58h5.24L88,103.56c0-.15-.13-.4-.16-.53,0,.13-.11.38-.15.53Z"/><path class="cls-1" d="M98.88,114.78l4.82-13.5h2.88l4.8,13.5h-3.14l-.95-2.85h-4.36l-1,2.85Zm4.9-5.33h2.66l-1-2.88a8.54,8.54,0,0,1-.36-1.31,6.45,6.45,0,0,1-.35,1.31Z"/><path class="cls-1" d="M113,114.78v-13.5h2.92l5.69,8.83v-8.83h2.92v13.5h-2.92L115.87,106v8.81Z"/><path class="cls-1" d="M127.28,114.78v-13.5h5.29c3.8,0,6.53,2.79,6.53,6.79a6.34,6.34,0,0,1-6.53,6.71ZM130.23,104v8h2c2.3,0,3.7-1.64,3.7-4s-1.44-4-3.7-4h-2Z"/><path class="cls-1" d="M139.16,114.78l4.82-13.5h2.88l4.8,13.5h-3.14l-1-2.85h-4.36l-1,2.85Zm4.91-5.33h2.66l-1-2.88a8.54,8.54,0,0,1-.36-1.31,6.45,6.45,0,0,1-.35,1.31Z"/><path class="cls-1" d="M156.22,112.13h5.29v2.65h-8.28v-13.5h3Z"/><path class="cls-1" d="M163.27,101.28h3v8.34a2.47,2.47,0,0,0,2.68,2.57,2.58,2.58,0,0,0,2.72-2.57v-8.34h3v8.43c0,3.37-2.61,5.29-5.67,5.29s-5.64-2-5.64-5.29Z"/><path class="cls-1" d="M176.52,114.78V112l6.07-7.88-6.07,0v-2.86h9.63v2.64L180,112h6v2.83Z"/><path class="cls-1" d="M187.14,114.78l4.82-13.5h2.88l4.8,13.5H196.5l-.95-2.85h-4.36l-1,2.85Zm4.91-5.33h2.66l-1-2.88a8.54,8.54,0,0,1-.36-1.31,6.45,6.45,0,0,1-.35,1.31Z"/><path class="cls-1" d="M204.9,114.78l4.8-13.06h1.61l4.83,13.06h-1.37l-1.24-3.47h-6l-1.28,3.47Zm3-4.58h5.24l-2.43-6.64c0-.15-.13-.4-.16-.53,0,.13-.11.38-.15.53Z"/><path class="cls-1" d="M218,114.78V101.72h1.33l7.19,10.91V101.72h1.3v13.06h-1.3l-7.19-10.87v10.87Z"/><path class="cls-1" d="M229.61,101.72h9.52v1.22H235v11.84h-1.31V102.94h-4.12v-1.22Z"/><path class="cls-1" d="M242.26,114.78H241V101.72h1.31Z"/><path class="cls-1" d="M246.75,109v5.75h-1.31V101.72h7.7V103h-6.39v4.89h5.36V109h-5.36Z"/><path class="cls-1" d="M255.35,114.78V101.72h5c2.66,0,4.27,1.44,4.27,3.78a3.52,3.52,0,0,1-2.7,3.67l2.68,5.62h-1.48l-2.54-5.42h-3.92v5.42h-1.31Zm1.31-6.64h3.7c1.86,0,2.86-1,2.86-2.61s-1.08-2.61-2.88-2.61h-3.69v5.22Z"/><path class="cls-1" d="M265.7,114.78l4.8-13.06h1.61l4.83,13.06h-1.37l-1.24-3.47h-6L267,114.78Zm3-4.58h5.24l-2.43-6.64c0-.15-.13-.4-.16-.53,0,.13-.11.38-.15.53Z"/><path class="cls-1" d="M278,101.72h1.33v8.59c0,2.68,1.92,3.45,3.59,3.45a3.28,3.28,0,0,0,3.59-3.45v-8.59h1.31v8.63c0,3.25-2.39,4.69-4.91,4.69s-4.93-1.28-4.93-4.69v-8.63Z"/><path class="cls-1" d="M290.87,114.78V101.72h4a6.53,6.53,0,0,1,0,13.06ZM292.18,103v10.58h2.61a5.29,5.29,0,0,0,0-10.58Z"/><path class="cls-1" d="M303.75,114.78V101.72h7.81V103h-6.51v4.67H311v1.17h-5.91v4.73h6.53v1.24h-7.83Z"/><path class="cls-2" d="M98.45,37.53a40.49,40.49,0,1,0-29.54,49A40.48,40.48,0,0,0,98.45,37.53ZM45.7,62.94a15.06,15.06,0,1,1,11-18.25A15.08,15.08,0,0,1,45.7,62.94Z"/><polygon class="cls-1" points="100.23 87.78 119.32 87.78 127.19 64.56 150.42 64.56 158.17 87.78 177.6 87.78 163.37 47.72 114.52 47.7 100.23 87.78"/><polygon class="cls-1" points="129.12 6.78 118.22 37.34 158.34 33.57 148.82 6.78 129.12 6.78"/><polygon class="cls-1" points="180.68 87.78 199.77 87.78 207.64 64.56 230.87 64.56 238.63 87.78 258.05 87.78 243.83 47.77 194.96 47.74 180.68 87.78"/><polygon class="cls-1" points="209.57 6.78 201.46 29.53 236.19 26.27 229.27 6.78 209.57 6.78"/><polygon class="cls-1" points="262.47 87.78 281.05 87.78 281.05 64.56 310.58 64.56 310.58 47.81 262.47 47.81 262.47 87.78"/><polygon class="cls-1" points="262.47 6.78 262.47 23.8 316.42 18.74 316.42 6.78 262.47 6.78"/></svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
34
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/Util.js
Normal file
@@ -0,0 +1,34 @@
|
||||
function pestanaActiva(pestana) {
|
||||
var links = document.getElementsByClassName("navBarLink")
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
if (links[i].classList.contains("linkNavActivo") == true)
|
||||
links[i].classList.remove("linkNavActivo")
|
||||
}
|
||||
|
||||
if (document.getElementById(pestana).classList.contains("linkNavActivo") == false) {
|
||||
document.getElementById(pestana).classList.add("linkNavActivo")
|
||||
}
|
||||
}
|
||||
|
||||
function eliminarCookies(id, cut) {
|
||||
var theCookies = document.cookie.split(';');
|
||||
for (var i = 0; i < theCookies.length; i++) {
|
||||
if (theCookies[i].trim().indexOf(id) >= 0 && theCookies[i].trim().indexOf(cut) == -1) {
|
||||
ASPxClientUtils.DeleteCookie(theCookies[i].trim().split("=")[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
function getUrlParameter(sParam) {
|
||||
var sPageURL = window.location.search.substring(1),
|
||||
sURLVariables = sPageURL.split('&'),
|
||||
sParameterName,
|
||||
i;
|
||||
|
||||
for (i = 0; i < sURLVariables.length; i++) {
|
||||
sParameterName = sURLVariables[i].split('=');
|
||||
|
||||
if (sParameterName[0] === sParam) {
|
||||
return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
|
||||
}
|
||||
}
|
||||
};
|
||||
6
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/all.min.js
vendored
Normal file
7
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/bootstrap.bundle.min.js
vendored
Normal file
7
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/bootstrap.min.js
vendored
Normal file
2
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/jquery.min.js
vendored
Normal file
1406
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/modernizr-2.8.3.js
vendored
Normal file
6
Antifraude.Net/GestionaDenunciasAN/wwwroot/Scripts/popper.min.js
vendored
Normal file
51
Antifraude.Net/GestionaDenunciasAN/wwwroot/app.css
Normal file
@@ -0,0 +1,51 @@
|
||||
html, body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
color: #006bb7;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid #e50000;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: #e50000;
|
||||
}
|
||||
|
||||
.blazor-error-boundary {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||
padding: 1rem 1rem 1rem 3.7rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
|
||||
.darker-border-checkbox.form-check-input {
|
||||
border-color: #929292;
|
||||
}
|
||||
7
Antifraude.Net/GestionaDenunciasAN/wwwroot/bootstrap/bootstrap.min.css
vendored
Normal file
BIN
Antifraude.Net/GestionaDenunciasAN/wwwroot/favicon.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |