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() { |     async logout() { | ||||||
|         return this.apiCall("user/logout"); |         return this.apiCall("user/logout"); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     async getNotifications() { | ||||||
|  |         return this.apiCall("notifications/fetch"); | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| @ -1,24 +1,11 @@ | |||||||
| import React, {useEffect, useState} from "react"; | import React from "react"; | ||||||
| 
 |  | ||||||
| function useStateFromProp(initialValue) { |  | ||||||
|     const [value, setValue] = useState(initialValue); |  | ||||||
| 
 |  | ||||||
|     useEffect(() => setValue(initialValue), [initialValue]); |  | ||||||
| 
 |  | ||||||
|     return [value, setValue]; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| export default function Dialog(props) { | export default function Dialog(props) { | ||||||
| 
 | 
 | ||||||
|     const [value, setValue] = useStateFromProp(props); |     const show = props.show; | ||||||
| 
 |  | ||||||
|     function onClose() { |  | ||||||
|         setValue({ }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const show = typeof value.message !== "undefined"; |  | ||||||
|     const classes = "modal fade" + (show ? " show" : ""); |     const classes = "modal fade" + (show ? " show" : ""); | ||||||
|     const style = { paddingRight: "12px", display: (show ? "block" : "none") }; |     const style = { paddingRight: "12px", display: (show ? "block" : "none") }; | ||||||
|  |     const onClose = props.onClose || function() { }; | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|         <div className={classes} id="modal-default" style={style} aria-modal="true" onClick={() => onClose()}> |         <div className={classes} id="modal-default" style={style} aria-modal="true" onClick={() => onClose()}> | ||||||
|  | |||||||
| @ -18,17 +18,38 @@ class AdminDashboard extends React.Component { | |||||||
|     this.state = { |     this.state = { | ||||||
|       currentView: "dashboard", |       currentView: "dashboard", | ||||||
|       loaded: false, |       loaded: false, | ||||||
|       dialog: { } |       dialog: { onClose: () => this.hideDialog() }, | ||||||
|  |       notifications: { } | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onChangeView(view) { |   onUpdate() { | ||||||
|     this.setState({ ...this.state, currentView: view || "dashboard", dialog: { } }); |     if (this.state.loaded) { | ||||||
|  |       this.fetchNotifications(); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   showDialog(props) { |   onChangeView(view) { | ||||||
|     props = props || { }; |     this.setState({ ...this.state, currentView: view || "dashboard" }); | ||||||
|     this.setState({ ...this.state, dialog: props }); |   } | ||||||
|  | 
 | ||||||
|  |   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() { |   render() { | ||||||
| @ -38,16 +59,17 @@ class AdminDashboard extends React.Component { | |||||||
|         if (!Success) { |         if (!Success) { | ||||||
|           document.location = "/admin"; |           document.location = "/admin"; | ||||||
|         } else { |         } else { | ||||||
|  |           this.fetchNotifications(); | ||||||
|  |           setInterval(this.onUpdate.bind(this), 60000); | ||||||
|           this.setState({...this.state, loaded: true}); |           this.setState({...this.state, loaded: true}); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|       return <b>Loading… <Icon icon={"spinner"} /></b> |       return <b>Loading… <Icon icon={"spinner"} /></b> | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     console.log("index.render, state=", this.state); |  | ||||||
|     return <> |     return <> | ||||||
|         <Header /> |         <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"}> |         <div className={"content-wrapper p-2"}> | ||||||
|           <section className={"content"}> |           <section className={"content"}> | ||||||
|             {this.createContent()} |             {this.createContent()} | ||||||
|  | |||||||
| @ -1,78 +1,76 @@ | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import Icon from "./icon"; | import Icon from "./icon"; | ||||||
| 
 | 
 | ||||||
| export default class Sidebar extends React.Component  { | export default function Sidebar(props) { | ||||||
| 
 | 
 | ||||||
|     constructor(props) { |     let parent = { | ||||||
|         super(props); |         onChangeView: props.onChangeView || function() { }, | ||||||
|         this.parent = { |         showDialog: props.showDialog || function() {}, | ||||||
|             onChangeView: props.onChangeView || function() { }, |         api: props.api | ||||||
|             showDialog: props.showDialog || function() {}, |     }; | ||||||
|             api: props.api | 
 | ||||||
|         }; |     function onChangeView(view) { | ||||||
|         this.state = { currentView: props.currentView, } |         parent.onChangeView(view); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     onChangeView(view) { |     function onLogout() { | ||||||
|         this.setState({ ...this.state, currentView: view }); |         parent.api.logout().then(obj => { | ||||||
|         this.parent.onChangeView(view); |             if (obj.success) { | ||||||
|     } |                 document.location = "/admin"; | ||||||
| 
 |             } else { | ||||||
|     onLogout() { |                 parent.showDialog("Error logging out: " + obj.msg, "Error logging out"); | ||||||
|         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"}); |  | ||||||
|            } |  | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     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 = { |     let numNotifications = Object.keys(props.notifications).length; | ||||||
|             "dashboard": { |     if (numNotifications > 0) { | ||||||
|                 "name": "Dashboard", |         if (numNotifications > 9) numNotifications = "9+"; | ||||||
|                 "icon": "tachometer-alt" |         menuItems["dashboard"]["badge"] = { type: "warning", value: numNotifications }; | ||||||
|             }, |     } | ||||||
|             "users": { |  | ||||||
|                 "name": "Users", |  | ||||||
|                 "icon": "users" |  | ||||||
|             }, |  | ||||||
|             "settings": { |  | ||||||
|                 "name": "Settings", |  | ||||||
|                 "icon": "tools" |  | ||||||
|             }, |  | ||||||
|             "help": { |  | ||||||
|                 "name": "Help", |  | ||||||
|                 "icon": "question-circle" |  | ||||||
|             }, |  | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         let li = []; |     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>);
 |     for (let id in menuItems) { | ||||||
|         // li.push(<li key={"hr"}><hr/></li>);
 |         let obj = menuItems[id]; | ||||||
|         // li.push(<li key={"header"} className={"header"}>MAIN NAVIGATION</li>);
 |         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) { |         li.push(<li key={id} className={"nav-item"}> | ||||||
|             let obj = menuItems[id]; |             <a href={"#"} onClick={() => onChangeView(id)} className={"nav-link" + active}> | ||||||
|             let active = this.state.currentView === id ? " active" : ""; |                 <Icon icon={obj.icon} classes={"nav-icon"} /><p>{obj.name}{badge}</p> | ||||||
|             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> |  | ||||||
|             </a> |             </a> | ||||||
|         </li>); |         </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"}} /> |                 <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> |             </a> | ||||||
| @ -93,7 +91,7 @@ export default class Sidebar extends React.Component  { | |||||||
|                             {/* LOGGED IN AS */} |                             {/* LOGGED IN AS */} | ||||||
|                             <div className="user-panel mt-3 pb-3 mb-3 d-flex"> |                             <div className="user-panel mt-3 pb-3 mb-3 d-flex"> | ||||||
|                                 <div className="info"> |                                 <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> | ||||||
|                             </div> |                             </div> | ||||||
| 
 | 
 | ||||||
| @ -109,6 +107,5 @@ export default class Sidebar extends React.Component  { | |||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </aside> |         </aside> | ||||||
|     } |     ) | ||||||
| 
 | } | ||||||
| }; |  | ||||||
|  | |||||||
| @ -15,8 +15,8 @@ class LoginBody extends Body { | |||||||
|   public function loadView() { |   public function loadView() { | ||||||
|     parent::loadView(); |     parent::loadView(); | ||||||
|     $head = $this->getDocument()->getHead(); |     $head = $this->getDocument()->getHead(); | ||||||
|     $head->loadBootstrap(); |  | ||||||
|     $head->loadJQuery(); |     $head->loadJQuery(); | ||||||
|  |     $head->loadBootstrap(); | ||||||
|     $head->addJS(Script::CORE); |     $head->addJS(Script::CORE); | ||||||
|     $head->addCSS(Link::CORE); |     $head->addCSS(Link::CORE); | ||||||
|     $head->addJS(Script::ADMIN); |     $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