Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/past knits dropdown #48

Merged
merged 26 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2433728
Merge pull request #4 from fabric-testbed/develop
suejinkim20 Jun 28, 2024
7162fd4
Merge pull request #6 from fabric-testbed/develop
suejinkim20 Aug 15, 2024
fc6515e
Merge pull request #13 from fabric-testbed/develop
suejinkim20 Aug 22, 2024
2b4a408
Merge pull request #5 from fabric-testbed/staging
suejinkim20 Aug 22, 2024
3c47242
Merge pull request #16 from fabric-testbed/develop
suejinkim20 Aug 22, 2024
dcbcfe1
Merge pull request #26 from fabric-testbed/develop
suejinkim20 Sep 9, 2024
3814788
Merge pull request #33 from fabric-testbed/develop
suejinkim20 Sep 9, 2024
989c1f4
Merge pull request #36 from fabric-testbed/develop
suejinkim20 Sep 26, 2024
b390704
Merge pull request #39 from fabric-testbed/develop
suejinkim20 Oct 7, 2024
0f6f616
Merge pull request #41 from fabric-testbed/develop
yaxue1123 Jan 6, 2025
f63820e
Merge pull request #43 from fabric-testbed/develop
yaxue1123 Jan 6, 2025
b408499
update routing and menu structure
suejinkim20 Jan 15, 2025
2fb5df9
add past knits page
suejinkim20 Jan 15, 2025
378b4d6
add submenu and subsubmenu components to desktop menu
suejinkim20 Jan 16, 2025
5425f54
add submenu items to drawer menu
suejinkim20 Jan 16, 2025
4bb463b
#49: added notice banner for FABRIC awards recoginization notice
yaxue1123 Jan 23, 2025
4e6537b
#49: formatted banner content and added expiration check for a banner
yaxue1123 Jan 23, 2025
7bb624b
Merge pull request #50 from fabric-testbed/feature/add-banner-message
yaxue1123 Jan 24, 2025
38694b1
add up down right left chevron icon svgs
suejinkim20 Jan 29, 2025
f7321aa
utilize chevron down icon in dropdown menu
suejinkim20 Jan 29, 2025
8010917
utlize chevron right icon next to subsubmenu label
suejinkim20 Jan 29, 2025
92f8cb8
update styles for submenu and subsubmenu
suejinkim20 Jan 29, 2025
186e085
move external link icon and mail to link icon to icons folder
suejinkim20 Jan 29, 2025
5d25cc4
Merge branch 'main' into feature/past-knits-dropdown
suejinkim20 Jan 29, 2025
3c53422
move external link icon inside link
suejinkim20 Jan 29, 2025
81b6bd4
fix selected page styling of submenu items
suejinkim20 Jan 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 265 additions & 49 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"@mdx-js/react": "^3.0.1",
"@mui/joy": "^5.0.0-beta.27",
"core-js": "^3.35.1",
"html-react-parser": "^5.2.2",
"moment": "^2.30.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-feather": "^2.0.10",
Expand Down
72 changes: 34 additions & 38 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,55 @@ import {
NotFoundView,
RegistrationView,
TravelView,
Knit9View,
} from './views'

import { Header, Footer } from '@components/layout'
import { Header, Footer, Banner } from '@components/layout'

const menuOptions = [
{
path: '/',
label: 'Home',
view: <HomeView />,
},
{
path: '/registration',
label: 'Registration',
view: <RegistrationView />,
},
const pastKnits = [
{ path: '/past-knits/knit9', label: 'KNIT 9'},
{ path: 'https://learn.fabric-testbed.net/knowledge-base/knit-8-a-fabric-community-workshop/', label: 'KNIT 8' },
{ path: 'https://learn.fabric-testbed.net/knowledge-base/knit-7-a-fabric-community-workshop/', label: 'KNIT 7' },
{
path: '/travel',
label: 'Travel Info',
view: <TravelView />,
label: 'Additional KNITs',
subsubItems: [
{ path: 'https://learn.fabric-testbed.net/knowledge-base/knit-6-a-fabric-community-workshop/', label: 'KNIT 6' },
{ path: 'https://learn.fabric-testbed.net/knowledge-base/knit-5-a-fabric-community-workshop/', label: 'KNIT 5' },
{ path: 'https://learn.fabric-testbed.net/knowledge-base/knit-winter-21-a-fabric-community-workshop', label: 'KNIT 4' },
],
},
{
path: '/cfa',
label: 'Calls for Action',
view: <CfaView />,
}
// {
// path: '/agenda',
// label: 'Agenda',
// view: <AgendaView />,
// }
]

//
const menuOptions = [
{ path: '/', label: 'Home' },
{ path: '/registration', label: 'Registration' },
{ path: '/travel', label: 'Travel Info' },
{ path: '/cfa', label: 'Calls for Action' },
{ path: '/agenda', label: 'Agenda' },
{
label: 'Past KNITs',
path: '/past-knits', // Parent path
subItems: pastKnits,
},
];

export const App = () => {
return (
<Fragment>
<Header />
<Banner />
<Menu options={ menuOptions } />
<main>
<Routes>
{
// we'll build the routes from the main menu items.
// note this implementation only supports a flat,
// one-level navigation structure.
menuOptions.map(({ path, view, label }) => (
<Route
key={ `route-${ label }` }
path={ path }
element={ view }
/>
))
}
<Route path="/" element={ <HomeView /> } />
<Route path="/registration" element={ <RegistrationView /> } />
<Route path="/travel" element={ <TravelView /> } />
<Route path="/cfa" element={ <CfaView /> } />
<Route path="/agenda" element={ <AgendaView /> } />
<Route path="/past-knits">
<Route path="knit9" element={ <Knit9View /> } />
</Route>

<Route path="__markdown" element={ <MarkdownView /> } />
<Route path="*" element={ <NotFoundView /> } />
</Routes>
Expand Down
50 changes: 50 additions & 0 deletions src/components/icons/chevron-icons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import PropTypes from "prop-types";

const ChevronIcon = ({ size = 24, fill = "#000", children, ...rest }) => (
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
height={`${size}px`}
width={`${size}px`}
fill={fill}
viewBox="0 0 24 24"
{...rest}
>
{children}
</svg>
);

export const ChevronUpIcon = props => (
<ChevronIcon {...props}>
<path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z" />
<path d="M0 0h24v24H0z" fill="none" />
</ChevronIcon>
);

export const ChevronDownIcon = props => (
<ChevronIcon {...props}>
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
<path d="M0 0h24v24H0z" fill="none" />
</ChevronIcon>
);

export const ChevronLeftIcon = props => (
<ChevronIcon {...props}>
<path d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z" />
</ChevronIcon>
);

export const ChevronRightIcon = props => (
<ChevronIcon {...props}>
<path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z" />
</ChevronIcon>
);

const requiredProps = {
fill: PropTypes.string,
size: PropTypes.number,
children: PropTypes.node,
};

ChevronIcon.propTypes = requiredProps;
2 changes: 2 additions & 0 deletions src/components/icons/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './chevron-icons'
export * from './link-icons'
File renamed without changes.
41 changes: 41 additions & 0 deletions src/components/layout/banner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Alert as MUIAlert} from '@mui/joy'
import Link from '@mui/joy/Link'
import Parser from 'html-react-parser'
import moment from 'moment';

const checkNotExpired = (start, end) => {
const startUTC = start.substring(0, 19);
const stillStartUTC = moment.utc(startUTC).toDate();
const endUTC = end.substring(0, 19);
const stillEndUTC = moment.utc(endUTC).toDate();
return stillEndUTC > new Date() && stillStartUTC < new Date();
}

export const Banner = () => {
const bannerContent = {
"content": "FABRIC invites nominations for four awards recognizing innovative uses of FABRIC resources—Best Published Paper, Best FABRIC Matrix, Best FABRIC Experiment, and Best Classroom Use of FABRIC — submissions due by <b>Monday, February 24 at 11:59 PM ET</b>, and winners announced at KNIT10.",
"end_date": "2025-02-25 00:00:00+00:00",
"link": "https://docs.google.com/forms/d/e/1FAIpQLSeTp3i2iDhB7bHgN8ryMxZci8ya87yjeQd7_JMZImUodNinVA/viewform",
"start_date": "2025-01-22 00:00:00+00:00",
"button": ">>> Submit Form"
}

return (
checkNotExpired(bannerContent.start_date, bannerContent.end_date) &&
<MUIAlert
color="warning"
size="md"
variant="soft"
>
<span>{Parser(bannerContent.content)}
<Link
href={bannerContent.link}
target="_blank"
rel="noreferrer"
sx={{ marginLeft: '20px' }}
>
{bannerContent.button}
</Link></span>
</MUIAlert>
)
}
1 change: 1 addition & 0 deletions src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './container'
export * from './header'
export * from './footer'
export * from './page'
export * from './banner'
6 changes: 3 additions & 3 deletions src/components/link/external-link.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fragment } from 'react'
import { BaseLinkPropTypes } from './'
import { ExternalLinkIcon } from './'
import { ExternalLinkIcon } from '../icons'
import { Button, Link } from '@mui/joy'

export const ExternalLink = ({ to, children, button, ...props }) => {
Expand All @@ -25,8 +25,8 @@ export const ExternalLink = ({ to, children, button, ...props }) => {
target="_blank"
rel="noopener noreferrer"
{ ...props }
>{ children }</Link>
<ExternalLinkIcon />
>{ children }<ExternalLinkIcon /> </Link>

</Fragment>
)}
</Fragment>
Expand Down
1 change: 0 additions & 1 deletion src/components/link/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './link'
export * from './link-icon'
export * from './external-link'
export * from './mail-to-link'
2 changes: 1 addition & 1 deletion src/components/link/mail-to-link.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fragment } from 'react'
import { BaseLinkPropTypes } from './'
import { MailtoLinkIcon } from './'
import { MailtoLinkIcon } from '../icons'

export const MailtoLink = ({ to, children }) => {
return (
Expand Down
54 changes: 0 additions & 54 deletions src/components/menu/desktop-menu.js

This file was deleted.

70 changes: 70 additions & 0 deletions src/components/menu/desktop-menu/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { NavLink, useLocation } from 'react-router-dom'
import { ChevronDownIcon } from '../../icons/chevron-icons'
import { MenuContainer, MenuLink, MenuItem } from './menuComponents'
import { Submenu, SubmenuHeader } from './submenuComponents'

export const DesktopMenu = ({ options = [] }) => {
const location = useLocation() // used to determine active paths
const [openSubmenu, setOpenSubmenu] = useState(-1)

const handleOpenSubmenu = (index) => () => setOpenSubmenu(index)
const handleCloseSubmenu = () => setOpenSubmenu(-1)

// determine if a path is active
const isActive = (path, subItems) => {
if (location.pathname === path) return true; // direct match
if (subItems) {
return subItems.some((item) =>
location.pathname.startsWith(item.path)
)
}
return false
}

return (
<MenuContainer role="navigation" aria-label="Desktop menu">
{options.map(({ label, path, subItems }, index) => (
<MenuItem
key={path || label}
onMouseOver={subItems ? handleOpenSubmenu(index) : undefined}
onMouseOut={subItems ? handleCloseSubmenu : undefined}
>
{subItems ? (
<>
<SubmenuHeader
active={isActive(path, subItems)}
open={openSubmenu === index}
aria-label={`${label} submenu`}
>
{label}
<ChevronDownIcon size={ 16 } fill="var(--knit-palette-primary-900)"/>
</SubmenuHeader>
{openSubmenu === index && <Submenu items={subItems} />}
</>
) : (
<MenuLink as={NavLink} to={path} active={isActive(path)}>
{label}
</MenuLink>
)}
</MenuItem>
))}
</MenuContainer>
)
}

DesktopMenu.propTypes = {
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
path: PropTypes.string,
subItems: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
})
),
})
),
}
Loading