@fortawesome/free-solid-svg-icons#faBan TypeScript Examples

The following examples show how to use @fortawesome/free-solid-svg-icons#faBan. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From genshin-optimizer with MIT License 8 votes vote down vote up
export default function ArtifactInfoDisplay() {
  const { t } = useTranslation("artifact")
  return <Grid container spacing={1} >
    <Grid item xs={12} lg={5} xl={4}>
      <ImgFullwidth src={artifactcard} />
    </Grid>
    <Grid item xs={12} lg={7} xl={8}>
      <Trans t={t} i18nKey="info.section1">
        <Typography variant="h5">Substat rolls</Typography>
        <Typography gutterBottom>The <b>number of rolls</b> a substat has is shown to the left of the substat. As the number gets higher, the substat is more colorful:<Colors />.</Typography>

        <Typography variant="h5">Substat Roll Value</Typography>
        <Typography gutterBottom>The Roll Value(RV) of an subtat is a percentage of the current value over the highest potential 5<Stars stars={1} /> value. From the Image, the maximum roll value of CRIT DMG is 7.8%. In RV: <b>5.8/7.8 = 69.2%.</b></Typography>

        <Typography variant="h5">Current Roll Value vs. Maximum Roll Value</Typography>
        <Typography gutterBottom>When a 5<Stars stars={1} /> have 9(4+5) total rolls, with each of the rolls having the highest value, that is defined as a 900% RV artifact. However, most of the artifacts are not this lucky. The <b>Current RV</b> of an artifact is a percentage over that 100% artifact. The <b>Maximum RV</b> is the maximum possible RV an artifact can achieve, if the remaining artifact rolls from upgrades are the hightest possible value.</Typography>

        <Typography variant="h5">Locking an artifact</Typography>
        <Typography>By locking an artifact <FontAwesomeIcon icon={faBan} />, This artifact will not be picked up by the build generator for optimization. An equipped artifact is locked by default.</Typography>
      </Trans>
    </Grid>
    <Grid item xs={12} lg={6} xl={7} >
      <Trans t={t} i18nKey="info.section2">
        <Typography variant="h5">Artifact Editor</Typography>
        <Typography gutterBottom>A fully featured artifact editor, that can accept any 3<Stars stars={1} /> to 5<Stars stars={1} /> Artifact. When a substat is inputted, it can calculate the exact roll values. It will also make sure that you have the correct number of rolls in the artifact according to the level, along with other metrics of validation.</Typography>

        <Typography variant="h5">Scan screenshots</Typography>
        <Typography gutterBottom>Manual input is not your cup of tea? You can scan in your artifacts with screenshots! On the Artifact Editor, click the <SqBadge color="info">Show Me How!</SqBadge> button to learn more.</Typography>

        <Typography variant="h6">Automatic Artifact Scanner</Typography>
        <Typography gutterBottom>If you are playing Genshin on PC, you can download a tool that automatically scans all your artifacts for you, and you can then import that data in <FontAwesomeIcon icon={faCog} /> Database. <Link component={RouterLink} to="/scanner">Click here</Link> for a list of scanners that are compatible with GO.</Typography>

        <Typography variant="h5">Duplicate/Upgrade artifact detection</Typography>
        <Typography>Did you know GO can detect if you are adding a <b>duplicate</b> artifact that exists in the system? It can also detect if the current artifact in editor is an <b>upgrade</b> of an existing artifact as well. Once a duplicate/upgrade is detected, a preview will allow you to compare the two artifacts in question(See Image).</Typography>
      </Trans>
    </Grid>
    <Grid item xs={12} lg={6} xl={5}>
      <ImgFullwidth src={artifacteditor} />
    </Grid>
    <Grid item xs={12} lg={7} xl={6}>
      <ImgFullwidth src={artifactfilter} />
    </Grid>
    <Grid item xs={12} lg={5} xl={6}>
      <Trans t={t} i18nKey="info.section3">
        <Typography variant="h5">Artifact Inventory</Typography>
        <Typography gutterBottom>All your artifacts that you've added to GO is displayed here. The filters here allow you to further refine your view of your artifacts. </Typography>
        <Typography variant="h5">Example: Finding Fodder Artifacts</Typography>
        <Typography>By utilizing the artifact filter, and the artifact RV, you can quickly find artifacts to feed as food.</Typography>
        <Typography>In this example, the filters are set thusly: </Typography>
        <Typography component="div" >
          <ul>
            <li>Limit level to 0-8.</li>
            <li>Unlocked artifacts in Inventory.</li>
            <li>Removing the contribution of flat HP, flat DEF and Energy Recharge to RV calculations.</li>
            <li>Sorted by Ascending Max Roll Value.</li>
          </ul>
        </Typography>
        <Typography>This will filter the artifact Inventory by the lowest RV artifacts, for desired substats.</Typography>
      </Trans>
    </Grid>
  </Grid>
}
Example #2
Source File: list-editor.component.ts    From msfs-community-downloader with GNU Affero General Public License v3.0 5 votes vote down vote up
faBan = faBan;
Example #3
Source File: package-edition.component.ts    From msfs-community-downloader with GNU Affero General Public License v3.0 5 votes vote down vote up
faBan = faBan;
Example #4
Source File: ArtifactFilterDisplay.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
export default function ArtifactFilterDisplay({ filterOption, filterOptionDispatch, }: { filterOption: FilterOption, filterOptionDispatch: (any) => void }) {
  const { t } = useTranslation(["artifact", "ui"]);

  const { artSetKeys = [], mainStatKeys = [], rarity = [], slotKeys = [], levelLow, levelHigh, substats = [],
    location = "", exclusion = ["excluded", "included"], locked = ["locked", "unlocked"] } = filterOption

  return <Grid container spacing={1}>
    {/* left */}
    <Grid item xs={12} md={6} display="flex" flexDirection="column" gap={1}>
      {/* Artifact stars filter */}
      <SolidToggleButtonGroup fullWidth onChange={(e, newVal) => filterOptionDispatch({ rarity: newVal })} value={rarity} size="small">
        {allArtifactRarities.map(star => <ToggleButton key={star} value={star}><Stars stars={star} /></ToggleButton>)}
      </SolidToggleButtonGroup>
      {/* Artifact Slot */}
      <SolidToggleButtonGroup fullWidth onChange={(e, newVal) => filterOptionDispatch({ slotKeys: newVal })} value={slotKeys} size="small">
        {allSlotKeys.map(slotKey => <ToggleButton key={slotKey} value={slotKey}>{artifactSlotIcon(slotKey)}</ToggleButton>)}
      </SolidToggleButtonGroup>
      {/* exclusion + locked */}
      <Box display="flex" gap={1}>
        <SolidToggleButtonGroup fullWidth value={exclusion} onChange={(e, newVal) => filterOptionDispatch({ exclusion: newVal })} size="small">
          <ToggleButton value="excluded" sx={{ display: "flex", gap: 1 }}>
            <FontAwesomeIcon icon={faBan} /><Trans i18nKey={"exclusion.excluded"} t={t} />
          </ToggleButton>
          <ToggleButton value="included" sx={{ display: "flex", gap: 1 }}>
            <FontAwesomeIcon icon={faChartLine} /><Trans i18nKey={"exclusion.included"} t={t} />
          </ToggleButton>
        </SolidToggleButtonGroup>
        <SolidToggleButtonGroup fullWidth value={locked} onChange={(e, newVal) => filterOptionDispatch({ locked: newVal })} size="small">
          <ToggleButton value="locked" sx={{ display: "flex", gap: 1 }}>
            <Lock /><Trans i18nKey={"ui:locked"} t={t} />
          </ToggleButton>
          <ToggleButton value="unlocked" sx={{ display: "flex", gap: 1 }}>
            <LockOpen /><Trans i18nKey={"ui:unlocked"} t={t} />
          </ToggleButton>
        </SolidToggleButtonGroup>
      </Box>
      {/* Artiface level filter */}
      <ArtifactLevelSlider showLevelText levelLow={levelLow} levelHigh={levelHigh}
        setLow={levelLow => filterOptionDispatch({ levelLow })}
        setHigh={levelHigh => filterOptionDispatch({ levelHigh })}
        setBoth={(levelLow, levelHigh) => filterOptionDispatch({ levelLow, levelHigh })} />
      <Grid container display="flex" gap={1}>
        <Grid item flexGrow={1}>
          {/* location */}
          <CharacterAutocomplete
            value={location}
            onChange={location => filterOptionDispatch({ location })}
            placeholderText={t("artifact:filterLocation.any")}
            defaultText={t("artifact:filterLocation.any")}
            labelText={t("artifact:filterLocation.location")}
            showDefault
            showInventory
            showEquipped
          />
        </Grid>
      </Grid>
    </Grid>
    {/* right */}
    <Grid item xs={12} md={6} display="flex" flexDirection="column" gap={1}>
      {/* Artifact Set */}
      <ArtifactSetMultiAutocomplete artSetKeys={artSetKeys} setArtSetKeys={artSetKeys => filterOptionDispatch({ artSetKeys })} />
      <ArtifactMainStatMultiAutocomplete mainStatKeys={mainStatKeys} setMainStatKeys={mainStatKeys => filterOptionDispatch({ mainStatKeys })} />
      <ArtifactSubstatMultiAutocomplete substatKeys={substats} setSubstatKeys={substats => filterOptionDispatch({ substats })} />
    </Grid>
  </Grid>
}
Example #5
Source File: GitGithubChallenge.tsx    From frontend.ro with MIT License 4 votes vote down vote up
function GitGithubChallenge({ user }: ConnectedProps<typeof connector>) {
  const router = useRouter();
  const [lastDoneTask, setLastDoneTask] = useState(null);
  const [errorForTask, setErrorForTask] = useState<{id: string, message: string}>(null);
  const [githubUsername, setGithubUsername] = useState(null);
  const [taskIdBeingVerified, setTaskIdBeingVerified] = useState(null);

  const indexOfLastDoneTask = tasks.findIndex((task) => task.id === lastDoneTask);

  const metaRef = useRef({});

  const verifyTask = async (task: Task) => {
    setTaskIdBeingVerified(task.id);
    setErrorForTask(null);

    try {
      const { isDone, errMessage, meta } = await task.verify({
        repo: REPO,
        owner: OWNER,
        username: githubUsername,
        // meta from previous task
        meta: metaRef.current[lastDoneTask],
      });

      if (isDone) {
        metaRef.current[task.id] = meta;
        setLastDoneTask(task.id);

        // TODO: what if this fails!!!???
        await ChallengesService.putLastDoneTask(CHALLENGE_ID, task.id, metaRef.current);
      } else {
        delete metaRef.current[task.id];
        setLastDoneTask(tasks[tasks.indexOf(task) - 1]?.id);
        setErrorForTask({
          id: task.id,
          message: errMessage,
        });
      }
    } catch (err) {
      // TODO: add error directly in the task
      console.error(err);
    }

    setTaskIdBeingVerified(null);
  };

  const handleGitHubRedirect = () => {
    if (router.query.error_description) {
      const errorDescription = Array.isArray(router.query.error_description)
        ? router.query.error_description[0]
        : router.query.error_description;

      SweetAlertService.toast({
        text: errorDescription,
        type: 'error',
        timer: 4000,
      });
    }

    router.replace(router.pathname);
  };

  useEffect(handleGitHubRedirect, []);

  useEffect(() => {
    if (user.info) {
      // If user is logged in then let's get his github credentials!
      setTaskIdBeingVerified(tasks[0].id);

      UserService
        .getGithubAccount()
        .then(async (githubUser) => {
          setGithubUsername(githubUser.login);
          GitHubService.init(githubUser.access_token);

          const { lastDoneTask, meta } = await ChallengesService.getLastDoneTask(CHALLENGE_ID);
          if (lastDoneTask) {
            metaRef.current = meta || {};
            setLastDoneTask(lastDoneTask);
          } else {
            await ChallengesService.startTask(CHALLENGE_ID);
            setLastDoneTask(tasks[0].id);
          }
        })
        .catch((err) => {
          console.log('ERROR', err);
          setLastDoneTask(null);
        })
        .finally(() => setTaskIdBeingVerified(null));
    }
  }, [user.info]);

  return (
    <PageContainer>
      <h1> Git & GitHub challenge ?</h1>
      <p>
        Dacă ai ajuns la acestă pagină înseamnă că faci parte
        din grupul de Alpha Testeri care ne ajută cu feedback,
        sau ne-ai stalkuit pe repo-ul din GitHub să vezi cum
        se numesc rutele ?
      </p>
      <p>
        Mai jos găsești primul challenge interactiv al platformei noastre.
        Acesta conține challenge-uri ce se auto-validează ;)
      </p>

      {!user.info && (
      <Button variant="success" onClick={withAuthModal(!!user.info, noop)}>
        Autentifica-te ca sa incepi provocarea
      </Button>
      )}

      <List className={styles['task-list']}>
        {tasks.map((task, index) => {
          let state: TaskState = 'available';
          const isDisabled = !user.info
          || indexOfLastDoneTask < index - 1
          || indexOfLastDoneTask >= index;

          if (isDisabled) {
            state = 'disabled';
          }

          if (indexOfLastDoneTask >= index) {
            state = 'done';
          } else if (taskIdBeingVerified === task.id) {
            state = 'loading';
          } else if (errorForTask?.id === task.id) {
            state = 'error';
          }

          let icon = <FontAwesomeIcon icon={faSync} />;

          if (state === 'done') {
            icon = <FontAwesomeIcon icon={faCheck} />;
          } else if (state === 'disabled') {
            icon = <FontAwesomeIcon icon={faBan} />;
          } else if (state === 'loading') {
            icon = <FontAwesomeIcon className="rotate" icon={faSpinner} />;
          } else if (state === 'error') {
            icon = <FontAwesomeIcon icon={faTimes} />;
          }

          return (
            <li className={`${styles.task} ${styles[`task--${state}`]}`} key={task.id}>
              <Button disabled={isDisabled} onClick={() => verifyTask(task)}>
                {icon}
              </Button>
              <div>
                {task.title}
                {/* <Button
                  style={{ marginLeft: '1em' }}
                  variant={indexOfLastDoneTask >= index ? 'success' : 'blue'}
                  loading={taskIdBeingVerified === task.id}
                  disabled={isDisabled}
                  onClick={() => verifyTask(task)}
                >
                  {indexOfLastDoneTask >= index ? 'DONE' : 'DO IT'}

                </Button> */}
                {errorForTask?.id === task.id && (
                <p className={styles.task__error}>
                  {errorForTask.message}
                </p>
                )}
              </div>
            </li>
          );
        })}
      </List>

      {lastDoneTask === tasks[tasks.length - 1].id && (
        <>
          <hr />
          <h2> Hooooray! You're ALL DONE! ??? </h2>
        </>
      )}
    </PageContainer>
  );
}
Example #6
Source File: ArtifactCard.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function ArtifactCard({ artifactId, artifactObj, onClick, onDelete, mainStatAssumptionLevel = 0, effFilter = allSubstatFilter, probabilityFilter, disableEditSetSlot = false, editor = false, canExclude = false, canEquip = false, extraButtons }: Data): JSX.Element | null {
  const { t } = useTranslation(["artifact", "ui"]);
  const { database } = useContext(DatabaseContext)
  const databaseArtifact = useArtifact(artifactId)
  const sheet = usePromise(ArtifactSheet.get((artifactObj ?? databaseArtifact)?.setKey), [artifactObj, databaseArtifact])
  const equipOnChar = (charKey: CharacterKey | "") => database.setArtLocation(artifactId!, charKey)
  const editable = !artifactObj
  const [showEditor, setshowEditor] = useState(false)
  const onHideEditor = useCallback(() => setshowEditor(false), [setshowEditor])
  const onShowEditor = useCallback(() => editable && setshowEditor(true), [editable, setshowEditor])

  const wrapperFunc = useCallback(children => <CardActionArea onClick={() => artifactId && onClick?.(artifactId)} sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }} >{children}</CardActionArea>, [onClick, artifactId],)
  const falseWrapperFunc = useCallback(children => <Box sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }} >{children}</Box>, [])

  const art = artifactObj ?? databaseArtifact
  if (!art) return null

  const { id, lock, slotKey, rarity, level, mainStatKey, substats, exclude, location = "" } = art
  const mainStatLevel = Math.max(Math.min(mainStatAssumptionLevel, rarity * 4), level)
  const mainStatUnit = KeyMap.unit(mainStatKey)
  const levelVariant = "roll" + (Math.floor(Math.max(level, 0) / 4) + 1)
  const { currentEfficiency, maxEfficiency } = Artifact.getArtifactEfficiency(art, effFilter)
  const artifactValid = maxEfficiency !== 0
  const slotName = sheet?.getSlotName(slotKey) || "Unknown Piece Name"
  const slotDesc = sheet?.getSlotDesc(slotKey)
  const slotDescTooltip = slotDesc && <InfoTooltip title={<Box>
    <Typography variant='h6'>{slotName}</Typography>
    <Typography>{slotDesc}</Typography>
  </Box>} />
  const setEffects = sheet?.setEffects
  const setDescTooltip = sheet && setEffects && <InfoTooltip title={
    <span>
      {Object.keys(setEffects).map(setNumKey => <span key={setNumKey}>
        <Typography variant="h6"><SqBadge color="success">{t(`artifact:setEffectNum`, { setNum: setNumKey })}</SqBadge></Typography>
        <Typography>{sheet.setEffectDesc(setNumKey as any)}</Typography>
      </span>)}
    </span>
  } />
  return <Suspense fallback={<Skeleton variant="rectangular" sx={{ width: "100%", height: "100%", minHeight: 350 }} />}>
    {editor && <Suspense fallback={false}>
      <ArtifactEditor
        artifactIdToEdit={showEditor ? artifactId : ""}
        cancelEdit={onHideEditor}
        disableEditSetSlot={disableEditSetSlot}
      />
    </Suspense>}
    <CardLight sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
      <ConditionalWrapper condition={!!onClick} wrapper={wrapperFunc} falseWrapper={falseWrapperFunc}>
        <Box className={`grad-${rarity}star`} sx={{ position: "relative", width: "100%" }}>
          {!onClick && <IconButton color="primary" disabled={!editable} onClick={() => database.updateArt({ lock: !lock }, id)} sx={{ position: "absolute", right: 0, bottom: 0, zIndex: 2 }}>
            {lock ? <Lock /> : <LockOpen />}
          </IconButton>}
          <Box sx={{ pt: 2, px: 2, position: "relative", zIndex: 1 }}>
            {/* header */}
            <Box component="div" sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1 }}>
              <Chip size="small" label={<strong>{` +${level}`}</strong>} color={levelVariant as any} />
              <Typography component="span" noWrap sx={{ backgroundColor: "rgba(100,100,100,0.35)", borderRadius: "1em", px: 1 }}><strong>{slotName}</strong></Typography>
              <Box flexGrow={1} sx={{ textAlign: "right" }}>
                {slotDescTooltip}
              </Box>
            </Box>
            <Typography color="text.secondary" variant="body2">
              <SlotNameWithIcon slotKey={slotKey} />
            </Typography>
            <Typography variant="h6" color={`${KeyMap.getVariant(mainStatKey)}.main`}>
              <span>{StatIcon[mainStatKey]} {KeyMap.get(mainStatKey)}</span>
            </Typography>
            <Typography variant="h5">
              <strong>
                <ColorText color={mainStatLevel !== level ? "warning" : undefined}>{cacheValueString(Artifact.mainStatValue(mainStatKey, rarity, mainStatLevel) ?? 0, KeyMap.unit(mainStatKey))}{mainStatUnit}</ColorText>
              </strong>
            </Typography>
            <Stars stars={rarity} colored />
            {/* {process.env.NODE_ENV === "development" && <Typography color="common.black">{id || `""`} </Typography>} */}
          </Box>
          <Box sx={{ height: "100%", position: "absolute", right: 0, top: 0 }}>
            <Box
              component="img"
              src={sheet?.slotIcons[slotKey] ?? ""}
              width="auto"
              height="100%"
              sx={{ float: "right" }}
            />
          </Box>
        </Box>
        <CardContent sx={{ flexGrow: 1, display: "flex", flexDirection: "column", pt: 1, pb: 0, width: "100%" }}>
          {substats.map((stat: ICachedSubstat) => <SubstatDisplay key={stat.key} stat={stat} effFilter={effFilter} rarity={rarity} />)}
          <Box sx={{ display: "flex", my: 1 }}>
            <Typography color="text.secondary" component="span" variant="caption" sx={{ flexGrow: 1 }}>{t`artifact:editor.curSubEff`}</Typography>
            <PercentBadge value={currentEfficiency} max={900} valid={artifactValid} />
          </Box>
          {currentEfficiency !== maxEfficiency && <Box sx={{ display: "flex", mb: 1 }}>
            <Typography color="text.secondary" component="span" variant="caption" sx={{ flexGrow: 1 }}>{t`artifact:editor.maxSubEff`}</Typography>
            <PercentBadge value={maxEfficiency} max={900} valid={artifactValid} />
          </Box>}
          <Box flexGrow={1} />
          {probabilityFilter && <strong>Probability: {(probability(art, probabilityFilter) * 100).toFixed(2)}%</strong>}
          <Typography color="success.main">{sheet?.name ?? "Artifact Set"} {setDescTooltip}</Typography>
        </CardContent>
      </ConditionalWrapper>
      <Box sx={{ p: 1, display: "flex", gap: 1, justifyContent: "space-between", alignItems: "center" }}>
        {editable && canEquip
          ? <CharacterAutocomplete sx={{ flexGrow: 1 }} size="small" showDefault
            defaultIcon={<BusinessCenter />} defaultText={t("ui:inventory")}
            value={location} onChange={equipOnChar} />
          : <LocationName location={location} />}
        {editable && <ButtonGroup sx={{ height: "100%" }}>
          {editor && <Tooltip title={<Typography>{t`artifact:edit`}</Typography>} placement="top" arrow>
            <Button color="info" size="small" onClick={onShowEditor} >
              <FontAwesomeIcon icon={faEdit} className="fa-fw" />
            </Button>
          </Tooltip>}
          {canExclude && <Tooltip title={<Typography>{t`artifact:excludeArtifactTip`}</Typography>} placement="top" arrow>
            <Button onClick={() => database.updateArt({ exclude: !exclude }, id)} color={exclude ? "error" : "success"} size="small" >
              <FontAwesomeIcon icon={exclude ? faBan : faChartLine} className="fa-fw" />
            </Button>
          </Tooltip>}
          {!!onDelete && <Button color="error" size="small" onClick={() => onDelete(id)} disabled={lock}>
            <FontAwesomeIcon icon={faTrashAlt} className="fa-fw" />
          </Button>}
          {extraButtons}
        </ButtonGroup>}
      </Box>
    </CardLight >
  </Suspense>
}
Example #7
Source File: ArtifactFilter.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export function ArtifactRedButtons({ artifactIds, filterOption }:
  { artifactIds: string[], filterOption: FilterOption }) {
  const { t } = useTranslation(["artifact", "ui"]);
  const { database } = useContext(DatabaseContext)
  const { numDelete, numUnequip, numExclude, numInclude, numUnlock, numLock } = useMemo(() => {
    const artifacts = artifactIds.map(id => database._getArt(id)) as ICachedArtifact[]
    const numUnlock = artifacts.reduce((a, art) => a + (art.lock ? 0 : 1), 0)
    const numLock = artifacts.length - numUnlock
    const numDelete = numUnlock
    const numUnequip = artifacts.reduce((a, art) => a + (art.location ? 1 : 0), 0)
    const numExclude = artifacts.reduce((a, art) => a + (art.exclude ? 1 : 0), 0)
    const numInclude = artifacts.length - numExclude

    return { numDelete, numUnequip, numExclude, numInclude, numUnlock, numLock }
  }, [artifactIds, database])

  const unequipArtifacts = () =>
    window.confirm(`Are you sure you want to unequip ${numUnequip} artifacts currently equipped on characters?`) &&
    artifactIds.map(id => database.setArtLocation(id, ""))

  const deleteArtifacts = () =>
    window.confirm(`Are you sure you want to delete ${numDelete} artifacts?`) &&
    artifactIds.map(id => !database._getArt(id)?.lock && database.removeArt(id))

  const excludeArtifacts = () =>
    window.confirm(`Are you sure you want to exclude ${numInclude} artifacts from build generations?`) &&
    artifactIds.map(id => database.updateArt({ exclude: true }, id))

  const includeArtifacts = () =>
    window.confirm(`Are you sure you want to include ${numExclude} artifacts in build generations?`) &&
    artifactIds.map(id => database.updateArt({ exclude: false }, id))

  const lockArtifacts = () =>
    window.confirm(`Are you sure you want to lock ${numUnlock} artifacts?`) &&
    artifactIds.map(id => database.updateArt({ lock: true }, id))

  const unlockArtifacts = () =>
    window.confirm(`Are you sure you want to unlock ${numLock} artifacts?`) &&
    artifactIds.map(id => database.updateArt({ lock: false }, id))

  return <Grid container spacing={1} alignItems="center">
    <Grid item xs={12} sm={6} md={3}>
      <Button fullWidth color="error" disabled={!numUnequip} onClick={unequipArtifacts} startIcon={<FontAwesomeIcon icon={faUserSlash} />}>
        <Trans t={t} i18nKey="button.unequipArtifacts" >Unequip Artifacts</Trans>
        <SqBadge sx={{ ml: 1 }} color={numUnequip ? "success" : "secondary"}>{numUnequip}</SqBadge>
      </Button>
    </Grid>
    <Grid item xs={12} sm={6} md={3}>
      <Button fullWidth color="error" disabled={!numDelete} onClick={deleteArtifacts} startIcon={<FontAwesomeIcon icon={faTrash} />}>
        <Trans t={t} i18nKey="button.deleteArtifacts" >Delete Artifacts</Trans>
        <SqBadge sx={{ ml: 1 }} color={numDelete ? "success" : "secondary"}>{numDelete}</SqBadge>
      </Button>
    </Grid>
    <Grid item xs={12} sm={6} md={3}>
      <Button fullWidth color="error" disabled={!numInclude} onClick={excludeArtifacts} startIcon={<FontAwesomeIcon icon={faBan} />}>
        <Trans t={t} i18nKey="button.excludeArtifacts" >Exclude Artifacts</Trans>
        <SqBadge sx={{ ml: 1 }} color={numInclude ? "success" : "secondary"}>{numInclude}</SqBadge>
      </Button>
    </Grid>
    <Grid item xs={12} sm={6} md={3}>
      <Button fullWidth color="error" disabled={!numExclude} onClick={includeArtifacts} startIcon={<FontAwesomeIcon icon={faChartLine} />}>
        <Trans t={t} i18nKey="button.includeArtifacts" >Include Artifacts</Trans>
        <SqBadge sx={{ ml: 1 }} color={numExclude ? "success" : "secondary"}>{numExclude}</SqBadge>
      </Button>
    </Grid>
    <Grid item xs={12} sm={6} md={3}>
      <Button fullWidth color="error" disabled={!numLock} onClick={unlockArtifacts} startIcon={<LockOpen />}>
        <Trans t={t} i18nKey="button.unlockrtifacts" >Unlock Artifacts</Trans>
        <SqBadge sx={{ ml: 1 }} color={numLock ? "success" : "secondary"}>{numLock}</SqBadge>
      </Button>
    </Grid>
    <Grid item xs={12} sm={6} md={3}>
      <Button fullWidth color="error" disabled={!numUnlock} onClick={lockArtifacts} startIcon={<Lock />}>
        <Trans t={t} i18nKey="button.lockArtifacts" >Lock Artifacts</Trans>
        <SqBadge sx={{ ml: 1 }} color={numUnlock ? "success" : "secondary"}>{numUnlock}</SqBadge>
      </Button>
    </Grid>
    <Grid item xs={12} sm={12} md={6} display="flex" justifyContent="space-around">
      <Typography variant="caption" color="text.secondary"><Trans t={t} i18nKey="buttonHint">Note: the red buttons above only applies to <b>currently filtered artifacts</b></Trans></Typography>
    </Grid>
  </Grid>
}