commit
bd7df3de6a
@ -1,7 +1,71 @@ |
||||
.bubble { |
||||
.container { |
||||
position: relative; |
||||
padding: calc(36rem / 16) 0; |
||||
overflow-x: clip; |
||||
} |
||||
|
||||
.bubble { |
||||
--border-radius: calc(5000rem / 16); |
||||
|
||||
display: flex; |
||||
flex-direction: row; |
||||
position: absolute; |
||||
top: 0; |
||||
height: 100%; |
||||
width: 100%; |
||||
justify-content: center; |
||||
align-items: flex-start; |
||||
} |
||||
|
||||
.bubble:nth-child(odd) { |
||||
.bar { |
||||
height: 100%; |
||||
width: 100%; |
||||
} |
||||
|
||||
.decoration { |
||||
display: none; |
||||
width: calc(128rem / 16); |
||||
} |
||||
|
||||
.margin { |
||||
display: none; |
||||
} |
||||
|
||||
.content { |
||||
position: relative; |
||||
z-index: 1; |
||||
} |
||||
|
||||
.container:nth-child(odd) .bar { |
||||
background-color: var(--primary-accent-light); |
||||
} |
||||
|
||||
@media only screen and (min-width: calc(1350rem / 16)) { |
||||
.container:nth-child(odd) .decoration { |
||||
display: block; |
||||
position: absolute; |
||||
} |
||||
|
||||
.container:nth-child(4n + 1) .bar { |
||||
border-top-right-radius: var(--border-radius); |
||||
border-bottom-right-radius: var(--border-radius); |
||||
transform: translateX(-12.5vw); |
||||
} |
||||
|
||||
.container:nth-child(4n + 1) .decoration { |
||||
top: calc(-50rem / 16); |
||||
right: 8vw; |
||||
} |
||||
|
||||
.container:nth-child(4n + 3) .bar { |
||||
border-top-left-radius: var(--border-radius); |
||||
border-bottom-left-radius: var(--border-radius); |
||||
transform: translateX(12.5vw); |
||||
} |
||||
|
||||
.container:nth-child(4n + 3) .decoration { |
||||
top: calc(-50rem / 16); |
||||
left: 8vw; |
||||
transform: rotateY(180deg); |
||||
} |
||||
} |
||||
|
@ -1,13 +1,24 @@ |
||||
import React from "react"; |
||||
|
||||
import { Image } from "@/components/Image"; |
||||
|
||||
import { DefaultLayout } from "./DefaultLayout"; |
||||
|
||||
import styles from "./Bubble.module.css"; |
||||
|
||||
export default function Bubble(props: { children: React.ReactNode }) { |
||||
export function Bubble(props: { children: React.ReactNode }) { |
||||
return ( |
||||
<div className={styles.bubble}> |
||||
<DefaultLayout>{props.children}</DefaultLayout> |
||||
<div className={styles.container}> |
||||
<div className={styles.bubble} aria-hidden> |
||||
<div className={styles.bar} /> |
||||
<Image |
||||
className={styles.decoration} |
||||
src="/images/bubble-decoration.svg" |
||||
/> |
||||
</div> |
||||
<div className={styles.content}> |
||||
<DefaultLayout>{props.children}</DefaultLayout> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
@ -0,0 +1,7 @@ |
||||
.line { |
||||
display: block; |
||||
margin: calc(1rem / 16) 0 calc(34rem / 16); |
||||
height: calc(1rem / 16); |
||||
border: none; |
||||
background-color: var(--primary-heading); |
||||
} |
@ -0,0 +1,7 @@ |
||||
import React from "react"; |
||||
|
||||
import styles from "./HorizontalLine.module.css"; |
||||
|
||||
export function HorizontalLine() { |
||||
return <hr className={styles.line} />; |
||||
} |
@ -0,0 +1,37 @@ |
||||
.page { |
||||
margin-top: calc(60rem / 16); |
||||
margin-bottom: calc(40rem / 16); |
||||
} |
||||
|
||||
.headerContainer { |
||||
display: flex; |
||||
flex-direction: row; |
||||
align-items: flex-end; |
||||
padding-bottom: 1rem; |
||||
border-bottom: calc(1rem / 16) solid var(--primary-heading); |
||||
} |
||||
|
||||
.header { |
||||
line-height: 1; |
||||
color: var(--primary-heading); |
||||
font-size: calc(48rem / 16); |
||||
margin: 0 0 0 calc(36rem / 16); |
||||
text-align: center; |
||||
} |
||||
|
||||
@media only screen and (max-width: calc(768rem / 16)) { |
||||
.headerContainer { |
||||
flex-direction: column; |
||||
align-items: center; |
||||
border: none; |
||||
} |
||||
|
||||
.header { |
||||
font-size: calc(24rem / 16); |
||||
margin: 1.5rem 0 0 0; |
||||
} |
||||
|
||||
.headerImage { |
||||
width: calc(100rem / 16); |
||||
} |
||||
} |
@ -0,0 +1,23 @@ |
||||
import React, { ReactNode } from "react"; |
||||
|
||||
import { Image } from "@/components/Image"; |
||||
|
||||
import styles from "./Header.module.css"; |
||||
|
||||
export interface Props { |
||||
title: string; |
||||
image: string; |
||||
children: ReactNode; |
||||
} |
||||
|
||||
export function Header({ title, image, children }: Props) { |
||||
return ( |
||||
<main className={styles.page}> |
||||
<header className={styles.headerContainer}> |
||||
<Image src={image} className={styles.headerImage} /> |
||||
<h1 className={styles.header}>{title}</h1> |
||||
</header> |
||||
{children} |
||||
</main> |
||||
); |
||||
} |
@ -0,0 +1,61 @@ |
||||
import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote"; |
||||
import React, { ComponentType } from "react"; |
||||
|
||||
import { |
||||
createLink, |
||||
createReadAllSection, |
||||
LinkProps, |
||||
OrganizedContent, |
||||
} from "@/components/OrganizedContent"; |
||||
|
||||
import { Header } from "./Header"; |
||||
|
||||
export interface SerializedSection { |
||||
section: { |
||||
id: string; |
||||
title: string; |
||||
}; |
||||
content: MDXRemoteSerializeResult; |
||||
} |
||||
|
||||
export interface Props { |
||||
sections: SerializedSection[]; |
||||
} |
||||
|
||||
export interface Options { |
||||
pagePath: string; |
||||
title: string; |
||||
image: string; |
||||
link?: ComponentType<LinkProps>; |
||||
} |
||||
|
||||
export function createReadAllPage({ title, image, pagePath, link }: Options) { |
||||
const Link = link ?? createLink(pagePath); |
||||
|
||||
return function Page({ sections }: Props) { |
||||
const readAllSection = createReadAllSection( |
||||
sections.map(({ section, content }) => ({ |
||||
section, |
||||
Content() { |
||||
return <MDXRemote {...content} />; |
||||
}, |
||||
})), |
||||
true |
||||
); |
||||
|
||||
return ( |
||||
<Header title={title} image={image}> |
||||
<OrganizedContent |
||||
id={readAllSection.section.id} |
||||
sections={[ |
||||
readAllSection.section, |
||||
...sections.map(({ section }) => section), |
||||
]} |
||||
link={Link} |
||||
> |
||||
<readAllSection.Content /> |
||||
</OrganizedContent> |
||||
</Header> |
||||
); |
||||
}; |
||||
} |
@ -0,0 +1,46 @@ |
||||
import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote"; |
||||
import React, { ComponentType } from "react"; |
||||
|
||||
import { |
||||
createLink, |
||||
LinkProps, |
||||
OrganizedContent, |
||||
} from "@/components/OrganizedContent"; |
||||
|
||||
import { Header } from "./Header"; |
||||
|
||||
interface Section { |
||||
id: string; |
||||
title: string; |
||||
} |
||||
|
||||
export interface Props { |
||||
content: MDXRemoteSerializeResult; |
||||
sections: Section[]; |
||||
current: number; |
||||
} |
||||
|
||||
export interface Options { |
||||
title: string; |
||||
pagePath: string; |
||||
image: string; |
||||
link?: ComponentType<LinkProps>; |
||||
} |
||||
|
||||
export function createSectionPage({ title, image, pagePath, link }: Options) { |
||||
const Link = link ?? createLink(pagePath); |
||||
|
||||
return function Page(this: void, { content, sections, current }: Props) { |
||||
return ( |
||||
<Header title={title} image={image}> |
||||
<OrganizedContent |
||||
sections={sections} |
||||
id={sections[current].id} |
||||
link={Link} |
||||
> |
||||
<MDXRemote {...content} /> |
||||
</OrganizedContent> |
||||
</Header> |
||||
); |
||||
}; |
||||
} |
@ -0,0 +1,69 @@ |
||||
import { ParsedUrlQuery } from "querystring"; |
||||
|
||||
import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next"; |
||||
|
||||
import { createReadAllSection } from "@/components/OrganizedContent"; |
||||
import { |
||||
getSectionNamesForPage, |
||||
getSectionsForPage, |
||||
} from "@/lib/organized-content"; |
||||
|
||||
import { Props as ReadAllProps } from "./ReadAll"; |
||||
import { Props as SectionProps } from "./Section"; |
||||
|
||||
export function createReadAllGetStaticProps(pagePath: string) { |
||||
return (async () => { |
||||
const sections = await getSectionsForPage(pagePath); |
||||
|
||||
return { |
||||
props: { |
||||
sections: sections.map(({ name: id, data: { title, content } }) => ({ |
||||
section: { |
||||
id, |
||||
title, |
||||
}, |
||||
content, |
||||
})), |
||||
}, |
||||
}; |
||||
}) as GetStaticProps<ReadAllProps>; |
||||
} |
||||
|
||||
interface SectionParams extends ParsedUrlQuery { |
||||
section: string; |
||||
} |
||||
|
||||
export function createSectionGetStaticProps(pagePath: string) { |
||||
return async function getStaticProps( |
||||
context: GetStaticPropsContext<SectionParams> |
||||
) { |
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const currentName = context.params!.section; |
||||
const fullSections = await getSectionsForPage(pagePath); |
||||
const current = fullSections.findIndex(({ name }) => name === currentName); |
||||
|
||||
const sections = fullSections.map(({ name, data: { title } }) => ({ |
||||
id: name, |
||||
title, |
||||
})); |
||||
|
||||
return { |
||||
props: { |
||||
content: fullSections[current].data.content, |
||||
current: current + 1, |
||||
sections: [createReadAllSection(sections, false), ...sections], |
||||
}, |
||||
}; |
||||
} as GetStaticProps<SectionProps, SectionParams>; |
||||
} |
||||
|
||||
export function createSectionGetStaticPaths(pagePath: string) { |
||||
return async function getStaticPaths() { |
||||
const names = await getSectionNamesForPage(pagePath); |
||||
|
||||
return { |
||||
paths: names.map((section) => ({ params: { section } })), |
||||
fallback: false, |
||||
}; |
||||
} as GetStaticPaths<SectionParams>; |
||||
} |
@ -1,29 +1,98 @@ |
||||
import React from "react"; |
||||
import React, { useState } from "react"; |
||||
|
||||
import { useWindowDimension } from "@/hooks/useWindowDimension"; |
||||
|
||||
import { Image } from "./Image"; |
||||
|
||||
import styles from "./TeamMemberCard.module.css"; |
||||
|
||||
interface TeamMemberCardProps { |
||||
export interface TeamMemberCardProps { |
||||
name: string; |
||||
role: string; |
||||
image?: string; // path to image of person, relative to public directory
|
||||
image: string; |
||||
children: React.ReactNode; |
||||
} |
||||
|
||||
export function TeamMemberCard(props: TeamMemberCardProps) { |
||||
interface TeamMemberInfoProps extends TeamMemberCardProps { |
||||
isPopup?: boolean; |
||||
} |
||||
|
||||
function TeamMemberInfo({ |
||||
name, |
||||
role, |
||||
image, |
||||
children, |
||||
isPopup = false, |
||||
}: TeamMemberInfoProps) { |
||||
return ( |
||||
<article className={styles.card}> |
||||
<> |
||||
<div className={styles.picture}> |
||||
<Image |
||||
className={styles.image} |
||||
src={props.image ?? "/images/team-member-placeholder.svg"} |
||||
alt={`Picture of ${props.name}`} |
||||
className={isPopup ? styles.popupImage : styles.image} |
||||
src={image} |
||||
alt={`Picture of ${name}`} |
||||
/> |
||||
</div> |
||||
<h1 className={styles.name}>{props.name}</h1> |
||||
<h2 className={styles.role}>{props.role}</h2> |
||||
<div className={styles.description}>{props.children}</div> |
||||
</article> |
||||
<h1 className={isPopup ? styles.popupName : styles.name}>{name}</h1> |
||||
<h2 className={isPopup ? styles.popupRole : styles.role}>{role}</h2> |
||||
<div className={isPopup ? styles.popupDescription : styles.description}> |
||||
{children} |
||||
</div> |
||||
</> |
||||
); |
||||
} |
||||
|
||||
export function TeamMemberCard({ |
||||
name, |
||||
role, |
||||
image, |
||||
children, |
||||
}: TeamMemberCardProps) { |
||||
const { width } = useWindowDimension(); |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
const handleClick = () => { |
||||
if (isOpen || width <= 768) { |
||||
setIsOpen(!isOpen); |
||||
} |
||||
}; |
||||
return ( |
||||
<> |
||||
<article className={styles.card} onClick={handleClick}> |
||||
<TeamMemberInfo {...{ name, role, image }}>{children}</TeamMemberInfo> |
||||
</article> |
||||
|
||||
{isOpen && ( |
||||
<ExecPopup |
||||
name={name} |
||||
role={role} |
||||
image={image} |
||||
handleClick={handleClick} |
||||
> |
||||
{children} |
||||
</ExecPopup> |
||||
)} |
||||
</> |
||||
); |
||||
} |
||||
|
||||
interface Propup extends TeamMemberCardProps { |
||||
handleClick: () => void; |
||||
} |
||||
|
||||
function ExecPopup({ name, role, image, children, handleClick }: Propup) { |
||||
return ( |
||||
<> |
||||
<div className={styles.popupBackground} onClick={handleClick} /> |
||||
<div className={styles.popupContainer}> |
||||
<button className={styles.closeBtn} onClick={handleClick}> |
||||
<Image src="images/team/popup-close.svg" /> |
||||
</button> |
||||
<div className={styles.popupContent}> |
||||
<TeamMemberInfo {...{ name, role, image }} isPopup={true}> |
||||
{children} |
||||
</TeamMemberInfo> |
||||
</div> |
||||
</div> |
||||
</> |
||||
); |
||||
} |
||||
|
@ -0,0 +1,9 @@ |
||||
--- |
||||
title: Addressing Grievances |
||||
index: 6 |
||||
--- |
||||
|
||||
If either the complainant or the subject disagree with the decision made by the Handling Officer, they can appeal to the Officers, who can overturn the decision with a majority vote of all the Officers. |
||||
|
||||
No Officer who was personally involved in the complaint, or is in a close relationship with someone involved in the complaint, shall participate in the Officers deliberation or vote on the appeal. |
||||
If the subject of a complaint is expelled from the Club, then at their request, but no more often than once a year, the Officers will review the decision to expel them from the Club. The Officers can reinstate the subject with a two-thirds vote of the Officers. |
@ -0,0 +1,13 @@ |
||||
--- |
||||
title: Consequences of Inappropriate Behaviour |
||||
index: 5 |
||||
--- |
||||
|
||||
After having done so, the Handling Officer shall use their best judgment to determine if the complaint is valid and, if so, determine with the relevant Officers the appropriate action to ensure that the complainant feels welcome in the Computer Science Club and to avoid a subsequent incident: |
||||
|
||||
- A warning. |
||||
- A suspension from the events and spaces governed by the Code of Conduct until the beginning of the next term. If the suspension would come into effect less than two full weeks from the end of classes in the current term, then the suspension applies to the subsequent term as well. |
||||
- If the incident is very serious, or the subject has a pattern of similar offences, expulsion from the Club. |
||||
- A formal complaint through University policy, such as 33, 34, and 42. |
||||
|
||||
The Handling Officer shall inform the complainant of the resolution of the issue and inform both the complainant and the subject of their right to appeal the decision. |
@ -0,0 +1,10 @@ |
||||
--- |
||||
title: Expected Behaviour |
||||
index: 2 |
||||
--- |
||||
|
||||
- Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this Club. |
||||
- Exercise consideration and respect in your speech and actions. |
||||
- Attempt collaboration before conflict. |
||||
- Refrain from demeaning, discriminatory, or harassing behaviour and speech. |
||||
- Be mindful of your surroundings and of your fellow participants. |
@ -0,0 +1,13 @@ |
||||
--- |
||||
title: Purpose |
||||
index: 1 |
||||
--- |
||||
|
||||
One of the primary goals of the Computer Science Club of the University of Waterloo is the inclusion and support of all members of the University of Waterloo community who are interested in Computer Science. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sex, sexual orientation, ability, ethnicity, socioeconomic status, age, and religion or lack thereof. |
||||
|
||||
We invite all those who participate in our events and who communicate with our Club at large to help us create a safe and positive experience for everyone involved. |
||||
|
||||
- The Code of Conduct highlights our expectations for all individuals who participate in our Club, as well as the steps to handle unacceptable behaviour. |
||||
- The Code of Conduct should be signed by new Club members. |
||||
- The Code of Conduct is in addition to existing University Policies, such as [policies 33](https://uwaterloo.ca/secretariat/policies-procedures-guidelines/policy-33), [34](https://uwaterloo.ca/secretariat/policies-procedures-guidelines/policy-34), and [42](https://uwaterloo.ca/secretariat/policies-procedures-guidelines/policies/policy-42-prevention-and-response-sexual-violence). |
||||
- The Code of Conduct does not cover criminal matters. Initiating a Code of Conduct complaint does not exclude other paths, such as going to Police Services. For criminal matters, threats or acts of physical violence, immediately contact directly UW Police at (519) 888-4911, or use the On Campus Extension x22222. |
@ -0,0 +1,6 @@ |
||||
--- |
||||
title: Revision |
||||
index: 12 |
||||
--- |
||||
|
||||
Revision 1.3, adopted by the Computer Science Club of the University of Waterloo on 25 January 2018. |
@ -0,0 +1,12 @@ |
||||
--- |
||||
title: Scope and Spaces |
||||
index: 8 |
||||
--- |
||||
|
||||
In cases where the Code of Conduct contradicts University policies, or applicable laws and bylaws, the Code of Conduct does not apply to the extent to which it conflicts. |
||||
|
||||
We expect all Club participants (participants, organizers, sponsors, and other guests) to abide by this Code of Conduct in all community venues (online and in-person) as well as in all one-on-one communications pertaining to Club business. |
||||
|
||||
- The Code of Conduct applies in the office, where office staff are responsible for enforcing it. |
||||
- The Code of Conduct applies in the IRC channel, where channel operators are responsible for enforcing it. |
||||
- The Code of Conduct applies at events the CSC organizes or co-organizes, where a designated organizer is responsible for enforcing it. |
@ -0,0 +1,16 @@ |
||||
--- |
||||
title: Unacceptable Behaviour |
||||
index: 3 |
||||
--- |
||||
|
||||
**Unacceptable behaviours include:** |
||||
|
||||
Intimidating, harassing, abusive, discriminatory, derogatory or demeaning speech or actions by any participant in our community online, at all related events and in one-on-one communications carried out in the context of Club business. |
||||
|
||||
- Club event venues may be shared; please be respectful to all patrons of these locations. |
||||
|
||||
**Harassment includes**: |
||||
|
||||
Harmful or prejudicial verbal or written comments related to gender, sexual orientation, race, religion, disability; inappropriate use of nudity and/or sexual images in public spaces (including presentation slides); deliberate intimidation, stalking or following; harassing photography or recording; sustained disruption of talks or other events; inappropriate physical contact, and unwelcome sexual attention. |
||||
|
||||
- Also refer to [Policy 33](https://uwaterloo.ca/secretariat/policies-procedures-guidelines/policy-33) for the definitions of discrimination and harassment. |
@ -0,0 +1,10 @@ |
||||
--- |
||||
title: 10. Amendments and Procedures |
||||
index: 10 |
||||
--- |
||||
|
||||
1. A proposed constitutional amendment can be initiated by the Executive Council or any ten (10) members. |
||||
2. The proposed amendment shall be announced to all members by email to the members' mailing list. |
||||
3. The proposed amendment shall be made available for viewing by all members in the Computer Science Club office. |
||||
4. A general meeting shall be held to consider the amendment at least seven (7) days after the announcement and no more than thirty (30) days after, which may be the regular meeting for the term, or a special meeting. |
||||
5. A constitutional amendment requires a 2/3 vote for adoption. |
@ -0,0 +1,27 @@ |
||||
--- |
||||
title: 7. Committees |
||||
index: 7 |
||||
--- |
||||
|
||||
## Programme Committee |
||||
|
||||
1. The Programme Committee shall be a standing committee chaired by the Vice-President. |
||||
2. The Vice-President shall appoint and remove members to and from the Programme Committee as needed. |
||||
3. The Programme Committee shall plan and arrange the events of the Club. |
||||
4. The Programme committee shall be responsible to the Executive Council and to the Vice-President. |
||||
|
||||
## Systems Committee |
||||
|
||||
1. The Systems Committee will be a standing committee, chaired by the Systems Administrator. |
||||
2. The Systems Administrator shall appoint and remove members to and from the Systems Committee. |
||||
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. |
||||
6. Members of the Systems Committee shall have root access to the machines operated by the Club. |
||||
|
||||
## Other Committees |
||||
|
||||
1. The President, with approval of the executive council, may appoint such special committees as are deemed necessary. |
@ -0,0 +1,6 @@ |
||||
--- |
||||
title: 11. Dissolution |
||||
index: 11 |
||||
--- |
||||
|
||||
1. In the event of dissolution of the Club, all assets of the Club shall be transferred to the Mathematics Society of the University of Waterloo. |
@ -0,0 +1,27 @@ |
||||
--- |
||||
title: 5. Duties of Officers |
||||
index: 5 |
||||