Merge branch 'main' of https://git.csclub.uwaterloo.ca/www/www-new into feat/meet-the-team-page
continuous-integration/drone/push Build is failing Details

This commit is contained in:
b38peng 2021-08-31 20:21:34 -03:00
commit 977d226b70
60 changed files with 17069 additions and 178 deletions

View File

@ -40,6 +40,7 @@
"files.eol": "\n",
"[markdown]": {
"editor.wordWrap": "on",
"editor.quickSuggestions": false
"editor.quickSuggestions": false,
"editor.tabSize": 4
}
}

21
README.md Normal file
View File

@ -0,0 +1,21 @@
# Development
## Dependencies
Make sure that you have `node` >= 14 and `npm` >= 7. Node 14 ships with npm v6,
so if you're using node 14, you would need to upgrade npm. Alternatively you
could also upgrade to node 16, which ships with npm 7.
How to upgrade npm: `npm i -g npm`
## Local
- `npm install` to install project dependencies
- `npm run dev` to run the dev server (http://localhost:3000)
## Production
- `npm install` to install project dependencies
- `npm run build` to generate html/css/js
- `npm run export` to move the built files (along with assets in the public directory) to the `/out` directory
- Use your favourite web server to host the files in the `/out` directory. (A very simple one would be `python -m http.server` - not sure if it should actually be used for production :P)

View File

@ -1,12 +1,14 @@
import React from "react";
import { Link } from "@/components/Link";
import { capitalize } from "@/utils";
import { Link } from "./Link";
import {
ShapesConfig,
GetShapesConfig,
defaultGetShapesConfig,
} from "@/components/ShapesBackground";
import { capitalize } from "@/utils";
} from "./ShapesBackground";
import { Title } from "./Title";
import styles from "./ArchivePage.module.css";
@ -20,6 +22,8 @@ export interface Props {
export function ArchivePage({ items, type }: Props) {
return (
<>
<Title>{[capitalize(type), "Archive"]}</Title>
<div className={styles.page}>
<h1>{capitalize(type)} Archive</h1>
<ul className={styles.list}>
@ -34,6 +38,7 @@ export function ArchivePage({ items, type }: Props) {
)}
</ul>
</div>
</>
);
}

View File

@ -20,7 +20,7 @@ export function ConnectWithUs() {
<p>
Send feedback through our{" "}
<Link href="https://bit.ly/uwcsclub-feedback-form">Feedback Form</Link>
<Link href="https://bit.ly/uwcsclub-feedback-form">Feedback Form</Link>.
</p>
</section>
);

View File

@ -133,7 +133,6 @@
}
@media only screen and (max-width: calc(768rem / 16)) {
.burger {
display: flex;
position: fixed;
@ -178,6 +177,11 @@
margin-bottom: calc(8rem / 16);
}
.content ul,
.content ol {
padding-left: 1rem;
}
.nav {
position: fixed;
@ -227,4 +231,3 @@
opacity: 100%;
}
}

View File

@ -26,6 +26,7 @@ interface Props {
children: ReactNode;
pageTitle: string;
link: Link;
numberedSections?: boolean;
}
export function OrganizedContent({
@ -34,6 +35,7 @@ export function OrganizedContent({
children,
pageTitle,
link: Link,
numberedSections = false,
}: Props) {
const [mobileNavOpen, setMobileNavOpen] = useState(false);
const currentIndex = sections.findIndex(
@ -71,6 +73,7 @@ export function OrganizedContent({
currentIndex={currentIndex}
link={Link}
pageTitle={pageTitle}
numberedSections={numberedSections}
mobileNavOpen={mobileNavOpen}
setMobileNavOpen={setMobileNavOpen}
/>
@ -80,7 +83,11 @@ export function OrganizedContent({
) : (
<>
<section>
<h1>{section.title}</h1>
<h1>
{numberedSections
? `${currentIndex}. ${section.title}`
: section.title}
</h1>
{children}
</section>
<Footer
@ -108,6 +115,7 @@ interface NavProps {
currentIndex: number;
link: Link;
pageTitle: string;
numberedSections: boolean;
mobileNavOpen: boolean;
setMobileNavOpen: (mobileNavOpen: boolean) => void;
}
@ -117,6 +125,7 @@ function Nav({
currentIndex,
link: Link,
pageTitle,
numberedSections,
mobileNavOpen,
setMobileNavOpen,
}: NavProps) {
@ -150,7 +159,11 @@ function Nav({
>
<Link className={classNames.join(" ")} id={section.id}>
<span className={styles.marker} />
<div>{section.title}</div>
<div>
{numberedSections && section.id !== READ_ALL_ID
? `${index}. ${section.title}`
: section.title}
</div>
</Link>
</div>
);
@ -221,15 +234,18 @@ export interface SectionWithContent {
export function createReadAllSection(
sections: Section[],
content: false
content: false,
numberedSections?: undefined
): Section;
export function createReadAllSection(
sections: SectionWithContent[],
content: true
content: true,
numberedSections: boolean
): SectionWithContent;
export function createReadAllSection(
sections: SectionWithContent[] | Section[],
content = true
content = true,
numberedSections?: boolean
): SectionWithContent | Section {
const readAllSection = {
id: READ_ALL_ID,
@ -243,9 +259,11 @@ export function createReadAllSection(
return (
<>
{(sections as SectionWithContent[]).map(
({ section: { id, title }, Content }) => (
({ section: { id, title }, Content }, index) => (
<section key={id}>
<h1>{title}</h1>
<h1>
{numberedSections ? `${index + 1}. ${title}` : title}
</h1>
<Content />
</section>
)

View File

@ -9,6 +9,7 @@ import {
} from "@/components/OrganizedContent";
import { GetShapesConfig } from "../ShapesBackground";
import { Title } from "../Title";
import { Header } from "./Header";
@ -32,6 +33,7 @@ export interface Options {
imagePosition?: "left" | "right";
link?: ComponentType<LinkProps>;
description?: string;
numberedSections?: boolean;
}
export function createReadAllPage({
@ -42,6 +44,7 @@ export function createReadAllPage({
link,
description,
imagePosition,
numberedSections = false,
}: Options) {
const Link = link ?? createLink(pagePath);
@ -53,10 +56,13 @@ export function createReadAllPage({
return <MDXRemote {...content} />;
},
})),
true
true,
numberedSections
);
return (
<>
<Title>{title}</Title>
<Header
title={title}
image={image}
@ -69,12 +75,14 @@ export function createReadAllPage({
readAllSection.section,
...sections.map(({ section }) => section),
]}
numberedSections={numberedSections}
pageTitle={title}
link={Link}
>
<readAllSection.Content />
</OrganizedContent>
</Header>
</>
);
}

View File

@ -3,6 +3,8 @@ import React from "react";
import { createLink, OrganizedContent } from "@/components/OrganizedContent";
import { Title } from "../Title";
import { Header } from "./Header";
import { Options } from "./ReadAll";
@ -25,11 +27,14 @@ export function createSectionPage({
link,
description,
imagePosition,
numberedSections,
}: Options) {
const Link = link ?? createLink(pagePath);
function Page(this: void, { content, sections, current }: Props) {
return (
<>
<Title>{[sections[current].title, title]}</Title>
<Header
title={title}
image={image}
@ -41,10 +46,12 @@ export function createSectionPage({
id={sections[current].id}
pageTitle={title}
link={Link}
numberedSections={numberedSections}
>
<MDXRemote {...content} />
</OrganizedContent>
</Header>
</>
);
}

19
components/Title.tsx Normal file
View File

@ -0,0 +1,19 @@
import Head from "next/head";
import React from "react";
interface Props {
children: string | string[];
}
export function Title(props: Props) {
const children =
typeof props.children === "string" ? [props.children] : props.children;
children.push("CSC", "University of Waterloo");
return (
<Head>
<title>{children.join(" - ")}</title>
</Head>
);
}

View File

@ -146,7 +146,7 @@ export function EventDescriptionCardDemo() {
export function EventCardDemo() {
return (
<>
{events.map(({ Content, metadata }, idx) => (
{events.map(({ Content, metadata }) => (
<>
<EventCard
{...metadata}
@ -220,12 +220,14 @@ export function LinkDemo() {
export function OrganizedContentDemo() {
const sections = [...constitution];
const numberedSections = false;
const readAllSection = createReadAllSection(
constitution.map(({ id, title, Content }) => ({
Content,
section: { id, title },
})),
true
true,
numberedSections
);
sections.unshift({
...readAllSection.section,
@ -253,6 +255,7 @@ export function OrganizedContentDemo() {
id={id}
link={FakeLink}
pageTitle="Playground"
numberedSections={numberedSections}
>
<Content />
</OrganizedContent>

View File

@ -1,5 +1,5 @@
---
title: 10. Amendments and Procedures
title: Amendments and Procedures
index: 10
---

View File

@ -1,5 +1,5 @@
---
title: 12. Code of Conduct
title: Code of Conduct
index: 12
---

View File

@ -1,5 +1,5 @@
---
title: 7. Committees
title: Committees
index: 7
---
@ -17,9 +17,9 @@ index: 7
3. Members should only be appointed to the Systems Committee if they show interest and some existing ability in systems administration.
4. Members should only be removed from the Systems Committee with cause, or when they no longer show interest in systems administration.
5. The Systems Committee will collectively, under the leadership of the Systems Administrator,
a. operate any and all equipment in the possession of the Club.
a. maintain and upgrade the software on equipment that is operated by the Club.
a. facilitate the use of equipment that is operated by the Club.
1. operate any and all equipment in the possession of the Club.
1. maintain and upgrade the software on equipment that is operated by the Club.
1. facilitate the use of equipment that is operated by the Club.
6. Members of the Systems Committee shall have root access to the machines operated by the Club.
## Other Committees

View File

@ -1,5 +1,5 @@
---
title: 11. Dissolution
title: Dissolution
index: 11
---

View File

@ -1,27 +1,27 @@
---
title: 5. Duties of Officers
title: Duties of Officers
index: 5
---
1. The duties of the President shall be:
a. to call and preside at all general, special, and executive meetings of the Club, except during the election of officers;
a. to appoint special committees of the Club and the membership and chairs of such committees, with the approval of the Executive Council; and
a. to audit, or to appoint a representative to audit, the financial records of the club at the end of each academic term.
a. with the approval of the Faculty Advisor, rule on any point of procedure under the constitution that arises outside of a meeting.
1. to call and preside at all general, special, and executive meetings of the Club, except during the election of officers;
1. to appoint special committees of the Club and the membership and chairs of such committees, with the approval of the Executive Council; and
1. to audit, or to appoint a representative to audit, the financial records of the club at the end of each academic term.
1. with the approval of the Faculty Advisor, rule on any point of procedure under the constitution that arises outside of a meeting.
1. The duties of the Vice-President shall be:
a. to assume the duties of the President in the event of the President's absence;
a. to chair the Programme Committee;
a. to appoint members to and remove members from the Programme Committee;
a. to ensure that Club events are held regularly; and
a. to assume those duties of the President that are delegated to them by the President.
1. to assume the duties of the President in the event of the President's absence;
1. to chair the Programme Committee;
1. to appoint members to and remove members from the Programme Committee;
1. to ensure that Club events are held regularly; and
1. to assume those duties of the President that are delegated to them by the President.
1. The duties of the Secretary shall be:
a. to keep minutes of all Club meetings;
a. to care for all Club correspondence; and
a. manage any persons appointed to internal positions by the Executive.
1. to keep minutes of all Club meetings;
1. to care for all Club correspondence; and
1. manage any persons appointed to internal positions by the Executive.
1. The duties of the Treasurer shall be:
a. to collect dues and maintain all financial and membership records;
a. to produce a financial or membership statement when requested.
1. to collect dues and maintain all financial and membership records;
1. to produce a financial or membership statement when requested.
1. The duties of the System Administrator shall be:
a. to chair the Systems Committee;
a. to appoint members to and remove members from the Systems Committee.
a. to ensure that the duties of the Systems Committee are performed.
1. to chair the Systems Committee;
1. to appoint members to and remove members from the Systems Committee.
1. to ensure that the duties of the Systems Committee are performed.

View File

@ -1,5 +1,5 @@
---
title: 6. Executive Council
title: Executive Council
index: 6
---

View File

@ -1,5 +1,5 @@
---
title: 9. Finances
title: Finances
index: 9
---

View File

@ -1,5 +1,5 @@
---
title: 8. Meetings
title: Meetings
index: 8
---

View File

@ -1,5 +1,5 @@
---
title: 3. Membership
title: Membership
index: 3
---

View File

@ -1,5 +1,5 @@
---
title: 1. Name
title: Name
index: 1
---

View File

@ -1,29 +1,29 @@
---
title: 4. Officers
title: Officers
index: 4
---
1. The officers of the Club shall be:
a. President
a. Vice-President
a. Secretary
a. Treasurer
a. System Administrator
1. President
1. Vice-President
1. Secretary
1. Treasurer
1. System Administrator
1. There shall additionally be a Faculty Advisor, selected by the Executive from time to time from among the faculty of the School of Computer Science. The Faculty Advisor shall be an ex-officio affiliate member of the Club.
1. The choice of officers shall be limited to full members of the Club.
1. All officers, other than the System Administrator, shall be elected at a meeting to be held no later than two weeks after the start of lectures in each term.
1. The election of officers shall be accomplished by the following procedure:
a. Before the end of the prior term, the then-Executive shall choose a willing Chief Returning Officer, who is responsible for carrying out elections according to this procedure.
a. The CRO shall set the date and time of the election meeting, and set the nomination period. The nomination shall be at least one week long and shall end at least 24 hours before the start of the election meeting.
a. Announcements of the election and the nomination procedure must be distributed to all members by the members' mailing list, and should also be advertised by posters in the MC building.
a. During the nomination period, the Chief Returning Officer (CRO) shall be available to receive nominations for the posts of officers of the club, either in person, by email, by depositing nomination forms in the CSC's mailbox in the MathSoc office, or by writing the nomination in a place in the CSC office to be specified by the CRO.
a. A nomination shall consist of the nominee's userid, and post(s) nominated for. Nominees must be full members of the Computer Science Club. A member may decline a nomination at any point prior to the taking of the vote.
a. The election shall commence with the offering of memberships for sale. After a reasonable time, control of the meeting is given to the CRO who will preside over the election of the President, Vice-President, Treasurer, and Secretary, in that order.
a. During each election, if the position has no nominees, the CRO will take nominations from the floor. Any present, eligible member can be nominated.
a. Each election shall be carried out by secret vote, in a manner to be decided on by the CRO, with the approval of the members at the meeting. A simple heads-down-hands-up method is considered acceptable.
a. The CRO shall not vote except to break a tie.
a. The CRO may, if feasible, accept absentee ballots from full members. No absentee vote from a member shall be counted if the member is present at the time the vote is taken. The CRO shall make a best effort to ensure that absentee ballots are compatible with the method of voting chosen; if this is not possible (for instance, if the CRO is overruled by the membership), then the absentee votes shall not be counted.
a. Immediately after the vote is taken, the CRO will announce the results of the election and the winner will be removed from subsequent contests. If, due to lack of candidates (because there were no nominations, or candidates withdrew or were eliminated), there is no one elected to an office, then the members at the meeting will decide whether or not to hold extra elections in accordance with the procedure for vacancies. If they choose not to, this does not prevent the Executive or a group of members from calling extra elections later in the term in accordance with the usual vacancy provisions.
1. Before the end of the prior term, the then-Executive shall choose a willing Chief Returning Officer, who is responsible for carrying out elections according to this procedure.
1. The CRO shall set the date and time of the election meeting, and set the nomination period. The nomination shall be at least one week long and shall end at least 24 hours before the start of the election meeting.
1. Announcements of the election and the nomination procedure must be distributed to all members by the members' mailing list, and should also be advertised by posters in the MC building.
1. During the nomination period, the Chief Returning Officer (CRO) shall be available to receive nominations for the posts of officers of the club, either in person, by email, by depositing nomination forms in the CSC's mailbox in the MathSoc office, or by writing the nomination in a place in the CSC office to be specified by the CRO.
1. A nomination shall consist of the nominee's userid, and post(s) nominated for. Nominees must be full members of the Computer Science Club. A member may decline a nomination at any point prior to the taking of the vote.
1. The election shall commence with the offering of memberships for sale. After a reasonable time, control of the meeting is given to the CRO who will preside over the election of the President, Vice-President, Treasurer, and Secretary, in that order.
1. During each election, if the position has no nominees, the CRO will take nominations from the floor. Any present, eligible member can be nominated.
1. Each election shall be carried out by secret vote, in a manner to be decided on by the CRO, with the approval of the members at the meeting. A simple heads-down-hands-up method is considered acceptable.
1. The CRO shall not vote except to break a tie.
1. The CRO may, if feasible, accept absentee ballots from full members. No absentee vote from a member shall be counted if the member is present at the time the vote is taken. The CRO shall make a best effort to ensure that absentee ballots are compatible with the method of voting chosen; if this is not possible (for instance, if the CRO is overruled by the membership), then the absentee votes shall not be counted.
1. Immediately after the vote is taken, the CRO will announce the results of the election and the winner will be removed from subsequent contests. If, due to lack of candidates (because there were no nominations, or candidates withdrew or were eliminated), there is no one elected to an office, then the members at the meeting will decide whether or not to hold extra elections in accordance with the procedure for vacancies. If they choose not to, this does not prevent the Executive or a group of members from calling extra elections later in the term in accordance with the usual vacancy provisions.
1. Following the elections, it is the responsibility of the new executive to select a System Administrator. The selection of System Administrator must then be ratified by the members at the meeting. If a suitable System Administrator is not available, then the executive may delay their selection until one becomes available. In this case the selection of System Administrator must be ratified at the next meeting of the Club.
1. Any two offices may be held by a single person with the approval of the President (if any), and the explicit approval of the members.
1. In the case of a resignation of an officer or officers, including the President, or if a vacancy occurs for any other reason, the Executive, members at a meeting, or any ten (10) members may call extra elections to replace such officer(s). If extra elections are held, they are held for all vacant offices.

View File

@ -1,10 +1,10 @@
---
title: 2. Purpose
title: Purpose
index: 2
---
1. The Club is organized and will be operated exclusively for educational and scientific purposes in furtherance of:
a. promoting an increased knowledge of computer science and its applications;
a. providing a means of communication between persons having interest in computer science.
a. promoting a greater interest in computer science and its applications; and
1. The above purposes will be fulfilled by the organization of discussions and lectures with professionals and academics in the field of computer science and related fields, the maintenance of a library of materials related to computer science, the maintenance of an office containing the library as an aid to aim (1.c) above, and such other means as decided by the club membership.
1. promoting an increased knowledge of computer science and its applications;
1. providing a means of communication between persons having interest in computer science.
1. promoting a greater interest in computer science and its applications; and
1. The above purposes will be fulfilled by the organization of discussions and lectures with professionals and academics in the field of computer science and related fields, the maintenance of a library of materials related to computer science, the maintenance of an office containing the library as an aid to aim (1.3) above, and such other means as decided by the club membership.

View File

@ -1,5 +1,5 @@
---
title: 13. Use of Club Resources
title: Use of Club Resources
index: 13
---

View File

@ -80,7 +80,7 @@ University of Waterloo <br />
Waterloo, ON N2L 3G1 <br />
Canada
Our office phone number is [(519) 888-4567 x33870](tel:+15198884567,33870)
Our office phone number is [(519) 888-4567 x33870](tel:+15198884567,33870).
</address>

View File

@ -1,6 +1,6 @@
**Everyone at the University of Waterloo is welcome to come to our events and to
use our resources!** Feel free to join our communities and chat with our
members. However, if you wanted to officially become a member or support our
members. However, if you want to officially become a member or support our
vision of creating a supportive environment for all computing students, there's
a bunch of ways you can join and help out.
@ -35,12 +35,12 @@ University of Waterloo email address with the following:
1. a scan or photograph copy of your **WatCard**,
2. your **WatIAM userid**, and
3. your acknowledgement of having read, understood, and agreeing with our 
3. your acknowledgement of having read, understood, and agreeing with our
[Machine Usage Agreement](/resources/machine-usage-agreement).
#### Membership Renewal
For this online term, you do not need to pay the $2 fee to renew your
For this online term (Spring 2021), you do not need to pay the $2 fee to renew your
membership. We have extended the memberships of all members who had already
previously paid for membership or have joined CS Club during an online term.
@ -62,18 +62,18 @@ social media to keep up to date on when applications open!
#### Website Committee
- Creates functional and modern design for the CSC website.
- Creates functional and modern designs for the CSC website.
- Builds and maintains the static website, updating content for events and news.
#### Systems Committee
- Maintaining all services that CSC provides which includes file share, DNS,
mail, configuration for IRC, Mattermost, Git hosting.
- Managing mirrors used by large public organizations and 1000s of people
- Managing mirrors used by large public organizations and thousands of people
internationally.
### Elected Roles
Each term the CSC holds elections to determine the executive council.
Each term, the CSC holds elections to determine the executive council:
- President
- Vice-President

View File

@ -5,11 +5,8 @@
},
{
"name": "Andrew Wang",
"role": "Member"
},
{
"name": "Bill Xiang",
"role": "Member"
"role": "Member",
"image": "/images/team/AndrewWang-Syscom.jpg"
},
{
"name": "Raymond Li",

View File

@ -22,7 +22,9 @@ export async function getExecNames() {
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 = await getMemberImagePath(metadata.name);
const image =
(metadata.image as string | undefined) ??
(await getMemberImagePath(metadata.name));
return {
content: convert ? await serialize(content) : content,

View File

@ -4,7 +4,7 @@ import {
createSectionGetStaticProps,
} from "@/components/OrganizedContent/static";
import { options } from "../code-of-conduct";
import { options } from "./";
export default createSectionPage(options);

View File

@ -1,9 +1,12 @@
import path from "path";
import { createReadAllPage } from "@/components/OrganizedContent/ReadAll";
import {
createReadAllPage,
Options,
} from "@/components/OrganizedContent/ReadAll";
import { createReadAllGetStaticProps } from "@/components/OrganizedContent/static";
export const options = {
export const options: Options = {
title: "Code of Conduct",
image: "images/code-of-conduct.svg",
pagePath: path.join("about", "code-of-conduct"),

View File

@ -4,7 +4,7 @@ import {
createSectionGetStaticProps,
} from "@/components/OrganizedContent/static";
import { options } from "../constitution";
import { options } from "./";
export default createSectionPage(options);

View File

@ -1,12 +1,16 @@
import path from "path";
import { createReadAllPage } from "@/components/OrganizedContent/ReadAll";
import {
createReadAllPage,
Options,
} from "@/components/OrganizedContent/ReadAll";
import { createReadAllGetStaticProps } from "@/components/OrganizedContent/static";
export const options = {
export const options: Options = {
title: "Constitution",
image: "images/constitution.svg",
pagePath: path.join("about", "constitution"),
numberedSections: true,
};
export default createReadAllPage(options);

View File

@ -8,6 +8,7 @@ import {
GetShapesConfig,
mobileShapesConfig,
} from "@/components/ShapesBackground";
import { Title } from "@/components/Title";
import Content from "../../content/about/index.mdx";
@ -16,6 +17,7 @@ import styles from "./index.module.css";
export default function AboutUs() {
return (
<>
<Title>About</Title>
<div className={styles.titleContainer}>
<h1 className={styles.title}>About Us!</h1>
<Image src="/images/about-us.svg" className={styles.codey} />

View File

@ -1,6 +1,7 @@
import React from "react";
import { Image } from "@/components/Image";
import { Title } from "@/components/Title";
import Content from "../../content/about/our-supporters.mdx";
@ -9,6 +10,7 @@ import styles from "./our-supporters.module.css";
export default function OurSupporters() {
return (
<>
<Title>Our Supporters</Title>
<div className={styles.headerContainer}>
<h1 className={styles.header}>Our Supporters</h1>
<Image src="images/our-supporters/codey.svg" className={styles.codey} />

View File

@ -8,6 +8,7 @@ import { Image } from "@/components/Image";
import { Link } from "@/components/Link";
import { TeamMember } from "@/components/TeamMember";
import { TeamMemberCard } from "@/components/TeamMemberCard";
import { Title } from "@/components/Title";
import {
getExec,
getExecNames,
@ -36,6 +37,7 @@ interface Props {
export default function Team({ execs, programme, website, systems }: Props) {
return (
<>
<Title>Team</Title>
<DefaultLayout>
<div className={styles.headerContainer}>
<div className={styles.headerTextContainer}>
@ -85,7 +87,7 @@ export default function Team({ execs, programme, website, systems }: Props) {
To find out when and where the next elections will be held, keep an
eye on on the <Link href="/#news">News</Link>. <br />
For details on the elections, read our
<Link href="/about/constitution"> Constitution</Link>
<Link href="/about/constitution"> Constitution</Link>.
</Bubble>
</div>
</>
@ -110,10 +112,12 @@ function MembersList(props: MembersProps) {
);
}
async function getTeamWithImages(team: Omit<Metadata, "image">[]) {
type TeamMember = Omit<Metadata, "image"> & { image?: string };
async function getTeamWithImages(team: TeamMember[]) {
return await Promise.all(
team.map(async (member) => {
const image = await getMemberImagePath(member.name);
const image = member.image ?? (await getMemberImagePath(member.name));
return {
...member,
image,

View File

@ -5,6 +5,7 @@ import { MDXRemote } from "next-mdx-remote";
import React from "react";
import { EventCard } from "@/components/EventCard";
import { Title } from "@/components/Title";
import {
Event,
getEventYears,
@ -12,20 +13,26 @@ import {
getEventsByTerm,
getEventBySlug,
} from "@/lib/events";
import { capitalize } from "@/utils";
export default function EventInfoPage(props: Props) {
export default function EventInfoPage({ year, term, event }: Props) {
return (
<>
<Title>{[event.metadata.name, `${capitalize(term)} ${year}`]}</Title>
<EventCard
{...props.event.metadata}
date={new Date(props.event.metadata.date)}
{...event.metadata}
date={new Date(event.metadata.date)}
showDescription
>
<MDXRemote {...props.event.content} />
<MDXRemote {...event.content} />
</EventCard>
</>
);
}
interface Props {
year: string;
term: string;
event: Event;
}
@ -40,7 +47,9 @@ export const getStaticProps: GetStaticProps<Props, Params> = async (
) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const { year, term, event } = context.params!;
return { props: { event: await getEventBySlug(year, term, event) } };
return {
props: { year, term, event: await getEventBySlug(year, term, event) },
};
};
export const getStaticPaths: GetStaticPaths<Params> = async () => {

View File

@ -3,15 +3,20 @@
margin-bottom: calc(60rem / 16);
}
.main > h2 {
padding-bottom: 1rem;
border-bottom: 1px solid var(--primary-heading);
.main > h1, .main > section > h1 {
padding-bottom: calc(16rem / 16);
border-bottom: calc(1rem / 16) solid var(--primary-heading);
}
.header {
display: flex;
flex-wrap: wrap;
}
.header a {
color: var(--text);
font-size: calc(18rem / 16);
margin-right: calc(30rem / 16);
margin-right: 1rem;
}
.header a .curTerm {

View File

@ -7,6 +7,7 @@ import React from "react";
import { EventCard } from "@/components/EventCard";
import { Link } from "@/components/Link";
import { MiniEventCard } from "@/components/MiniEventCard";
import { Title } from "@/components/Title";
import {
Event,
getEventsPageProps,
@ -54,6 +55,7 @@ export default function Term(props: Props) {
return (
<div className={styles.main}>
<Title>{["Events", `${capitalize(props.term)} ${props.year}`]}</Title>
<div className={styles.header}>
{headerTerms.map((link) => (
<HeaderLink
@ -65,8 +67,8 @@ export default function Term(props: Props) {
<Link href="/events/archive">Archive</Link>
</div>
{hasFutureEvents && (
<>
<h2>Upcoming Events</h2>
<section>
<h1>Upcoming Events</h1>
<div className={styles.miniEventCards}>
{props.futureEvents.map(({ content, metadata }) => (
<EventCard
@ -79,20 +81,34 @@ export default function Term(props: Props) {
</EventCard>
))}
</div>
</>
</section>
)}
{hasPastEvents && props.isCurrentTerm && (
<section>
<h1>Past Events</h1>
<div className={styles.miniEventCards}>
{props.pastEvents.map(({ content, metadata }) => (
<MiniEventCard
{...metadata}
date={new Date(metadata.date)}
description={<MDXRemote {...content} />}
key={metadata.name + metadata.date.toString()}
/>
))}
</div>
</section>
)}
{hasPastEvents && props.isCurrentTerm && <h2>Past Events</h2>}
{hasPastEvents && !props.isCurrentTerm && (
<h2>
<h1>
Events Archive:
<span className={styles.blue}>
{` ${capitalize(props.term)} ${props.year}`}
</span>
</h2>
</h1>
)}
{!hasFutureEvents && !hasPastEvents && (
<>
<h2>Events</h2>
<h1>Events</h1>
There are no upcoming or past events for the{" "}
{`${capitalize(props.term)} ${props.year}`} term. Please check back
later!

View File

@ -2,9 +2,9 @@
margin-top: calc(60rem / 16);
}
.main > h2 {
padding-bottom: calc(1rem / 16);
border-bottom: 1px solid var(--primary-heading);
.main > h1 {
padding-bottom: calc(16rem / 16);
border-bottom: calc(1rem / 16) solid var(--primary-heading);
}
.blue {

View File

@ -4,6 +4,7 @@ import { GetStaticPaths, GetStaticProps } from "next";
import React from "react";
import { Link } from "@/components/Link";
import { Title } from "@/components/Title";
import { getEventYears, getEventTermsByYear } from "@/lib/events";
import styles from "./index.module.css";
@ -16,6 +17,7 @@ interface Props {
export default function Year(props: Props) {
return (
<div className={styles.main}>
<Title>{["Events", props.year]}</Title>
<h2>
Events Archive:<span className={styles.blue}>{` ${props.year}`}</span>
</h2>

View File

@ -2,7 +2,7 @@ import { GetStaticProps } from "next";
import { getCurrentTerm, getEventsPageProps } from "@/lib/events";
import Term, { Props } from "./[year]/[term]/index";
import Term, { Props } from "./[year]/[term]";
export default Term;

View File

@ -34,6 +34,10 @@
font-weight: 600;
}
.content summary {
cursor: pointer;
}
.content details > * {
padding-left: 1rem;
}

View File

@ -3,6 +3,7 @@ import React from "react";
import { ConnectWithUs } from "@/components/ConnectWithUs";
import { EmailSignup } from "@/components/EmailSignup";
import { Image } from "@/components/Image";
import { Title } from "@/components/Title";
import Content from "../content/get-involved.mdx";
@ -11,6 +12,7 @@ import styles from "./get-involved.module.css";
export default function GetInvolved() {
return (
<div className={styles.page}>
<Title>Get Involved</Title>
<header>
<div className={styles.headerText}>
<h1>Get Involved!</h1>

View File

@ -11,6 +11,7 @@ import { Link } from "@/components/Link";
import { NewsCard } from "@/components/NewsCard";
import { GetShapesConfig } from "@/components/ShapesBackground";
import { SocialLinks } from "@/components/SocialLinks";
import { Title } from "@/components/Title";
import { Event, getUpcomingEvents } from "@/lib/events";
import { News, getRecentNews } from "@/lib/news";
@ -25,6 +26,7 @@ interface Props {
export default function Home(props: Props) {
return (
<>
<Title>{[]}</Title>
<DefaultLayout>
<header className={styles.intro}>
<div className={styles.introTop} />

View File

@ -2,6 +2,11 @@
padding-bottom: calc(30rem / 16);
}
.page > h1 {
padding-bottom: calc(16rem / 16);
border-bottom: calc(1rem / 16) solid var(--primary-heading);
}
.term {
color: var(--primary-accent);
}

View File

@ -10,6 +10,7 @@ import {
defaultGetShapesConfig,
GetShapesConfig,
} from "@/components/ShapesBackground";
import { Title } from "@/components/Title";
import {
getNewsBySlug,
getNewsByTerm,
@ -30,6 +31,7 @@ interface Props {
export default function TermNews({ year, term, news }: Props) {
return (
<div className={styles.page}>
<Title>{["News", `${capitalize(term)} ${capitalize(year)}`]}</Title>
<h1>
News Archive:{" "}
<span className={styles.term}>

View File

@ -1,13 +1,18 @@
import React from "react";
import { Title } from "@/components/Title";
import Content from "../../../content/advice/academic-advice.mdx";
import { Advice } from "./coop";
export default function AcademicAdvice() {
return (
<>
<Title>Academic Advice</Title>
<Advice>
<Content />
</Advice>
</>
);
}

View File

@ -3,6 +3,7 @@ import { useRouter } from "next/router";
import React, { ReactNode } from "react";
import { Image } from "@/components/Image";
import { Title } from "@/components/Title";
import Content from "../../../content/advice/coop-advice.mdx";
@ -10,9 +11,12 @@ import styles from "./coop.module.css";
export default function CoopAdvice() {
return (
<>
<Title>Co-op Advice</Title>
<Advice>
<Content />
</Advice>
</>
);
}

View File

@ -1,13 +1,18 @@
import React from "react";
import { Title } from "@/components/Title";
import Content from "../../../content/advice/misc-advice.mdx";
import { Advice } from "./coop";
export default function MiscAdvice() {
return (
<>
<Title>Additional Advice</Title>
<Advice>
<Content />
</Advice>
</>
);
}

View File

@ -4,7 +4,7 @@ import {
createSectionGetStaticProps,
} from "@/components/OrganizedContent/static";
import { options } from "../machine-usage-agreement";
import { options } from "./";
export default createSectionPage(options);

View File

@ -4,7 +4,7 @@ import {
createSectionGetStaticProps,
} from "@/components/OrganizedContent/static";
import { options } from "../services";
import { options } from "./";
export default createSectionPage(options);

View File

@ -5,10 +5,12 @@ import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote";
import React from "react";
import { TechTalkCard } from "@/components/TechTalkCard";
import { Title } from "@/components/Title";
import { getTechTalk, getTechTalkNames, Metadata } from "@/lib/tech-talks";
import { Header } from "../tech-talks";
import styles from "../tech-talks.module.css";
import { Header } from "./";
import styles from "./index.module.css";
interface Props {
content: MDXRemoteSerializeResult;
@ -18,6 +20,7 @@ interface Props {
export default function TechTalk({ content, metadata }: Props) {
return (
<div className={styles.page}>
<Title>{[metadata.title, "Tech Talks"]}</Title>
<Header />
<TechTalkCard
{...metadata}

View File

@ -3,9 +3,10 @@ import React from "react";
import { Image } from "@/components/Image";
import { MiniTechTalkCard } from "@/components/MiniTechTalkCard";
import { Title } from "@/components/Title";
import { getTechTalks, Metadata } from "@/lib/tech-talks";
import styles from "./tech-talks.module.css";
import styles from "./index.module.css";
interface Props {
talks: Metadata[];
@ -14,6 +15,7 @@ interface Props {
export default function TechTalks({ talks }: Props) {
return (
<div className={styles.page}>
<Title>Tech Talks</Title>
<Header />
<div className={styles.miniCards}>
{talks.map((talk) => (

View File

@ -3,6 +3,7 @@ import React from "react";
import { Button } from "@/components/Button";
import { Input } from "@/components/Input";
import { useThemeContext, emptyPalette } from "@/components/Theme";
import { Title } from "@/components/Title";
import styles from "./themer.module.css";
@ -12,6 +13,7 @@ export default function Themer() {
return (
<main className={styles.page}>
<Title>Themer</Title>
<h1>Themer</h1>
<form onSubmit={(event) => event.preventDefault()}>
<div className={styles.controls}>
@ -72,7 +74,7 @@ export default function Themer() {
</div>
);
})}
</div>{" "}
</div>
</form>
</main>
);

8178
public/events.atom Normal file

File diff suppressed because it is too large Load Diff

5696
public/events.ics Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 KiB

2850
public/news.atom Normal file

File diff suppressed because it is too large Load Diff