Add Term Type (#361)

Co-authored-by: Jared He <66887902+jaredjhe@users.noreply.github.com>
Reviewed-on: #361
Reviewed-by: Amy <a258wang@csclub.uwaterloo.ca>
Reviewed-by: n3parikh <n3parikh@csclub.uwaterloo.ca>
Co-authored-by: j285he <j285he@localhost>
Co-committed-by: j285he <j285he@localhost>
j285he-ldap-test-example
Jared He 1 year ago
parent ff0594eac7
commit 2264e60852
  1. 4
      components/ArchivePage.tsx
  2. 35
      lib/events.ts
  3. 17
      lib/members.ts
  4. 13
      lib/news.ts
  5. 4
      pages/about/members.tsx
  6. 6
      pages/events/[year]/[term]/[event].tsx
  7. 14
      pages/events/[year]/[term]/index.tsx
  8. 3
      pages/events/[year]/index.tsx
  9. 4
      pages/events/index.tsx
  10. 6
      pages/news/[year]/[term].tsx
  11. 8
      utils.ts

@ -1,6 +1,6 @@
import React from "react";
import { capitalize } from "@/utils";
import { capitalize, Term } from "@/utils";
import { Link } from "./Link";
import {
@ -16,7 +16,7 @@ export interface Props {
type: "news" | "events";
items: {
year: string;
terms: string[];
terms: Term[];
}[];
}

@ -8,9 +8,10 @@ import { MDXRemoteSerializeResult } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
import type { Props } from "../pages/events/[year]/[term]/index";
// do not use alias "@/utils" as generate-calendar imports a function from this file and ts-node is not compatible
import { Term, TERMS, isTerm } from "../utils";
const EVENTS_PATH = path.join("content", "events");
export const TERMS = ["winter", "spring", "fall"];
export async function getEventYears(): Promise<string[]> {
return (await fs.readdir(EVENTS_PATH, { withFileTypes: true }))
@ -19,12 +20,12 @@ export async function getEventYears(): Promise<string[]> {
.sort();
}
export async function getEventTermsByYear(year: string): Promise<string[]> {
export async function getEventTermsByYear(year: string): Promise<Term[]> {
return (
await fs.readdir(path.join(EVENTS_PATH, year), { withFileTypes: true })
)
.filter((dirent) => dirent.isDirectory() && TERMS.includes(dirent.name))
.map((dirent) => dirent.name)
.filter((dirent) => dirent.isDirectory() && isTerm(dirent.name))
.map((dirent) => dirent.name as Term)
.sort((a, b) => TERMS.indexOf(a) - TERMS.indexOf(b));
}
@ -58,7 +59,7 @@ export const DATE_FORMAT = "MMMM dd yyyy HH:mm";
export async function getEventBySlug(
year: string,
term: string,
term: Term,
slug: string
): Promise<Event> {
const file = await fs.readFile(
@ -84,7 +85,7 @@ export async function getEventBySlug(
export async function getEventsByTerm(
year: string,
term: string
term: Term
): Promise<string[]> {
try {
return (await fs.readdir(path.join(EVENTS_PATH, year, term)))
@ -130,7 +131,7 @@ export async function getUpcomingEvents(): Promise<Event[]> {
});
}
export async function getAllEvents() {
export async function getAllEvents(): Promise<Event[]> {
const events: Event[] = [];
for (const year of await getEventYears()) {
@ -149,7 +150,7 @@ export async function getEventsPageProps({
term,
}: {
year: string;
term: string;
term: Term;
}): Promise<Props> {
const eventNames = await getEventsByTerm(year, term);
@ -177,7 +178,7 @@ export async function getEventsPageProps({
const eventYears = await getEventYears();
const minYear = eventYears[0];
const pastTerms: { year: string; term: string }[] = [];
const pastTerms: { year: string; term: Term }[] = [];
let curPastYear = year;
let curPastTerm = term;
while (parseInt(curPastYear) >= parseInt(minYear) && pastTerms.length < 2) {
@ -191,7 +192,7 @@ export async function getEventsPageProps({
pastTerms.reverse();
const maxYear = eventYears[eventYears.length - 1];
const futureTerms: { year: string; term: string }[] = [];
const futureTerms: { year: string; term: Term }[] = [];
let curFutureYear = year;
let curFutureTerm = term;
while (
@ -217,7 +218,7 @@ export async function getEventsPageProps({
};
}
export function getCurrentTerm() {
export function getCurrentTerm(): { year: string; term: Term } {
const today = new Date().toLocaleDateString("en-CA", {
timeZone: "EST",
year: "numeric",
@ -241,17 +242,14 @@ export function getCurrentTerm() {
term = "fall";
}
if (term === "") {
if (!isTerm(term)) {
throw new Error("Error setting the current term");
}
return { year, term };
}
function getPastTerm(
year: string,
term: string
): { year: string; term: string } {
function getPastTerm(year: string, term: Term): { year: string; term: Term } {
const index = TERMS.indexOf(term);
if (index === -1) {
@ -269,10 +267,7 @@ function getPastTerm(
};
}
function getFutureTerm(
year: string,
term: string
): { year: string; term: string } {
function getFutureTerm(year: string, term: Term): { year: string; term: Term } {
const index = TERMS.indexOf(term);
if (index === -1) {

@ -1,23 +1,17 @@
import { Client } from "ldapts";
import { Term } from "@/utils";
export interface Member {
name: string;
id: string;
program: string;
}
export async function getMembers(
year: string,
term: string
): Promise<Member[]> {
if (term !== "winter" && term !== "spring" && term !== "fall") {
throw new Error(`[getMembers] Not a valid term: "${term}"`);
}
export async function getMembers(year: string, term: Term): Promise<Member[]> {
if (process.env.USE_LDAP?.toLowerCase() !== "true") {
return dummyMembers;
}
let members: Member[] = [];
const url = "ldap://ldap1.csclub.uwaterloo.ca";
@ -28,7 +22,10 @@ export async function getMembers(
await client.bind("", "");
const { searchEntries } = await client.search(searchDN, {
scope: "sub",
filter: `(&(objectClass=member)(term=${term.slice(0, 1)}${year}))`,
filter: `(&(objectClass=member)(term=${(term as string).slice(
0,
1
)}${year}))`,
});
members = searchEntries

@ -6,10 +6,11 @@ import matter from "gray-matter";
import { MDXRemoteSerializeResult } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
import { isTerm, Term, TERMS } from "@/utils";
import { DATE_FORMAT, getLocalDateFromEST } from "./events";
export const NEWS_PATH = path.join("content", "news");
const TERMS = ["winter", "spring", "fall"];
export interface Metadata {
author: string;
@ -28,20 +29,20 @@ export async function getNewsYears(): Promise<string[]> {
.sort();
}
export async function getNewsTermsByYear(year: string): Promise<string[]> {
export async function getNewsTermsByYear(year: string): Promise<Term[]> {
return (
await fs.readdir(path.join(NEWS_PATH, year), {
withFileTypes: true,
})
)
.filter((dirent) => dirent.isDirectory() && TERMS.includes(dirent.name))
.map((dirent) => dirent.name)
.filter((dirent) => dirent.isDirectory() && isTerm(dirent.name))
.map((dirent) => dirent.name as Term)
.sort((a, b) => TERMS.indexOf(a) - TERMS.indexOf(b));
}
export async function getNewsByTerm(
year: string,
term: string
term: Term
): Promise<string[]> {
return (
await fs.readdir(path.join(NEWS_PATH, year, term), {
@ -54,7 +55,7 @@ export async function getNewsByTerm(
export async function getNewsBySlug(
year: string,
term: string,
term: Term,
slug: string
): Promise<News> {
const raw = await fs.readFile(

@ -6,14 +6,14 @@ import { Table } from "@/components/Table";
import { Title } from "@/components/Title";
import { getCurrentTerm } from "@/lib/events";
import { getMembers, Member } from "@/lib/members";
import { capitalize } from "@/utils";
import { Term, capitalize } from "@/utils";
import styles from "./members.module.css";
interface Props {
members: Member[];
year: string;
term: string;
term: Term;
}
export default function Members(props: Props) {

@ -18,7 +18,7 @@ import {
getEventsByTerm,
getEventBySlug,
} from "@/lib/events";
import { capitalize } from "@/utils";
import { capitalize, Term } from "@/utils";
export default function EventInfoPage({ year, term, event }: Props) {
return (
@ -43,13 +43,13 @@ EventInfoPage.getShapesConfig = ((width, height) => {
interface Props {
year: string;
term: string;
term: Term;
event: Event;
}
interface Params extends ParsedUrlQuery {
year: string;
term: string;
term: Term;
event: string;
}

@ -14,21 +14,21 @@ import {
getEventYears,
getEventTermsByYear,
} from "@/lib/events";
import { capitalize } from "@/utils";
import { capitalize, Term } from "@/utils";
import styles from "./index.module.css";
export interface Props {
year: string;
term: string;
term: Term;
pastEvents: Event[];
futureEvents: Event[];
isCurrentTerm: boolean;
pastTerms: { year: string; term: string }[];
futureTerms: { year: string; term: string }[];
pastTerms: { year: string; term: Term }[];
futureTerms: { year: string; term: Term }[];
}
export default function Term(props: Props) {
export default function TermPage(props: Props) {
let headerTerms = [{ year: props.year, term: props.term }];
// p, Current, f
@ -120,7 +120,7 @@ export default function Term(props: Props) {
function HeaderLink(props: {
year: string;
term: string;
term: Term;
isCurrentTerm?: boolean;
}) {
return (
@ -134,7 +134,7 @@ function HeaderLink(props: {
interface Params extends ParsedUrlQuery {
year: string;
term: string;
term: Term;
}
export const getStaticProps: GetStaticProps<Props, Params> = async (

@ -6,12 +6,13 @@ import React from "react";
import { Link } from "@/components/Link";
import { Title } from "@/components/Title";
import { getEventYears, getEventTermsByYear } from "@/lib/events";
import { Term } from "@/utils";
import styles from "./index.module.css";
interface Props {
year: string;
terms: string[];
terms: Term[];
}
export default function Year(props: Props) {

@ -2,9 +2,9 @@ import { GetStaticProps } from "next";
import { getCurrentTerm, getEventsPageProps } from "@/lib/events";
import Term, { Props } from "./[year]/[term]";
import TermPage, { Props } from "./[year]/[term]";
export default Term;
export default TermPage;
export const getStaticProps: GetStaticProps<Props> = async () => {
return { props: await getEventsPageProps(getCurrentTerm()) };

@ -18,13 +18,13 @@ import {
getNewsYears,
News,
} from "@/lib/news";
import { capitalize } from "@/utils";
import { capitalize, Term } from "@/utils";
import styles from "./[term].module.css";
interface Props {
year: string;
term: string;
term: Term;
news: News[];
}
@ -75,7 +75,7 @@ export const getStaticProps: GetStaticProps<Props, Params> = async (
interface Params extends ParsedUrlQuery {
year: string;
term: string;
term: Term;
}
export const getStaticPaths: GetStaticPaths<Params> = async () => {

@ -1,3 +1,11 @@
export const TERMS = ["winter", "spring", "fall"] as const;
export type Term = typeof TERMS[number];
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
export function isTerm(x: string): x is Term {
return TERMS.some((term) => x === term);
}
export function capitalize(str: string) {
return str.slice(0, 1).toUpperCase() + str.slice(1);
}

Loading…
Cancel
Save