diff --git a/src/components/pages/Timeline/components/EventGrid/index.tsx b/src/components/pages/Timeline/components/EventGrid/index.tsx index 8974451addcd86d4f62488a565161f2458e7221d..8ade24df0d5032ac4f8f4916d81bee8607122f6f 100644 --- a/src/components/pages/Timeline/components/EventGrid/index.tsx +++ b/src/components/pages/Timeline/components/EventGrid/index.tsx @@ -1,32 +1,55 @@ import React from "react"; import styles from "./style.module.scss"; -import { TimelineEvent } from "../.."; +import { TimelineEvent, ModuleTracks } from "../.."; import TimelineEventCard from "../TimelineEventCard"; export interface EventGridProps { numWeeks: number; trackHeight: number; - events: TimelineEvent[]; + modulesList: any[]; + moduleTracks: ModuleTracks; +} + +interface EventDisplay { + title: string; + id: number; + startColumn: number; + endColumn: number; + rowNumber: number; } const EventGrid: React.FC<EventGridProps> = ({ numWeeks, trackHeight, - events, -}) => { + modulesList, + moduleTracks, +}) => { + //calculate event positions + let eventPositions: EventDisplay[] = []; + + // Generates template for rows + let gridTemplateRows: string = ""; + for (let i = 0; i < modulesList.length; i++) { + const code = modulesList[i].code; + const moduleTrack = moduleTracks[code]; + moduleTrack.forEach(() => (gridTemplateRows += `${trackHeight}rem `)); + gridTemplateRows += + i === 0 || i === modulesList.length - 1 ? "0.3125rem " : "0.625rem "; + } + return ( <div className={styles.timelineCardGrid} style={{ gridTemplateColumns: `repeat(${numWeeks}, 3rem 3rem 3rem 3rem 3rem 0.625rem)`, - gridTemplateRows: `${trackHeight}rem ${trackHeight}rem 0.3125rem repeat(${7}, ${trackHeight}rem ${trackHeight}rem 0.625rem) ${trackHeight}rem ${trackHeight}rem 0.3125rem`, + gridTemplateRows: gridTemplateRows, }} > - {events.map(({ title }, i) => ( + {eventPositions.map(({ title, startColumn, endColumn, rowNumber }) => ( <TimelineEventCard title={title} - startColumn={i + 1} - endColumn={i + 8} - rowNumber={2 * i} + startColumn={startColumn} + endColumn={endColumn} + rowNumber={rowNumber} /> ))} </div> diff --git a/src/components/pages/Timeline/components/ModuleRows/index.tsx b/src/components/pages/Timeline/components/ModuleRows/index.tsx index 42e5d8a6b1b6d46d417c61726e138eb3786332f3..612f34422208cf44241cda09a370774bfba471d2 100644 --- a/src/components/pages/Timeline/components/ModuleRows/index.tsx +++ b/src/components/pages/Timeline/components/ModuleRows/index.tsx @@ -23,33 +23,30 @@ const ModuleRows: React.FC<ModuleRowsProps> = ({ for (let i = 0; i < modulesList.length; i++) { const code = modulesList[i].code; const tracks = moduleTracks[code]; - if (tracks) { - moduleHeadings.push( - <ModuleHeading - key={code} - style={{ height: `${tracks.length * trackHeight}rem` }} - moduleCode={code} - title={modulesList[i].title} - /> + moduleHeadings.push( + <ModuleHeading + key={code} + style={{ height: `${tracks.length * trackHeight}rem` }} + moduleCode={code} + title={modulesList[i].title} + /> + ); + const timelineBackgroundsClass = classNames( + i % 2 === 0 + ? styles.timelineBackgroundEven + : styles.timelineBackgroundOdd, + i === 0 ? styles.timelineBackgroundFirst : "", + i === modulesList.length - 1 ? styles.timelineBackgroundLast : "" + ); + const offset = i === modulesList.length - 1 || i === 0 ? 0.625 / 2 : 0.625; + for (let j = 0; j < numWeeks; j++) { + timelineBackgrounds.push( + <div + key={code + j} + style={{ height: `${tracks.length * trackHeight + offset}rem` }} + className={timelineBackgroundsClass} + ></div> ); - const timelineBackgroundsClass = classNames( - i % 2 === 0 - ? styles.timelineBackgroundEven - : styles.timelineBackgroundOdd, - i === 0 ? styles.timelineBackgroundFirst : "", - i === modulesList.length - 1 ? styles.timelineBackgroundLast : "" - ); - const offset = - i === modulesList.length - 1 || i === 0 ? 0.625 / 2 : 0.625; - for (let j = 0; j < numWeeks; j++) { - timelineBackgrounds.push( - <div - key={code + j} - style={{ height: `${tracks.length * trackHeight + offset}rem` }} - className={timelineBackgroundsClass} - ></div> - ); - } } } diff --git a/src/components/pages/Timeline/index.tsx b/src/components/pages/Timeline/index.tsx index ac29254e2e3365fae625303e769d8473d561ee14..2c698bbe91443af788fb60f76ebff04de03338b0 100644 --- a/src/components/pages/Timeline/index.tsx +++ b/src/components/pages/Timeline/index.tsx @@ -8,6 +8,7 @@ import ModuleRows from "./components/ModuleRows"; import DayIndicatorGrid from "./components/DayIndicatorGrid"; import EventGrid from "./components/EventGrid"; import { eventsData } from "./eventsData"; +import LoadingScreen from "components/molecules/LoadingScreen"; interface TimelineProps { initSideBar: () => void; @@ -15,11 +16,11 @@ interface TimelineProps { } export interface TimelineEvent { - title: string; - id: number; - moduleCode: string; - startDate: Date; - endDate: Date; + title: string; + id: number; + moduleCode: string; + startDate: Date; + endDate: Date; } export type ModuleTracks = { @@ -28,12 +29,13 @@ export type ModuleTracks = { interface TimelineState { moduleTracks: ModuleTracks; + isLoaded: boolean; } class Timeline extends React.Component<TimelineProps, TimelineState> { constructor(props: TimelineProps) { super(props); - this.state = { moduleTracks: {} }; + this.state = { moduleTracks: {}, isLoaded: false }; } componentDidMount() { @@ -42,7 +44,28 @@ class Timeline extends React.Component<TimelineProps, TimelineState> { modulesList.forEach(({ code }) => { moduleTracks[code] = [[], []]; }); - this.setState({ moduleTracks: moduleTracks }); + + let timelineEvents = eventsData; + for (let i = 0; i < timelineEvents.length; i++) { + const event = timelineEvents[i]; + let tracks: TimelineEvent[][] = moduleTracks[event.moduleCode]; + let isPlaced = false; + for (const track of tracks) { + if (track.every((te) => !eventsOverlaps(te, event))) { + isPlaced = true; + track.push(event); + break; + } + } + if (!isPlaced){ + tracks.push([event]); + } + } + + this.setState({ + moduleTracks: moduleTracks, + isLoaded: true, + }); } componentWillUnmount() { @@ -60,7 +83,9 @@ class Timeline extends React.Component<TimelineProps, TimelineState> { const activeDay = new Date("2020-10-12"); const numWeeks = 11; const trackHeight = 4; - + if (!this.state.isLoaded) { + return <LoadingScreen successful={<></>} />; + } return ( <div className={styles.timelineContainer}> <MyBreadcrumbs /> @@ -79,16 +104,25 @@ class Timeline extends React.Component<TimelineProps, TimelineState> { /> <DayIndicatorGrid - numWeeks={numWeeks} - activeDay={activeDay} + numWeeks={numWeeks} + activeDay={activeDay} activeColumn={this.dateToColumn(activeDay, termStart)} /> - <EventGrid numWeeks={numWeeks} trackHeight={trackHeight} events={eventsData}/> + <EventGrid + numWeeks={numWeeks} + trackHeight={trackHeight} + modulesList={modulesList} + moduleTracks={this.state.moduleTracks} + /> </div> </div> ); } } +function eventsOverlaps(e1: TimelineEvent, e2: TimelineEvent) { + return e1.startDate <= e2.endDate && e1.endDate >= e2.startDate; +} + export default Timeline;