Skip to content

Commit

Permalink
feat: display meeting indexes by semester
Browse files Browse the repository at this point in the history
fix: improve calendar event handling and metadata
refactor: update button class names and styles across multiple components
  • Loading branch information
WhiteHoodHacker committed Jan 3, 2025
1 parent 657b00c commit 08e70e6
Show file tree
Hide file tree
Showing 30 changed files with 496 additions and 210 deletions.
36 changes: 36 additions & 0 deletions _global/components/Icons/fluentui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,36 @@ export const ChevronCircleRightRegular = (props: TSVGElementProps) => (
</SvgWrapper>
);

export const ChevronLeftFilled = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M10.2603 3.20041C10.5639 3.48226 10.5814 3.95681 10.2996 4.26034L6.77348 8L10.2996 11.7397C10.5814 12.0432 10.5639 12.5177 10.2603 12.7996C9.9568 13.0815 9.48226 13.0639 9.2004 12.7603L5.2004 8.51034C4.9332 8.22258 4.9332 7.77743 5.2004 7.48966L9.20041 3.23966C9.48226 2.93613 9.95681 2.91856 10.2603 3.20041Z"/>
</SvgWrapper>
);

export const ChevronLeftRegular = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M10.3536 3.14645C10.5488 3.34171 10.5488 3.65829 10.3536 3.85355L6.20711 8L10.3536 12.1464C10.5488 12.3417 10.5488 12.6583 10.3536 12.8536C10.1583 13.0488 9.84171 13.0488 9.64645 12.8536L5.14645 8.35355C4.95118 8.15829 4.95118 7.84171 5.14645 7.64645L9.64645 3.14645C9.84171 2.95118 10.1583 2.95118 10.3536 3.14645Z"/>
</SvgWrapper>
);

export const ChevronRightFilled = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M5.73966 3.20041C5.43613 3.48226 5.41856 3.95681 5.70041 4.26034L9.22652 8L5.70041 11.7397C5.41856 12.0432 5.43613 12.5177 5.73967 12.7996C6.0432 13.0815 6.51775 13.0639 6.7996 12.7603L10.7996 8.51034C11.0668 8.22258 11.0668 7.77743 10.7996 7.48966L6.7996 3.23966C6.51775 2.93613 6.0432 2.91856 5.73966 3.20041Z"/>
</SvgWrapper>
);

export const ChevronRightRegular = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z" />
</SvgWrapper>
);

export const ChevronUpDownFilled = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M4.21967 6.53033C4.51256 6.82322 4.98744 6.82322 5.28033 6.53033L8 3.81066L10.7197 6.53033C11.0126 6.82322 11.4874 6.82322 11.7803 6.53033C12.0732 6.23744 12.0732 5.76256 11.7803 5.46967L8.53033 2.21967C8.23744 1.92678 7.76256 1.92678 7.46967 2.21967L4.21967 5.46967C3.92678 5.76256 3.92678 6.23744 4.21967 6.53033ZM4.21967 9.46967C4.51256 9.17678 4.98744 9.17678 5.28033 9.46967L8 12.1893L10.7197 9.46967C11.0126 9.17678 11.4874 9.17678 11.7803 9.46967C12.0732 9.76256 12.0732 10.2374 11.7803 10.5303L8.53033 13.7803C8.23744 14.0732 7.76256 14.0732 7.46967 13.7803L4.21967 10.5303C3.92678 10.2374 3.92678 9.76256 4.21967 9.46967Z"/>
</SvgWrapper>
);

export const ClockRegular = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M8 2C11.3137 2 14 4.68629 14 8C14 11.3137 11.3137 14 8 14C4.68629 14 2 11.3137 2 8C2 4.68629 4.68629 2 8 2ZM8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3ZM7.50153 5C7.74699 5 7.95114 5.17688 7.99347 5.41012L8.00153 5.5V8H9.5C9.77614 8 10 8.22386 10 8.5C10 8.74546 9.82312 8.94961 9.58988 8.99194L9.5 9H7.50153C7.25607 9 7.05192 8.82312 7.00958 8.58988L7.00153 8.5V5.5C7.00153 5.22386 7.22538 5 7.50153 5Z" />
Expand All @@ -114,6 +138,18 @@ export const HatGraduationRegular = (props: TSVGElementProps) => (
</SvgWrapper>
);

export const InfoFilled = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M8 1C11.866 1 15 4.13401 15 8C15 11.866 11.866 15 8 15C4.13401 15 1 11.866 1 8C1 4.13401 4.13401 1 8 1ZM8.00001 6.24907C8.41369 6.24907 8.74905 5.91371 8.74905 5.50003C8.74905 5.08635 8.41369 4.751 8.00001 4.751C7.58633 4.751 7.25098 5.08635 7.25098 5.50003C7.25098 5.91371 7.58633 6.24907 8.00001 6.24907ZM8.5 7.5C8.5 7.22386 8.27614 7 8 7C7.72386 7 7.5 7.22386 7.5 7.5V10.5C7.5 10.7761 7.72386 11 8 11C8.27614 11 8.5 10.7761 8.5 10.5V7.5Z"/>
</SvgWrapper>
);

export const InfoRegular = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M8.49902 7.49998C8.49902 7.22384 8.27517 6.99998 7.99902 6.99998C7.72288 6.99998 7.49902 7.22384 7.49902 7.49998V10.5C7.49902 10.7761 7.72288 11 7.99902 11C8.27517 11 8.49902 10.7761 8.49902 10.5V7.49998ZM8.74807 5.50001C8.74807 5.91369 8.41271 6.24905 7.99903 6.24905C7.58535 6.24905 7.25 5.91369 7.25 5.50001C7.25 5.08633 7.58535 4.75098 7.99903 4.75098C8.41271 4.75098 8.74807 5.08633 8.74807 5.50001ZM8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1ZM2 8C2 4.68629 4.68629 2 8 2C11.3137 2 14 4.68629 14 8C14 11.3137 11.3137 14 8 14C4.68629 14 2 11.3137 2 8Z"/>
</SvgWrapper>
);

export const LinkRegular = (props: TSVGElementProps) => (
<SvgWrapper {...props}>
<path d="M9.49999 4H10.5C12.433 4 14 5.567 14 7.5C14 9.36856 12.5357 10.8951 10.6941 10.9948L10.5023 11L9.5023 11.0046C9.22616 11.0059 9.00127 10.783 8.99999 10.5069C8.99888 10.2614 9.17481 10.0565 9.40787 10.0131L9.4977 10.0046L10.5 10C11.8807 10 13 8.88071 13 7.5C13 6.17452 11.9685 5.08996 10.6644 5.00532L10.5 5H9.49999C9.22386 5 8.99999 4.77614 8.99999 4.5C8.99999 4.25454 9.17687 4.05039 9.41012 4.00806L9.49999 4H10.5H9.49999ZM5.5 4H6.5C6.77614 4 7 4.22386 7 4.5C7 4.74546 6.82312 4.94961 6.58988 4.99194L6.5 5H5.5C4.11929 5 3 6.11929 3 7.5C3 8.82548 4.03154 9.91004 5.33562 9.99468L5.5 10H6.5C6.77614 10 7 10.2239 7 10.5C7 10.7455 6.82312 10.9496 6.58988 10.9919L6.5 11H5.5C3.567 11 2 9.433 2 7.5C2 5.63144 3.46428 4.10487 5.30796 4.00518L5.5 4H6.5H5.5ZM5.50023 7L10.5002 7.0023C10.7764 7.00242 11.0001 7.22638 11 7.50252C10.9999 7.74798 10.8229 7.95205 10.5897 7.99428L10.4998 8.0023L5.49977 8C5.22363 7.99987 4.99987 7.77591 5 7.49977C5.00011 7.25431 5.17708 7.05024 5.41035 7.00801L5.50023 7Z" />
Expand Down
2 changes: 1 addition & 1 deletion _global/content/events/fallctf/2023/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ links:
## Registration
Registration for the CTF competition platform is now available!

<a href="https://fallctf.sigpwny.com/" class="btn-primary mb-2">Register on CTFd</a>
<a href="https://fallctf.sigpwny.com/" class="button btn-primary mb-2">Register on CTFd</a>

<p class="mt-4">
Registration via Google Forms for a free shirt and electronic badge has closed. If you previously registered beforehand, please make sure to bring your iCard to the event (or show your ID on the Illinois app). If you did not register on Google Forms, we will be handing out any remaining shirts later in the event. We will also be raffling off extra electronic badges.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ We are excited to have both our sponsor CrowdStrike and UIUC's Privacy and Cyber

Pizza will be provided!

<a href="https://falcon.events/landing#H5M4" class="btn-primary">Live Scavenger Hunt</a>
<a href="https://falcon.events/landing#H5M4" class="button btn-primary">Live Scavenger Hunt</a>
61 changes: 36 additions & 25 deletions _global/utils/meetingMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
export const meetingMetatypes = [
'general',
'ctf',
'purple',
'embedded',
];

'general',
'seminar',
'ctf',
'purple',
'embedded',
];

export type MeetingMetatype = typeof meetingMetatypes[number];

export interface MeetingMetadata {
name: string;
shortName: string;
}
name: string;
shortName: string;
description?: string;
};

export const meetingMetadata: Record<MeetingMetatype, MeetingMetadata> = {
'general': {
name: 'General',
shortName: 'General',
},
'ctf': {
name: 'CTF Team',
shortName: 'CTF',
},
'purple': {
name: 'Purple Team',
shortName: 'Purple',
},
'embedded': {
name: 'Embedded Team',
shortName: 'Embedded',
},
'general': {
name: 'General Meetings',
shortName: 'General',
description: 'Attend our weekly general meetings to learn fundamental skills in cybersecurity.',
},
'seminar': {
name: 'Seminar Meetings',
shortName: 'Seminar',
description: 'Attend our seminars to discuss advanced and novel research topics in cybersecurity.',
},
'ctf': {
name: 'CTF Team',
shortName: 'CTF',
description: 'Compete in "Capture the Flag" events to hone your cybersecurity skills.',
},
'purple': {
name: 'Purple Team',
shortName: 'Purple',
description: 'Learn red-teaming (offensive) and blue-teaming (defensive) skills to secure systems and networks.',
},
'embedded': {
name: 'Embedded Team',
shortName: 'Embedded',
description: 'Build secure embedded systems and learn about hardware hacking!',
},
};
2 changes: 1 addition & 1 deletion fallctf.com/src/pages/2024.astro
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const event = {
{event.links.map((link) => (
<Link
href={link.url}
class="btn-primary font-bold border-2 border-surface-250"
class="button btn-primary font-bold border-2 border-surface-250"
>
{link.name}
</Link>
Expand Down
2 changes: 1 addition & 1 deletion fallctf.com/src/pages/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const flavor = 'Fall CTF is a beginner-friendly CTF competition for UIUC student
{event.links.map((link) => (
<Link
href={link.url}
class="btn-primary font-bold border-2 border-surface-250"
class="button btn-primary font-bold border-2 border-surface-250"
>
{link.name}
</Link>
Expand Down
9 changes: 4 additions & 5 deletions fallctf.com/src/styles/fallctf.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,11 @@ h3 {
.panel-p-0 {
@apply bg-surface-100 rounded-xl;
}
.btn-primary {
@apply bg-primary text-surface-000 px-3 py-1 rounded-full cursor-pointer;
.button {
@apply border-0 rounded-md px-3 py-1 cursor-pointer select-none;
}
.btn-primary:hover {
background-color: rgb(var(--rgb-secondary));
color: rgb(var(--rgb-surface-000));
.btn-primary {
@apply bg-primary hover:bg-secondary text-surface-000 hover:text-surface-000;
}
.button {
@apply flex flex-row items-center gap-1 px-3 py-1 cursor-pointer rounded-md;
Expand Down
7 changes: 4 additions & 3 deletions sigpwny.com/src/components/CalendarSubscribe.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useState } from 'react';
import type { Placement } from '@floating-ui/react';
import {
Popover,
PopoverTrigger,
Expand All @@ -25,7 +26,7 @@ import { type MeetingMetatype } from '$/utils/meetingMetadata';

interface CalendarSubscribeProps {
selected: MeetingMetatype[];
placement?: 'top' | 'bottom' | 'left' | 'right';
placement?: Placement;
}

export default function CalendarSubscribe({ selected, placement }: CalendarSubscribeProps) {
Expand Down Expand Up @@ -54,7 +55,7 @@ export default function CalendarSubscribe({ selected, placement }: CalendarSubsc
<div className="flex flex-shrink-0 flex-grow-0">
<PopoverTrigger
onClick={() => setOpen(!open)}
className={`btn-primary flex flex-row gap-2 items-center ${open ? "ring-primary ring-2 ring-offset-2 ring-offset-surface-000" : ""}`}
className={`button btn-primary flex flex-row gap-2 items-center ${open ? "ring-primary ring-2 ring-offset-2 ring-offset-surface-000" : ""}`}
>
<CalendarSyncRegular className="text-black" />
<span>
Expand All @@ -65,7 +66,7 @@ export default function CalendarSubscribe({ selected, placement }: CalendarSubsc
</div>
<div className="absolute top-full mt-2 left-0">
<PopoverContent>
<Menu>
<Menu className="custom-scrollbar">
<ul>
{Object.entries(reactMeetingMetadata).map(([meeting_type, metadata]) => (
<li
Expand Down
45 changes: 45 additions & 0 deletions sigpwny.com/src/components/DropdownSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useState } from 'react';
import type { Placement } from '@floating-ui/react';
import {
Popover,
PopoverTrigger,
PopoverContent,
} from '@/components/Popover';
import Menu from '@/components/Menu';
import { ChevronUpDownFilled } from '$/components/Icons/fluentui';

interface DropdownSelectOptionsProps {
id: string;
displayText?: string;
href?: string;
}

interface DropdownSelectProps {
children?: React.ReactNode;
contentRootClassName?: string;
options: DropdownSelectOptionsProps[];
selectedId: string;
displayText?: string;
onSelect?: (selected: string) => void;
placement?: Placement;
}

export default function DropdownSelect(props: DropdownSelectProps) {
const [open, setOpen] = useState(false);
const selectedText = props.displayText ?? props.options.find((option) => option.id === props.selectedId)?.displayText ?? props.selectedId;

return (
<Popover open={open} onOpenChange={setOpen} placement={props.placement ?? "bottom-start"}>
<PopoverTrigger
onClick={() => setOpen(!open)}
className={`button flex flex-row gap-2 items-center justify-between bg-surface-100 hover:bg-surface-150 text-white w-full border border-surface-200 pr-1 ${open ? "ring-primary ring-2 ring-offset-2 ring-offset-surface-000" : ""}`}
>
<span className="truncate">{selectedText}</span>
<ChevronUpDownFilled />
</PopoverTrigger>
<PopoverContent className={props.contentRootClassName}>
{props.children}
</PopoverContent>
</Popover>
);
};
12 changes: 6 additions & 6 deletions sigpwny.com/src/components/Meeting/Row.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ import { CountdownBadge } from '@/components/ReactMigration/Countdown';
import { TagGroup } from '@/components/ReactMigration/Tag';
import { convertDate, weekNumber } from '@/utils/meetings';
import { getProfilesFromNames } from '$/utils/profiles';
import type { Meeting } from '@/utils/meetings';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import utc from 'dayjs/plugin/utc';
import UpcomingMeta from '@/components/ReactMigration/UpcomingMeta';
import type { MeetingType } from '@/pages/meetings/index.astro';
dayjs.extend(duration);
dayjs.extend(utc);
interface Props {
input: MeetingType;
showUpcoming: boolean;
input: Meeting;
hideUpcoming?: boolean;
}
const { input, showUpcoming } = Astro.props;
const { input, hideUpcoming } = Astro.props;
const meeting = input.data;
const time_close = dayjs(meeting.time_start).add(dayjs.duration(meeting.duration)).toDate();
// Resolve credit names to profiles
const profiles = await getProfilesFromNames(meeting.credit);
const upcomingVisibility = showUpcoming ? 'block' : 'none';
const notUpcomingVisibility = showUpcoming ? 'none' : 'block';
const upcomingVisibility = hideUpcoming ? 'none' : 'block';
const notUpcomingVisibility = hideUpcoming ? 'none' : 'block';
---
<style define:vars={{ upcomingVisibility, notUpcomingVisibility }}>
/* The filters override the upcoming visibility selector */
Expand Down
9 changes: 7 additions & 2 deletions sigpwny.com/src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import './styles.css';

export default function Menu({ children }: { children: React.ReactNode }) {
interface Props {
children?: React.ReactNode;
className?: string;
}

export default function Menu({ children, className }: Props) {
return (
<div className="pwny-menu">
<div className={className ? `pwny-menu ${className}` : "pwny-menu"}>
{children}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion sigpwny.com/src/components/Menu/styles.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.pwny-menu {
@apply isolate bg-surface-200/70 border-2 border-surface-250 backdrop-blur-xl shadow-lg rounded-lg flex flex-col;
@apply isolate bg-surface-200/70 border-2 border-surface-250 backdrop-blur-xl shadow-lg rounded-lg flex flex-col max-h-screen overflow-y-auto;
}

.pwny-menu ul {
Expand Down
28 changes: 8 additions & 20 deletions sigpwny.com/src/layouts/Meeting.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,21 @@
import Layout from '@/layouts/Base.astro';
import type { HeadProps } from '$/components/BaseHead.astro';
import Sidebar from '@/components/Sidebar';
import { getMeetings, formatSemester, weekNumber } from '@/utils/meetings';
import {
getSemesterToMeetingsMap,
formatSemester,
weekNumber,
} from '@/utils/meetings';
import 'katex/dist/katex.min.css';
import { reactMeetingMetadata } from '@/utils/reactMeetingMetadata';
const props: HeadProps = Astro.props;
const rawMeetings = (await getMeetings()).sort(
(a, b) => b.data.time_start.valueOf() - a.data.time_start.valueOf()
);
const semesterToMeetingsMap = await getSemesterToMeetingsMap();
type MeetingType = typeof rawMeetings[0];
const meetingsBySemester = rawMeetings.reduce(
(acc, meeting) => {
const semester = meeting.data.semester;
if (acc[semester]) {
acc[semester].push(meeting);
} else {
acc[semester] = [meeting];
}
return acc;
}, {} as {[semester: string]: MeetingType[]}
);
const meetingSidebarItems = Object.keys(meetingsBySemester).map((semester) => ({
const meetingSidebarItems = Array.from(semesterToMeetingsMap.entries()).map(([semester, meetings]) => ({
name: formatSemester(semester),
items: meetingsBySemester[semester].map((meeting) => ({
items: meetings.map((meeting) => ({
name: meeting.data.week_number != null ? `Week ${weekNumber(meeting.data.week_number)}: ${meeting.data.title}` : meeting.data.title,
url: meeting.slug,
active: meeting.slug === Astro.url.pathname,
Expand Down
15 changes: 15 additions & 0 deletions sigpwny.com/src/layouts/MeetingIndex.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
import Layout from '@/layouts/Base.astro';
---
<Layout
title="Meetings"
description="Index of SIGPwny meetings"
>
<div class="flex flex-col mx-auto page-width-lg pb-8">
<h1>Meetings</h1>
<nav>
<span>TODO: Select Semester</span>
</nav>
<slot />
</div>
</Layout>
2 changes: 1 addition & 1 deletion sigpwny.com/src/pages/applecal.astro
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const webcalLink = "webcal://sigpwny.com/calendar/all/apple.ics";
<div class="flex flex-col gap-2 items-center">
<a
href={webcalLink}
class="btn-primary flex flex-row gap-2 items-center max-w-fit"
class="button btn-primary flex flex-row gap-2 items-center max-w-fit"
>
<CalendarSyncRegular />
<span class="inline align-middle">Subscribe</span>
Expand Down
2 changes: 1 addition & 1 deletion sigpwny.com/src/pages/cal.astro
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const webcalLink = "webcal://sigpwny.com/calendar/all/generic.ics";
<div class="flex flex-col gap-2 items-center">
<a
href={webcalLink}
class="btn-primary flex flex-row gap-2 items-center max-w-fit"
class="button btn-primary flex flex-row gap-2 items-center max-w-fit"
>
<CalendarSyncRegular />
<span class="inline align-middle">Subscribe</span>
Expand Down
Loading

0 comments on commit 08e70e6

Please sign in to comment.