Skip to content

Commit 8eb4dc9

Browse files
committed
Timeline: Migrate to Markdown source files - initial implementation
- The timeline app is introduced, moved from the home app. - Add a basic README.md to illustrate the overall code breakdown of the app as it is in the current stage. - Two entries are added for now. - Add ability to link headers using the slug portion of the filename. - The way markdown files are fetched is similar to that of the resources app - using the AppConfig ready() function, all resources are ensured to be only fetched once when the app is first laoded. I debated whether to introduce the new functionality in the home app instead, without creating a new app. Eventually I decided extracting it to a standalone app now is better as it allows easier extension of functionality in the future. The home app can remain as it is to only server the `/` homepage. The timeline CSS is kept the same, as with the structure of the timeline HTML template. Once the CSS rewrite PR is merged, it's relatively easy to fix conflicts here (again, since timeline is now its own app, with the CSS file and HTML template moved - extra advantage). References to `home:timeline` are updated to use `timeline:index` throughout the codebase, as far as my ripgrep search could go. The format of the markdown + YAML entries are still up for debate, so I've only added the first two entries for now. They can be completely overwritten in the future once the formats are decided by using a script to convert all the data from my JSON file into individual markdown files: http://0x0.st/Xr78.txt This link should last for at least a few months. (Originally saved on https://paste.pythondiscord.com/KPJA, but it expires on 12th April 2024.)
1 parent ba6aec1 commit 8eb4dc9

File tree

16 files changed

+4016
-11
lines changed

16 files changed

+4016
-11
lines changed

pydis_site/apps/home/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# The "home" app
22

33
This Django application takes care of serving the homepage of our website, that
4-
is, the first page that you see when you open pythondiscord.com. It also
5-
manages the timeline page showcasing the history of our community.
4+
is, the first page that you see when you open pythondiscord.com.
65

76
## Directory structure
87

pydis_site/apps/home/urls.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from django_distill import distill_path
22

3-
from .views import HomeView, timeline
3+
from .views import HomeView
44

55
app_name = 'home'
66
urlpatterns = [
77
distill_path('', HomeView.as_view(), name='home'),
8-
distill_path('timeline/', timeline, name="timeline"),
98
]

pydis_site/apps/home/views.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,3 @@ def get(self, request: WSGIRequest) -> HttpResponse:
153153
"""Collect repo data and render the homepage view."""
154154
repo_data = self._get_repo_data()
155155
return render(request, "home/index.html", {"repo_data": repo_data})
156-
157-
158-
def timeline(request: WSGIRequest) -> HttpResponse:
159-
"""Render timeline view."""
160-
return render(request, 'home/timeline.html')

pydis_site/apps/timeline/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# The "timeline" app
2+
3+
The [timeline page](https://www.pythondiscord.com/timeline/) on our website is
4+
powered by this Django application.
5+
6+
## The entries
7+
8+
Timeline entries are written in markdown files with YAML frontmatter under the
9+
`entries` directory.
10+
11+
Each file represents a timeline entry. The files are named with the format
12+
`<date>_<name>.md`:
13+
- `date`: The date is in the `YYYY-MM-DD` format, intended for easy sorting in
14+
editor/shell command directory listings. It's also used to sort the entries
15+
before rendering the timeline page.
16+
- `name`: The name component is an arbitrary slug in **kebab-case**. This is used
17+
for linking to individual timeline entries on the page, and will be set in
18+
the `id` attribute.
19+
20+
Each file contains:
21+
- YAML frontmatter. This defines some metadata shown next to each entry in
22+
the timeline, including:
23+
- Date: User-facing date label.
24+
- Icon: The CSS class to be used for the icon. Set to `pydis` to use the
25+
pydis logo image.
26+
- Icon color: The CSS class that sets the background color of the icon. Leave
27+
empty if the pydis logo is used.
28+
- Markdown content.
29+
30+
31+
## Directory structure
32+
33+
The app has a single view in `views.py` that takes care of reading the `.md`
34+
files in the `entires` directory. This is a standard Django view, mounted in
35+
`urls.py` as usual.
36+
37+
The `tests` directory validates that our redirects and helper functions work as
38+
expected. If you made changes to the app and are looking for guidance on adding
39+
new tests, the [Django tutorial introducing automated
40+
testing](https://docs.djangoproject.com/en/dev/intro/tutorial05/) is a good
41+
place to start.
42+
43+
This application does not use the database and as such does not have models nor
44+
migrations.

pydis_site/apps/timeline/__init__.py

Whitespace-only changes.

pydis_site/apps/timeline/apps.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from pathlib import Path
2+
3+
from django.apps import AppConfig
4+
import frontmatter
5+
import markdown
6+
7+
from pydis_site import settings
8+
9+
10+
ENTRIES_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "timeline", "entries")
11+
12+
13+
class TimelineConfig(AppConfig):
14+
"""AppConfig instance for Timeline app."""
15+
16+
name = 'pydis_site.apps.timeline'
17+
18+
def ready(self) -> None:
19+
"""Fetch all the timeline entries."""
20+
self.entries = []
21+
22+
for path in ENTRIES_PATH.rglob("*.md"):
23+
metadata, content = frontmatter.parse(path.read_text(encoding="utf-8"))
24+
25+
md = markdown.Markdown()
26+
html = str(md.convert(content))
27+
28+
# Strip `.md` file extension from filename and split it into the
29+
# date (for sorting) and slug (for linking).
30+
key, slug = path.name[:-3].split("_")
31+
entry = {
32+
"key": key,
33+
"slug": slug,
34+
"title": metadata["title"],
35+
"date": metadata["date"],
36+
"icon": metadata["icon"],
37+
# This key might not be used if the icon uses the pydis logo.
38+
"icon_color": metadata.get("icon_color"),
39+
"content": html,
40+
}
41+
42+
self.entries.append(entry)
43+
44+
# Sort the entries in reverse-chronological order.
45+
self.entries.sort(key=lambda e: e['key'], reverse=True)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Retirement of Joe and Sebastiaan
3+
date: 2023-01-30
4+
icon: pydis
5+
---
6+
7+
Having been at the helm of Python Discord for over 5 and 3 years respectively,
8+
Joe and Sebastiaan retire and step down. They gain the **@Founders** role and
9+
continue as advisors to the **@Directors**, the new name of the original
10+
**@Owners** role.
11+
12+
At the same time, Mina and Zig join Leon as co-directors.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Switch to new paste service
3+
date: 2023-07-11
4+
icon: fa-regular fa-clipboard
5+
icon_color: pastel-pink
6+
---
7+
8+
We migrate over to [pinnwand](https://github.com/supakeen/pinnwand) as the
9+
service that powers our paste bin over at <https://paste.pythondiscord.com/>.
10+
We made the switch as it comes with native light/dark modes, support for
11+
multi-file pastes, additional support for text highlighting languages, and
12+
plus, it's written in Python!

pydis_site/apps/timeline/urls.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django_distill import distill_path
2+
3+
from .views import TimelineView
4+
5+
app_name = "timeline"
6+
7+
urlpatterns = [
8+
distill_path("", TimelineView.as_view(), name="index"),
9+
]

pydis_site/apps/timeline/views.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from django.apps import apps
2+
from django.core.handlers.wsgi import WSGIRequest
3+
from django.http import HttpResponse
4+
from django.shortcuts import render
5+
from django.views import View
6+
7+
APP_NAME = "timeline"
8+
9+
class TimelineView(View):
10+
"""A vertical timeline showcasing milestones in the history of Python Discord."""
11+
12+
def get(self, request: WSGIRequest) -> HttpResponse:
13+
"""Render the timeline."""
14+
app = apps.get_app_config(APP_NAME)
15+
16+
return render(
17+
request,
18+
template_name="timeline/timeline.html",
19+
context={ "entries": app.entries },
20+
)

0 commit comments

Comments
 (0)