Skip to content
This repository has been archived by the owner on Jan 31, 2023. It is now read-only.

Adds basic layout #17

Merged
merged 5 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
Adds basic layout and very lightly styled header
  • Loading branch information
madsnedergaard committed Nov 3, 2022
commit 9bb8691383acde21157d5b5dd6c00b905e417838
2 changes: 1 addition & 1 deletion web/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="text-gray-900 antialiased dark:bg-gray-800 dark:text-white">
<html lang="en" class="antialiased">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
Expand Down
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"react-dom": "18.2.0",
"react-map-gl": "^7.0.19",
"react-router-dom": "6.3.0",
"tailwindcss-classnames": "^3.0.6",
madsnedergaard marked this conversation as resolved.
Show resolved Hide resolved
"tiny-invariant": "^1.3.1"
},
"devDependencies": {
Expand Down Expand Up @@ -81,7 +82,6 @@
"prettier-plugin-tailwindcss": "0.1.13",
"start-server-and-test": "1.14.0",
"tailwindcss": "3.1.8",
"tailwindcss-classnames": "^3.0.6",
"typescript": "4.8.4",
"vite": "3.1.8",
"vite-plugin-pwa": "0.13.1",
Expand Down
26 changes: 26 additions & 0 deletions web/public/electricity-maps-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 13 additions & 5 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import LoadingOrError from 'components/LoadingOrError';
import LeftPanel from 'features/panels/LeftPanel';
import ErrorBoundary from 'features/error-boundary/ErrorBoundary';
import Header from 'features/header/Header';
import type { ReactElement } from 'react';
import { lazy, Suspense } from 'react';

const Map = lazy(async () => import('features/map/Map'));
const LeftPanel = lazy(async () => import('features/panels/LeftPanel'));

export default function App(): ReactElement {
return (
<Suspense fallback={<LoadingOrError />}>
<LeftPanel />
<Map />
<Suspense fallback={<div />}>
<div className="h-full">
<Header />
<div className="flex h-screen">
<ErrorBoundary>
madsnedergaard marked this conversation as resolved.
Show resolved Hide resolved
<LeftPanel />
<Map />
</ErrorBoundary>
</div>
</div>
</Suspense>
);
}
57 changes: 57 additions & 0 deletions web/src/features/error-boundary/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Component, ErrorInfo, ReactNode } from 'react';

interface Props {
children?: ReactNode;
}

interface State {
hasError: boolean;
error: Error | undefined;
}

class ErrorBoundary extends Component<Props, State> {
public state: State = {
hasError: false,
error: undefined,
};

public static getDerivedStateFromError(error: Error): State {
// Update state so the next render will show the fallback UI.
return { hasError: true, error: error };
}

public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// TODO: Send this to Sentry
console.error('Uncaught error:', error, errorInfo);
}

public render() {
if (this.state.hasError) {
const url = window.location.href;
return (
<div className="flex w-full flex-col items-center justify-center">
<h1>Oh no, something went wrong...</h1>
<p>
Please let us know <a href="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/electricityMaps/electricitymaps-contrib">on Github</a> so we
can fix this!
</p>
<pre className="rounded-lg bg-gray-300 p-2 text-xs">
Error message: {this.state.error?.message}
<br />
Url: {url}
</pre>
<a
href="/map"
className="mt-4 cursor-pointer rounded-lg border border-gray-200 bg-gray-100 p-2 text-base text-black"
>
Back to map
</a>
</div>
);
}

return this.props.children;
}
}

export default ErrorBoundary;
52 changes: 52 additions & 0 deletions web/src/features/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import { classnames } from 'tailwindcss-classnames';

interface MenuLinkProps {
href: string;
children: React.ReactNode;
active?: boolean;
}
function MenuLink({ children, href, active }: MenuLinkProps): JSX.Element {
return (
<div className="relative flex py-2 ">
<NavigationMenu.Item asChild className="rounded-md transition-colors hover:bg-zinc-100">
<NavigationMenu.Link
active={active}
href={href}
className={classnames('px-2 py-2 text-sm', active && 'font-bold')}
>
{children}
{active && <div className="absolute left-0 bottom-0 h-[2px] w-full bg-green-500"></div>}
</NavigationMenu.Link>
</NavigationMenu.Item>
</div>
);
}

export default function Header(): JSX.Element {
return (
<div className="flex items-center justify-between pl-4 pr-8 shadow-md">
<img src="/electricity-maps-logo.svg" alt="" className="w-100 h-10" />

<NavigationMenu.Root>
<NavigationMenu.List className="flex space-x-2">
<MenuLink href="/" active>
Live
</MenuLink>
<MenuLink href="https://electricitymaps.com/open-source/?utm_source=app.electricitymaps.com&utm_medium=referral">
We&apos;re hiring!
</MenuLink>
<MenuLink href="https://electricitymaps.com/open-source/?utm_source=app.electricitymaps.com&utm_medium=referral">
Open Source
</MenuLink>
<MenuLink href="https://electricitymaps.com/blog/?utm_source=app.electricitymaps.com&utm_medium=referral">
Blog
</MenuLink>
<MenuLink href="https://electricitymaps.com?utm_source=app.electricitymaps.com&utm_medium=referral">
Get our data
</MenuLink>
</NavigationMenu.List>
</NavigationMenu.Root>
</div>
);
}
31 changes: 15 additions & 16 deletions web/src/features/panels/LeftPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BrowserRouter, Navigate, Route, Routes, useParams } from 'react-router-dom';
import { Navigate, Route, Routes, useParams } from 'react-router-dom';
import ZoneDetails from './Zone/ZoneDetails';

function ValidZoneIdGuardWrapper({ children }: { children: JSX.Element }): JSX.Element {
Expand All @@ -12,21 +12,20 @@ function ValidZoneIdGuardWrapper({ children }: { children: JSX.Element }): JSX.E

export default function LeftPanel(): JSX.Element {
return (
<div className="left-panel">
<BrowserRouter>
<Routes>
<Route path="/" element={<p>Ranking</p>} />
<Route path="/map" element={<p>Ranking</p>} />
<Route
path="/zone/:zoneId"
element={
<ValidZoneIdGuardWrapper>
<ZoneDetails />
</ValidZoneIdGuardWrapper>
}
/>
</Routes>
</BrowserRouter>
<div className=" flex w-4/12 bg-zinc-200 shadow-lg">
<Routes>
<Route path="/" element={<p>Ranking Panel</p>} />
<Route
path="/zone/:zoneId"
element={
<ValidZoneIdGuardWrapper>
<ZoneDetails />
</ValidZoneIdGuardWrapper>
}
/>
{/* Alternative: add /map here and have a NotFound component for anything else*/}
<Route path="*" element={<p>Ranking Panel</p>} />
</Routes>
</div>
);
}
6 changes: 6 additions & 0 deletions web/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@
src: url('/fonts/Inter-Bold.woff2') format('woff2');
}
}

html,
body,
#root {
@apply h-full;
}
4 changes: 3 additions & 1 deletion web/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ if (container) {
root.render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</StrictMode>
Expand Down