diff --git a/.env.development b/.env.development index 6792a8ba4..c41c4c5c6 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,3 @@ EP_SESSIONS_API="https://static.europython.eu/programme/ep2025/releases/current/sessions.json" EP_SPEAKERS_API="https://static.europython.eu/programme/ep2025/releases/current/speakers.json" +EP_SCHEDULE_API="https://static.europython.eu/programme/ep2025/releases/current/schedule.json" diff --git a/.env.preview b/.env.preview index 91bc3a8bc..c41c4c5c6 100644 --- a/.env.preview +++ b/.env.preview @@ -1,3 +1,3 @@ -EP_SESSIONS_API="https://static.europython.eu/programme/ep2024/releases/current/sessions.json" -EP_SPEAKERS_API="https://gist.githubusercontent.com/nikoshell/24f8c99de3758dc4ed1391876c382b43/raw/bdf11fe89e5010f35dc1351e9b71c02a19adefe2/24speakers.json" -EP_SCHEDULE_API="https://static.europython.eu/programme/ep2024/releases/current/schedule.json" +EP_SESSIONS_API="https://static.europython.eu/programme/ep2025/releases/current/sessions.json" +EP_SPEAKERS_API="https://static.europython.eu/programme/ep2025/releases/current/speakers.json" +EP_SCHEDULE_API="https://static.europython.eu/programme/ep2025/releases/current/schedule.json" diff --git a/.env.production b/.env.production index 6792a8ba4..c41c4c5c6 100644 --- a/.env.production +++ b/.env.production @@ -1,2 +1,3 @@ EP_SESSIONS_API="https://static.europython.eu/programme/ep2025/releases/current/sessions.json" EP_SPEAKERS_API="https://static.europython.eu/programme/ep2025/releases/current/speakers.json" +EP_SCHEDULE_API="https://static.europython.eu/programme/ep2025/releases/current/schedule.json" diff --git a/package.json b/package.json index ecfd184f5..2f6685d2d 100644 --- a/package.json +++ b/package.json @@ -16,21 +16,21 @@ "@astrojs/mdx": "^4.2.3", "@astrojs/react": "^4.2.3", "@astrojs/sitemap": "^3.3.0", - "@astrojs/tailwind": "^5.1.4", - "@fontsource-variable/inter": "^5.1.1", + "@astrojs/tailwind": "^5.1.5", + "@fontsource-variable/inter": "^5.2.5", "@fortawesome/fontawesome-free": "^6.7.2", "@tailwindcss/typography": "^0.5.16", "@types/react": "^19.1.0", "@types/react-dom": "^19.1.1", - "astro": "^5.1.6", + "astro": "^5.5.2", "astro-delete-unused-images": "^1.0.3", "astro-meta-tags": "^0.3.1", - "astro-pagefind": "^1.8.1", + "astro-pagefind": "^1.8.3", "astro-preload": "^1.1.2", "clsx": "^2.1.1", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", - "hastscript": "^9.0.0", + "hastscript": "^9.0.1", "js-yaml": "^4.1.0", "marked": "^15.0.7", "pagefind": "^1.3.0", @@ -45,7 +45,7 @@ }, "devDependencies": { "@types/js-yaml": "^4.0.9", - "prettier": "^3.4.2", + "prettier": "^3.5.3", "prettier-plugin-astro": "^0.14.1" }, "prettier": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15eb290db..082bf68ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,10 +24,10 @@ importers: specifier: ^3.3.0 version: 3.3.0 '@astrojs/tailwind': - specifier: ^5.1.4 + specifier: ^5.1.5 version: 5.1.5(astro@5.5.2(jiti@1.21.7)(rollup@4.39.0)(typescript@5.8.3)(yaml@2.7.0))(tailwindcss@3.4.17) '@fontsource-variable/inter': - specifier: ^5.1.1 + specifier: ^5.2.5 version: 5.2.5 '@fortawesome/fontawesome-free': specifier: ^6.7.2 @@ -42,7 +42,7 @@ importers: specifier: ^19.1.1 version: 19.1.1(@types/react@19.1.0) astro: - specifier: ^5.1.6 + specifier: ^5.5.2 version: 5.5.2(jiti@1.21.7)(rollup@4.39.0)(typescript@5.8.3)(yaml@2.7.0) astro-delete-unused-images: specifier: ^1.0.3 @@ -51,7 +51,7 @@ importers: specifier: ^0.3.1 version: 0.3.1(astro@5.5.2(jiti@1.21.7)(rollup@4.39.0)(typescript@5.8.3)(yaml@2.7.0)) astro-pagefind: - specifier: ^1.8.1 + specifier: ^1.8.3 version: 1.8.3(astro@5.5.2(jiti@1.21.7)(rollup@4.39.0)(typescript@5.8.3)(yaml@2.7.0)) astro-preload: specifier: ^1.1.2 @@ -66,7 +66,7 @@ importers: specifier: ^3.2.0 version: 3.2.0(date-fns@4.1.0) hastscript: - specifier: ^9.0.0 + specifier: ^9.0.1 version: 9.0.1 js-yaml: specifier: ^4.1.0 @@ -106,7 +106,7 @@ importers: specifier: ^4.0.9 version: 4.0.9 prettier: - specifier: ^3.4.2 + specifier: ^3.5.3 version: 3.5.3 prettier-plugin-astro: specifier: ^0.14.1 diff --git a/src/components/schedule/break.astro b/src/components/schedule/break.astro index affbcd255..3da93b677 100644 --- a/src/components/schedule/break.astro +++ b/src/components/schedule/break.astro @@ -8,18 +8,19 @@ export interface Props { const { time, title, style }: Props = Astro.props; --- -
+
{time}{" "} {title} + {time} {title}
diff --git a/src/pages/schedule/[day].astro b/src/components/schedule/day.astro similarity index 85% rename from src/pages/schedule/[day].astro rename to src/components/schedule/day.astro index c909548e7..e60260705 100644 --- a/src/pages/schedule/[day].astro +++ b/src/components/schedule/day.astro @@ -1,13 +1,20 @@ + --- -import { getEntry, getCollection } from "astro:content"; -import Layout from "../../layouts/Layout.astro"; -import Break from "../../components/schedule/break.astro"; -import Session from "../../components/schedule/session.astro"; +import { type CollectionEntry, getEntry, getCollection } from "astro:content"; +import Break from "@components/schedule/break.astro"; +import Session from "@components/schedule/session.astro"; import { addMinutes, differenceInMinutes, parseISO } from "date-fns"; -import { Title } from "../../components/typography/title"; -import { Select } from "../../components/form/select"; +//import { Title } from "@components/typography/title"; +import Headline from "@components/ui/Headline.astro"; +import Button from "@ui/Button.astro"; +import { Select } from "@components/form/select"; import { formatInTimeZone } from "date-fns-tz"; + +interface Props { + day: CollectionEntry<"days">; +} + const format = (date: Date, format: string) => { return formatInTimeZone(date, "Europe/Prague", format); }; @@ -31,10 +38,12 @@ export const getStaticPaths = async () => { }); }; -const days = await getCollection("days"); -const day = await getEntry("days", Astro.params.day); -const ROOMS = (day?.data.rooms ?? []) +const { day } = Astro.props; +const dayName = day.id; +//const day = getEntry("days", dayName); + +const ROOMS = (day.data.rooms ?? []) .filter((room) => room.toLowerCase() !== "exhibit hall") .sort(); @@ -53,7 +62,7 @@ type ScheduleSession = { // hack for posters :) const posters: Array = []; -const sessions = day?.data.events +const sessions = day.data.events .map((event) => { const start = parseISO(event.start); const startTime = format(start, "HH:mm"); @@ -212,7 +221,7 @@ for (let i = 0; i < slots.length; i++) { const sizeInMinutes = nextTime - currentTime; let size = sizeInMinutes / 5; - let sizeValue = `repeat(${size}, fit-content(200px))`; + let sizeValue = `repeat(${size}, fit-content(100px))`; if (current.type === "break") { // we might have some "breaks" that are quite short, for example @@ -310,39 +319,25 @@ posters.forEach((poster) => { postersByTime[poster.startTime].push(poster); }); + + +const date = parseISO(dayName); +const dateText = format(date, "eeee - do MMMM"); --- - -
- Schedule - - -
+
-
+ +
Time
@@ -355,7 +350,7 @@ posters.forEach((poster) => { class="schedule" style={{ gridTemplateRows: gridRows.join(" "), - gridTemplateColumns: `80px repeat(${ROOMS.length}, minmax(200px, 1fr))`, + gridTemplateColumns: `80px repeat(${ROOMS.length}, minmax(100px, 1fr))`, }} > { @@ -420,18 +415,39 @@ posters.forEach((poster) => {
- + + + diff --git a/src/components/schedule/speakers.astro b/src/components/schedule/speakers.astro index 33e851e80..fdee5ce05 100644 --- a/src/components/schedule/speakers.astro +++ b/src/components/schedule/speakers.astro @@ -31,4 +31,8 @@ const speakers = Astro.props.speakers a:hover { text-decoration: underline; } + + a { + font-weight: 500; + } diff --git a/src/components/ui/Headline.astro b/src/components/ui/Headline.astro index 3940a768e..8fa66493d 100644 --- a/src/components/ui/Headline.astro +++ b/src/components/ui/Headline.astro @@ -8,7 +8,7 @@ const isCenter = center ? "text-center" : ""; --- - + {isAnchor && ( {Title} diff --git a/src/content/config.ts b/src/content/config.ts index 58ca12181..45ad98f54 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -1,5 +1,5 @@ import { defineCollection, reference, z } from "astro:content"; -import { loadData } from "../utils/dataLoader"; +import { loadData } from "@utils/dataLoader"; const mode = import.meta.env.MODE; console.log(`\x1b[35m[EP]\x1b[0m Current MODE: \x1b[1m\x1b[34m${mode}\x1b[0m`); @@ -159,17 +159,29 @@ const sessions = defineCollection({ }); const days = defineCollection({ - type: "data", + loader: async (): Promise => { + const schedule = await loadData(import.meta.env.EP_SCHEDULE_API); + + if (Object.keys(schedule).length === 0) { + return schedule; + } + return Object.entries(schedule.days).map(([date, data]: [string, any]) => ({ + id: date, + ...data, + })); + }, schema: z.object({ - rooms: z.array(z.string()), + id: z.string(), + rooms: z.array(z.string()).optional(), events: z.array( z.object({ - rooms: z.array(z.string()), - event_type: z.string(), code: z.string().optional(), - title: z.string(), + duration: z.number(), + event_type: z.string(), + level: z.string().optional().nullable(), + rooms: z.array(z.string()), + session_type: z.string().optional(), slug: z.string().optional(), - session_type: z.string().optional(), // why? speakers: z .array( z.object({ @@ -179,11 +191,11 @@ const days = defineCollection({ }) ) .optional(), - tweet: z.string().optional().nullable(), - level: z.string().optional().nullable(), start: z.string(), + title: z.string(), + track: z.string().optional().nullable(), + tweet: z.string().optional().nullable(), website_url: z.string().optional().nullable(), - duration: z.number(), }) ), }), diff --git a/src/data/links.json b/src/data/links.json index d95c6703e..5477b6471 100644 --- a/src/data/links.json +++ b/src/data/links.json @@ -54,6 +54,19 @@ } ] }, + { + "name": "Schedule", + "items": [ + { + "name": "Tutorials", + "path": "/schedule/tutorials" + }, + { + "name": "Talks", + "path": "/schedule/talks" + } + ] + }, { "name": "Prague & Venue", "items": [ diff --git a/src/env.d.ts b/src/env.d.ts index ccf023d42..107ecdf18 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -4,6 +4,7 @@ interface ImportMetaEnv { readonly EP_SESSIONS_API: string; readonly EP_SPEAKERS_API: string; + readonly EP_SCHEDULE_API: string; } interface ImportMeta { diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index fe4b0a03e..9040dab23 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,4 +1,5 @@ --- +import BaseLayout from "@layouts/BaseLayout.astro"; import BaseHead from "@components/BaseHead.astro"; import Header from "@components/Header.astro"; import Footer from "@components/Footer.astro"; @@ -16,14 +17,18 @@ export interface Props { } const { title, description } = Astro.props; + +if (!title || !description) { +throw new Error(`${Astro.url.pathname} Both 'title' and 'description' must be set.`); +} --- - - - + + - + + Skip to main content @@ -37,4 +42,4 @@ const { title, description } = Astro.props;