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

feat: user auth #34

Merged
merged 13 commits into from
Sep 11, 2024
2 changes: 1 addition & 1 deletion backend-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"scripts": {
"generate": "./openapi-generator.sh remote https://app.dev.green-ecolution.de/api/v1",
"generate:ci": "./openapi-generator.sh local",
"generate:local": "./openapi-generator.sh remote http://localhost:8080/api/v1",
"generate:local": "./openapi-generator.sh remote http://localhost:3000/api/v1",
"generate:dev": "./openapi-generator.sh remote https://app.dev.green-ecolution.de/api/v1",
"build": "tsc"
},
Expand Down
30 changes: 12 additions & 18 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import { QueryClientProvider } from "@tanstack/react-query";
import queryClient from "./api/queryClient";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import React, { Suspense } from "react";
import { TreeDataContextProvider } from "./context/TreeDataContext";
import { Toaster } from "@/components/ui/sonner";
import { FakeTreeDataContextProvider } from "./context/FakeTreeDataContext";
import { TooltipProvider } from "./components/ui/tooltip";
import Footer from "./components/layout/Footer";
import Header from "./components/layout/Header";
Expand All @@ -25,22 +23,18 @@ function App() {
<Toaster />
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<TreeDataContextProvider>
<FakeTreeDataContextProvider>
<ReactQueryDevtools initialIsOpen={false} position="bottom" />
<Suspense>
<TanStackRouterDevtools
initialIsOpen={false}
position="bottom-right"
/>
</Suspense>
<Header />
<main className="flex-1 lg:pl-20">
<Outlet />
</main>
<Footer />
</FakeTreeDataContextProvider>
</TreeDataContextProvider>
<ReactQueryDevtools initialIsOpen={false} position="bottom" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to get the a variable out of the .env? We could hide the dev tools on production.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hidden when the release version is created, or when NODE_ENV is set to production.

<Suspense>
<TanStackRouterDevtools
initialIsOpen={false}
position="bottom-right"
/>
</Suspense>
<Header />
<main className="flex-1 lg:pl-20">
<Outlet />
</main>
<Footer />
</TooltipProvider>
</QueryClientProvider>
</>
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/api/backendApi.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import {
Configuration,
ConfigurationParameters,
HTTPHeaders,
InfoApi,
TreesApi,
UserApi,
} from "@green-ecolution/backend-client";

const headers: HTTPHeaders = {
"Content-Type": "application/json",
"Accept": "application/json",
};

const configParams: ConfigurationParameters = {
basePath: import.meta.env.VITE_BACKEND_BASEURL ?? "/api-local",
headers
};

const config = new Configuration(configParams);

export const treeApi = new TreesApi(config);
// export const treeApi = new TreesApi(config);
export const infoApi = new InfoApi(config);
export const userApi = new UserApi(config);

export * from "@green-ecolution/backend-client";
2 changes: 1 addition & 1 deletion frontend/src/components/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MapContainer, TileLayer } from "react-leaflet";
import React from "react";
import useMapStore from "@/store/map/store";
import useMapStore from "@/store/store";

export interface MapProps extends React.PropsWithChildren {
width?: string;
Expand Down
107 changes: 75 additions & 32 deletions frontend/src/components/layout/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
import { ArrowLeftRight, Car, FolderClosed, HardDrive, LogOut, Map, PieChart, Settings, Users } from 'lucide-react';
import * as React from 'react';
import NavLink from '../navigation/NavLink';
import NavHeadline from '../navigation/NavHeadline';
import NavHeader from '../navigation/NavHeader';
import {
ArrowLeftRight,
Bug,
Car,
FolderClosed,
HardDrive,
LogIn,
LogOut,
Map,
PieChart,
Settings,
Users,
} from "lucide-react";
import * as React from "react";
import NavLink from "../navigation/NavLink";
import NavHeadline from "../navigation/NavHeadline";
import NavHeader from "../navigation/NavHeader";
import useStore from "@/store/store";

interface NavigationProps {
isOpen: boolean;
openSidebar: () => void;
closeSidebar: () => void;
}

const Navigation: React.FC<NavigationProps> = ({ isOpen, openSidebar, closeSidebar }) => {
const isLargeScreen = () => window.matchMedia('(min-width: 1024px)').matches;
const Navigation: React.FC<NavigationProps> = ({
isOpen,
openSidebar,
closeSidebar,
}) => {
const isLargeScreen = () => window.matchMedia("(min-width: 1024px)").matches;
const isLoggedIn = useStore((state) => state.auth.isAuthenticated);
const mapPosition = useStore((state) => ({
lat: state.map.center[0],
lng: state.map.center[1],
zoom: state.map.zoom,
}));

const handleMouseOver = () => {
if (isLargeScreen()) openSidebar();
Expand All @@ -25,99 +48,119 @@ const Navigation: React.FC<NavigationProps> = ({ isOpen, openSidebar, closeSideb
if (!isLargeScreen()) closeSidebar();
};

const navigationLinks = [
const protectedNavLinks = [
{
headline: 'Grünflächen',
headline: "Grünflächen",
links: [
{
label: 'Baumkataster',
label: "Baumkataster",
icon: <Map className="w-5 h-5" />,
to: "/map",
to: `/map?lat=${mapPosition.lat}&lng=${mapPosition.lng}&zoom=${mapPosition.zoom}`,
},
{
label: 'Baumgruppen',
label: "Baumgruppen",
icon: <FolderClosed className="w-5 h-5" />,
to: "/treecluster",
},
{
label: 'Beete',
label: "Beete",
icon: <FolderClosed className="w-5 h-5" />,
to: "/",
},
],
},
{
headline: 'Einsatzplanung',
headline: "Einsatzplanung",
links: [
{
label: 'Einsätze',
label: "Einsätze",
icon: <ArrowLeftRight className="w-5 h-5" />,
to: "/waypoints",
},
{
label: 'Fahrzeuge',
label: "Fahrzeuge",
icon: <Car className="w-5 h-5" />,
to: "/vehicles",
},
{
label: 'Mitarbeitenden',
label: "Mitarbeitenden",
icon: <Users className="w-5 h-5" />,
to: "/team",
},
],
},
{
headline: 'Weiteres',
headline: "Weiteres",
links: [
{
label: 'Sensoren',
label: "Sensoren",
icon: <HardDrive className="w-5 h-5" />,
to: "/sensors",
},
{
label: 'Auswertungen',
label: "Auswertungen",
icon: <PieChart className="w-5 h-5" />,
to: "/evaluations",
},
{
label: 'Einstellungen',
label: "Einstellungen",
icon: <Settings className="w-5 h-5" />,
to: "/settings",
},
{
label: 'Ausloggen',
label: "Debug",
icon: <Bug className="w-5 h-5" />,
to: "/debug",
},
{
label: "Ausloggen",
icon: <LogOut className="w-5 h-5" />,
to: "/logout",
},
],
},
];

// This is currently invisible to the user as the application is redirected directly to the login page.
// Maybe for future use.
const publicNavLinks = [
{
headline: "",
links: [
{
label: "Anmelden",
icon: <LogIn className="w-5 h-5" />,
to: "/login",
},
],
},
];

const navigationLinks = isLoggedIn ? protectedNavLinks : publicNavLinks;

return (
<nav
id="main-navigation"
aria-label="Hauptnavigation"
onMouseOut={handleMouseOut}
onMouseOver={handleMouseOver}
className={`fixed inset-0 z-50 bg-dark w-screen overflow-hidden h-screen transition-all ease-in-out duration-300
${isOpen ? 'visible block left-0 lg:w-[17rem] lg:rounded-r-xl' : 'invisible -left-full lg:visible lg:w-[5rem] lg:left-0'}`}
${isOpen ? "visible block left-0 lg:w-[17rem] lg:rounded-r-xl" : "invisible -left-full lg:visible lg:w-[5rem] lg:left-0"}`}
>
<div className="relative px-4 py-5 h-full overflow-y-auto no-scrollbar">
<NavHeader
isOpen={isOpen}
closeSidebar={closeSidebar} />

<NavHeader isOpen={isOpen} closeSidebar={closeSidebar} />

{navigationLinks.map((section, index) => (
<React.Fragment key={index}>
<NavHeadline label={section.headline} navIsOpen={isOpen} />
<ul className="mb-10">
{section.links.map((link, key) => (
<NavLink
<NavLink
key={key}
label={link.label}
icon={link.icon}
label={link.label}
icon={link.icon}
url={link.to}
navIsOpen={isOpen}
navIsOpen={isOpen}
closeSidebar={handleNavLinkClick}
/>
))}
Expand All @@ -127,6 +170,6 @@ const Navigation: React.FC<NavigationProps> = ({ isOpen, openSidebar, closeSideb
</div>
</nav>
);
}
};

export default Navigation;
Loading
Loading