Older and Newer buttons for history navigation instead of list

This commit is contained in:
Matthias Portzel 2023-03-03 21:47:30 -05:00
parent 0ab37f6298
commit 8b9bb999a7
4 changed files with 83 additions and 74 deletions

View File

@ -37,7 +37,7 @@ def season_year_for_date(date):
def formatted_name_for_season_year(current_season, current_year): def formatted_name_for_season_year(current_season, current_year):
return str(current_year) + " - " + ["Winter", "Spring", "Summer", "Fall"][current_season] return ["Winter", "Spring", "Summer", "Fall"][current_season] + " " + str(current_year)
def get_page_slug(thought): def get_page_slug(thought):
@ -101,31 +101,3 @@ def get_all_pages():
# .formatted_name # .formatted_name
# .get_all_entries # .get_all_entries
# return [Pages] # return [Pages]
def get_page(requested_slug, highlighted_uuid=None):
pages = get_all_pages()
# show=uuid takes priority over page
if highlighted_uuid:
try:
highlighted_thought = Thought.objects.get(uuid=highlighted_uuid)
requested_slug = get_page_slug(highlighted_thought)
except Thought.DoesNotExist:
pass
# When we get here, either:
# no slug was passed, requested_slug is ""
# a valid highlighted_uuid was passed, requested_slug is the slug of that page
# requested_slug is an invalid slug
# requested_slug is a valid slug
# First item in pages should be listed first
requested_page = pages[0]
for p in pages:
if p.slug == requested_slug:
requested_page = p
return requested_page

View File

@ -240,25 +240,19 @@ h1 {
} }
.history-nav { .history-nav {
font-size: 1.1em;
margin-top: 30px; margin-top: 30px;
margin-bottom: 40px; margin-bottom: 40px;
margin-left: 20px; display: flex; /* Mostly just removes the horizontal space from whitespace */
}
.history-nav ul {
margin: 0;
padding: 0;
list-style: none;
} }
.history-nav li { .history-nav .nav-item:not(:last-child)::after {
line-height: 1.3; content: "•";
} margin-left: 0.7em;
.history-nav li::before { margin-right: 0.7em;
content: "➤"; text-decoration: none !important;
}
.history-nav li > * {
margin-left: 10px;
} }
.history-nav .current-page { .history-nav .current-page {
font-weight: bold; font-weight: bold;
} }

View File

@ -12,7 +12,7 @@
{% block head %} {% block head %}
{% if not first_page %} {% if not first_page %}
<link rel="canonical" href="/?page={{ current_page_slug }}"> <link rel="canonical" href="/?page={{ page.slug }}">
{% else %} {% else %}
<link rel="canonical" href="/"> <link rel="canonical" href="/">
{% endif %} {% endif %}
@ -41,20 +41,19 @@
{% endblock %} {% endblock %}
{% block main %} {% block main %}
{% if not first_page %} <nav class="history-nav top" aria-label="History Navigation">
<nav class="history-nav top" aria-label="History Navigation"> {% if not is_first_page %}
<ul> <span class="nav-item"><a href="?page={{ previous_page_slug }}">Newer</a></span>
{% for page in pages %} {% endif %}
{% if page.slug == current_page_slug %}
<li><span class="current-page">{{ page.formatted_name }}</span></li> <span class="nav-item"><span class="current-page">{{ page.formatted_name }}</span></span>
{% else %}
<li><a href="?page={{ page.slug }}">{{ page.formatted_name }}</a></li> {% if not is_last_page %}
{% endif %} <span class="nav-item"><a href="?page={{ next_page_slug }}">Older</a></span>
{% endfor %} {% endif %}
<li><a href="/search">Search</a></li>
</ul> <span class="nav-item"><a href="/search">Search</a></span>
</nav> </nav>
{% endif %}
{% for thought in thoughts %} {% for thought in thoughts %}
<div class="thought{% if thought.uuid == highlighted %} highlighted{% endif %}" id="{{ thought.uuid }}"> <div class="thought{% if thought.uuid == highlighted %} highlighted{% endif %}" id="{{ thought.uuid }}">
@ -71,16 +70,17 @@
{% endfor %} {% endfor %}
<nav class="history-nav bottom" aria-label="History Navigation"> <nav class="history-nav bottom" aria-label="History Navigation">
<ul> {% if not is_first_page %}
{% for page in pages %} <a class="nav-item" href="?page={{ previous_page_slug }}">Older</a>
{% if page.slug == current_page_slug %} {% endif %}
<li><span class="current-page">{{ page.formatted_name }}</span></li>
{% else %} <span class="current-page nav-item"><span>{{ page.formatted_name }}</span></span>
<li><a href="?page={{ page.slug }}">{{ page.formatted_name }}</a></li>
{% endif %} {% if not is_last_page %}
{% endfor %} <a class="nav-item" href="?page={{ previous_page_slug }}">Older</a>
<li><a href="/search">Search</a></li> {% endif %}
</ul>
<a class="nav-item" href="/search">Search</a>
</nav> </nav>
{% endblock %} {% endblock %}

View File

@ -2,6 +2,8 @@ import os.path
import uuid import uuid
import subprocess import subprocess
import base64 import base64
import collections
from itertools import islice
import magic import magic
@ -15,7 +17,22 @@ from haystack.forms import SearchForm
from whispermaphone import settings from whispermaphone import settings
from .models import Thought, ThoughtForm, ALLOWED_MEDIA_TYPES from .models import Thought, ThoughtForm, ALLOWED_MEDIA_TYPES
from .pagination import get_all_pages, get_page_slug, get_page from .pagination import get_all_pages, get_page_slug
# Python's itertools standard library is bad
# Instead of providing functions
# They provide "receipes" that you can copy-paste into your own program
# => https://docs.python.org/3/library/itertools.html#itertools-recipes
def sliding_window(iterable, n):
# sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
it = iter(iterable)
window = collections.deque(islice(it, n), maxlen=n)
if len(window) == n:
yield tuple(window)
for x in it:
window.append(x)
yield tuple(window)
def check_authenticated(request): def check_authenticated(request):
authenticated = False authenticated = False
@ -39,17 +56,43 @@ def index(request):
pages = get_all_pages() pages = get_all_pages()
requested_slug = request.GET.get("page", default="") requested_slug = request.GET.get("page", default="")
requested_page = get_page(requested_slug, highlighted_uuid)
thoughts = requested_page.get_all_entries() # If we've passed a valid highlighted thought uuid,
# that takes priority over a page= value, so we overwrite requested_slug
if highlighted_uuid:
try:
requested_slug = get_page_slug(Thought.objects.get(uuid=highlighted_uuid))
except Thought.DoesNotExist:
pass
# When we get here, either:
# no slug was passed, requested_slug is ""
# a valid highlighted_uuid was passed, requested_slug is the slug of that page
# requested_slug is an invalid slug
# requested_slug is a valid slug
# First item in pages should be the default
previous_page, current_page, next_page = None, pages[0], pages[1]
# We don't have any way of validating slugs or anything,
# so we just have to loop though and see if the requested slug matches any pages
for (prev, curr, nex) in sliding_window(pages, 3):
if curr.slug == requested_slug:
previous_page, current_page, next_page = prev, curr, nex
# If you requested the last page, then this runs on the last iteration
# It runs right before every matching slug, but it only matters if it's the last iteration
if nex.slug == requested_slug:
previous_page, current_page, next_page = curr, nex, None
thoughts = current_page.get_all_entries()
return render(request, "thoughts/index.html", { return render(request, "thoughts/index.html", {
"thoughts": thoughts, "thoughts": thoughts,
"highlighted": highlighted_uuid, "highlighted": highlighted_uuid,
"authenticated": authenticated, "authenticated": authenticated,
"pages": pages, "page": current_page,
"current_page_slug": requested_page.slug, "previous_page_slug": getattr(previous_page, "slug", None),
"first_page": requested_page.slug == pages[0].slug # if you're viewing the first page "next_page_slug": getattr(next_page, "slug", None),
"is_first_page": current_page.slug == pages[0].slug, # if you're viewing the first page
"is_last_page": current_page.slug == pages[-1].slug
}) })