import React, { useState, useEffect } from 'react'; import Link from 'next/link'; import AppBar from '@material-ui/core/AppBar'; import Box from '@material-ui/core/Box'; import Menu from '@material-ui/core/Menu'; import MenuItem from '@material-ui/core/MenuItem'; import Drawer from '@material-ui/core/Drawer'; import Avatar from '@material-ui/core/Avatar'; import Hidden from '@material-ui/core/Hidden'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import IconButton from '@material-ui/core/IconButton'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; import Snackbar from '@material-ui/core/Snackbar'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogContentText from '@material-ui/core/DialogContentText'; import DialogTitle from '@material-ui/core/DialogTitle'; import Button from '@material-ui/core/Button'; import Alert from '@material-ui/lab/Alert'; import HomeIcon from '@material-ui/icons/Home'; import DataUsageIcon from '@material-ui/icons/DataUsage'; import PhotoIcon from '@material-ui/icons/Photo'; import LinkIcon from '@material-ui/icons/Link'; import MenuIcon from '@material-ui/icons/Menu'; import AccountCircleIcon from '@material-ui/icons/AccountCircle'; import GroupIcon from '@material-ui/icons/Group'; import FileCopyIcon from '@material-ui/icons/FileCopy'; import ExitToAppIcon from '@material-ui/icons/ExitToApp'; import PublishIcon from '@material-ui/icons/Publish'; import RotateLeftIcon from '@material-ui/icons/RotateLeft'; import Divider from '@material-ui/core/Divider'; import copy from 'copy-to-clipboard'; import { LOGOUT, UPDATE_USER } from '../reducer'; import { makeStyles, useTheme, withStyles } from '@material-ui/core/styles'; import { useRouter } from 'next/router'; import { useDispatch } from 'react-redux'; import { store } from '../store'; import { MD5 } from 'crypto-js'; const drawerWidth = 240; const useStyles = makeStyles(theme => ({ root: { display: 'flex', flexGrow: 1 }, drawer: { [theme.breakpoints.up('sm')]: { width: drawerWidth, flexShrink: 0 }, outlineColor: '#fff' }, appBar: { display: 'flex', backgroundColor: theme.palette.type === 'dark' ? '#000' : '#fff', color: theme.palette.type !== 'dark' ? '#000' : '#fff', [theme.breakpoints.up('sm')]: { width: 'calc(100%)', marginLeft: drawerWidth }, borderBottom: theme.palette.type === 'dark' ? '1px solid #1f1f1f' : '1px solid #e0e0e0' }, menuButton: { marginRight: theme.spacing(2), [theme.breakpoints.up('sm')]: { display: 'none' } }, rightButton: { marginLeft: 'auto' }, // necessary for content to be below app bar toolbar: theme.mixins.toolbar, drawerPaper: { width: drawerWidth }, content: { flexGrow: 1, padding: theme.spacing(1) }, menuIcon: { marginRight: '10px' } })); const NoFocusMenuItem = withStyles(theme => ({ root: { '&:hover': { backgroundColor: theme.palette.type === 'dark' ? '#000' : '#f7f7f7' } } }))(MenuItem); export default function UI({ children }) { const classes = useStyles(); const theme = useTheme(); const state = store.getState(); const router = useRouter(); const dispatch = useDispatch(); const [emailHash, setEmailHash] = useState(''); const [mobileOpen, setMobileOpen] = useState(false); const [admin, setAdmin] = useState(false); const [anchorEl, setAnchorEl] = useState(null); const [alertMessage, setAlertMessage] = useState('Copied token!'); const [tokenOpen, setTokenOpen] = useState(false); const [resetToken, setResetToken] = useState(false); const [alertOpen, setAlertOpen] = useState(false); const open = Boolean(anchorEl); useEffect(() => { (async () => { const d = await (await fetch('/api/user')).json(); if (d.error) { dispatch({ type: LOGOUT }); dispatch({ type: UPDATE_USER, payload: null }); router.push('/user/login'); } else setAdmin(d.administrator); })(); setEmailHash(MD5(state.user.email).toString()); }, []); const handleCopyTokenThenClose = async () => { const data = await (await fetch('/api/user')).json(); if (!data.error) { copy(data.token); setAlertMessage('Copied token!'); setTokenOpen(false); setAlertOpen(true); setAnchorEl(null); } }; const handleResetTokenThenClose = async () => { const data = await ( await fetch('/api/user/reset-token', { method: 'POST' }) ).json(); if (!data.error && data.updated) { setAlertMessage('Reset token!'); setResetToken(false); setAlertOpen(true); } }; const handleLogout = async () => { const data = await ( await fetch('/api/user/logout', { method: 'POST' }) ).json(); if (!data.error && data.clearStore) { dispatch({ type: LOGOUT }); dispatch({ type: UPDATE_USER, payload: null }); setAlertMessage('Logged out!'); setAlertOpen(true); router.push('/user/login'); } }; const handleDrawerToggle = () => setMobileOpen(!mobileOpen); const drawer = (
Zipline {state.user.email ? ( ) : ( setAnchorEl(event.currentTarget)} color='inherit' className={classes.rightButton} > )} setAnchorEl(null)} > {state.user.username} setAnchorEl(null)}> Manage Profile setTokenOpen(true)}> Copy Token setResetToken(true)}> Reset Token Logout {admin ? ( ) : null}
); const container = typeof window !== 'undefined' ? () => window.document.body : undefined; return (
setAlertOpen(false)} > {alertMessage} setTokenOpen(false)} aria-labelledby='alert-dialog-title' aria-describedby='alert-dialog-description' > Are you sure? This token is used to upload images to Zipline, and should not be shared! setResetToken(false)} aria-labelledby='alert-dialog-title' aria-describedby='alert-dialog-description' > Are you sure? This token is used to upload images to Zipline, resetting your token will cause any uploading actions to not work until you update them your self. Zipline
{children}
); }