Separate Teams on meet the team page (Close #364) #403

Closed
b72zhou wants to merge 33 commits from b72zhou-separate-teams into main
9 changed files with 449 additions and 22 deletions

View File

@ -0,0 +1,18 @@
[
{
"name": "Jenny Zhang",
"role": "Team Lead"
},
{
"name": "Vivian Guo",
"role": "Team Lead"
},
{
"name": "Rachel Ma",
"role": "Design"
},
{
"name": "Aaryan Shroff",
"role": "Design"
}
]

View File

@ -0,0 +1,39 @@
[
{
"name": "Andy Wang",
"role": "Team Lead"
},
{
"name": "Alex Zhang",
"role": "Developer"
},
{
"name": "Allen Qin Lu",
"role": "Developer",
"image": "/images/team/AllenLu.png"
},
{
"name": "Chris Xie",
"role": "Developer"
},
{
"name": "Edwin Yang",
"role": "Developer"
},
{
"name": "Laura Nguyen",
"role": "Developer"
},
{
"name": "Marcus Chan",
"role": "Developer"
},
{
"name": "Mark Chen",
"role": "Developer"
},
{
"name": "Victor Zheng",
"role": "Developer"
}
]

View File

@ -0,0 +1,75 @@
[
{
"name": "Eden Chan",
"role": "Team Lead"
},
{
"name": "Eric Huang",
"role": "Team Lead"
},
{
"name": "Adele Chen",
"role": "Events"
},
{
"name": "Amya Singhal",
"role": "Events"
},
{
"name": "Anna Wang",
"role": "Events"
},
{
"name": "Catherine Wan",
"role": "Events"
},
{
"name": "Diana Brebeanu",
"role": "Events"
},
{
"name": "Elaine Han",
"role": "Events"
},
{
"name": "Jonathan Cui",
"role": "Events"
},
{
"name": "Kenson Hui",
"role": "Events"
},
{
"name": "Mabel Kwok",
"role": "Events"
},
{
"name": "Mashrur Chowdhury",
"role": "Events"
},
{
"name": "Matthew Wang",
"role": "Events"
},
{
"name": "Naman Chhawchharia",
"role": "Events"
},
{
"name": "Riddhi Bajaj",
"role": "Events"
},
{
"name": "Santiago Montemayor Gomez",
"role": "Events",
"image": "/images/team/SantiagoMontemayor.jpg"
},
{
"name": "Tommy Jiang",
"role": "Events"
},
{
"name": "William Tran",
"role": "Events"
}
]

View File

@ -0,0 +1,22 @@
[
{
"name": "David Chen",
"role": "Team Lead"
},
{
"name": "Daniel Kim",
"role": "External Affairs"
},
{
"name": "Eric Liu",
"role": "External Affairs"
},
{
"name": "Victor Wu",
"role": "External Affairs"
},
{
"name": "Wanda Song",
"role": "External Affairs"
}
]

View File

@ -0,0 +1,31 @@
[
{
"name": "Dina Orucevic",
"role": "Team Lead"
},
{
"name": "Arjun Amit Athalye",
"role": "Marketing",
"image": "/images/team/ArjunAthalye.jpeg"
},
{
"name": "Catherine Tao",
"role": "Marketing"
},
{
"name": "Ethan Hong",
"role": "Marketing"
},
{
"name": "Gurnika Kaur",
"role": "Marketing"
},
{
"name": "Haley Song",
"role": "Marketing"
},
{
"name": "Kshama Patel",
"role": "Marketing"
}
]

View File

@ -0,0 +1,18 @@
[
{
"name": "Bonnie Peng",
"role": "Team Lead"
},
{
"name": "Annie Zhang",
"role": "Photographer"
},
{
"name": "Calvin Zhong",
"role": "Photographer"
},
{
"name": "Jesse Liu",
"role": "Photographer"
}
]

View File

@ -0,0 +1,42 @@
[
{
"name": "Amy Luo",
"role": "Team Lead"
},
{
"name": "Govind Varma",
"role": "Representative"
},
{
"name": "Guneet Bola",
"role": "Representative"
},
{
"name": "Ivy Lei",
"role": "Representative"
},
{
"name": "Jasmine Bal",
"role": "Representative"
},
{
"name": "Mayank Mehra",
"role": "Representative"
},
{
"name": "Olivia Liu",
"role": "Representative"
},
{
"name": "Sat Arora",
"role": "Representative"
},
{
"name": "Star Xie",
"role": "Representative"
},
{
"name": "Tracy Dong",
"role": "Representative"
}
]

View File

@ -2,10 +2,35 @@ import { readFile, readdir, access } from "fs/promises";
import path from "path";
import matter from "gray-matter";
import { Client } from "ldapts";
import { serialize } from "next-mdx-remote/serialize";
import { getCurrentTerm } from "@/lib/events";
const EXECS_PATH = path.join("content", "team", "execs");
const fileType = ".md";
const { year, term } = getCurrentTerm();
const execPositions: { [name: string]: number } = {
president: 1,
"vice-president": 2,
secretary: 3,
treasurer: 4,
sysadmin: 5,
};
const positionNames: string[] = [
"President",
"Vice President",
"Assistant Vice President",
"Treasurer",
"System Administrator",
];
export interface ExecMembers {
name: string;
position: string;
}
export interface Metadata {
name: string;
@ -14,22 +39,100 @@ export interface Metadata {
}
export async function getExecNames() {
return (await readdir(EXECS_PATH))
.filter((name) => name.endsWith(fileType))
.map((name) => name.slice(0, -1 * fileType.length));
if (process.env.USE_LDAP?.toLowerCase() !== "true") {
return (await readdir(EXECS_PATH))
.filter((name) => name.endsWith(fileType))
.map((name) => name.slice(0, -1 * fileType.length));
}
const url = "ldap://ldap1.csclub.uwaterloo.ca";
const searchDN = "ou=People,dc=csclub,dc=uwaterloo,dc=ca";
const client = new Client({ url });
let execMembers: ExecMembers[] = [];
let formattedExec: string[];
try {
await client.bind("", "");
const { searchEntries } = await client.search(searchDN, {
scope: "sub",
filter: `(&(objectClass=member)(term=${(term as string).slice(
0,
1
)}${year}))`,
});
execMembers = searchEntries
.map((item) => {
return {
name: item.cn as string,
position:
item.position === undefined
? ""
: typeof item.position === "string"
? item.position
: (item.position[0] as string),
};
})
.filter((item: ExecMembers) => item.position !== "");
execMembers = execMembers.sort((item1: ExecMembers, item2: ExecMembers) => {
return execPositions[item1.position] - execPositions[item2.position];
});
formattedExec = execMembers.map(
(member) =>
`0${execPositions[member.position]}-${member.name
.split(" ")[0]
.toLowerCase()}-${member.name.split(" ")[1].toLowerCase()}`
);
formattedExec = [...formattedExec, "06-codey"];
} finally {
await client.unbind();
}
return formattedExec;
}
export async function getExec(fileName: string, convert = true) {
const raw = await readFile(path.join(EXECS_PATH, `${fileName}${fileType}`));
const { content, data: metadata } = matter(raw);
const image =
(metadata.image as string | undefined) ??
(await getMemberImagePath(metadata.name));
let content, metadata;
return {
content: convert ? await serialize(content) : content,
metadata: { ...metadata, image } as Metadata,
};
try {
const raw = await readFile(path.join(EXECS_PATH, `${fileName}${fileType}`));
({ content, data: metadata } = matter(raw));
const image =
(metadata.image as string | undefined) ??
(await getMemberImagePath(metadata.name));
return {
content: convert ? await serialize(content) : content,
metadata: { ...metadata, image } as Metadata,
};
} catch (err) {
const firstName =
fileName.split("-")[1][0].toUpperCase() + fileName.split("-")[1].slice(1);
const lastName =
fileName.split("-")[2][0].toUpperCase() + fileName.split("-")[2].slice(1);
const posOrder = fileName.split("-")[0][1];
const posName = positionNames[Number(posOrder) - 1];
({ content, metadata } = {
content: "Coming soon!",
metadata: {
name: `${firstName} ${lastName}`,
role: `${posName} ${Number(posOrder) - 1}`,
},
});
const image = await getMemberImagePath(metadata.name);
return {
content: convert ? await serialize(content) : content,
metadata: { ...metadata, image } as Metadata,
};
}
}
async function getImage(imgPath: string) {

View File

@ -16,7 +16,13 @@ import {
getMemberImagePath,
} from "@/lib/team";
import programmeData from "../../content/team/programme-committee.json";
import designData from "../../content/team/design-team.json";
import discordData from "../../content/team/discord-team.json";
import eventsData from "../../content/team/events-team.json";
import externalData from "../../content/team/external-affairs-team.json";
import marketingData from "../../content/team/marketing-team.json";
import photographyData from "../../content/team/photography-team.json";
import RepsData from "../../content/team/representative-team.json";
import systemsData from "../../content/team/systems-committee.json";
import terminalData from "../../content/team/terminal-committee.json";
import webData from "../../content/team/web-committee.json";
@ -30,7 +36,13 @@ interface SerializedExec {
interface Props {
execs: SerializedExec[];
programme: Metadata[];
design: Metadata[];
discord: Metadata[];
events: Metadata[];
external: Metadata[];
marketing: Metadata[];
photography: Metadata[];
reps: Metadata[];
website: Metadata[];
systems: Metadata[];
terminal: Metadata[];
@ -38,7 +50,13 @@ interface Props {
export default function Team({
execs,
programme,
design,
discord,
events,
external,
marketing,
photography,
reps,
website,
systems,
terminal,
@ -52,7 +70,13 @@ export default function Team({
<h1 className={styles.header}>Meet the Team!</h1>
<div className={styles.nav}>
<Link href="#execs">The Executives</Link>
<Link href="#programme">Programme Committee</Link>
<Link href="#design">Design Team</Link>
<Link href="#discord">Discord Team</Link>
<Link href="#events">Events Team</Link>
<Link href="#external">External Affairs Team</Link>
<Link href="#marketing">Marketing Team</Link>
<Link href="#photography">Photography Team</Link>
<Link href="#reps">Representatives Team</Link>
<Link href="#website">Website Committee</Link>
<Link href="#system">Systems Committee</Link>
<Link href="#terminal">Terminal Committee</Link>
@ -77,9 +101,33 @@ export default function Team({
);
})}
</div>
<div id="programme">
<h2 className={styles.subheading}>Programme Committee</h2>
<MembersList team={programme} />
<div id="design">
<h2 className={styles.subheading}>Design Team</h2>
<MembersList team={design} />
</div>
<div id="discord">
<h2 className={styles.subheading}>Discord Team</h2>
<MembersList team={discord} />
</div>
<div id="events">
<h2 className={styles.subheading}>Events Team</h2>
<MembersList team={events} />
</div>
<div id="external">
<h2 className={styles.subheading}>External Affairs Team</h2>
<MembersList team={external} />
</div>
<div id="marketing">
<h2 className={styles.subheading}>Marketing Team</h2>
<MembersList team={marketing} />
</div>
<div id="photography">
<h2 className={styles.subheading}>Photography Team</h2>
<MembersList team={photography} />
</div>
<div id="reps">
<h2 className={styles.subheading}>Representatives Team</h2>
<MembersList team={reps} />
</div>
<div id="website">
<h2 className={styles.subheading}>Website Committee</h2>
@ -141,17 +189,48 @@ async function getTeamWithImages(team: TeamMember[]) {
export const getStaticProps: GetStaticProps<Props> = async () => {
const execNames = await getExecNames();
const execs = (await Promise.all(
execNames.map((name) => getExec(name))
)) as SerializedExec[];
const [programme, website, systems, terminal] = await Promise.all([
getTeamWithImages(programmeData),
const [
design,
discord,
events,
external,
marketing,
photography,
reps,
website,
systems,
terminal,
] = await Promise.all([
getTeamWithImages(designData),
getTeamWithImages(discordData),
getTeamWithImages(eventsData),
getTeamWithImages(externalData),
getTeamWithImages(marketingData),
getTeamWithImages(photographyData),
getTeamWithImages(RepsData),
getTeamWithImages(webData),
getTeamWithImages(systemsData),
getTeamWithImages(terminalData),
]);
return {
props: { execs, programme, website, systems, terminal },
props: {
execs,
design,
discord,
events,
external,
marketing,
photography,
reps,
website,
systems,
terminal,
},
};
};