Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/schedule/break.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ export interface Props {
}

const { time, title, style, className }: Props = Astro.props;
const label = [time, title].filter(Boolean).join(" ");
---

<div class={className? className: "break"} style={style} aria-label=`${time} ${title}` >
{time}{" "}
<div class={className? className: "break"} style={style} aria-label={label} >
{time && `${time} `}
{title}
<span class="sr-only">{time} {title}</span>
</div>

<style>
Expand Down
178 changes: 134 additions & 44 deletions src/components/schedule/day.astro
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,20 @@ const { day } = Astro.props;
const dayName = day.id;
//const day = getEntry("days", dayName);

const getRoomSortKey = (room: string) => {
const match = room.match(/\(S(\d+)([A-Z]?)\)/i);

if (!match) {
return `99-${room}`;
}

const [, number, suffix = ""] = match;
return `${number.padStart(2, "0")}-${suffix || "0"}-${room}`;
};

const ROOMS = (day.data.rooms ?? [])
.filter((room) => room.toLowerCase() !== "exhibit hall")
.sort();
.sort((a, b) => getRoomSortKey(a).localeCompare(getRoomSortKey(b)));

type ScheduleSession = {
title: string;
Expand Down Expand Up @@ -117,18 +128,21 @@ for (let i = 0; i < sessionAndTimes.length - 1; i++) {

const ends = sessions.map((session) => session.end);
const nextStart = nextSessions[0].start;
const candidateEndTimes = ends
.filter(
// skip talks than end after the next start,
// this is for events that span for multiple slots
// (like a sponsor fair)
(end) => end.getTime() <= nextStart.getTime(),
)
.map((end) => end.getTime());

if (candidateEndTimes.length === 0) {
continue;
}

const end = new Date(
Math.max(
...ends
.filter(
// skip talks than end after the next start,
// this is for events that span for multiple slots
// (like a sponsor fair)
(end) => end.getTime() <= nextStart.getTime(),
)
.map((end) => end.getTime()),
),
Math.max(...candidateEndTimes),
);

const hasBreakAfter = nextSessions.some(
Expand Down Expand Up @@ -220,7 +234,7 @@ for (let i = 0; i < slots.length; i++) {
const sizeInMinutes = nextTime - currentTime;
let size = sizeInMinutes / 5;

let sizeValue = `repeat(${size}, fit-content(100px))`;
let rowSize = `fit-content(100px)`;

if (current.type === "break") {
// we might have some "breaks" that are quite short, for example
Expand All @@ -229,16 +243,24 @@ for (let i = 0; i < slots.length; i++) {
// visually small breaks :)
size = Math.max(3, size);

sizeValue = `repeat(${size}, var(--break))`;
rowSize = `var(--break)`;
} else if (current.type === "room-change") {
sizeValue = `repeat(${size}, var(--room-change))`;
size = 1;
rowSize = `var(--room-change)`;
}

gridRows.push(sizeValue);
const rowTimes = Array.from({ length: size }, (_, i) =>
numberToTime(currentTime + i * 5),
);
const visibleRowCount = rowTimes.filter(
(time) => !timesToSkip.includes(time),
).length;

for (let i = 0; i < size; i++) {
const time = numberToTime(currentTime + i * 5);
if (visibleRowCount > 0) {
gridRows.push(`repeat(${visibleRowCount}, ${rowSize})`);
}

for (const time of rowTimes) {
timeToRow[time] = row;

if (!timesToSkip.includes(time)) {
Expand Down Expand Up @@ -267,30 +289,54 @@ type Session = {
rooms: string[];
};

const spansAllRooms = (rooms: string[]) => {
return ROOMS.every((room) => rooms.includes(room));
};

const getColStart = ({ type, rooms }: Session) => {
if (["room-change", "break"].includes(type)) {
if (type === "room-change") {
return 1;
}

if (type === "break" && spansAllRooms(rooms)) {
return 1;
}

const indexes = rooms
.map((room) => ROOMS.indexOf(room))
.filter((index) => index >= 0);

if (indexes.length === 0) {
return 1;
}

return Math.min(...indexes) + 2;
};

const getColEnd = ({ type, rooms }: Session) => {
if (["room-change", "break"].includes(type)) {
if (type === "room-change" || (type === "break" && spansAllRooms(rooms))) {
return -1;
}

const indexes = rooms
.map((room) => ROOMS.indexOf(room))
.filter((index) => index >= 0);

if (indexes.length === 0) {
return -1;
}

const indexes = rooms.map((room) => ROOMS.indexOf(room));
return Math.max(...indexes) + 3;
};

const getSessionStyle = (session: any) => {
const startRow = timeToRow[session.startTime];
const style = {
"--start": timeToRow[session.startTime],
"--end": timeToRow[session.endTime],
"--start": startRow,
"--end":
session.type === "room-change"
? startRow + 1
: timeToRow[session.endTime],
"--col-start": getColStart(session),
"--col-end": getColEnd(session),
};
Expand Down Expand Up @@ -362,25 +408,35 @@ const dateText = format(date, "eeee - do MMMM");
{
slots.map((slot) => (
<div class="slot">
<div
class="time"
style={{
"--start": timeToRow[slot.startTime],
"--end": timeToRow[slot.endTime],
}}
>
<h2>{format(slot.start, "HH:mm")}</h2>
</div>
{slot.type !== "room-change" && (
<div
class="time"
style={{
"--start": timeToRow[slot.startTime],
"--end": timeToRow[slot.endTime],
}}
>
<h2>{format(slot.start, "HH:mm")}</h2>
</div>
)}

{(sessionsByTime[slot.startTime] ?? [])
.sort(sortSessionByRooms)
.map((session) => {
const style = getSessionStyle(session);

if (
session.type === "room-change" ||
session.type === "break"
) {
if (session.type === "room-change") {
return (
<Break
title={session.title}
time={session.startTime}
className="break room-change"
style={style}
/>
);
}

if (session.type === "break") {
return (
<Break
title={session.title}
Expand Down Expand Up @@ -428,22 +484,31 @@ const dateText = format(date, "eeee - do MMMM");
</div>
<div class="h-12"></div>
</div>
</day>
</div>

<style is:global>

.layout-wrapper {
display: grid;
grid-template-columns: 1fr (770px, 100%) 1fr !important;
grid-template-columns: 1fr minmax(0, 100%) 1fr !important;
}

</style>
<style>
.schedule-wrapper
{
width: 100%;
margin-top: 0.75rem;
}

.day {
margin-block: 2rem 3rem;
}

.day:first-child {
margin-top: 0;
}


:global(.day-end) {
display: flex;
Expand Down Expand Up @@ -496,7 +561,6 @@ const dateText = format(date, "eeee - do MMMM");
:global(.session),
.time,
:global(.break),
.room-change,
header,
header > div > div {
/*outline: 2px solid var(--color-primary);*/
Expand All @@ -506,6 +570,29 @@ const dateText = format(date, "eeee - do MMMM");
padding:2px 0;
}

:global(.room-change) {
align-items: center;
background-color: #FCFBFA;
border-radius: 10px;
box-sizing: border-box;
color: var(--color-text);
display: flex;
font-weight: 400;
justify-content: center;
line-height: 1.2;
margin: 2px;
min-height: 0;
overflow: hidden;
padding: 0 8px;
white-space: nowrap;
}

:global(.break:not(.room-change)) {
background-color: #FFFCF7;
font-weight: 600;
letter-spacing: 0;
}

.posters {
text-align: center;
display: none;
Expand Down Expand Up @@ -542,6 +629,11 @@ const dateText = format(date, "eeee - do MMMM");

.schedule-container.header {
padding-bottom: 0;
margin-top: 0.5rem;
}

.schedule-container:not(.header) {
margin-top: 0.75rem;
}

.time,
Expand All @@ -553,7 +645,7 @@ const dateText = format(date, "eeee - do MMMM");
position: sticky;
top: 0;
background: var(--color-body-background);
z-index: 20;inherit
z-index: 20;

> div > div {
padding: 8px;
Expand All @@ -562,25 +654,23 @@ const dateText = format(date, "eeee - do MMMM");
}

.schedule {
--room-change: calc(var(--minute) * 8);
--5min: calc(var(--minute) * 5);
--break: 14px;
--room-change: 52px;

display: grid;
gap: 2px;
padding: 0;
padding-top:100px;
}

:global(.session),
.time,
.posters,
.room-change,
:global(.room-change),
:global(.break) {
grid-row: var(--start) / var(--end);
grid-column: var(--col-start) / var(--col-end);
}


:global(.day-end){
font-size: 1.2rem;
margin: 2px;
Expand Down
8 changes: 3 additions & 5 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,9 @@ interface ScheduleData {

const days = defineCollection({
loader: async (): Promise<any[]> => {
// TODO: Re-enable when the API is available
// const schedule = (await loadData(
// import.meta.env.EP_SCHEDULE_API
// )) as ScheduleData;
const schedule = null as ScheduleData | null;
const schedule = (await loadData(
import.meta.env.EP_SCHEDULE_API
)) as ScheduleData;

if (!schedule || Object.keys(schedule).length === 0) {
return [];
Expand Down
20 changes: 20 additions & 0 deletions src/data/links.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
{
"name": "Programme",
"items": [
{
"name": "Schedule",
"path": "/schedule"
},
{
"name": "List of Sessions",
"path": "/sessions"
Expand Down Expand Up @@ -132,10 +136,26 @@
{
"name": "Programme",
"items": [
{
"name": "Schedule",
"path": "/schedule"
},
{
"name": "List of Sessions",
"path": "/sessions"
},
{
"name": "List of Speakers",
"path": "/speakers"
},
{
"name": "Tracks",
"path": "/tracks"
},
{
"name": "Speaker Guidelines",
"path": "/guidelines"
},
{
"name": "Speaker Mentorship",
"path": "/mentorship"
Expand Down
Loading
Loading