Skip to content

Commit

Permalink
Refactor query string manipulation for blog dates
Browse files Browse the repository at this point in the history
  • Loading branch information
ahosgood committed Nov 15, 2024
1 parent 53cd7ef commit f90e1cc
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 63 deletions.
4 changes: 4 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
parse_json,
pretty_date,
pretty_date_with_day,
qs_active,
qs_toggler,
rfc_822_format,
seconds_to_time,
sidebar_items_from_wagtail_body,
Expand Down Expand Up @@ -156,6 +158,8 @@ def apply_extra_headers(response):
app.add_template_filter(parse_json)
app.add_template_filter(pretty_date)
app.add_template_filter(pretty_date_with_day)
app.add_template_filter(qs_active)
app.add_template_filter(qs_toggler)
app.add_template_filter(rfc_822_format)
app.add_template_filter(seconds_to_time)
app.add_template_filter(sidebar_items_from_wagtail_body)
Expand Down
32 changes: 29 additions & 3 deletions app/lib/template_filters.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import json
import math
import re
import urllib.parse
from datetime import datetime
from urllib.parse import unquote, urlencode, urlparse

from markupsafe import Markup

Expand Down Expand Up @@ -44,7 +44,7 @@ def seconds_to_time(s):

def get_url_domain(s):
try:
domain = urllib.parse.urlparse(s).netloc
domain = urlparse(s).netloc
domain = re.sub(r"^www\.", "", domain)
return domain
except Exception:
Expand Down Expand Up @@ -166,7 +166,7 @@ def group_headings(index, grouping):

def parse_json(s):
try:
unquoted_string = urllib.parse.unquote(s)
unquoted_string = unquote(s)
return json.loads(unquoted_string)
except Exception:
return {}
Expand Down Expand Up @@ -310,3 +310,29 @@ def wagtail_cell_alignment_parser(classes, cell_alignment_regex):
else:
data["body"].append(row_data)
return data


def qs_active(existing_qs, filter, by):
"""Active when identical key/value in existing query string."""
qs_set = {(filter, str(by))}
# Not active if either are empty.
if not existing_qs or not qs_set:
return False
# See if the intersection of sets is the same.
existing_qs_set = set(existing_qs.items())
return existing_qs_set.intersection(qs_set) == qs_set


def qs_toggler(existing_qs, filter, by):
"""Resolve filter against an existing query string."""
qs = {filter: by}
# Don't change the currently rendering existing query string!
rtn_qs = existing_qs.copy()
# Test for identical key and value in existing query string.
if qs_active(existing_qs, filter, by):
# Remove so that buttons toggle their own value on and off.
rtn_qs.pop(filter)
else:
# Update or add the query string.
rtn_qs.update(qs)
return urlencode(rtn_qs)
72 changes: 42 additions & 30 deletions app/wagtail/pages/blog_index_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import math

from app.lib.pagination import pagination_object
from app.lib.template_filters import qs_active, qs_toggler
from app.wagtail.api import (
blog_authors,
blog_post_counts,
Expand Down Expand Up @@ -67,6 +68,7 @@ def blog_index_page(page_data, year=None, month=None, day=None):
pages = math.ceil(total_blog_posts / children_per_page)
if page > pages:
return render_template("errors/page-not-found.html"), 404
existing_qs_as_dict = request.args.to_dict()
date_filters = [
{
"label": "Any date",
Expand All @@ -75,40 +77,50 @@ def blog_index_page(page_data, year=None, month=None, day=None):
"selected": not year,
}
]
if year:
for year_count in reversed(blog_post_counts_data):
if year_count["year"] == year:
for year_count in reversed(blog_post_counts_data):
date_filters.append(
{
"label": f"All {year_count['year']} ({year_count['posts']})",
"href": "?"
+ (
qs_toggler(existing_qs_as_dict, "month", month)
if year == year_count["year"] and month
else f"year={year_count['year']}"
),
"title": f"Blog posts from {year_count['year']}",
"selected": qs_active(
existing_qs_as_dict, "year", year_count["year"]
)
and not month,
}
)
if year == year_count["year"]:
for month_count in reversed(year_count["months"]):
each_month_name = datetime.date(
year, month_count["month"], 1
).strftime("%B")
date_filters.append(
{
"label": f"All {year_count['year']} ({year_count['posts']})",
"href": f"?year={year_count['year']}",
"title": f"Blog posts from {year_count['year']}",
"selected": not month,
"label": f"{each_month_name} {year_count['year']} ({month_count['posts']})",
"href": "?"
+ (
f"year={year_count['year']}&month={month_count['month']}"
if month == month_count["month"]
else qs_toggler(
existing_qs_as_dict,
"month",
month_count["month"],
)
),
"title": f"Blog posts from {each_month_name} {year_count['year']}",
"selected": qs_active(
existing_qs_as_dict, "year", year_count["year"]
)
and qs_active(
existing_qs_as_dict, "month", month_count["month"]
),
}
)
for month_count in reversed(year_count["months"]):
each_month_name = datetime.date(
year, month_count["month"], 1
).strftime("%B")
date_filters.append(
{
"label": f"{each_month_name} {year_count['year']} ({month_count['posts']})",
"href": f"?year={year_count['year']}&month={month_count['month']}",
"title": f"Blog posts from {each_month_name} {year_count['year']}",
"selected": year == year_count["year"]
and month == month_count["month"],
}
)
else:
for year_count in reversed(blog_post_counts_data):
date_filters.append(
{
"label": f"{year_count['year']} ({year_count['posts']})",
"href": f"?year={year_count['year']}",
"title": f"Blog posts from {year_count['year']}",
"selected": False,
}
)
return render_template(
"blog/index.html",
breadcrumbs=breadcrumbs(page_data["id"]),
Expand Down
72 changes: 42 additions & 30 deletions app/wagtail/pages/blog_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import math

from app.lib.pagination import pagination_object
from app.lib.template_filters import qs_active, qs_toggler
from app.wagtail.api import (
blog_authors,
blog_post_counts,
Expand Down Expand Up @@ -73,6 +74,7 @@ def blog_page(page_data, year=None, month=None, day=None):
pages = math.ceil(total_blog_posts / children_per_page)
if page > pages:
return render_template("errors/page-not-found.html"), 404
existing_qs_as_dict = request.args.to_dict()
date_filters = [
{
"label": "Any date",
Expand All @@ -81,40 +83,50 @@ def blog_page(page_data, year=None, month=None, day=None):
"selected": not year,
}
]
if year:
for year_count in reversed(blog_post_counts_data):
if year_count["year"] == year:
for year_count in reversed(blog_post_counts_data):
date_filters.append(
{
"label": f"All {year_count['year']} ({year_count['posts']})",
"href": "?"
+ (
qs_toggler(existing_qs_as_dict, "month", month)
if year == year_count["year"] and month
else f"year={year_count['year']}"
),
"title": f"Blog posts from {year_count['year']}",
"selected": qs_active(
existing_qs_as_dict, "year", year_count["year"]
)
and not month,
}
)
if year == year_count["year"]:
for month_count in reversed(year_count["months"]):
each_month_name = datetime.date(
year, month_count["month"], 1
).strftime("%B")
date_filters.append(
{
"label": f"All {year_count['year']} ({year_count['posts']})",
"href": f"?year={year_count['year']}",
"title": f"Blog posts from {year_count['year']}",
"selected": not month,
"label": f"{each_month_name} {year_count['year']} ({month_count['posts']})",
"href": "?"
+ (
f"year={year_count['year']}&month={month_count['month']}"
if month == month_count["month"]
else qs_toggler(
existing_qs_as_dict,
"month",
month_count["month"],
)
),
"title": f"Blog posts from {each_month_name} {year_count['year']}",
"selected": qs_active(
existing_qs_as_dict, "year", year_count["year"]
)
and qs_active(
existing_qs_as_dict, "month", month_count["month"]
),
}
)
for month_count in reversed(year_count["months"]):
each_month_name = datetime.date(
year, month_count["month"], 1
).strftime("%B")
date_filters.append(
{
"label": f"{each_month_name} {year_count['year']} ({month_count['posts']})",
"href": f"?year={year_count['year']}&month={month_count['month']}",
"title": f"Blog posts from {each_month_name} {year_count['year']}",
"selected": year == year_count["year"]
and month == month_count["month"],
}
)
else:
for year_count in reversed(blog_post_counts_data):
date_filters.append(
{
"label": f"{year_count['year']} ({year_count['posts']})",
"href": f"?year={year_count['year']}",
"title": f"Blog posts from {year_count['year']}",
"selected": False,
}
)
return render_template(
"blog/index.html",
breadcrumbs=breadcrumbs(page_data["id"]),
Expand Down
28 changes: 28 additions & 0 deletions test/lib/test_template_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import unittest

from app.lib.template_filters import qs_active, qs_toggler


class ContentParserTestCase(unittest.TestCase):
def test_jinja_filters_qs_toggler(self):
TEST_QS = {"a": "1", "b": "2"}
# Adds a new qs
self.assertEqual("a=1&b=2&c=3", qs_toggler(TEST_QS.copy(), "c", "3"))
# Changes an existing qs
self.assertEqual("a=1&b=1", qs_toggler(TEST_QS.copy(), "b", "1"))
# Removes a qs of the same value.
self.assertEqual("b=2", qs_toggler(TEST_QS.copy(), "a", "1"))
# Handle empty existing qs
self.assertEqual("a=1", qs_toggler({}, "a", "1"))

def test_jinja_filters_qs_active(self):
TEST_QS = {"a": "1", "b": "2"}
self.assertTrue(qs_active(TEST_QS, "a", "1"))
self.assertTrue(qs_active(TEST_QS, "b", "2"))
self.assertFalse(qs_active(TEST_QS, "a", "2"))
self.assertFalse(qs_active(TEST_QS, "b", "1"))
self.assertFalse(qs_active(TEST_QS, "c", "3"))
# Handles empty query strings
self.assertFalse(qs_active({}, "a", "1"))
self.assertFalse(qs_active({}, "", ""))
self.assertFalse(qs_active({"a": "1"}, "", ""))

0 comments on commit f90e1cc

Please sign in to comment.