React Routes

This commit is contained in:
Roman Hergenreder 2020-06-15 14:56:51 +02:00
parent 2f9115d24a
commit fffd0bdbbf
7 changed files with 566 additions and 46 deletions

217
admin/dist/main.js vendored

File diff suppressed because one or more lines are too long

@ -6275,6 +6275,19 @@
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
}, },
"history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"requires": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
}
},
"hmac-drbg": { "hmac-drbg": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@ -6285,6 +6298,14 @@
"minimalistic-crypto-utils": "^1.0.1" "minimalistic-crypto-utils": "^1.0.1"
} }
}, },
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
}
},
"homedir-polyfill": { "homedir-polyfill": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
@ -8191,6 +8212,15 @@
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
}, },
"mini-create-react-context": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz",
"integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==",
"requires": {
"@babel/runtime": "^7.5.5",
"tiny-warning": "^1.0.3"
}
},
"mini-css-extract-plugin": { "mini-css-extract-plugin": {
"version": "0.9.0", "version": "0.9.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz",
@ -10674,6 +10704,52 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"react-router": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
"integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
"mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
}
}
}
},
"react-router-dom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
"integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
"react-router": "5.2.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
}
},
"react-scripts": { "react-scripts": {
"version": "3.4.1", "version": "3.4.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz",
@ -11265,6 +11341,11 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
}, },
"resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
"resolve-url": { "resolve-url": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@ -12691,6 +12772,16 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
}, },
"tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
"integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
},
"tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"tmp": { "tmp": {
"version": "0.0.33", "version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@ -13062,6 +13153,11 @@
"spdx-expression-parse": "^3.0.0" "spdx-expression-parse": "^3.0.0"
} }
}, },
"value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
},
"vary": { "vary": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

@ -9,6 +9,7 @@
"moment": "^2.26.0", "moment": "^2.26.0",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1" "react-scripts": "3.4.1"
}, },
"scripts": { "scripts": {

@ -9,6 +9,7 @@ import UserOverview from './users.js';
import Overview from './overview.js' import Overview from './overview.js'
import Icon from "./icon"; import Icon from "./icon";
import Dialog from "./dialog"; import Dialog from "./dialog";
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
class AdminDashboard extends React.Component { class AdminDashboard extends React.Component {
@ -16,7 +17,6 @@ class AdminDashboard extends React.Component {
super(props); super(props);
this.api = new API(); this.api = new API();
this.state = { this.state = {
currentView: "dashboard",
loaded: false, loaded: false,
dialog: { onClose: () => this.hideDialog() }, dialog: { onClose: () => this.hideDialog() },
notifications: { } notifications: { }
@ -29,10 +29,6 @@ class AdminDashboard extends React.Component {
} }
} }
onChangeView(view) {
this.setState({ ...this.state, currentView: view || "dashboard" });
}
showDialog(message, title) { showDialog(message, title) {
const props = { show: true, message: message, title: title }; const props = { show: true, message: message, title: title };
this.setState({ ...this.state, dialog: { ...this.state.dialog, ...props } }); this.setState({ ...this.state, dialog: { ...this.state.dialog, ...props } });
@ -52,47 +48,51 @@ class AdminDashboard extends React.Component {
}); });
} }
componentDidMount() {
this.api.fetchUser().then(Success => {
if (!Success) {
document.location = "/admin";
} else {
this.fetchNotifications();
setInterval(this.onUpdate.bind(this), 60000);
this.setState({...this.state, loaded: true});
}
});
}
render() { render() {
if (!this.state.loaded) { if (!this.state.loaded) {
this.api.fetchUser().then(Success => {
if (!Success) {
document.location = "/admin";
} else {
this.fetchNotifications();
setInterval(this.onUpdate.bind(this), 60000);
this.setState({...this.state, loaded: true});
}
});
return <b>Loading <Icon icon={"spinner"} /></b> return <b>Loading <Icon icon={"spinner"} /></b>
} }
const controlObj = { const controlObj = {
notifications: this.state.notifications, notifications: this.state.notifications,
currentView: this.state.currentView,
onChangeView: this.onChangeView.bind(this),
showDialog: this.showDialog.bind(this), showDialog: this.showDialog.bind(this),
api: this.api api: this.api
}; };
return <> const createView = (view) => {
controlObj.currentView = view;
switch (view) {
case "users":
return <UserOverview {...controlObj} />;
case "dashboard":
default:
return <Overview {...controlObj} />;
}
};
return <Router>
<Header {...controlObj} /> <Header {...controlObj} />
<Sidebar {...controlObj} /> <Sidebar {...controlObj} />
<div className={"content-wrapper p-2"}> <div className={"content-wrapper p-2"}>
<section className={"content"}> <section className={"content"}>
{this.createContent()} <Route path={"/admin/:view"} component={(obj) => createView(obj.match.params.view)}/>
<Dialog {...this.state.dialog}/> <Dialog {...this.state.dialog}/>
</section> </section>
</div> </div>
</> </Router>
}
createContent() {
if (this.state.currentView === "users") {
return <UserOverview />
} else {
return <Overview />
}
} }
} }

@ -1,6 +1,7 @@
import * as React from "react"; import * as React from "react";
export default class Overview extends React.Component { export default class Overview extends React.Component {
render() { render() {
return <div>Overview</div> return <div>Overview</div>
} }

@ -1,18 +1,14 @@
import React from 'react'; import React from 'react';
import Icon from "./icon"; import Icon from "./icon";
import {Link, NavLink} from "react-router-dom";
export default function Sidebar(props) { export default function Sidebar(props) {
let parent = { let parent = {
onChangeView: props.onChangeView || function() { },
showDialog: props.showDialog || function() {}, showDialog: props.showDialog || function() {},
api: props.api api: props.api
}; };
function onChangeView(view) {
parent.onChangeView(view);
}
function onLogout() { function onLogout() {
parent.api.logout().then(obj => { parent.api.logout().then(obj => {
if (obj.success) { if (obj.success) {
@ -29,7 +25,7 @@ export default function Sidebar(props) {
"icon": "tachometer-alt" "icon": "tachometer-alt"
}, },
"users": { "users": {
"name": "Users", "name": "Users & Groups",
"icon": "users" "icon": "users"
}, },
"settings": { "settings": {
@ -51,14 +47,15 @@ export default function Sidebar(props) {
let li = []; let li = [];
for (let id in menuItems) { for (let id in menuItems) {
let obj = menuItems[id]; let obj = menuItems[id];
let active = props.currentView === id ? " active" : "";
const badge = (obj.badge ? <span className={"right badge badge-" + obj.badge.type}>{obj.badge.value}</span> : <></>); const badge = (obj.badge ? <span className={"right badge badge-" + obj.badge.type}>{obj.badge.value}</span> : <></>);
li.push(<li key={id} className={"nav-item"}> li.push(
<a href={"#"} onClick={() => onChangeView(id)} className={"nav-link" + active}> <li key={id} className={"nav-item"}>
<Icon icon={obj.icon} classes={"nav-icon"} /><p>{obj.name}{badge}</p> <NavLink to={"/admin/" + id} className={"nav-link"} activeClassName={"active"}>
</a> <Icon icon={obj.icon} classes={"nav-icon"} /><p>{obj.name}{badge}</p>
</li>); </NavLink>
</li>
);
} }
li.push(<li className={"nav-item"} key={"logout"}> li.push(<li className={"nav-item"} key={"logout"}>
@ -70,10 +67,10 @@ export default function Sidebar(props) {
return ( return (
<aside className={"main-sidebar sidebar-dark-primary elevation-4"}> <aside className={"main-sidebar sidebar-dark-primary elevation-4"}>
<a href={"#"} className={"brand-link"} onClick={() => onChangeView("dashboard")}> <Link href={"#"} className={"brand-link"} to={"/admin/dashboard"}>
<img src={"/img/icons/logo.png"} alt={"Logo"} className={"brand-image img-circle elevation-3"} style={{opacity: ".8"}} /> <img src={"/img/icons/logo.png"} alt={"Logo"} className={"brand-image img-circle elevation-3"} style={{opacity: ".8"}} />
<span className={"brand-text font-weight-light ml-2"}>WebBase</span> <span className={"brand-text font-weight-light ml-2"}>WebBase</span>
</a> </Link>
<div className={"sidebar os-host os-theme-light os-host-overflow os-host-overflow-y os-host-resize-disabled os-host-scrollbar-horizontal-hidden os-host-transition"}> <div className={"sidebar os-host os-theme-light os-host-overflow os-host-overflow-y os-host-resize-disabled os-host-scrollbar-horizontal-hidden os-host-transition"}>
{/* IDK what this is */} {/* IDK what this is */}
@ -101,7 +98,6 @@ export default function Sidebar(props) {
{li} {li}
</ul> </ul>
</nav> </nav>
</div> </div>
</div> </div>
</div> </div>

217
js/admin.min.js vendored

File diff suppressed because one or more lines are too long