Actualización del 2025-06-18 a las 17:08:45

This commit is contained in:
jlimolina 2025-06-18 17:08:45 +02:00
parent eb72ec9e56
commit 78c01fd61b
7 changed files with 368 additions and 239 deletions

View file

@ -9,7 +9,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<style>
/* --- Variables Globales de Diseño --- */
:root {
@ -160,15 +160,12 @@
</a>
<p class="subtitle">Tu centro de información personalizado</p>
<!-- NAVEGACIÓN SIMPLIFICADA -->
<nav class="main-nav">
<a href="{{ url_for('home') }}" class="nav-link">Noticias</a>
<a href="{{ url_for('dashboard') }}" class="nav-link">Dashboard</a>
<a href="{{ url_for('manage_feeds') }}" class="nav-link">Gestionar Feeds</a>
<a href="{{ url_for('manage_urls') }}" class="nav-link">Gestionar URLs</a>
<div class="nav-actions">
<a href="{{ url_for('scrape_url') }}" class="btn btn-small btn-info">Procesar URL</a>
</div>
</nav>
</header>

View file

@ -1,44 +1,59 @@
{% extends "base.html" %}
{% block title %}Dashboard de Feeds{% endblock %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<div class="dashboard-grid">
<div class="stat-card">
<div class="stat-number">{{ stats.feeds_totales }}</div>
<div class="stat-label">Feeds RSS Totales</div>
<div class="stat-label">Feeds Totales</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ stats.noticias_totales }}</div>
<div class="stat-label">Noticias Recopiladas</div>
<div class="stat-label">Noticias Totales</div>
</div>
<div class="stat-card">
<div class="stat-number" style="background: linear-gradient(135deg, #f72585 0%, #7209b7 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
{{ stats.feeds_caidos }}
<div class="stat-number">{{ stats.feeds_caidos }}</div>
<div class="stat-label">Feeds Caídos</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-4">
<div class="card">
<div class="card-header">
<h3>Gestión de Feeds RSS</h3>
</div>
<div class="card-body">
<p>Exporta tu lista de feeds RSS o restaura/importa desde un archivo CSV.</p>
<a href="{{ url_for('backup_feeds') }}" class="btn"><i class="fas fa-download"></i> Exportar Feeds</a>
<a href="{{ url_for('restore_feeds') }}" class="btn btn-info"><i class="fas fa-upload"></i> Importar Feeds</a>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card">
<div class="card-header">
<h3>Gestión de Fuentes URL</h3>
</div>
<div class="card-body">
<p>Exporta tu lista de fuentes URL o restaura/importa desde un archivo CSV.</p>
<a href="{{ url_for('backup_urls') }}" class="btn"><i class="fas fa-download"></i> Exportar URLs</a>
<a href="{{ url_for('restore_urls') }}" class="btn btn-info"><i class="fas fa-upload"></i> Importar URLs</a>
</div>
</div>
<div class="stat-label">Feeds Caídos / Inactivos</div>
</div>
</div>
<div class="card">
<h2 style="text-align: center; margin-bottom: 20px;">Opciones de Backup y Restauración</h2>
<p style="text-align: center; color: var(--text-color-light); margin-bottom: 25px;">
Exporta tus datos para mantener copias de seguridad o restaura desde un archivo.
</p>
<div style="display: flex; justify-content: center; gap: 15px; flex-wrap: wrap;">
<a href="{{ url_for('backup_feeds') }}" class="btn" style="display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-file-csv"></i> Feeds (CSV)
</a>
<a href="{{ url_for('backup_noticias') }}" class="btn" style="display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-file-csv"></i> Noticias (CSV)
</a>
<a href="{{ url_for('backup_completo') }}" class="btn" style="background: linear-gradient(135deg, #00b894 0%, #00cec9 100%); display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-file-archive"></i> Completo (ZIP)
</a>
<a href="{{ url_for('restore_feeds') }}" class="btn btn-secondary" style="display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-file-import"></i> Importar Feeds
</a>
<div class="card-header">
<h3>Operaciones del Sistema</h3>
</div>
<div class="card-body">
<p>Genera una copia de seguridad completa o ejecuta la tarea de recolección manualmente para pruebas.</p>
<a href="{{ url_for('backup_completo') }}" class="btn btn-secondary"><i class="fas fa-archive"></i> Backup Completo (.zip)</a>
<a href="{{ url_for('run_fetch_now') }}" class="btn btn-danger" onclick="return confirm('Esto puede tardar un momento. ¿Estás seguro?')"><i class="fas fa-cogs"></i> Ejecutar Recolección Manual</a>
</div>
</div>
{% endblock %}

View file

@ -3,14 +3,6 @@
{% block title %}Últimas Noticias RSS{% endblock %}
{% block content %}
<header>
<h1>Agregador de Noticias</h1>
<p class="subtitle">Tus fuentes de información, en un solo lugar.</p>
<a href="{{ url_for('dashboard') }}" class="top-link" style="margin-top:15px;">
<i class="fas fa-cogs"></i> Gestionar Feeds
</a>
</header>
<div class="card">
<h2><i class="fas fa-filter" style="color: var(--secondary-color); margin-right: 10px;"></i>Filtrar Noticias</h2>
<form method="get" action="{{ url_for('home') }}" id="filter-form">
@ -116,3 +108,4 @@ document.addEventListener('DOMContentLoaded', function() {
});
</script>
{% endblock %}

View file

@ -0,0 +1,33 @@
{% extends "base.html" %}
{% block title %}Importar Fuentes URL desde CSV{% endblock %}
{% block content %}
<div class="card">
<div class="card-header">
<h2>Añadir/Restaurar Fuentes URL desde archivo CSV</h2>
</div>
<div class="card-body">
<p>
Sube un archivo CSV para añadir en bloque nuevas fuentes URL o para actualizar las existentes.
</p>
<p>
El archivo debe contener, como mínimo, las columnas: <code>id</code>, <code>nombre</code>, <code>url</code>, <code>categoria_id</code>, <code>pais_id</code>, e <code>idioma</code>.
Para añadir nuevas fuentes, asegúrate de que los <code>id</code> no existan en la base de datos (puedes usar números altos).
</p>
<hr>
<form method="POST" enctype="multipart/form-data" action="{{ url_for('restore_urls') }}">
<div class="mb-3">
<label for="file" class="form-label">Selecciona el archivo CSV:</label>
<input class="form-control" type="file" id="file" name="file" accept=".csv" required>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-upload"></i> Importar Fuentes URL
</button>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary">
<i class="fas fa-times"></i> Cancelar
</a>
</form>
</div>
</div>
{% endblock %}

View file

@ -1,44 +1,45 @@
{% extends "base.html" %}
{% block title %}Gestionar Fuentes URL{% endblock %}
{% block content %}
<div class="feed-detail-card">
<div class="card feed-detail-card">
<div class="feed-header">
<h2>Fuentes de Noticias URL</h2>
<a href="{{ url_for('add_url_source') }}" class="btn btn-small">Añadir Nueva Fuente URL</a>
<h2>Lista de Fuentes URL ({{ fuentes|length }})</h2>
<div class="nav-actions">
<a href="{{ url_for('add_url_source') }}" class="btn btn-small"><i class="fas fa-plus"></i> Añadir URL</a>
</div>
</div>
<div class="feed-body">
{% if fuentes %}
<table class="table table-hover">
<thead>
<tr>
<th>Nombre</th>
<th>URL</th>
<th>Categoría</th>
<th>País</th>
<th>Idioma</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{% for fuente in fuentes %}
<tr>
<td>{{ fuente.nombre }}</td>
<td><a href="{{ fuente.url }}" target="_blank">{{ fuente.url[:50] }}...</a></td>
<td>{{ fuente.categoria or 'N/A' }}</td>
<td>{{ fuente.pais or 'N/A' }}</td>
<td>{{ fuente.idioma }}</td>
<td>
<a href="{{ url_for('edit_url_source', url_id=fuente.id) }}" class="btn btn-small btn-secondary">Editar</a>
<a href="{{ url_for('delete_url_source', url_id=fuente.id) }}" class="btn btn-small btn-danger" onclick="return confirm('¿Estás seguro de que quieres eliminar esta fuente?');">Eliminar</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-center text-muted">No hay fuentes URL guardadas. ¡Añade la primera!</p>
{% endif %}
<div class="feed-body" style="padding: 0;">
<table style="width:100%; border-collapse: collapse;">
<thead>
<tr style="background-color: rgba(0,0,0,0.05);">
<th style="padding: 12px 15px; text-align: left;">Nombre</th>
<th style="padding: 12px 15px; text-align: left;">Categoría</th>
<th style="padding: 12px 15px; text-align: left;">País</th>
<th style="padding: 12px 15px; text-align: right;">Acciones</th>
</tr>
</thead>
<tbody>
{% for fuente in fuentes %}
<tr>
<td style="padding: 12px 15px; border-top: 1px solid var(--border-color);">
<a href="{{ fuente.url }}" target="_blank" title="{{ fuente.url }}">{{ fuente.nombre }}</a>
</td>
<td style="padding: 12px 15px; border-top: 1px solid var(--border-color);">{{ fuente.categoria or 'N/A' }}</td>
<td style="padding: 12px 15px; border-top: 1px solid var(--border-color);">{{ fuente.pais or 'Global' }}</td>
<td style="padding: 12px 15px; text-align: right; border-top: 1px solid var(--border-color);">
<a href="{{ url_for('edit_url_source', url_id=fuente.id) }}" class="btn btn-small btn-info"><i class="fas fa-edit"></i></a>
<a href="{{ url_for('delete_url_source', url_id=fuente.id) }}" class="btn btn-small btn-danger" onclick="return confirm('¿Estás seguro?')"><i class="fas fa-trash"></i></a>
</td>
</tr>
{% else %}
<tr>
<td colspan="4" style="padding: 20px; text-align: center;">No hay fuentes URL para mostrar.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}