webui: Add basic panel layout

This commit is contained in:
Kevin Kandlbinder 2022-03-04 01:59:39 +01:00
parent 45ca353b3f
commit ac5faca859
5 changed files with 136 additions and 11 deletions

View file

@ -1,5 +1,5 @@
import React, {useState} from 'react';
import { Routes, Route, Link } from "react-router-dom";
import React from 'react';
import { Routes, Route } from "react-router-dom";
import AuthLayout from "./layouts/AuthLayout";
import LoginView from "./components/auth/LoginView";
import RegisterView from "./components/auth/RegisterView";
@ -7,6 +7,7 @@ import RequireAuth from "./features/auth/RequireAuth";
import {useAppDispatch} from "./app/hooks";
import broadcastChannel from "./app/broadcastChannel";
import {logOut, receiveAuthUpdate} from "./features/auth/authSlice";
import PanelLayout from "./layouts/PanelLayout";
function App() {
const dispatch = useAppDispatch()
@ -23,10 +24,14 @@ function App() {
<Route path={"login"} element={<LoginView/>} />
<Route path={"register"} element={<RegisterView/>} />
</Route>
<Route path={"/"} element={<RequireAuth><h1>hi</h1> <button onClick={() => {
dispatch(logOut())
}
}>Log out</button></RequireAuth>}/>
<Route path={"/"} element={<PanelLayout/>}>
<Route path={""} element={<RequireAuth><h1>hi</h1> <button onClick={() => {
dispatch(logOut())
}
}>Log out</button></RequireAuth>} />
<Route path={"hashing/lists"} element={<RequireAuth><h1>lists</h1></RequireAuth>} />
<Route path={"hashing/entries"} element={<RequireAuth><h1>entries</h1></RequireAuth>} />
</Route>
</Routes>
);
}

View file

@ -1,6 +1,6 @@
import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit';
import {RootState, AppThunk} from '../../app/store';
import broadcastChannel, { BroadcastMessage, sendMessage } from "../../app/broadcastChannel";
import {createSlice, PayloadAction} from '@reduxjs/toolkit';
import {RootState} from '../../app/store';
import { BroadcastMessage, sendMessage } from "../../app/broadcastChannel";
export interface AuthState {
jwt: string|null;

View file

@ -5,7 +5,7 @@ import {Link, useLocation, useNavigate, useOutlet} from "react-router-dom";
import {UserPlus, User} from "lucide-react";
import {ReactComponent as Logo} from "../logo.svg";
import {useAppDispatch, useAppSelector} from "../app/hooks";
import {useAppSelector} from "../app/hooks";
import {selectAuth} from "../features/auth/authSlice";
export type AuthLocationState = {
@ -18,7 +18,6 @@ const AuthLayout = () => {
const locationState = location.state as AuthLocationState
const dispatch = useAppDispatch()
const authState = useAppSelector(selectAuth)
const navigate = useNavigate()

View file

@ -0,0 +1,88 @@
@import "../globals";
.skipToContent {
opacity: 0;
pointer-events: none;
padding: var(--veles-layout-padding-slim);
background-color: var(--veles-color-background);
color: var(--veles-color-foreground);
position: absolute;
top: 0;
left: 0;
&:focus {
opacity: 1;
pointer-events: auto;
}
}
@mixin panelTopBarLink {
padding: var(--veles-layout-padding-slim) var(--veles-layout-padding);
display: flex;
align-items: center;
text-decoration: none;
transition: color .25s;
font-weight: 600;
&:hover, &.active, &:focus {
color: var(--veles-color-accent);
}
> svg {
margin-right: var(--veles-layout-padding);
width: 25px;
height: 25px;
stroke-width: 1;
}
}
.panel {
width: 100vw;
height: 100vh;
background-color: var(--veles-color-background);
color: var(--veles-color-foreground);
display: flex;
flex-direction: column;
.topBar {
display: flex;
border-bottom: thin solid var(--veles-color-border);
a {
@include panelTopBarLink;
}
.logo {
margin-right: auto;
> svg {
width: 40px;
height: 40px;
}
}
}
.content {
display: flex;
align-items: stretch;
flex-grow: 1;
> nav {
display: flex;
flex-direction: column;
border-right: thin solid var(--veles-color-border);
a {
@include panelTopBarLink;
padding: var(--veles-layout-padding);
}
}
> main {
padding: var(--veles-layout-padding)
}
}
}

View file

@ -0,0 +1,33 @@
import React from "react";
import {Link, NavLink, useOutlet} from "react-router-dom";
import {Home, List, ClipboardList, ExternalLink} from "lucide-react";
import {ReactComponent as Logo} from "../logo.svg";
import styles from "./PanelLayout.module.scss";
const PanelLayout = () => {
const outlet = useOutlet();
return <div className={styles.panel}>
<a href={"#main"} className={styles.skipToContent}>Jump to Content</a>
<a href={"#navigation"} className={styles.skipToContent}>Jump to Navigation</a>
<div className={styles.topBar}>
<Link to={"/"} className={styles.logo}><Logo/> <span>Matrix-Veles</span></Link>
<a href={"https://veles.1in1.net/docs/intro"} target={"_blank"} rel={"noreferrer"}><ExternalLink/> <span>Documentation</span></a>
</div>
<div className={styles.content}>
<nav id={"navigation"}>
<NavLink to={"/"}><Home/><span>Dashboard</span></NavLink>
<NavLink to={"/hashing/lists"}><List/><span>Lists</span></NavLink>
<NavLink to={"/hashing/entries"}><ClipboardList/><span>Entries</span></NavLink>
</nav>
<main id={"main"}>
{outlet}
</main>
</div>
</div>
}
export default PanelLayout