@mui/material#Badge TypeScript Examples

The following examples show how to use @mui/material#Badge. 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: SetupScreen.tsx    From rewind with MIT License 6 votes vote down vote up
function DirectorySelection({ value, onChange, placeHolder, badgeOnEmpty }: DirectorySelectionProps) {
  const handleSelectFolderClick = useCallback(() => {
    window.api.selectDirectory(value ?? "").then((path) => {
      if (path !== null) {
        onChange(path);
      }
    });
  }, [onChange, value]);

  const onInputChange = useCallback(
    (event) => {
      onChange(event.target.value);
    },
    [onChange],
  );

  const invisibleBadge = !badgeOnEmpty || !!value;
  return (
    <Paper sx={{ px: 2, py: 1, display: "flex", alignItems: "center", width: 400 }} elevation={2}>
      {/*<span className={"text-gray-400 select-none w-96"}>{value ?? placeHolder}</span>*/}
      <InputBase sx={{ flex: 1 }} placeholder={placeHolder} value={value} onChange={onInputChange} disabled={true} />
      <IconButton onClick={handleSelectFolderClick}>
        <Badge invisible={invisibleBadge} color={"primary"} variant={"dot"}>
          <FolderIcon />
        </Badge>
      </IconButton>
    </Paper>
  );
}
Example #2
Source File: Profiler.tsx    From NekoMaid with MIT License 6 votes vote down vote up
ProfilerIcon: React.FC = () => {
  const plugin = usePlugin()
  const globalData = useGlobalData()
  const [status, setStatus] = useState(!!globalData.profilerStarted)
  useEffect(() => {
    const off = plugin.on('profiler:status', (res: boolean) => {
      setStatus(globalData.profilerStarted = res)
    })
    return () => { off() }
  })
  return <Badge color='secondary' variant='dot' invisible={!status}><Equalizer /></Badge>
}
Example #3
Source File: MarketItem.tsx    From Cromwell with MIT License 5 votes vote down vote up
export default function MarketItem(props: PropsType) {
    const data = props?.data;
    const [installing, setInstalling] = useState(false);
    const [installed, setInstalled] = useState(!!(props.data?.name
        && props?.listItemProps?.installedModules?.find(inst => inst.name === props.data?.name)));

    const installModule = async () => {
        if (!props.listItemProps?.install || !data) return;

        setInstalling(true);
        const success = await props.listItemProps.install(data);
        if (success) setInstalled(true);
        setInstalling(false);
    }

    return (
        <Grid item xs={6} lg={4} className={styles.listItem}>
            <div className={clsx(styles.listItemContent, installing && styles.installing)}>
                {data?.image && (
                    <CardActionArea
                        onClick={() => props.listItemProps?.open(props.data)}
                        className={styles.cardActionArea}
                    >
                        <img src={data.image} className={styles.image} />
                    </CardActionArea>
                )}
                <div className={styles.caption}>
                    <Badge color="secondary" badgeContent={installed ? 'installed' : null}>
                        <Typography gutterBottom variant="h5" component="h3" className={styles.title}>
                            {data?.title ?? ''}
                        </Typography>
                    </Badge>
                    <p className={styles.version}>{data?.version ?? ''}</p>
                    <p className={styles.excerpt}>{data?.excerpt ?? ''}</p>
                </div>
                <div className={styles.actions}>
                    <Button
                        size="small" color="primary" variant="contained"
                        onClick={() => props.listItemProps?.open(props.data)}
                    >Open</Button>
                    <Button
                        disabled={installed || installing}
                        size="small" color="primary" variant="contained"
                        onClick={installModule}
                    >Install</Button>
                </div>
                {installing && (
                    <LinearProgress className={styles.updateProgress} />
                )}
            </div>
        </Grid>
    )
}
Example #4
Source File: MarketModal.tsx    From Cromwell with MIT License 5 votes vote down vote up
export default function MarketModal(props: {
    data: TCCSModuleInfo | TPackageCromwellConfig;
    installedModules?: TPackageCromwellConfig[];
    noInstall?: boolean;
    install?: (info: TCCSModuleInfo | TPackageCromwellConfig) => Promise<boolean>;
}) {
    const { data, installedModules } = props;
    const [installing, setInstalling] = useState(false);
    const [installed, setInstalled] = useState(!!(data?.name &&
        installedModules?.find(inst => inst.name === data?.name)));

    const installModule = async () => {
        if (!props.install) return;
        setInstalling(true);
        const success = await props.install(data);
        if (success) setInstalled(true);
        setInstalling(false);
    }

    return (
        <div className={styles.MarketModal}>
            <div className={styles.header}>
                <div>
                    <Badge color="secondary" badgeContent={installed ? 'installed' : null}>
                        <Typography gutterBottom variant="h5" component="h3" className={styles.title}>
                            {data?.title ?? ''}
                        </Typography>
                    </Badge>
                    <p className={styles.version}>{data?.version ?? ''} by {data?.author ?? ''}</p>
                </div>
                <div>
                    {data?.link && (
                        <Tooltip title="Documentation">
                            <IconButton
                                onClick={() => window.open(data.link, '_blank')}>
                                <HelpOutlineIcon />
                            </IconButton>
                        </Tooltip>
                    )}
                    {!props.noInstall && (
                        <Button
                            disabled={installed || installing}
                            size="small" color="primary" variant="contained"
                            onClick={installModule}
                        >Install</Button>
                    )}
                </div>
            </div>
            {data?.images && (
                <div className={styles.images}>
                    <CGallery
                        id="MarketModal_gallery"
                        gallery={{
                            images: data.images.map(url => ({
                                src: url
                            })),
                            height: 300,
                            navigation: true,
                            thumbs: {
                                backgroundSize: 'contain'
                            },
                            backgroundSize: 'contain',
                            lazy: true,
                            visibleSlides: 1,
                        }}
                    />
                </div>
            )}
            {data?.description && (
                <div className={styles.description}
                    dangerouslySetInnerHTML={{ __html: data?.description }}></div>
            )}
        </div>
    )
}
Example #5
Source File: AccountList.tsx    From abrechnung with GNU Affero General Public License v3.0 5 votes vote down vote up
TextBadge = styled(Badge)<BadgeProps>(({ theme }: { theme: Theme }) => ({
    "& .MuiBadge-badge": {
        right: -12,
        border: `2px solid ${theme.palette.background.paper}`,
        padding: "0 4px",
        marginRight: "5px",
    },
}))
Example #6
Source File: LeftMenuSidebar.tsx    From rewind with MIT License 5 votes vote down vote up
export function LeftMenuSidebar() {
  // const LinkBehavior = React.forwardRef((props, ref) => <Link ref={ref} to="/" {...props} role={undefined} />);
  const dispatch = useAppDispatch();
  const pathname = useAppSelector((state) => state.router.location.pathname);

  const handleLinkClick = (to: string) => () => dispatch(push(to));
  const buttonColor = (name: string) => (name === pathname ? "primary" : "default");
  const updateState = useCheckForUpdate();

  return (
    <Stack
      sx={{
        width: (theme) => theme.spacing(10),
        paddingBottom: 2,
      }}
      gap={1}
      p={1}
      alignItems={"center"}
      component={"nav"}
    >
      <Box onClick={handleLinkClick("/home")} sx={{ cursor: "pointer" }}>
        <RewindLogo />
      </Box>
      <Divider orientation={"horizontal"} sx={{ borderWidth: 1, width: "80%" }} />
      <Tooltip title={"Overview"} placement={"right"}>
        <IconButton color={buttonColor("/home")} onClick={handleLinkClick("/home")}>
          <Home />
        </IconButton>
      </Tooltip>
      <Tooltip title={"Analyzer"} placement={"right"}>
        <IconButton
          // These are not centered
          onClick={handleLinkClick("/analyzer")}
          color={buttonColor("/analyzer")}
        >
          <FaMicroscope height={"0.75em"} />
        </IconButton>
      </Tooltip>
      {/*Nothing*/}
      <Box flexGrow={1} />
      {updateState.hasNewUpdate && (
        <Tooltip title={`New version ${updateState.latestVersion} available!`} placement={"right"}>
          <IconButton onClick={() => window.open(latestReleaseUrl)}>
            <Badge variant={"dot"} color={"error"}>
              <UpdateIcon />
            </Badge>
          </IconButton>
        </Tooltip>
      )}
    </Stack>
  );
}
Example #7
Source File: TableHeader.tsx    From firecms with MIT License 4 votes vote down vote up
function TableHeaderInternal<M extends { [Key: string]: any }>({
                                                                   sort,
                                                                   onColumnSort,
                                                                   onFilterUpdate,
                                                                   filter,
                                                                   column
                                                               }: TableHeaderProps<M>) {

    const [onHover, setOnHover] = useState(false);
    const ref = useRef<HTMLDivElement>(null);

    const classes = useStyles({ onHover, align: column.align });

    const [open, setOpen] = React.useState(false);

    const handleSettingsClick = useCallback((event: any) => {
        setOpen(true);
    }, []);

    const handleClose = useCallback(() => {
        setOpen(false);
    }, []);

    const update = useCallback((filterForProperty?: [TableWhereFilterOp, any]) => {
        onFilterUpdate(filterForProperty);
        setOpen(false);
    }, []);

    return (
        <ErrorBoundary>
            <Grid
                className={classes.header}
                ref={ref}
                wrap={"nowrap"}
                alignItems={"center"}
                onMouseEnter={() => setOnHover(true)}
                onMouseMove={() => setOnHover(true)}
                onMouseLeave={() => setOnHover(false)}
                container>

                <Grid item xs={true} className={classes.headerTitle}>
                    <div className={classes.headerInternal}>
                        <div className={classes.headerIcon}>
                            {column.icon && column.icon(onHover || open)}
                        </div>
                        <div className={classes.headerTitleInternal}>
                            {column.label}
                        </div>
                    </div>
                </Grid>

                {column.sortable && (sort || onHover || open) &&
                <Grid item>
                    <Badge color="secondary"
                           variant="dot"
                           overlap="circular"
                           invisible={!sort}>
                        <IconButton
                            size={"small"}
                            className={classes.headerIconButton}
                            onClick={() => {
                                onColumnSort(column.key as Extract<keyof M, string>);
                            }}
                        >
                            {!sort && <ArrowUpwardIcon fontSize={"small"}/>}
                            {sort === "asc" &&
                            <ArrowUpwardIcon fontSize={"small"}/>}
                            {sort === "desc" &&
                            <ArrowDownwardIcon fontSize={"small"}/>}
                        </IconButton>
                    </Badge>
                </Grid>
                }

                {column.filter && <Grid item>
                    <Badge color="secondary"
                           variant="dot"
                           overlap="circular"
                           invisible={!filter}>
                        <IconButton
                            className={classes.headerIconButton}
                            size={"small"}
                            onClick={handleSettingsClick}>
                            <ArrowDropDownCircleIcon fontSize={"small"}
                                                     color={onHover || open ? undefined : "disabled"}/>
                        </IconButton>

                    </Badge>
                </Grid>}
            </Grid>

            {column.sortable && <Popover
                id={open ? `popover_${column.key}` : undefined}
                open={open}
                elevation={2}
                anchorEl={ref.current}
                onClose={handleClose}
                anchorOrigin={{
                    vertical: "bottom",
                    horizontal: "right"
                }}
                transformOrigin={{
                    vertical: "top",
                    horizontal: "right"
                }}
            >
                <FilterForm column={column}
                            filter={filter}
                            onFilterUpdate={update}/>
            </Popover>}

        </ErrorBoundary>
    );
}
Example #8
Source File: StoreCurrencies.tsx    From Cromwell with MIT License 4 votes vote down vote up
export default function StoreCurrencies(props: TTabProps) {
    const { settings, changeSettings } = props;
    const currencies = settings?.currencies ?? [];

    const handleDeleteCurrency = (tag: string) => {
        const currencies = (settings?.currencies ?? []);
        changeSettings('currencies', currencies.filter(curr => curr.tag !== tag));
    }

    const handleAddCurrency = () => {
        const currencies = (settings?.currencies ?? []);
        changeSettings('currencies', [...currencies, {
            tag: 'new',
            id: currencies.length + 1 + '',
        }]);
    }

    return (
        <Grid container spacing={3}>
            <Grid item xs={12}>
                <ResponsiveGridLayout
                    margin={[15, 15]}
                    layouts={{
                        xs: currencies.map((currency, index) => {
                            return { i: currency.id, x: (index % 2), y: Math.floor(index / 2), w: 1, h: 1 }
                        }),
                        xxs: currencies.map((currency, index) => {
                            return { i: currency.id, x: 0, y: index, w: 1, h: 1 }
                        })
                    }}
                    breakpoints={{ xs: 480, xxs: 0 }}
                    rowHeight={330}
                    isResizable={false}
                    cols={{ xs: 2, xxs: 1 }}
                    draggableHandle='.draggableHandle'
                    onLayoutChange={(layout) => {
                        const sortedCurrencies: TCurrency[] = [];
                        const sorted = [...layout].sort((a, b) => (a.x + a.y * 10) - (b.x + b.y * 10));
                        sorted.forEach(item => {
                            const curr = currencies.find(curr => curr.id === item.i);
                            if (curr) sortedCurrencies.push(curr);
                        });
                        changeSettings('currencies', sortedCurrencies)
                    }}
                >
                    {currencies.map((currency, index) => {
                        const onChange = (item) => {
                            const newCurrencies = [...currencies];
                            newCurrencies[index] = item;
                            changeSettings('currencies', newCurrencies)
                        }

                        const handleTextFieldChange = (key: keyof TCurrency, type?: 'number' | 'string') =>
                            (event: React.ChangeEvent<{ value: string }>) => {
                                let val: string | number | undefined = event.target.value;
                                if (type === 'number') {
                                    val = parseFloat(val);
                                    if (isNaN(val)) val = undefined;
                                }
                                onChange({
                                    ...currency,
                                    [key]: val
                                })
                            }

                        const isPrimary = index === 0;

                        return (
                            <div className={styles.currencyItem} key={currency.id}>
                                <div className={styles.currencyItemHeader}>
                                    <div className={styles.currencyBadge}>
                                        <Badge color="secondary" badgeContent={isPrimary ? 'Primary' : null}>
                                            <div></div>
                                        </Badge>
                                    </div>
                                    <div>
                                        <IconButton onClick={() => handleDeleteCurrency(currency.tag)}>
                                            <DeleteForeverIcon />
                                        </IconButton>
                                        <IconButton style={{ cursor: 'move' }} className="draggableHandle">
                                            <DragIndicatorIcon />
                                        </IconButton>
                                    </div>
                                </div>
                                <TextField label="Tag"
                                    value={currency.tag ?? ''}
                                    className={styles.textField + ' draggableCancel'}
                                    fullWidth
                                    variant="standard"
                                    onChange={handleTextFieldChange('tag')}
                                />
                                <TextField label="Title"
                                    value={currency.title ?? ''}
                                    className={styles.textField + ' draggableCancel'}
                                    fullWidth
                                    variant="standard"
                                    onChange={handleTextFieldChange('title')}
                                />
                                <TextField label="Ratio"
                                    value={currency.ratio ?? ''}
                                    className={styles.textField + ' draggableCancel'}
                                    fullWidth
                                    type="number"
                                    variant="standard"
                                    onChange={handleTextFieldChange('ratio', 'number')}
                                />
                                <TextField label="Symbol"
                                    value={currency.symbol ?? ''}
                                    className={styles.textField + ' draggableCancel'}
                                    fullWidth
                                    variant="standard"
                                    onChange={handleTextFieldChange('symbol')}
                                />
                            </div>
                        )
                    })}
                </ResponsiveGridLayout>
                <Tooltip title="Add currency">
                    <IconButton onClick={handleAddCurrency}>
                        <AddIcon />
                    </IconButton>
                </Tooltip>
            </Grid>
        </Grid>
    )
}
Example #9
Source File: ThemeList.tsx    From Cromwell with MIT License 4 votes vote down vote up
render() {
        const { isLoading, packages, installedThemes, cmsConfig, isChangingTheme } = this.state;
        return (
            <div className={styles.ThemeList} ref={this.pageRef}>
                <Button
                    className={styles.addBtn}
                    onClick={this.handleOpenMarket}
                    variant="contained"
                    color="primary"
                    startIcon={<AddCircleOutlineIcon />}
                >Add themes</Button>
                {isLoading && (
                    <div className={styles.list}>
                        {Array(2).fill(1).map((it, index) => (
                            <Skeleton key={index} variant="rectangular" height="388px" width="300px" style={{ margin: '0 10px 20px 10px' }} > </Skeleton>
                        ))}
                    </div>
                )}
                {!isLoading &&
                    <div className={styles.list}>
                        {packages.map(info => {
                            const isActive = Boolean(cmsConfig && cmsConfig.themeName === info.name);
                            const entity = installedThemes?.find(ent => ent.name === info.name);
                            const isInstalled = entity?.isInstalled ?? false;
                            const availableUpdate = this.themeUpdates[info.name];
                            const isUnderUpdate = this.themeUnderUpdate[info.name];

                            return (
                                <div className={`${styles.themeCard} ${commonStyles.paper}`} key={info.name}>
                                    <CardActionArea
                                        className={styles.cardActionArea}
                                        style={{ opacity: isUnderUpdate ? 0.5 : 1 }}
                                    >
                                        <div
                                            style={{ backgroundImage: `url("data:image/png;base64,${info.image}")` }}
                                            className={styles.themeImage}
                                        ></div>
                                        <CardContent className={styles.mainInfo}>
                                            <Badge color="secondary" badgeContent={isActive ? 'Active' : null}>
                                                <Typography gutterBottom variant="h5" component="h2" className={styles.themeTitle}>
                                                    {info.title}
                                                </Typography>
                                            </Badge>
                                            <p className={styles.version}
                                                onClick={this.handleShowUpdate(entity, info, availableUpdate)}
                                                style={{ cursor: availableUpdate ? 'pointer' : 'initial' }}
                                            >{(info?.version ?? '') +
                                                (availableUpdate ? ' > ' + availableUpdate.version + ' Open info' : '')}</p>
                                            <Typography variant="body2" color="textSecondary" component="p">
                                                {info.excerpt}
                                            </Typography>
                                        </CardContent>
                                    </CardActionArea>
                                    <CardActions
                                        style={{ opacity: isUnderUpdate ? 0.5 : 1 }}
                                        className={styles.themeActions}
                                        disableSpacing
                                    >
                                        {!isInstalled && (
                                            <Button
                                                disabled={isUnderUpdate || isChangingTheme}
                                                size="small" color="primary" variant="contained"
                                                onClick={this.handleActivateTheme(info.name)}
                                            >Install theme</Button>
                                        )}
                                        {isInstalled && isActive && (
                                            <Button
                                                disabled={isUnderUpdate || isChangingTheme}
                                                size="small" color="primary" variant="contained"
                                                onClick={() => {
                                                    const route = `${themeEditPageInfo.baseRoute}`;
                                                    this.props.history.push(route);
                                                }}
                                            >
                                                Edit theme
                                            </Button>
                                        )}
                                        {availableUpdate && (
                                            <Button
                                                disabled={isUnderUpdate || isChangingTheme}
                                                size="small" color="primary" variant="contained"
                                                onClick={() => this.startUpdate(info)}
                                            >Update</Button>
                                        )}
                                        {isInstalled && !isActive && (
                                            <Button size="small" color="primary" variant="contained"
                                                onClick={() => this.handleSetActiveTheme(info)}
                                                disabled={isUnderUpdate || isChangingTheme}
                                            >Set active</Button>
                                        )}
                                        <Button size="small" color="primary" variant="outlined"
                                            disabled={isUnderUpdate || isChangingTheme}
                                            onClick={() => this.handleDelete(info)}
                                        >Delete</Button>
                                        <Button size="small" color="primary" variant="outlined"
                                            onClick={() => this.openTheme(info)}
                                        >Info</Button>
                                        {isUnderUpdate && (
                                            <LinearProgress className={styles.updateProgress} />
                                        )}
                                    </CardActions>
                                </div>
                            )
                        })}
                    </div>}
                <LoadingStatus isActive={isChangingTheme} />
                {/* <ManagerLogger isActive={isChangingTheme} /> */}
                <Modal
                    open={!!this.state.updateModalInfo}
                    onClose={() => this.setState({ updateModalInfo: null })}
                    className={commonStyles.center}
                    blurSelector="#root"
                >
                    <UpdateModalContent
                        underUpdate={this.themeUnderUpdate}
                        {...(this.state?.updateModalInfo ?? {})}
                        onStartUpdate={this.startUpdate}
                        onClose={() => this.setState({ updateModalInfo: null })}
                    />
                </Modal>
                <Modal
                    open={!!this.state.openedTheme}
                    blurSelector="#root"
                    className={commonStyles.center}
                    onClose={() => this.setState({ openedTheme: undefined })}
                >
                    {this.state?.openedTheme && (
                        <MarketModal
                            installedModules={this.state?.installedThemes ?? []}
                            data={this.state.openedTheme}
                            noInstall
                        />
                    )}
                </Modal>
            </div>
        )

    }
Example #10
Source File: TabOverview.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function TabOverview() {
  const { data, characterSheet, character, character: { key: characterKey } } = useContext(DataContext)
  const characterDispatch = useCharacterReducer(characterKey)
  const navigate = useNavigate()
  const { t } = useTranslation("page_character")
  const charEle = data.get(input.charEle).value as ElementKey
  const weaponTypeKey = characterSheet.weaponTypeKey
  const level = data.get(input.lvl).value
  const ascension = data.get(input.asc).value
  const constellation = data.get(input.constellation).value
  const tlvl = {
    auto: data.get(input.total.auto).value,
    skill: data.get(input.total.skill).value,
    burst: data.get(input.total.burst).value,
  }
  const tBoost = {
    auto: data.get(input.bonus.auto).value,
    skill: data.get(input.bonus.skill).value,
    burst: data.get(input.bonus.burst).value,
  }
  return <Grid container spacing={1} sx={{ justifyContent: "center" }}>
    <Grid item xs={8} sm={5} md={4} lg={2.5}  >
      {/* Image card with star and name and level */}
      <CardLight >
        <Box src={characterSheet.cardImg} component="img" width="100%" height="auto" />
        <CardContent>
          <Typography variant="h5" >
            {characterSheet.name}&nbsp;
            <ImgIcon sx={{ pr: 0.5 }} src={Assets.weaponTypes?.[weaponTypeKey]} />
            {StatIcon[charEle]}
            <IconButton sx={{ p: 0.5, mt: -0.5 }} onClick={() => characterDispatch({ favorite: !character.favorite })}>
              {character.favorite ? <Favorite /> : <FavoriteBorder />}
            </IconButton>
          </Typography>
          <Typography variant="h6"><Stars stars={characterSheet.rarity} colored /></Typography>
          <Typography variant="h5">Lvl. {CharacterSheet.getLevelString(level, ascension)}</Typography>
          <CardActionArea sx={{ p: 1 }} onClick={() => navigate("talent")}>
            <Grid container spacing={1} mt={-1}>
              {(["auto", "skill", "burst"] as TalentSheetElementKey[]).map(tKey =>
                <Grid item xs={4} key={tKey}>
                  <Badge badgeContent={tlvl[tKey]} color={tBoost[tKey] ? "info" : "secondary"}
                    overlap="circular"
                    anchorOrigin={{
                      vertical: 'bottom',
                      horizontal: 'right',
                    }}
                    sx={{
                      width: "100%",
                      height: "100%",
                      "& > .MuiBadge-badge": {
                        fontSize: "1.25em",
                        padding: ".25em .4em",
                        borderRadius: ".5em",
                        lineHeight: 1,
                        height: "1.25em"
                      }
                    }}>
                    <Box component="img" src={characterSheet.getTalentOfKey(tKey, charEle)?.img} width="100%" height="auto" />
                  </Badge>
                </Grid>)}
            </Grid>
          </CardActionArea>
          <Typography sx={{ textAlign: "center", mt: 1 }} variant="h6">{characterSheet.constellationName}</Typography>
          <Grid container spacing={1}>
            {range(1, 6).map(i =>
              <Grid item xs={4} key={i}>
                <CardActionArea onClick={() => characterDispatch({ constellation: i === constellation ? i - 1 : i })}>
                  <Box component="img" src={characterSheet.getTalentOfKey(`constellation${i}` as TalentSheetElementKey, charEle)?.img}
                    sx={{
                      ...(constellation >= i ? {} : { filter: "brightness(50%)" })
                    }}
                    width="100%" height="auto" />
                </CardActionArea>
              </Grid>)}
          </Grid>
          <Typography sx={{ textAlign: "center", mt: 1 }} variant="h6">{t("teammates")}</Typography>
          <CardActionArea sx={{ p: 1 }} onClick={() => navigate("teambuffs")}>
            <Grid container columns={3} spacing={1}>
              {range(0, 2).map(i => <Grid key={i} item xs={1} height="100%"><CharacterCardPico characterKey={character.team[i]} index={i} /></Grid>)}
            </Grid>
          </CardActionArea>
        </CardContent>
      </CardLight>
    </Grid>
    <Grid item xs={12} sm={7} md={8} lg={9.5} sx={{
      display: "flex", flexDirection: "column", gap: 1
    }} >
      <Grid container spacing={1} columns={{ xs: 2, sm: 2, md: 3, lg: 4, xl: 6 }}>
        <Grid item xs={1}>
          <WeaponCardNano weaponId={character.equippedWeapon} BGComponent={CardLight} onClick={() => navigate("equip")} />
        </Grid>
        {allSlotKeys.map(slotKey =>
          <Grid item key={slotKey} xs={1} >
            <ArtifactCardNano artifactId={data.get(input.art[slotKey].id).value} slotKey={slotKey} BGComponent={CardLight} onClick={() => navigate("equip")} />
          </Grid>)}
      </Grid>
      <MainStatsCards />
    </Grid>
  </Grid >
}
Example #11
Source File: ListObjects.tsx    From console with GNU Affero General Public License v3.0 4 votes vote down vote up
ListObjects = ({ match, history }: IListObjectsProps) => {
  const classes = useStyles();
  const dispatch = useDispatch();

  const rewindEnabled = useSelector(
    (state: AppState) => state.objectBrowser.rewind.rewindEnabled
  );
  const rewindDate = useSelector(
    (state: AppState) => state.objectBrowser.rewind.dateToRewind
  );
  const bucketToRewind = useSelector(
    (state: AppState) => state.objectBrowser.rewind.bucketToRewind
  );
  const versionsMode = useSelector(
    (state: AppState) => state.objectBrowser.versionsMode
  );

  const searchObjects = useSelector(
    (state: AppState) => state.objectBrowser.searchObjects
  );
  const showDeleted = useSelector(
    (state: AppState) => state.objectBrowser.showDeleted
  );
  const detailsOpen = useSelector(
    (state: AppState) => state.objectBrowser.objectDetailsOpen
  );
  const selectedInternalPaths = useSelector(
    (state: AppState) => state.objectBrowser.selectedInternalPaths
  );
  const loading = useSelector(
    (state: AppState) => state.objectBrowser.loadingObjects
  );
  const simplePath = useSelector(
    (state: AppState) => state.objectBrowser.simplePath
  );

  const loadingBucket = useSelector(selBucketDetailsLoading);
  const bucketInfo = useSelector(selBucketDetailsInfo);
  const allowResources = useSelector(
    (state: AppState) => state.console.session.allowResources
  );

  const [records, setRecords] = useState<BucketObjectItem[]>([]);
  const [deleteMultipleOpen, setDeleteMultipleOpen] = useState<boolean>(false);
  const [loadingStartTime, setLoadingStartTime] = useState<number>(0);
  const [loadingMessage, setLoadingMessage] =
    useState<React.ReactNode>(defLoading);
  const [loadingVersioning, setLoadingVersioning] = useState<boolean>(true);
  const [isVersioned, setIsVersioned] = useState<boolean>(false);
  const [loadingLocking, setLoadingLocking] = useState<boolean>(true);
  const [lockingEnabled, setLockingEnabled] = useState<boolean>(false);
  const [rewindSelect, setRewindSelect] = useState<boolean>(false);
  const [selectedObjects, setSelectedObjects] = useState<string[]>([]);
  const [previewOpen, setPreviewOpen] = useState<boolean>(false);
  const [selectedPreview, setSelectedPreview] =
    useState<BucketObjectItem | null>(null);
  const [shareFileModalOpen, setShareFileModalOpen] = useState<boolean>(false);
  const [sortDirection, setSortDirection] = useState<
    "ASC" | "DESC" | undefined
  >("ASC");
  const [currentSortField, setCurrentSortField] = useState<string>("name");
  const [iniLoad, setIniLoad] = useState<boolean>(false);
  const [canShareFile, setCanShareFile] = useState<boolean>(false);
  const [canPreviewFile, setCanPreviewFile] = useState<boolean>(false);
  const [quota, setQuota] = useState<BucketQuota | null>(null);

  const internalPaths = get(match.params, "subpaths", "");
  const bucketName = match.params["bucketName"];

  const fileUpload = useRef<HTMLInputElement>(null);
  const folderUpload = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (folderUpload.current !== null) {
      folderUpload.current.setAttribute("directory", "");
      folderUpload.current.setAttribute("webkitdirectory", "");
    }
  }, [folderUpload]);

  useEffect(() => {
    if (selectedObjects.length === 1) {
      const objectName = selectedObjects[0];

      if (extensionPreview(objectName) !== "none") {
        setCanPreviewFile(true);
      } else {
        setCanPreviewFile(false);
      }

      if (objectName.endsWith("/")) {
        setCanShareFile(false);
      } else {
        setCanShareFile(true);
      }
    } else {
      setCanShareFile(false);
      setCanPreviewFile(false);
    }
  }, [selectedObjects]);

  useEffect(() => {
    if (!quota) {
      api
        .invoke("GET", `/api/v1/buckets/${bucketName}/quota`)
        .then((res: BucketQuota) => {
          let quotaVals = null;

          if (res.quota) {
            quotaVals = res;
          }

          setQuota(quotaVals);
        })
        .catch((err) => {
          console.error("Error Getting Quota Status: ", err.detailedError);
          setQuota(null);
        });
    }
  }, [quota, bucketName]);

  useEffect(() => {
    if (selectedObjects.length > 0) {
      dispatch(setObjectDetailsView(true));
      return;
    }

    if (selectedObjects.length === 0 && selectedInternalPaths === null) {
      dispatch(setObjectDetailsView(false));
    }
  }, [selectedObjects, selectedInternalPaths, dispatch]);

  const displayDeleteObject = hasPermission(bucketName, [
    IAM_SCOPES.S3_DELETE_OBJECT,
  ]);

  const displayListObjects = hasPermission(bucketName, [
    IAM_SCOPES.S3_LIST_BUCKET,
  ]);

  const updateMessage = () => {
    let timeDelta = Date.now() - loadingStartTime;

    if (timeDelta / 1000 >= 6) {
      setLoadingMessage(
        <Fragment>
          <Typography component="h3">
            This operation is taking longer than expected... (
            {Math.ceil(timeDelta / 1000)}s)
          </Typography>
        </Fragment>
      );
    } else if (timeDelta / 1000 >= 3) {
      setLoadingMessage(
        <Typography component="h3">
          This operation is taking longer than expected...
        </Typography>
      );
    }
  };

  useEffect(() => {
    if (!iniLoad) {
      dispatch(setBucketDetailsLoad(true));
      setIniLoad(true);
    }
  }, [iniLoad, dispatch, setIniLoad]);

  useInterval(() => {
    // Your custom logic here
    if (loading) {
      updateMessage();
    }
  }, 1000);

  useEffect(() => {
    if (loadingVersioning) {
      if (displayListObjects) {
        api
          .invoke("GET", `/api/v1/buckets/${bucketName}/versioning`)
          .then((res: BucketVersioning) => {
            setIsVersioned(res.is_versioned);
            setLoadingVersioning(false);
          })
          .catch((err: ErrorResponseHandler) => {
            console.error(
              "Error Getting Object Versioning Status: ",
              err.detailedError
            );
            setLoadingVersioning(false);
          });
      } else {
        setLoadingVersioning(false);
        setRecords([]);
      }
    }
  }, [bucketName, loadingVersioning, dispatch, displayListObjects]);

  useEffect(() => {
    if (loadingLocking) {
      if (displayListObjects) {
        api
          .invoke("GET", `/api/v1/buckets/${bucketName}/object-locking`)
          .then((res: BucketObjectLocking) => {
            setLockingEnabled(res.object_locking_enabled);
            setLoadingLocking(false);
          })
          .catch((err: ErrorResponseHandler) => {
            console.error(
              "Error Getting Object Locking Status: ",
              err.detailedError
            );
            setLoadingLocking(false);
          });
      } else {
        setRecords([]);
        setLoadingLocking(false);
      }
    }
  }, [bucketName, loadingLocking, dispatch, displayListObjects]);

  useEffect(() => {
    const decodedIPaths = decodeURLString(internalPaths);

    if (decodedIPaths.endsWith("/") || decodedIPaths === "") {
      dispatch(setObjectDetailsView(false));
      dispatch(setSelectedObjectView(null));
      dispatch(
        setSimplePathHandler(decodedIPaths === "" ? "/" : decodedIPaths)
      );
    } else {
      dispatch(setLoadingObjectInfo(true));
      dispatch(setObjectDetailsView(true));
      dispatch(setLoadingVersions(true));
      dispatch(
        setSelectedObjectView(
          `${decodedIPaths ? `${encodeURLString(decodedIPaths)}` : ``}`
        )
      );
      dispatch(
        setSimplePathHandler(
          `${decodedIPaths.split("/").slice(0, -1).join("/")}/`
        )
      );
    }
  }, [internalPaths, rewindDate, rewindEnabled, dispatch]);

  useEffect(() => {
    dispatch(setSearchObjects(""));
    dispatch(setLoadingObjectsList(true));
    setSelectedObjects([]);
  }, [simplePath, dispatch, setSelectedObjects]);

  useEffect(() => {
    if (loading) {
      if (displayListObjects) {
        let pathPrefix = "";
        if (internalPaths) {
          const decodedPath = decodeURLString(internalPaths);
          pathPrefix = decodedPath.endsWith("/")
            ? decodedPath
            : decodedPath + "/";
        }

        let currentTimestamp = Date.now();
        setLoadingStartTime(currentTimestamp);
        setLoadingMessage(defLoading);

        // We get URL to look into
        let urlTake = `/api/v1/buckets/${bucketName}/objects`;

        // Is rewind enabled?, we use Rewind API
        if (rewindEnabled) {
          if (bucketToRewind !== bucketName) {
            dispatch(resetRewind());
            return;
          }

          if (rewindDate) {
            const rewindParsed = rewindDate.toISOString();

            urlTake = `/api/v1/buckets/${bucketName}/rewind/${rewindParsed}`;
          }
        } else if (showDeleted) {
          // Do we want to display deleted items too?, we use rewind to current time to show everything
          const currDate = new Date();
          const currDateISO = currDate.toISOString();

          urlTake = `/api/v1/buckets/${bucketName}/rewind/${currDateISO}`;
        }

        api
          .invoke(
            "GET",
            `${urlTake}${
              pathPrefix ? `?prefix=${encodeURLString(pathPrefix)}` : ``
            }`
          )
          .then((res: BucketObjectItemsList) => {
            const records: BucketObjectItem[] = res.objects || [];
            const folders: BucketObjectItem[] = [];
            const files: BucketObjectItem[] = [];

            // We separate items between folders or files to display folders at the beginning always.
            records.forEach((record) => {
              // We omit files from the same path
              if (record.name !== decodeURLString(internalPaths)) {
                // this is a folder
                if (record.name.endsWith("/")) {
                  folders.push(record);
                } else {
                  // this is a file
                  files.push(record);
                }
              }
            });

            const recordsInElement = [...folders, ...files];

            if (recordsInElement.length === 0 && pathPrefix !== "") {
              let pathTest = `/api/v1/buckets/${bucketName}/objects${
                internalPaths ? `?prefix=${internalPaths}` : ""
              }`;

              if (rewindEnabled) {
                const rewindParsed = rewindDate.toISOString();

                let pathPrefix = "";
                if (internalPaths) {
                  const decodedPath = decodeURLString(internalPaths);
                  pathPrefix = decodedPath.endsWith("/")
                    ? decodedPath
                    : decodedPath + "/";
                }

                pathTest = `/api/v1/buckets/${bucketName}/rewind/${rewindParsed}${
                  pathPrefix ? `?prefix=${encodeURLString(pathPrefix)}` : ``
                }`;
              }

              api
                .invoke("GET", pathTest)
                .then((res: BucketObjectItemsList) => {
                  //It is a file since it has elements in the object, setting file flag and waiting for component mount
                  if (!res.objects) {
                    // It is a folder, we remove loader & set original results list
                    dispatch(setLoadingObjectsList(false));
                    setRecords(recordsInElement);
                  } else {
                    // This code prevents the program from opening a file when a substring of that file is entered as a new folder.
                    // Previously, if there was a file test1.txt and the folder test was created with the same prefix, the program
                    // would open test1.txt instead
                    let found = false;
                    let pathPrefixChopped = pathPrefix.slice(
                      0,
                      pathPrefix.length - 1
                    );
                    for (let i = 0; i < res.objects.length; i++) {
                      if (res.objects[i].name === pathPrefixChopped) {
                        found = true;
                      }
                    }
                    if (
                      (res.objects.length === 1 &&
                        res.objects[0].name.endsWith("/")) ||
                      !found
                    ) {
                      // This is a folder, we set the original results list
                      setRecords(recordsInElement);
                    } else {
                      // This is a file. We change URL & Open file details view.
                      dispatch(setObjectDetailsView(true));
                      dispatch(setSelectedObjectView(internalPaths));

                      // We split the selected object URL & remove the last item to fetch the files list for the parent folder
                      const parentPath = `${decodeURLString(internalPaths)
                        .split("/")
                        .slice(0, -1)
                        .join("/")}/`;

                      api
                        .invoke(
                          "GET",
                          `${urlTake}${
                            pathPrefix
                              ? `?prefix=${encodeURLString(parentPath)}`
                              : ``
                          }`
                        )
                        .then((res: BucketObjectItemsList) => {
                          const records: BucketObjectItem[] = res.objects || [];

                          setRecords(records);
                        })
                        .catch(() => {});
                    }

                    dispatch(setLoadingObjectsList(false));
                  }
                })
                .catch((err: ErrorResponseHandler) => {
                  dispatch(setLoadingObjectsList(false));
                  dispatch(setErrorSnackMessage(err));
                });
            } else {
              setRecords(recordsInElement);
              dispatch(setLoadingObjectsList(false));
            }
          })
          .catch((err: ErrorResponseHandler) => {
            const permitItems = permissionItems(
              bucketName,
              pathPrefix,
              allowResources || []
            );

            if (!permitItems || permitItems.length === 0) {
              dispatch(setErrorSnackMessage(err));
            } else {
              setRecords(permitItems);
            }

            dispatch(setLoadingObjectsList(false));
          });
      } else {
        dispatch(setLoadingObjectsList(false));
      }
    }
  }, [
    loading,
    match,
    dispatch,
    bucketName,
    rewindEnabled,
    rewindDate,
    internalPaths,
    bucketInfo,
    showDeleted,
    displayListObjects,
    bucketToRewind,
    allowResources,
  ]);

  // bucket info
  useEffect(() => {
    if (loadingBucket) {
      api
        .invoke("GET", `/api/v1/buckets/${bucketName}`)
        .then((res: BucketInfo) => {
          dispatch(setBucketDetailsLoad(false));
          dispatch(setBucketInfo(res));
        })
        .catch((err: ErrorResponseHandler) => {
          dispatch(setBucketDetailsLoad(false));
          dispatch(setErrorSnackMessage(err));
        });
    }
  }, [bucketName, loadingBucket, dispatch]);

  const closeDeleteMultipleModalAndRefresh = (refresh: boolean) => {
    setDeleteMultipleOpen(false);

    if (refresh) {
      dispatch(setSnackBarMessage(`Objects deleted successfully.`));
      setSelectedObjects([]);
      dispatch(setLoadingObjectsList(true));
    }
  };

  const handleUploadButton = (e: any) => {
    if (
      e === null ||
      e === undefined ||
      e.target.files === null ||
      e.target.files === undefined
    ) {
      return;
    }
    e.preventDefault();
    var newFiles: File[] = [];

    for (var i = 0; i < e.target.files.length; i++) {
      newFiles.push(e.target.files[i]);
    }
    uploadObject(newFiles, "");

    e.target.value = "";
  };

  const downloadObject = (object: BucketObjectItem) => {
    const identityDownload = encodeURLString(
      `${bucketName}-${object.name}-${new Date().getTime()}-${Math.random()}`
    );

    const downloadCall = download(
      bucketName,
      encodeURLString(object.name),
      object.version_id,
      object.size,
      (progress) => {
        dispatch(
          updateProgress({
            instanceID: identityDownload,
            progress: progress,
          })
        );
      },
      () => {
        dispatch(completeObject(identityDownload));
      },
      () => {
        dispatch(failObject(identityDownload));
      },
      () => {
        dispatch(cancelObjectInList(identityDownload));
      }
    );
    const ID = makeid(8);
    storeCallForObjectWithID(ID, downloadCall);
    dispatch(
      setNewObject({
        ID,
        bucketName,
        done: false,
        instanceID: identityDownload,
        percentage: 0,
        prefix: object.name,
        type: "download",
        waitingForFile: true,
        failed: false,
        cancelled: false,
      })
    );

    downloadCall.send();
  };

  const openPath = (idElement: string) => {
    setSelectedObjects([]);

    const newPath = `/buckets/${bucketName}/browse${
      idElement ? `/${encodeURLString(idElement)}` : ``
    }`;
    history.push(newPath);

    dispatch(setObjectDetailsView(true));
    dispatch(setLoadingVersions(true));
    dispatch(
      setSelectedObjectView(
        `${idElement ? `${encodeURLString(idElement)}` : ``}`
      )
    );
  };

  const uploadObject = useCallback(
    (files: File[], folderPath: string): void => {
      let pathPrefix = "";
      if (simplePath) {
        pathPrefix = simplePath.endsWith("/") ? simplePath : simplePath + "/";
      }

      const upload = (
        files: File[],
        bucketName: string,
        path: string,
        folderPath: string
      ) => {
        let uploadPromise = (file: File) => {
          return new Promise((resolve, reject) => {
            let uploadUrl = `api/v1/buckets/${bucketName}/objects/upload`;
            const fileName = file.name;

            const blobFile = new Blob([file], { type: file.type });

            let encodedPath = "";

            const filePath = get(file, "path", "");
            const fileWebkitRelativePath = get(file, "webkitRelativePath", "");

            let relativeFolderPath = folderPath;

            // File was uploaded via drag & drop
            if (filePath !== "") {
              relativeFolderPath = filePath;
            } else if (fileWebkitRelativePath !== "") {
              // File was uploaded using upload button
              relativeFolderPath = fileWebkitRelativePath;
            }

            if (path !== "" || relativeFolderPath !== "") {
              const finalFolderPath = relativeFolderPath
                .split("/")
                .slice(0, -1)
                .join("/");

              const pathClean = path.endsWith("/") ? path.slice(0, -1) : path;

              encodedPath = encodeURLString(
                `${pathClean}${
                  !pathClean.endsWith("/") &&
                  finalFolderPath !== "" &&
                  !finalFolderPath.startsWith("/")
                    ? "/"
                    : ""
                }${finalFolderPath}${
                  !finalFolderPath.endsWith("/") ||
                  (finalFolderPath.trim() === "" && !path.endsWith("/"))
                    ? "/"
                    : ""
                }`
              );
            }

            if (encodedPath !== "") {
              uploadUrl = `${uploadUrl}?prefix=${encodedPath}`;
            }

            const identity = encodeURLString(
              `${bucketName}-${encodedPath}-${new Date().getTime()}-${Math.random()}`
            );

            let xhr = new XMLHttpRequest();
            xhr.open("POST", uploadUrl, true);

            const areMultipleFiles = files.length > 1;
            let errorMessage = `An error occurred while uploading the file${
              areMultipleFiles ? "s" : ""
            }.`;

            const errorMessages: any = {
              413: "Error - File size too large",
            };

            xhr.withCredentials = false;
            xhr.onload = function (event) {
              // resolve promise only when HTTP code is ok
              if (xhr.status >= 200 && xhr.status < 300) {
                dispatch(completeObject(identity));
                resolve({ status: xhr.status });
              } else {
                // reject promise if there was a server error
                if (errorMessages[xhr.status]) {
                  errorMessage = errorMessages[xhr.status];
                } else if (xhr.response) {
                  try {
                    const err = JSON.parse(xhr.response);
                    errorMessage = err.detailedMessage;
                  } catch (e) {
                    errorMessage = "something went wrong";
                  }
                }
                dispatch(failObject(identity));
                reject({ status: xhr.status, message: errorMessage });
              }
            };

            xhr.upload.addEventListener("error", (event) => {
              reject(errorMessage);
              dispatch(failObject(identity));
              return;
            });

            xhr.upload.addEventListener("progress", (event) => {
              const progress = Math.floor((event.loaded * 100) / event.total);

              dispatch(
                updateProgress({
                  instanceID: identity,
                  progress: progress,
                })
              );
            });

            xhr.onerror = () => {
              reject(errorMessage);
              dispatch(failObject(identity));
              return;
            };
            xhr.onloadend = () => {
              if (files.length === 0) {
                dispatch(setLoadingObjectsList(true));
              }
            };
            xhr.onabort = () => {
              dispatch(cancelObjectInList(identity));
            };

            const formData = new FormData();
            if (file.size !== undefined) {
              formData.append(file.size.toString(), blobFile, fileName);
              const ID = makeid(8);
              storeCallForObjectWithID(ID, xhr);
              dispatch(
                setNewObject({
                  ID,
                  bucketName,
                  done: false,
                  instanceID: identity,
                  percentage: 0,
                  prefix: `${decodeURLString(encodedPath)}${fileName}`,
                  type: "upload",
                  waitingForFile: false,
                  failed: false,
                  cancelled: false,
                })
              );

              xhr.send(formData);
            }
          });
        };

        const uploadFilePromises: any = [];
        // open object manager
        dispatch(openList());
        for (let i = 0; i < files.length; i++) {
          const file = files[i];
          uploadFilePromises.push(uploadPromise(file));
        }
        Promise.allSettled(uploadFilePromises).then((results: Array<any>) => {
          const errors = results.filter(
            (result) => result.status === "rejected"
          );
          if (errors.length > 0) {
            const totalFiles = uploadFilePromises.length;
            const successUploadedFiles =
              uploadFilePromises.length - errors.length;
            const err: ErrorResponseHandler = {
              errorMessage: "There were some errors during file upload",
              detailedError: `Uploaded files ${successUploadedFiles}/${totalFiles}`,
            };
            dispatch(setErrorSnackMessage(err));
          }
          // We force objects list reload after all promises were handled
          dispatch(setLoadingObjectsList(true));
          setSelectedObjects([]);
        });
      };

      upload(files, bucketName, pathPrefix, folderPath);
    },
    [bucketName, dispatch, simplePath]
  );

  const onDrop = useCallback(
    (acceptedFiles: any[]) => {
      if (acceptedFiles && acceptedFiles.length > 0) {
        let newFolderPath: string = acceptedFiles[0].path;
        uploadObject(acceptedFiles, newFolderPath);
      }
    },
    [uploadObject]
  );

  const { getRootProps, getInputProps, isDragActive, isDragAccept } =
    useDropzone({
      noClick: true,
      onDrop,
    });

  const dndStyles = useMemo(
    () => ({
      ...baseDnDStyle,
      ...(isDragActive ? activeDnDStyle : {}),
      ...(isDragAccept ? acceptDnDStyle : {}),
    }),
    [isDragActive, isDragAccept]
  );

  const openPreview = () => {
    if (selectedObjects.length === 1) {
      let fileObject: BucketObjectItem | undefined;

      const findFunction = (currValue: BucketObjectItem) =>
        selectedObjects.includes(currValue.name);

      fileObject = filteredRecords.find(findFunction);

      if (fileObject) {
        setSelectedPreview(fileObject);
        setPreviewOpen(true);
      }
    }
  };

  const openShare = () => {
    if (selectedObjects.length === 1) {
      let fileObject: BucketObjectItem | undefined;

      const findFunction = (currValue: BucketObjectItem) =>
        selectedObjects.includes(currValue.name);

      fileObject = filteredRecords.find(findFunction);

      if (fileObject) {
        setSelectedPreview(fileObject);
        setShareFileModalOpen(true);
      }
    }
  };

  const closeShareModal = () => {
    setShareFileModalOpen(false);
    setSelectedPreview(null);
  };

  const filteredRecords = records.filter((b: BucketObjectItem) => {
    if (searchObjects === "") {
      return true;
    } else {
      const objectName = b.name.toLowerCase();
      if (objectName.indexOf(searchObjects.toLowerCase()) >= 0) {
        return true;
      } else {
        return false;
      }
    }
  });

  const rewindCloseModal = () => {
    setRewindSelect(false);
  };

  const closePreviewWindow = () => {
    setPreviewOpen(false);
    setSelectedPreview(null);
  };

  const selectListObjects = (e: React.ChangeEvent<HTMLInputElement>) => {
    const targetD = e.target;
    const value = targetD.value;
    const checked = targetD.checked;

    let elements: string[] = [...selectedObjects]; // We clone the selectedBuckets array

    if (checked) {
      // If the user has checked this field we need to push this to selectedBucketsList
      elements.push(value);
    } else {
      // User has unchecked this field, we need to remove it from the list
      elements = elements.filter((element) => element !== value);
    }
    setSelectedObjects(elements);
    dispatch(setSelectedObjectView(null));

    return elements;
  };

  const sortChange = (sortData: any) => {
    const newSortDirection = get(sortData, "sortDirection", "DESC");
    setCurrentSortField(sortData.sortBy);
    setSortDirection(newSortDirection);
    dispatch(setLoadingObjectsList(true));
  };

  const pageTitle = decodeURLString(internalPaths);
  const currentPath = pageTitle.split("/").filter((i: string) => i !== "");

  const plSelect = filteredRecords;
  const sortASC = plSelect.sort(sortListObjects(currentSortField));

  let payload: BucketObjectItem[] = [];

  if (sortDirection === "ASC") {
    payload = sortASC;
  } else {
    payload = sortASC.reverse();
  }

  const selectAllItems = () => {
    dispatch(setSelectedObjectView(null));

    if (selectedObjects.length === payload.length) {
      setSelectedObjects([]);
      return;
    }

    const elements = payload.map((item) => item.name);
    setSelectedObjects(elements);
  };

  const downloadSelected = () => {
    if (selectedObjects.length !== 0) {
      let itemsToDownload: BucketObjectItem[] = [];

      const filterFunction = (currValue: BucketObjectItem) =>
        selectedObjects.includes(currValue.name);

      itemsToDownload = filteredRecords.filter(filterFunction);

      itemsToDownload.forEach((filteredItem) => {
        downloadObject(filteredItem);
      });
    }
  };
  let uploadPath = [bucketName];
  if (currentPath.length > 0) {
    uploadPath = uploadPath.concat(currentPath);
  }

  const onClosePanel = (forceRefresh: boolean) => {
    dispatch(setSelectedObjectView(null));
    dispatch(setVersionsModeEnabled({ status: false }));
    if (detailsOpen && selectedInternalPaths !== null) {
      // We change URL to be the contained folder

      const decodedPath = decodeURLString(internalPaths);
      const splitURLS = decodedPath.split("/");

      // We remove the last section of the URL as it should be a file
      splitURLS.pop();

      let URLItem = "";

      if (splitURLS && splitURLS.length > 0) {
        URLItem = `${splitURLS.join("/")}/`;
      }

      history.push(`/buckets/${bucketName}/browse/${encodeURLString(URLItem)}`);
    }

    dispatch(setObjectDetailsView(false));
    setSelectedObjects([]);

    if (forceRefresh) {
      dispatch(setLoadingObjectsList(true));
    }
  };

  const setDeletedAction = () => {
    dispatch(setShowDeletedObjects(!showDeleted));
    onClosePanel(true);
  };

  const tableActions: ItemActions[] = [
    {
      type: "view",
      label: "View",
      onClick: openPath,
      sendOnlyId: true,
    },
  ];

  const multiActionButtons = [
    {
      action: downloadSelected,
      label: "Download",
      disabled: selectedObjects.length === 0,
      icon: <DownloadIcon />,
      tooltip: "Download Selected",
    },
    {
      action: openShare,
      label: "Share",
      disabled: selectedObjects.length !== 1 || !canShareFile,
      icon: <ShareIcon />,
      tooltip: "Share Selected File",
    },
    {
      action: openPreview,
      label: "Preview",
      disabled: selectedObjects.length !== 1 || !canPreviewFile,
      icon: <PreviewIcon />,
      tooltip: "Preview Selected File",
    },
    {
      action: () => {
        setDeleteMultipleOpen(true);
      },
      label: "Delete",
      icon: <DeleteIcon />,
      disabled:
        !hasPermission(bucketName, [IAM_SCOPES.S3_DELETE_OBJECT]) ||
        selectedObjects.length === 0 ||
        !displayDeleteObject,
      tooltip: "Delete Selected Files",
    },
  ];

  return (
    <Fragment>
      {shareFileModalOpen && selectedPreview && (
        <ShareFile
          open={shareFileModalOpen}
          closeModalAndRefresh={closeShareModal}
          bucketName={bucketName}
          dataObject={{
            name: selectedPreview.name,
            last_modified: "",
            version_id: selectedPreview.version_id,
          }}
        />
      )}
      {deleteMultipleOpen && (
        <DeleteMultipleObjects
          deleteOpen={deleteMultipleOpen}
          selectedBucket={bucketName}
          selectedObjects={selectedObjects}
          closeDeleteModalAndRefresh={closeDeleteMultipleModalAndRefresh}
          versioning={isVersioned}
        />
      )}
      {rewindSelect && (
        <RewindEnable
          open={rewindSelect}
          closeModalAndRefresh={rewindCloseModal}
          bucketName={bucketName}
        />
      )}
      {previewOpen && (
        <PreviewFileModal
          open={previewOpen}
          bucketName={bucketName}
          object={selectedPreview}
          onClosePreview={closePreviewWindow}
        />
      )}
      <PageLayout variant={"full"}>
        <Grid item xs={12} className={classes.screenTitleContainer}>
          <ScreenTitle
            className={classes.screenTitle}
            icon={
              <span className={classes.listIcon}>
                <BucketsIcon />
              </span>
            }
            title={<span className={classes.titleSpacer}>{bucketName}</span>}
            subTitle={
              <Fragment>
                <Grid item xs={12} className={classes.bucketDetails}>
                  <span className={classes.detailsSpacer}>
                    Created:&nbsp;&nbsp;&nbsp;
                    <strong>{bucketInfo?.creation_date || ""}</strong>
                  </span>
                  <span className={classes.detailsSpacer}>
                    Access:&nbsp;&nbsp;&nbsp;
                    <strong>{bucketInfo?.access || ""}</strong>
                  </span>
                  {bucketInfo && (
                    <Fragment>
                      <span className={classes.detailsSpacer}>
                        {bucketInfo.size && (
                          <Fragment>{niceBytesInt(bucketInfo.size)}</Fragment>
                        )}
                        {bucketInfo.size && quota && (
                          <Fragment> / {niceBytesInt(quota.quota)}</Fragment>
                        )}
                        {bucketInfo.size && bucketInfo.objects ? " - " : ""}
                        {bucketInfo.objects && (
                          <Fragment>
                            {bucketInfo.objects}&nbsp;Object
                            {bucketInfo.objects && bucketInfo.objects !== 1
                              ? "s"
                              : ""}
                          </Fragment>
                        )}
                      </span>
                    </Fragment>
                  )}
                </Grid>
              </Fragment>
            }
            actions={
              <Fragment>
                <div className={classes.actionsSection}>
                  <RBIconButton
                    id={"rewind-objects-list"}
                    tooltip={"Rewind Bucket"}
                    text={"Rewind"}
                    icon={
                      <Badge
                        badgeContent=" "
                        color="secondary"
                        variant="dot"
                        invisible={!rewindEnabled}
                        className={classes.badgeOverlap}
                        sx={{ height: 16 }}
                      >
                        <HistoryIcon
                          style={{
                            minWidth: 16,
                            minHeight: 16,
                            width: 16,
                            height: 16,
                          }}
                        />
                      </Badge>
                    }
                    color="primary"
                    variant={"outlined"}
                    onClick={() => {
                      setRewindSelect(true);
                    }}
                    disabled={
                      !isVersioned ||
                      !hasPermission(bucketName, [IAM_SCOPES.S3_PUT_OBJECT])
                    }
                  />
                  <RBIconButton
                    id={"refresh-objects-list"}
                    tooltip={"Reload List"}
                    text={"Refresh"}
                    icon={<RefreshIcon />}
                    color="primary"
                    variant={"outlined"}
                    onClick={() => {
                      if (versionsMode) {
                        dispatch(setLoadingVersions(true));
                      } else {
                        dispatch(setLoadingObjectsList(true));
                      }
                    }}
                    disabled={
                      !hasPermission(bucketName, [IAM_SCOPES.S3_LIST_BUCKET]) ||
                      rewindEnabled
                    }
                  />
                  <input
                    type="file"
                    multiple
                    onChange={handleUploadButton}
                    style={{ display: "none" }}
                    ref={fileUpload}
                  />
                  <input
                    type="file"
                    multiple
                    onChange={handleUploadButton}
                    style={{ display: "none" }}
                    ref={folderUpload}
                  />
                  <UploadFilesButton
                    bucketName={bucketName}
                    uploadPath={uploadPath.join("/")}
                    uploadFileFunction={(closeMenu) => {
                      if (fileUpload && fileUpload.current) {
                        fileUpload.current.click();
                      }
                      closeMenu();
                    }}
                    uploadFolderFunction={(closeMenu) => {
                      if (folderUpload && folderUpload.current) {
                        folderUpload.current.click();
                      }
                      closeMenu();
                    }}
                  />
                </div>
              </Fragment>
            }
          />
        </Grid>
        <div
          id="object-list-wrapper"
          {...getRootProps({ style: { ...dndStyles } })}
        >
          <input {...getInputProps()} />
          <Grid
            item
            xs={12}
            className={classes.tableBlock}
            sx={{ border: "#EAEDEE 1px solid", borderTop: 0 }}
          >
            {versionsMode ? (
              <Fragment>
                {selectedInternalPaths !== null && (
                  <VersionsNavigator
                    internalPaths={selectedInternalPaths}
                    bucketName={bucketName}
                  />
                )}
              </Fragment>
            ) : (
              <SecureComponent
                scopes={[IAM_SCOPES.S3_LIST_BUCKET]}
                resource={bucketName}
                errorProps={{ disabled: true }}
              >
                <Grid item xs={12} className={classes.fullContainer}>
                  <Grid item xs={12} className={classes.breadcrumbsContainer}>
                    <BrowserBreadcrumbs
                      bucketName={bucketName}
                      internalPaths={pageTitle}
                      existingFiles={records || []}
                      additionalOptions={
                        !isVersioned || rewindEnabled ? null : (
                          <div>
                            <CheckboxWrapper
                              name={"deleted_objects"}
                              id={"showDeletedObjects"}
                              value={"deleted_on"}
                              label={"Show deleted objects"}
                              onChange={setDeletedAction}
                              checked={showDeleted}
                              overrideLabelClasses={classes.labelStyle}
                              className={classes.overrideShowDeleted}
                              noTopMargin
                            />
                          </div>
                        )
                      }
                      hidePathButton={false}
                    />
                  </Grid>
                  <TableWrapper
                    itemActions={tableActions}
                    columns={
                      rewindEnabled ? rewindModeColumns : listModeColumns
                    }
                    isLoading={loading}
                    loadingMessage={loadingMessage}
                    entityName="Objects"
                    idField="name"
                    records={payload}
                    customPaperHeight={`${classes.browsePaper} ${
                      detailsOpen ? "actionsPanelOpen" : ""
                    }`}
                    selectedItems={selectedObjects}
                    onSelect={selectListObjects}
                    customEmptyMessage={`This location is empty${
                      !rewindEnabled ? ", please try uploading a new file" : ""
                    }`}
                    sortConfig={{
                      currentSort: currentSortField,
                      currentDirection: sortDirection,
                      triggerSort: sortChange,
                    }}
                    onSelectAll={selectAllItems}
                    rowStyle={({ index }) => {
                      if (payload[index]?.delete_flag) {
                        return "deleted";
                      }

                      return "";
                    }}
                    parentClassName={classes.parentWrapper}
                  />
                </Grid>
              </SecureComponent>
            )}
            <SecureComponent
              scopes={[IAM_SCOPES.S3_LIST_BUCKET]}
              resource={bucketName}
              errorProps={{ disabled: true }}
            >
              <DetailsListPanel
                open={detailsOpen}
                closePanel={() => {
                  onClosePanel(false);
                }}
                className={`${versionsMode ? classes.hideListOnSmall : ""}`}
              >
                {selectedObjects.length > 0 && (
                  <ActionsListSection
                    items={multiActionButtons}
                    title={"Selected Objects:"}
                  />
                )}
                {selectedInternalPaths !== null && (
                  <ObjectDetailPanel
                    internalPaths={selectedInternalPaths}
                    bucketName={bucketName}
                    onClosePanel={onClosePanel}
                    versioning={isVersioned}
                    locking={lockingEnabled}
                  />
                )}
              </DetailsListPanel>
            </SecureComponent>
          </Grid>
        </div>
      </PageLayout>
    </Fragment>
  );
}