Skip to content

Commit 9ac31dd

Browse files
authored
📆 Add iCal schedule export feature (#127) (#140)
- Create schedule-ical.html template to generate .ics calendar file - Include all talks with proper timezone handling - Add "Add to Calendar" button to schedule page - Calendar includes event details: time, location, presenter, description Closes #127
1 parent 098ca0d commit 9ac31dd

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

src/schedule-ical.html

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
permalink: /schedule.ics
3+
eleventyExcludeFromCollections: true
4+
---
5+
BEGIN:VCALENDAR
6+
VERSION:2.0
7+
PRODID:-//DjangoCon US {{ site.conf_year }}//Schedule//EN
8+
CALSCALE:GREGORIAN
9+
METHOD:PUBLISH
10+
X-WR-CALNAME:DjangoCon US {{ site.conf_year }}
11+
X-WR-TIMEZONE:{{ site.timezone }}
12+
X-WR-CALDESC:DjangoCon US {{ site.conf_year }} Conference Schedule
13+
BEGIN:VTIMEZONE
14+
TZID:{{ site.timezone }}
15+
BEGIN:DAYLIGHT
16+
TZOFFSETFROM:-0600
17+
TZOFFSETTO:-0500
18+
TZNAME:CDT
19+
DTSTART:19700308T020000
20+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
21+
END:DAYLIGHT
22+
BEGIN:STANDARD
23+
TZOFFSETFROM:-0500
24+
TZOFFSETTO:-0600
25+
TZNAME:CST
26+
DTSTART:19701101T020000
27+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
28+
END:STANDARD
29+
END:VTIMEZONE
30+
{%- for talk in collections.talks %}
31+
BEGIN:VEVENT
32+
DTSTART;TZID={{ site.timezone }}:{{ talk.data.start_datetime | formatDateTime: "yyyyMMdd'T'HHmmss" }}
33+
DTEND;TZID={{ site.timezone }}:{{ talk.data.end_datetime | formatDateTime: "yyyyMMdd'T'HHmmss" }}
34+
DTSTAMP:{{ talk.data.start_datetime | formatDateTime: "yyyyMMdd'T'HHmmss'Z'" }}
35+
UID:{{ talk.fileSlug }}@{{ site.domain }}
36+
SUMMARY:{{ talk.data.title | replace: ",", "\," | replace: ";", "\;" | replace: "\n", " " | replace: "\r", " " }}
37+
{%- if talk.data.room %}
38+
LOCATION:{{ talk.data.room | replace: ",", "\," | replace: ";", "\;" }}
39+
{%- endif %}
40+
{%- if talk.data.presenter_slugs or talk.templateContent %}
41+
DESCRIPTION:
42+
{%- if talk.data.presenter_slugs -%}
43+
{%- for slug in talk.data.presenter_slugs -%}
44+
{%- assign presenter = collections.presenters | find: slug -%}
45+
{%- if presenter %}Presenter: {{ presenter.data.name }}\n{% endif -%}
46+
{%- endfor -%}
47+
{%- if talk.templateContent %}\n{% endif -%}
48+
{%- endif -%}
49+
{%- if talk.templateContent -%}
50+
{{ talk.templateContent | strip_html | replace: "\n", "\n " | replace: ",", "\," | replace: ";", "\;" | truncate: 1000 }}
51+
{%- endif %}
52+
{%- endif %}
53+
{%- if talk.data.permalink %}
54+
URL:{{ site.domain }}{{ talk.data.permalink }}
55+
{%- endif %}
56+
STATUS:CONFIRMED
57+
END:VEVENT
58+
{%- endfor %}
59+
END:VCALENDAR

src/schedule.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ <h1 class="text-center pageheading">{{ title }}</h1>
2323

2424
<div class="pt-6 block-container">
2525
<div class="wrapper">
26+
<div class="max-w-5xl mx-auto mb-8 text-center">
27+
<a href="/schedule.ics" class="inline-flex items-center gap-2 px-6 py-3 text-lg font-medium text-white bg-teal hover:bg-teal-dark rounded-lg transition-colors" download>
28+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
29+
Add to Calendar
30+
</a>
31+
</div>
2632
<nav class="max-w-5xl mx-auto mb-12">
2733
<h2 class="mb-1 font-bold uppercase sr-only">Jump to day</h2>
2834
<ul class="flex flex-wrap justify-center gap-6">

0 commit comments

Comments
 (0)