commit
83b68a3ce3
@ -0,0 +1,12 @@ |
||||
.warning{ |
||||
background-color: var(--warning-background); |
||||
padding: calc(6rem / 16); |
||||
color: var(--warning-text); |
||||
font-size: calc(16rem / 16); |
||||
text-align: center; |
||||
opacity: 1; |
||||
|
||||
/* The following are for a smooth fade in if there ever is a loading required for the warning, is not needed currently */ |
||||
/* max-height: 500px; |
||||
/* transition: max-height 1000ms ease-in, padding 100ms ease-in; */ |
||||
} |
@ -0,0 +1,60 @@ |
||||
import { parse } from "date-fns"; |
||||
import React from "react"; |
||||
|
||||
import warnings from "../content/warnings/warnings.json"; |
||||
import { DATE_FORMAT, getLocalDateFromEST } from "../utils"; |
||||
|
||||
import styles from "./WarningHeader.module.css"; |
||||
|
||||
interface Warning { |
||||
message: string; |
||||
startDate: string; |
||||
endDate: string; |
||||
} |
||||
|
||||
function getCurrentWarning(): Warning | null { |
||||
const today = new Date(); |
||||
const currentWarnings: Warning[] = warnings.filter((warning) => { |
||||
// convert dates to date objects in EST time zone
|
||||
let startDate = parse(warning.startDate, DATE_FORMAT, new Date()); |
||||
let endDate = parse(warning.endDate, DATE_FORMAT, new Date()); |
||||
|
||||
if ( |
||||
!startDate || |
||||
!endDate || |
||||
isNaN(startDate.getTime()) || // this checks if the parsed date is not valid (eg. wrong format), since getLocalDateFromEST fails with invalid dates
|
||||
isNaN(endDate.getTime()) |
||||
) { |
||||
throw new Error('WARNING WITH INVALID DATES: "' + warning.message + '"'); |
||||
} |
||||
|
||||
startDate = getLocalDateFromEST(startDate); |
||||
endDate = getLocalDateFromEST(endDate); |
||||
|
||||
return ( |
||||
startDate.getTime() <= today.getTime() && |
||||
endDate.getTime() >= today.getTime() |
||||
); |
||||
}); |
||||
|
||||
if (currentWarnings.length > 1) { |
||||
// If more than one warning is scheduled, log an error to the console. We cannot throw an error, since the site would go down on the live
|
||||
// website, on the day when more than one warning is scheduled.
|
||||
console.error( |
||||
"ERROR: MORE THAN ONE WARNING SCHEDULED CURRENTLY! ", |
||||
currentWarnings |
||||
); |
||||
} |
||||
|
||||
return currentWarnings.length === 0 ? null : currentWarnings[0]; |
||||
} |
||||
|
||||
export function WarningHeader() { |
||||
const warning = getCurrentWarning(); |
||||
|
||||
if (warning == null) { |
||||
return null; |
||||
} |
||||
|
||||
return <div className={styles.warning}>{warning.message}</div>; |
||||
} |
@ -0,0 +1,12 @@ |
||||
[ |
||||
{ |
||||
"startDate": "February 15 2022 00:00", |
||||
"endDate": "February 20 2022 18:00", |
||||
"message": "Warning: There will be a scheduled system maintenance on February 17 from 9pm to 12pm EST" |
||||
}, |
||||
{ |
||||
"startDate": "January 29 2022 21:00", |
||||
"endDate": "January 30 2022 18:00", |
||||
"message": "This is a sample warning" |
||||
} |
||||
] |
After Width: | Height: | Size: 515 KiB |
@ -0,0 +1,8 @@ |
||||
.page { |
||||
padding-bottom: calc(30rem / 16); |
||||
} |
||||
|
||||
.page > h1 { |
||||
padding-bottom: calc(16rem / 16); |
||||
border-bottom: calc(1rem / 16) solid var(--primary-heading); |
||||
} |
@ -0,0 +1,108 @@ |
||||
import { ParsedUrlQuery } from "querystring"; |
||||
|
||||
import { GetStaticPaths, GetStaticProps } from "next"; |
||||
import { MDXRemote } from "next-mdx-remote"; |
||||
import React from "react"; |
||||
|
||||
import { NewsCard } from "@/components/NewsCard"; |
||||
import { |
||||
ShapesConfig, |
||||
defaultGetShapesConfig, |
||||
GetShapesConfig, |
||||
} from "@/components/ShapesBackground"; |
||||
import { Title } from "@/components/Title"; |
||||
import { |
||||
getNewsBySlug, |
||||
getNewsByTerm, |
||||
getNewsTermsByYear, |
||||
getNewsDateByTerm, |
||||
getNewsYears, |
||||
News, |
||||
} from "@/lib/news"; |
||||
import { Term } from "@/utils"; |
||||
|
||||
import styles from "./[date].module.css"; |
||||
|
||||
interface Props { |
||||
year: string; |
||||
term: Term; |
||||
news: News[]; |
||||
} |
||||
|
||||
export default function DateNews({ news }: Props) { |
||||
const date = new Date(news[0].metadata.date).toLocaleDateString("en-US", { |
||||
year: "numeric", |
||||
month: "long", |
||||
day: "numeric", |
||||
}); |
||||
return ( |
||||
<div className={styles.page}> |
||||
<Title>{["News", `${date}`]}</Title> |
||||
<h1>News: {date}</h1> |
||||
{news.map(({ content, metadata }, idx) => ( |
||||
<NewsCard |
||||
key={idx} |
||||
{...metadata} |
||||
date={new Date(metadata.date)} |
||||
fit={true} |
||||
> |
||||
<MDXRemote {...content} /> |
||||
</NewsCard> |
||||
))} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
DateNews.getShapesConfig = ((width, height) => { |
||||
return window.innerWidth <= 768 |
||||
? ({} as ShapesConfig) |
||||
: defaultGetShapesConfig(width, height); |
||||
}) as GetShapesConfig; |
||||
|
||||
export const getStaticProps: GetStaticProps<Props, Params> = async ( |
||||
context |
||||
) => { |
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const { year, term, date } = context.params!; |
||||
const slugs = (await getNewsByTerm(year, term)).filter((slug) => |
||||
slug.includes(date) |
||||
); |
||||
|
||||
const news = await Promise.all( |
||||
slugs.map((slug) => getNewsBySlug(year, term, slug)) |
||||
); |
||||
// Reverse so that we are displaying the most recent news
|
||||
// of term first
|
||||
return { props: { year, term, news: news.reverse() } }; |
||||
}; |
||||
|
||||
interface Params extends ParsedUrlQuery { |
||||
year: string; |
||||
term: Term; |
||||
date: string; |
||||
} |
||||
|
||||
export const getStaticPaths: GetStaticPaths<Params> = async () => { |
||||
const years = await getNewsYears(); |
||||
const terms = await Promise.all( |
||||
years.map(async (year) => { |
||||
const termsInYear = await getNewsTermsByYear(year); |
||||
return termsInYear.map((term) => ({ year, term })); |
||||
}) |
||||
); |
||||
const dates = await Promise.all( |
||||
terms.map(async (termInYear) => { |
||||
const datesInTerm: Params[] = []; |
||||
for (const { year, term } of termInYear) { |
||||
const dates = await getNewsDateByTerm(year, term); |
||||
dates.map((date) => datesInTerm.push({ year, term, date })); |
||||
} |
||||
return datesInTerm.flat(); |
||||
}) |
||||
); |
||||
|
||||
return { |
||||
paths: dates.flat().map((params) => ({ params })), |
||||
fallback: false, |
||||
}; |
||||
}; |
Loading…
Reference in new issue