Attempt a shortcode for the schedule overview #65
24 changed files with 570 additions and 148 deletions
commit
c0dfc9131d
21
README.md
21
README.md
|
|
@ -24,4 +24,23 @@ Use the `lang` shortcode to mark whether a tour is in German, English or bilingu
|
|||
- English: `{{< lang en >}}`
|
||||
- Bilingual: `{{< lang deen >}}`
|
||||
|
||||
For usage references check the [German](/content/de/39c3/_index.md) and [English](/content/en/39c3/_index.md) tour overview.
|
||||
## Shortcode: Tour schedule
|
||||
|
||||
The tour overview of an event (`content/*/<event>/_index.md`) shows the schedule with `{{< schedule >}}`. It reads `data/schedule/<event>.yaml`, which is shared by both languages:
|
||||
|
||||
```yaml
|
||||
days:
|
||||
- day: 1
|
||||
date: "2025-12-27"
|
||||
tours:
|
||||
- { time: "11:30", tour: xfel, lang: deen }
|
||||
- { time: "12:00", tour: city-walk, lang: de }
|
||||
```
|
||||
|
||||
- `tour` is the slug of the tour page in the event section. The card shows that page's title, without the event prefix, and links to it.
|
||||
- `lang` is `de`, `en` or `deen`, or a list of these. It renders the same badge as the `lang` shortcode.
|
||||
- `time` is `HH:MM` with a leading zero (`09:30`). Tours are sorted by time, so their order in the file doesn't matter.
|
||||
|
||||
Wide screens get one column per day on an hour grid, with tours that start at the same time side by side. The first column shows the hour wherever the first day has no tour in it. On narrow screens a day picker shows one day at a time, starting with today's day during the event.
|
||||
|
||||
For a different event than the page's section, pass its name: `{{< schedule 39c3 >}}`.
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
@import './_schedule.css';
|
||||
|
||||
.header__intro_headline {
|
||||
font: bold var(--fs-xxl) "Arial";
|
||||
padding-bottom: 10px;
|
||||
|
|
|
|||
239
assets/css/_schedule.css
Normal file
239
assets/css/_schedule.css
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
/* Tour schedule shortcode: one column of cards per day, a day picker on narrow screens. */
|
||||
|
||||
.schedule {
|
||||
--schedule-line: color-mix(in oklch, var(--color-text) 20%, transparent);
|
||||
--schedule-card-bg: color-mix(in oklch, var(--color-text) 4%, transparent);
|
||||
--schedule-accent: var(--color-link);
|
||||
|
||||
container-type: inline-size;
|
||||
margin-block: var(--spacing-l);
|
||||
}
|
||||
|
||||
.schedule__days {
|
||||
display: grid;
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
|
||||
/* Hour lines are only drawn in the aligned grid below. */
|
||||
.schedule__hour {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* One column per day; the shortcode puts each card in the row of its start time
|
||||
(--schedule-row), and the subgrids line those rows up across the days. */
|
||||
@container (width >= 48rem) {
|
||||
.schedule__days {
|
||||
grid-template-columns: repeat(var(--schedule-days), minmax(0, 1fr));
|
||||
grid-template-rows: auto repeat(var(--schedule-rows), auto);
|
||||
gap: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
/* Placed explicitly: auto-placement would move the days out of the way of the hour lines. */
|
||||
.schedule__day {
|
||||
display: grid;
|
||||
grid-column: var(--schedule-column);
|
||||
grid-row: 1 / -1;
|
||||
grid-template-rows: subgrid;
|
||||
}
|
||||
|
||||
.schedule__list {
|
||||
grid-row: 2 / -1;
|
||||
grid-template-rows: subgrid;
|
||||
}
|
||||
|
||||
.schedule__card {
|
||||
grid-row: var(--schedule-row);
|
||||
}
|
||||
|
||||
/* Titles always take two lines, so all cards in the grid are the same size; longer
|
||||
titles get an ellipsis. */
|
||||
.schedule__title {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
overflow: hidden;
|
||||
min-height: calc(2 * 1.3em);
|
||||
}
|
||||
|
||||
/* Line above each hour, drawn in the middle of the row gap. Spans all days, so it must
|
||||
not catch clicks meant for the cards. */
|
||||
.schedule__hour {
|
||||
display: block;
|
||||
grid-column: 1 / -1;
|
||||
grid-row: var(--schedule-row);
|
||||
margin-block-start: -0.25rem;
|
||||
border-block-start: 1px solid var(--schedule-line);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lined up with the time on the cards. */
|
||||
.schedule__hour-label {
|
||||
display: block;
|
||||
padding: calc(0.5rem + 0.25rem) 0.75rem 0.5rem calc(0.75rem + 3px);
|
||||
font-family: var(--ff-alt);
|
||||
font-size: var(--fs-s);
|
||||
font-weight: bold;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--color-text-meta);
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.schedule__day-title {
|
||||
margin: 0 0 0.75rem;
|
||||
padding-block-end: 0.35rem;
|
||||
border-block-end: 2px solid var(--schedule-accent);
|
||||
font-size: var(--fs-l);
|
||||
}
|
||||
|
||||
.schedule__date {
|
||||
font-family: var(--ff-alt);
|
||||
font-size: var(--fs-s);
|
||||
font-weight: normal;
|
||||
color: var(--color-text-meta);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.schedule__list {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.schedule__card {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 0.15rem 0.5rem;
|
||||
margin: 0;
|
||||
padding: 0.5rem 0.75rem 0.6rem;
|
||||
border: 1px solid var(--schedule-line);
|
||||
border-inline-start: 3px solid var(--schedule-accent);
|
||||
border-radius: var(--radius-m);
|
||||
background: var(--schedule-card-bg);
|
||||
transition: border-color 0.15s;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--schedule-accent);
|
||||
}
|
||||
|
||||
&:has(a:focus-visible) {
|
||||
outline: 2px solid var(--schedule-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.schedule__time {
|
||||
font-family: var(--ff-alt);
|
||||
font-size: var(--fs-s);
|
||||
font-weight: bold;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--color-text-meta);
|
||||
}
|
||||
|
||||
.schedule__langs {
|
||||
/* Above the card-wide link, so the badge tooltip still works. */
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.schedule__lang {
|
||||
padding: 0 0.4rem;
|
||||
border: 1px solid var(--schedule-line);
|
||||
border-radius: 999px;
|
||||
font-family: var(--ff-alt);
|
||||
font-size: var(--fs-xs);
|
||||
letter-spacing: 0.03em;
|
||||
text-decoration: none;
|
||||
color: var(--color-text-meta);
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.schedule__title {
|
||||
grid-column: 1 / -1;
|
||||
font-family: var(--ff-headings);
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
text-decoration: none;
|
||||
|
||||
/* Make the whole card clickable. Being absolutely positioned against the card, it is not
|
||||
clipped by the overflow set in the grid view. */
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
/* The picker only exists with JavaScript and is only used on narrow screens. */
|
||||
.schedule__picker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@container (width < 48rem) {
|
||||
.schedule__picker:not([hidden]) {
|
||||
position: sticky;
|
||||
inset-block-start: 0;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
margin-block-end: 1rem;
|
||||
padding: 0.25rem;
|
||||
border-radius: var(--radius-l);
|
||||
background: var(--color-body-bg);
|
||||
box-shadow: inset 0 0 0 1px var(--schedule-line);
|
||||
}
|
||||
|
||||
.schedule__pick {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0.35rem 0.25rem;
|
||||
border: 0;
|
||||
border-radius: var(--radius-m);
|
||||
background: transparent;
|
||||
color: var(--color-text);
|
||||
font-family: var(--ff-alt);
|
||||
font-size: var(--fs-s);
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
|
||||
&[aria-pressed="true"] {
|
||||
background: var(--schedule-accent);
|
||||
color: var(--color-body-bg);
|
||||
|
||||
.schedule__pick-date {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.schedule__pick-date {
|
||||
font-size: var(--fs-xs);
|
||||
font-weight: normal;
|
||||
color: var(--color-text-meta);
|
||||
}
|
||||
|
||||
.schedule--picker {
|
||||
.schedule__day:not(.schedule__day--selected) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The picker already names the day. */
|
||||
.schedule__day-title {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip-path: inset(50%);
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
assets/js/schedule.js
Normal file
27
assets/js/schedule.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Day picker for the schedule shortcode. The CSS only uses it on narrow screens;
|
||||
// without JavaScript all days stack vertically there.
|
||||
for (const schedule of document.querySelectorAll('[data-schedule]')) {
|
||||
const picker = schedule.querySelector('.schedule__picker');
|
||||
const buttons = [...picker.querySelectorAll('button')];
|
||||
|
||||
const select = (selected) => {
|
||||
for (const button of buttons) {
|
||||
const isSelected = button === selected;
|
||||
button.setAttribute('aria-pressed', isSelected);
|
||||
document
|
||||
.getElementById(button.getAttribute('aria-controls'))
|
||||
.classList.toggle('schedule__day--selected', isSelected);
|
||||
}
|
||||
};
|
||||
|
||||
for (const button of buttons) {
|
||||
button.addEventListener('click', () => select(button));
|
||||
}
|
||||
|
||||
// During the event, start on today's tours. The 'sv' locale formats as YYYY-MM-DD.
|
||||
const today = new Date().toLocaleDateString('sv');
|
||||
select(buttons.find((button) => button.dataset.date === today) ?? buttons[0]);
|
||||
|
||||
picker.hidden = false;
|
||||
schedule.classList.add('schedule--picker');
|
||||
}
|
||||
|
|
@ -10,17 +10,6 @@ cascade:
|
|||
|
||||
Diese Touren haben wir zum 37c3 in 2023 angeboten.
|
||||
|
||||
| Zeit | Tag 1 (27.12.) | Tag 2 (28.12.) | Tag 3 (29.12.) |
|
||||
|------|-----------------------------------------------------------|-----------------------------------------------------------|-----------------------------------------------------------|
|
||||
| 10 | – | 10:45 [U-434]({{< relref "37c3/u-434" >}}) | – |
|
||||
| 11 | – | 11:15 [Eisenbahnmuseum]({{< relref "37c3/eisenbahnmuseum" >}}) | 11:05 [U-434]({{< relref "37c3/u-434" >}}) |
|
||||
| 12 | 12:30 [electrum]({{< relref "37c3/electrum" >}}) | 12:40 [Cap San Diego]({{< relref "37c3/cap-san-diego" >}}) | 12:40 [Cap San Diego]({{< relref "37c3/cap-san-diego" >}}) |
|
||||
| 13 | – | 13:40 [Alter Elbtunnel]({{< relref "37c3/alter-elbtunnel" >}}) | 13:20 [Energiebunker]({{< relref "37c3/energiebunker" >}}) |
|
||||
| 14 | 14:40 [Alter Elbtunnel]({{< relref "37c3/alter-elbtunnel" >}}) | 14:45 [MS Stubnitz]({{< relref "37c3/chaostrawler" >}}) | 14:35 [Energiebunker]({{< relref "37c3/energiebunker" >}}) |
|
||||
| | | | 14:40 [Alter Elbtunnel]({{< relref "37c3/alter-elbtunnel" >}}) |
|
||||
| 15 | 15:45 [U-434]({{< relref "37c3/u-434" >}}) | 15:40 [Alter Elbtunnel]({{< relref "37c3/alter-elbtunnel" >}}) | |
|
||||
| 16 | 16:40 [Alter Elbtunnel]({{< relref "37c3/alter-elbtunnel" >}}) | – | 16:40 [Alter Elbtunnel]({{< relref "37c3/alter-elbtunnel" >}}) |
|
||||
| 17 | | | | |
|
||||
| 18 | | 18:00 [Hansaplatz]({{< relref "37c3/hansaplatz" >}})| | |
|
||||
{{< schedule >}}
|
||||
|
||||
Wir haben keine Touren an Tag 4 (30.12.).
|
||||
|
|
@ -11,23 +11,6 @@ cascade:
|
|||
|
||||
Diese Touren bieten wir zum 38c3 Chaos Communication Congress an:
|
||||
|
||||
| Zeit | Tag 1 (27.12.) | Tag 2 (28.12.) | Tag 3 (29.12.) |
|
||||
| ----- | ----------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- |
|
||||
| 10:00 | | 10:30 [Rote Flora](flora) | |
|
||||
| 11:00 | | 10:45 [MS Stubnitz](chaostrawler) | 11:15 [MS Stubnitz](chaostrawler) |
|
||||
| 12:00 | 12:15 [Curious Community Lab](curious-community-lab ) | 12:00 [Eisenbahnmuseum](eisenbahnmuseum) | |
|
||||
| | | 12:30 [Rote Flora](flora) | |
|
||||
| 13:00 | 13:00 [NDR](ndr) | 13:30 [Hafenrundfahrt](alternative-harbor-cruise) | 13:30 [Hafenrundfahrt](alternative-harbor-cruise) |
|
||||
| | | | 13:45 [Electrum](electrum) |
|
||||
| 14:00 | 14:30 [XFEL](xfel) | 14:15 [Alter Elbtunnel](alter-elbtunnel) en | 14:00 [Energiebunker](energiebunker) |
|
||||
| | | | 14:45 [Electrum](electrum) |
|
||||
| 15:00 | 15:00 [DESY](desy) | | 15:00 [Energiebunker](energiebunker) |
|
||||
| | 15:30 [NDR](ndr) | | |
|
||||
| | 15:45 [Congress Lounge](lounge) | | |
|
||||
| 16:00 | 16:00 [Gängeviertel](gaengeviertel) | 16:00 [Gängeviertel](gaengeviertel) | 16:00 [Gängeviertel](gaengeviertel) |
|
||||
| 17:00 | 17:15 [Alter Elbtunnel](alter-elbtunnel) de | 17:15 [Tour der Giganten](tour-der-giganten) | 17:15 [Alter Elbtunnel](alter-elbtunnel) de |
|
||||
| 18:00 | 18:15 [Miwula](miwula) | 18:00 [Alter Elbtunnel](alter-elbtunnel) de | 18:15 [Miwula](miwula) |
|
||||
| | | 18:15 [Miwula](miwula) | |
|
||||
| 19:00 | 19:30 [Alsterdampfer](alsterdampfer) | | |
|
||||
{{< schedule >}}
|
||||
|
||||
Wir haben keine Touren an Tag 4 (30.12.).
|
||||
|
|
@ -14,29 +14,7 @@ cascade:
|
|||
|
||||
Diese Touren bieten wir zum 39C3 Chaos Communication Congress an:
|
||||
|
||||
**Tag 0 (26.12.)**: [Miniatur Wunderland](./miwula/) um 12:25 {{< lang deen >}} und 17:15 {{< lang deen >}}.
|
||||
|
||||
| Zeit | Tag 1 (27.12.) | Tag 2 (28.12.) | Tag 3 (29.12.) |
|
||||
|-------|----------------------------------------------------------------------------------|----------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
|
||||
| 10:00 | | 10:30 [Rote Flora](./flora/) {{< lang de >}} | 09:30 [Feuerwehr eHLF](./firestation/) {{< lang de >}} |
|
||||
| 11:00 | 11:30 [European XFEL](./xfel/) {{< lang deen >}} | 11:30 [European XFEL](./xfel/) {{< lang deen >}} | |
|
||||
| 12:00 | 12:00 [Stadtrundgang](./city-walk/) {{< lang de >}} | 12:00 [Stadtrundgang](./city-walk/) {{< lang de >}} | 12:00 [Stadtrundgang](./city-walk/) {{< lang de >}} |
|
||||
| | | 12:15 [Eisenbahnmuseum](./eisenbahnmuseum/) {{< lang deen >}} | |
|
||||
| | | 12:30 [Rote Flora](./flora/) {{< lang deen >}} | |
|
||||
| 13:00 | 13:00 [Retro Spiele Museum](./retro-games-museum/) {{< lang deen >}} | | |
|
||||
| | 13:30 [Alternative Hafenrundfahrt](./alternative-harbor-cruise/) {{< lang de >}} | 13:30 [Alternative Hafenrundfahrt](./alternative-harbor-cruise/) {{< lang de >}} | 13:30 [Alternative Hafenrundfahrt](./alternative-harbor-cruise/) {{< lang en >}} |
|
||||
| | 13:45 [Freies Sender Kombinat](./fsk/) {{< lang de >}} | | |
|
||||
| 14:00 | 14:00 [Stadtrundgang](./city-walk/) {{< lang en >}} | 14:00 [Stadtrundgang](./city-walk/) {{< lang en >}} | 14:00 [Stadtrundgang](./city-walk/) {{< lang en >}} |
|
||||
| | 14:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 14:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 14:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} |
|
||||
| | 14:15 [Alter Elbtunnel](./alter-elbtunnel/) {{< lang de >}} | | 14:15 [Alter Elbtunnel](./alter-elbtunnel/) {{< lang en >}} |
|
||||
| | | | 14:45 [Freies Sender Kombinat](./fsk/) {{< lang de >}} |
|
||||
| 15:00 | 15:45 [Congress Lounge](./lounge/) {{< lang deen >}} | | |
|
||||
| 16:00 | | | |
|
||||
| 17:00 | 17:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 17:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 17:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} |
|
||||
| | | 17:30 [Alsterdampfer](./alsterdampfer/) {{< lang de >}} | 17:30 [Alsterdampfer](./alsterdampfer/) {{< lang de >}} |
|
||||
| | 17:45 [Tour der Giganten](./tour-der-giganten/) {{< lang de >}} | 17:45 [Tour der Giganten](./tour-der-giganten/) {{< lang en >}} | 17:45 [Tour der Giganten](./tour-der-giganten/) {{< lang de >}} |
|
||||
| 18:00 | 18:00 [Körperfunkkollektiv](./koerperfunk/) {{< lang deen >}} | 18:00 [Körperfunkkollektiv](./koerperfunk/) {{< lang deen >}} | 18:00 [Körperfunkkollektiv](./koerperfunk/) {{< lang deen >}} |
|
||||
| 19:00 | 19:00 [Alsterdampfer](./alsterdampfer/) {{< lang de >}} | | |
|
||||
{{< schedule >}}
|
||||
|
||||
Wir haben keine Touren an Tag 4 (30.12.).
|
||||
|
||||
|
|
|
|||
|
|
@ -13,17 +13,7 @@ cascade:
|
|||
|
||||
Diese Touren bieten wir zum [Easterhegg 2025](https://eh22.easterhegg.eu/start) an:
|
||||
|
||||
| Zeit | Tag 1 (18.4.) | Tag 2 (19.4.) | Tag 3 (20.4.) |
|
||||
| ----- | ---------------------------- | ---------------------------------------- | -------------------------------------- |
|
||||
| 11:00 | | 11:00 [XFEL](xfel) | |
|
||||
| 12:00 | | 12:00 [Eisenbahnmuseum](eisenbahnmuseum) | |
|
||||
| 13:00 | | 13:00 [Freies Senderkombinat](fsk) | |
|
||||
| 14:00 | | 14:45 [Hafenrundfahrt](hafenrundfahrt) | 14:45 [Hafenrundfahrt](hafenrundfahrt) |
|
||||
| 15:00 | | | |
|
||||
| 16:00 | | 16:00 [Kampnagel](kampnagel) | |
|
||||
| 17:00 | 17:00 [Kampnagel](kampnagel) | 17:30 [Kampnagel](kampnagel) | 17:45 [Alsterdampfer](alsterdampfer) |
|
||||
| 18:00 | | | |
|
||||
| 19:00 | | | 19:15 [Alsterdampfer](alsterdampfer) |
|
||||
{{< schedule >}}
|
||||
|
||||
Wir haben keine Touren an Tag 4 (21.4.).
|
||||
|
||||
|
|
|
|||
|
|
@ -10,18 +10,6 @@ cascade:
|
|||
|
||||
These are the tours we did offer for 37c3 in 2023.
|
||||
|
||||
|
||||
| Time | Day 1 (27.12.) | Day 2 (28.12.) | Day 3 (29.12.) |
|
||||
|-------|----------------|----------------|----------------|
|
||||
| 10 | – | 10:45 [U-434]({{< relref "37c3/u-434" >}}) | – |
|
||||
| 11 | – | 11:15 [Train Museum]({{< relref "37c3/eisenbahnmuseum" >}}) | 11:05 [U-434]({{< relref "37c3/u-434" >}}) |
|
||||
| 12 | 12:30 [electrum]({{< relref "37c3/electrum" >}}) | 12:40 [Cap San Diego]({{< relref "37c3/cap-san-diego" >}}) | 12:40 [Cap San Diego]({{< relref "37c3/cap-san-diego" >}}) |
|
||||
| 13 | – | 13:40 [Old Elbe Tunnel]({{< relref "37c3/alter-elbtunnel" >}}) | 13:20 [Energy Bunker]({{< relref "37c3/energiebunker" >}}) de |
|
||||
| 14 | 14:40 [Old Elbe Tunnel]({{< relref "37c3/alter-elbtunnel" >}}) | 14:45 [MS Stubnitz]({{< relref "37c3/chaostrawler" >}}) | 14:35 [Energy Bunker]({{< relref "37c3/energiebunker" >}}) de |
|
||||
| | | | 14:40 [Old Elbe Tunnel]({{< relref "37c3/alter-elbtunnel" >}})|
|
||||
| 15 | 15:45 [U-434]({{< relref "37c3/u-434" >}}) | 15:40 [Old Elbe Tunnel]({{< relref "37c3/alter-elbtunnel" >}}) | |
|
||||
| 16 | 16:40 [Old Elbe Tunnel]({{< relref "37c3/alter-elbtunnel" >}}) | – | 16:40 [Old Elbe Tunnel]({{< relref "37c3/alter-elbtunnel" >}}) |
|
||||
| 17 | | | | |
|
||||
| 18 | | 18:00 [Hansaplatz]({{< relref "37c3/hansaplatz" >}})| | |
|
||||
{{< schedule >}}
|
||||
|
||||
There are no tours on day 4 (30.12.).
|
||||
|
|
@ -9,24 +9,6 @@ cascade:
|
|||
|
||||
These are the tours on offer for 38c3 Chaos Communication Congress:
|
||||
|
||||
|
||||
| Time | Day 1 (27 December) | Day 2 (28 December) | Day 3 (29 December) |
|
||||
| ----- | ----------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------ |
|
||||
| 10:00 | | 10:30 [Rote Flora](flora) | |
|
||||
| 11:00 | | 10:45 [MS Stubnitz](chaostrawler) | 11:15 [MS Stubnitz](chaostrawler) |
|
||||
| 12:00 | 12:15 [Curious Community Lab](curious-community-lab ) | 12:00 [Train Museum](eisenbahnmuseum) | |
|
||||
| | | 12:30 [Rote Flora](flora) | |
|
||||
| 13:00 | 13:00 [NDR](ndr) | 13:30 [Harbor Cruise](alternative-harbor-cruise) | 13:30 [Harbor Cruise](alternative-harbor-cruise) |
|
||||
| | | | 13:45 [Electrum](electrum) |
|
||||
| 14:00 | 14:30 [XFEL](xfel) | 14:15 [Old Elbe Tunnel](alter-elbtunnel) en | 14:00 [Energiebunker](energiebunker) |
|
||||
| | | | 14:45 [Electrum](electrum) |
|
||||
| 15:00 | 15:00 [DESY](desy) | | 15:00 [Energiebunker](energiebunker) |
|
||||
| | 15:30 [NDR](ndr) | | |
|
||||
| | 15:45 [Congress Lounge](lounge) | | |
|
||||
| 16:00 | 16:00 [Gängeviertel](gaengeviertel) | 16:00 [Gängeviertel](gaengeviertel) | 16:00 [Gängeviertel](gaengeviertel) |
|
||||
| 17:00 | 17:15 [Old Elbe Tunnel](alter-elbtunnel) de | 17:15 [Tour of the Giganten](tour-der-giganten) | 17:15 [Old Elbe Tunnel](alter-elbtunnel) de |
|
||||
| 18:00 | 18:15 [Miwula](miwula) | 18:00 [Old Elbe Tunnel](alter-elbtunnel) de | 18:15 [Miwula](miwula) |
|
||||
| | | 18:15 [Miwula](miwula) | |
|
||||
| 19:00 | 19:30 [Alster Steamer](alsterdampfer) | | |
|
||||
{{< schedule >}}
|
||||
|
||||
There are no tours on day 4 (30 December).
|
||||
|
|
@ -12,30 +12,7 @@ cascade:
|
|||
|
||||
These are the tours on offer for 39C3 Chaos Communication Congress:
|
||||
|
||||
|
||||
**Day 0 (26.12.)**: [Miniatur Wunderland](./miwula/) at 12:25 {{< lang deen >}} and 17:15 {{< lang deen >}}.
|
||||
|
||||
| Time | Day 1 (27.12.) | Day 2 (28.12.) | Day 3 (29.12.) |
|
||||
| ----- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| 10:00 | | 10:30 [Rote Flora](./flora/) {{< lang de >}} | 09:30 [Electric Firetruck](./firestation/) {{< lang de >}} |
|
||||
| 11:00 | 11:30 [European XFEL](./xfel/) {{< lang deen >}} | 11:30 [European XFEL](./xfel/) {{< lang deen >}} | |
|
||||
| 12:00 | 12:00 [City Walk](./city-walk/) {{< lang de >}} | 12:00 [City Walk](./city-walk/) {{< lang de >}} | 12:00 [City Walk](./city-walk/) {{< lang de >}} |
|
||||
| | | 12:15 [Train Museum](./eisenbahnmuseum/) {{< lang deen >}} | |
|
||||
| | | 12:30 [Rote Flora](./flora/) {{< lang deen >}} | |
|
||||
| 13:00 | 13:00 [Retro Games Museum](./retro-games-museum/) {{< lang deen >}} | | |
|
||||
| | 13:30 [Alternative Harbour Cruise](./alternative-harbor-cruise/) {{< lang de >}} | 13:30 [Alternative Harbour Cruise](./alternative-harbor-cruise/) {{< lang de >}} | 13:30 [Alternative Harbour Cruise](./alternative-harbor-cruise/) {{< lang en >}} |
|
||||
| | 13:45 [Freies Sender Kombinat Radio](./fsk/) {{< lang de >}} | | |
|
||||
| 14:00 | 14:00 [City Walk](./city-walk/) {{< lang en >}} | 14:00 [City Walk](./city-walk/) {{< lang en >}} | 14:00 [City Walk](./city-walk/) {{< lang en >}} |
|
||||
| | 14:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 14:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 14:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} |
|
||||
| | 14:15 [Alter Elbtunnel](./alter-elbtunnel/) {{< lang de >}} | | 14:15 [Alter Elbtunnel](./alter-elbtunnel/) {{< lang en >}} |
|
||||
| | | | 14:45 [Freies Sender Kombinat Radio](./fsk/) {{< lang de >}} |
|
||||
| 15:00 | 15:45 [Congress Lounge](./lounge/) {{< lang deen >}} | | |
|
||||
| 16:00 | | | |
|
||||
| 17:00 | 17:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 17:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} | 17:15 [Miniatur Wunderland](./miwula/) {{< lang deen >}} |
|
||||
| | | 17:30 [Alster Steamer](./alsterdampfer/) {{< lang de >}} | 17:30 [Alster Steamer](./alsterdampfer/) {{< lang de >}} |
|
||||
| | 17:45 [Tour of the Giants](./tour-der-giganten/) {{< lang de >}} | 17:45 [Tour of the Giants](./tour-der-giganten/) {{< lang en >}} | 17:45 [Tour of the Giants](./tour-der-giganten/) {{< lang de >}} |
|
||||
| 18:00 | 18:00 [Körperfunkkollektiv](./koerperfunk/) {{< lang deen >}} | 18:00 [Körperfunkkollektiv](./koerperfunk/) {{< lang deen >}} | 18:00 [Körperfunkkollektiv](./koerperfunk/) {{< lang deen >}} |
|
||||
| 19:00 | 19:00 [Alster Steamer](./alsterdampfer/) {{< lang de >}} | | |
|
||||
{{< schedule >}}
|
||||
|
||||
There are no tours on day 4 (30 December).
|
||||
|
||||
|
|
|
|||
|
|
@ -13,17 +13,7 @@ cascade:
|
|||
|
||||
We are offering these tours for [Easterhegg 2025](https://eh22.easterhegg.eu/start):
|
||||
|
||||
| Time | Day 1 (18 April) | Day 2 (19 April) | Day 3 (20 April) |
|
||||
| ----- | ---------------------------- | ------------------------------------- | ---------------------------------------- |
|
||||
| 11:00 | | 11:00 [XFEL](xfel) | |
|
||||
| 12:00 | | 12:00 [Train Museum](eisenbahnmuseum) | |
|
||||
| 13:00 | | 13:00 [Free Radio](fsk) | |
|
||||
| 14:00 | | 14:45 [Harbor Cruise](hafenrundfahrt) | 14:45 [Harbor Cruise](hafenrundfahrt) |
|
||||
| 15:00 | | | |
|
||||
| 16:00 | | 16:00 [Kampnagel](kampnagel) | |
|
||||
| 17:00 | 17:00 [Kampnagel](kampnagel) | 17:30 [Kampnagel](kampnagel) | 17:45 [Alster Steam Boat](alsterdampfer) |
|
||||
| 18:00 | | | |
|
||||
| 19:00 | | | 19:15 [Alster Steam Boat](alsterdampfer) |
|
||||
{{< schedule >}}
|
||||
|
||||
There are no tours on Monday, April 21st.
|
||||
|
||||
|
|
|
|||
29
data/schedule/37c3.yaml
Normal file
29
data/schedule/37c3.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Tour schedule for 37C3, rendered by the schedule shortcode.
|
||||
# tour: slug of the tour page in this section; lang: de, en or deen.
|
||||
days:
|
||||
- day: 1
|
||||
date: "2023-12-27"
|
||||
tours:
|
||||
- { time: "12:30", tour: electrum }
|
||||
- { time: "14:40", tour: alter-elbtunnel }
|
||||
- { time: "15:45", tour: u-434 }
|
||||
- { time: "16:40", tour: alter-elbtunnel }
|
||||
- day: 2
|
||||
date: "2023-12-28"
|
||||
tours:
|
||||
- { time: "10:45", tour: u-434 }
|
||||
- { time: "11:15", tour: eisenbahnmuseum }
|
||||
- { time: "12:40", tour: cap-san-diego }
|
||||
- { time: "13:40", tour: alter-elbtunnel }
|
||||
- { time: "14:45", tour: chaostrawler }
|
||||
- { time: "15:40", tour: alter-elbtunnel }
|
||||
- { time: "18:00", tour: hansaplatz }
|
||||
- day: 3
|
||||
date: "2023-12-29"
|
||||
tours:
|
||||
- { time: "11:05", tour: u-434 }
|
||||
- { time: "12:40", tour: cap-san-diego }
|
||||
- { time: "13:20", tour: energiebunker, lang: de }
|
||||
- { time: "14:35", tour: energiebunker, lang: de }
|
||||
- { time: "14:40", tour: alter-elbtunnel }
|
||||
- { time: "16:40", tour: alter-elbtunnel }
|
||||
41
data/schedule/38c3.yaml
Normal file
41
data/schedule/38c3.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Tour schedule for 38C3, rendered by the schedule shortcode.
|
||||
# tour: slug of the tour page in this section; lang: de, en or deen.
|
||||
days:
|
||||
- day: 1
|
||||
date: "2024-12-27"
|
||||
tours:
|
||||
- { time: "12:15", tour: curious-community-lab }
|
||||
- { time: "13:00", tour: ndr }
|
||||
- { time: "14:30", tour: xfel }
|
||||
- { time: "15:00", tour: desy }
|
||||
- { time: "15:30", tour: ndr }
|
||||
- { time: "15:45", tour: lounge }
|
||||
- { time: "16:00", tour: gaengeviertel }
|
||||
- { time: "17:15", tour: alter-elbtunnel, lang: de }
|
||||
- { time: "18:15", tour: miwula }
|
||||
- { time: "19:30", tour: alsterdampfer }
|
||||
- day: 2
|
||||
date: "2024-12-28"
|
||||
tours:
|
||||
- { time: "10:30", tour: flora }
|
||||
- { time: "10:45", tour: chaostrawler }
|
||||
- { time: "12:00", tour: eisenbahnmuseum }
|
||||
- { time: "12:30", tour: flora }
|
||||
- { time: "13:30", tour: alternative-harbor-cruise }
|
||||
- { time: "14:15", tour: alter-elbtunnel, lang: en }
|
||||
- { time: "16:00", tour: gaengeviertel }
|
||||
- { time: "17:15", tour: tour-der-giganten }
|
||||
- { time: "18:00", tour: alter-elbtunnel, lang: de }
|
||||
- { time: "18:15", tour: miwula }
|
||||
- day: 3
|
||||
date: "2024-12-29"
|
||||
tours:
|
||||
- { time: "11:15", tour: chaostrawler }
|
||||
- { time: "13:30", tour: alternative-harbor-cruise }
|
||||
- { time: "13:45", tour: electrum }
|
||||
- { time: "14:00", tour: energiebunker }
|
||||
- { time: "14:45", tour: electrum }
|
||||
- { time: "15:00", tour: energiebunker }
|
||||
- { time: "16:00", tour: gaengeviertel }
|
||||
- { time: "17:15", tour: alter-elbtunnel, lang: de }
|
||||
- { time: "18:15", tour: miwula }
|
||||
53
data/schedule/39c3.yaml
Normal file
53
data/schedule/39c3.yaml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Tour schedule for 39C3, rendered by the schedule shortcode.
|
||||
# tour: slug of the tour page in this section; lang: de, en or deen.
|
||||
days:
|
||||
- day: 0
|
||||
date: "2025-12-26"
|
||||
tours:
|
||||
- { time: "12:25", tour: miwula, lang: deen }
|
||||
- { time: "17:15", tour: miwula, lang: deen }
|
||||
- day: 1
|
||||
date: "2025-12-27"
|
||||
tours:
|
||||
- { time: "11:30", tour: xfel, lang: deen }
|
||||
- { time: "12:00", tour: city-walk, lang: de }
|
||||
- { time: "13:00", tour: retro-games-museum, lang: deen }
|
||||
- { time: "13:30", tour: alternative-harbor-cruise, lang: de }
|
||||
- { time: "13:45", tour: fsk, lang: de }
|
||||
- { time: "14:00", tour: city-walk, lang: en }
|
||||
- { time: "14:15", tour: alter-elbtunnel, lang: de }
|
||||
- { time: "14:15", tour: miwula, lang: deen }
|
||||
- { time: "15:45", tour: lounge, lang: deen }
|
||||
- { time: "17:15", tour: miwula, lang: deen }
|
||||
- { time: "17:45", tour: tour-der-giganten, lang: de }
|
||||
- { time: "18:00", tour: koerperfunk, lang: deen }
|
||||
- { time: "19:00", tour: alsterdampfer, lang: de }
|
||||
- day: 2
|
||||
date: "2025-12-28"
|
||||
tours:
|
||||
- { time: "10:30", tour: flora, lang: de }
|
||||
- { time: "11:30", tour: xfel, lang: deen }
|
||||
- { time: "12:00", tour: city-walk, lang: de }
|
||||
- { time: "12:15", tour: eisenbahnmuseum, lang: deen }
|
||||
- { time: "12:30", tour: flora, lang: deen }
|
||||
- { time: "13:30", tour: alternative-harbor-cruise, lang: de }
|
||||
- { time: "14:00", tour: city-walk, lang: en }
|
||||
- { time: "14:15", tour: miwula, lang: deen }
|
||||
- { time: "17:15", tour: miwula, lang: deen }
|
||||
- { time: "17:30", tour: alsterdampfer, lang: de }
|
||||
- { time: "17:45", tour: tour-der-giganten, lang: en }
|
||||
- { time: "18:00", tour: koerperfunk, lang: deen }
|
||||
- day: 3
|
||||
date: "2025-12-29"
|
||||
tours:
|
||||
- { time: "09:30", tour: firestation, lang: de }
|
||||
- { time: "12:00", tour: city-walk, lang: de }
|
||||
- { time: "13:30", tour: alternative-harbor-cruise, lang: en }
|
||||
- { time: "14:00", tour: city-walk, lang: en }
|
||||
- { time: "14:15", tour: alter-elbtunnel, lang: en }
|
||||
- { time: "14:15", tour: miwula, lang: deen }
|
||||
- { time: "14:45", tour: fsk, lang: de }
|
||||
- { time: "17:15", tour: miwula, lang: deen }
|
||||
- { time: "17:30", tour: alsterdampfer, lang: de }
|
||||
- { time: "17:45", tour: tour-der-giganten, lang: de }
|
||||
- { time: "18:00", tour: koerperfunk, lang: deen }
|
||||
22
data/schedule/eh22.yaml
Normal file
22
data/schedule/eh22.yaml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Tour schedule for EH22, rendered by the schedule shortcode.
|
||||
# tour: slug of the tour page in this section; lang: de, en or deen.
|
||||
days:
|
||||
- day: 1
|
||||
date: "2025-04-18"
|
||||
tours:
|
||||
- { time: "17:00", tour: kampnagel, lang: de }
|
||||
- day: 2
|
||||
date: "2025-04-19"
|
||||
tours:
|
||||
- { time: "11:00", tour: xfel, lang: de }
|
||||
- { time: "12:00", tour: eisenbahnmuseum, lang: de }
|
||||
- { time: "13:00", tour: fsk, lang: de }
|
||||
- { time: "14:45", tour: hafenrundfahrt, lang: de }
|
||||
- { time: "16:00", tour: kampnagel, lang: de }
|
||||
- { time: "17:30", tour: kampnagel, lang: de }
|
||||
- day: 3
|
||||
date: "2025-04-20"
|
||||
tours:
|
||||
- { time: "14:45", tour: hafenrundfahrt, lang: de }
|
||||
- { time: "17:45", tour: alsterdampfer, lang: de }
|
||||
- { time: "19:15", tour: alsterdampfer, lang: de }
|
||||
2
i18n/de.yaml
Normal file
2
i18n/de.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
schedule_day: "Tag {{ .Day }}"
|
||||
schedule_pick_day: "Tag auswählen"
|
||||
2
i18n/en.yaml
Normal file
2
i18n/en.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
schedule_day: "Day {{ .Day }}"
|
||||
schedule_pick_day: "Choose a day"
|
||||
21
layouts/_partials/lang-badge.html
Normal file
21
layouts/_partials/lang-badge.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{{- /* Language badge for a tour. Params: code ("de", "en" or "deen"), class (optional; without it the badge is styled as an inline superscript). */ -}}
|
||||
{{- $code := .code | lower -}}
|
||||
{{- $validCodes := slice "de" "en" "deen" -}}
|
||||
{{- if not (in $validCodes $code) -}}
|
||||
<span style="color: red; font-weight: bold;">Warning: Invalid or missing language code '{{ $code }}'. Use 'de', 'en', or 'deen'.</span>
|
||||
{{- else -}}
|
||||
{{- $label := cond (eq $code "de") "DE" (cond (eq $code "en") "EN" (cond (eq $code "deen") "DE/EN" "")) -}}
|
||||
{{- $title := "" -}}
|
||||
{{- if eq $code "deen" -}}
|
||||
{{- $title = cond (eq site.Language.Name "de") "Diese Tour wird zweisprachig stattfinden (Deutsch und Englisch)" "This tour will be bilingual (German and English)" -}}
|
||||
{{- else if eq $code "de" -}}
|
||||
{{- $title = cond (eq site.Language.Name "de") "Diese Tour wird auf Deutsch stattfinden" "This tour will be held in German" -}}
|
||||
{{- else if eq $code "en" -}}
|
||||
{{- $title = cond (eq site.Language.Name "de") "Diese Tour wird auf Englisch stattfinden" "This tour will be held in English" -}}
|
||||
{{- end -}}
|
||||
{{- with .class -}}
|
||||
<abbr class="{{ . }}" title="{{ $title }}">{{ $label }}</abbr>
|
||||
{{- else -}}
|
||||
<abbr style="font-size: .65em; vertical-align: super;" title="{{ $title }}">{{ $label }}</abbr>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
4
layouts/_partials/schedule-script.html
Normal file
4
layouts/_partials/schedule-script.html
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{{- /* Script for the schedule shortcode, included by the base templates on pages that use it. */ -}}
|
||||
{{- with resources.Get "js/schedule.js" | minify | fingerprint -}}
|
||||
<script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous" defer></script>
|
||||
{{- end -}}
|
||||
|
|
@ -1,16 +1 @@
|
|||
{{- $code := .Get 0 | lower -}}
|
||||
{{- $validCodes := slice "de" "en" "deen" -}}
|
||||
{{- if not (in $validCodes $code) -}}
|
||||
<span style="color: red; font-weight: bold;">Warning: Invalid or missing language code '{{ $code }}'. Use 'de', 'en', or 'deen'.</span>
|
||||
{{- else -}}
|
||||
{{- $label := cond (eq $code "de") "DE" (cond (eq $code "en") "EN" (cond (eq $code "deen") "DE/EN" "")) -}}
|
||||
{{- $title := "" -}}
|
||||
{{- if eq $code "deen" -}}
|
||||
{{- $title = cond (eq .Site.Language.Name "de") "Diese Tour wird zweisprachig stattfinden (Deutsch und Englisch)" "This tour will be bilingual (German and English)" -}}
|
||||
{{- else if eq $code "de" -}}
|
||||
{{- $title = cond (eq .Site.Language.Name "de") "Diese Tour wird auf Deutsch stattfinden" "This tour will be held in German" -}}
|
||||
{{- else if eq $code "en" -}}
|
||||
{{- $title = cond (eq .Site.Language.Name "de") "Diese Tour wird auf Englisch stattfinden" "This tour will be held in English" -}}
|
||||
{{- end -}}
|
||||
<abbr style="font-size: .65em; vertical-align: super;" title="{{ $title }}">{{ $label }}</abbr>
|
||||
{{- end -}}
|
||||
{{- partial "lang-badge.html" (dict "code" (.Get 0)) -}}
|
||||
|
|
|
|||
97
layouts/_shortcodes/schedule.html
Normal file
97
layouts/_shortcodes/schedule.html
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
{{- /*
|
||||
Tour schedule from data/schedule/<event>.yaml, one column of tour cards per day.
|
||||
On narrow screens the days stack; with JavaScript a day picker shows one day at a time.
|
||||
|
||||
Usage: {{< schedule >}} on a section page (the event is the section name),
|
||||
or {{< schedule 39c3 >}}.
|
||||
*/ -}}
|
||||
{{- $event := .Get 0 | default .Page.Section -}}
|
||||
{{- $schedule := index hugo.Data.schedule $event -}}
|
||||
{{- if not $schedule -}}
|
||||
{{- errorf "schedule: no data file data/schedule/%s.yaml: %s" $event .Position -}}
|
||||
{{- end -}}
|
||||
{{- $id := printf "schedule-%s" $event | anchorize -}}
|
||||
{{- /* Tour page titles start with the event name ("39C3 Rote Flora"); the cards don't need it. */ -}}
|
||||
{{- $prefix := printf `(?i)^%s\s+` $event -}}
|
||||
{{- /*
|
||||
On wide screens tours line up by start time: every start time gets a grid row, or several
|
||||
when one day has more than one tour starting then. $slotRow maps a time to its first row.
|
||||
Every hour from the first to the last tour starts a new row ($hours) with a line above it,
|
||||
so an hour without tours still gets a row.
|
||||
*/ -}}
|
||||
{{- $slotCount := dict -}}
|
||||
{{- range $schedule.days -}}
|
||||
{{- $count := dict -}}
|
||||
{{- range .tours -}}
|
||||
{{- $count = merge $count (dict .time (add (index $count .time | default 0) 1)) -}}
|
||||
{{- end -}}
|
||||
{{- range $time, $n := $count -}}
|
||||
{{- if gt $n (index $slotCount $time | default 0) -}}
|
||||
{{- $slotCount = merge $slotCount (dict $time $n) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- $times := slice -}}
|
||||
{{- range $time, $n := $slotCount }}{{ $times = $times | append $time }}{{ end -}}
|
||||
{{- $hourOf := dict -}}
|
||||
{{- range $times }}{{ $hourOf = merge $hourOf (dict . (int (strings.TrimLeft "0" (substr . 0 2) | default "0"))) }}{{ end -}}
|
||||
{{- $slotRow := dict -}}
|
||||
{{- $hours := slice -}}
|
||||
{{- $rows := 0 -}}
|
||||
{{- range $hour := seq (index $hourOf (index $times 0)) (index $hourOf (index $times (sub (len $times) 1))) -}}
|
||||
{{- $start := add $rows 1 -}}
|
||||
{{- range $time := $times -}}
|
||||
{{- if eq (index $hourOf $time) $hour -}}
|
||||
{{- $slotRow = merge $slotRow (dict $time (add $rows 1)) -}}
|
||||
{{- $rows = add $rows (index $slotCount $time) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if eq $rows (sub $start 1) }}{{ $rows = $start }}{{ end -}}
|
||||
{{- $hours = $hours | append (dict "hour" $hour "row" $start) -}}
|
||||
{{- end -}}
|
||||
<div class="schedule" id="{{ $id }}" data-schedule>
|
||||
<div class="schedule__picker" role="group" aria-label="{{ i18n "schedule_pick_day" }}" hidden>
|
||||
{{- range $schedule.days }}
|
||||
<button type="button" class="schedule__pick" aria-controls="{{ $id }}-day-{{ .day }}" aria-pressed="false" data-date="{{ .date }}">{{ i18n "schedule_day" (dict "Day" .day) }} <span class="schedule__pick-date">{{ time.AsTime .date | time.Format "2.1." }}</span></button>
|
||||
{{- end }}
|
||||
</div>
|
||||
<div class="schedule__days" style="--schedule-days: {{ len $schedule.days }}; --schedule-rows: {{ $rows }}">
|
||||
{{- range $column, $day := $schedule.days }}
|
||||
<section class="schedule__day" id="{{ $id }}-day-{{ .day }}" aria-labelledby="{{ $id }}-day-{{ .day }}-title" style="--schedule-column: {{ add $column 1 }}">
|
||||
<h2 class="schedule__day-title" id="{{ $id }}-day-{{ .day }}-title">{{ i18n "schedule_day" (dict "Day" .day) }} <span class="schedule__date">{{ time.AsTime .date | time.Format "Mon 2.1." }}</span></h2>
|
||||
<ol class="schedule__list">
|
||||
{{- $seen := dict }}
|
||||
{{- range sort .tours "time" }}
|
||||
{{- $nth := index $seen .time | default 0 }}
|
||||
{{- $seen = merge $seen (dict .time (add $nth 1)) }}
|
||||
{{- $page := $.Page.GetPage .tour }}
|
||||
{{- if not $page }}{{ warnf "schedule: %s: no page for tour %q on day %v" $event .tour $day.day }}{{ end }}
|
||||
<li class="schedule__card" style="--schedule-row: {{ add (index $slotRow .time) $nth }}">
|
||||
<time class="schedule__time" datetime="{{ $day.date }}T{{ .time }}">{{ .time }}</time>
|
||||
{{- with .lang }}
|
||||
<span class="schedule__langs">{{ range (cond (reflect.IsSlice .) . (slice .)) }}{{ partial "lang-badge.html" (dict "code" . "class" "schedule__lang") }}{{ end }}</span>
|
||||
{{- end }}
|
||||
{{- with $page }}
|
||||
{{- $title := .LinkTitle | replaceRE $prefix "" }}
|
||||
<a class="schedule__title" href="{{ .RelPermalink }}" title="{{ $title }}">{{ $title }}</a>
|
||||
{{- else }}
|
||||
<span class="schedule__title">{{ .tour }}</span>
|
||||
{{- end }}
|
||||
</li>
|
||||
{{- end }}
|
||||
</ol>
|
||||
</section>
|
||||
{{- end }}
|
||||
{{- /* Hour lines; where the first day has no tour in the hour's first row, its column shows the hour.
|
||||
They sit in .schedule__days, whose first row holds the day titles, hence the + 1. */}}
|
||||
{{- $firstDay := index $schedule.days 0 }}
|
||||
{{- range $hours }}
|
||||
{{- $row := .row }}
|
||||
<div class="schedule__hour" style="--schedule-row: {{ add .row 1 }}" aria-hidden="true">
|
||||
{{- $busy := false }}
|
||||
{{- range $firstDay.tours }}{{ if eq (index $slotRow .time) $row }}{{ $busy = true }}{{ end }}{{ end }}
|
||||
{{- if not $busy }}<span class="schedule__hour-label">{{ printf "%02d:00" .hour }}</span>{{ end -}}
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
{{ partialCached "head/tracking.html" . }}
|
||||
{{ partial "head/extra.html" . }}
|
||||
{{ block "head" . }}{{ end }}
|
||||
{{ if .HasShortcode "schedule" }}{{ partial "schedule-script.html" . }}{{ end }}
|
||||
</head>
|
||||
|
||||
<body class="{{ if .IsPage }}single-page{{ else }}list-page{{ end }}{{ if .IsHome }} front{{ end }}{{ with .Section }} section-page--{{ . | urlize }}{{ end }}{{ with $.Param "bodyclass" }} {{ . }}{{ end }}">
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
{{ partialCached "head/tracking.html" . }}
|
||||
{{ partial "head/extra.html" . }}
|
||||
{{ block "head" . }}{{ end }}
|
||||
{{ if .HasShortcode "schedule" }}{{ partial "schedule-script.html" . }}{{ end }}
|
||||
</head>
|
||||
|
||||
<body class="{{ if .IsPage }}single-page{{ else }}list-page{{ end }}{{ if .IsHome }} front{{ end }}{{ with .Section }} section-page--{{ . | urlize }}{{ end }}{{ with $.Param "bodyclass" }} {{ . }}{{ end }}">
|
||||
|
|
|
|||
Loading…
Reference in a new issue