Actualización del 2025-06-15 a las 19:26:12

This commit is contained in:
jlimolina 2025-06-15 19:26:12 +02:00
parent d23754d3b8
commit 603149d47a
9 changed files with 350 additions and 122 deletions

View file

@ -0,0 +1,49 @@
{% extends "base.html" %}
{% block title %}Añadir Fuente URL{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h4 class="mb-0">Añadir Nueva Fuente de Noticias URL</h4>
</div>
<div class="card-body">
<p class="card-text text-muted">Añade un periódico o sitio de noticias para poder procesar sus artículos más tarde.</p>
<form action="{{ url_for('add_url_source') }}" method="post" class="mt-3">
<div class="mb-3">
<label for="nombre" class="form-label"><strong>Nombre de la Fuente</strong></label>
<input type="text" class="form-control" id="nombre" name="nombre" required placeholder="Ej: El País (Portada)">
</div>
<div class="mb-3">
<label for="url" class="form-label"><strong>URL de la Fuente</strong></label>
<input type="url" class="form-control" id="url" name="url" required placeholder="https://elpais.com">
</div>
<div class="mb-3">
<label for="categoria_id" class="form-label"><strong>Categoría por Defecto</strong></label>
<select class="form-select" id="categoria_id" name="categoria_id">
<option value="">-- Sin categoría --</option>
{% for cat in categorias %}<option value="{{ cat.id }}">{{ cat.nombre }}</option>{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="pais_id" class="form-label"><strong>País por Defecto</strong></label>
<select class="form-select" id="pais_id" name="pais_id">
<option value="">-- Sin país --</option>
{% for p in paises %}<option value="{{ p.id }}">{{ p.nombre }}</option>{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="idioma" class="form-label"><strong>Idioma (código de 2 letras)</strong></label>
<input type="text" class="form-control" id="idioma" name="idioma" value="es" required pattern="[a-z]{2}">
</div>
<div class="d-flex justify-content-end pt-3">
<a href="{{ url_for('manage_urls') }}" class="btn btn-secondary" style="margin-right: 10px;">Cancelar</a>
<button type="submit" class="btn">Guardar Fuente</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

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 {
@ -69,6 +69,7 @@
.btn:hover, button:hover { transform: translateY(-3px); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); text-decoration: none; }
.btn-secondary { background: #34495e; } .btn-secondary:hover { background: #2c3e50; }
.btn-info { background: #17a2b8; } .btn-info:hover { background: #138496; }
.btn-danger { background: #dc3545; } .btn-danger:hover { background: #c82333; }
.btn-small { padding: 6px 14px; font-size: 0.9rem; }
a { color: var(--secondary-color); text-decoration: none; font-weight: 500; } a:hover { text-decoration: underline; }
.top-link { display: inline-block; margin-bottom: 25px; font-weight: 500; color: var(--primary-color); }
@ -110,7 +111,7 @@
.feed-body dt { font-weight: 600; color: var(--text-color-light); }
.feed-body dd { margin: 0; word-break: break-all; }
/* --- NUEVOS ESTILOS PARA LA NAVEGACIÓN PRINCIPAL --- */
/* --- Estilos para la Navegación Principal --- */
.main-nav {
display: flex;
justify-content: center;
@ -136,7 +137,7 @@
.nav-actions {
display: flex;
gap: 10px;
margin-left: 20px; /* Espacio entre los enlaces y los botones */
margin-left: 20px;
}
/* --- Responsividad --- */
@ -163,10 +164,10 @@
<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('add_feed') }}" class="btn btn-small">Añadir Feed</a>
<a href="{{ url_for('add_url') }}" class="btn btn-small btn-info">Añadir URL</a>
<a href="{{ url_for('scrape_url') }}" class="btn btn-small btn-info">Procesar URL</a>
</div>
</nav>
</header>

View file

@ -2,16 +2,10 @@
{% block title %}Dashboard de Feeds{% endblock %}
{% block content %}
<header>
<h1>Dashboard de Feeds</h1>
<p class="subtitle">Un resumen del estado de tu agregador de noticias.</p>
<a href="{{ url_for('home') }}" class="top-link">← Volver a las Noticias</a>
</header>
<div class="dashboard-grid">
<div class="stat-card">
<div class="stat-number">{{ stats.feeds_totales }}</div>
<div class="stat-label">Feeds Totales</div>
<div class="stat-label">Feeds RSS Totales</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ stats.noticias_totales }}</div>
@ -26,9 +20,9 @@
</div>
<div class="card">
<h2 style="text-align: center; margin-bottom: 20px;">Opciones de Backup</h2>
<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 seguras
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;">
@ -41,24 +35,10 @@
<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>
</div>
</div>
<div class="card" style="text-align: center; margin-top: 30px;">
<h2 style="margin-bottom: 20px;">Gestionar Feeds</h2>
<p style="color: var(--text-color-light); margin-bottom: 25px;">
Administra tu lista de fuentes de noticias
</p>
<div style="display: flex; justify-content: center; gap: 15px; flex-wrap: wrap;">
<a href="{{ url_for('manage_feeds') }}" class="btn" style="display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-list"></i> Lista Completa
</a>
<a href="{{ url_for('add_feed') }}" class="btn" style="display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-plus"></i> Nuevo Feed
</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
<i class="fas fa-file-import"></i> Importar Feeds
</a>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,37 @@
{% extends "base.html" %}
{% block title %}Editar Fuente URL{% endblock %}
{% block content %}
<h2>Editar Fuente: {{ fuente.nombre }}</h2>
<form action="{{ url_for('edit_url_source', url_id=fuente.id) }}" method="post" class="form-section">
<div class="mb-3">
<label for="nombre">Nombre de la Fuente</label>
<input type="text" id="nombre" name="nombre" value="{{ fuente.nombre }}" required>
</div>
<div class="mb-3">
<label for="url">URL de la Fuente</label>
<input type="url" id="url" name="url" value="{{ fuente.url }}" required>
</div>
<div class="mb-3">
<label for="categoria_id">Categoría por Defecto</label>
<select id="categoria_id" name="categoria_id">
<option value="">-- Sin categoría --</option>
{% for cat in categorias %}<option value="{{ cat.id }}" {% if cat.id == fuente.categoria_id %}selected{% endif %}>{{ cat.nombre }}</option>{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="pais_id">País por Defecto</label>
<select id="pais_id" name="pais_id">
<option value="">-- Sin país --</option>
{% for p in paises %}<option value="{{ p.id }}" {% if p.id == fuente.pais_id %}selected{% endif %}>{{ p.nombre }}</option>{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="idioma">Idioma (código de 2 letras)</label>
<input type="text" id="idioma" name="idioma" value="{{ fuente.idioma }}" required pattern="[a-z]{2}">
</div>
<div class="d-flex justify-content-end">
<a href="{{ url_for('manage_urls') }}" class="btn btn-secondary" style="margin-right: 10px;">Cancelar</a>
<button type="submit" class="btn">Actualizar Fuente</button>
</div>
</form>
{% endblock %}

30
templates/scrape_url.html Normal file
View file

@ -0,0 +1,30 @@
{% extends "base.html" %}
{% block title %}Scrapear Noticias desde Fuente URL{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header bg-info text-white">
<h4>Procesar Noticias desde una Fuente Guardada</h4>
</div>
<div class="card-body">
<form action="{{ url_for('scrape_url') }}" method="post">
<div class="mb-3">
<label for="source_id" class="form-label"><strong>Selecciona una fuente de noticias:</strong></label>
<select class="form-select" id="source_id" name="source_id" required>
<option value="" disabled selected>-- Elige un periódico --</option>
{% for fuente in fuentes %}
<option value="{{ fuente.id }}">{{ fuente.nombre }}</option>
{% endfor %}
</select>
</div>
<div class="d-flex justify-content-end pt-3">
<button type="submit" class="btn">Procesar Noticias</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

44
templates/urls_list.html Normal file
View file

@ -0,0 +1,44 @@
{% extends "base.html" %}
{% block title %}Gestionar Fuentes URL{% endblock %}
{% block content %}
<div class="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>
</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>
</div>
{% endblock %}