Compare commits
4 Commits
642083bad6
...
68501897e4
Author | SHA1 | Date | |
---|---|---|---|
68501897e4 | |||
6e3419019b | |||
d990c46a02 | |||
ea3b847268 |
1
size-plugin.json
Normal file
1
size-plugin.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{"timestamp":1646751614979,"files":[{"filename":"bundle.2a54a.css","previous":0,"size":1709,"diff":1709},{"filename":"bundle.*****.esm.js","previous":0,"size":9856,"diff":9856},{"filename":"polyfills.*****.esm.js","previous":0,"size":2187,"diff":2187},{"filename":"sw.js","previous":0,"size":10599,"diff":10599},{"filename":"sw-esm.js","previous":0,"size":10603,"diff":10603},{"filename":"bundle.1a7a6.js","previous":0,"size":11947,"diff":11947},{"filename":"polyfills.058fb.js","previous":0,"size":2288,"diff":2288},{"filename":"index.html","previous":0,"size":536,"diff":536},{"filename":"200.html","previous":0,"size":536,"diff":536}]}]
|
@ -1,57 +1,57 @@
|
|||||||
import { Component, createRef, h } from "preact";
|
import { h } from "preact";
|
||||||
import { Router } from "preact-router";
|
import { Router, route } from "preact-router";
|
||||||
import Header from "./header";
|
import {Header, Menu} from "./";
|
||||||
import Login from "../routes/login";
|
import { menuReducer, sessionReducer } from "../store/reducers";
|
||||||
import Profile from "../routes/profile";
|
import { useReducer } from "preact/hooks";
|
||||||
import Menu from "./menu";
|
import { Home, Users, Profile, Login, Logout } from "../route";
|
||||||
import Users from "../routes/users";
|
import { AppStateProvider } from "../store/AppState";
|
||||||
import { useCallback, useState } from "preact/hooks";
|
function App() {
|
||||||
const menu = createRef();
|
// useReducer
|
||||||
class App extends Component {
|
const menu = useReducer(menuReducer, false);
|
||||||
toggleMenu() {
|
const session = useReducer(sessionReducer, {active: true});
|
||||||
const [visible, setValue] = useState(false);
|
this.menu_items = [
|
||||||
const toggle = useCallback(() => {
|
{ text: "Übersicht", path: "/" },
|
||||||
setValue(!visible);
|
{ text: "Benutzer", path: "/users" },
|
||||||
return !visible;
|
{ text: "System", path: "/system" },
|
||||||
}, [visible]);
|
{ text: "Profil", path: "/profile" },
|
||||||
return { visible, toggle };
|
{ text: "Abmelden", path: "/logout" }
|
||||||
}
|
]
|
||||||
authenticateUser() {
|
this.handleRoute = async e => {
|
||||||
const [session, setValue] = useState({ token: null });
|
switch (e.url) {
|
||||||
const login = (username, password) => {
|
default:
|
||||||
if (username == "admin" && password == "admin") {
|
if (!session[0].active) route('/login', true);
|
||||||
setValue({ ...session, token: "ABCDEFG" });
|
break;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const logout = () => setValue({ ...session, token: null });
|
|
||||||
const isAuthenticated = () => session.token != null;
|
|
||||||
return { login, logout, isAuthenticated };
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const menu = this.toggleMenu();
|
|
||||||
const auth = this.authenticateUser();
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
|
<AppStateProvider value={{ menu, session}} >
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<Header menu={menu} auth={auth} />
|
<Header />
|
||||||
<Menu menu={menu} />
|
|
||||||
{!menu.visible &&
|
|
||||||
(!auth.isAuthenticated() ? (
|
|
||||||
<Login auth={auth} />
|
|
||||||
) : (
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<Router>
|
<Menu items={this.menu_items} />
|
||||||
<Profile path="/test/" user="me" />
|
{!menu[0] &&
|
||||||
<Profile path="/profile/:user" />
|
|
||||||
|
<Router onChange={this.handleRoute}>
|
||||||
|
<Home path="/" user="me" />
|
||||||
|
<Login path="login" />
|
||||||
|
<Profile path="/profile" />
|
||||||
|
<Logout path="/logout" />
|
||||||
<Users path="/users" />
|
<Users path="/users" />
|
||||||
<div class="container" default>Error 404</div>
|
<div class="container" default>Error 404</div>
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<div className="container" style={'text-align: center; align-items: center'}>
|
||||||
|
<span>© Jean Jacques Avril 2022 </span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</AppStateProvider>
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { Component, createRef, h } from 'preact';
|
import { useContext } from 'preact/hooks';
|
||||||
//import { Link } from 'preact-router/match';
|
import AppState from '../../store/AppState';
|
||||||
|
const Header = () => {
|
||||||
const Header = (props) => (
|
let { menu, session } = useContext(AppState);
|
||||||
|
let [menu_shown, toggle_menu] = menu;
|
||||||
|
let [sessiondata] = session;
|
||||||
|
return (
|
||||||
<header className='header'>
|
<header className='header'>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<h1>Login</h1>
|
<h1>Login</h1>
|
||||||
{props.auth.isAuthenticated() && (<div id="hamburger-button" className={`hamburger ${props.menu.visible && 'hamburger-active'}`}
|
{ sessiondata.active &&(<div id="hamburger-button" className={`hamburger ${menu_shown && 'hamburger-active'}`}
|
||||||
onClick={() => props.menu.toggle()}>
|
onClick={() => toggle_menu('toggle')}>
|
||||||
<hr />
|
<hr />
|
||||||
<hr />
|
<hr />
|
||||||
<hr />
|
<hr />
|
||||||
@ -14,7 +17,7 @@ const Header = (props) => (
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
9
src/components/index.js
Normal file
9
src/components/index.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import App from "./app";
|
||||||
|
import Breadcrumbs from "./breadcrumbs";
|
||||||
|
import Pageselector from "./Pageselector";
|
||||||
|
import Header from "./header";
|
||||||
|
import UserList from "./userlist";
|
||||||
|
import Menu from "./menu";
|
||||||
|
|
||||||
|
export {App, Breadcrumbs, Pageselector, Header, UserList, Menu}
|
||||||
|
export default App
|
@ -1,8 +1,10 @@
|
|||||||
import { Component, h } from 'preact';
|
import { h } from 'preact';
|
||||||
import { Link } from 'preact-router';
|
import { Link } from 'preact-router';
|
||||||
class Menu extends Component {
|
import { useContext } from 'preact/hooks';
|
||||||
|
import AppState from '../../store/AppState';
|
||||||
menu_items = [
|
function Menu({items}) {
|
||||||
|
let [ menu_shown, toggle_menu ] = useContext(AppState).menu;
|
||||||
|
let menu_items = [
|
||||||
{ text: "Übersicht", path: "/" },
|
{ text: "Übersicht", path: "/" },
|
||||||
{ text: "Benutzer", path: "/users" },
|
{ text: "Benutzer", path: "/users" },
|
||||||
{ text: "System", path: "/system" },
|
{ text: "System", path: "/system" },
|
||||||
@ -10,26 +12,25 @@ class Menu extends Component {
|
|||||||
{ text: "Abmelden", path: "/logout" }
|
{ text: "Abmelden", path: "/logout" }
|
||||||
]
|
]
|
||||||
|
|
||||||
getAlert() {
|
|
||||||
alert("getAlert from Child");
|
const onClick = (e) => {
|
||||||
}
|
|
||||||
onClick = (e) => {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.menu.toggle();
|
toggle_menu('hide');
|
||||||
}
|
}
|
||||||
render(props, state) {
|
|
||||||
if (props.menu.visible)
|
if (items)
|
||||||
|
menu_items = items;
|
||||||
|
if (menu_shown)
|
||||||
return (
|
return (
|
||||||
<div class="container" >
|
<div class="container" >
|
||||||
<nav className='menu' >
|
<nav className='menu' >
|
||||||
<ul>
|
<ul>
|
||||||
<li><Link href="/test" >Test</Link></li>
|
{menu_items.map((element, i) => (<li key={i}><Link href={element.path} onClick={onClick} >{element.text}</Link></li>))}
|
||||||
{this.menu_items.map((element, i) => (<li key={i}><Link href={element.path} onClick={this.onClick} >{element.text}</Link></li>))}
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
</div>)
|
</div>)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Menu;
|
export default Menu;
|
@ -1,6 +1,6 @@
|
|||||||
import './style/style.sass';
|
import './style/style.sass';
|
||||||
import App from './components/app';
|
import App from './components';
|
||||||
import { h, render, Component } from "preact"
|
import { h, render } from "preact"
|
||||||
|
|
||||||
render(<App />, document.body)
|
render(<App />, document.body)
|
||||||
//export default App;
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
import style from './style.css';
|
|
||||||
|
|
||||||
const Home = () => (
|
function Home() {return(
|
||||||
<div class={style.home}>
|
<div class="container">
|
||||||
<h1>Home</h1>
|
<h1>Home</h1>
|
||||||
<p>This is the Home component.</p>
|
<p>This is the Home component.</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
export default Home;
|
export default Home;
|
6
src/route/index.js
Normal file
6
src/route/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import Home from "./home"
|
||||||
|
import Users from './users'
|
||||||
|
import Profile from "./profile"
|
||||||
|
import Login from "./login"
|
||||||
|
import Logout from './logout'
|
||||||
|
export {Home, Users, Profile, Login, Logout }
|
55
src/route/login/index.jsx
Normal file
55
src/route/login/index.jsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
import { route } from 'preact-router';
|
||||||
|
import { useContext,useState } from 'preact/hooks';
|
||||||
|
import AppState from '../../store/AppState';
|
||||||
|
import Breadcrumbs from '../../components/breadcrumbs';
|
||||||
|
|
||||||
|
function Login() {
|
||||||
|
let [sessiondata, setsession]= useContext(AppState).session;
|
||||||
|
const [val, set] = useState({ username: '', password: '', error: null });
|
||||||
|
const navigation = ["Login"];
|
||||||
|
if(sessiondata.active)
|
||||||
|
route('/', true);
|
||||||
|
function onSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
//sucess
|
||||||
|
if (val.username === 'admin') {
|
||||||
|
let newsession = {
|
||||||
|
type: 'start',
|
||||||
|
username: 'affe',
|
||||||
|
token: 'dsf4w3qr'
|
||||||
|
}
|
||||||
|
setsession(newsession);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set({ ...val, error: "user" });
|
||||||
|
}
|
||||||
|
set({ username: '', password: '' });
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div class="container">
|
||||||
|
<Breadcrumbs items={navigation} />
|
||||||
|
|
||||||
|
<form id="login_form" onSubmit={onSubmit} >
|
||||||
|
<p >
|
||||||
|
Bitte melden Sie sich mit ihren Nutzerdaten an.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
{val.error !== null && <span style={'color: red'}>Fehler: Ungültige Anmeldedaten.</span>}
|
||||||
|
<div class="input-box">
|
||||||
|
<input id="name" type="text" placeholder="Username" onInput={e => set({ ...val, username: e.target.value })} value={val.username} />
|
||||||
|
<label for="name">Benutzername</label>
|
||||||
|
</div>
|
||||||
|
<div class="input-box">
|
||||||
|
<input id="pass" type="password" placeholder="Passwort" onInput={e => set({ ...val, password: e.target.value })} value={val.password} />
|
||||||
|
<label for="pass">Password</label>
|
||||||
|
</div>
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Login;
|
32
src/route/logout/index.jsx
Normal file
32
src/route/logout/index.jsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
import { Link } from 'preact-router';
|
||||||
|
import { useContext } from 'preact/hooks';
|
||||||
|
import AppState from '../../store/AppState';
|
||||||
|
import { Breadcrumbs } from '../../components';
|
||||||
|
|
||||||
|
function Logout() {
|
||||||
|
const navigation = ["Logout"];
|
||||||
|
let [sessiondata, setsession] = useContext(AppState).session;
|
||||||
|
this.shouldComponentUpdate = function () {
|
||||||
|
console.log('functional component vs closures');
|
||||||
|
}
|
||||||
|
if (sessiondata.active) {
|
||||||
|
setsession({ type: 'end' })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="container">
|
||||||
|
<Breadcrumbs items={navigation} />
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Erfolgreich abgemeldet.
|
||||||
|
<Link href="/login">Erneut Anmelden</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Logout;
|
@ -13,6 +13,7 @@ const Profile = ({ user }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className='container'>
|
||||||
<div class={style.profile}>
|
<div class={style.profile}>
|
||||||
<h1>Profile: {user}</h1>
|
<h1>Profile: {user}</h1>
|
||||||
<p>This is the user profile for a user named {user}.</p>
|
<p>This is the user profile for a user named {user}.</p>
|
||||||
@ -25,6 +26,7 @@ const Profile = ({ user }) => {
|
|||||||
Clicked {count} times.
|
Clicked {count} times.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
0
src/route/system/index.jsx
Normal file
0
src/route/system/index.jsx
Normal file
@ -1,5 +0,0 @@
|
|||||||
.home {
|
|
||||||
padding: 56px 20px;
|
|
||||||
min-height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
import { Component, h } from 'preact';
|
|
||||||
import Breadcrumbs from '../../components/breadcrumbs';
|
|
||||||
|
|
||||||
class Login extends Component {
|
|
||||||
state = { username: '', password: '' };
|
|
||||||
navigation = ["Login"];
|
|
||||||
onSubmit = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
console.log(this.state);
|
|
||||||
this.setState({ username: '', password: '' });
|
|
||||||
if(!this.props.auth.login(this.state.username,this.state.password))
|
|
||||||
alert("Wrong login")
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
return (<div id="login-screen" class="page">
|
|
||||||
<div class="container">
|
|
||||||
<Breadcrumbs items={this.navigation} />
|
|
||||||
|
|
||||||
<form id="login_form" onSubmit={this.onSubmit} >
|
|
||||||
<p>
|
|
||||||
Bitte melden Sie sich mit ihren Nutzerdaten an.
|
|
||||||
</p>
|
|
||||||
<div class="input-box">
|
|
||||||
<input id="name" type="text" placeholder="Username" onInput={e => this.setState(prev => ({ ...prev, username: e.target.value }))} value={this.state.username} />
|
|
||||||
<label for="name">Benutzername</label>
|
|
||||||
</div>
|
|
||||||
<div class="input-box">
|
|
||||||
<input id="pass" type="password" placeholder="Passwort" onInput={e => this.setState(prev => ({ ...prev, password: e.target.value }))} value={this.state.password} />
|
|
||||||
<label for="pass">Password</label>
|
|
||||||
</div>
|
|
||||||
<input type="submit" value="Submit" />
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Login;
|
|
6
src/store/AppState.js
Normal file
6
src/store/AppState.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { createContext } from "preact";
|
||||||
|
|
||||||
|
const AppState = createContext({});
|
||||||
|
|
||||||
|
export const AppStateProvider = AppState.Provider;
|
||||||
|
export default AppState;
|
16
src/store/reducers.js
Normal file
16
src/store/reducers.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const menuReducer = (state, action) => {
|
||||||
|
switch (action) {
|
||||||
|
case 'show': return true;
|
||||||
|
case 'hide': return false;
|
||||||
|
case 'toggle': return !state;
|
||||||
|
default: throw new Error("menustate unknown to reducer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sessionReducer = (state, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'start': return {active: true, token: action.token, username: action.username}
|
||||||
|
case 'end': return {active: false, token: null, username: null, exiry: null}
|
||||||
|
default: throw new Error("action type unknown to session reducer");
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
@mixin breadcrumbs
|
@mixin breadcrumbs
|
||||||
padding: 1em 0
|
padding-top: 1rem
|
||||||
ul
|
ul
|
||||||
display: flex
|
display: flex
|
||||||
background: #eee
|
background: #eee
|
||||||
box-shadow: inset 0 0 .3em #ccc, 0 0 .5em #ddd
|
box-shadow: inset 0 0 .3em #ccc, 0 0 .5em #ddd
|
||||||
padding: .3em
|
padding: .3em
|
||||||
|
margin: 0
|
||||||
border: 0.05em solid #fff
|
border: 0.05em solid #fff
|
||||||
border-radius: .3em
|
border-radius: .3em
|
||||||
list-style-type: none
|
list-style-type: none
|
||||||
|
9
src/style/_footer.sass
Normal file
9
src/style/_footer.sass
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@mixin footer
|
||||||
|
display: block
|
||||||
|
background: #bbb
|
||||||
|
text-shadow: 0 0 .2em #34d
|
||||||
|
color: white
|
||||||
|
flex-shrink: 0
|
||||||
|
padding: 0.5rem 0
|
||||||
|
margin-top: 1rem
|
||||||
|
width: 100%
|
@ -16,6 +16,9 @@
|
|||||||
//text-shadow: 0 0 .2em #000
|
//text-shadow: 0 0 .2em #000
|
||||||
width: 100%
|
width: 100%
|
||||||
//background: #ccc
|
//background: #ccc
|
||||||
|
&:hover
|
||||||
|
background: #bbb
|
||||||
|
color: #333
|
||||||
&::after
|
&::after
|
||||||
top: 100%
|
top: 100%
|
||||||
left: 0
|
left: 0
|
||||||
|
@ -3,18 +3,19 @@
|
|||||||
@use 'login'
|
@use 'login'
|
||||||
@use 'breadcrumbs'
|
@use 'breadcrumbs'
|
||||||
@use 'pageselector'
|
@use 'pageselector'
|
||||||
|
@use 'footer'
|
||||||
*
|
*
|
||||||
//border: red 1px dotted
|
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
html
|
html
|
||||||
font-family: Helvetica, sans-serif
|
font-family: Helvetica, sans-serif
|
||||||
font-size: 16px
|
font-size: 16px
|
||||||
|
height: 100%
|
||||||
body
|
body
|
||||||
|
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
background-color: white
|
background-color: white
|
||||||
//min-height: 100vh
|
height: 100%
|
||||||
width: 100%
|
width: 100%
|
||||||
#wrapper
|
#wrapper
|
||||||
display: flex
|
display: flex
|
||||||
@ -22,12 +23,14 @@ body
|
|||||||
justify-content: flex-start
|
justify-content: flex-start
|
||||||
align-items: stretch
|
align-items: stretch
|
||||||
min-height: 100%
|
min-height: 100%
|
||||||
|
//margin-bottom: -2rem
|
||||||
width: 100%
|
width: 100%
|
||||||
.header
|
.header
|
||||||
z-index: 100
|
z-index: 100
|
||||||
position: fixed
|
position: fixed
|
||||||
|
top: 0em
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 4em
|
height: 4rem
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
justify-content: flex-end
|
justify-content: flex-end
|
||||||
@ -54,7 +57,9 @@ body
|
|||||||
display: flex
|
display: flex
|
||||||
background: white
|
background: white
|
||||||
width: 100%
|
width: 100%
|
||||||
padding-top: 6em
|
flex: 1
|
||||||
|
margin-top: 4rem
|
||||||
|
|
||||||
.menu
|
.menu
|
||||||
@include menu.nav
|
@include menu.nav
|
||||||
|
|
||||||
@ -124,3 +129,6 @@ body
|
|||||||
.btn-edit
|
.btn-edit
|
||||||
@include button()
|
@include button()
|
||||||
background-image: url("../assets/icons/edit-icon3.svg")
|
background-image: url("../assets/icons/edit-icon3.svg")
|
||||||
|
|
||||||
|
footer
|
||||||
|
@include footer.footer
|
Loading…
x
Reference in New Issue
Block a user