react fixes

This commit is contained in:
Roman Hergenreder 2020-06-15 00:00:15 +02:00
parent 95b803a1e4
commit dfc9697ed8
7 changed files with 108 additions and 98 deletions

8
admin/dist/main.js vendored

File diff suppressed because one or more lines are too long

@ -33,4 +33,8 @@ export default class API {
async logout() {
return this.apiCall("user/logout");
}
async getNotifications() {
return this.apiCall("notifications/fetch");
}
};

@ -1,24 +1,11 @@
import React, {useEffect, useState} from "react";
function useStateFromProp(initialValue) {
const [value, setValue] = useState(initialValue);
useEffect(() => setValue(initialValue), [initialValue]);
return [value, setValue];
}
import React from "react";
export default function Dialog(props) {
const [value, setValue] = useStateFromProp(props);
function onClose() {
setValue({ });
}
const show = typeof value.message !== "undefined";
const show = props.show;
const classes = "modal fade" + (show ? " show" : "");
const style = { paddingRight: "12px", display: (show ? "block" : "none") };
const onClose = props.onClose || function() { };
return (
<div className={classes} id="modal-default" style={style} aria-modal="true" onClick={() => onClose()}>

@ -18,17 +18,38 @@ class AdminDashboard extends React.Component {
this.state = {
currentView: "dashboard",
loaded: false,
dialog: { }
dialog: { onClose: () => this.hideDialog() },
notifications: { }
};
}
onChangeView(view) {
this.setState({ ...this.state, currentView: view || "dashboard", dialog: { } });
onUpdate() {
if (this.state.loaded) {
this.fetchNotifications();
}
}
showDialog(props) {
props = props || { };
this.setState({ ...this.state, dialog: props });
onChangeView(view) {
this.setState({ ...this.state, currentView: view || "dashboard" });
}
showDialog(message, title) {
const props = { show: true, message: message, title: title };
this.setState({ ...this.state, dialog: { ...this.state.dialog, ...props } });
}
hideDialog() {
this.setState({ ...this.state, dialog: { ...this.state.dialog, show: false } });
}
fetchNotifications() {
this.api.getNotifications().then((res) => {
if (!res.success) {
this.showDialog("Error fetching notifications: " + res.msg, "Error fetching notifications");
} else {
this.setState({...this.state, notifications: res.notifications});
}
});
}
render() {
@ -38,16 +59,17 @@ class AdminDashboard extends React.Component {
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>
}
console.log("index.render, state=", this.state);
return <>
<Header />
<Sidebar currentView={this.state.currentView} onChangeView={this.onChangeView.bind(this)} showDialog={this.showDialog.bind(this)} api={this.api} />
<Sidebar currentView={this.state.currentView} notifications={this.state.notifications} onChangeView={this.onChangeView.bind(this)} showDialog={this.showDialog.bind(this)} api={this.api} />
<div className={"content-wrapper p-2"}>
<section className={"content"}>
{this.createContent()}

@ -1,78 +1,76 @@
import React from 'react';
import Icon from "./icon";
export default class Sidebar extends React.Component {
export default function Sidebar(props) {
constructor(props) {
super(props);
this.parent = {
onChangeView: props.onChangeView || function() { },
showDialog: props.showDialog || function() {},
api: props.api
};
this.state = { currentView: props.currentView, }
let parent = {
onChangeView: props.onChangeView || function() { },
showDialog: props.showDialog || function() {},
api: props.api
};
function onChangeView(view) {
parent.onChangeView(view);
}
onChangeView(view) {
this.setState({ ...this.state, currentView: view });
this.parent.onChangeView(view);
}
onLogout() {
this.parent.api.logout().then(obj => {
if (obj.success) {
document.location = "/admin";
} else {
this.parent.showDialog({message: "Error logging out: " + obj.msg, title: "Error logging out"});
}
function onLogout() {
parent.api.logout().then(obj => {
if (obj.success) {
document.location = "/admin";
} else {
parent.showDialog("Error logging out: " + obj.msg, "Error logging out");
}
});
}
render() {
const menuItems = {
"dashboard": {
"name": "Dashboard",
"icon": "tachometer-alt"
},
"users": {
"name": "Users",
"icon": "users"
},
"settings": {
"name": "Settings",
"icon": "tools"
},
"help": {
"name": "Help",
"icon": "question-circle"
},
};
const menuItems = {
"dashboard": {
"name": "Dashboard",
"icon": "tachometer-alt"
},
"users": {
"name": "Users",
"icon": "users"
},
"settings": {
"name": "Settings",
"icon": "tools"
},
"help": {
"name": "Help",
"icon": "question-circle"
},
};
let numNotifications = Object.keys(props.notifications).length;
if (numNotifications > 0) {
if (numNotifications > 9) numNotifications = "9+";
menuItems["dashboard"]["badge"] = { type: "warning", value: numNotifications };
}
let li = [];
// li.push(<li className={"nav-item"} key={"logged-in-as"}><span className={""}>Logged in as: {this.parent.api.user.name}</span><hr/></li>);
// li.push(<li key={"hr"}><hr/></li>);
// li.push(<li key={"header"} className={"header"}>MAIN NAVIGATION</li>);
let li = [];
for (let id in menuItems) {
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> : <></>);
for (let id in menuItems) {
let obj = menuItems[id];
let active = this.state.currentView === id ? " active" : "";
li.push(<li key={id} className={"nav-item"}>
<a href={"#"} onClick={() => this.onChangeView(id)} className={"nav-link" + active}>
<Icon icon={obj.icon} classes={"nav-icon"} /><p>{obj.name}</p>
</a>
</li>);
}
li.push(<li className={"nav-item"} key={"logout"}>
<a href={"#"} onClick={() => this.onLogout()} className={"nav-link"}>
<Icon icon={"arrow-left"} classes={"nav-icon"} />
<p>Logout</p>
li.push(<li key={id} className={"nav-item"}>
<a href={"#"} onClick={() => onChangeView(id)} className={"nav-link" + active}>
<Icon icon={obj.icon} classes={"nav-icon"} /><p>{obj.name}{badge}</p>
</a>
</li>);
return <aside className={"main-sidebar sidebar-dark-primary elevation-4"}>
<a href={"#"} className={"brand-link"} onClick={() => this.onChangeView("dashboard")}>
}
li.push(<li className={"nav-item"} key={"logout"}>
<a href={"#"} onClick={() => onLogout()} className={"nav-link"}>
<Icon icon={"arrow-left"} classes={"nav-icon"} />
<p>Logout</p>
</a>
</li>);
return (
<aside className={"main-sidebar sidebar-dark-primary elevation-4"}>
<a href={"#"} className={"brand-link"} onClick={() => onChangeView("dashboard")}>
<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>
</a>
@ -93,7 +91,7 @@ export default class Sidebar extends React.Component {
{/* LOGGED IN AS */}
<div className="user-panel mt-3 pb-3 mb-3 d-flex">
<div className="info">
<a href="#" className="d-block">Logged in as: {this.parent.api.user.name}</a>
<a href="#" className="d-block">Logged in as: {parent.api.user.name}</a>
</div>
</div>
@ -109,6 +107,5 @@ export default class Sidebar extends React.Component {
</div>
</div>
</aside>
}
};
)
}

@ -15,8 +15,8 @@ class LoginBody extends Body {
public function loadView() {
parent::loadView();
$head = $this->getDocument()->getHead();
$head->loadBootstrap();
$head->loadJQuery();
$head->loadBootstrap();
$head->addJS(Script::CORE);
$head->addCSS(Link::CORE);
$head->addJS(Script::ADMIN);

8
js/admin.min.js vendored

File diff suppressed because one or more lines are too long