Añadida restauración de feeds desde CSV, mejoras en UI, y campo descripción en feeds

This commit is contained in:
jlimolina 2025-05-27 12:36:35 +02:00
parent d7cabbb2c6
commit 4ca48836c9
6 changed files with 298 additions and 182 deletions

17
templates/base.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>{% block title %}Noticias RSS{% endblock %}</title>
<link href="https://fonts.googleapis.com/css?family=Inter:400,600&display=swap" rel="stylesheet">
<style>
/* [todo el CSS del ejemplo anterior aquí] */
</style>
</head>
<body>
<div class="container">
{% block content %}{% endblock %}
</div>
</body>
</html>

View file

@ -1,50 +1,42 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Editar Feed RSS</title>
</head>
<body>
{% extends "base.html" %}
{% block title %}Editar Feed RSS{% endblock %}
{% block content %}
<h1>Editar Feed</h1>
<form method="post">
<label>
Nombre del feed:<br>
<input name="nombre" placeholder="Nombre" value="{{ feed['nombre'] }}" required>
</label>
<br><br>
<label>
URL del RSS:<br>
<input name="url" placeholder="URL" value="{{ feed['url'] }}" required>
</label>
<br><br>
<label>
Categoría:<br>
<select name="categoria_id" required>
<div class="card">
<form method="post" autocomplete="off">
<label for="nombre">Nombre del feed</label>
<input id="nombre" name="nombre" type="text" placeholder="Nombre" value="{{ feed['nombre'] }}" required>
<label for="descripcion">Descripción</label>
<textarea id="descripcion" name="descripcion" rows="2" placeholder="Breve descripción del feed">{{ feed['descripcion'] or '' }}</textarea>
<label for="url">URL del RSS</label>
<input id="url" name="url" type="url" placeholder="URL" value="{{ feed['url'] }}" required>
<label for="categoria_id">Categoría</label>
<select id="categoria_id" name="categoria_id" required>
<option value="">— Elige categoría —</option>
{% for cat in categorias %}
<option value="{{ cat.id }}" {% if cat.id == feed['categoria_id'] %}selected{% endif %}>{{ cat.nombre }}</option>
{% endfor %}
</select>
</label>
<br><br>
<label>
País:<br>
<select name="pais_id" required>
<label for="pais_id">País</label>
<select id="pais_id" name="pais_id" required>
<option value="">— Elige país —</option>
{% for p in paises %}
<option value="{{ p.id }}" {% if p.id == feed['pais_id'] %}selected{% endif %}>{{ p.nombre }}</option>
{% endfor %}
</select>
</label>
<br><br>
<label>
<input type="checkbox" name="activo" {% if feed['activo'] %}checked{% endif %}>
Activo
</label>
<br><br>
<button type="submit">Guardar cambios</button>
<a href="{{ url_for('index') }}">Cancelar</a>
</form>
</body>
</html>
<div style="margin: 12px 0;">
<input type="checkbox" id="activo" name="activo" {% if feed['activo'] %}checked{% endif %}>
<label for="activo" style="display:inline;">Activo</label>
</div>
<button class="btn" type="submit">Guardar cambios</button>
<a href="{{ url_for('feeds') }}">Cancelar</a>
</form>
</div>
{% endblock %}

View file

@ -1,10 +1,95 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Gestión de Feeds RSS</title>
{% extends "base.html" %}
{% block title %}Gestión de Feeds RSS{% endblock %}
{% block content %}
<h1>Gestión de Feeds RSS</h1>
<a href="/" class="top-link">← Volver a últimas noticias</a>
<div class="card">
<h2>Añadir un nuevo feed</h2>
<form action="/add" method="post" autocomplete="off">
<label for="nombre">Nombre del feed</label>
<input id="nombre" name="nombre" placeholder="Nombre del feed" required>
<label for="descripcion">Descripción</label>
<textarea id="descripcion" name="descripcion" placeholder="Breve descripción del feed" rows="2"></textarea>
<label for="url">URL del RSS</label>
<input id="url" name="url" placeholder="URL del RSS" required>
<label for="categoria_id">Categoría</label>
<select id="categoria_id" name="categoria_id" required>
<option value="">— Elige categoría —</option>
{% for cid, cnom in categorias %}
<option value="{{ cid }}">{{ cnom }}</option>
{% endfor %}
</select>
<label for="continente_id">Continente</label>
<select name="continente_id" id="continente_id" onchange="filtrarPaisesPorContinente()">
<option value="">— Elige continente —</option>
{% for coid, conom in continentes %}
<option value="{{ coid }}">{{ conom }}</option>
{% endfor %}
</select>
<label for="pais_id">País</label>
<select name="pais_id" id="pais_id">
<option value="">— N/A —</option>
{% for pid, pnom, contid in paises %}
<option value="{{ pid }}">{{ pnom }}</option>
{% endfor %}
</select>
<button class="btn" type="submit">Añadir</button>
<!-- Datos en JSON para el filtro dinámico de países -->
<script type="application/json" id="paises-data">{{ paises|tojson }}</script>
</form>
</div>
<div class="card">
<h2>Lista de Feeds</h2>
<a href="/backup_feeds" target="_blank" class="btn">⬇️ Descargar backup de feeds (CSV)</a>
<a href="/restore_feeds" class="btn" style="margin-left:10px;">🔄 Restaurar feeds desde backup</a>
<table>
<thead>
<tr>
<th>Nombre y descripción</th>
<th>URL</th>
<th>Categoría</th>
<th>País</th>
<th>Activo</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{% for id, nombre, descripcion, url, categoria_id, pais_id, activo, cat_nom, pais_nom in feeds %}
<tr>
<td>
<strong>{{ nombre }}</strong>
{% if descripcion %}
<div style="font-size:0.95em; color:#64748b;">{{ descripcion }}</div>
{% endif %}
</td>
<td><a href="{{ url }}" target="_blank">{{ url }}</a></td>
<td>{{ cat_nom or 'N/A' }}</td>
<td>{{ pais_nom or 'N/A' }}</td>
<td>{{ 'Sí' if activo else 'No' }}</td>
<td class="actions">
<a href="/edit/{{ id }}">Editar</a> |
<a href="/delete/{{ id }}" onclick="return confirm('¿Seguro que quieres eliminar este feed?');">Eliminar</a>
</td>
</tr>
{% else %}
<tr>
<td colspan="6">No hay feeds aún.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<a href="/" class="top-link">← Volver a últimas noticias</a>
<script>
// Script para filtrar países según continente elegido
function filtrarPaisesPorContinente() {
const continenteId = document.getElementById('continente_id').value;
const paises = JSON.parse(document.getElementById('paises-data').textContent);
@ -25,63 +110,5 @@
});
}
</script>
</head>
<body>
<h1>Gestión de Feeds RSS</h1>
<p><a href="/">← Volver a últimas noticias</a></p>
<!-- Enlace de backup de feeds -->
<p>
<a href="/backup_feeds" target="_blank">⬇️ Descargar backup de feeds (CSV)</a>
</p>
<h2>Añadir un nuevo feed</h2>
<form action="/add" method="post">
<input name="nombre" placeholder="Nombre del feed" required>
<input name="url" placeholder="URL del RSS" required>
<select name="categoria_id" required>
<option value="">— Elige categoría —</option>
{% for cid, cnom in categorias %}
<option value="{{ cid }}">{{ cnom }}</option>
{% endfor %}
</select>
<select name="continente_id" id="continente_id" onchange="filtrarPaisesPorContinente()">
<option value="">— Elige continente —</option>
{% for coid, conom in continentes %}
<option value="{{ coid }}">{{ conom }}</option>
{% endfor %}
</select>
<select name="pais_id" id="pais_id">
<option value="">— N/A —</option>
{% for pid, pnom, contid in paises %}
<option value="{{ pid }}">{{ pnom }}</option>
{% endfor %}
</select>
<button type="submit">Añadir</button>
<!-- Datos en JSON para el filtro dinámico de países -->
<script type="application/json" id="paises-data">{{ paises|tojson }}</script>
</form>
<h2>Lista de Feeds</h2>
<ul>
{% for id, nombre, url, categoria_id, pais_id, activo, cat_nom, pais_nom in feeds %}
<li>
<strong>{{ nombre }}</strong>
(<a href="{{ url }}" target="_blank">{{ url }}</a>)
— Categoría: {{ cat_nom or 'N/A' }}
— País: {{ pais_nom or 'N/A' }}
— Activo: {{ 'Sí' if activo else 'No' }}
<!-- Enlace de edición de feed -->
| <a href="/edit/{{ id }}">Editar</a>
<!-- Enlace para eliminar feed con confirmación -->
| <a href="/delete/{{ id }}" onclick="return confirm('¿Seguro que quieres eliminar este feed?');">Eliminar</a>
</li>
{% else %}
<li>No hay feeds aún.</li>
{% endfor %}
</ul>
<p><a href="/">← Volver a últimas noticias</a></p>
</body>
</html>
{% endblock %}

View file

@ -1,8 +1,82 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Últimas Noticias RSS</title>
{% extends "base.html" %}
{% block title %}Últimas Noticias RSS{% endblock %}
{% block content %}
<h1>Últimas Noticias Recopiladas</h1>
<a href="/feeds" class="top-link">⚙️ Gestionar feeds RSS</a>
<div class="card">
<form method="get" action="">
<div style="display: flex; flex-wrap: wrap; gap: 12px;">
<div style="flex:1;">
<label for="categoria_id">Categoría</label>
<select name="categoria_id" id="categoria_id">
<option value="">— Categoría —</option>
{% for cid, cnom in categorias %}
<option value="{{ cid }}" {% if cat_id == cid %}selected{% endif %}>{{ cnom }}</option>
{% endfor %}
</select>
</div>
<div style="flex:1;">
<label for="continente_id">Continente</label>
<select name="continente_id" id="continente_id" onchange="filtrarPaisesPorContinente()">
<option value="">— Continente —</option>
{% for coid, conom in continentes %}
<option value="{{ coid }}" {% if cont_id == coid %}selected{% endif %}>{{ conom }}</option>
{% endfor %}
</select>
</div>
<div style="flex:1;">
<label for="pais_id">País</label>
<select name="pais_id" id="pais_id">
<option value="">— País —</option>
{% for pid, pnom, contid in paises %}
<option value="{{ pid }}"
{% if pais_id == pid %}selected{% endif %}
{% if cont_id and contid != cont_id %}style="display:none"{% endif %}>
{{ pnom }}
</option>
{% endfor %}
</select>
</div>
<div style="align-self: flex-end;">
<button class="btn" type="submit">Filtrar</button>
</div>
</div>
<script type="application/json" id="paises-data">{{ paises|tojson }}</script>
</form>
</div>
<div class="card">
<h2 style="margin-top:0;">Noticias recientes</h2>
<ul style="list-style:none; padding:0;">
{% for fecha, titulo, resumen, url, imagen_url, cat_nom, pais_nom, cont_nom in noticias %}
<li style="margin-bottom: 2em; border-bottom: 1px solid #eee; padding-bottom: 1em;">
<div style="display: flex; gap:18px;">
{% if imagen_url %}
<div>
<img src="{{ imagen_url }}" alt="img" style="max-width:160px; max-height:100px; border-radius:6px;">
</div>
{% endif %}
<div style="flex:1;">
<div style="color:#64748b; font-size:0.97em;"><b>{{ fecha }}</b></div>
<a href="{{ url }}" target="_blank"><strong>{{ titulo }}</strong></a><br>
<span>{{ resumen|safe }}</span><br>
<small style="color:#64748b;">
Categoría: {{ cat_nom or 'N/A' }} |
País: {{ pais_nom or 'N/A' }} |
Continente: {{ cont_nom or 'N/A' }}
</small>
</div>
</div>
</li>
{% else %}
<li>No hay noticias que mostrar con estos filtros.</li>
{% endfor %}
</ul>
</div>
<a href="/feeds" class="top-link">← Volver a gestión de feeds</a>
<script>
function filtrarPaisesPorContinente() {
const continenteId = document.getElementById('continente_id').value;
@ -12,7 +86,7 @@
// Opción N/A siempre presente
const optionNA = document.createElement('option');
optionNA.value = '';
optionNA.textContent = '— N/A —';
optionNA.textContent = '— País —';
selectPais.appendChild(optionNA);
paises.forEach(([id, nombre, contId]) => {
if (!continenteId || contId == continenteId) {
@ -24,63 +98,5 @@
});
}
</script>
</head>
<body>
<h1>Últimas Noticias Recopiladas</h1>
<!-- Enlace de gestión de feeds -->
<p><a href="/feeds">⚙️ Gestionar feeds RSS</a></p>
<form method="get" action="">
<select name="categoria_id">
<option value="">— Categoría —</option>
{% for cid, cnom in categorias %}
<option value="{{ cid }}" {% if cat_id == cid %}selected{% endif %}>{{ cnom }}</option>
{% endfor %}
</select>
<select name="continente_id" id="continente_id" onchange="filtrarPaisesPorContinente()">
<option value="">— Continente —</option>
{% for coid, conom in continentes %}
<option value="{{ coid }}" {% if cont_id == coid %}selected{% endif %}>{{ conom }}</option>
{% endfor %}
</select>
<select name="pais_id" id="pais_id">
<option value="">— País —</option>
{% for pid, pnom, contid in paises %}
<option value="{{ pid }}"
{% if pais_id == pid %}selected{% endif %}
{% if cont_id and contid != cont_id %}style="display:none"{% endif %}>
{{ pnom }}
</option>
{% endfor %}
</select>
<button type="submit">Filtrar</button>
<script type="application/json" id="paises-data">{{ paises|tojson }}</script>
</form>
<hr>
<ul>
{% for fecha, titulo, resumen, url, imagen_url, cat_nom, pais_nom, cont_nom in noticias %}
<li style="margin-bottom: 2em;">
<small><b>{{ fecha }}</b></small><br>
<a href="{{ url }}" target="_blank"><strong>{{ titulo }}</strong></a><br>
{% if imagen_url %}
<img src="{{ imagen_url }}" alt="img" style="max-width:200px; max-height:120px;"><br>
{% endif %}
<span>{{ resumen|safe }}</span><br>
<small>
Categoría: {{ cat_nom or 'N/A' }} |
País: {{ pais_nom or 'N/A' }} |
Continente: {{ cont_nom or 'N/A' }}
</small>
</li>
{% else %}
<li>No hay noticias que mostrar con estos filtros.</li>
{% endfor %}
</ul>
<p><a href="/feeds">← Volver a gestión de feeds</a></p>
</body>
</html>
{% endblock %}

View file

@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block title %}Restaurar Feeds RSS{% endblock %}
{% block content %}
<h1>Restaurar feeds desde backup CSV</h1>
<div class="card" style="max-width:500px;margin:auto;">
<form method="post" enctype="multipart/form-data" autocomplete="off">
<label for="file"><strong>Selecciona el archivo CSV exportado de feeds:</strong></label>
<input type="file" name="file" id="file" accept=".csv" required style="margin:10px 0;">
<button class="btn" type="submit">Restaurar</button>
</form>
{% if msg %}
<div style="margin:15px 0;">
<strong>{{ msg }}</strong>
</div>
{% endif %}
<p style="font-size:0.92em;color:#64748b;">
El archivo debe contener las columnas: <br>
<code>id, nombre, [descripcion,] url, categoria_id, categoria, pais_id, pais, activo</code><br>
<small>La columna <b>descripcion</b> es opcional.</small>
</p>
</div>
<a href="/feeds" class="top-link">← Volver a feeds</a>
{% endblock %}