Spaces:
Configuration error
Configuration error
| import { useState, useRef, useEffect } from 'react' | |
| import PropTypes from 'prop-types' | |
| import { useSelector, useDispatch } from 'react-redux' | |
| import { useNavigate } from 'react-router-dom' | |
| // material-ui | |
| import { useTheme } from '@mui/material/styles' | |
| import { | |
| Box, | |
| ButtonBase, | |
| Avatar, | |
| ClickAwayListener, | |
| Divider, | |
| List, | |
| ListItemButton, | |
| ListItemIcon, | |
| ListItemText, | |
| Paper, | |
| Popper, | |
| Typography | |
| } from '@mui/material' | |
| // third-party | |
| import PerfectScrollbar from 'react-perfect-scrollbar' | |
| // project imports | |
| import MainCard from 'ui-component/cards/MainCard' | |
| import Transitions from 'ui-component/extended/Transitions' | |
| import { BackdropLoader } from 'ui-component/loading/BackdropLoader' | |
| // assets | |
| import { IconLogout, IconSettings, IconFileExport, IconFileDownload } from '@tabler/icons' | |
| // API | |
| import databaseApi from 'api/database' | |
| import { SET_MENU } from 'store/actions' | |
| import './index.css' | |
| // ==============================|| PROFILE MENU ||============================== // | |
| const ProfileSection = ({ username, handleLogout }) => { | |
| const theme = useTheme() | |
| const dispatch = useDispatch() | |
| const navigate = useNavigate() | |
| const customization = useSelector((state) => state.customization) | |
| const [open, setOpen] = useState(false) | |
| const [loading, setLoading] = useState(false) | |
| const anchorRef = useRef(null) | |
| const uploadRef = useRef(null) | |
| const handleClose = (event) => { | |
| if (anchorRef.current && anchorRef.current.contains(event.target)) { | |
| return | |
| } | |
| setOpen(false) | |
| } | |
| const handleToggle = () => { | |
| setOpen((prevOpen) => !prevOpen) | |
| } | |
| const handleExportDB = async () => { | |
| setOpen(false) | |
| try { | |
| const response = await databaseApi.getExportDatabase() | |
| const exportItems = response.data | |
| let dataStr = JSON.stringify(exportItems) | |
| let dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr) | |
| let exportFileDefaultName = `DB.json` | |
| let linkElement = document.createElement('a') | |
| linkElement.setAttribute('href', dataUri) | |
| linkElement.setAttribute('download', exportFileDefaultName) | |
| linkElement.click() | |
| } catch (e) { | |
| console.error(e) | |
| } | |
| } | |
| const handleFileUpload = (e) => { | |
| if (!e.target.files) return | |
| const file = e.target.files[0] | |
| const reader = new FileReader() | |
| reader.onload = async (evt) => { | |
| if (!evt?.target?.result) { | |
| return | |
| } | |
| const { result } = evt.target | |
| if (result.includes(`"chatmessages":[`) && result.includes(`"chatflows":[`) && result.includes(`"apikeys":[`)) { | |
| dispatch({ type: SET_MENU, opened: false }) | |
| setLoading(true) | |
| try { | |
| await databaseApi.createLoadDatabase(JSON.parse(result)) | |
| setLoading(false) | |
| navigate('/', { replace: true }) | |
| navigate(0) | |
| } catch (e) { | |
| console.error(e) | |
| setLoading(false) | |
| } | |
| } else { | |
| alert('Incorrect Flowise Database Format') | |
| } | |
| } | |
| reader.readAsText(file) | |
| } | |
| const prevOpen = useRef(open) | |
| useEffect(() => { | |
| if (prevOpen.current === true && open === false) { | |
| anchorRef.current.focus() | |
| } | |
| prevOpen.current = open | |
| }, [open]) | |
| return ( | |
| <> | |
| <ButtonBase ref={anchorRef} sx={{ borderRadius: '12px', overflow: 'hidden' }}> | |
| <Avatar | |
| variant='rounded' | |
| sx={{ | |
| ...theme.typography.commonAvatar, | |
| ...theme.typography.mediumAvatar, | |
| transition: 'all .2s ease-in-out', | |
| background: theme.palette.secondary.light, | |
| color: theme.palette.secondary.dark, | |
| '&:hover': { | |
| background: theme.palette.secondary.dark, | |
| color: theme.palette.secondary.light | |
| } | |
| }} | |
| onClick={handleToggle} | |
| color='inherit' | |
| > | |
| <IconSettings stroke={1.5} size='1.3rem' /> | |
| </Avatar> | |
| </ButtonBase> | |
| <Popper | |
| placement='bottom-end' | |
| open={open} | |
| anchorEl={anchorRef.current} | |
| role={undefined} | |
| transition | |
| disablePortal | |
| popperOptions={{ | |
| modifiers: [ | |
| { | |
| name: 'offset', | |
| options: { | |
| offset: [0, 14] | |
| } | |
| } | |
| ] | |
| }} | |
| > | |
| {({ TransitionProps }) => ( | |
| <Transitions in={open} {...TransitionProps}> | |
| <Paper> | |
| <ClickAwayListener onClickAway={handleClose}> | |
| <MainCard border={false} elevation={16} content={false} boxShadow shadow={theme.shadows[16]}> | |
| {username && ( | |
| <Box sx={{ p: 2 }}> | |
| <Typography component='span' variant='h4'> | |
| {username} | |
| </Typography> | |
| </Box> | |
| )} | |
| <PerfectScrollbar style={{ height: '100%', maxHeight: 'calc(100vh - 250px)', overflowX: 'hidden' }}> | |
| <Box sx={{ p: 2 }}> | |
| <Divider /> | |
| <List | |
| component='nav' | |
| sx={{ | |
| width: '100%', | |
| maxWidth: 250, | |
| minWidth: 200, | |
| backgroundColor: theme.palette.background.paper, | |
| borderRadius: '10px', | |
| [theme.breakpoints.down('md')]: { | |
| minWidth: '100%' | |
| }, | |
| '& .MuiListItemButton-root': { | |
| mt: 0.5 | |
| } | |
| }} | |
| > | |
| <ListItemButton | |
| sx={{ borderRadius: `${customization.borderRadius}px` }} | |
| onClick={() => { | |
| setOpen(false) | |
| uploadRef.current.click() | |
| }} | |
| > | |
| <ListItemIcon> | |
| <IconFileDownload stroke={1.5} size='1.3rem' /> | |
| </ListItemIcon> | |
| <ListItemText primary={<Typography variant='body2'>Load Database</Typography>} /> | |
| </ListItemButton> | |
| <ListItemButton | |
| sx={{ borderRadius: `${customization.borderRadius}px` }} | |
| onClick={handleExportDB} | |
| > | |
| <ListItemIcon> | |
| <IconFileExport stroke={1.5} size='1.3rem' /> | |
| </ListItemIcon> | |
| <ListItemText primary={<Typography variant='body2'>Export Database</Typography>} /> | |
| </ListItemButton> | |
| {localStorage.getItem('username') && localStorage.getItem('password') && ( | |
| <ListItemButton | |
| sx={{ borderRadius: `${customization.borderRadius}px` }} | |
| onClick={handleLogout} | |
| > | |
| <ListItemIcon> | |
| <IconLogout stroke={1.5} size='1.3rem' /> | |
| </ListItemIcon> | |
| <ListItemText primary={<Typography variant='body2'>Logout</Typography>} /> | |
| </ListItemButton> | |
| )} | |
| </List> | |
| </Box> | |
| </PerfectScrollbar> | |
| </MainCard> | |
| </ClickAwayListener> | |
| </Paper> | |
| </Transitions> | |
| )} | |
| </Popper> | |
| <input ref={uploadRef} type='file' hidden accept='.json' onChange={(e) => handleFileUpload(e)} /> | |
| <BackdropLoader open={loading} /> | |
| </> | |
| ) | |
| } | |
| ProfileSection.propTypes = { | |
| username: PropTypes.string, | |
| handleLogout: PropTypes.func | |
| } | |
| export default ProfileSection | |