react fixes
This commit is contained in:
		
							parent
							
								
									95b803a1e4
								
							
						
					
					
						commit
						dfc9697ed8
					
				
							
								
								
									
										8
									
								
								admin/dist/main.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								js/admin.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user