From 6f544db2099b606eec6c451bcfe85b5036936667 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joakim=20Hells=C3=A9n?=
Date: Tue, 30 Jan 2024 05:37:14 +0100
Subject: [PATCH] Update HTML
---
.vscode/settings.json | 1 +
feeds/urls.py | 6 ++++-
feeds/views.py | 47 ++++++++++++++++++++++++++++++++
static/Feed.svg | 1 +
static/style.css | 21 ++++++---------
templates/api.html | 8 ++++++
templates/base.html | 31 ++++++++++++++++-----
templates/index.html | 63 ++++++++++++++++++++++++++++---------------
8 files changed, 137 insertions(+), 41 deletions(-)
create mode 100644 static/Feed.svg
create mode 100644 templates/api.html
diff --git a/.vscode/settings.json b/.vscode/settings.json
index cecafac..b1ba086 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,6 +4,7 @@
"feedburner",
"feedparser",
"feedvault",
+ "leftright",
"PGHOST",
"PGPORT",
"PGUSER",
diff --git a/feeds/urls.py b/feeds/urls.py
index d4a2c3a..9a507b8 100644
--- a/feeds/urls.py
+++ b/feeds/urls.py
@@ -2,7 +2,7 @@
from django.urls import path
-from feeds.views import FeedsView, IndexView
+from feeds.views import APIView, FeedsView, IndexView, add_feeds
app_name = "feeds"
@@ -11,4 +11,8 @@ urlpatterns = [
path("", IndexView.as_view(), name="index"),
# /feeds
path("feeds", FeedsView.as_view(), name="feeds"),
+ # /add
+ path("add", add_feeds, name="add"),
+ # /api
+ path("api", APIView.as_view(), name="api"),
]
diff --git a/feeds/views.py b/feeds/views.py
index 2627b3b..d3be0d6 100644
--- a/feeds/views.py
+++ b/feeds/views.py
@@ -8,12 +8,17 @@ from __future__ import annotations
import typing
+from django.contrib import messages
from django.db import connection
+from django.shortcuts import redirect
from django.views.generic.base import TemplateView
from django.views.generic.list import ListView
from feeds.models import Feed
+if typing.TYPE_CHECKING:
+ from django.http import HttpRequest, HttpResponseRedirect
+
def get_database_size() -> int:
"""Get the size of a database.
@@ -65,3 +70,45 @@ class FeedsView(ListView):
context["feed_count"] = Feed.objects.count()
context["database_size"] = get_database_size()
return context
+
+
+def add_feeds(request: HttpRequest) -> HttpResponseRedirect:
+ """Add feeds to the database.
+
+ Args:
+ request: The request object.
+
+ Returns:
+ A redirect to the index page.
+ """
+ if request.method == "POST":
+ urls = request.POST.get("urls")
+ if not urls:
+ messages.error(request, "No URLs provided")
+ return redirect("feeds:index", permanent=False)
+
+ if urls == "Test":
+ messages.error(request, "Hello, world!")
+ return redirect("feeds:index", permanent=False)
+
+ for url in urls.splitlines():
+ print(f"Adding {url} to the database...") # noqa: T201
+
+ return redirect("feeds:feeds", permanent=False)
+
+ msg: str = f"You must use a POST request. You used a {request.method} request. You can find out how to use this endpoint here: http://127.0.0.1:8000/. If you think this is a mistake, please contact the administrator." # noqa: E501
+ messages.error(request, msg)
+ return redirect("feeds:index", permanent=False)
+
+
+class APIView(TemplateView):
+ """Index page."""
+
+ template_name = "api.html"
+
+ def get_context_data(self: APIView, **kwargs: dict) -> dict:
+ """Add feed count and database size to context data."""
+ context: dict = super().get_context_data(**kwargs)
+ context["feed_count"] = Feed.objects.count()
+ context["database_size"] = get_database_size()
+ return context
diff --git a/static/Feed.svg b/static/Feed.svg
new file mode 100644
index 0000000..bfa1926
--- /dev/null
+++ b/static/Feed.svg
@@ -0,0 +1 @@
+
diff --git a/static/style.css b/static/style.css
index c82cd12..d863cf0 100644
--- a/static/style.css
+++ b/static/style.css
@@ -1,25 +1,19 @@
html {
max-width: 70ch;
- /* larger spacing on larger screens, very small spacing on tiny screens */
padding: calc(1vmin + 0.5rem);
- /* shorthand for margin-left/margin-right */
margin-inline: auto;
- /* fluid sizing: https://frontaid.io/blog/fluid-typography-2d-css-locks-clamp/ */
font-size: clamp(1em, 0.909em + 0.45vmin, 1.25em);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif;
- /* use dark mode if user prefers it */
color-scheme: light dark;
}
-/* h1 */
h1 {
font-size: 2.5rem;
font-weight: 600;
margin: 0;
}
-/* FeedVault logo */
.title {
text-align: center;
}
@@ -27,21 +21,15 @@ h1 {
.search {
display: flex;
justify-content: center;
-
- /* Spacing between search bar and nav bar */
margin-top: 1rem;
-
- /* Center the search bar */
margin-inline: auto;
}
-/* Links at the top and bottom of the page */
.leftright {
display: flex;
justify-content: center;
}
-/* Align the links to the left and right */
.left {
margin-right: auto;
}
@@ -50,9 +38,16 @@ h1 {
margin-left: auto;
}
-/* Add feeds box */
textarea {
width: 100%;
height: 10rem;
resize: vertical;
}
+
+.error {
+ color: red;
+}
+
+.messages {
+ list-style-type: none;
+}
diff --git a/templates/api.html b/templates/api.html
new file mode 100644
index 0000000..a8159bd
--- /dev/null
+++ b/templates/api.html
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+{% block title %}Feeds{% endblock %}
+{% block description %}FeedVault - A feed archive{% endblock %}
+{% block keywords %}RSS, Atom, Feed, Archive{% endblock %}
+{% block content %}
+ API documentation
+ Here be dragons.
+{% endblock %}
diff --git a/templates/base.html b/templates/base.html
index d3d43aa..9b4ea8c 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -13,20 +13,39 @@
{% if canonical_url %}{% endif %}
+ {% if messages %}
+
+ {% for message in messages %}
+ - {{ message|safe }}
+ {% endfor %}
+
+
+ {% endif %}
-
- FeedVault
-
+
- An archive of web feeds. Currently archiving {{ feed_count }} feeds. ~{{ database_size|floatformat:2 }} MB of data.
+
+
+
Archive of web feeds. {{ feed_count }} feeds. ~{{ database_size|floatformat:2 }} MB.
+
+
+
+
+
+
How does it work?
- FeedVault uses feedparser to parse the feeds. The parsed feeds are then stored in a database. The feeds are updated every 30 minutes.
+
+ -
+ Parse XML data using the feedparser library.
+
+ -
+ Before saving the parsed data to the database, HTML content is sanitized.
+
+ - The sanitized data is then stored in a PostgreSQL database using Django's ORM.
+ -
+ The data is then made available through the website and the API.
+
+
How can I access the archived feeds?
- You can find feeds by using the search bar at the top of the page. You can also use the API to access the feeds.
+
+ - You can search for feeds through the search bar at the top of the page.
+ -
+ You can access the archived feeds through the website.
+
+ -
+ You can access the archived feeds through the API.
+
+ -
+ You can download database dumps from here.
+
+
-
{% endblock %}