@mui/icons-material#HelpOutline TypeScript Examples

The following examples show how to use @mui/icons-material#HelpOutline. 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: AccountTransactionListEntry.tsx    From abrechnung with GNU Affero General Public License v3.0 5 votes vote down vote up
export default function AccountTransactionListEntry({ group, transaction, accountID }) {
    return (
        <ListItemLink to={`/groups/${group.id}/transactions/${transaction.id}`}>
            <ListItemAvatar sx={{ minWidth: { xs: "40px", md: "56px" } }}>
                {transaction.type === "purchase" ? (
                    <Tooltip title="Purchase">
                        <PurchaseIcon color="primary" />
                    </Tooltip>
                ) : transaction.type === "transfer" ? (
                    <Tooltip title="Money Transfer">
                        <TransferIcon color="primary" />
                    </Tooltip>
                ) : (
                    <Tooltip title="Unknown Transaction Type">
                        <HelpOutline color="primary" />
                    </Tooltip>
                )}
            </ListItemAvatar>
            <ListItemText
                primary={
                    <>
                        {transaction.is_wip && (
                            <Chip color="info" variant="outlined" label="WIP" size="small" sx={{ mr: 3 }} />
                        )}
                        <Typography variant="body1" component="span">
                            {transaction.description}
                        </Typography>
                    </>
                }
                secondary={DateTime.fromISO(transaction.billed_at).toLocaleString(DateTime.DATE_FULL)}
            />
            <ListItemText>
                <Typography align="right" variant="body2">
                    <Typography
                        component="span"
                        sx={{ color: (theme) => balanceColor(transaction.account_balances[accountID].total, theme) }}
                    >
                        {transaction.account_balances[accountID].total.toFixed(2)} {group.currency_symbol}
                    </Typography>
                    <br />
                    <Typography component="span" sx={{ typography: "body2", color: "text.secondary" }}>
                        last changed:{" "}
                        {DateTime.fromISO(transaction.last_changed).toLocaleString(DateTime.DATETIME_FULL)}
                    </Typography>
                </Typography>
            </ListItemText>
        </ListItemLink>
    );
}
Example #2
Source File: TransactionListEntry.tsx    From abrechnung with GNU Affero General Public License v3.0 5 votes vote down vote up
export function TransactionListEntry({ group, transaction }) {
    const accounts = useRecoilValue(accountsSeenByUser(group.id));
    const accountNamesFromShares = (shares) => {
        return shares.map((s) => accounts.find((a) => a.id === parseInt(s))?.name).join(", ");
    };

    return (
        <>
            <ListItemLink to={`/groups/${group.id}/transactions/${transaction.id}`}>
                <ListItemAvatar sx={{ minWidth: { xs: "40px", md: "56px" } }}>
                    {transaction.type === "purchase" ? (
                        <Tooltip title="Purchase">
                            <PurchaseIcon color="primary" />
                        </Tooltip>
                    ) : transaction.type === "transfer" ? (
                        <Tooltip title="Money Transfer">
                            <TransferIcon color="primary" />
                        </Tooltip>
                    ) : (
                        <Tooltip title="Unknown Transaction Type">
                            <HelpOutline color="primary" />
                        </Tooltip>
                    )}
                </ListItemAvatar>
                <ListItemText
                    primary={
                        <>
                            {transaction.is_wip && (
                                <Chip color="info" variant="outlined" label="WIP" size="small" sx={{ mr: 1 }} />
                            )}
                            <Typography variant="body1" component="span">
                                {transaction.description}
                            </Typography>
                        </>
                    }
                    secondary={
                        <>
                            <Typography variant="body2" component="span" sx={{ color: "text.primary" }}>
                                by {accountNamesFromShares(Object.keys(transaction.creditor_shares))}, for{" "}
                                {accountNamesFromShares(Object.keys(transaction.debitor_shares))}
                            </Typography>
                            <br />
                            {DateTime.fromISO(transaction.billed_at).toLocaleString(DateTime.DATE_FULL)}
                        </>
                    }
                />
                <ListItemText>
                    <Typography align="right" variant="body2">
                        {transaction.value.toFixed(2)} {transaction.currency_symbol}
                        <br />
                        <Typography component="span" sx={{ typography: "body2", color: "text.secondary" }}>
                            last changed:{" "}
                            {DateTime.fromISO(transaction.last_changed).toLocaleString(DateTime.DATETIME_FULL)}
                        </Typography>
                    </Typography>
                </ListItemText>
            </ListItemLink>
            <Divider sx={{ display: { lg: "none" } }} component="li" />
        </>
    );
}
Example #3
Source File: Affinity.tsx    From your_spotify with GNU General Public License v3.0 4 votes vote down vote up
export default function Affinity() {
  const navigate = useNavigateAndSearch();
  const user = useSelector(selectUser);
  const [ids, setIds] = useState<Set<string>>(new Set());
  const [mode, setMode] = useState(CollaborativeMode.MINIMA);
  const [statType, setStatType] = useState('songs');
  const [dataInterval, setDataInterval] = useState<IntervalDetail>(presetIntervals[1]);
  const accounts = useSelector(selectAccounts);

  const add = useCallback(
    (account: AdminAccount) => {
      const newSet = new Set(ids);
      if (newSet.has(account.id)) {
        newSet.delete(account.id);
      } else {
        newSet.add(account.id);
      }
      setIds(newSet);
    },
    [ids],
  );

  const compute = useCallback(() => {
    navigate(`/collaborative/top/${statType}/${mode}`, {
      ids: Array.from(ids).join(','),
      ...detailIntervalToQuery(dataInterval, AFFINITY_PREFIX),
    });
  }, [navigate, statType, mode, ids, dataInterval]);

  return (
    <div className={s.root}>
      <div>
        <Text element="h1" className={s.title}>
          Affinity{' '}
          <Tooltip
            title={
              <div>
                <p>
                  The affinity represents the probability the user like the same songs. The affinity
                  feature comes with two <strong>modes</strong>:
                </p>
                <ul>
                  <li>
                    <strong>Average</strong>: bases the ranking on the average of the proportion
                    each people listening to a specific element. If A listens to a song 50% of his
                    time, B 25% and C 0%, the average will be 25%, thus ranking higher than A 12%, B
                    12% and C 12%.
                  </li>
                  <li>
                    <strong>Minima</strong>: bases the ranking on the minimal proportion of each
                    people listening to a specific element. If A listens to a song 50% of his time,
                    B 25% and C 0%, the minima will be 0%, thus ranking lower than A 100% B 5% and C
                    1%.
                  </li>
                </ul>
                <p>
                  Average can mean that the top songs will satisfy a lot some people while minima
                  means that the top songs will be known by everyone but not enjoyed as much for
                  everyone.
                </p>
              </div>
            }>
            <HelpOutline className={s.question} />
          </Tooltip>
        </Text>
        <div className={s.accountselection}>
          <Text element="h2" className={s.section}>
            Users
          </Text>
          {accounts.map((account) => (
            <button
              type="button"
              key={account.id}
              className={s.account}
              onClick={() => add(account)}>
              <Text>{account.username}</Text>
              <Checkbox
                checked={ids.has(account.id) || account.id === user?._id}
                disabled={account.id === user?._id}
                disableRipple
                disableTouchRipple
                disableFocusRipple
              />
            </button>
          ))}
        </div>
        <div className={s.modeselection}>
          <Text element="h2" className={s.section}>
            Mode
          </Text>
          <Select
            variant="standard"
            value={mode}
            onChange={(ev) => setMode(ev.target.value as CollaborativeMode)}>
            <MenuItem value={CollaborativeMode.MINIMA}>Minima</MenuItem>
            <MenuItem value={CollaborativeMode.AVERAGE}>Average</MenuItem>
          </Select>
        </div>
        <div className={s.typeselection}>
          <Text element="h2" className={s.section}>
            Type
          </Text>
          <Select
            variant="standard"
            value={statType}
            onChange={(ev) => setStatType(ev.target.value)}>
            <MenuItem value="songs">Songs</MenuItem>
            <MenuItem value="albums">Albums</MenuItem>
            <MenuItem value="artists">Artists</MenuItem>
          </Select>
        </div>
        <div className={s.timeselection}>
          <Text element="h2" className={s.section}>
            Interval
          </Text>
          <IntervalSelector
            forceTiny
            value={dataInterval}
            onChange={setDataInterval}
            selectType="standard"
          />
        </div>
        <Button onClick={compute} variant="contained" disabled={ids.size === 0}>
          Calculate affinity
        </Button>
      </div>
    </div>
  );
}
Example #4
Source File: ItemViewer.tsx    From NekoMaid with MIT License 4 votes vote down vote up
ItemViewer: React.FC<ItemViewerProps> = ({ item, data, onDrag, onDrop, onEdit, onClick, ...props }) => {
  const globalData = useGlobalData()
  const lowerCase = item ? item.type.toLowerCase() : ''
  const type = item ? item.icon || lowerCase : ''
  const hasEnchants = item?.hasEnchants && type in icons
  const nbt: NBT | null = item?.nbt ? parse(item.nbt) as any as NBT : null
  const elm = <Paper
    {...props}
    onDragOver={globalData.hasNBTAPI && onDrop
      ? e => {
        e.preventDefault()
        e.dataTransfer.dropEffect = 'move'
      }
      : undefined}
    onDrop={globalData.hasNBTAPI && onDrop
      ? e => {
        e.preventDefault()
        const obj = JSON.parse(e.dataTransfer.getData('application/json'))
        if (obj.item) onDrop(obj.item, obj.data)
      }
      : undefined}
    onClick={onClick || (globalData.hasNBTAPI && onEdit
      ? () => openItemEditor(item).then(onEdit)
      : undefined)}
    sx={{
      width: '40px',
      height: '40px',
      display: 'inline-block',
      margin: 0.5,
      position: 'relative',
      overflow: 'hidden',
      userSelect: 'none',
      cursor: globalData.hasNBTAPI && (onEdit || onDrag) ? 'pointer' : undefined,
      backgroundColor: theme => theme.palette.mode === 'dark' ? 'rgba(255,255,255,.06)' : 'rgba(0,0,0,.06)',
      '& span': {
        position: 'absolute',
        right: 2,
        bottom: -5,
        pointerEvents: 'none',
        textShadow: theme => theme.palette.mode === 'light'
          ? '#fff 1px 0 0, #fff 0 1px 0, #fff -1px 0 0, #fff 0 -1px 0'
          : '#000 1px 0 0, #000 0 1px 0, #000 -1px 0 0, #000 0 -1px 0'
      }
    }}
  >
    {item && <div
      onMouseDown={() => window.getSelection()?.removeAllRanges()}
      draggable={!!onDrag}
      onDragStart={onDrag
        ? e => {
          e.dataTransfer.effectAllowed = 'copyMove'
          e.dataTransfer.setData('application/json', JSON.stringify({ item, data }))
          onDrag(data)
        }
        : undefined}
      style={{
        position: 'absolute',
        top: 0,
        right: 0,
        left: 0,
        bottom: 0,
        backgroundSize: 'cover',
        imageRendering: 'pixelated',
        filter: hasEnchants ? 'brightness(1.5)' : undefined,
        WebkitMaskSize: 'cover',
        maskImage: !hasEnchants && type in icons ? `url(/icons/minecraft/${type}.png)` : undefined,
        WebkitMaskImage: !hasEnchants && type in icons ? `url(/icons/minecraft/${type}.png)` : undefined,
        backgroundImage: item && type in icons ? `url(/icons/minecraft/${type}.png)` : undefined
      }}
    >
      {item && (item.type === 'PLAYER_HEAD' && nbt?.tag?.SkullOwner?.Id
        ? <img
          crossOrigin='anonymous'
          src={`https://mc-heads.net/head/${nbt.tag.SkullOwner.Id.reduce((s, it) => s + (it >>> 0).toString(16), '')}/30`}
        />
        : !(type in icons) && type !== 'air' && <HelpOutline sx={{ position: 'absolute', left: 8, top: 8 }} />)}
      {hasEnchants && type !== 'air' && <div style={{
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        opacity: 0.5,
        WebkitMaskSize: 'cover',
        filter: 'blur(1px) brightness(1.7)',
        maskImage: `url(/icons/minecraft/${type}.png)`,
        WebkitMaskImage: `url(/icons/minecraft/${type}.png)`,
        animation: 'enchants-animation 6s infinite linear',
        backgroundPositionY: 128,
        backgroundImage: 'url(/icons/minecraft/enchanted_item_glint.png)'
      }} />}
    </div>}
    {item && item.amount && item.amount > 1 ? <span>{item.amount}</span> : null}
  </Paper>
  const nbtTexts = nbt
    ? <>
      {nbt.tag?.display?.Lore?.map((it, i) => <React.Fragment key={i}>{parseComponent(JSON.parse(it))}<br /></React.Fragment>)}
      {nbt.tag?.Enchantments?.length
        ? nbt.tag?.Enchantments.map((it, i) => <React.Fragment key={i}><br />{getEnchantmentName(it)}</React.Fragment>)
        : null}
      {nbt.tag?.Unbreakable?.value === 1 && <><br />{minecraft['item.unbreakable']}</>}
    </>
    : null
  return item
    ? <Tooltip title={<>
      <h3 style={{ margin: 0 }}>{nbt?.tag?.display?.Name
        ? parseComponent(JSON.parse(nbt.tag.display.Name))
        : item.name ? parseComponent(item.name) : getName(lowerCase)}</h3>
      {nbtTexts}
    </>}>{elm}</Tooltip>
    : elm
}
Example #5
Source File: Config.tsx    From NekoMaid with MIT License 4 votes vote down vote up
configs.push({
  title: lang.config.serverConfig,
  component () {
    const plugin = usePlugin()
    const globalData = useGlobalData()
    const [flag, update] = useState(0)
    const [info, setInfo] = useState<Record<string, string>>({ })
    const [open, setOpen] = useState(false)
    const [canGetData, setCanGetData] = useState(true)
    const [loading, setLoading] = useState(false)
    const setValue = (field: string, value: any, isGlobal = true) => {
      plugin.emit('server:set', field, value)
      success()
      if (isGlobal) {
        (globalData as any)[field] = value
        update(flag + 1)
        location.reload()
      }
    }
    const createEditButtom = (field: string, isGlobal?: boolean, isInt = true) => <IconButton
      onClick={() => dialog(
        {
          content: lang.inputValue,
          input: isInt
            ? {
                error: true,
                type: 'number',
                helperText: lang.invalidValue,
                validator: (it: string) => /^\d+$/.test(it) && +it >= 0
              }
            : { }
        }).then(res => res != null && setValue(field, isInt ? parseInt(res as any) : (res || null), isGlobal))}
    ><Edit /></IconButton>

    const infoElm: JSX.Element[] = []
    for (const key in info) {
      const name = (lang.config as any)[key]
      infoElm.push(<ListItem key={key} sx={{ pl: 4 }}>
        <ListItemText
          primary={key === 'isAikarFlags' ? <Link href='https://mcflags.emc.gs' target='_blank' rel='noopener'>{name}</Link> : name}
          secondary={info[key].toString()}
        />
      </ListItem>)
    }

    return <List>
      <CircularLoading loading={loading} />
      <ListItem secondaryAction={globalData.canSetMaxPlayers
        ? createEditButtom('maxPlayers')
        : undefined}>
        <ListItemText primary={lang.config.maxPlayers + ': ' + globalData.maxPlayers} />
      </ListItem>
      <ListItem secondaryAction={createEditButtom('spawnRadius')}>
        <ListItemText primary={lang.config.spawnRadius + ': ' + globalData.spawnRadius} />
      </ListItem>
      <ListItem secondaryAction={createEditButtom('motd', false, false)}>
        <ListItemText primary={lang.config.motd} />
      </ListItem>
      <ListItem secondaryAction={<Switch checked={globalData.hasWhitelist} onChange={e => setValue('hasWhitelist', e.target.checked)} />}>
        <ListItemText primary={lang.config.whitelist} />
      </ListItem>
      {canGetData && <>
        <ListItemButton onClick={() => {
          if (infoElm.length) setOpen(!open)
          else {
            setLoading(true)
            plugin.emit('server:fetchInfo', (data: any) => {
              setLoading(false)
              if (!data) {
                failed(lang.unsupported)
                setCanGetData(false)
                return
              }
              setInfo(data)
              setOpen(true)
            })
          }
        }}>
        <ListItemIcon><Equalizer /></ListItemIcon>
          <ListItemText primary={lang.info} />
          {open ? <ExpandLess /> : <ExpandMore />}
        </ListItemButton>
        <Collapse in={open} timeout='auto' unmountOnExit>
          <List component='div' dense disablePadding>{infoElm}</List>
        </Collapse>
      </>}
    </List>
  }
},
{
  title: lang.history,
  component () {
    const [cur, update] = useState(0)
    const list: ServerRecord[] = JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')
    return <List>
      {list.sort((a, b) => b.time - a.time).map(it => {
        const i = it.address.indexOf('?')
        return <ListItem
          disablePadding
          key={it.address}
          secondaryAction={<IconButton edge='end' size='small' onClick={() => {
            localStorage.setItem('NekoMaid:servers', JSON.stringify(list.filter(s => s.address !== it.address)))
            success()
            update(cur + 1)
          }}><Delete /></IconButton>}
        >
          <ListItemButton onClick={() => {
            location.hash = ''
            location.search = it.address
          }} dense>
            <ListItemAvatar><Avatar src={it.icon} variant='rounded'><HelpOutline /></Avatar></ListItemAvatar>
            <ListItemText primary={<Tooltip title={it.address.slice(i + 1)}>
              <span>{it.address.slice(0, i)}</span></Tooltip>} secondary={dayjs(it.time).fromNow()} />
          </ListItemButton>
        </ListItem>
      })}
    </List>
  }
},
{
  title: lang.config.theme,
  component () {
    const color = localStorage.getItem('NekoMaid:color') || 'blue'
    return <CardContent sx={{ textAlign: 'center' }}>
      <Box>
        <ToggleButtonGroup exclusive value={localStorage.getItem('NekoMaid:colorMode') || ''} onChange={(_, it) => {
          localStorage.setItem('NekoMaid:colorMode', it)
          location.reload()
        }}>
          <ToggleButton value='light'><Brightness7 /> {lang.config.light}</ToggleButton>
          <ToggleButton value=''><SettingsBrightness /> {lang.config.system}</ToggleButton>
          <ToggleButton value='dark'><Brightness4 /> {lang.config.dark}</ToggleButton>
        </ToggleButtonGroup>
      </Box>
      <Paper sx={{ marginTop: 2, width: '176px', overflow: 'hidden', display: 'inline-block' }}>
        {Object.keys(colors).slice(1, 17).map((key, i) => {
          const checked = color === key
          const elm = <Box
            key={key}
            onClick={() => {
              localStorage.setItem('NekoMaid:color', key)
              location.reload()
            }}
            sx={{
              backgroundColor: (colors as any)[key][600],
              width: '44px',
              height: '44px',
              display: 'inline-block',
              cursor: 'pointer'
            }}
          ><Check htmlColor='white' sx={{ top: '10px', position: 'relative', opacity: checked ? 1 : 0 }} /></Box>
          return (i + 1) % 4 === 0 ? <React.Fragment key={key}>{elm}<br /></React.Fragment> : elm
        })}
      </Paper>
    </CardContent>
  }
})