@mui/material#Tabs JavaScript Examples

The following examples show how to use @mui/material#Tabs. 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: index.js    From zoomkoding-gatsby-blog with BSD Zero Clause License 6 votes vote down vote up
function PostTabs({ tabIndex, onChange, tabs, posts, showMoreButton }) {
  const tabPosts = useMemo(() => {
    if (tabs[tabIndex] === 'All') return posts;
    return posts.filter((post) => post.categories.includes(tabs[tabIndex]));
  }, [posts, tabs, tabIndex]);

  return (
    <div className="post-tabs-wrapper">
      <div className="post-tabs">
        <Tabs
          className="mui-tabs"
          value={tabIndex}
          onChange={onChange}
          variant="scrollable"
          scrollButtons="desktop"
        >
          {tabs.map((title, index) => (
            <Tab label={title} key={index} />
          ))}
        </Tabs>
      </div>
      <PostCardColumn
        posts={showMoreButton ? tabPosts.slice(0, 4) : tabPosts}
        showMoreButton={showMoreButton && tabPosts.length > 4}
        moreUrl={`posts/${tabIndex === 0 ? '' : tabs[tabIndex]}`}
      />
    </div>
  );
}
Example #2
Source File: NavigationLinks.js    From admin-web with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    const { classes, t, expandedDomain, location, domains, capabilities } = this.props;
    const { filter, tab } = this.state;
    const isSysAdmin = capabilities.includes(SYSTEM_ADMIN_READ);
    const pathname = location.pathname;
    return(
      <React.Fragment>
        <div className={classes.drawerHeader}>
          <img
            src={logo}
            width="140"
            height="32"
            alt="grommunio"
            onClick={this.handleNavigation('')}
            className={classes.logo}
          />
        </div>
        {isSysAdmin && <Tabs
          onChange={(event, tab) => this.setState({ tab: tab })}
          value={tab}
          className={classes.tabs}
          indicatorColor="primary"
          textColor="primary"
        >
          <Tab className={classes.tab} value={0} label={t('Admin')} />
          <Tab className={classes.tab} value={1} label={t('Domains')} />
        </Tabs>}
        {(tab === 1 || !isSysAdmin) &&
            <Grid container component="form" autoComplete="off">
              <TextField
                variant="outlined"
                label={t('Search')}
                value={filter}
                onChange={this.handleTextInput}
                InputLabelProps={{
                  classes: {
                    root: classes.input,
                  },
                  shrink: true,
                }}
                InputProps={{
                  classes: { root: classes.input },
                  startAdornment: (
                    <InputAdornment position="start">
                      <Search color="secondary" />
                    </InputAdornment>
                  ),
                }}
                color="primary"
                className={classes.textfield}
              />
            </Grid>}
        <List className={classes.list}>
          {(tab === 1 || !isSysAdmin) &&
            domains.map(({ domainname: name, ID, domainStatus }) => {
              return name.includes(filter) ?
                <React.Fragment key={name}>
                  <ListItem
                    onClick={this.handleDrawer(ID)}
                    button
                    className={classes.li}
                    selected={expandedDomain === ID && pathname === '/' + ID}
                  >
                    <Grid container alignItems="center">
                      <Domains className={classes.icon} />
                      <ListItemText primary={name + (domainStatus === 3 ? ` [${t('Deactivated')}]` : '')} />
                    </Grid>
                  </ListItem>
                  <Collapse in={expandedDomain === ID} unmountOnExit>
                    <List component="div" disablePadding>
                      <ListItem
                        className={classes.li}
                        button
                        onClick={this.handleNavigation(ID + '/users')}
                        selected={expandedDomain === ID &&
                          pathname.startsWith('/' + ID + '/users')}
                      >
                        <Grid container alignItems="center">
                          <People className={classes.nestedIcon}/>
                          <ListItemText primary={t('Users')}/>
                        </Grid>
                      </ListItem>
                      <ListItem
                        className={classes.li}
                        button
                        onClick={this.handleNavigation(ID + '/folders')}
                        selected={expandedDomain === ID &&
                          pathname.startsWith('/' + ID + '/folders')}
                      >
                        <Grid container alignItems="center">
                          <Folder className={classes.nestedIcon}/>
                          <ListItemText primary={t('Public folders')}/>
                        </Grid>
                      </ListItem>
                      <ListItem
                        className={classes.li}
                        button
                        onClick={this.handleNavigation(ID + '/classes')}
                        selected={pathname.startsWith('/' + ID + '/classes')}
                      >
                        <Grid container alignItems="center">
                          <Classes className={classes.nestedIcon}/>
                          <ListItemText primary={t('Groups')}/>
                        </Grid>
                      </ListItem>
                      <ListItem
                        className={classes.li}
                        button
                        onClick={this.handleNavigation(ID + '/mailLists')}
                        selected={pathname.startsWith('/' + ID + '/mailLists')}
                      >
                        <Grid container alignItems="center">
                          <MLists className={classes.nestedIcon}/>
                          <ListItemText primary={t('Mail lists')}/>
                        </Grid>
                      </ListItem>
                    </List>
                  </Collapse>
                </React.Fragment> : null;
            })}
          {(tab === 0 && !isSysAdmin) && <ListItem
            button
            onClick={this.handleNavigation('taskq')}
            className={classes.li}
            selected={pathname.startsWith('/taskq')}
          >
            <Grid container alignItems="center">
              <TaskAlt className={classes.icon}/>
              <ListItemText primary={t('Task queue')} />
            </Grid>
          </ListItem>}
          {tab === 0 && isSysAdmin && <React.Fragment>
            <Typography variant="inherit" className={classes.subheader}>{t('Overview')}</Typography>
            <ListItem
              button
              onClick={this.handleNavigation('')}
              className={classes.li}
              selected={pathname === '/'}
            >
              <Grid container alignItems="center">
                <Dashboard className={classes.icon} />
                <ListItemText primary="Dashboard"/>
              </Grid>
            </ListItem>
            <Typography variant="inherit" className={classes.subheader}>{t('Management')}</Typography>
            <ListItem
              className={classes.li}
              button
              onClick={this.handleNavigation('orgs')}
              selected={pathname.startsWith('/orgs')}
            >
              <Grid container alignItems="center">
                <Orgs className={classes.icon}/>
                <ListItemText primary={t('Organizations')}/>
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('domains')}
              className={classes.li}
              selected={pathname.startsWith('/domains')}
            >
              <Grid container alignItems="center">
                <Domains className={classes.icon}/>
                <ListItemText primary={t('Domains')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('users')}
              className={classes.li}
              selected={pathname.startsWith('/users')}
            >
              <Grid container alignItems="center">
                <People className={classes.icon}/>
                <ListItemText primary={t('Users')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('roles')}
              className={classes.li}
              selected={pathname === '/roles'}
            >
              <Grid container alignItems="center">
                <Roles className={classes.icon}/>
                <ListItemText primary={t('Roles')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('defaults')}
              className={classes.li}
              selected={pathname === '/defaults'}
            >
              <Grid container alignItems="center">
                <BackupTable className={classes.icon}/>
                <ListItemText primary={t('Defaults')} />
              </Grid>
            </ListItem>
            <Typography variant="inherit" className={classes.subheader}>{t('Configuration')}</Typography>
            <ListItem
              button
              onClick={this.handleNavigation('directory')}
              className={classes.li}
              selected={pathname === '/directory'}
            >
              <Grid container alignItems="center">
                <Ldap className={classes.icon}/>
                <ListItemText primary={t('Directory')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('dbconf')}
              className={classes.li}
              selected={pathname.startsWith('/dbconf')}
            >
              <Grid container alignItems="center">
                <Storage className={classes.icon}/>
                <ListItemText primary={t('Configuration DB')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('servers')}
              className={classes.li}
              selected={pathname.startsWith('/servers')}
            >
              <Grid container alignItems="center">
                <Dns className={classes.icon}/>
                <ListItemText primary={t('Servers')} />
              </Grid>
            </ListItem>
            <Typography variant="inherit" className={classes.subheader}>{t('Monitoring')}</Typography>
            <ListItem
              button
              onClick={this.handleNavigation('logs')}
              className={classes.li}
              selected={pathname.startsWith('/logs')}
            >
              <Grid container alignItems="center">
                <Logs className={classes.icon}/>
                <ListItemText primary={t('Logs')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('mailq')}
              className={classes.li}
              selected={pathname.startsWith('/mailq')}
            >
              <Grid container alignItems="center">
                <QueryBuilder className={classes.icon}/>
                <ListItemText primary={t('Mail queue')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('taskq')}
              className={classes.li}
              selected={pathname.startsWith('/taskq')}
            >
              <Grid container alignItems="center">
                <TaskAlt className={classes.icon}/>
                <ListItemText primary={t('Task queue')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('sync')}
              className={classes.li}
              selected={pathname.startsWith('/sync')}
            >
              <Grid container alignItems="center">
                <Sync className={classes.icon}/>
                <ListItemText primary={t('Mobile devices')} />
              </Grid>
            </ListItem>
            <ListItem
              button
              onClick={this.handleNavigation('status')}
              className={classes.li}
              selected={pathname.startsWith('/status')}
            >
              <Grid container alignItems="center">
                <TableChart className={classes.icon}/>
                <ListItemText primary={t('Live status')} />
              </Grid>
            </ListItem>
          </React.Fragment>
          }
        </List>
        <div className={classes.background} />
      </React.Fragment>
    );
  }
Example #3
Source File: Classes.js    From admin-web with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    const { classes, t, _classes, domain, tableState, handleMatch, handleRequestSort,
      handleAdd, handleAddingSuccess, handleAddingClose, handleAddingError,
      handleDelete, handleDeleteClose, handleDeleteError,
      handleDeleteSuccess, handleEdit } = this.props;
    const { order, orderBy, match, snackbar, adding, deleting } = tableState;
    const writable = this.context.includes(DOMAIN_ADMIN_WRITE);
    const { tab, root } = this.state;

    return (
      <TableViewContainer
        handleScroll={this.handleScroll}
        headline={t("Groups")}
        subtitle={t("groups_sub")}
        href="https://docs.grommunio.com/admin/administration.html#groups"
        snackbar={snackbar || this.state.snackbar}
        onSnackbarClose={this.handleSnackbarClose}
        baseRef={tc => (this.treeContainer = tc)}
      >
        <Grid container alignItems="flex-end" className={classes.buttonGrid}>
          <Button
            variant="contained"
            color="primary"
            onClick={handleAdd}
            className={classes.newButton}
            disabled={!writable}
          >
            {t('New group')}
          </Button>
          <div className={classes.actions}>
            <TextField
              value={match}
              onChange={handleMatch}
              placeholder={t("Search")}
              variant="outlined"
              className={classes.textfield}
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <Search color="secondary" />
                  </InputAdornment>
                ),
              }}
              color="primary"
            />
          </div>
        </Grid>
        <Tabs
          indicatorColor="primary"
          textColor="primary"
          className={classes.tabs}
          onChange={this.handleTab}
          value={tab}
        >
          <Tab value={0} label={t("List")} />
          <Tab value={1} label={t("Tree")} />
        </Tabs>
        {!tab && <Typography className={classes.count} color="textPrimary">
          {t("showingGroups", { count: _classes.Classes.length })}
        </Typography>}
        {!tab ? <Paper className={classes.tablePaper} elevation={1}>
          <Table size="small">
            <TableHead>
              <TableRow>
                {this.columns.map(column =>
                  <TableCell key={column.value}>
                    <TableSortLabel
                      active={orderBy === column.value}
                      align="left" 
                      direction={orderBy === column.value ? order : 'asc'}
                      onClick={handleRequestSort(column.value)}
                    >
                      {t(column.label)}
                    </TableSortLabel>
                  </TableCell>
                )}
                <TableCell></TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {_classes.Classes.map((obj, idx) =>
                <TableRow key={idx} hover onClick={handleEdit('/' + domain.ID + '/classes/' + obj.ID)}>
                  <TableCell>{obj.classname}</TableCell>
                  <TableCell>{obj.listname}</TableCell>
                  <TableCell align="right">
                    {writable && <IconButton onClick={handleDelete(obj)} size="large">
                      <Delete color="error"/>
                    </IconButton>}
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
          {(_classes.Classes.length < _classes.count) && <Grid container justifyContent="center">
            <CircularProgress color="primary" className={classes.circularProgress}/>
          </Grid>}
        </Paper> :
          <>
            <FormControl className={classes.select}>
              <InputLabel variant="standard">{t("Root group")}</InputLabel>
              <Select
                fullWidth
                value={root > -1 ? root : ''}
                onChange={this.handleRootSelect}
                input={<Input />}
                placeholder={t('Select root group')}
              >
                {_classes.Trees.map((tree, idx) => (
                  <MenuItem key={idx} value={idx}>
                    {tree.name}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
            <div className={classes.treeContainer}>
              {root !== -1 &&
                  <Paper style={{ flex: 1 }}>
                    <Tree
                      data={_classes.Trees[root]}
                      orientation="vertical"
                      renderCustomNodeElement={this.renderNode}
                      depthFactor={50}
                      pathFunc="step"
                      translate={this.getOffset()}
                      scaleExtent={{
                        min: 0.1,
                        max: 2,
                      }}
                      separation={{
                        siblings: 1,
                        nonSiblings: 2,
                      }}
                      onNodeClick={this.handleNodeClicked}
                      collapsible={false}
                    />
                  </Paper>}
            </div>
          </>
        }
        <AddClass
          open={adding}
          onSuccess={handleAddingSuccess}
          onError={handleAddingError}
          domain={domain}
          onClose={handleAddingClose}
        />
        <DomainDataDelete
          open={!!deleting}
          delete={this.props.delete}
          onSuccess={handleDeleteSuccess}
          onError={handleDeleteError}
          onClose={handleDeleteClose}
          item={deleting.name}
          id={deleting.ID}
          domainID={domain.ID}
        />
      </TableViewContainer>
    );
  }
Example #4
Source File: DBConf.js    From admin-web with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    const { classes, t, services, commands } = this.props;
    const { adding, configuring, snackbar, match, tab, deleting } = this.state;
    const writable = this.context.includes(SYSTEM_ADMIN_WRITE);
    return (
      <TableViewContainer
        headline={t("Configuration DB")}
        href="https://docs.grommunio.com/admin/administration.html#db-configuration"
        subtitle={t('dbconf_sub')}
        snackbar={snackbar}
        onSnackbarClose={() => this.setState({ snackbar: '' })}
      >
        <Grid container alignItems="flex-end" className={classes.buttonGrid}>
          <Button
            variant="contained"
            color="primary"
            onClick={() => this.setState({ adding: true })}
            disabled={!writable}
          >
            {t("Create file")}
          </Button>
          <Button
            variant="contained"
            color="primary"
            onClick={() => this.setState({ configuring: true })}
            className={classes.button}
            disabled={!writable}
          >
            {t("Configure grommunio-dbconf")}
          </Button>
          <div className={classes.actions}>
            <TextField
              value={match}
              onChange={this.handleMatch}
              placeholder={t("search services")}
              variant="outlined"
              className={classes.textfield}
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <Search color="secondary" />
                  </InputAdornment>
                ),
              }}
              color="primary"
            />
          </div>
        </Grid>
        <Grid container alignItems="flex-end" className={classes.buttonGrid}>
          <Tabs
            textColor="primary" 
            indicatorColor="primary"
            value={tab}
            onChange={this.handleTab}
          >
            <Tab value={0} label="Services" />
            <Tab value={1} label="Commands" />
          </Tabs>
        </Grid>
        {tab === 0 ? <Paper elevation={1}>
          <Table size="small">
            <TableHead>
              <TableRow>
                <TableCell>
                  {t('Name')}
                </TableCell>
                <TableCell padding="checkbox"></TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {services.filter(s => s.includes(match)).map((service, idx) =>
                <TableRow onClick={this.handleNavigation('dbconf/' + service)} key={idx} hover>
                  <TableCell>{service}</TableCell>
                  <TableCell align="right">
                    {writable && <IconButton onClick={this.handleDelete(service)} size="large">
                      <Delete color="error" />
                    </IconButton>}
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </Paper> : <Paper className={classes.paper}>
          <Typography variant="h6">Key</Typography>
          {commands.key.length > 0 ? commands.key.map((key, idx) =>
            <pre className={classes.pre} key={idx}>
              <code key={idx}>{key}</code>
            </pre>
          ) : <Typography><i>none</i></Typography>}
          <Typography className={classes.title} variant="h6">File</Typography>
          {commands.file.length > 0 ? commands.file.map((key, idx) =>
            <pre className={classes.pre} key={idx}>
              <code>{key}</code>
            </pre>
          ) : <Typography><i>none</i></Typography>}
          <Typography className={classes.title} variant="h6">Service</Typography>
          {commands.service.length > 0 ? commands.service.map((key, idx) =>
            <pre className={classes.pre} key={idx}>
              <code>{key}</code>
            </pre>
          ) : <Typography><i>none</i></Typography>}
        </Paper>}
        <GeneralDelete
          open={!!deleting}
          delete={this.props.delete}
          onSuccess={this.handleDeleteSuccess}
          onError={this.handleDeleteError}
          onClose={this.handleDeleteClose}
          item={deleting}
          id={deleting}
        />
        <UploadServiceFile
          open={adding}
          onClose={this.handleAddingClose}
          onError={this.handleAddingError}
          onSuccess={this.handleAddingSuccess}
        />
        <CreateDbconfFile
          open={configuring}
          onClose={this.handleAddingClose}
          onError={this.handleAddingError}
          onSuccess={this.handleAddingSuccess}
        />
      </TableViewContainer>
    );
  }
Example #5
Source File: DomainDetails.js    From admin-web with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    const { classes, t, orgs, capabilities, servers } = this.props;
    const writable = this.context.includes(SYSTEM_ADMIN_WRITE);
    const { domainname, domainStatus, orgID, maxUser, title, address, adminName,
      tel, syncPolicy, checkPw, newPw, changingPw, snackbar, tab, defaultPolicy,
      chat, homeserver, autocompleteInput } = this.state;
    
    return (
      <ViewWrapper
        topbarTitle={t('Domains')}
        snackbar={snackbar}
        onSnackbarClose={() => this.setState({ snackbar: '' })}
      >
        <Paper className={classes.paper} elevation={1}>
          <Grid container>
            <Typography
              color="primary"
              variant="h5"
            >
              {t('editHeadline', { item: 'Domain' })}
            </Typography>
          </Grid>
          <Tabs className={classes.tabs} indicatorColor="primary" onChange={this.handleTab} value={tab}>
            <Tab value={0} label={t('Domain')} />
            <Tab value={1} label={t('Sync policies')} />
          </Tabs>
          {tab === 0 && <FormControl className={classes.form}>
            <Grid container className={classes.input}>
              <TextField
                label={t("Domain")} 
                style={{ flex: 1, marginRight: 8 }} 
                value={domainname || ''}
                autoFocus
                disabled
              />
            </Grid>
            <TextField
              select
              className={classes.input}
              label={t("Status")}
              fullWidth
              value={domainStatus || 0}
              onChange={this.handleInput('domainStatus')}
            >
              {this.statuses.map((status, key) => (
                <MenuItem key={key} value={status.ID}>
                  {status.name}
                </MenuItem>
              ))}
            </TextField>
            {capabilities.includes(SYSTEM_ADMIN_READ) && <MagnitudeAutocomplete
              value={orgID}
              filterAttribute={'name'}
              onChange={this.handleAutocomplete('orgID')}
              className={classes.input} 
              options={orgs}
              inputValue={autocompleteInput}
              onInputChange={this.handleInput('autocompleteInput')}
              label={t('Organization')}
            />}
            <TextField 
              className={classes.input} 
              label={t("Maximum users")} 
              fullWidth 
              value={maxUser || ''}
              onChange={this.handleInput('maxUser')}
            />
            <TextField 
              className={classes.input} 
              label={t("Title")} 
              fullWidth 
              value={title || ''}
              onChange={this.handleInput('title')}
            />
            <TextField 
              className={classes.input} 
              label={t("Address")} 
              fullWidth 
              value={address || ''}
              onChange={this.handleInput('address')}
            />
            <TextField 
              className={classes.input} 
              label={t("Administrator")} 
              fullWidth 
              value={adminName || ''}
              onChange={this.handleInput('adminName')}
            />
            <TextField 
              className={classes.input} 
              label={t("Telephone")} 
              fullWidth 
              value={tel || ''}
              onChange={this.handleInput('tel')}
            />
            <MagnitudeAutocomplete
              value={homeserver}
              filterAttribute={'hostname'}
              onChange={this.handleServer}
              className={classes.input} 
              options={servers}
              label={t('Homeserver')}
            />
            <FormControlLabel
              control={
                <Checkbox
                  checked={chat || false}
                  onChange={this.handleCheckbox('chat')}
                  color="primary"
                />
              }
              className={classes.input} 
              label={t('grommunio-chat Team')}
            />
          </FormControl>}
          {tab === 1 && <SlimSyncPolicies
            syncPolicy={syncPolicy}
            defaultPolicy={defaultPolicy}
            handleChange={this.handleSyncChange}
            handleCheckbox={this.handleSyncCheckboxChange}
            handleSlider={this.handleSlider}
          />}
          <Button
            color="secondary"
            onClick={this.handleBack}
            style={{ marginRight: 8 }}
          >
            {t('Back')}
          </Button>
          <Button
            variant="contained"
            color="primary"
            onClick={this.handleEdit}
            disabled={!writable}
          >
            {t('Save')}
          </Button>
        </Paper>
        <Dialog open={!!changingPw} onClose={() => this.setState({ changingPw: false })}>
          <DialogTitle>{t('Change password')}</DialogTitle>
          <DialogContent>
            <TextField 
              className={classes.input} 
              label={t("New password")} 
              fullWidth
              type="password"
              value={newPw}
              onChange={event => this.setState({ newPw: event.target.value })}
              autoFocus
              onKeyPress={this.handleKeyPress}
            />
            <TextField 
              className={classes.input} 
              label={t("Repeat new password")} 
              fullWidth
              type="password"
              value={checkPw}
              onChange={event => this.setState({ checkPw: event.target.value })}
              onKeyPress={this.handleKeyPress}
            />
          </DialogContent>
          <DialogActions>
            <Button
              color="secondary"
              onClick={() => this.setState({ changingPw: false })}>
              {t('Cancel')}
            </Button>
            <Button
              variant="contained"
              color="primary"
              onClick={this.handlePasswordChange}
              disabled={checkPw !== newPw}
            >
              {t('Save')}
            </Button>
          </DialogActions>
        </Dialog>
      </ViewWrapper>
    );
  }
Example #6
Source File: UserDetails.js    From admin-web with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    const { classes, t, domain, history } = this.props;
    const writable = this.context.includes(DOMAIN_ADMIN_WRITE);
    const sysAdminReadPermissions = this.context.includes(SYSTEM_ADMIN_READ);
    const { user, changingPw, snackbar, tab, sizeUnits, detachLoading, defaultPolicy, langs,
      detaching, adding, editing, dump, rawData, syncPolicy, domainDetails, forwardError } = this.state;
    const { ID, username, properties, roles, aliases, fetchmail, ldapID, forward } = user; //eslint-disable-line
    return (
      <ViewWrapper
        topbarTitle={t('Users')}
        snackbar={snackbar}
        onSnackbarClose={() => this.setState({ snackbar: '' })}
      >
        <Paper className={classes.paper} elevation={1}>
          <Grid container className={classes.header}>
            <Typography
              color="primary"
              variant="h5"
            >
              {t('editHeadline', { item: 'User' })} {properties.displayname ? ` - ${properties.displayname}` : ''}
            </Typography>
          </Grid>
          {ldapID && <Grid container className={classes.syncButtons}>
            <Tooltip title="Detach user from LDAP object" placement="top">
              <Button
                variant="contained"
                color="secondary"
                style={{ marginRight: 8 }}
                onClick={this.handleDetachDialog(true)}
                size="small"
              >
                <Detach fontSize="small" className={classes.leftIcon} /> Detach
              </Button>
            </Tooltip>
            <Tooltip title="Synchronize data from LDAP" placement="top">
              <Button
                size="small"
                onClick={this.handleSync}
                variant="contained"
                color="primary"
                style={{ marginRight: 8 }}
              >
                <Sync fontSize="small" className={classes.leftIcon}/> Sync
              </Button>
            </Tooltip>
            <Tooltip title="Show raw data" placement="top">
              <Button
                size="small"
                onClick={this.handleDump}
                variant="contained"
                color="primary"
              >
                <Dump fontSize="small" className={classes.leftIcon}/> Dump
              </Button>
            </Tooltip>
          </Grid>}
          <div className={classes.tabsContainer}>
            <Tabs
              indicatorColor="primary"
              value={tab}
              onChange={this.handleTabChange}
              variant="scrollable"
              scrollButtons="auto"
              classes={{
                scroller: classes.scroller,
              }}
            >
              <Tab label={t("Account")} />
              <Tab label={t("User")} disabled={!ID}/>
              <Tab label={t("Contact")} disabled={!ID}/>
              <Tab label={t("Roles")} disabled={!ID || !sysAdminReadPermissions}/>
              <Tab label={t("SMTP")} disabled={!ID}/>
              <Tab label={t("Permissions")} disabled={!ID}/>
              <Tab label={t("FetchMail")} disabled={!ID}/>
              <Tab label={t("Mobile devices")} disabled={!ID}/>
              <Tab label={t("Sync policy")} disabled={!ID}/>
            </Tabs>
          </div>
          {tab === 0 && <Account
            domain={domainDetails.ID ? domainDetails : domain}
            user={user}
            sizeUnits={sizeUnits}
            langs={langs}
            handleInput={this.handleInput}
            handleStatusInput={this.handleStatusInput}
            handlePropertyChange={this.handlePropertyChange}
            handleIntPropertyChange={this.handleIntPropertyChange}
            handleCheckbox={this.handleCheckbox}
            handleUnitChange={this.handleUnitChange}
            handlePasswordChange={this.handlePasswordDialogToggle(true)}
            rawData={rawData}
            handleQuotaDelete={this.handleQuotaDelete}
            handleChatUser={this.handleChatUser}
            handleServer={this.handleServer}
          />}
          {tab === 1 && <User
            user={user}
            handlePropertyChange={this.handlePropertyChange}
          />}
          {tab === 2 && <Contact
            user={user}
            handlePropertyChange={this.handlePropertyChange}
          />}
          {tab === 3 && sysAdminReadPermissions && <Roles
            roles={roles}
            handleAutocomplete={this.handleAutocomplete}
          />}
          {tab === 4 && <Smtp
            user={user}
            aliases={aliases}
            forward={forward || {}}
            forwardError={forwardError}
            handleForwardInput={this.handleForwardInput}
            handleAliasEdit={this.handleAliasEdit}
            handleAddAlias={this.handleAddAlias}
            handleRemoveAlias={this.handleRemoveAlias}
          />}
          {tab === 5 && <Delegates
            domainID={domain.ID}
            userID={user.ID}
            disabled={!writable}
          />}
          {tab === 6 && <FetchMail
            fetchmail={fetchmail}
            handleAdd={this.handleFetchmailDialog(true)}
            handleEdit={this.handleFetchmailEditDialog}
            handleDelete={this.handleFetchmailDelete}
          />}
          {tab === 7 && <SyncTab
            domainID={domain.ID}
            userID={user.ID}
          />}
          {tab === 8 && <SlimSyncPolicies
            syncPolicy={syncPolicy}
            defaultPolicy={defaultPolicy}
            handleChange={this.handleSyncChange}
            handleCheckbox={this.handleSyncCheckboxChange}
            handleSlider={this.handleSlider}
          />}
          {tab !== 5 && <Grid container className={classes.buttonGrid}>
            <Button
              onClick={history.goBack}
              style={{ marginRight: 8 }}
              color="secondary"
            >
              {t('Back')}
            </Button>
            <Button
              variant="contained"
              color="primary"
              onClick={tab === 3 ? this.handleSaveRoles : this.handleEdit}
              disabled={!writable || forwardError}
            >
              {t('Save')}
            </Button>
          </Grid>}
        </Paper>
        <DetachDialog
          open={detaching}
          loading={detachLoading}
          onClose={this.handleDetachDialog(false)}
          onDetach={this.handleDetach}
        />
        <AddFetchmail
          open={adding}
          add={this.addFetchmail}
          onClose={this.handleFetchmailDialog(false)}
          username={username + '@' + domain.domainname}
        />
        <EditFetchmail
          open={editing !== null}
          entry={editing !== null ? fetchmail[editing] : editing}
          edit={this.editFetchmail}
          onClose={this.handleFetchmailEditDialog(null)}
          username={username + '@' + domain.domainname}
        />
        <ChangeUserPassword
          onClose={this.handlePasswordDialogToggle(false)}
          onError={this.handleError}
          onSuccess={this.handleSuccess}
          changingPw={changingPw}
          domain={domain}
          user={user}
        />
        <DumpDialog onClose={this.handleCloseDump} open={!!dump} dump={dump} />
      </ViewWrapper>
    );
  }