@mui/material#ListItemText JavaScript Examples
The following examples show how to use
@mui/material#ListItemText.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: MessageListItem.js From react-saas-template with MIT License | 6 votes |
function MessageListItem(props) {
const { message, divider } = props;
const [hasErrorOccurred, setHasErrorOccurred] = useState(false);
const handleError = useCallback(() => {
setHasErrorOccurred(true);
}, [setHasErrorOccurred]);
return (
<ListItem divider={divider}>
<ListItemAvatar>
{hasErrorOccurred ? (
<ErrorIcon color="secondary" />
) : (
<Avatar
src={hasErrorOccurred ? null : message.src}
onError={handleError}
/>
)}
</ListItemAvatar>
<ListItemText
primary={message.text}
secondary={`${formatDistance(message.date * 1000, new Date())} ago`}
/>
</ListItem>
);
}
Example #2
Source File: Permissions.js From admin-web with GNU Affero General Public License v3.0 | 6 votes |
render() {
const { classes, t } = this.props;
const { snackbar, permittedUsers } = this.state;
return (
<FormControl className={classes.form}>
<Grid container alignItems="center" className={classes.headline}>
<Typography variant="h6">{t('Permitted Users')}</Typography>
<IconButton onClick={this.handleAddDialog(true)} size="large">
<AddCircleOutline color="primary" fontSize="small"/>
</IconButton>
</Grid>
<List>
{(permittedUsers || []).map((user, key) => <Fragment key={key}>
<ListItem className={classes.listItem}>
<ListItemText primary={user.displayName} />
<IconButton onClick={this.handleRemoveUser(user.ID, key)} size="large">
<Delete color="error" />
</IconButton>
</ListItem>
<Divider />
</Fragment>)}
</List>
<Feedback
snackbar={snackbar}
onClose={() => this.setState({ snackbar: '' })}
/>
</FormControl>
);
}
Example #3
Source File: UserMoreMenu.js From Django-REST-Framework-React-BoilerPlate with MIT License | 6 votes |
// ----------------------------------------------------------------------
export default function UserMoreMenu() {
const ref = useRef(null);
const [isOpen, setIsOpen] = useState(false);
return (
<>
<IconButton ref={ref} onClick={() => setIsOpen(true)}>
<Iconify icon="eva:more-vertical-fill" width={20} height={20} />
</IconButton>
<Menu
open={isOpen}
anchorEl={ref.current}
onClose={() => setIsOpen(false)}
PaperProps={{
sx: { width: 200, maxWidth: '100%' },
}}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
>
<MenuItem sx={{ color: 'text.secondary' }}>
<ListItemIcon>
<Iconify icon="eva:trash-2-outline" width={24} height={24} />
</ListItemIcon>
<ListItemText primary="Delete" primaryTypographyProps={{ variant: 'body2' }} />
</MenuItem>
<MenuItem component={RouterLink} to="#" sx={{ color: 'text.secondary' }}>
<ListItemIcon>
<Iconify icon="eva:edit-fill" width={24} height={24} />
</ListItemIcon>
<ListItemText primary="Edit" primaryTypographyProps={{ variant: 'body2' }} />
</MenuItem>
</Menu>
</>
);
}
Example #4
Source File: SubscriptionInfo.js From react-saas-template with MIT License | 6 votes |
function SubscriptionInfo(props) {
const { classes, openAddBalanceDialog } = props;
return (
<Toolbar className={classes.toolbar}>
<ListItemText primary="Status" secondary="Premium Account" />
<Button
variant="contained"
color="secondary"
onClick={openAddBalanceDialog}
disableElevation
>
Add Balance
</Button>
</Toolbar>
);
}
Example #5
Source File: index.js From neutron with Mozilla Public License 2.0 | 6 votes |
SectionAutofill = () => {
const passwordsAskToSave = useSelector((state) => state.preferences.passwordsAskToSave);
return (
<List disablePadding dense>
<ListItem>
<ListItemText
primary="Ask to save logins and passwords for websites"
secondary={getStaticGlobal('passwordManagerExtensionDetected')
? `The built-in autofill feature has been taken over by the '${getStaticGlobal('passwordManagerExtensionDetected')}'.`
: `Passwords are stored encrypted locally on disk with the master key stored securely in ${getKeytarVaultName()}.`}
/>
<ListItemSecondaryAction>
<Switch
edge="end"
color="primary"
checked={getStaticGlobal('passwordManagerExtensionDetected') ? false : passwordsAskToSave}
disabled={getStaticGlobal('passwordManagerExtensionDetected')}
onChange={(e) => {
requestSetPreference('passwordsAskToSave', e.target.checked);
}}
/>
</ListItemSecondaryAction>
</ListItem>
</List>
);
}
Example #6
Source File: AccountInformationArea.js From react-saas-template with MIT License | 6 votes |
function AccountInformationArea(props) {
const { classes, toggleAccountActivation, isAccountActivated } = props;
return (
<Paper className={classes.paper}>
<Toolbar className={classes.toolbar}>
<Box display="flex" alignItems="center">
<Box mr={2}>
<ListItemText
primary="Status"
secondary={isAccountActivated ? "Activated" : "Not activated"}
className="mr-2"
/>
</Box>
<ListItemIcon>
<LoopIcon
className={classNames(
isAccountActivated ? classes.spin : null,
classes.scaleMinus
)}
/>
</ListItemIcon>
</Box>
<ListItemSecondaryAction className={classes.listItemSecondaryAction}>
<Switch
color="secondary"
checked={isAccountActivated}
onClick={toggleAccountActivation}
inputProps={{
"aria-label": isAccountActivated
? "Deactivate Account"
: "Activate Account"
}}
/>
</ListItemSecondaryAction>
</Toolbar>
</Paper>
);
}
Example #7
Source File: index.js From fireact with MIT License | 6 votes |
AppMenu = () => {
return (
<List>
<Link to="/" style={{textDecoration:'none'}}>
<ListItem button key="My Accounts">
<ListItemIcon><AppIcon /></ListItemIcon>
<ListItemText primary={<Typography color="textPrimary">My Accounts</Typography>} />
</ListItem>
</Link>
<Divider />
<Link to="/user/profile" style={{textDecoration:'none'}}>
<ListItem button key="Profile">
<ListItemIcon><AccountBoxIcon /></ListItemIcon>
<ListItemText primary={<Typography color="textPrimary">Profile</Typography>} />
</ListItem>
</Link>
<Link to="/user/log" style={{textDecoration:'none'}}>
<ListItem button key="Activity Logs">
<ListItemIcon><ListAltIcon /></ListItemIcon>
<ListItemText primary={<Typography color="textPrimary">Activity Logs</Typography>} />
</ListItem>
</Link>
</List>
)
}
Example #8
Source File: SideBarItem.component.jsx From Stackoverflow-Clone-Frontend with MIT License | 6 votes |
DefaultItem = ({ link, icon, text }) => (
<NavLink
activeClassName='active'
className='icon-link nav-link'
to={link}
>
<ListItem disablePadding>
<ListItemButton className='menu-list-btn'>
<ListItemIcon className='menu-list-icon'>
{icon}
</ListItemIcon>
<ListItemText className='menu-list-text' primary={text}/>
</ListItemButton>
</ListItem>
</NavLink>
)
Example #9
Source File: Alphabetical.jsx From Edlib with GNU General Public License v3.0 | 6 votes |
Alphabetical = ({ allH5ps, contentTypes }) => {
const { classes } = useStyles();
return (
<List dense component="div" disablePadding>
{allH5ps.map((h5p, index) => (
<ListItem
key={index}
button
dense
onClick={() => contentTypes.toggle(h5p)}
>
<ListItemIcon
classes={{
root: classes.listItemIcon,
}}
>
<Checkbox
size="small"
edge="start"
checked={contentTypes.has(h5p)}
tabIndex={-1}
disableRipple
color="primary"
classes={{
root: classes.checkboxRoot,
}}
/>
</ListItemIcon>
<ListItemText
primary={`${h5p.title} (${h5p.filteredCount})`}
/>
</ListItem>
))}
</List>
);
}
Example #10
Source File: SideBarItem.component.jsx From Stackoverflow-Clone-Frontend with MIT License | 6 votes |
HomeItem = ({ link, text }) => (
<NavLink
exact
activeClassName='active'
className='home-link nav-link'
to={link}
>
<ListItem disablePadding>
<ListItemButton style={{ paddingLeft: '8px' }}>
<ListItemText className='menu-list-text' primary={text} />
</ListItemButton>
</ListItem>
</NavLink>
)
Example #11
Source File: index.js From neutron with Mozilla Public License 2.0 | 5 votes |
SectionNeverSaved = () => {
const passwordsNeverSaveDomains = useSelector(
(state) => state.preferences.passwordsNeverSaveDomains,
);
return (
<List disablePadding dense>
{passwordsNeverSaveDomains.length < 1 ? (
<ListItem disabled>
<ListItemText primary="Empty." />
</ListItem>
) : (
<ListItem>
<Table size="small" aria-label="Never Saved">
<TableBody>
{passwordsNeverSaveDomains.map((domain) => (
<TableRow key={domain}>
<TableCell component="th" scope="row">
{domain}
</TableCell>
<TableCell align="right">
<Tooltip title="Remove">
<IconButton
aria-label="Remove"
size="small"
onClick={() => {
requestSetPreference(
'passwordsNeverSaveDomains',
passwordsNeverSaveDomains.filter(((item) => item !== domain)),
);
}}
>
<ClearIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ListItem>
)}
</List>
);
}
Example #12
Source File: CheckLdapDialog.js From admin-web with GNU Affero General Public License v3.0 | 5 votes |
render() {
const { classes, t, open, onClose, Orphaned } = this.props;
return (
<Dialog
onClose={onClose}
open={open}
maxWidth="md"
fullWidth
>
<DialogTitle>{t('Orphaned users')}</DialogTitle>
<DialogContent style={{ minWidth: 400 }}>
{Orphaned.length > 0 ? <List>
{Orphaned.map(user =>
<ListItem key={user.ID}>
<ListItemText
primary={user.username}
/>
</ListItem>
)}
</List> : <Typography>All LDAP users are valid</Typography>}
</DialogContent>
<DialogActions>
<Button
onClick={onClose}
color="secondary"
>
{t('Close')}
</Button>
<Button
className={classes.delete}
onClick={this.handleDelete(true)}
variant="contained"
color="secondary"
disabled={Orphaned.length === 0}
>
{t('Delete with files')}
</Button>
<Button
className={classes.delete}
onClick={this.handleDelete(false)}
variant="contained"
color="secondary"
disabled={Orphaned.length === 0}
>
{t('Delete')}
</Button>
</DialogActions>
</Dialog>
);
}
Example #13
Source File: DBService.js From admin-web with GNU Affero General Public License v3.0 | 5 votes |
render() {
const { classes, t } = this.props;
const { name, snackbar, files, deleting } = this.state;
const writable = this.context.includes(SYSTEM_ADMIN_WRITE);
return (
<ViewWrapper
topbarTitle={t('DB Service')}
snackbar={snackbar}
onSnackbarClose={() => this.setState({ snackbar: '' })}
>
<Paper className={classes.paper} elevation={1}>
<Grid container>
<Typography
color="primary"
variant="h5"
>
{t('editHeadline', { item: 'Service' })}
</Typography>
</Grid>
<FormControl className={classes.form}>
<TextField
label={t("Service")}
className={classes.input}
value={name || ''}
autoFocus
onChange={this.handleInput('name')}
/>
</FormControl>
<Typography variant="h6">Files</Typography>
<List>
{files.map((file, idx) => <React.Fragment key={idx}>
<ListItem button onClick={this.handleNavigation(`dbconf/${name}/${file}`)}>
<ListItemText
primary={file}
/>
{writable && <IconButton onClick={this.handleDelete(file)} size="large">
<Delete color="error" />
</IconButton>}
</ListItem>
<Divider />
</React.Fragment>
)}
</List>
<Button
color="secondary"
onClick={this.handleNavigation('dbconf')}
style={{ marginRight: 8 }}
>
{t('Back')}
</Button>
<Button
variant="contained"
color="primary"
onClick={this.handleEdit}
disabled={!writable}
>
{t('Save')}
</Button>
</Paper>
<DomainDataDelete
open={!!deleting}
delete={this.props.delete}
onSuccess={this.handleDeleteSuccess}
onError={this.handleDeleteError}
onClose={this.handleDeleteClose}
item={deleting}
id={deleting}
domainID={name}
/>
</ViewWrapper>
);
}
Example #14
Source File: VertOptions.js From react-saas-template with MIT License | 5 votes |
function VertOptions(props) {
const { items, classes, color } = props;
const anchorEl = useRef();
const [isOpen, setIsOpen] = useState(false);
const handleClose = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const handleOpen = useCallback(() => {
setIsOpen(true);
}, [setIsOpen]);
const id = isOpen ? "scroll-playground" : null;
return (
<Fragment>
<IconButton
onClick={handleOpen}
buttonRef={anchorEl}
style={{ color: color ? color : null }}
aria-describedby={id}
aria-label="More Options"
size="large">
<MoreVertIcon style={{ color: color ? color : null }} />
</IconButton>
<Popover
id={id}
open={isOpen}
anchorEl={anchorEl.current}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
onClose={handleClose}
disableScrollLock
>
<MenuList dense>
{items.map((item) => (
<MenuItem
key={item.name}
onClick={() => {
handleClose();
item.onClick();
}}
>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText className={classes.listItemtext}>
{item.name}
</ListItemText>
</MenuItem>
))}
</MenuList>
</Popover>
</Fragment>
);
}
Example #15
Source File: Ldap.js From admin-web with GNU Affero General Public License v3.0 | 5 votes |
render() {
const { classes, t, domain, ldapUsers } = this.props;
const { loading, snackbar, confirming } = this.state;
const writable = this.context.includes(DOMAIN_ADMIN_WRITE);
return (
<ViewWrapper
topbarTitle={domain.domainname}
snackbar={snackbar}
onSnackbarClose={() => this.setState({ snackbar: '' })}
>
<Typography variant="h2" className={classes.pageTitle}>
<BackIcon onClick={this.handleNavigation(domain.ID + '/users')} className={classes.backIcon} />
<span className={classes.pageTitleSecondary}>| </span>
{t("LDAP")}
</Typography>
<Grid container justifyContent="center">
<TextField
autoFocus
placeholder={t("Search LDAP")}
onChange={this.handleLdapSearch}
variant="outlined"
color="primary"
fullWidth
className={classes.searchTf}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search color="primary"/>
</InputAdornment>
),
}}
/>
</Grid>
{ldapUsers.length > 0 && <Paper elevation={1}>
<List>
{ldapUsers.map((user, idx) => <React.Fragment key={idx}>
<ListItem >
<ListItemText
primary={user.name}
primaryTypographyProps={{ color: 'primary' }}
secondary={user.email}
/>
{writable && <IconButton onClick={this.handleImport(user)} size="large">
<Import />
</IconButton>}
</ListItem>
<Divider />
</React.Fragment>
)}
</List>
</Paper>}
<Grid container justifyContent="center" className={classes.loaderContainer}>
<Grow
in={loading}
timeout={{
appear: 500,
enter: 10,
exit: 10,
}}
>
<CircularProgress color="primary" size={40}/>
</Grow>
</Grid>
<ImportDialog
open={!!confirming}
user={confirming || {}}
onSuccess={this.handleSuccess}
onClose={this.handleClose}
onError={this.handleError}
/>
</ViewWrapper>
);
}
Example #16
Source File: MessagePopperButton.js From react-saas-template with MIT License | 5 votes |
function MessagePopperButton(props) {
const { classes, messages } = props;
const anchorEl = useRef();
const [isOpen, setIsOpen] = useState(false);
const handleClick = useCallback(() => {
setIsOpen(!isOpen);
}, [isOpen, setIsOpen]);
const handleClickAway = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const id = isOpen ? "scroll-playground" : null;
return (
<Fragment>
<IconButton
onClick={handleClick}
buttonRef={anchorEl}
aria-label="Open Messages"
aria-describedby={id}
color="primary"
size="large">
<MessageIcon />
</IconButton>
<Popover
disableScrollLock
id={id}
open={isOpen}
anchorEl={anchorEl.current}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
classes={{ paper: classes.popoverPaper }}
onClose={handleClickAway}
>
<AppBar position="static" color="inherit" className={classes.noShadow}>
<Box pt={1} pl={2} pb={1} pr={1}>
<Typography variant="subtitle1">Messages</Typography>
</Box>
<Divider className={classes.divider} />
</AppBar>
<List dense className={classes.tabContainer}>
{messages.length === 0 ? (
<ListItem>
<ListItemText>
You haven't received any messages yet.
</ListItemText>
</ListItem>
) : (
messages.map((element, index) => (
<MessageListItem
key={index}
message={element}
divider={index !== messages.length - 1}
/>
))
)}
</List>
</Popover>
</Fragment>
);
}
Example #17
Source File: SelectedMenu.jsx From matx-react with MIT License | 5 votes |
export default function SelectedMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const [selectedIndex, setSelectedIndex] = React.useState(1);
function handleClickListItem(event) {
setAnchorEl(event.currentTarget);
}
function handleMenuItemClick(event, index) {
setSelectedIndex(index);
setAnchorEl(null);
}
function handleClose() {
setAnchorEl(null);
}
return (
<MenuRoot>
<List component="nav" aria-label="Device settings">
<ListItem
button
aria-haspopup="true"
aria-controls="lock-menu"
aria-label="When device is locked"
onClick={handleClickListItem}
>
<ListItemText primary="When device is locked" secondary={options[selectedIndex]} />
</ListItem>
</List>
<Menu
id="lock-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{options.map((option, index) => (
<MenuItem
key={option}
disabled={index === 0}
selected={index === selectedIndex}
onClick={(event) => handleMenuItemClick(event, index)}
>
{option}
</MenuItem>
))}
</Menu>
</MenuRoot>
);
}
Example #18
Source File: Licenses.jsx From Edlib with GNU General Public License v3.0 | 5 votes |
Licenses = ({ licenses, filterCount, licenseData }) => {
const { t } = useTranslation();
const { classes } = useStyles();
return (
<List dense component="div" disablePadding className={classes.nested}>
{licenseData
.map((item) => {
const parts = item.id.split('-');
const count = filterCount.find(
(filterCount) =>
filterCount.key === item.id.toLowerCase()
);
return {
title: parts
.map((part) => t(`licenses.${part}`))
.join(' - '),
value: item.id,
filteredCount: count ? count.count : 0,
};
})
.sort((a, b) =>
a.title < b.title ? -1 : a.title > b.title ? 1 : 0
)
.map((license) => (
<ListItem
key={license.value}
button
dense
onClick={() => licenses.toggle(license)}
>
<ListItemIcon
classes={{
root: classes.listItemIcon,
}}
>
<Checkbox
size="small"
edge="start"
checked={licenses.has(license)}
tabIndex={-1}
disableRipple
color="primary"
classes={{
root: classes.checkboxRoot,
}}
/>
</ListItemIcon>
<ListItemText
primary={`${license.title} (${license.filteredCount})`}
/>
</ListItem>
))}
</List>
);
}
Example #19
Source File: SavedFilters.jsx From Edlib with GNU General Public License v3.0 | 5 votes |
SavedFilters = ({ savedFilterData, setShowDelete, filterUtils }) => {
const { t } = useTranslation();
const { classes } = useStyles();
return (
<>
<List
dense
component="div"
disablePadding
className={classes.nested}
>
{savedFilterData.map((savedFilter) => {
return (
<ListItem
key={savedFilter.id}
button
dense
onClick={() =>
filterUtils.setFilterFromChoices(
savedFilter.choices
)
}
>
<ListItemIcon
classes={{
root: classes.listItemIcon,
}}
>
<Checkbox
size="small"
edge="start"
checked={filterUtils.areFiltersAndChoicesIdentical(
savedFilter.choices
)}
tabIndex={-1}
disableRipple
color="primary"
classes={{
root: classes.checkboxRoot,
}}
/>
</ListItemIcon>
<ListItemText primary={savedFilter.name} />
</ListItem>
);
})}
<ListItem dense>
<Box>
<Button
color="primary"
variant="outlined"
onClick={() => setShowDelete(true)}
size="small"
disabled={savedFilterData.length === 0}
>
{t('delete')}
</Button>
</Box>
</ListItem>
</List>
</>
);
}
Example #20
Source File: index.js From fireact with MIT License | 5 votes |
AccountMenu = () => {
const { accountId } = useParams();
const { userData } = useContext(AuthContext);
useEffect(() => {
document.querySelectorAll('.c-sidebar').forEach(element => {
window.coreui.Sidebar._sidebarInterface(element)
});
})
return (
<List>
<Link to={'/account/'+accountId+'/'} style={{textDecoration:'none'}}>
<ListItem button key="Demo App">
<ListItemIcon><DashboardIcon /></ListItemIcon>
<ListItemText primary={<Typography color="textPrimary">Demo App</Typography>} />
</ListItem>
</Link>
{userData.currentAccount.role === 'admin' &&
<>
<Divider />
<Link to={'/account/'+accountId+'/users'} style={{textDecoration:'none'}}>
<ListItem button key="Users">
<ListItemIcon><PeopleIcon /></ListItemIcon>
<ListItemText primary={<Typography color="textPrimary">Users</Typography>} />
</ListItem>
</Link>
<Link to={'/account/'+accountId+'/billing'} style={{textDecoration:'none'}}>
<ListItem button key="Billing">
<ListItemIcon><PaymentIcon /></ListItemIcon>
<ListItemText primary={<Typography color="textPrimary">Billing</Typography>} />
</ListItem>
</Link>
</>
}
</List>
)
}
Example #21
Source File: License.js From admin-web with GNU Affero General Public License v3.0 | 4 votes |
render() {
const { classes, t, license, Domains } = this.props;
const { snackbar, expandedDomainIdxs, domainUsers, domainsExpanded, counts } = this.state;
return (
<TableViewContainer
headline={t("License")}
subtitle={t('license_sub')}
href="https://docs.grommunio.com/admin/administration.html#license"
snackbar={snackbar}
onSnackbarClose={() => this.setState({ snackbar: '' })}
>
<Paper className={classes.paper} elevation={1}>
<Grid container alignItems="center">
<Grid item className={classes.gridItem}>
<Button
variant="contained"
color="primary"
onClick={this.handleUpload}
size="small"
>
{t('Upload')}
</Button>
</Grid>
<Typography variant="body2">{t("Don't have a license?")}</Typography>
<Button
className={classes.buyNow}
variant="contained"
color="primary"
href="https://grommunio.com/product/"
target="_blank"
size="small"
>
{t('Buy now')}
</Button>
</Grid>
<Grid container direction="column" className={classes.licenseContainer}>
<Typography className={classes.data}>
<span className={classes.description}>{t('Product')}:</span>
{license.product}
</Typography>
<Typography className={classes.data}>
<span className={classes.description}>{t('Created')}:</span>
{license.notBefore}
</Typography>
<Typography className={classes.data}>
<span className={classes.description}>{t('Expires')}:</span>
{license.notAfter}
</Typography>
<Typography className={classes.data}>
<span className={classes.description}>{t('Users')}:</span>
{license.currentUsers}
<IconButton onClick={this.toggleDomainExpansion} size="small">
{domainsExpanded ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</Typography>
<Collapse in={domainsExpanded} unmountOnExit>
<List>
{Domains.map(({ ID, domainname }, idx) => <React.Fragment key={idx}>
<ListItemButton onClick={this.handleExpansion(ID, idx)}>
<ListItemText
primary={`${domainname} (${counts[domainname] || 0})`}
/>
{expandedDomainIdxs.includes(idx) ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={expandedDomainIdxs.includes(idx)} unmountOnExit>
<List component="div" disablePadding>
{domainUsers[ID] ? domainUsers[ID].map((user, idx) =>
<ListItem key={idx} sx={{ pl: 4 }}>
<ListItemText primary={user.username}/>
</ListItem>
) : <div className={classes.progressContainer}>
<CircularProgress/>
</div>}
<ListItemButton onClick={this.handleNavigation(ID)} sx={{ pl: 4 }}>
<ListItemText primary={t('View all') + "..."}/>
</ListItemButton>
</List>
</Collapse>
</React.Fragment>)}
</List>
</Collapse>
<Typography className={classes.data}>
<span className={classes.description}>{t('Max users')}:</span>
{license.maxUsers}
</Typography>
</Grid>
<input
accept=".crt,.pem"
style={{ display: 'none' }}
id="license-upload-input"
type="file"
ref={r => (this.imageInputRef = r)}
onChange={this.handleUploadConfirm}
/>
</Paper>
</TableViewContainer>
);
}
Example #22
Source File: Logs.js From admin-web with GNU Affero General Public License v3.0 | 4 votes |
render() {
const { classes, t, logs } = this.props;
const { snackbar, log, filename, autorefresh, clipboardMessage } = this.state;
return (
<TableViewContainer
headline={t("Logs")}
subtitle={t("logs_sub")}
href="https://docs.grommunio.com/admin/administration.html#logs"
snackbar={snackbar}
onSnackbarClose={() => this.setState({ snackbar: '' })}
>
<div className={classes.logViewer}>
<List style={{ width: 200 }}>
<ListItem>
<ListItemText
primary={t("Log files")}
primaryTypographyProps={{ color: "primary", variant: 'h6' }}
/>
</ListItem>
{logs.Logs.map((log, idx) =>
<ListItem
key={idx}
onClick={this.handleLog(log)}
button
className={classes.li}
selected={log === filename}
>
<ListItemText
primary={log}
primaryTypographyProps={{ color: "textPrimary" }}
/>
</ListItem>
)}
</List>
<Paper elevation={1} className={classes.paper}>
{filename && <Grid container justifyContent="flex-end">
<IconButton onClick={this.handleRefresh} style={{ marginRight: 8 }} size="large">
<Refresh />
</IconButton>
<FormControlLabel
control={
<Switch
checked={autorefresh}
onChange={this.handleAutoRefresh}
name="autorefresh"
color="primary"
/>
}
label="Autorefresh"
/>
</Grid>}
{log.length > 0 ? <IconButton onClick={this.handleScroll} size="large">
<ArrowUp />
</IconButton> : filename && <Typography><no logs></Typography>}
{log.map((log, idx) =>
<pre
key={idx}
className={log.level < 4 ? classes.errorLog : log.level < 6 ? classes.noticeLog : classes.log}
onClick={this.handleCopyToClipboard(log.message)}
>
{'[' + log.time + ']: ' + log.message}
</pre>
)}
</Paper>
</div>
<Portal>
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
open={!!clipboardMessage}
onClose={this.handleSnackbarClose}
autoHideDuration={2000}
transitionDuration={{ in: 0, appear: 250, enter: 250, exit: 0 }}
>
<Alert
onClose={this.handleSnackbarClose}
severity={"success"}
elevation={6}
variant="filled"
>
{clipboardMessage}
</Alert>
</Snackbar>
</Portal>
</TableViewContainer>
);
}
Example #23
Source File: index.js From neutron with Mozilla Public License 2.0 | 4 votes |
SectionSavedPassword = () => {
const [credentials, setCredentials] = useState([]);
const [revealPasswords, setRevealPasswords] = useState({});
const reloadCredentials = useCallback(() => {
getAllCredentialsAsync()
.then((_credentials) => {
setCredentials(_credentials);
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log(err);
});
}, [setCredentials]);
useEffect(() => {
reloadCredentials();
}, [reloadCredentials]);
useEffect(() => {
ipcRenderer.removeAllListeners('password-credentials-added');
ipcRenderer.on('password-credentials-added', () => {
reloadCredentials();
});
return () => {
ipcRenderer.removeAllListeners('password-credentials-added');
};
}, [reloadCredentials]);
return (
<List disablePadding dense>
{credentials.length < 1 ? (
<ListItem disabled>
<ListItemText primary="Saved passwords will appear here." />
</ListItem>
) : (
<>
<ListItem>
<Table size="small" aria-label="Saved Passwords">
<TableHead>
<TableRow>
<TableCell>Website</TableCell>
<TableCell align="right">Username</TableCell>
<TableCell align="right">Password</TableCell>
<TableCell align="right" />
</TableRow>
</TableHead>
<TableBody>
{credentials.map((row) => {
const key = `${row.domain}-${row.username}`;
return (
<TableRow key={key}>
<TableCell component="th" scope="row">
{row.domain}
</TableCell>
<TableCell align="right">
<TextField
value={row.username}
margin="dense"
fullWidth
variant="outlined"
inputProps={{ 'aria-label': 'Username' }}
disabled
/>
</TableCell>
<TableCell align="right">
<FormControl variant="outlined">
<OutlinedInput
id="outlined-adornment-password"
type={revealPasswords[key] ? 'text' : 'password'}
defaultValue={row.password}
margin="dense"
endAdornment={(
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() => {
setRevealPasswords({
...revealPasswords,
[key]: !revealPasswords[key],
});
}}
edge="end"
size="large"
>
{revealPasswords[key]
? <VisibilityIcon /> : <VisibilityOffIcon />}
</IconButton>
</InputAdornment>
)}
inputProps={{ 'aria-label': 'Password' }}
fullWidth
onChange={(e) => {
const newPassword = e.target.value;
saveCredentialAsync(row.domain, row.username, newPassword, row.id)
.then(() => reloadCredentials())
.catch((err) => {
// eslint-disable-next-line no-console
console.log(err);
});
}}
/>
</FormControl>
</TableCell>
<TableCell align="right">
<Tooltip title="Remove">
<IconButton
aria-label="Remove"
size="small"
onClick={() => {
deleteCredentialAsync(row.id)
.then(() => reloadCredentials())
.catch((err) => {
// eslint-disable-next-line no-console
console.log(err);
});
}}
>
<ClearIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</ListItem>
<ListItem disabled>
<ListItemText primary={`Passwords are stored encrypted locally on disk with the master key stored securely in ${getKeytarVaultName()}.`} />
</ListItem>
</>
)}
</List>
);
}
Example #24
Source File: ClassDetails.js From admin-web with GNU Affero General Public License v3.0 | 4 votes |
render() {
const { classes, t, domain, _classes } = this.props;
const writable = this.context.includes(DOMAIN_ADMIN_WRITE);
const { _class, autocompleteInput, snackbar, stack } = this.state;
const { classname, parentClasses, members, filters, children } = _class;
return (
<ViewWrapper
topbarTitle={t('Groups')}
snackbar={snackbar}
onSnackbarClose={() => this.setState({ snackbar: '' })}
>
<Paper className={classes.paper} elevation={1}>
<Grid container>
<Typography
color="primary"
variant="h5"
>
{t('editHeadline', { item: 'Group' })}
</Typography>
</Grid>
<FormControl className={classes.form}>
<Breadcrumbs className={classes.breadcrumbs}>
{stack.map((_class, idx) =>
<Link
className={classes.breadcrumb}
key={_class.ID}
color="inherit"
onClick={this.handleBreadcrumb(_class.ID, idx)}
>
{_class.classname}
</Link>
)}
</Breadcrumbs>
<TextField
className={classes.input}
label={t("Groupname")}
fullWidth
value={classname || ''}
onChange={this.handleInput('classname')}
autoFocus
required
/>
<MagnitudeAutocomplete
value={parentClasses || []}
filterAttribute={'classname'}
inputValue={autocompleteInput}
onChange={this.handleAutocomplete('parentClasses')}
className={classes.input}
options={_classes || []}
onInputChange={this.handleAutocompleteInput}
label={t("Parent groups")}
placeholder={t("Search groups") + "..."}
multiple
autoSelect
/>
<TextField
className={classes.input}
label={t("Members (separate by comma)")}
fullWidth
value={members || ''}
onChange={this.handleMemberInput}
/>
</FormControl>
<div>
<Typography variant="body1">{t('Filters (All must be true)')}</Typography>
{filters && filters.map((ANDFilter, ANDidx) =>
<Accordion
className={classes.panel}
elevation={2 /* 1 has global overwrite */}
key={ANDidx}
defaultExpanded
>
<AccordionSummary>
<Grid container justifyContent="space-between">
<Typography body="body1">{t('Filter (One must be true)')}</Typography>
<IconButton onClick={this.handleRemoveAND(ANDidx)} size="large">
<Delete fontSize="small" color="error"/>
</IconButton>
</Grid>
</AccordionSummary>
<AccordionDetails>
<Grid container>
{ANDFilter.map((ORFilter, ORidx) =>
<Grid item xs={12} key={ORidx} className={classes.grid}>
<Autocomplete
value={ORFilter.prop || ''}
inputValue={ORFilter.prop || ''}
onChange={this.handleAutocomplete(ANDidx, ORidx, 'prop')}
onInputChange={this.handleFilterInput(ANDidx, ORidx, 'prop')}
freeSolo
className={classes.flexTextfield}
options={this.columns}
renderInput={(params) => (
<TextField
{...params}
label={t("Name of property to match")}
/>
)}
/>
<TextField
className={classes.flexTextfield}
label={t("Comparison operator")}
value={ORFilter.op || ''}
onChange={this.handleFilterInput(ANDidx, ORidx, 'op')}
select
>
{this.operators.map(op =>
<MenuItem value={op.value} key={op.label}>{op.label}</MenuItem>
)}
</TextField>
<TextField
className={classes.flexTextfield}
label={t("Compare value (binary operators)")}
value={ORFilter.val || ''}
onChange={this.handleFilterInput(ANDidx, ORidx, 'val')}
/>
{filters[ANDidx].length > 1 &&
<IconButton onClick={this.handleRemoveOR(ANDidx, ORidx)} size="large">
<Delete fontSize="small" color="error"/>
</IconButton>}
</Grid>
)}
<Grid container justifyContent="center">
<Button variant="outlined" onClick={this.handleAddOR(ANDidx)}>{t('Add or-statement')}</Button>
</Grid>
</Grid>
</AccordionDetails>
</Accordion>
)}
<Grid container justifyContent="center">
<Button variant="outlined" onClick={this.handleAddAND}>{t('Add and-statement')}</Button>
</Grid>
</div>
<Typography variant="h6">{t('Children')}</Typography>
<List>
{children && children.map(child =>
<ListItem
key={child.ID}
button
onClick={this.handleChildClicked(child)}
>
<ListItemText primary={child.classname} />
</ListItem>
)}
</List>
<Button
variant="text"
color="secondary"
onClick={this.handleNavigation(domain.ID + '/classes')}
style={{ marginRight: 8 }}
>
{t('Back')}
</Button>
<Button
variant="contained"
color="primary"
onClick={this.handleEdit}
disabled={!writable}
>
{t('Save')}
</Button>
</Paper>
</ViewWrapper>
);
}
Example #25
Source File: FolderPermissions.js From admin-web with GNU Affero General Public License v3.0 | 4 votes |
render() {
const { classes, t, open, onCancel, owners, domain, folderID } = this.props;
const { permissions, selected, adding, deleting } = this.state;
return (
<Dialog
onClose={onCancel}
open={open}
maxWidth="sm"
fullWidth
TransitionProps={{
onEnter: this.handleEnter,
}}
>
<DialogTitle>{t('Permissions')}</DialogTitle>
<DialogContent style={{ minWidth: 400 }}>
{owners.length > 0 ? <List className={classes.list}>
{owners.map((user, idx) => <Fragment key={idx}>
<ListItem disablePadding>
<ListItemButton
selected={user.memberID === selected?.memberID}
component="a"
onClick={this.handleUserSelect(user)}
>
<ListItemText primary={user.username}/>
</ListItemButton>
</ListItem>
<Divider />
</Fragment>)}
</List> : <div className={classes.noOwnersContainer}>
<em>{t('No owners')}</em>
</div>}
<div className={classes.addUserRow}>
<Button
onClick={this.handleAdd}
variant="contained"
color="primary"
style={{ marginRight: 8 }}
>
{t('Add')}
</Button>
<Button
onClick={this.handleDelete}
color="secondary"
>
{t('Remove')}
</Button>
</div>
<FormControl fullWidth style={{ marginBottom: 4 }}>
<InputLabel>{t('Profile')}</InputLabel>
<Select
labelId="demo-simple-select-label"
value={permissionProfiles.findIndex(profile => profile.value === permissions) === -1 ? "" : permissions}
label={t('Profile')}
onChange={this.handleProfileSelect}
>
{permissionProfiles.map((profile, idx) =>
<MenuItem key={idx} value={profile.value}>
{profile.name}
</MenuItem>
)}
</Select>
</FormControl>
<Grid container>
<Grid item xs={6}>
<FormControl className={classes.form}>
<FormLabel>Read</FormLabel>
<RadioGroup defaultValue={0} value={permissions & 1} onChange={this.handlePermissions}>
<FormControlLabel
value={0x0}
control={<Radio size="small" className={classes.radio}/>}
label="None"
/>
<FormControlLabel
value={0x1}
control={<Radio size="small" className={classes.radio}/>}
label="Full Details"
/>
</RadioGroup>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl className={classes.form}>
<FormLabel>Write</FormLabel>
<FormControlLabel
control={
<Checkbox
value={0x2}
checked={Boolean(permissions & 0x2)}
onChange={this.handlePermissions}
className={classes.radio}
color="primary"
/>
}
label={t('Create items')}
/>
<FormControlLabel
control={
<Checkbox
value={0x80}
checked={Boolean(permissions & 0x80)}
className={classes.radio}
onChange={this.handlePermissions}
color="primary"
/>
}
label={t('Create subfolders')}
/>
<FormControlLabel
control={
<Checkbox
checked={Boolean(permissions & 0x8)}
value={0x8}
className={classes.radio}
onChange={this.handlePermissions}
color="primary"
/>
}
label={t('Edit own')}
/>
<FormControlLabel
control={
<Checkbox
className={classes.radio}
checked={Boolean(permissions & 0x20)}
value={0x20}
onChange={this.handlePermissions}
color="primary"
/>
}
label={t('Edit all')}
/>
</FormControl>
</Grid>
</Grid>
<Grid container style={{ marginTop: 16 }}>
<Grid item xs={6}>
<FormControl className={classes.form}>
<FormLabel>Delete items</FormLabel>
<RadioGroup
value={(permissions & 0x50) || true /* This is a bit janky */}
defaultValue={true}
onChange={this.handleRadioPermissions}
>
<FormControlLabel
value={(permissions & 0x50) === 0} // Has explicit handling
control={<Radio size="small" className={classes.radio}/>}
label="None" />
<FormControlLabel
value={0x10}
control={<Radio size="small" className={classes.radio}/>}
label="Own"
/>
<FormControlLabel
value={0x50}
control={<Radio size="small" className={classes.radio}/>}
label="All"
/>
</RadioGroup>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl className={classes.form}>
<FormLabel>Other</FormLabel>
<FormControlLabel
control={
<Checkbox
className={classes.radio}
checked={Boolean(permissions & 0x100)}
value={0x100}
onChange={this.handlePermissions}
color="primary"
/>
}
label={t('Folder owner')}
/>
<FormControlLabel
control={
<Checkbox
className={classes.radio}
checked={Boolean(permissions & 0x200)}
onChange={this.handlePermissions}
color="primary"
value={0x200}
/>
}
label={t('Folder contact')}
/>
<FormControlLabel
control={
<Checkbox
className={classes.radio}
checked={Boolean(permissions & 0x400)}
onChange={this.handlePermissions}
color="primary"
value={0x400}
/>
}
label={t('Folder visible')}
/>
</FormControl>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button
onClick={onCancel}
color="secondary"
>
{t('Close')}
</Button>
<Button
onClick={this.handleSave}
variant="contained"
color="primary"
disabled={owners.length === 0 || !selected}
>
{t('Save')}
</Button>
</DialogActions>
<AddOwner
open={adding}
onSuccess={this.handleAddingSuccess}
onError={this.handleAddingError}
onCancel={this.handleAddingCancel}
domain={domain}
folderID={folderID}
/>
{selected && <RemoveOwner
open={deleting}
onSuccess={this.handleDeleteSuccess}
onError={this.handleDeleteError}
onClose={this.handleDeleteClose}
ownerName={selected.username}
domainID={domain.ID}
folderID={folderID}
memberID={selected.memberID}
/>}
</Dialog>
);
}
Example #26
Source File: NavSection.js From Django-REST-Framework-React-BoilerPlate with MIT License | 4 votes |
function NavItem({ item, active }) {
const theme = useTheme();
const isActiveRoot = active(item.path);
const { title, path, icon, info, children } = item;
const [open, setOpen] = useState(isActiveRoot);
const handleOpen = () => {
setOpen((prev) => !prev);
};
const activeRootStyle = {
color: 'primary.main',
fontWeight: 'fontWeightMedium',
bgcolor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
};
const activeSubStyle = {
color: 'text.primary',
fontWeight: 'fontWeightMedium',
};
if (children) {
return (
<>
<ListItemStyle
onClick={handleOpen}
sx={{
...(isActiveRoot && activeRootStyle),
}}
>
<ListItemIconStyle>{icon && icon}</ListItemIconStyle>
<ListItemText disableTypography primary={title} />
{info && info}
<Iconify
icon={open ? 'eva:arrow-ios-downward-fill' : 'eva:arrow-ios-forward-fill'}
sx={{ width: 16, height: 16, ml: 1 }}
/>
</ListItemStyle>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{children.map((item) => {
const { title, path } = item;
const isActiveSub = active(path);
return (
<ListItemStyle
key={title}
component={RouterLink}
to={path}
sx={{
...(isActiveSub && activeSubStyle),
}}
>
<ListItemIconStyle>
<Box
component="span"
sx={{
width: 4,
height: 4,
display: 'flex',
borderRadius: '50%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'text.disabled',
transition: (theme) => theme.transitions.create('transform'),
...(isActiveSub && {
transform: 'scale(2)',
bgcolor: 'primary.main',
}),
}}
/>
</ListItemIconStyle>
<ListItemText disableTypography primary={title} />
</ListItemStyle>
);
})}
</List>
</Collapse>
</>
);
}
return (
<ListItemStyle
component={RouterLink}
to={path}
sx={{
...(isActiveRoot && activeRootStyle),
}}
>
<ListItemIconStyle>{icon && icon}</ListItemIconStyle>
<ListItemText disableTypography primary={title} />
{info && info}
</ListItemStyle>
);
}
Example #27
Source File: NavigationDrawer.js From react-saas-template with MIT License | 4 votes |
function NavigationDrawer(props) {
const { open, onClose, anchor, classes, menuItems, selectedItem, theme } =
props;
const isWidthUpSm = useMediaQuery(theme.breakpoints.up("sm"));
window.onresize = () => {
if (isWidthUpSm && open) {
onClose();
}
};
return (
<Drawer variant="temporary" open={open} onClose={onClose} anchor={anchor}>
<Toolbar className={classes.headSection}>
<ListItem
style={{
paddingTop: theme.spacing(0),
paddingBottom: theme.spacing(0),
height: "100%",
justifyContent: anchor === "left" ? "flex-start" : "flex-end",
}}
disableGutters
>
<ListItemIcon className={classes.closeIcon}>
<IconButton
onClick={onClose}
aria-label="Close Navigation"
size="large"
>
<CloseIcon color="primary" />
</IconButton>
</ListItemIcon>
</ListItem>
</Toolbar>
<List className={classes.blackList}>
{menuItems.map((element) => {
if (element.link) {
return (
<Link
key={element.name}
to={element.link}
className={classes.noDecoration}
onClick={onClose}
>
<ListItem
button
selected={selectedItem === element.name}
/**
* We disable ripple as it will make a weird animation
* with primary and secondary color
*/
disableRipple
disableTouchRipple
>
<ListItemIcon>{element.icon}</ListItemIcon>
<ListItemText
primary={
<Typography variant="subtitle1" className="text-white">
{element.name}
</Typography>
}
/>
</ListItem>
</Link>
);
}
return (
<ListItem button key={element.name} onClick={element.onClick}>
<ListItemIcon>{element.icon}</ListItemIcon>
<ListItemText
primary={
<Typography variant="subtitle1" className="text-white">
{element.name}
</Typography>
}
/>
</ListItem>
);
})}
</List>
</Drawer>
);
}
Example #28
Source File: AddPostOptions.js From react-saas-template with MIT License | 4 votes |
function AddPostOptions(props) {
const {
Dropzone,
classes,
files,
deleteItem,
onDrop,
EmojiTextArea,
ImageCropper,
DateTimePicker,
cropperFile,
onCrop,
onCropperClose,
uploadAt,
onChangeUploadAt,
} = props;
const [option1, setOption1] = useState("None");
const [option2, setOption2] = useState("None");
const [option3, setOption3] = useState("None");
const [option4, setOption4] = useState("None");
const handleChange = useCallback(
(event) => {
const { name, value } = event.target;
switch (name) {
case "option1":
setOption1(value);
break;
case "option2":
setOption2(value);
break;
case "option3":
setOption3(value);
break;
case "option4":
setOption4(value);
break;
default:
throw new Error("No branch selected in switch-statement.");
}
},
[setOption1, setOption2, setOption3, setOption4]
);
const printFile = useCallback(() => {
if (files[0]) {
return (
<div className={classes.imgWrapper}>
<img
alt="uploaded item"
src={files[0].preview}
className={classes.img}
style={{ height: 148 }}
/>
<div className={classes.floatButtonWrapper}>
<IconButton onClick={deleteItem} size="large">
<CloseIcon />
</IconButton>
</div>
</div>
);
}
return (
<Dropzone accept="image/png, image/jpeg" onDrop={onDrop} fullHeight>
<span className={classes.uploadText}>
Click / Drop file <br /> here
</span>
</Dropzone>
);
}, [onDrop, files, classes, deleteItem]);
const inputs =
[
{
state: option1,
label: "Option 1",
stateName: "option1",
},
{
state: option2,
label: "Option 2",
stateName: "option2",
},
{
state: option3,
label: "Option 3",
stateName: "option3",
},
{
state: option4,
label: "Option 4",
stateName: "option4",
},
];
return (
<Fragment>
{ImageCropper && (
<ImageCropperDialog
open={cropperFile ? true : false}
ImageCropper={ImageCropper}
src={cropperFile ? cropperFile.preview : ""}
onCrop={onCrop}
onClose={onCropperClose}
aspectRatio={4 / 3}
/>
)}
<Typography paragraph variant="h6">
Upload Image
</Typography>
<Box mb={2}>
{EmojiTextArea && (
<EmojiTextArea
inputClassName={classes.emojiTextArea}
maxCharacters={2200}
rightContent={printFile()}
emojiSet="google"
/>
)}
</Box>
<Typography paragraph variant="h6">
Options
</Typography>
<List disablePadding>
<Bordered disableVerticalPadding disableBorderRadius>
<ListItem divider disableGutters className="listItemLeftPadding">
<ListItemText>
<Typography variant="body2">Upload at</Typography>
</ListItemText>
<ListItemSecondaryAction>
{DateTimePicker && (
<DateTimePicker
value={uploadAt}
format="yyyy/MM/dd hh:mm a"
onChange={onChangeUploadAt}
disablePast
/>
)}
</ListItemSecondaryAction>
</ListItem>
{inputs.map((element, index) => (
<ListItem
className="listItemLeftPadding"
disableGutters
divider={index !== inputs.length - 1}
key={index}
>
<ListItemText>
<Typography variant="body2">{element.label}</Typography>
</ListItemText>
<FormControl variant="outlined">
<ListItemSecondaryAction>
<Select
value={element.state}
onChange={handleChange}
input={
<OutlinedInput
name={element.stateName}
labelWidth={0}
className={classes.numberInput}
classes={{ input: classes.numberInputInput }}
/>
}
MenuProps={{ disableScrollLock: true }}
>
{inputOptions.map((innerElement) => (
<MenuItem value={innerElement} key={innerElement}>
{innerElement}
</MenuItem>
))}
</Select>
</ListItemSecondaryAction>
</FormControl>
</ListItem>
))}
</Bordered>
</List>
</Fragment>
);
}
Example #29
Source File: NavBar.js From react-saas-template with MIT License | 4 votes |
function NavBar(props) {
const { selectedTab, messages, classes, openAddBalanceDialog, theme } = props;
// Will be use to make website more accessible by screen readers
const links = useRef([]);
const [isMobileOpen, setIsMobileOpen] = useState(false);
const [isSideDrawerOpen, setIsSideDrawerOpen] = useState(false);
const isWidthUpSm = useMediaQuery(theme.breakpoints.up("sm"));
const openMobileDrawer = useCallback(() => {
setIsMobileOpen(true);
}, [setIsMobileOpen]);
const closeMobileDrawer = useCallback(() => {
setIsMobileOpen(false);
}, [setIsMobileOpen]);
const openDrawer = useCallback(() => {
setIsSideDrawerOpen(true);
}, [setIsSideDrawerOpen]);
const closeDrawer = useCallback(() => {
setIsSideDrawerOpen(false);
}, [setIsSideDrawerOpen]);
const menuItems = [
{
link: "/c/dashboard",
name: "Dashboard",
onClick: closeMobileDrawer,
icon: {
desktop: (
<DashboardIcon
className={
selectedTab === "Dashboard" ? classes.textPrimary : "text-white"
}
fontSize="small"
/>
),
mobile: <DashboardIcon className="text-white" />,
},
},
{
link: "/c/posts",
name: "Posts",
onClick: closeMobileDrawer,
icon: {
desktop: (
<ImageIcon
className={
selectedTab === "Posts" ? classes.textPrimary : "text-white"
}
fontSize="small"
/>
),
mobile: <ImageIcon className="text-white" />,
},
},
{
link: "/c/subscription",
name: "Subscription",
onClick: closeMobileDrawer,
icon: {
desktop: (
<AccountBalanceIcon
className={
selectedTab === "Subscription"
? classes.textPrimary
: "text-white"
}
fontSize="small"
/>
),
mobile: <AccountBalanceIcon className="text-white" />,
},
},
{
link: "/",
name: "Logout",
icon: {
desktop: (
<PowerSettingsNewIcon className="text-white" fontSize="small" />
),
mobile: <PowerSettingsNewIcon className="text-white" />,
},
},
];
return (
<Fragment>
<AppBar position="sticky" className={classes.appBar}>
<Toolbar className={classes.appBarToolbar}>
<Box display="flex" alignItems="center">
<Hidden smUp>
<Box mr={1}>
<IconButton
aria-label="Open Navigation"
onClick={openMobileDrawer}
color="primary"
size="large"
>
<MenuIcon />
</IconButton>
</Box>
</Hidden>
<Hidden smDown>
<Typography
variant="h4"
className={classes.brandText}
display="inline"
color="primary"
>
Wa
</Typography>
<Typography
variant="h4"
className={classes.brandText}
display="inline"
color="secondary"
>
Ver
</Typography>
</Hidden>
</Box>
<Box
display="flex"
justifyContent="flex-end"
alignItems="center"
width="100%"
>
{isWidthUpSm && (
<Box mr={3}>
<Balance
balance={2573}
openAddBalanceDialog={openAddBalanceDialog}
/>
</Box>
)}
<MessagePopperButton messages={messages} />
<ListItem
disableGutters
className={classNames(classes.iconListItem, classes.smBordered)}
>
<Avatar
alt="profile picture"
src={`${process.env.PUBLIC_URL}/images/logged_in/profilePicture.jpg`}
className={classNames(classes.accountAvatar)}
/>
{isWidthUpSm && (
<ListItemText
className={classes.username}
primary={
<Typography color="textPrimary">Username</Typography>
}
/>
)}
</ListItem>
</Box>
<IconButton
onClick={openDrawer}
color="primary"
aria-label="Open Sidedrawer"
size="large"
>
<SupervisorAccountIcon />
</IconButton>
<SideDrawer open={isSideDrawerOpen} onClose={closeDrawer} />
</Toolbar>
</AppBar>
<Hidden smDown>
<Drawer // both drawers can be combined into one for performance
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
open={false}
>
<List>
{menuItems.map((element, index) => (
<Link
to={element.link}
className={classes.menuLink}
onClick={element.onClick}
key={index}
ref={(node) => {
links.current[index] = node;
}}
>
<Tooltip
title={element.name}
placement="right"
key={element.name}
>
<ListItem
selected={selectedTab === element.name}
button
divider={index !== menuItems.length - 1}
className={classes.permanentDrawerListItem}
onClick={() => {
links.current[index].click();
}}
aria-label={
element.name === "Logout"
? "Logout"
: `Go to ${element.name}`
}
>
<ListItemIcon className={classes.justifyCenter}>
{element.icon.desktop}
</ListItemIcon>
</ListItem>
</Tooltip>
</Link>
))}
</List>
</Drawer>
</Hidden>
<NavigationDrawer
menuItems={menuItems.map((element) => ({
link: element.link,
name: element.name,
icon: element.icon.mobile,
onClick: element.onClick,
}))}
anchor="left"
open={isMobileOpen}
selectedItem={selectedTab}
onClose={closeMobileDrawer}
/>
</Fragment>
);
}