Add /news/archive and /news/[year]/[term] pages #146
|
@ -5,6 +5,12 @@
|
||||||
border-radius: calc(20rem / 16);
|
border-radius: calc(20rem / 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fit.card {
|
||||||
|
max-width: unset;
|
||||||
|
padding: unset;
|
||||||
|
border-radius: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
font-size: calc(18rem / 16);
|
font-size: calc(18rem / 16);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -6,15 +6,19 @@ interface NewsCardProps {
|
||||||
date: Date;
|
date: Date;
|
||||||
author: string;
|
author: string;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
fit?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NewsCard: React.FC<NewsCardProps> = ({
|
export const NewsCard: React.FC<NewsCardProps> = ({
|
||||||
date,
|
date,
|
||||||
author,
|
author,
|
||||||
children,
|
children,
|
||||||
|
fit = false,
|
||||||
}) => {
|
}) => {
|
||||||
|
const classes = fit ? [styles.card, styles.fit] : [styles.card];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={styles.card}>
|
<article className={classes.join(" ")}>
|
||||||
<h1 className={styles.date}>
|
<h1 className={styles.date}>
|
||||||
<time dateTime={date.toISOString()}>
|
<time dateTime={date.toISOString()}>
|
||||||
{date.toLocaleDateString("en-US", {
|
{date.toLocaleDateString("en-US", {
|
||||||
|
|
|
@ -3,6 +3,6 @@ author: "ja2morri"
|
||||||
date: "2003-07-09"
|
date: "2003-07-09"
|
||||||
---
|
---
|
||||||
|
|
||||||
Jim Elliott gave a great talk for the CSC yesterday and has put his slides online. <br>
|
Jim Elliott gave a great talk for the CSC yesterday and has put his slides online.
|
||||||
|
|
||||||
[ http://www.vm.ibm.com/devpages/jelliott/events](<http://www.vm.ibm.com/devpages/jelliott/events>)
|
[ http://www.vm.ibm.com/devpages/jelliott/events](<http://www.vm.ibm.com/devpages/jelliott/events>)
|
|
@ -3,10 +3,10 @@ author: "dtbartle"
|
||||||
date: "2008-05-04"
|
date: "2008-05-04"
|
||||||
---
|
---
|
||||||
|
|
||||||
Spring 2008 elections will be held on Tuesday May 13th at 4:30pm in the Comfy Lounge.<br>
|
Spring 2008 elections will be held on Tuesday May 13th at 4:30pm in the Comfy Lounge.
|
||||||
|
|
||||||
Get your nominations in as soon as possible on the CSC whiteboard!<br>
|
Get your nominations in as soon as possible on the CSC whiteboard!
|
||||||
|
|
||||||
Nominations close 24 hours before the polls open.<br>
|
Nominations close 24 hours before the polls open.
|
||||||
|
|
||||||
You can email your nominations to cro@csclub.uwaterloo.ca
|
You can email your nominations to cro@csclub.uwaterloo.ca
|
|
@ -5,12 +5,12 @@ date: "2018-09-01"
|
||||||
|
|
||||||
Power has now been restored to the machine room and most CSC systems and services are now available, with the exception of:
|
Power has now been restored to the machine room and most CSC systems and services are now available, with the exception of:
|
||||||
|
|
||||||
- **sucrose and taurine**<br>
|
- **sucrose and taurine**
|
||||||
|
|
||||||
We are currently unable to access to servers remotely. To restore these servers, we need a visit to the machine room to identify and resolve boot issues. <br>
|
We are currently unable to access to servers remotely. To restore these servers, we need a visit to the machine room to identify and resolve boot issues.
|
||||||
|
|
||||||
*As of Sept. 5, taurine is available again with reduced RAM.*
|
*As of Sept. 5, taurine is available again with reduced RAM.*
|
||||||
- **[test-ipv6](<http://test-ipv6.csclub.uwaterloo.ca>) (restored as of Sept. 2)**<br>
|
- **[test-ipv6](<http://test-ipv6.csclub.uwaterloo.ca>) (restored as of Sept. 2)**
|
||||||
|
|
||||||
Currently available from within the UW network only. Investigation is still ongoing and may require assistance from IST's security team.
|
Currently available from within the UW network only. Investigation is still ongoing and may require assistance from IST's security team.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
.page {
|
||||||
|
padding-bottom: calc(30rem / 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.term {
|
||||||
|
color: var(--primary-accent);
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
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 {
|
||||||
|
getNewsBySlug,
|
||||||
|
getNewsByTerm,
|
||||||
|
getNewsTermsByYear,
|
||||||
|
getNewsYears,
|
||||||
|
News,
|
||||||
|
} from "@/lib/news";
|
||||||
|
|
||||||
|
import styles from "./[term].module.css";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
year: string;
|
||||||
|
term: string;
|
||||||
|
news: News[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function TermNews({ year, term, news }: Props) {
|
||||||
|
return (
|
||||||
|
<div className={styles.page}>
|
||||||
|
<h1>
|
||||||
|
News Archive:{" "}
|
||||||
|
<span className={styles.term}>
|
||||||
|
{capitalize(term)} {year}
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
{news.map(({ content, metadata }, idx) => (
|
||||||
|
<NewsCard
|
||||||
|
key={idx}
|
||||||
|
{...metadata}
|
||||||
|
date={new Date(metadata.date)}
|
||||||
|
fit={true}
|
||||||
|
>
|
||||||
|
<MDXRemote {...content} />
|
||||||
|
</NewsCard>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps<Props, Params> = async (
|
||||||
|
context
|
||||||
|
) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
const { year, term } = context.params!;
|
||||||
|
const slugs = await getNewsByTerm(year, term);
|
||||||
|
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: 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 }));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
paths: terms.flat().map((params) => ({ params })),
|
||||||
|
fallback: false,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function capitalize(str: string) {
|
||||||
|
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
.page {
|
||||||
|
margin-bottom: calc(40rem / 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list > li {
|
||||||
|
line-height: 3;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { getNewsTermsByYear, getNewsYears } from "lib/news";
|
||||||
|
import { GetStaticProps } from "next";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { Link } from "@/components/Link";
|
||||||
|
|
||||||
|
import styles from "./archive.module.css";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
items: {
|
||||||
|
year: string;
|
||||||
|
terms: string[];
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NewsArchive({ items }: Props) {
|
||||||
|
return (
|
||||||
|
<div className={styles.page}>
|
||||||
|
<h1>News Archive</h1>
|
||||||
|
<ul className={styles.list}>
|
||||||
|
{items.map(({ year, terms }) =>
|
||||||
|
terms.map((term) => (
|
||||||
|
<li key={`${year}-${term}`}>
|
||||||
|
<Link href={`/news/${year}/${term}`}>
|
||||||
|
{capitalize(term)} {year}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps<Props> = async () => {
|
||||||
|
const years = (await getNewsYears()).reverse();
|
||||||
|
const yearsWithTerms = await Promise.all(
|
||||||
|
years.map(async (year) => ({
|
||||||
|
year,
|
||||||
|
terms: (await getNewsTermsByYear(year)).reverse(),
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
return { props: { items: yearsWithTerms } };
|
||||||
|
};
|
||||||
|
|
||||||
|
function capitalize(str: string) {
|
||||||
|
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
||||||
|
}
|
Loading…
Reference in New Issue