@@ -8,22 +8,22 @@ import {
88 Toolbar ,
99 Menu ,
1010 MenuItem ,
11+ Divider ,
1112 Typography ,
1213 Button ,
1314 IconButton ,
1415 FormControl ,
1516 InputLabel ,
1617 TextField ,
1718 Select ,
18- Backdrop ,
1919 Dialog ,
2020 DialogActions ,
2121 DialogContent ,
2222 DialogTitle ,
23- Fade ,
2423} from '@mui/material' ;
2524import { makeStyles } from '@mui/styles'
2625import AddIcon from '@mui/icons-material/Add' ;
26+ import WidgetsIcon from '@mui/icons-material/Widgets' ;
2727import AccountCircleIcon from '@mui/icons-material/AccountCircle' ;
2828import { User } from '@firebase/auth' ;
2929import { ref , set , onValue , DataSnapshot } from '@firebase/database' ;
@@ -56,6 +56,9 @@ const useStyles = makeStyles((theme) => ({
5656 title : {
5757 flexGrow : 1 ,
5858 } ,
59+ profile : {
60+ flexGrow : 1
61+ } ,
5962} ) ) ;
6063
6164type Widget = {
@@ -65,18 +68,15 @@ type Widget = {
6568
6669type WidgetList = { [ key : string ] : Widget }
6770
68- const Widgets = ( ) => {
71+ const Widgets = ( { profile } : { profile : string } ) => {
6972 const [ widgets , setWidgets ] = useState < WidgetList > ( { } ) ;
70- const profile = 'default' ;
7173
7274 useEffect ( ( ) => {
7375 const widgetsRef = ref ( db , `/profiles/${ profile } /widgets` ) ;
7476 onValue ( widgetsRef , ( snap : DataSnapshot ) => {
75- if ( snap ?. val ( ) ) {
76- setWidgets ( snap . val ( ) ) ;
77- }
77+ setWidgets ( snap . val ( ) || { } ) ;
7878 } ) ;
79- } , [ ] ) ;
79+ } , [ profile ] ) ;
8080
8181 return (
8282 < div >
@@ -91,8 +91,7 @@ const Widgets = () => {
9191 ) ;
9292} ;
9393
94- const AddWidgetModel = ( { open, onClose } : { open : boolean , onClose : ( ) => void } ) => {
95- const profile = 'default' ;
94+ const AddWidgetDialog = ( { profile, open, onClose } : { profile : string , open : boolean , onClose : ( ) => void } ) => {
9695 const [ widgetId , setWidgetId ] = useState ( "" ) ;
9796 const [ widgetType , setWidgetType ] = useState ( "text" ) ;
9897
@@ -158,6 +157,34 @@ const AddWidgetModel = ({ open, onClose }: { open: boolean, onClose: () => void
158157 name : widgetType ,
159158 props : Editors [ widgetType ] . defaultProps
160159 } ) ;
160+
161+ setWidgetId ( "" ) ;
162+ setWidgetType ( "text" ) ;
163+ onClose ( ) ;
164+ } } > Add</ Button >
165+ </ DialogActions >
166+ </ Dialog >
167+ ) ;
168+ } ;
169+
170+ const AddProfileDialog = ( { open, onClose } : { open : boolean , onClose : ( ) => void } ) => {
171+ const [ profileId , setProfileId ] = useState ( "" ) ;
172+
173+ return (
174+ < Dialog open = { open } onClose = { onClose } >
175+ < DialogTitle > Add Profile</ DialogTitle >
176+ < DialogContent >
177+ < FormControl variant = "standard" >
178+ < TextField required autoFocus fullWidth label = "ID" value = { profileId } variant = "standard" onChange = { ( e ) => { setProfileId ( e . target . value ) ; } } />
179+ </ FormControl >
180+ </ DialogContent >
181+ < DialogActions >
182+ < Button color = "primary" variant = "contained" onClick = { ( ) => {
183+ if ( profileId . length > 0 ) {
184+ set ( ref ( db , `/profiles/${ profileId } /name` ) , profileId ) ;
185+ setProfileId ( "" ) ;
186+ onClose ( ) ;
187+ }
161188 } } > Add</ Button >
162189 </ DialogActions >
163190 </ Dialog >
@@ -167,18 +194,34 @@ const AddWidgetModel = ({ open, onClose }: { open: boolean, onClose: () => void
167194const AdminIndexPage = ( ) => {
168195 const classes = useStyles ( ) ;
169196 const [ currentUser , setCurrentUser ] = useState < User | null > ( null ) ;
170- const [ anchorEl , setAnchorEl ] = useState < HTMLElement | null > ( null ) ;
171- const [ addWidgetModalOpened , setAddWidgetModalOpened ] = useState ( false ) ;
172- const isUserMenuOpen = Boolean ( anchorEl ) ;
197+ const [ userAnchorEl , setUserAnchorEl ] = useState < HTMLElement | null > ( null ) ;
198+ const [ profileAnchorEl , setProfileAnchorEl ] = useState < HTMLElement | null > ( null ) ;
199+ const [ addProfileDialogOpened , setAddProfileDialogOpened ] = useState ( false ) ;
200+ const [ addWidgetDialogOpened , setAddWidgetDialogOpened ] = useState ( false ) ;
201+ const [ currentProfile , setCurrentProfile ] = useState ( 'default' ) ;
202+ const [ profiles , setProfiles ] = useState < string [ ] > ( [ ] ) ;
203+
204+ const isUserMenuOpen = Boolean ( userAnchorEl ) ;
205+ const isProfileMenuOpen = Boolean ( profileAnchorEl ) ;
173206
174207 useEffect ( ( ) => {
175208 auth . onAuthStateChanged ( ( user ) => {
176209 setCurrentUser ( user ) ;
177210 } ) ;
178211 } ) ;
179212
213+ useEffect ( ( ) => {
214+ const profilesRef = ref ( db , `/profiles` ) ;
215+ onValue ( profilesRef , ( snap : DataSnapshot ) => {
216+ if ( snap ?. val ( ) ) {
217+ setProfiles ( Object . keys ( snap . val ( ) ) ) ;
218+ }
219+ } ) ;
220+ } , [ ] ) ;
221+
180222 const signout = async ( ) => {
181- setAnchorEl ( null ) ;
223+ setUserAnchorEl ( null ) ;
224+ setProfileAnchorEl ( null ) ;
182225 try {
183226 await auth . signOut ( ) ;
184227 } catch ( err ) {
@@ -188,10 +231,18 @@ const AdminIndexPage = () => {
188231
189232 const userMenuId = 'user-menu' ;
190233 const handleUserMenuOpen = ( event : MouseEvent < HTMLElement > ) => {
191- setAnchorEl ( event . currentTarget ) ;
234+ setUserAnchorEl ( event . currentTarget ) ;
192235 } ;
193236 const handleUserMenuClose = ( ) => {
194- setAnchorEl ( null ) ;
237+ setUserAnchorEl ( null ) ;
238+ } ;
239+
240+ const profileMenuId = 'profile-menu' ;
241+ const handleProfileMenuOpen = ( event : MouseEvent < HTMLElement > ) => {
242+ setProfileAnchorEl ( event . currentTarget ) ;
243+ } ;
244+ const handleProfileMenuClose = ( ) => {
245+ setProfileAnchorEl ( null ) ;
195246 } ;
196247
197248 return currentUser !== null ? (
@@ -203,12 +254,27 @@ const AdminIndexPage = () => {
203254 < Typography variant = "h6" className = { classes . title } >
204255 Admin
205256 </ Typography >
257+ < Typography variant = "h6" className = { classes . title } >
258+ Profile:{ ' ' }
259+ { currentProfile }
260+ </ Typography >
206261 < Box sx = { { flexGrow : 1 } } />
207262 < Box sx = { { display : { xs : 'none' , md : 'flex' } } } >
208263 < IconButton
209264 size = "large"
210265 color = "inherit"
211- onClick = { ( ) => { setAddWidgetModalOpened ( true ) ; } }
266+ edge = "end"
267+ aria-controls = { profileMenuId }
268+ aria-haspopup = "true"
269+ aria-expanded = { isProfileMenuOpen ? 'true' : undefined }
270+ onClick = { handleProfileMenuOpen }
271+ >
272+ < WidgetsIcon />
273+ </ IconButton >
274+ < IconButton
275+ size = "large"
276+ color = "inherit"
277+ onClick = { ( ) => { setAddWidgetDialogOpened ( true ) ; } }
212278 >
213279 < AddIcon />
214280 </ IconButton >
@@ -218,31 +284,51 @@ const AdminIndexPage = () => {
218284 edge = "end"
219285 aria-controls = { userMenuId }
220286 aria-haspopup = "true"
287+ aria-expanded = { isUserMenuOpen ? 'true' : undefined }
221288 onClick = { handleUserMenuOpen }
222289 >
223290 < AccountCircleIcon />
224291 </ IconButton >
225292 </ Box >
226293 </ Toolbar >
227294 </ AppBar >
295+ < Menu
296+ id = { profileMenuId }
297+ anchorEl = { profileAnchorEl }
298+ open = { isProfileMenuOpen }
299+ onClose = { handleProfileMenuClose }
300+ >
301+ { profiles . map ( ( profile ) => (
302+ < MenuItem key = { profile } color = "inherit" onClick = { ( ) => { setCurrentProfile ( profile ) ; } } > { profile } </ MenuItem >
303+ ) ) }
304+ < Divider />
305+ < MenuItem color = "inherit" onClick = { ( ) => { setAddProfileDialogOpened ( true ) ; } } > Add</ MenuItem >
306+ </ Menu >
228307 < Menu
229308 id = { userMenuId }
230- anchorEl = { anchorEl }
309+ anchorEl = { userAnchorEl }
231310 open = { isUserMenuOpen }
232311 onClose = { handleUserMenuClose }
233312 >
234313 < MenuItem color = "inherit" onClick = { signout } > Logout</ MenuItem >
235314 </ Menu >
236- < AddWidgetModel
237- open = { addWidgetModalOpened }
315+ < AddProfileDialog
316+ open = { addProfileDialogOpened }
317+ onClose = { ( ) => {
318+ setAddProfileDialogOpened ( false ) ;
319+ } }
320+ />
321+ < AddWidgetDialog
322+ profile = { currentProfile }
323+ open = { addWidgetDialogOpened }
238324 onClose = { ( ) => {
239- setAddWidgetModalOpened ( false ) ;
325+ setAddWidgetDialogOpened ( false ) ;
240326 } }
241327 />
242328
243329 < Container className = { classes . content } >
244330 < Box my = { 4 } >
245- < Widgets />
331+ < Widgets profile = { currentProfile } />
246332 </ Box >
247333 </ Container >
248334 </ div >
0 commit comments