@mui/material#Collapse JavaScript Examples

The following examples show how to use @mui/material#Collapse. 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: Grouped.jsx    From Edlib with GNU General Public License v3.0 4 votes vote down vote up
Grouped = ({ allH5ps, contentTypes }) => {
    const { t } = useTranslation();
    const { classes } = useStyles();
    const open = useArray();

    const categoriesObject = allH5ps.reduce((categories, h5p) => {
        let groups = contentAuthorConstants.groups.filter(
            (group) => group.contentTypes.indexOf(h5p.value) !== -1
        );
        if (groups.length === 0) {
            groups.push({
                translationKey: 'others',
                order: null,
            });
        }

        groups.forEach((group) => {
            if (!categories[group.translationKey]) {
                categories[group.translationKey] = {
                    translationKey: group.translationKey,
                    order: group.order,
                    contentTypes: [],
                };
            }

            categories[group.translationKey].contentTypes.push(h5p);
        });

        return categories;
    }, {});

    const categories = Object.values(categoriesObject).sort((a, b) => {
        if (a.order === null) {
            return 1;
        }
        if (b.order === null) {
            return -1;
        }

        return a.order - b.order;
    });

    return (
        <List dense component="div" disablePadding className={classes.nested}>
            {categories.map((category, index) => (
                <React.Fragment key={index}>
                    <ListItem
                        button
                        onClick={() => open.toggle(category.translationKey)}
                    >
                        <ListItemText>
                            <strong>
                                {_.capitalize(
                                    t(
                                        `content_type_groups.${category.translationKey}`
                                    )
                                )}
                            </strong>
                        </ListItemText>
                        {open.has(category.translationKey) ? (
                            <ExpandLess />
                        ) : (
                            <ExpandMore />
                        )}
                    </ListItem>
                    <Collapse
                        in={open.has(category.translationKey)}
                        timeout="auto"
                        unmountOnExit
                    >
                        <List dense component="div" disablePadding>
                            {category.contentTypes.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>
                    </Collapse>
                </React.Fragment>
            ))}
        </List>
    );
}
Example #2
Source File: ResourceFilters.jsx    From Edlib with GNU General Public License v3.0 4 votes vote down vote up
ResourceFilters = ({
    filters,
    filterCount,
    contentTypeData,
    licenseData,
    savedFilterData,
    updateSavedFilter,
}) => {
    const { t } = useTranslation();
    const { classes } = useStyles();
    const { getUserConfig } = useEdlibComponentsContext();
    const { getConfigurationValue, setConfigurationValue } =
        useConfigurationContext();

    const open = useArray([resourceFilters.H5P_TYPE, resourceFilters.LICENSE]);

    const disabledFilters = getUserConfig('disabledFilters') || null;
    const [filterViewType, _setFilterViewType] = React.useState(() => {
        return getConfigurationValue('filterViewType', viewTypes.GROUPED);
    });
    const setFilterViewType = React.useCallback(
        (value) => {
            _setFilterViewType(value);
            setConfigurationValue('filterViewType', value);
        },
        [_setFilterViewType]
    );

    const filterUtils = FilterUtils(filters, {
        contentTypes: contentTypeData,
        licenses: licenseData,
    });
    const [showCreateFilter, setShowCreateFilter] = React.useState(false);
    const [showDelete, setShowDelete] = React.useState(false);

    const filterBlocks = [
        {
            type: resourceFilters.SAVED_FILTERS,
            title: _.capitalize(t('saved_filter', { count: 2 })),
            content: (
                <SavedFilters
                    savedFilterData={savedFilterData}
                    setShowDelete={setShowDelete}
                    filterUtils={filterUtils}
                />
            ),
        },
        {
            type: resourceFilters.H5P_TYPE,
            title: _.capitalize(t('content_type', { count: 2 })),
            count: filters.contentTypes.value.length,
            content: (
                <H5PTypes
                    contentTypeData={contentTypeData}
                    contentTypes={filters.contentTypes}
                    filterCount={filterCount ? filterCount.contentTypes : []}
                    filterViewType={filterViewType}
                />
            ),
        },
        {
            type: resourceFilters.LICENSE,
            title: _.capitalize(t('license', { count: 1 })),
            count: filters.licenses.value.length,
            content: (
                <Licenses
                    licenseData={licenseData}
                    licenses={filters.licenses}
                    filterCount={filterCount ? filterCount.licenses : []}
                />
            ),
        },
    ];

    return (
        <>
            <Box px={1} pb={1} display="flex" justifyContent="space-between">
                <Button
                    color="primary"
                    variant="contained"
                    onClick={() => setShowCreateFilter(true)}
                    size="small"
                    disabled={
                        filters.contentTypes.value.length === 0 &&
                        filters.licenses.value.length === 0
                    }
                >
                    {t('save_filter')}
                </Button>
                <Button
                    onClick={() =>
                        setFilterViewType(
                            filterViewType === viewTypes.GROUPED
                                ? viewTypes.ALPHABETICAL
                                : viewTypes.GROUPED
                        )
                    }
                    endIcon={<FilterListIcon />}
                    style={{
                        color: 'inherit',
                    }}
                    size="small"
                >
                    {filterViewType === viewTypes.GROUPED
                        ? t('grouped')
                        : t('A-Z')}
                </Button>
            </Box>
            <List component="nav" className={classes.root} dense>
                {filterBlocks
                    .filter(
                        (filterBlock) =>
                            disabledFilters === null ||
                            disabledFilters.indexOf(filterBlock.type) === -1
                    )
                    .map((filterBlock) => (
                        <React.Fragment key={filterBlock.type}>
                            <ListItem
                                button
                                onClick={() => open.toggle(filterBlock.type)}
                            >
                                <ListItemText
                                    classes={{
                                        primary: classes.mainCategories,
                                    }}
                                >
                                    <strong>{t(filterBlock.title)}</strong>
                                </ListItemText>
                                {open.has(filterBlock.type) ? (
                                    <ExpandLess />
                                ) : (
                                    <ExpandMore />
                                )}
                            </ListItem>
                            <Collapse
                                in={open.has(filterBlock.type)}
                                timeout="auto"
                                unmountOnExit
                            >
                                {filterBlock.content}
                            </Collapse>
                        </React.Fragment>
                    ))}
            </List>
            <Button
                variant="outlined"
                color="primary"
                fullWidth
                type="gray"
                onClick={() => {
                    filters.reset();
                }}
            >
                {_.capitalize(t('reset'))}
            </Button>
            <CreateSavedFilter
                show={showCreateFilter}
                onClose={() => setShowCreateFilter(false)}
                savedFilterData={savedFilterData}
                filters={filters}
                onDone={(savedFilter) => {
                    setShowCreateFilter(false);
                    updateSavedFilter(savedFilter);
                }}
                filterUtils={filterUtils}
            />
            <DeleteSavedFilter
                show={showDelete}
                onClose={() => setShowDelete(false)}
                savedFilterData={savedFilterData}
                filters={filters}
                onDeleted={(id) => {
                    setShowDelete(false);
                    updateSavedFilter(id, true);
                }}
                filterUtils={filterUtils}
                setShowDelete={setShowDelete}
            />
        </>
    );
}
Example #3
Source File: EmojiTextArea.js    From react-saas-template with MIT License 4 votes vote down vote up
function EmojiTextarea(props) {
  const {
    theme,
    classes,
    rightContent,
    placeholder,
    maxCharacters,
    emojiSet,
    inputClassName,
    onChange
  } = props;
  const [open, setOpen] = useState(false);
  const [value, setValue] = useState("");
  const [characters, setCharacters] = useState(0);

  const onSelectEmoji = useCallback(
    emoji => {
      let _characters;
      let _value = value + emoji.native;
      if (maxCharacters) {
        _characters = countWithEmojis(_value);
        if (_characters > maxCharacters) {
          return;
        }
      }
      if (onChange) {
        onChange(_value, _characters);
      }
      setValue(_value);
      setCharacters(_characters);
    },
    [value, setValue, setCharacters, maxCharacters, onChange]
  );

  const handleTextFieldChange = useCallback(
    event => {
      const { target } = event;
      const { value } = target;
      let characters;
      if (maxCharacters) {
        characters = countWithEmojis(value);
        if (characters > maxCharacters) {
          return;
        }
      }
      if (onChange) {
        onChange(value, characters);
      }
      setValue(value);
      setCharacters(characters);
    },
    [maxCharacters, onChange, setValue, setCharacters]
  );

  const toggleOpen = useCallback(() => {
    setOpen(!open);
  }, [open, setOpen]);

  return (
    <Fragment>
      <Grid spacing={0} container>
        <Grid
          item
          xs={rightContent ? 8 : 12}
          sm={rightContent ? 9 : 12}
          lg={rightContent ? 10 : 12}
          className={classes.relative}
        >
          <TextField
            fullWidth
            multiline
            variant="outlined"
            rows={6}
            onInput={handleTextFieldChange}
            value={value}
            placeholder={placeholder}
            InputProps={{
              classes: {
                notchedOutline: inputClassName ? inputClassName : null
              }
            }}
          />
          <div className={classes.floatButtonWrapper}>
            <IconButton onClick={toggleOpen} size="large">
              {open ? (
                <CloseIcon color="primary" />
              ) : (
                <EmojiEmotionsIcon color="primary" />
              )}
            </IconButton>
          </div>
        </Grid>
        {rightContent && (
          <Grid item xs={4} sm={3} lg={2}>
            {rightContent}
          </Grid>
        )}
      </Grid>
      {maxCharacters && (
        <FormHelperText error={characters >= maxCharacters}>
          {`${characters}/${maxCharacters} characters`}
        </FormHelperText>
      )}
      <Collapse in={open}>
        <Box mt={1}>
          <Picker
            set={emojiSet}
            color={theme.palette.primary.main}
            style={{ width: "100%" }}
            onSelect={onSelectEmoji}
            emojisToShowFilter={emojisToShowFilter}
          />
        </Box>
      </Collapse>
    </Fragment>
  );
}
Example #4
Source File: NavSection.js    From Django-REST-Framework-React-BoilerPlate with MIT License 4 votes vote down vote up
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 #5
Source File: License.js    From admin-web with GNU Affero General Public License v3.0 4 votes vote down vote up
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 #6
Source File: expand.js    From react-table-library with MIT License 4 votes vote down vote up
Component = () => {
  const data = { nodes };

  const materialTheme = getTheme(DEFAULT_OPTIONS);
  const customTheme = {
    Table: `
      .animate {
        grid-column: 1 / -1;

        display: flex;
      }

      .animate > div {
        flex: 1;
        display: flex;
      }
    `,
  };
  const theme = useTheme([materialTheme, customTheme]);

  const [ids, setIds] = React.useState([]);

  const handleExpand = (item) => {
    if (ids.includes(item.id)) {
      setIds(ids.filter((id) => id !== item.id));
    } else {
      setIds(ids.concat(item.id));
    }
  };

  const COLUMNS = [
    { label: 'Task', renderCell: (item) => item.name },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
    },
    { label: 'Type', renderCell: (item) => item.type },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
    },
    { label: 'Tasks', renderCell: (item) => item.nodes?.length },
  ];

  const ROW_PROPS = {
    onClick: handleExpand,
  };

  const ROW_OPTIONS = {
    renderAfterRow: (item) => (
      <Collapse className="animate" in={ids.includes(item.id)}>
        <tr style={{ flex: '1', display: 'flex' }}>
          <td style={{ flex: '1' }}>
            <ul
              style={{
                margin: '0',
                padding: '0',
              }}
            >
              <li>
                <strong>Name:</strong> {item.name.toUpperCase()}
              </li>
              <li>
                <strong>Deadline:</strong> {item.deadline.toLocaleDateString('en-US')}
              </li>
              <li>
                <strong>Type:</strong> {item.type}
              </li>
              <li>
                <strong>Complete:</strong> {item.isComplete.toString()}
              </li>
            </ul>
          </td>
        </tr>
      </Collapse>
    ),
  };

  return (
    <>
      <CompactTable
        columns={COLUMNS}
        rowProps={ROW_PROPS}
        rowOptions={ROW_OPTIONS}
        data={data}
        theme={theme}
      />

      <br />
      <DocumentationSee anchor={'Features/' + key} />
    </>
  );
}