Compare commits

...

3 Commits

Author SHA1 Message Date
Ryan Rix 56f8309776 fix route for configuration page 2024-03-05 11:07:18 -08:00
Ryan Rix 36bd20f0d2 if a page has no published entries, return a 404 for the feed 2024-03-05 11:07:01 -08:00
Ryan Rix b4c12058be reformat doc again 2024-03-05 11:06:47 -08:00
5 changed files with 87 additions and 89 deletions

View File

@ -523,21 +523,7 @@ class FeedEntryAdmin(admin.ModelAdmin):
* The Web Server
"""arcology URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
These are the route [[https://docs.djangoproject.com/en/3.2/topics/http/urls/][urlpatterns]]:
#+begin_src python :tangle arcology/urls.py
from django.contrib import admin
@ -560,9 +546,11 @@ urlpatterns = [
]
#+end_src
This is the topmatter for the views described below:
#+begin_src python :tangle arcology/views.py
import logging
from django.http import HttpResponse, HttpResponseNotFound
from django.http import HttpResponse, HttpResponseNotFound, Http404
from django.shortcuts import render, get_object_or_404
from arcology.models import Page, Feed, Site
@ -573,16 +561,14 @@ from prometheus_client import Counter, Histogram
logger = logging.getLogger(__name__)
#+end_src
** NEXT =GET /= site index
** =GET /= site index
this will just call the org-page rendering handler for the site's index pages eventually
this will just call the Org Page rendering function for the site's index page. =render_page= is defined below.
#+begin_src python :tangle arcology/views.py
def index(request):
site = Site.from_request(request)
full_key = f"{site.key}/index"
return render_page(request, site, full_key)
#+end_src
@ -594,7 +580,7 @@ def index(request):
- State "INPROGRESS" from [2023-12-20 Wed 17:48]
:END:
This constructs a page key, tries to load that page and its HTML, and renders that along with a bunch of other metadata.
This constructs a page key from the request, tries to load that page and its HTML, and renders that along with a bunch of other metadata stored in relation to the =Page= object in the DB.
#+begin_src python :tangle arcology/views.py
def org_page(request, key):
@ -657,7 +643,7 @@ def render_page(request, site, full_key):
))
#+end_src
*** Rendering the converted Org HTML in to a whole web-page
*** =arcology/page.html= extends =app.html= to embed the Org page and its metadata
:PROPERTIES:
:ID: 20240226T174503.655394
:ROAM_ALIASES: "Arcology Page HTML Template"
@ -783,7 +769,7 @@ Here's a really simple 404 template, too.
:ROAM_ALIASES: "Arcology Page CSS Files"
:END:
Most of the page CSS is defined below, but the content CSS is here, nearer the actual implementation of the flexbox:
Most of the page CSS is defined below as part of the =app.html=, but the content-specific CSS is here, nearer the actual implementation of the flexbox above.
#+begin_src css :tangle arcology/static/arcology/css/app.css :mkdirp yes
.content {
@ -893,11 +879,16 @@ def feed(request, key):
# Fetch page metadata
the_feed = get_object_or_404(Feed, route_key=full_key)
entries = the_feed.feedentry_set.order_by("-pubdate").all()[:10]
if len(entries) == 0:
return Http404()
try:
page_author = roam.models.Keyword.objects.get(keyword="AUTHOR", path=the_feed.file).value
except roam.models.Keyword.DoesNotExist:
logger.warn(f"Feed {key} does not have an AUTHOR!")
page_author = "Arcology User"
page_url = the_feed.file.page_set.first().to_url()
updated_at = arrow.get(entries[0].pubdate).format(arrow.FORMAT_RFC3339) # entries is already sorted
@ -971,7 +962,7 @@ def get_item(dictionary, key):
- State "CANCELLED" from "NEXT" [2024-02-26 Mon 17:46]
:END:
** NEXT unpublished/not found endpoint
** 404 unpublished/not found endpoint
There are plenty of links inside the Arcology which aren't meant to be clicked. =roam:= stub links will of course
@ -991,7 +982,7 @@ def unpublished(request):
)
#+end_src
** =robots.txt= Endpoint
** =GET /robots.txt= Endpoint
[[https://en.wikipedia.org/wiki/Robots.txt][robots.txt]] is the [[roam:Robots Exclusion Protocol]], a standard used by websites to indicate to visiting web crawlers and other web robots which portions of the website they are allowed to visit.
@ -1029,7 +1020,7 @@ Disallow: /
{% endfor %}
#+end_src
** Feed discovery endpoint
** =GET /feeds.json= Feed discovery endpoint
:LOGBOOK:
CLOCK: [2024-02-15 Thu 14:17]--[2024-02-15 Thu 14:41] => 0:24
:END:
@ -1053,7 +1044,45 @@ def feed_list(request):
return HttpResponse(json.dumps(ret), content_type="application/json")
#+end_src
** Arcology Site Templates
** =GET /sites.css= Per-Site link color dynamic CSS endpoint
:PROPERTIES:
:ID: 20231229T215425.830707
:END:
This endpoint generates a dynamic CSS file that colorizes internal URLs based on the [[id:20231229T164611.256424][The Arcology's Site List]] which is stored in the database. It does something [[https://twitter.com/gotMLK7/status/1675994399086641152][extremely wicked]] to make the page links less jarring until you hover over them by faking an alpha-channel in to the color.
#+begin_src python :tangle arcology/views.py
def site_css(request):
sites = Site.objects.all()
stanzas = []
for site in sites:
for domain in site.sitedomain_set.all():
stanzas.append(f'''
a[href*="//{domain.domain}"] {{
border-radius: 0.25em;
padding: 0.1em;
background-color: {site.link_color}66;
}}
a[href*="//{domain.domain}"]:hover {{
background-color: {site.link_color}FF !important;
}}
''')
stanzas.append(f'''
a[href*="/404"] {{
color: var(--alert);
/* text-decoration: line-through; */
}}
a[href*="/404"]::after {{
content: " ⚠";
}}
a[href*="/404"]::before {{
content: "⚠ ";
}}
''')
return HttpResponse(stanzas, content_type="text/css")
#+end_src
** =app.html= Arcology Site Templates
In short, there are four blocks that the page template and other templates will use to embed content in the rendered web page:
- =title= is the =<title>= element, the name of the tab.
@ -1286,43 +1315,9 @@ There are per-site CSS in [[id:20231229T164611.256424][The Arcology's Site List]
(write-file "~/org/arcology-django/arcology/static/arcology/css/vulf.css"))
#+end_src
** Per-Site link color dynamic CSS endpoint
:PROPERTIES:
:ID: 20231229T215425.830707
:END:
*** NEXT this is a lever for restructuring the arcology
This endpoint generates a dynamic CSS file that colorizes internal URLs based on the [[id:20231229T164611.256424][The Arcology's Site List]] which is stored in the database. It does something [[https://twitter.com/gotMLK7/status/1675994399086641152][extremely wicked]] to make the page links less jarring until you hover over them by faking an alpha-channel in to the color.
#+begin_src python :tangle arcology/views.py
def site_css(request):
sites = Site.objects.all()
stanzas = []
for site in sites:
for domain in site.sitedomain_set.all():
stanzas.append(f'''
a[href*="//{domain.domain}"] {{
border-radius: 0.25em;
padding: 0.1em;
background-color: {site.link_color}66;
}}
a[href*="//{domain.domain}"]:hover {{
background-color: {site.link_color}FF !important;
}}
''')
stanzas.append(f'''
a[href*="/404"] {{
color: var(--alert);
/* text-decoration: line-through; */
}}
a[href*="/404"]::after {{
content: " ⚠";
}}
a[href*="/404"]::before {{
content: "⚠ ";
}}
''')
return HttpResponse(stanzas, content_type="text/css")
#+end_src
=app.html= template would be provided by a configuration-module repo that a user should set up on a template that depends on arroyo, arcology, roam modules. It would be the one responsible for setting up =gunicorn= etc, and also provide the command line wrapper
* NEXT Testing

View File

@ -1,10 +1,10 @@
{# [[file:../../../arcology.org::*Arcology Site Templates][Arcology Site Templates:1]] #}
{# [[file:../../../arcology.org::*=app.html= Arcology Site Templates][=app.html= Arcology Site Templates:1]] #}
<!DOCTYPE html>
<html>
<head>
{# Arcology Site Templates:1 ends here #}
{# =app.html= Arcology Site Templates:1 ends here #}
{# [[file:../../../arcology.org::*Arcology Site Templates][Arcology Site Templates:2]] #}
{# [[file:../../../arcology.org::*=app.html= Arcology Site Templates][=app.html= Arcology Site Templates:2]] #}
{% load static %}
{% load django_htmx %}
<link rel="stylesheet" href="{% static 'arcology/css/app.css' %}"/>
@ -20,9 +20,9 @@
<title>{% block title %}{{head_title | default:"The Arcology Project" }}{% endblock %}</title>
{% block extra_head %}{% endblock %}
</head>
{# Arcology Site Templates:2 ends here #}
{# =app.html= Arcology Site Templates:2 ends here #}
{# [[file:../../../arcology.org::*Arcology Site Templates][Arcology Site Templates:3]] #}
{# [[file:../../../arcology.org::*=app.html= Arcology Site Templates][=app.html= Arcology Site Templates:3]] #}
<body>
<header>
<div class="header-content">
@ -39,15 +39,15 @@
</div>
</div>
</header>
{# Arcology Site Templates:3 ends here #}
{# =app.html= Arcology Site Templates:3 ends here #}
{# [[file:../../../arcology.org::*Arcology Site Templates][Arcology Site Templates:4]] #}
{# [[file:../../../arcology.org::*=app.html= Arcology Site Templates][=app.html= Arcology Site Templates:4]] #}
<div class="content">
{% block content %}{% endblock %}
</div>
{# Arcology Site Templates:4 ends here #}
{# =app.html= Arcology Site Templates:4 ends here #}
{# [[file:../../../arcology.org::*Arcology Site Templates][Arcology Site Templates:5]] #}
{# [[file:../../../arcology.org::*=app.html= Arcology Site Templates][=app.html= Arcology Site Templates:5]] #}
<footer>
<hr/>
&copy; 02024 <a href="https://arcology.garden/people/rrix">Ryan Rix</a> &lt;<a href="mailto:site@whatthefuck.computer">site@whatthefuck.computer</a>&gt;
@ -82,9 +82,9 @@
<a href="https://fediring.net/">Fediring</a>
<a href="https://fediring.net/next?host=arcology.garden">&rarr;</a>
</p>
{# Arcology Site Templates:5 ends here #}
{# =app.html= Arcology Site Templates:5 ends here #}
{# [[file:../../../arcology.org::*Arcology Site Templates][Arcology Site Templates:6]] #}
{# [[file:../../../arcology.org::*=app.html= Arcology Site Templates][=app.html= Arcology Site Templates:6]] #}
<!--
<p>
<input type="checkbox" id="boredom-mode"><label for="boredom-mode">I do not like your aesthetic sensibilities!!</label>
@ -97,4 +97,4 @@
</footer>
</body>
</html>
{# Arcology Site Templates:6 ends here #}
{# =app.html= Arcology Site Templates:6 ends here #}

View File

@ -1,4 +1,4 @@
{# [[file:../../../arcology.org::*=robots.txt= Endpoint][=robots.txt= Endpoint:2]] #}
{# [[file:../../../arcology.org::*=GET /robots.txt= Endpoint][=GET /robots.txt= Endpoint:2]] #}
{% for agent in disallow_all_agents %}
User-agent: {{ agent }}
Disallow: /
@ -8,4 +8,4 @@ User-agent: *
Disallow: /
{% for page in pages %}Allow: {{ page.to_url_path }}
{% endfor %}
{# =robots.txt= Endpoint:2 ends here #}
{# =GET /robots.txt= Endpoint:2 ends here #}

View File

@ -1,6 +1,6 @@
# [[file:../arcology.org::*The Web Server][The Web Server:2]]
import logging
from django.http import HttpResponse, HttpResponseNotFound
from django.http import HttpResponse, HttpResponseNotFound, Http404
from django.shortcuts import render, get_object_or_404
from arcology.models import Page, Feed, Site
@ -14,9 +14,7 @@ logger = logging.getLogger(__name__)
# [[file:../arcology.org::*=GET /= site index][=GET /= site index:1]]
def index(request):
site = Site.from_request(request)
full_key = f"{site.key}/index"
return render_page(request, site, full_key)
# =GET /= site index:1 ends here
@ -94,11 +92,16 @@ def feed(request, key):
# Fetch page metadata
the_feed = get_object_or_404(Feed, route_key=full_key)
entries = the_feed.feedentry_set.order_by("-pubdate").all()[:10]
if len(entries) == 0:
return Http404()
try:
page_author = roam.models.Keyword.objects.get(keyword="AUTHOR", path=the_feed.file).value
except roam.models.Keyword.DoesNotExist:
logger.warn(f"Feed {key} does not have an AUTHOR!")
page_author = "Arcology User"
page_url = the_feed.file.page_set.first().to_url()
updated_at = arrow.get(entries[0].pubdate).format(arrow.FORMAT_RFC3339) # entries is already sorted
@ -135,7 +138,7 @@ def get_item(dictionary, key):
return dictionary.get(key)
# move this function to somewhere else more reasonable:1 ends here
# [[file:../arcology.org::*unpublished/not found endpoint][unpublished/not found endpoint:1]]
# [[file:../arcology.org::*404 unpublished/not found endpoint][404 unpublished/not found endpoint:1]]
def unpublished(request):
key = request.GET.get("key")
if key is None:
@ -149,9 +152,9 @@ def unpublished(request):
return HttpResponseNotFound(
template.render(context, request)
)
# unpublished/not found endpoint:1 ends here
# 404 unpublished/not found endpoint:1 ends here
# [[file:../arcology.org::*=robots.txt= Endpoint][=robots.txt= Endpoint:1]]
# [[file:../arcology.org::*=GET /robots.txt= Endpoint][=GET /robots.txt= Endpoint:1]]
def robots(request):
site = Site.from_request(request)
public_pages = Page.objects \
@ -165,9 +168,9 @@ def robots(request):
disallow_all_agents=["GPTBot", "ChatGPT-User", "Google-Extended", "CCBot", "anthropic-ai"],
pages=public_pages,
), content_type="text/plain")
# =robots.txt= Endpoint:1 ends here
# =GET /robots.txt= Endpoint:1 ends here
# [[file:../arcology.org::*Feed discovery endpoint][Feed discovery endpoint:1]]
# [[file:../arcology.org::*=GET /feeds.json= Feed discovery endpoint][=GET /feeds.json= Feed discovery endpoint:1]]
import json
def feed_list(request):
site = Site.from_request(request)
@ -184,9 +187,9 @@ def feed_list(request):
]
return HttpResponse(json.dumps(ret), content_type="application/json")
# Feed discovery endpoint:1 ends here
# =GET /feeds.json= Feed discovery endpoint:1 ends here
# [[file:../arcology.org::*Per-Site link color dynamic CSS endpoint][Per-Site link color dynamic CSS endpoint:1]]
# [[file:../arcology.org::*=GET /sites.css= Per-Site link color dynamic CSS endpoint][=GET /sites.css= Per-Site link color dynamic CSS endpoint:1]]
def site_css(request):
sites = Site.objects.all()
stanzas = []
@ -215,4 +218,4 @@ def site_css(request):
}}
''')
return HttpResponse(stanzas, content_type="text/css")
# Per-Site link color dynamic CSS endpoint:1 ends here
# =GET /sites.css= Per-Site link color dynamic CSS endpoint:1 ends here

View File

@ -4,7 +4,7 @@
#+TITLE: Arcology Project Configuration
#+filetags: :Project:
#+OPTIONS: ^:nil
#+ARCOLOGY_KEY: arcology/django/configuration
#+ARCOLOGY_KEY: arcology/configuration
,#+AUTO_TANGLE: vars:org-babel-default-header-args
#+ARROYO_NIXOS_MODULE: nixos/arcology2.nix