-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #653 from battlecode/serena/routing
Add routing
- Loading branch information
Showing
22 changed files
with
330 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,55 @@ | ||
import React from "react"; | ||
import React, { useState } from "react"; | ||
import EpisodeLayout from "./components/EpisodeLayout"; | ||
import Home from "./views/Home"; | ||
import Logout from "./views/Logout"; | ||
import Register from "./views/Register"; | ||
import PasswordForgot from "./views/PasswordForgot"; | ||
import PasswordChange from "./views/PasswordChange"; | ||
import Account from "./views/Account"; | ||
import Login from "./views/Login"; | ||
import QuickStart from "./views/QuickStart"; | ||
import { EpisodeContext } from "./contexts/EpisodeContext"; | ||
import { | ||
RouterProvider, | ||
createBrowserRouter, | ||
Navigate, | ||
} from "react-router-dom"; | ||
import { DEFAULT_EPISODE } from "./utils/constants"; | ||
import NotFound from "./views/NotFound"; | ||
|
||
const App: React.FC = () => { | ||
const [episodeId, setEpisodeId] = useState(DEFAULT_EPISODE); | ||
return ( | ||
<div className="App"> | ||
<header className="App-header text-3xl font-bold underline"> | ||
<p> | ||
Edit <code>src/App.tsx</code> and save to reload. | ||
</p> | ||
<a | ||
className="App-link" | ||
href="https://reactjs.org" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Learn React | ||
</a> | ||
</header> | ||
</div> | ||
<EpisodeContext.Provider value={{ episodeId, setEpisodeId }}> | ||
<RouterProvider router={router} /> | ||
</EpisodeContext.Provider> | ||
); | ||
}; | ||
|
||
const router = createBrowserRouter([ | ||
// Pages that should render without a sidebar/navbar | ||
{ path: "/login", element: <Login /> }, | ||
{ path: "/logout", element: <Logout /> }, | ||
{ path: "/register", element: <Register /> }, | ||
{ path: "/password_forgot", element: <PasswordForgot /> }, | ||
{ path: "/password_change", element: <PasswordChange /> }, | ||
// Pages that will contain the episode specific sidebar and navbar | ||
{ | ||
element: <EpisodeLayout />, | ||
children: [ | ||
// Pages that should always be visible | ||
// TODO: /:episodeId/resources, /:episodeId/tournaments, /:episodeId/rankings, /:episodeId/queue | ||
{ path: "/:episodeId/home", element: <Home /> }, | ||
{ path: "/:episodeId/quickstart", element: <QuickStart /> }, | ||
{ path: "/:episodeId/*", element: <NotFound /> }, | ||
// Pages that should only be visible when logged in | ||
// TODO: /:episodeId/team, /:episodeId/submissions, /:episodeId/scrimmaging | ||
{ path: "/account", element: <Account /> }, | ||
// etc | ||
], | ||
}, | ||
// Pages that should redirect | ||
{ path: "/*", element: <Navigate to={`/${DEFAULT_EPISODE}/home`} /> }, | ||
]); | ||
|
||
export default App; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import React, { useContext } from "react"; | ||
import Navbar from "./Navbar"; | ||
import Sidebar from "./sidebar"; | ||
import { Outlet, useParams } from "react-router-dom"; | ||
import { EpisodeContext } from "../contexts/EpisodeContext"; | ||
|
||
// This component contains the NavBar and SideBar. | ||
// Child route components are rendered with <Outlet /> | ||
const EpisodeLayout: React.FC = () => { | ||
const episodeContext = useContext(EpisodeContext); | ||
const { episodeId } = useParams(); | ||
if (episodeId !== undefined && episodeId !== episodeContext.episodeId) { | ||
episodeContext.setEpisodeId(episodeId); | ||
} | ||
return ( | ||
<div className="h-screen"> | ||
<Navbar/> | ||
<div className="flex flex-row h-full"> | ||
<Sidebar /> | ||
<Outlet /> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default EpisodeLayout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const Navbar: React.FC = () => { | ||
return <p>navbar here</p>; | ||
}; | ||
|
||
export default Navbar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React from "react"; | ||
import { NavLink } from "react-router-dom"; | ||
|
||
interface SidebarItemProps { | ||
icon: React.ReactNode; | ||
text: string; | ||
linkTo: string; | ||
} | ||
|
||
const SidebarItem: React.FC<SidebarItemProps> = ({ | ||
icon, | ||
text, | ||
linkTo, | ||
}) => { | ||
const baseStyle = | ||
"text-base flex items-center gap-3 "; | ||
const colorVariants = { | ||
gray: "text-gray-800 hover:text-gray-400", | ||
color: "text-teal", | ||
}; | ||
return ( | ||
<NavLink | ||
className={({ isActive }) => | ||
baseStyle + (isActive ? colorVariants.color : colorVariants.gray) | ||
} | ||
to={linkTo} | ||
> | ||
{icon} | ||
{text} | ||
</NavLink> | ||
); | ||
}; | ||
|
||
export default SidebarItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from "react"; | ||
|
||
interface SidebarSectionProps { | ||
children?: React.ReactNode, | ||
title?: string; | ||
} | ||
|
||
const SidebarSection: React.FC<SidebarSectionProps> = ({ children, title }) => { | ||
return ( | ||
<div className="pl-5 pr-8"> | ||
{title !== undefined && <h2 className="uppercase text-gray-500 tracking-wider text-sm mb-3">{title}</h2>} | ||
<div className="flex flex-col gap-5"> | ||
{children} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SidebarSection; |
27 changes: 27 additions & 0 deletions
27
frontend2/src/components/sidebar/__test__/Sidebar.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from "react"; | ||
import { render, screen } from "@testing-library/react"; | ||
import Sidebar from "../"; | ||
import { DEFAULT_EPISODE } from "../../../utils/constants"; | ||
import { EpisodeContext } from "../../../contexts/EpisodeContext"; | ||
import { MemoryRouter } from "react-router-dom"; | ||
|
||
test('UI: should link to default episode', () => { | ||
render(<MemoryRouter><Sidebar /></MemoryRouter>); | ||
const linkElement = screen.getByText('Resources').closest('a')?.getAttribute('href'); | ||
expect(linkElement).toEqual(expect.stringContaining(`/${DEFAULT_EPISODE}/resources`)); | ||
}); | ||
|
||
test('UI: should collapse sidebar', () => { | ||
render(<MemoryRouter><Sidebar collapsed={true} /></MemoryRouter>); | ||
expect(screen.queryByText('Home')).toBeNull(); | ||
}); | ||
|
||
test('UI: should link to episode in surrounding context', () => { | ||
render(<MemoryRouter> | ||
<EpisodeContext.Provider value={{ episodeId: "something", setEpisodeId: (_) => undefined }}> | ||
<Sidebar /> | ||
</EpisodeContext.Provider></MemoryRouter> | ||
); | ||
const linkElement = screen.getByText('Resources').closest('a')?.getAttribute('href'); | ||
expect(linkElement).toEqual(expect.stringContaining(`/something/resources`)); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import React, { useContext } from "react"; | ||
import SidebarSection from "./SidebarSection"; | ||
import SidebarItem from "./SidebarItem"; | ||
import { | ||
ClipboardDocumentIcon, HomeIcon, MapIcon, | ||
TrophyIcon, ChartBarIcon, ClockIcon, | ||
UserGroupIcon, ArrowUpTrayIcon, PlayCircleIcon, | ||
} from "@heroicons/react/24/outline"; | ||
import { EpisodeContext } from "../../contexts/EpisodeContext"; | ||
|
||
interface SidebarProps { | ||
collapsed?: boolean; | ||
} | ||
|
||
const Sidebar: React.FC<SidebarProps> = ({ | ||
collapsed | ||
}) => { | ||
collapsed = collapsed ?? false; | ||
const { episodeId } = useContext(EpisodeContext); | ||
const linkBase = `/${episodeId}/`; | ||
|
||
return ( | ||
collapsed ? null : ( | ||
<div className="flex flex-col gap-8 py-4 h-full bg-gray-50 shadow-gray-200 shadow-sm"> | ||
<SidebarSection title="" > | ||
<SidebarItem | ||
icon={<HomeIcon className="h-6 w-6" />} | ||
text="Home" | ||
linkTo={`${linkBase}home`} | ||
/> | ||
<SidebarItem | ||
icon={<MapIcon className="h-6 w-6" />} | ||
text="Quick Start" | ||
linkTo={`${linkBase}quickstart`} | ||
/> | ||
<SidebarItem | ||
icon={<ClipboardDocumentIcon className="h-6 w-6" />} | ||
text="Resources" | ||
linkTo={`${linkBase}resources`} | ||
/> | ||
</SidebarSection> | ||
<SidebarSection title="compete" > | ||
<SidebarItem | ||
icon={<TrophyIcon className="h-6 w-6" />} | ||
text="Tournaments" | ||
linkTo={`${linkBase}tournaments`} | ||
/> | ||
<SidebarItem | ||
icon={<ChartBarIcon className="h-6 w-6" />} | ||
text="Rankings" | ||
linkTo={`${linkBase}rankings`} | ||
/> | ||
<SidebarItem | ||
icon={<ClockIcon className="h-6 w-6" />} | ||
text="Queue" | ||
linkTo={`${linkBase}queue`} | ||
/> | ||
</SidebarSection> | ||
<SidebarSection title="team management" > | ||
<SidebarItem | ||
icon={<UserGroupIcon className="h-6 w-6" />} | ||
text="My Team" | ||
linkTo={`${linkBase}team`} | ||
/> | ||
<SidebarItem | ||
icon={<ArrowUpTrayIcon className="h-6 w-6" />} | ||
text="Submissions" | ||
linkTo={`${linkBase}submission`} | ||
/> | ||
<SidebarItem | ||
icon={<PlayCircleIcon className="h-6 w-6" />} | ||
text="Scrimmaging" | ||
linkTo={`${linkBase}scrimmaging`} | ||
/> | ||
</SidebarSection> | ||
</div> | ||
) | ||
); | ||
|
||
|
||
}; | ||
|
||
export default Sidebar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { createContext } from "react"; | ||
import { DEFAULT_EPISODE } from "../utils/constants"; | ||
|
||
export const EpisodeContext = createContext({ | ||
// the default episode. | ||
episodeId: DEFAULT_EPISODE, | ||
setEpisodeId: (episodeId: string) => { | ||
console.log("default episode"); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Home from "./views/Home"; | ||
|
||
export const AppModules = { | ||
bc23: { | ||
home: Home, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const DEFAULT_EPISODE = "bc23"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React, { useContext } from "react"; | ||
import { EpisodeContext } from "../contexts/EpisodeContext"; | ||
|
||
const Account: React.FC = () => { | ||
const { episodeId } = useContext(EpisodeContext); | ||
return <p>the episode is {episodeId} and this is the account page</p>; | ||
}; | ||
|
||
export default Account; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const Home: React.FC = () => { | ||
return <p>Homepage</p>; | ||
}; | ||
|
||
export default Home; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const Login: React.FC = () => { | ||
return <p>login page</p>; | ||
}; | ||
|
||
export default Login; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const Logout: React.FC = () => { | ||
return <p>logout page</p>; | ||
}; | ||
|
||
export default Logout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const NotFound: React.FC = () => { | ||
return <p>That page was not found.</p>; | ||
}; | ||
|
||
export default NotFound; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const PasswordChange: React.FC = () => { | ||
return <p>passwordchange page</p>; | ||
}; | ||
|
||
export default PasswordChange; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const PasswordForgot: React.FC = () => { | ||
return <p>passwordforgot page</p>; | ||
}; | ||
|
||
export default PasswordForgot; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from "react"; | ||
|
||
const QuickStart: React.FC = () => { | ||
return <p>quickstart page</p>; | ||
}; | ||
|
||
export default QuickStart; |
Oops, something went wrong.