added api connectin to create and update user interface
This commit is contained in:
parent
c97d12e669
commit
a0adef9ec5
@ -1 +1 @@
|
|||||||
[{"timestamp":1646924506348,"files":[{"filename":"index.html","previous":487,"size":487,"diff":0},{"filename":"bundle.45d14.css","previous":1691,"size":1691,"diff":0},{"filename":"bundle.*****.js","previous":12153,"size":14680,"diff":2527},{"filename":"polyfills.*****.js","previous":2288,"size":2288,"diff":0}]},{"timestamp":1646755354217,"files":[{"filename":"bundle.*****.esm.js","previous":9839,"size":0,"diff":-9839},{"filename":"polyfills.*****.esm.js","previous":2187,"size":0,"diff":-2187},{"filename":"sw.js","previous":10597,"size":0,"diff":-10597},{"filename":"sw-esm.js","previous":10603,"size":0,"diff":-10603},{"filename":"polyfills.058fb.js","previous":2288,"size":0,"diff":-2288},{"filename":"index.html","previous":521,"size":487,"diff":-34},{"filename":"200.html","previous":521,"size":0,"diff":-521},{"filename":"bundle.45d14.css","previous":1691,"size":1691,"diff":0},{"filename":"bundle.caa2d.js","previous":12219,"size":0,"diff":-12219},{"filename":"bundle.*****.js","previous":0,"size":12153,"diff":12153},{"filename":"polyfills.*****.js","previous":0,"size":2288,"diff":2288}]},{"timestamp":1646755194517,"files":[{"filename":"bundle.2a54a.css","previous":1709,"size":0,"diff":-1709},{"filename":"bundle.*****.esm.js","previous":9842,"size":9839,"diff":-3},{"filename":"polyfills.*****.esm.js","previous":2187,"size":2187,"diff":0},{"filename":"sw.js","previous":10595,"size":10597,"diff":2},{"filename":"sw-esm.js","previous":10600,"size":10603,"diff":3},{"filename":"polyfills.058fb.js","previous":2288,"size":2288,"diff":0},{"filename":"index.html","previous":536,"size":521,"diff":-15},{"filename":"200.html","previous":536,"size":521,"diff":-15},{"filename":"bundle.3030b.js","previous":12224,"size":0,"diff":-12224},{"filename":"bundle.45d14.css","previous":0,"size":1691,"diff":1691},{"filename":"bundle.caa2d.js","previous":0,"size":12219,"diff":12219}]},{"timestamp":1646755054393,"files":[{"filename":"bundle.2a54a.css","previous":1709,"size":1709,"diff":0},{"filename":"bundle.*****.esm.js","previous":9856,"size":9842,"diff":-14},{"filename":"polyfills.*****.esm.js","previous":2187,"size":2187,"diff":0},{"filename":"sw.js","previous":10599,"size":10595,"diff":-4},{"filename":"sw-esm.js","previous":10603,"size":10600,"diff":-3},{"filename":"bundle.1a7a6.js","previous":11947,"size":0,"diff":-11947},{"filename":"polyfills.058fb.js","previous":2288,"size":2288,"diff":0},{"filename":"index.html","previous":536,"size":536,"diff":0},{"filename":"200.html","previous":536,"size":536,"diff":0},{"filename":"bundle.3030b.js","previous":0,"size":12224,"diff":12224}]},{"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}]}]
|
[{"timestamp":1646927116411,"files":[{"filename":"index.html","previous":487,"size":487,"diff":0},{"filename":"bundle.45d14.css","previous":1691,"size":1691,"diff":0},{"filename":"bundle.*****.js","previous":14680,"size":14692,"diff":12},{"filename":"polyfills.*****.js","previous":2288,"size":2288,"diff":0}]},{"timestamp":1646924506348,"files":[{"filename":"index.html","previous":487,"size":487,"diff":0},{"filename":"bundle.45d14.css","previous":1691,"size":1691,"diff":0},{"filename":"bundle.*****.js","previous":12153,"size":14680,"diff":2527},{"filename":"polyfills.*****.js","previous":2288,"size":2288,"diff":0}]},{"timestamp":1646755354217,"files":[{"filename":"bundle.*****.esm.js","previous":9839,"size":0,"diff":-9839},{"filename":"polyfills.*****.esm.js","previous":2187,"size":0,"diff":-2187},{"filename":"sw.js","previous":10597,"size":0,"diff":-10597},{"filename":"sw-esm.js","previous":10603,"size":0,"diff":-10603},{"filename":"polyfills.058fb.js","previous":2288,"size":0,"diff":-2288},{"filename":"index.html","previous":521,"size":487,"diff":-34},{"filename":"200.html","previous":521,"size":0,"diff":-521},{"filename":"bundle.45d14.css","previous":1691,"size":1691,"diff":0},{"filename":"bundle.caa2d.js","previous":12219,"size":0,"diff":-12219},{"filename":"bundle.*****.js","previous":0,"size":12153,"diff":12153},{"filename":"polyfills.*****.js","previous":0,"size":2288,"diff":2288}]},{"timestamp":1646755194517,"files":[{"filename":"bundle.2a54a.css","previous":1709,"size":0,"diff":-1709},{"filename":"bundle.*****.esm.js","previous":9842,"size":9839,"diff":-3},{"filename":"polyfills.*****.esm.js","previous":2187,"size":2187,"diff":0},{"filename":"sw.js","previous":10595,"size":10597,"diff":2},{"filename":"sw-esm.js","previous":10600,"size":10603,"diff":3},{"filename":"polyfills.058fb.js","previous":2288,"size":2288,"diff":0},{"filename":"index.html","previous":536,"size":521,"diff":-15},{"filename":"200.html","previous":536,"size":521,"diff":-15},{"filename":"bundle.3030b.js","previous":12224,"size":0,"diff":-12224},{"filename":"bundle.45d14.css","previous":0,"size":1691,"diff":1691},{"filename":"bundle.caa2d.js","previous":0,"size":12219,"diff":12219}]},{"timestamp":1646755054393,"files":[{"filename":"bundle.2a54a.css","previous":1709,"size":1709,"diff":0},{"filename":"bundle.*****.esm.js","previous":9856,"size":9842,"diff":-14},{"filename":"polyfills.*****.esm.js","previous":2187,"size":2187,"diff":0},{"filename":"sw.js","previous":10599,"size":10595,"diff":-4},{"filename":"sw-esm.js","previous":10603,"size":10600,"diff":-3},{"filename":"bundle.1a7a6.js","previous":11947,"size":0,"diff":-11947},{"filename":"polyfills.058fb.js","previous":2288,"size":2288,"diff":0},{"filename":"index.html","previous":536,"size":536,"diff":0},{"filename":"200.html","previous":536,"size":536,"diff":0},{"filename":"bundle.3030b.js","previous":0,"size":12224,"diff":12224}]},{"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,40 +1,70 @@
|
|||||||
const server = 'http://192.168.4.22'
|
const server = 'http://192.168.4.22'
|
||||||
|
|
||||||
async function login(username,password){
|
async function login(username, password) {
|
||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
formData.append('username',username)
|
formData.append('username', username)
|
||||||
formData.append('password',password);
|
formData.append('password', password);
|
||||||
formData.append('action','login');
|
formData.append('action', 'login');
|
||||||
const resp = await fetch(`${server}/api/auth`,{method: 'POST',mode: 'cors',body:formData }).then(resp=>resp.text())
|
const resp = fetch(`${server}/api/auth`, { method: 'POST', mode: 'cors', body: formData }).then(resp => resp.text());
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
function logout(){
|
async function logout(token) {
|
||||||
return 'DUMMYTOKEN';
|
let formData = new FormData()
|
||||||
|
formData.append('token', token);
|
||||||
|
formData.append('action', 'logout');
|
||||||
|
const resp = fetch(`${server}/api/auth`, { method: 'POST', mode: 'cors', body: formData }).then(resp => resp.text());
|
||||||
|
return resp;
|
||||||
}
|
}
|
||||||
function checkAuth(token){
|
function checkAuth(token) {
|
||||||
return token==='DUMMYTOKEN';
|
return token === 'DUMMYTOKEN';
|
||||||
}
|
}
|
||||||
async function fetchdb(token='azif7eqCl5'){
|
async function fetchdb(token = 'azif7eqCl5') {
|
||||||
//fetch(`${server}/api/userdb`).then()
|
//fetch(`${server}/api/userdb`).then()
|
||||||
//let xmlHttp = new XMLHttpRequest();
|
//let xmlHttp = new XMLHttpRequest();
|
||||||
//xmlHttp.open( "GET", `${server}/api/userdb`, false ); // false for synchronous request
|
//xmlHttp.open( "GET", `${server}/api/userdb`, false ); // false for synchronous request
|
||||||
//xmlHttp.send( null );
|
//xmlHttp.send( null );
|
||||||
const resp = await fetch(`${server}/api/userdb`,{method: 'GET',mode: 'cors',headers:{Authentification:token}})
|
const resp = await fetch(`${server}/api/userdb`, { method: 'GET', mode: 'cors', headers: { Authentification: token } })
|
||||||
.then(resp=>resp.text()).then(text=>parsedb(text))
|
.then(resp => resp.text()).then(text => parsedb(text))
|
||||||
return resp;
|
return resp;
|
||||||
|
|
||||||
}
|
}
|
||||||
function parsedb(raw){
|
function createCsvTable(userdb) {
|
||||||
|
let res = '';
|
||||||
|
let first = true;
|
||||||
|
for (let u of userdb) {
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
res += `${!first && '\n'}${u.uid},${u.first_name},${u.last_name},${u.rfid_uid},${u.user_pin},${u.enabled ? '1' : '0'}`;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
async function updateUser(token, user) {
|
||||||
|
const resp = await fetch(`${server}/api/user/`, { method: 'POST', body: JSON.stringify(user), mode: 'cors', headers: { Authentification: token } })
|
||||||
|
.then(resp => resp.json());
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
async function deleteUser(token, user) {
|
||||||
|
const resp = await fetch(`${server}/api/user/${user.uid}`, { method: 'DELETE', body: JSON.stringify(user), mode: 'cors', headers: { Authentification: token } })
|
||||||
|
.then(resp => resp.json());
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
async function createUser(token, user) {
|
||||||
|
const resp = await fetch(`${server}/api/user/`, { method: 'PUT', body: JSON.stringify(user), mode: 'cors', headers: { Authentification: token } })
|
||||||
|
.then(resp => resp.json());
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
function parsedb(raw) {
|
||||||
|
|
||||||
let lines = raw.split('\n');
|
let lines = raw.split('\n');
|
||||||
let users = [];
|
let users = [];
|
||||||
lines.map((l,line)=>{
|
lines.map((l, line) => {
|
||||||
let [uid, first_name, last_name, rfid_uid, user_pin, active] = l.split([';']);
|
let [uid, first_name, last_name, rfid_uid, user_pin, enabled] = l.split([';']);
|
||||||
users.push({ line, uid, first_name, last_name, rfid_uid, user_pin, enabled: active[0]==='1' });
|
users.push({ line, uid, first_name, last_name, rfid_uid, user_pin, enabled: enabled[0] === '1' });
|
||||||
});
|
});
|
||||||
return users;
|
return users;
|
||||||
|
|
||||||
}
|
}
|
||||||
const publicfunctions = {login, logout, checkAuth, parsedb, fetchdb};
|
const publicfunctions = { login, logout, checkAuth, parsedb,fetchdb, createCsvTable, updateUser, deleteUser, createUser };
|
||||||
export default {...publicfunctions}
|
export default { ...publicfunctions }
|
||||||
export {login, logout, checkAuth, parsedb}
|
export { login, logout, checkAuth, parsedb,fetchdb, createCsvTable, updateUser, deleteUser, createUser }
|
@ -8,12 +8,13 @@ import { AppStateProvider, UserTableProvider, menuReducer, sessionReducer, userT
|
|||||||
function App() {
|
function App() {
|
||||||
// useReducer
|
// useReducer
|
||||||
const menu = useReducer(menuReducer, false);
|
const menu = useReducer(menuReducer, false);
|
||||||
const session = useReducer(sessionReducer, { active: false });
|
const session = useReducer(sessionReducer, { active:true ,token: "0t6BF94Y92" });
|
||||||
const [usertable, userreducer] = useReducer(userTableReducer, []);
|
const [usertable, userreducer] = useReducer(userTableReducer, []);
|
||||||
|
|
||||||
this.menu_items = [
|
this.menu_items = [
|
||||||
{ text: "Übersicht", path: "/" },
|
{ text: "Übersicht", path: "/" },
|
||||||
{ text: "Benutzer", path: "/users" },
|
{ text: "Benutzer anlegen", path: "/newuser" },
|
||||||
|
{ text: "Benutzer verwalten", path: "/users" },
|
||||||
{ text: "System", path: "/system" },
|
{ text: "System", path: "/system" },
|
||||||
{ text: "Abmelden", path: "/logout" }
|
{ text: "Abmelden", path: "/logout" }
|
||||||
]
|
]
|
||||||
@ -28,7 +29,7 @@ function App() {
|
|||||||
|
|
||||||
<AppStateProvider value={{ menu, session }} >
|
<AppStateProvider value={{ menu, session }} >
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<Header />
|
<Header title={"Doorlock"} />
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<Menu items={this.menu_items} />
|
<Menu items={this.menu_items} />
|
||||||
{!menu[0] &&
|
{!menu[0] &&
|
||||||
@ -39,7 +40,8 @@ function App() {
|
|||||||
<System path="/system" />
|
<System path="/system" />
|
||||||
<Logout path="/logout" />
|
<Logout path="/logout" />
|
||||||
<Users path="/users/:pageid?" />
|
<Users path="/users/:pageid?" />
|
||||||
<EditUser path="/edituser/:userid" />
|
<EditUser path="/edituser/:userid?" />
|
||||||
|
<EditUser path="/newuser" />
|
||||||
<div class="container" default>Error 404</div>
|
<div class="container" default>Error 404</div>
|
||||||
</Router>
|
</Router>
|
||||||
</UserTableProvider>
|
</UserTableProvider>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { useContext } from 'preact/hooks';
|
import { useContext } from 'preact/hooks';
|
||||||
import AppState from '../../store/AppState';
|
import AppState from '../../store/AppState';
|
||||||
const Header = () => {
|
const Header = ({title}) => {
|
||||||
let { menu, session } = useContext(AppState);
|
let { menu, session } = useContext(AppState);
|
||||||
let [menu_shown, toggle_menu] = menu;
|
let [menu_shown, toggle_menu] = menu;
|
||||||
let [sessiondata] = session;
|
let [sessiondata] = session;
|
||||||
return (
|
return (
|
||||||
<header className='header'>
|
<header className='header'>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<h1>Login</h1>
|
<h1>{title}</h1>
|
||||||
{ sessiondata.active &&(<div id="hamburger-button" className={`hamburger ${menu_shown && 'hamburger-active'}`}
|
{ sessiondata.active &&(<div id="hamburger-button" className={`hamburger ${menu_shown && 'hamburger-active'}`}
|
||||||
onClick={() => toggle_menu('toggle')}>
|
onClick={() => toggle_menu('toggle')}>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -1,35 +1,54 @@
|
|||||||
import {h} from 'preact';
|
import { h } from 'preact';
|
||||||
import { useContext, useState } from 'preact/hooks';
|
import { useContext, useEffect, useState } from 'preact/hooks';
|
||||||
import { route } from 'preact-router';
|
import { route } from 'preact-router';
|
||||||
import { UserTable } from "../../store";
|
import AppState, { UserTable } from "../../store";
|
||||||
function EditUser({userid}){
|
import api from '../../api'
|
||||||
|
function EditUser({ userid }) {
|
||||||
|
let [sessiondata,] = useContext(AppState).session;
|
||||||
const { usertable, userreducer } = useContext(UserTable);
|
const { usertable, userreducer } = useContext(UserTable);
|
||||||
let user = usertable.find(u=>u.uid===userid)
|
|
||||||
const [formdata, formchange] = useState(user?user:{});
|
const [formdata, formchange] = useState({});
|
||||||
const onChange=(e)=>{
|
const onChange = (e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
if(e.target.type==='checkbox')
|
if (e.target.type === 'checkbox')
|
||||||
formchange({...formdata, [e.target.id]:e.target.checked})
|
formchange({ ...formdata, [e.target.id]: e.target.checked })
|
||||||
else
|
else
|
||||||
formchange({...formdata, [e.target.id]:e.target.value})
|
formchange({ ...formdata, [e.target.id]: e.target.value })
|
||||||
}
|
}
|
||||||
const onSubmit=(e)=>{
|
useEffect(()=>{
|
||||||
|
let user = userid !== undefined?usertable.find(u => u.uid === userid):undefined;
|
||||||
|
if(user!==undefined){
|
||||||
|
formchange(user);
|
||||||
|
}
|
||||||
|
},[userid]);
|
||||||
|
const onSubmit = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
userreducer({type:'update', user: formdata})
|
console.log(api);
|
||||||
|
if(formdata.line!==undefined){
|
||||||
|
api.updateUser(sessiondata.token, formdata).then(r => {
|
||||||
|
userreducer({ type: 'update', user: r })
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
api.createUser(sessiondata.token, formdata).then(r => {
|
||||||
|
userreducer({ type: 'create', user: r })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
route('/users');
|
route('/users');
|
||||||
}
|
}
|
||||||
const Input = ({id, type='text', label, disabled})=>(<div><label for={id}>{label}</label><input disabled={disabled} type={type} checked={type=='checkbox'&&formdata[id]?'on':''} value={formdata[id]} id={id} onChange={onChange} name={`edit-${id}`} /></div>)
|
const Input = ({ id, type = 'text', label, disabled }) => (<div className={'textbox'} ><input placeholder=" " disabled={disabled} type={type} checked={type == 'checkbox' && formdata[id] ? 'on' : ''} value={formdata[id]} id={id} onChange={onChange} name={`edit-${id}`} /><label for={id}>{label}</label></div>)
|
||||||
return(
|
return (
|
||||||
<div className='container'>
|
<div className='container'>
|
||||||
<h1>Benutzer Bearbeiten</h1>
|
<h1>{formdata.line != undefined ? "Benutzer Bearbeiten" : "Neuer Benutzer"}</h1>
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<Input id="uid" label="UserID" />
|
<Input id="uid" label="UserID" />
|
||||||
<Input id="first_name" label="Vorname" />
|
<Input id="first_name" label="Vorname" />
|
||||||
<Input id="last_name" label="NachName" />
|
<Input id="last_name" label="NachName" />
|
||||||
<Input id="rfid_uid" label="RFID" />
|
<Input id="rfid_uid" label="RFID" />
|
||||||
<Input id="user_pin" label="Pin" />
|
<Input id="user_pin" label="Pin" />
|
||||||
<Input id="enabled" type={'checkbox'} label="Vorname" />
|
<Input id="enabled" type={'checkbox'} label="" />
|
||||||
<input type={'submit'}>Speichern</input>
|
<div className={'button'} ><input type={'submit'}>Speichern</input> </div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,29 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
|
import { Link } from 'preact-router';
|
||||||
|
import { useContext, useState } from 'preact/hooks';
|
||||||
|
import AppState from '../../store/AppState';
|
||||||
|
|
||||||
function Home() {return(
|
function Home() {
|
||||||
|
let [sessiondata, ] = useContext(AppState).session;
|
||||||
|
return (
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Home</h1>
|
<div className={'contentbox'} >
|
||||||
<p>This is the Home component.</p>
|
<h2>Startseite</h2>
|
||||||
|
<p>Willkommen zurück {sessiondata.username} </p>
|
||||||
|
<div>
|
||||||
|
<h3>Status</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Aktiv seit: 12.01.2022</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
<div>
|
||||||
|
<p>Hier können Sie den Türöffner manuell aktivieren.</p>
|
||||||
|
|
||||||
|
<p>Um Benutzer anzulegen, öffnen sie das Menü und tippen auf <Link href="/newuser">Benutzer anlegen</Link> </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
export default Home;
|
export default Home;
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
import { route } from 'preact-router';
|
import { route } from 'preact-router';
|
||||||
import { useContext,useState } from 'preact/hooks';
|
import { useContext, useState } from 'preact/hooks';
|
||||||
import AppState from '../../store/AppState';
|
import AppState from '../../store/AppState';
|
||||||
import Breadcrumbs from '../../components/breadcrumbs';
|
import Breadcrumbs from '../../components/breadcrumbs';
|
||||||
import api from '../../api'
|
import api from '../../api'
|
||||||
function Login() {
|
function Login() {
|
||||||
let [sessiondata, setsession]= useContext(AppState).session;
|
let [sessiondata, setsession] = useContext(AppState).session;
|
||||||
const [val, set] = useState({ username: '', password: '', error: null });
|
const [val, set] = useState({ username: '', password: '', error: null });
|
||||||
const navigation = ["Login"];
|
const navigation = ["Login"];
|
||||||
if(sessiondata.active)
|
if (sessiondata.active)
|
||||||
route('/', true);
|
route('/', true);
|
||||||
function onSubmit(e) {
|
function onSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
api.login(val.username, val.password).then(token=>{
|
api.login(val.username, val.password).then(token => {
|
||||||
if (token!='failed!') {
|
if (token != 'failed!') {
|
||||||
let newsession = {
|
let newsession = {
|
||||||
type: 'start',
|
type: 'start',
|
||||||
username: val.username,
|
username: val.username,
|
||||||
@ -31,13 +31,13 @@ function Login() {
|
|||||||
return (
|
return (
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Breadcrumbs items={navigation} />
|
<Breadcrumbs items={navigation} />
|
||||||
|
<div className={'contentbox'} >
|
||||||
<form id="login_form" onSubmit={onSubmit} >
|
<h2>Anmeldung</h2>
|
||||||
<p >
|
<p >Bitte melden Sie sich mit ihren Nutzerdaten an.</p>
|
||||||
Bitte melden Sie sich mit ihren Nutzerdaten an.
|
|
||||||
|
|
||||||
</p>
|
|
||||||
{val.error !== null && <span style={'color: red'}>Fehler: Ungültige Anmeldedaten.</span>}
|
{val.error !== null && <span style={'color: red'}>Fehler: Ungültige Anmeldedaten.</span>}
|
||||||
|
<form id="login_form" onSubmit={onSubmit} >
|
||||||
|
|
||||||
|
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
<input id="name" type="text" placeholder="Username" onInput={e => set({ ...val, username: e.target.value })} value={val.username} />
|
<input id="name" type="text" placeholder="Username" onInput={e => set({ ...val, username: e.target.value })} value={val.username} />
|
||||||
<label for="name">Benutzername</label>
|
<label for="name">Benutzername</label>
|
||||||
@ -46,10 +46,11 @@ function Login() {
|
|||||||
<input id="pass" type="password" placeholder="Passwort" onInput={e => set({ ...val, password: e.target.value })} value={val.password} />
|
<input id="pass" type="password" placeholder="Passwort" onInput={e => set({ ...val, password: e.target.value })} value={val.password} />
|
||||||
<label for="pass">Password</label>
|
<label for="pass">Password</label>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" value="Submit" />
|
<div class={'button'} onClick={onSubmit} ><input type="submit" value="Anmelden" /></div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,38 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
import { Link } from 'preact-router';
|
import { Link } from 'preact-router';
|
||||||
import { useContext } from 'preact/hooks';
|
import { useContext, useState } from 'preact/hooks';
|
||||||
import AppState from '../../store/AppState';
|
import AppState from '../../store/AppState';
|
||||||
import { Breadcrumbs } from '../../components';
|
import { Breadcrumbs } from '../../components';
|
||||||
|
import api from '../../api'
|
||||||
function Logout() {
|
function Logout() {
|
||||||
const navigation = ["Logout"];
|
const navigation = ["Logout"];
|
||||||
|
let [text, settext] = useState('');
|
||||||
let [sessiondata, setsession] = useContext(AppState).session;
|
let [sessiondata, setsession] = useContext(AppState).session;
|
||||||
this.shouldComponentUpdate = function () {
|
this.shouldComponentUpdate = function () {
|
||||||
console.log('functional component vs closures');
|
console.log('functional component vs closures');
|
||||||
}
|
}
|
||||||
if (sessiondata.active) {
|
if (sessiondata.active) {
|
||||||
|
api.logout(sessiondata.token).then((r) => r === 'success' ? settext('Sitzung beendet.') : settext('Sitzung war bereits nicht mehr vorhanden.'));
|
||||||
setsession({ type: 'end' })
|
setsession({ type: 'end' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Breadcrumbs items={navigation} />
|
<Breadcrumbs items={navigation} />
|
||||||
|
<div className={'contentbox'} >
|
||||||
|
<h2>
|
||||||
|
Erfolgreich abgemeldet:
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
Erfolgreich abgemeldet.
|
{text}<br />
|
||||||
<Link href="/login">Erneut Anmelden</Link>
|
<Link className={'button'} href="/login">Erneut Anmelden</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -5,32 +5,33 @@ function System() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='container'>
|
<div className='container'>
|
||||||
<h1>System</h1>
|
<div className={'contentbox'} >
|
||||||
<h2>WiFi Setup</h2>
|
<h2>System</h2>
|
||||||
|
<h3>WiFi Setup</h3>
|
||||||
<hr />
|
<hr />
|
||||||
<form>
|
<form>
|
||||||
<div>
|
<div className={'textbox'} >
|
||||||
<label>SSID</label>
|
|
||||||
<input type="text" placeholder='Wifi network name' />
|
<input type="text" placeholder='Wifi network name' />
|
||||||
|
<label>SSID</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className={'textbox'} >
|
||||||
<label>SSID</label>
|
|
||||||
<input type="text" placeholder='Wifi network name' />
|
<input type="text" placeholder='Wifi network name' />
|
||||||
|
<label>Password</label>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<h2>Admin User</h2>
|
<h3>Admin User</h3>
|
||||||
<hr />
|
<hr />
|
||||||
<form>
|
<form>
|
||||||
<div>
|
<div className={'textbox'} >
|
||||||
<label>SSID</label>
|
|
||||||
<input type="text" placeholder='Wifi network name' />
|
<input type="text" placeholder='Wifi network name' />
|
||||||
|
<label>Username</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className={'textbox'} >
|
||||||
<label>SSID</label>
|
|
||||||
<input type="text" placeholder='Wifi network name' />
|
<input type="text" placeholder='Wifi network name' />
|
||||||
|
<label>Password</label>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<h2>Datenbank Backup</h2><hr />
|
<h3>Datenbank Backup</h3><hr />
|
||||||
<div>
|
<div>
|
||||||
<form>
|
<form>
|
||||||
<h3>Backup einspielen</h3>
|
<h3>Backup einspielen</h3>
|
||||||
@ -41,7 +42,7 @@ function System() {
|
|||||||
<button>Download</button>
|
<button>Download</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
export default System
|
export default System
|
@ -7,7 +7,7 @@ import AppState, { UserTable } from "../../store";
|
|||||||
function Users({ pageid }) {
|
function Users({ pageid }) {
|
||||||
const [viewstate, setview] = useState({ limit: 100, page: 1, pages: null })
|
const [viewstate, setview] = useState({ limit: 100, page: 1, pages: null })
|
||||||
const { usertable, userreducer } = useContext(UserTable);
|
const { usertable, userreducer } = useContext(UserTable);
|
||||||
let [sessiondata, setsession] = useContext(AppState).session;
|
let [sessiondata,] = useContext(AppState).session;
|
||||||
const setPage = (e) => {
|
const setPage = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log(e)
|
console.log(e)
|
||||||
@ -25,7 +25,7 @@ function Users({ pageid }) {
|
|||||||
let action = { type: 'import', imported };
|
let action = { type: 'import', imported };
|
||||||
userreducer(action);
|
userreducer(action);
|
||||||
});
|
});
|
||||||
},[sessiondata]);
|
}, [sessiondata]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setview({ ...viewstate, pages: Math.ceil(usertable.length / viewstate.limit) });
|
setview({ ...viewstate, pages: Math.ceil(usertable.length / viewstate.limit) });
|
||||||
@ -36,11 +36,14 @@ function Users({ pageid }) {
|
|||||||
setview({ ...viewstate, page: pageid })
|
setview({ ...viewstate, page: pageid })
|
||||||
}, [pageid])
|
}, [pageid])
|
||||||
const deleteUser = (user) => {
|
const deleteUser = (user) => {
|
||||||
|
api.deleteUser(sessiondata.token,user).then(r=>{
|
||||||
let action = {
|
let action = {
|
||||||
type: 'delete',
|
type: 'delete',
|
||||||
user
|
user, r
|
||||||
}
|
}
|
||||||
userreducer(action)
|
userreducer(action)
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
const calculateView = () => {
|
const calculateView = () => {
|
||||||
let start = viewstate.limit * (viewstate.page - 1);
|
let start = viewstate.limit * (viewstate.page - 1);
|
||||||
@ -55,10 +58,13 @@ function Users({ pageid }) {
|
|||||||
return (
|
return (
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Breadcrumbs items={navigation} />
|
<Breadcrumbs items={navigation} />
|
||||||
|
<div className={'contentbox'} >
|
||||||
<div>Suche: <input type={'text'} /><button>Hinzufügen</button> Limit: <select><optgroup label={'Anzahl'}><option>10</option><option>25</option><option>50</option><option>100</option></optgroup><option>Alle</option></select></div>
|
<div>Suche: <input type={'text'} /><button>Hinzufügen</button> Limit: <select><optgroup label={'Anzahl'}><option>10</option><option>25</option><option>50</option><option>100</option></optgroup><option>Alle</option></select></div>
|
||||||
|
</div>
|
||||||
<UserList {...calculateView()} userlist={usertable} deleteUser={deleteUser} editUser={editUser} />
|
<UserList {...calculateView()} userlist={usertable} deleteUser={deleteUser} editUser={editUser} />
|
||||||
<Pageselector start={1} end={viewstate.pages} current={viewstate.page} setPage={setPage} />
|
<Pageselector start={1} end={viewstate.pages} current={viewstate.page} setPage={setPage} />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ export const userTableReducer = (state, action) => {
|
|||||||
let newstate = [];
|
let newstate = [];
|
||||||
let newindex = 0;
|
let newindex = 0;
|
||||||
state.forEach((u, i) => {
|
state.forEach((u, i) => {
|
||||||
if (user.uid && u.uid !== user.uid|| user.line && i !== user.line )
|
if (user.uid && u.uid != user.uid|| user.line && i != user.line )
|
||||||
newstate.push({ ...u, line: newindex++ })
|
newstate.push({ ...u, line: newindex++ })
|
||||||
return newstate;
|
return newstate;
|
||||||
}, []);
|
}, []);
|
||||||
@ -32,7 +32,7 @@ export const userTableReducer = (state, action) => {
|
|||||||
case 'update': {
|
case 'update': {
|
||||||
let newstate = [];
|
let newstate = [];
|
||||||
state.forEach((u, i) => {
|
state.forEach((u, i) => {
|
||||||
if (user.uid && u.uid === user.uid || user.line && i === user.line)
|
if (user.uid && u.uid == user.uid || user.line && i == user.line)
|
||||||
newstate.push(user);
|
newstate.push(user);
|
||||||
else
|
else
|
||||||
newstate.push(u);
|
newstate.push(u);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
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
|
margin: 0 .5em
|
||||||
border: 0.05em solid #fff
|
border: 0.05em solid #fff
|
||||||
border-radius: .3em
|
border-radius: .3em
|
||||||
list-style-type: none
|
list-style-type: none
|
||||||
|
46
src/style/_button.sass
Normal file
46
src/style/_button.sass
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
@mixin default
|
||||||
|
z-index: 1
|
||||||
|
margin: 1em
|
||||||
|
padding: 0.5em
|
||||||
|
text-align: center
|
||||||
|
display: inline-block
|
||||||
|
position: relative
|
||||||
|
color: #333
|
||||||
|
font-weight: bold
|
||||||
|
text-decoration: none
|
||||||
|
border: solid 1px #999
|
||||||
|
border-radius: .2rem
|
||||||
|
input[type=submit]
|
||||||
|
display: block
|
||||||
|
background: none
|
||||||
|
width: 100%
|
||||||
|
border: none
|
||||||
|
border-radius: none
|
||||||
|
font-size: 2em
|
||||||
|
transition: all ease-in-out 100ms
|
||||||
|
|
||||||
|
&::before
|
||||||
|
z-index: -1
|
||||||
|
border-radius: .2rem
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
right: 0
|
||||||
|
content: ''
|
||||||
|
background: transparent
|
||||||
|
width: 0%
|
||||||
|
height: 100%
|
||||||
|
transition: all ease-in-out 250ms
|
||||||
|
&:hover
|
||||||
|
color: #fff
|
||||||
|
input[type=submit]
|
||||||
|
background: #333
|
||||||
|
color: #fff
|
||||||
|
border-radius: .3rem
|
||||||
|
&::before
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
right: auto
|
||||||
|
content: ''
|
||||||
|
background: #333
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
37
src/style/_input.sass
Normal file
37
src/style/_input.sass
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
@mixin textfield
|
||||||
|
position: relative
|
||||||
|
display: inline-block
|
||||||
|
margin: 0 .25em 1em .25em
|
||||||
|
background: #fafafa
|
||||||
|
border-radius: .3em
|
||||||
|
border-bottom: 1px solid #ccc
|
||||||
|
&:hover
|
||||||
|
background: #fff
|
||||||
|
input
|
||||||
|
display: block
|
||||||
|
background: none
|
||||||
|
width: 100%
|
||||||
|
border-radius: none
|
||||||
|
outline: none
|
||||||
|
border: none
|
||||||
|
font-size: 1em
|
||||||
|
padding: 0.7em
|
||||||
|
+ label
|
||||||
|
user-select: none
|
||||||
|
position: absolute
|
||||||
|
top: 0.15em
|
||||||
|
left: 0.25em
|
||||||
|
font-size: .7em
|
||||||
|
cursor: text
|
||||||
|
transition: 250ms all
|
||||||
|
|
||||||
|
&::placeholder
|
||||||
|
color: transparent
|
||||||
|
|
||||||
|
&:placeholder-shown + label
|
||||||
|
color: grey
|
||||||
|
position: absolute
|
||||||
|
padding: .7em
|
||||||
|
top: 0em
|
||||||
|
left: 0em
|
||||||
|
font-size: 1em
|
@ -1,40 +1,13 @@
|
|||||||
@mixin text-input
|
@use 'input'
|
||||||
position: relative
|
|
||||||
input
|
|
||||||
display: block
|
|
||||||
width: 100%
|
|
||||||
border-radius: none
|
|
||||||
outline: none
|
|
||||||
border: none
|
|
||||||
font-size: 1.5em
|
|
||||||
padding: .7em
|
|
||||||
+ label
|
|
||||||
position: absolute
|
|
||||||
top: 0
|
|
||||||
left: 0
|
|
||||||
cursor: text
|
|
||||||
transition: 250ms all
|
|
||||||
|
|
||||||
&::placeholder
|
|
||||||
color: transparent
|
|
||||||
&:placeholder-shown + label
|
|
||||||
color: grey
|
|
||||||
font-size: 1.5em
|
|
||||||
position: absolute
|
|
||||||
padding: .7em
|
|
||||||
|
|
||||||
@mixin login-form
|
@mixin login-form
|
||||||
|
|
||||||
padding: 1em
|
padding: 1em
|
||||||
|
width: 100%
|
||||||
margin: 0 auto
|
margin: 0 auto
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
.input-box
|
.input-box
|
||||||
@include text-input
|
@include input.textfield
|
||||||
|
font-size: 1.5em
|
||||||
p
|
p
|
||||||
font-size: 2em
|
font-size: 2em
|
||||||
|
|
||||||
input[type=submit]
|
|
||||||
border: none
|
|
||||||
border-radius: none
|
|
||||||
font-size: 2em
|
|
||||||
|
@ -15,10 +15,13 @@
|
|||||||
color: #666
|
color: #666
|
||||||
//text-shadow: 0 0 .2em #000
|
//text-shadow: 0 0 .2em #000
|
||||||
width: 100%
|
width: 100%
|
||||||
|
transition: all ease-in-out 150ms
|
||||||
//background: #ccc
|
//background: #ccc
|
||||||
&:hover
|
&:hover
|
||||||
background: #bbb
|
padding-left: .5em
|
||||||
color: #333
|
background: #888
|
||||||
|
color: #fff
|
||||||
|
text-shadow: 0 0 1em #fff
|
||||||
&::after
|
&::after
|
||||||
top: 100%
|
top: 100%
|
||||||
left: 0
|
left: 0
|
||||||
@ -27,5 +30,5 @@
|
|||||||
position: absolute
|
position: absolute
|
||||||
width: 100%
|
width: 100%
|
||||||
height: .1em
|
height: .1em
|
||||||
background: #8a8080
|
background: #ccc
|
||||||
//border-bottom-left-radius: 2em 1em
|
//border-bottom-left-radius: 2em 1em
|
@ -1,16 +1,22 @@
|
|||||||
@mixin pageselector
|
@mixin pageselector
|
||||||
text-align: center
|
text-align: center
|
||||||
//background-color: #ccc
|
//background-color: #ccc
|
||||||
margin: 1em
|
margin: 2em
|
||||||
ul
|
ul
|
||||||
list-style: none
|
list-style: none
|
||||||
justify-content: center
|
justify-content: center
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
display: flex
|
display: flex
|
||||||
|
flex-wrap: wrap
|
||||||
li a
|
li a
|
||||||
|
display: inline-flex
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
font-weight: bold
|
font-weight: bold
|
||||||
|
min-width: 2rem
|
||||||
|
min-height: 2rem
|
||||||
|
justify-content: center
|
||||||
|
align-items: center
|
||||||
padding: .2em .5em
|
padding: .2em .5em
|
||||||
margin: .3em
|
margin: .3em
|
||||||
border-radius: .3em
|
border-radius: .3em
|
||||||
@ -23,4 +29,4 @@
|
|||||||
&:hover
|
&:hover
|
||||||
color: #333
|
color: #333
|
||||||
background: #fff
|
background: #fff
|
||||||
border: .1em solid #ccc
|
border: .1em solid #444
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
@use 'breadcrumbs'
|
@use 'breadcrumbs'
|
||||||
@use 'pageselector'
|
@use 'pageselector'
|
||||||
@use 'footer'
|
@use 'footer'
|
||||||
|
@use 'button'
|
||||||
|
@use 'input'
|
||||||
*
|
*
|
||||||
|
//border: 1px dotted red
|
||||||
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
|
||||||
@ -30,11 +33,12 @@ body
|
|||||||
position: fixed
|
position: fixed
|
||||||
top: 0em
|
top: 0em
|
||||||
width: 100%
|
width: 100%
|
||||||
|
max-width: 100vw
|
||||||
height: 4rem
|
height: 4rem
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
justify-content: flex-end
|
justify-content: center
|
||||||
padding: .5em 0
|
padding: 0.5em .5em
|
||||||
margin: 0 0 0 0
|
margin: 0 0 0 0
|
||||||
background: linear-gradient(#9e9e9e 0% , #d1d1d1 100%)
|
background: linear-gradient(#9e9e9e 0% , #d1d1d1 100%)
|
||||||
box-shadow: 0 0 .2em #444
|
box-shadow: 0 0 .2em #444
|
||||||
@ -49,6 +53,7 @@ body
|
|||||||
.container
|
.container
|
||||||
width: clamp(5ch, 100%,75ch)
|
width: clamp(5ch, 100%,75ch)
|
||||||
margin: 0 auto
|
margin: 0 auto
|
||||||
|
|
||||||
.breadcrumb
|
.breadcrumb
|
||||||
@include breadcrumbs.breadcrumbs
|
@include breadcrumbs.breadcrumbs
|
||||||
|
|
||||||
@ -73,6 +78,7 @@ body
|
|||||||
display: flex
|
display: flex
|
||||||
flex-direction: row
|
flex-direction: row
|
||||||
background: #eee
|
background: #eee
|
||||||
|
margin: 0 0.5em
|
||||||
padding: .5em 0
|
padding: .5em 0
|
||||||
border-radius: .3em
|
border-radius: .3em
|
||||||
&:not(:last-child)
|
&:not(:last-child)
|
||||||
@ -132,3 +138,26 @@ body
|
|||||||
|
|
||||||
footer
|
footer
|
||||||
@include footer.footer
|
@include footer.footer
|
||||||
|
|
||||||
|
.contentbox
|
||||||
|
display: flex
|
||||||
|
flex-wrap: wrap
|
||||||
|
flex-direction: column
|
||||||
|
align-content: stretch
|
||||||
|
padding: 1em
|
||||||
|
margin: 1em 0.5em
|
||||||
|
border: 1px solid #fff
|
||||||
|
background: #f4f4f4
|
||||||
|
box-shadow: 0 0 .5em #ddd, inset 0 0 1em #fff
|
||||||
|
border-radius: .5em
|
||||||
|
h2
|
||||||
|
margin: 0
|
||||||
|
display: flex
|
||||||
|
flex-break: after
|
||||||
|
flex-basis: 100%
|
||||||
|
.button
|
||||||
|
@include button.default
|
||||||
|
|
||||||
|
.textbox
|
||||||
|
@include input.textfield
|
||||||
|
font-size: 1.5em
|
||||||
|
Loading…
x
Reference in New Issue
Block a user