react-icons/fi#FiX TypeScript Examples

The following examples show how to use react-icons/fi#FiX. 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 dxvote with GNU Affero General Public License v3.0 6 votes vote down vote up
CloseIcon = styled(FiX)`
  color: ${({ theme }) => theme.colors.text};
  height: 1.5rem;
  width: 1.5rem;

  &:hover {
    cursor: pointer;
    opacity: 0.6;
  }
`
Example #2
Source File: MobileFilters.tsx    From po8klasie with GNU General Public License v3.0 6 votes vote down vote up
MobileFilters: FC<MobileFiltersProps> = ({ onFiltersChange, filtersValues}) => {
  let [isOpen, setIsOpen] = useState(false)
  const { searchView } = useProjectConfig();
  const { filters: filtersConfig } = searchView as SearchViewConfig;
  return (
    <>
      <button
        className="rounded-xl border border-light px-3 py-1 mx-2 flex items-center md:hidden"
        onClick={() => setIsOpen(!isOpen)}>
        <BiFilterAlt className="mr-2" />
        Filtry
      </button>
      <Dialog open={isOpen} onClose={() => setIsOpen(false)}>
        <Dialog.Panel className="top-0 left-0 h-full w-full fixed z-40 bg-appBg pt-navbarHeight">
          <div className="flex items-center justify-end">
            <button className="p-2" onClick={() => setIsOpen(false)}>
              <FiX className="text-xl" />
            </button>
          </div>
          {filtersConfig.map(({ options, key, component, displayInRowOnMobile }) => {
            const FilterComponent = mobileFiltersComponents[component as keyof typeof mobileFiltersComponents];
            if (displayInRowOnMobile) return null;
            return (
              <FilterComponent
                options={options}
                onChange={onFiltersChange(key)}
                value={filtersValues[key]}
              />
            );
          })}
        </Dialog.Panel>
      </Dialog>
    </>
  )
}
Example #3
Source File: index.tsx    From dxvote with GNU Affero General Public License v3.0 6 votes vote down vote up
CloseIcon = styled(FiX)`
  position: absolute;
  color: ${({ theme }) => theme.colors.text};
  right: 1.5rem;
  top: 50%;
  transform: translateY(-50%);
  height: 1.5rem;
  width: 1.5rem;
  z-index: 800;

  &:hover {
    cursor: pointer;
    opacity: 0.6;
  }
`
Example #4
Source File: BetaBanner.tsx    From po8klasie with GNU General Public License v3.0 6 votes vote down vote up
BetaBanner = () => {
  const shouldBannerBeShownInitially =
    typeof window !== 'undefined'
      ? localStorage.getItem(BANNER_LOCAL_STORAGE_KEY) !== 'true'
      : false;
  const [shouldBannerBeShown, setShouldBannerBeShown] = useState(shouldBannerBeShownInitially);

  const closeBanner = () => {
    setShouldBannerBeShown(false);
    localStorage.setItem(BANNER_LOCAL_STORAGE_KEY, 'true');
  };

  if (!shouldBannerBeShown) return null;

  return (
    <div className="fixed bottom-0 w-full">
      <div className="w-container mb-5 w-container mx-auto">
        <div className="relative bg-primaryBg backdrop-filter backdrop-blur-2xl bg-opacity-70 border-2 rounded border-primary text-primary px-5 py-2">
          <button className="absolute right-2 top-2" onClick={closeBanner}>
            <FiX />
          </button>
          <h4 className="font-bold text-lg">Aplikacja w fazie beta</h4>
          <p>
            Nie wszystkie funkcje serwisu mogą działać poprawnie. Jeśli zauważysz błąd w działaniu
            aplikacji lub chcesz podzielić się sugestią,{' '}
            <Link href="/#contact-us">
              <a className="underline">skontaktuj siÄ™ z nami</a>
            </Link>
            .
          </p>
        </div>
      </div>
    </div>
  );
}
Example #5
Source File: index.tsx    From tobira with Apache License 2.0 6 votes vote down vote up
OpenMenuMode: React.FC = () => {
    const { t } = useTranslation();
    const menu = useMenu();

    return <>
        <Logo />
        <ButtonContainer>
            <ActionIcon title={t("close")} onClick={() => menu.close()}>
                <FiX />
            </ActionIcon>
        </ButtonContainer>
    </>;
}
Example #6
Source File: Navbar.tsx    From po8klasie with GNU General Public License v3.0 5 votes vote down vote up
Navbar: FC<NavbarProps> = ({ navbarWrapperClassName, projectsList }) => {
  const [shouldNavbarHaveBackground, setShouldNavbarHaveBackground] = useState(false);
  const [isNavbarCollapsed, setNavbarCollapsed] = useState(true);

  const { t } = useTranslation('landing');
  useEffect(() => {
    const handleScroll = () => setShouldNavbarHaveBackground(window.scrollY > 10);
    document.addEventListener('scroll', handleScroll);
    return () => document.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <div
      className={`fixed top-0 left-0 w-full z-10 transition duration-100 ${
        (shouldNavbarHaveBackground || !isNavbarCollapsed) && navbarBgStyle
      } ${navbarWrapperClassName ?? ''}`}
    >
      <div className="w-container mx-auto md:flex justify-between items-center">
        <div className="flex justify-between items-center w-full">
          <a {...getScrollToSectionProps('top')}>
            <Brand className="font-bold text-2xl" />
          </a>
          <span className="md:hidden" onClick={() => setNavbarCollapsed(!isNavbarCollapsed)}>
            {isNavbarCollapsed ? <FiMenu /> : <FiX />}
          </span>
        </div>
        <div
          className={`w-full mt-5 md:flex items-center justify-end ${
            isNavbarCollapsed && 'hidden'
          }`}
        >
          <ul className="flex md:flex-row flex-col">
            {
              isFeatureFlagEnabled(publicRuntimeConfig.SHOW_LINKS_TO_APP) && (
                <li className="my-1">
                  <Popover className="relative">
                    <Popover.Button className="font-bold">{t('navbar.schools')}</Popover.Button>
                    <Popover.Panel className={popoverPanelClassName}>
                      <ul>
                        {projectsList.map(({ projectID, appName }) => (
                          <li className="ml-2 md:ml-0 my-2">
                            <a href={`/${projectID}`}>{capitalize(appName)}</a>
                          </li>
                        ))}
                      </ul>
                    </Popover.Panel>
                  </Popover>
                </li>
              )
            }
            <li className="font-bold md:mx-10 my-1">
              <Link href="/calculator">
                <a>{t('navbar.pointsCalculator')}</a>
              </Link>
            </li>
          </ul>
          <span className="block mt-5 md:mt-0 md:ml-5">
            <a
              {...getScrollToSectionProps('support-us')}
              className={[
                'font-bold inline-block w-full sm:w-auto text-center',
                roundedSmallLinkClassName,
              ].join(' ')}
            >
              {t('navbar.supportTheProject')}
            </a>
          </span>
        </div>
      </div>
    </div>
  );
}
Example #7
Source File: Modal.tsx    From meshtastic-web with GNU General Public License v3.0 5 votes vote down vote up
Modal = ({
  open,
  bgDismiss,
  onClose,
  actions,
  ...props
}: ModalProps): JSX.Element => {
  const darkMode = useAppSelector((state) => state.app.darkMode);

  return (
    <AnimatePresence>
      {open && (
        <m.div
          className={`fixed inset-0  ${darkMode ? 'dark' : ''} ${
            open ? 'z-30' : 'z-0'
          }`}
        >
          <m.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.1 }}
            className="fixed h-full w-full backdrop-blur-md backdrop-brightness-75 backdrop-filter"
            onClick={(): void => {
              bgDismiss && onClose();
            }}
          />
          <m.div className="text-center ">
            <span
              className="inline-block h-screen align-middle "
              aria-hidden="true"
            >
              &#8203;
            </span>
            <div className="inline-block w-full max-w-3xl align-middle">
              <Card
                border
                actions={
                  <div className="flex gap-2">
                    {actions}
                    <IconButton
                      tooltip="Close"
                      icon={<FiX />}
                      onClick={onClose}
                    />
                  </div>
                }
                className="relative flex-col"
                {...props}
              />
            </div>
          </m.div>
        </m.div>
      )}
    </AnimatePresence>
  );
}
Example #8
Source File: RangeTable.tsx    From HoldemSolver with MIT License 5 votes vote down vote up
function RangeTable(props: RangeTableProps): React.ReactElement {
  const { className = '' } = props;
  const [modalShown, setModalShown] = useState(false);
  return (
    <RangeTableStyle className={className}>
        <Modal
            title="Add Range"
            shown={modalShown}
            closeModal={() => setModalShown(false)}
            actionButtons={[
                <Button variant="primary" onClick={() => {}}>
                    Create Range
                </Button>,
            ]}
        >
            <CreateRangeForm/>
        </Modal>
      <div className="range-table-container">
        <div className="range-table-header">
            RANGES
        </div>
        <table className="range-table">
          <thead>
            <tr>
              <th>POSITION</th>
              <th>TITLE</th>
              <th>EQUITY</th>
            </tr>
          </thead>
          <tbody>
            <tr className="range-table-item">
              <td>CO</td>
              <td>Limp</td>
              <td>32.53%</td>
              <td className="range-table-item-icons">
                <FiX/>
              </td>
            </tr>
            <tr className="range-table-item range-table-item-active">
              <td>UTG+1</td>
              <td>Raise first in</td>
              <td>56.64%</td>
              <td className="range-table-item-icons">
                <FiX/>
              </td>
            </tr>
          </tbody>
        </table>
        <div className="range-table-footer">
            <div onClick={() => setModalShown(true)} className="range-table-add">
            <FiPlusCircle/>
            <div>Add Range</div>
          </div>
        </div>
      </div>
    </RangeTableStyle>
  );
}
Example #9
Source File: Modal.tsx    From tobira with Apache License 2.0 5 votes vote down vote up
Modal = forwardRef<ModalHandle, PropsWithChildren<ModalProps>>(({
    title,
    closable = true,
    children,
}, ref) => {
    const [isOpen, setOpen] = useState(false);

    useImperativeHandle(ref, () => ({
        open: () => setOpen(true),
        close: closable ? (() => setOpen(false)) : undefined,
    }));

    useEffect(() => {
        const handleEscape = (event: KeyboardEvent) => {
            if (closable && event.key === "Escape") {
                setOpen(false);
            }
        };
        window.addEventListener("keydown", handleEscape);
        return () => window.removeEventListener("keydown", handleEscape);
    }, [closable]);

    return ReactDOM.createPortal(
        isOpen && <div
            {...(closable && { onClick: e => {
                if (e.target === e.currentTarget) {
                    setOpen(false);
                }
            } })}
            css={{
                position: "fixed",
                top: 0,
                bottom: 0,
                left: 0,
                right: 0,
                backgroundColor: "rgba(0, 0, 0, 0.8)",
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
                zIndex: 2000,
            }}
        >
            <div css={{
                backgroundColor: "white",
                borderRadius: 4,
                width: 400,
                maxWidth: "100%",
                margin: 16,
            }}>
                <div css={{
                    padding: "12px 16px",
                    borderBottom: "1px solid var(--grey80)",
                    display: "flex",
                    alignItems: "center",
                }}>
                    <h2 css={{ flex: "1" }}>{title}</h2>
                    {closable && <div
                        onClick={() => setOpen(false)}
                        css={{ fontSize: 32, cursor: "pointer", display: "inline-flex" }}
                    ><FiX /></div>}
                </div>
                <div css={{ padding: 16 }}>{children}</div>
            </div>
        </div>,
        document.body,
    );
})
Example #10
Source File: index.tsx    From rocketredis with MIT License 5 votes vote down vote up
Header: React.FC = () => {
  const handleCloseWindow = useCallback(() => {
    const window = remote.getCurrentWindow()

    window.close()
  }, [])

  const handleMaximize = useCallback(() => {
    const window = remote.getCurrentWindow()

    const isMacSystem = os.platform() === 'darwin'
    if (isMacSystem) {
      return window.setFullScreen(!window.isFullScreen())
    }

    const { width: currentWidth, height: currentHeight } = window.getBounds()

    const {
      width: maxWidth,
      height: maxHeight
    } = remote.screen.getPrimaryDisplay().workAreaSize

    const isMaximized = currentWidth === maxWidth && currentHeight === maxHeight

    if (!isMaximized) {
      window.maximize()
    } else {
      window.unmaximize()
    }
  }, [])

  const handleMinimize = useCallback(() => {
    const window = remote.getCurrentWindow()

    window.minimize()
  }, [])

  const useMacOSWindowActionButtons = useConfig('useMacOSWindowActionButtons')

  const shouldUseMacOSWindowActions = useMemo(() => {
    return useMacOSWindowActionButtons || os.platform() === 'darwin'
  }, [useMacOSWindowActionButtons])

  return (
    <Container>
      <strong>Rocket Redis</strong>

      {shouldUseMacOSWindowActions ? (
        <WindowActions position="left" shouldShowIconsOnHover>
          <MacActionButton color="close" onClick={handleCloseWindow}>
            <FiX />
          </MacActionButton>
          <MacActionButton color="minimize" onClick={handleMinimize}>
            <FiMinus />
          </MacActionButton>
          <MacActionButton color="maximize" onClick={handleMaximize}>
            <FiMaximize2 />
          </MacActionButton>
        </WindowActions>
      ) : (
        <WindowActions position="right">
          <DefaultActionButton onClick={handleMinimize}>
            <FiMinus />
          </DefaultActionButton>
          <DefaultActionButton onClick={handleMaximize}>
            <FiSquare />
          </DefaultActionButton>
          <DefaultActionButton onClick={handleCloseWindow}>
            <FiX />
          </DefaultActionButton>
        </WindowActions>
      )}
    </Container>
  )
}
Example #11
Source File: index.tsx    From vagasExplorer with MIT License 4 votes vote down vote up
Repository: React.FC<ToggleTheme> = ({ toggleTheme }) => {
  const [repository, setRepositories] = useState<RepositoryProps | null>(null);
  const [issues, setIssues] = useState<IssueProps[]>([]);
  const [searchValue, setSearchValue] = useState('');


  const { params } = useRouteMatch<RepositoryParamsProps>();

  const [allIssues, setAllIssues] = useState<IssueProps[]>([]);

  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    api.get(`repos/${params.repository}`).then((response) => {
      setRepositories(response.data);
    });

    api.get(`repos/${params.repository}/issues`).then((response) => {
      setIssues(response.data);
      setAllIssues(response.data);
      console.log(response.data);
    });
  }, [params.repository]);

  const handleSearch = (val: string) => {
    if (null !== inputRef.current) {
      inputRef.current.focus();
    }

    if (!val) setIssues(allIssues);

    setSearchValue(val);

    // eslint-disable-next-line
    const issuesFiltered = allIssues.filter((issue) => {
      if (issue.title.toLowerCase().indexOf(val.toLowerCase()) !== -1) {
        return true;
      }

      if (issue.body.toLowerCase().indexOf(val.toLowerCase()) !== -1) {
        return true;
      }

      for (let i = 0; i < issue.labels.length; i++) {
        if (
          issue.labels[i].name.toLowerCase().indexOf(val.toLowerCase()) !== -1
        ) {
          return true;
        }
      }

      return false;
    });

    setIssues(issuesFiltered);
  };

  return (
    <Layout isContentFull>
      <Header isLink="/dashboard" toggleTheme={toggleTheme} />
      <S.Container>
        {repository && (
          <S.RepositoryInfo>
            <div>
              <img
                src={repository.owner.avatar_url}
                alt={repository.owner.login}
              />
              <div>
                <strong>{repository.full_name}</strong>
                <p>{repository.description}</p>
              </div>
            </div>
            <ul>
              <li>
                <strong>{repository.open_issues_count}</strong>
                <span>Vagas abertas</span>
              </li>
            </ul>
          </S.RepositoryInfo>
        )}

        <S.Issues>
          <>
            <S.Search>
              <S.Input
                ref={inputRef}
                type="text"
                placeholder="Busque por tecnologia, nível de vaga, local, regime, tipo etc..."
                value={searchValue}
                onChange={(e) => handleSearch(e.target.value)}
              />
              {searchValue && (
                <S.Icon onClick={() => handleSearch('')}>
                  <FiX size={20} />
                </S.Icon>
              )}
            </S.Search>
            {issues.map((issue, index) => (
              <React.Fragment key={issue.id}>
                <a
                  href={issue.html_url}
                  style={{ animationDelay: `0.${index}ms` }}
                >
                  <img src={issue.user.avatar_url} alt={issue.user.login} />
                  <div>
                    <strong>{issue.title}</strong>
                    <p>{issue.user.login}</p>
                  </div>
                  <FiChevronRight size={20} />
                </a>

                {issue.labels.length > 0 && (
                  <S.Labels style={{ animationDelay: `0.${index}ms` }}>
                    {issue.labels.map((label) => (
                      <S.Label
                        color={label.color}
                        onClick={() => handleSearch(label.name)}
                      >
                        <span>{label.name}</span>
                      </S.Label>
                    ))}
                  </S.Labels>
                )}
              </React.Fragment>
            ))}
          </>
        </S.Issues>
      </S.Container>
    </Layout>
  );
}
Example #12
Source File: Configuration.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
ConfigPage = observer(() => {
  const {
    context: {
      configStore,
      pinataService,
      etherscanService,
      infuraService,
      poktService,
      alchemyService,
      customRpcService,
    },
  } = useContext();
  const networkName = configStore.getActiveChainName();

  const [etherscanApiStatus, setEtherscanApiStatus] = React.useState(
    etherscanService.auth
  );
  const [pinataKeyStatus, setPinataKeyStatus] = React.useState(
    pinataService.auth
  );
  const [infuraKeyStatus, setInfuraKeyStatus] = React.useState(
    infuraService.auth
  );
  const [poktStatus, setPoktStatus] = React.useState(poktService.auth);
  const [alchemyKeyStatus, setAlchemyKeyStatus] = React.useState(
    alchemyService.auth
  );
  const [customRpcUrlStatus, setCustomRpcUrlStatus] = React.useState(
    customRpcService.auth
  );

  const [localConfig, setLocalConfig] = React.useState(
    configStore.getLocalConfig()
  );
  const [, forceUpdate] = React.useReducer(x => x + 1, 0);

  function onApiKeyValueChange(value, key) {
    localConfig[key] = value;
    setLocalConfig(localConfig);
    forceUpdate();
  }

  function saveConfig() {
    configStore.setLocalConfig(localConfig);
  }

  async function testApis() {
    await pinataService.isAuthenticated();
    await etherscanService.isAuthenticated(networkName);
    await infuraService.isAuthenticated();
    await poktService.isAuthenticated();
    await alchemyService.isAuthenticated();
    await customRpcService.isAuthenticated();
    setPinataKeyStatus(pinataService.auth);
    setEtherscanApiStatus(etherscanService.auth);
    setInfuraKeyStatus(infuraService.auth);
    setPoktStatus(poktService.auth);
    setAlchemyKeyStatus(alchemyService.auth);
    setCustomRpcUrlStatus(customRpcService.auth);
  }

  async function pinDXvoteHashes() {
    pinataService.updatePinList();
  }

  async function clearCache() {
    localStorage.clear();
    caches.delete(`dxvote-cache`);
    window.location.reload();
  }

  return (
    <Box centered>
      <h2>
        API Keys <Question question="8" />
      </h2>
      <FormContainer>
        <Row>
          <FormLabel>Etherscan:</FormLabel>
          <InputBox
            type="text"
            serviceName="etherscan"
            onChange={event =>
              onApiKeyValueChange(event.target.value, 'etherscan')
            }
            value={localConfig.etherscan}
          ></InputBox>
          <FormLabel>
            {etherscanApiStatus ? <FiCheckCircle /> : <FiX />}
          </FormLabel>
        </Row>
        <Row>
          <FormLabel>Pinata:</FormLabel>
          <InputBox
            type="text"
            serviceName="pinata"
            onChange={event =>
              onApiKeyValueChange(event.target.value, 'pinata')
            }
            value={localConfig.pinata}
          ></InputBox>
          <FormLabel>{pinataKeyStatus ? <FiCheckCircle /> : <FiX />}</FormLabel>
        </Row>

        <Row>
          <FormLabel>RPC:</FormLabel>
          <Dropdown
            onChange={event =>
              onApiKeyValueChange(event.target.value, 'rpcType')
            }
            value={localConfig.rpcType}
          >
            <option value="">Default</option>
            <option value="pokt">Pokt</option>
            <option value="infura">Infura</option>
            <option value="alchemy">Alchemy</option>
            <option value="custom">Custom</option>
          </Dropdown>
        </Row>

        {localConfig.rpcType === 'pokt' && (
          <Row>
            <FormLabel>Pokt:</FormLabel>
            <InputBox
              type="text"
              serviceName="pokt"
              onChange={event =>
                onApiKeyValueChange(event.target.value, 'pokt')
              }
              value={localConfig.pokt}
            ></InputBox>
            <FormLabel>{poktStatus ? <FiCheckCircle /> : <FiX />}</FormLabel>
          </Row>
        )}
        {localConfig.rpcType === 'infura' && (
          <Row>
            <FormLabel>Infura:</FormLabel>
            <InputBox
              type="text"
              serviceName="infura"
              onChange={event =>
                onApiKeyValueChange(event.target.value, 'infura')
              }
              value={localConfig.infura}
            ></InputBox>
            <FormLabel>
              {infuraKeyStatus ? <FiCheckCircle /> : <FiX />}
            </FormLabel>
          </Row>
        )}
        {localConfig.rpcType === 'alchemy' && (
          <Row>
            <FormLabel>Alchemy:</FormLabel>
            <InputBox
              type="text"
              serviceName="alchemy"
              onChange={event =>
                onApiKeyValueChange(event.target.value, 'alchemy')
              }
              value={localConfig.alchemy}
            ></InputBox>
            <FormLabel>
              {alchemyKeyStatus ? <FiCheckCircle /> : <FiX />}
            </FormLabel>
          </Row>
        )}
        {localConfig.rpcType === 'custom' && (
          <Row>
            <FormLabel>RPC URL:</FormLabel>
            <InputBox
              type="text"
              serviceName="customRpcUrl"
              onChange={event =>
                onApiKeyValueChange(event.target.value, 'customRpcUrl')
              }
              value={localConfig.customRpcUrl}
            ></InputBox>
            <FormLabel>
              {customRpcUrlStatus ? <FiCheckCircle /> : <FiX />}
            </FormLabel>
          </Row>
        )}
      </FormContainer>
      <Row>
        <FormLabel>Pin DXdao hashes on start</FormLabel>
        <InputBox
          type="checkbox"
          checked={localConfig.pinOnStart}
          onChange={event =>
            onApiKeyValueChange(event.target.checked, 'pinOnStart')
          }
        ></InputBox>
      </Row>
      <Row>
        <Button onClick={saveConfig}>Save</Button>
        <Button onClick={testApis}>Test Apis</Button>
        <Button onClick={clearCache}>Clear Cache</Button>
        <Button onClick={pinDXvoteHashes}>Pin DXVote Hashes</Button>
      </Row>
    </Box>
  );
})
Example #13
Source File: CreateOrphanage.tsx    From happy with MIT License 4 votes vote down vote up
export default function CreateOrphanage() {
  const history = useHistory();

  const [position, setPosition] = useState({ latitude: 0, longitude: 0 });

  const [name, setName] = useState('');
  const [about, setAbout] = useState('');
  const [instructions, setInstructions] = useState('');
  const [opening_hours, setOpeningHours] = useState('');
  const [open_on_weekends, setOpenOnWeekends] = useState(true);
  const [images, setImages] = useState<File[]>([]);
  const [previewImages, setPreviewImages] = useState<PreviewImage[]>([]);

  function handleMapClick(event: LeafletMouseEvent) {
    const { lat, lng } = event.latlng;

    setPosition({
      latitude: lat,
      longitude: lng
    });
  }

  async function handleSubmit(event: FormEvent) {
    event.preventDefault();

    const { latitude, longitude } = position;

    const data = new FormData();

    data.append('name', name);
    data.append('about', about);
    data.append('latitude', String(latitude));
    data.append('longitude', String(longitude));
    data.append('instructions', instructions);
    data.append('opening_hours', opening_hours);
    data.append('open_on_weekends', String(open_on_weekends));

    images.forEach(image => {
      data.append('images', image);
    });

    await api.post('/orphanages', data);

    alert('Orfanato cadastrado com sucesso!');

    history.push('/app');
  }

  function handleSelectImages(event: ChangeEvent<HTMLInputElement>) {
    if (!event.target.files) {
      return;
    }
    const selectedImages = Array.from(event.target.files);

    event.target.value = "";

    setImages(selectedImages);

    const selectedImagesPreview = selectedImages.map(image => {
      return { name: image.name, url: URL.createObjectURL(image) };
    });

    setPreviewImages(selectedImagesPreview);
  }

  function handleRemoveImage(image: PreviewImage) {
    setPreviewImages(
      previewImages.map((image) => image).filter((img) => img.url !== image.url)
    );
    setImages(
      images.map((image) => image).filter((img) => img.name !== image.name)
    );
  }

  return (
    <div id="page-create-orphanage">
      <Sidebar />

      <main>
        <form onSubmit={handleSubmit} className="create-orphanage-form">
          <fieldset>
            <legend>Dados</legend>

            <Map
              center={[-27.2092052, -49.6401092]}
              style={{ width: '100%', height: 280 }}
              zoom={15}
              onclick={handleMapClick}
            >
              <TileLayer
                url={`https://api.mapbox.com/styles/v1/mapbox/light-v10/tiles/256/{z}/{x}/{y}@2x?access_token=${process.env.REACT_APP_MAPBOX_TOKEN}`}
              />

              {position.latitude !== 0 && (
                <Marker
                  interactive={false}
                  icon={mapIcon}
                  position={[
                    position.latitude,
                    position.longitude
                  ]}
                />
              )}

            </Map>

            <div className="input-block">
              <label htmlFor="name">Nome</label>
              <input
                id="name"
                value={name}
                onChange={event => setName(event.target.value)}
              />
            </div>

            <div className="input-block">
              <label htmlFor="about">Sobre <span>Máximo de 300 caracteres</span></label>
              <textarea
                id="name"
                maxLength={300}
                value={about}
                onChange={event => setAbout(event.target.value)}
              />
            </div>

            <div className="input-block">
              <label htmlFor="images">Fotos</label>

              <div className="images-container">
                {previewImages.map((image) => {
                  return (
                    <div key={image.url}>
                      <span
                        className="remove-image"
                        onClick={() => handleRemoveImage(image)}
                      >
                        <FiX size={18} color="#ff669d" />
                      </span>
                      <img src={image.url} alt={name} className="new-image" />
                    </div>
                  );
                })}

                <label htmlFor="image[]" className="new-image">
                  <FiPlus size={24} color="#15b6d6" />
                </label>
              </div>

              <input
                type="file"
                multiple
                accept=".png, .jpg, .jpeg"
                onChange={handleSelectImages}
                id="image[]"
              />
            </div>
          </fieldset>

          <fieldset>
            <legend>Visitação</legend>

            <div className="input-block">
              <label htmlFor="instructions">Instruções</label>
              <textarea
                id="instructions"
                value={instructions}
                onChange={event => setInstructions(event.target.value)}
              />
            </div>

            <div className="input-block">
              <label htmlFor="opening_hours">Horário de Funcionamento</label>
              <input
                id="opening_hours"
                value={opening_hours}
                onChange={event => setOpeningHours(event.target.value)}
              />
            </div>

            <div className="input-block">
              <label htmlFor="open_on_weekends">Atende fim de semana</label>

              <div className="button-select">
                <button
                  type="button"
                  className={open_on_weekends ? 'active' : ''}
                  onClick={() => setOpenOnWeekends(true)}
                >
                  Sim
                </button>
                <button
                  type="button"
                  className={!open_on_weekends ? 'active' : ''}
                  onClick={() => setOpenOnWeekends(false)}
                >
                  Não
                </button>
              </div>
            </div>
          </fieldset>

          <button className="confirm-button" type="submit">
            Confirmar
          </button>
        </form>
      </main>
    </div>
  );
}
Example #14
Source File: HardwareModal.tsx    From Meshtastic with GNU General Public License v3.0 4 votes vote down vote up
HardwareModal = ({
  device,
  open,
  close,
}: HardwareModal): JSX.Element => {
  const [hideDetails, setHideDetails] = useState(false);
  const { breakpoint } = useBreakpoint(BREAKPOINTS, 'md');

  return (
    <Modal open={open} onClose={close}>
      <div className="absolute right-0 z-20 m-2 md:flex">
        <Button onClick={close}>
          <FiX />
        </Button>
      </div>
      <div className="absolute inset-0">
        <motion.div
          layout
          animate={
            breakpoint === 'sm'
              ? hideDetails
                ? 'hiddenSm'
                : 'visibleSm'
              : hideDetails
              ? 'hidden'
              : 'visible'
          }
          variants={{
            hidden: { width: '100%', height: '100%' },
            hiddenSm: { height: '100%', width: '100%' },
            visible: { width: '20%', height: '100%' },
            visibleSm: { height: '33%', width: '100%' },
          }}
          transition={{
            type: 'just',
          }}
          className="flex flex-col md:h-full md:flex-row"
        >
          <motion.div
            layout
            className={`relative z-10 flex h-full w-full rounded-t-2xl md:rounded-l-2xl md:rounded-tr-none ${device.misc.Gradient}`}
          >
            <motion.img
              layout
              src={device.images.Front}
              alt=""
              className="pointer-events-none m-auto max-h-full max-w-full object-cover p-2"
            />
            <div className="absolute -bottom-5 z-20 flex w-full md:bottom-auto md:-right-5 md:h-full md:w-auto">
              <Button
                animate={
                  breakpoint === 'sm'
                    ? hideDetails
                      ? 'hiddenSm'
                      : 'visibleSm'
                    : hideDetails
                    ? 'hidden'
                    : 'visible'
                }
                variants={{
                  hidden: { rotate: 180 },
                  hiddenSm: { rotate: -90 },
                  visible: { rotate: 0 },
                  visibleSm: { rotate: 90 },
                }}
                onClick={() => {
                  setHideDetails(!hideDetails);
                }}
              >
                <FiChevronRight />
              </Button>
            </div>
            <AnimatePresence>
              {!hideDetails && (
                <>
                  <motion.div
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    exit={{ opacity: 0 }}
                    className={`absolute -bottom-5 z-20 flex md:mt-0 md:hidden md:pb-2 ${
                      hideDetails ? 'opacity-0' : 'opacity-100'
                    }`}
                  >
                    <VariantSelectButton options={device.variants} />
                  </motion.div>
                  <motion.div
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    exit={{ opacity: 0 }}
                    className="absolute -bottom-3 right-0 m-auto mr-2 ml-auto flex md:inset-x-1 md:bottom-4 md:mt-2"
                  >
                    <div className="m-auto flex gap-2">
                      {device.features.BLE && (
                        <Badge
                          name="Bluetooth"
                          color="bg-blue-500"
                          icon={<FiBluetooth />}
                        />
                      )}
                      {device.features.WiFi && (
                        <Badge
                          name="WiFi"
                          color="bg-orange-500"
                          icon={<FiWifi />}
                        />
                      )}
                    </div>
                  </motion.div>
                </>
              )}
            </AnimatePresence>
          </motion.div>
          <div
            className={`h-7 bg-base opacity-0 md:h-auto md:w-7 ${
              hideDetails ? 'flex' : 'hidden'
            }`}
          />
        </motion.div>
      </div>
      <div className="z-[1] mt-[25%] flex h-full flex-col md:ml-[20%] md:mt-0 md:w-4/5">
        <div className="z-0 hidden pb-2 md:flex">
          <VariantSelectButton options={device.variants} />
        </div>
        <div
          className={`mt-1 flex flex-grow rounded-2xl bg-base p-2 shadow-inner transition-opacity duration-100 ease-linear md:mt-0 md:rounded-l-none md:rounded-r-2xl md:p-4 ${
            hideDetails ? 'opacity-0' : 'opacity-100'
          }`}
        >
          <Tab.Group
            as="div"
            className="flex flex-grow flex-col rounded-2xl bg-primary p-2"
          >
            <Tab.List className="flex gap-2">
              <CardTab title="Info" />
              <CardTab title="Power" />
              <CardTab title="Pinout" />
            </Tab.List>
            <Tab.Panels as="div" className="flex-grow overflow-y-auto">
              <InfoTab device={device} />
              <PowerTab device={device} />
              <PinoutTab device={device} />
            </Tab.Panels>
          </Tab.Group>
        </div>
      </div>
    </Modal>
  );
}
Example #15
Source File: Cache.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
CachePage = observer(() => {
  // Set html title to cache to differentiate from dxvote dapp
  document.title = 'Cache';

  const {
    context: { cacheService, configStore, notificationStore, ipfsService },
  } = useContext();

  const [updateProposalTitles, setUpdateProposalTitles] = React.useState(false);
  const [buildingCacheState, setBuildingCacheState] = React.useState(0);
  const [updatedCacheHash, setUpdatedCacheHash] = React.useState({
    proposalTitles: {},
    configHashes: {},
    configs: {},
    caches: {},
  });
  const [resetCache, setResetCache] = React.useState({
    mainnet: false,
    rinkeby: false,
    xdai: false,
    arbitrum: false,
    arbitrumTestnet: false,
  });
  const [localConfig, setLocalConfig] = React.useState(
    configStore.getLocalConfig()
  );
  const [, forceUpdate] = React.useReducer(x => x + 1, 0);

  async function resetCacheOptions() {
    configStore.resetLocalConfig();
    setLocalConfig(configStore.getLocalConfig());
    setBuildingCacheState(0);
    setResetCache({
      mainnet: false,
      rinkeby: false,
      xdai: false,
      arbitrum: false,
      arbitrumTestnet: false,
    });
    setUpdatedCacheHash({
      proposalTitles: {},
      configHashes: {},
      configs: {},
      caches: {},
    });
    setUpdateProposalTitles(false);
  }

  async function uploadToIPFS(content) {
    ipfsService.upload(content);
  }

  async function runCacheScript() {
    setBuildingCacheState(1);
    const updatedCache = await cacheService.getUpdatedCacheConfig(
      {
        1: {
          rpcUrl: localConfig.mainnet_rpcURL,
          toBlock: localConfig.mainnet_toBlock,
          reset: resetCache.mainnet,
        },
        4: {
          rpcUrl: localConfig.rinkeby_rpcURL,
          toBlock: localConfig.rinkeby_toBlock,
          reset: resetCache.rinkeby,
        },
        100: {
          rpcUrl: localConfig.xdai_rpcURL,
          toBlock: localConfig.xdai_toBlock,
          reset: resetCache.xdai,
        },
        42161: {
          rpcUrl: localConfig.arbitrum_rpcURL,
          toBlock: localConfig.arbitrum_toBlock,
          reset: resetCache.arbitrum,
        },
        421611: {
          rpcUrl: localConfig.arbitrumTestnet_rpcURL,
          toBlock: localConfig.arbitrumTestnet_toBlock,
          reset: resetCache.arbitrumTestnet,
        },
      },
      updateProposalTitles
    );
    console.log('[Updated Cache]', updatedCache);
    setUpdatedCacheHash(updatedCache);
    setBuildingCacheState(2);
    forceUpdate();
  }

  function onApiKeyValueChange(value, key) {
    localConfig[key] = value;
    setLocalConfig(localConfig);
    configStore.setLocalConfig(localConfig);
    forceUpdate();
  }

  function downloadAll() {
    var zip = new JSZip();

    var cache = zip.folder('cache');

    var configs = zip.folder('configs');
    zip.file(
      'default.json',
      JSON.stringify(
        {
          mainnet: updatedCacheHash.configHashes['mainnet'],
          xdai: updatedCacheHash.configHashes['xdai'],
          arbitrum: updatedCacheHash.configHashes['arbitrum'],
          rinkeby: updatedCacheHash.configHashes['rinkeby'],
          arbitrumTestnet: updatedCacheHash.configHashes['arbitrumTestnet'],
        },
        null,
        2
      )
    );
    zip.file(
      'proposalTitles.json',
      JSON.stringify(updatedCacheHash.proposalTitles, null, 2)
    );

    NETWORKS.map((network, i) => {
      cache.file(
        network.name + '.json',
        JSON.stringify(updatedCacheHash.caches[network.name], null, 2)
      );
      const configFolder = configs.folder(network.name);
      configFolder.file(
        'config.json',
        JSON.stringify(updatedCacheHash.configs[network.name], null, 2)
      );
    });

    zip.generateAsync({ type: 'blob' }).then(function (content) {
      saveAs(content, 'dxvote-cache.zip');
    });
  }

  if (window.location.hash.length > 7) {
    const searchParams = new URLSearchParams(window.location.hash.substring(7));
    setUpdateProposalTitles(searchParams.get('proposalTitles') ? true : false);
    NETWORKS.map((network, i) => {
      const networkName = network.name;
      if (searchParams.get(networkName + '_toBlock'))
        localConfig[networkName + '_toBlock'] = searchParams.get(
          networkName + '_toBlock'
        );
      if (searchParams.get(networkName + '_targetHash'))
        localConfig[networkName + '_targetHash'] = searchParams.get(
          networkName + '_targetHash'
        );
      if (searchParams.get(networkName + '_reset')) {
        resetCache[networkName] = true;
      }
    });
    setLocalConfig(localConfig);
    setResetCache(resetCache);
    configStore.setLocalConfig(localConfig);
    window.location.assign(window.location.origin + '/#cache');
    forceUpdate();
  }

  function getOptionsLink(): string {
    let optionsLinkUrl =
      window.location.origin + '/' + window.location.hash + '?';
    if (updateProposalTitles)
      optionsLinkUrl = optionsLinkUrl = 'proposalTitles=1&';
    NETWORKS.map((network, i) => {
      const networkName = network.name;
      if (localConfig[networkName + '_toBlock'])
        optionsLinkUrl =
          optionsLinkUrl +
          networkName +
          '_toBlock=' +
          localConfig[networkName + '_toBlock'] +
          '&';
      if (localConfig[networkName + '_targetHash'])
        optionsLinkUrl =
          optionsLinkUrl +
          networkName +
          '_targetHash=' +
          localConfig[networkName + '_targetHash'] +
          '&';
      if (resetCache[networkName])
        optionsLinkUrl = optionsLinkUrl + networkName + '_reset=1&';
    });
    optionsLinkUrl = optionsLinkUrl.slice(0, -1);
    return optionsLinkUrl;
  }

  return buildingCacheState === 1 ? (
    <LoadingBox>
      <div className="loader">
        {' '}
        <PulsingIcon size={80} inactive={false} />
        <LoadingProgressText>
          {notificationStore.globalMessage}
        </LoadingProgressText>
      </div>
    </LoadingBox>
  ) : (
    <Box>
      <FormContainer>
        {NETWORKS.map((network, i) => {
          const networkName = network.name;
          return (
            networkName !== 'localhost' && (
              <div key={`networkOptions${i}`}>
                <RowAlignedLeft>
                  {' '}
                  <strong>{toCamelCaseString(networkName)}</strong>{' '}
                </RowAlignedLeft>
                <RowAlignedLeft>
                  <FormLabel>Block:</FormLabel>
                  <InputBox
                    type="text"
                    onChange={event =>
                      onApiKeyValueChange(
                        event.target.value,
                        networkName + '_toBlock'
                      )
                    }
                    value={localConfig[networkName + '_toBlock']}
                    style={{ width: '100px' }}
                  ></InputBox>
                  <FormLabel>RPC:</FormLabel>
                  <InputBox
                    type="text"
                    onChange={event =>
                      onApiKeyValueChange(
                        event.target.value,
                        networkName + '_rpcURL'
                      )
                    }
                    value={localConfig[networkName + '_rpcURL']}
                    style={{ width: '100%' }}
                  ></InputBox>
                  <FormLabel>Reset</FormLabel>
                  <InputBox
                    type="checkbox"
                    checked={resetCache[networkName]}
                    onChange={() => {
                      resetCache[networkName] = !resetCache[networkName];
                      setResetCache(resetCache);
                      forceUpdate();
                    }}
                  ></InputBox>
                </RowAlignedLeft>
                <RowAlignedLeft>
                  <FormLabel>Target Config Hash:</FormLabel>
                  <InputBox
                    type="text"
                    onChange={event =>
                      onApiKeyValueChange(
                        event.target.value,
                        networkName + '_targetHash'
                      )
                    }
                    value={localConfig[networkName + '_targetHash']}
                    style={{ width: '400px' }}
                  ></InputBox>
                  {updatedCacheHash.configs[networkName] && (
                    <div>
                      <Button
                        onClick={() =>
                          uploadToIPFS(
                            JSON.stringify(
                              updatedCacheHash.configs[networkName],
                              null,
                              2
                            )
                          )
                        }
                      >
                        <FiUpload></FiUpload> Config
                      </Button>
                      <Button
                        onClick={() =>
                          uploadToIPFS(
                            JSON.stringify(
                              updatedCacheHash.caches[networkName],
                              null,
                              2
                            )
                          )
                        }
                      >
                        <FiUpload></FiUpload> Cache
                      </Button>
                    </div>
                  )}
                </RowAlignedLeft>
                {updatedCacheHash.configs[networkName] && (
                  <RowAlignedLeft>
                    Received Config Hash:{' '}
                    {updatedCacheHash.configHashes[networkName]}
                    {'  '}
                    <FormLabel>
                      {updatedCacheHash.configHashes[networkName] ==
                      localConfig[networkName + '_targetHash'] ? (
                        <FiCheckCircle />
                      ) : (
                        <FiX />
                      )}
                    </FormLabel>
                  </RowAlignedLeft>
                )}
              </div>
            )
          );
        })}
      </FormContainer>
      <Row style={{ justifyContent: 'left' }}>
        <FormLabel>Update Proposal Titles</FormLabel>
        <InputBox
          type="checkbox"
          checked={updateProposalTitles}
          onChange={() => setUpdateProposalTitles(!updateProposalTitles)}
        ></InputBox>
      </Row>
      {buildingCacheState === 2 && (
        <Row>
          <Button onClick={downloadAll}>
            {' '}
            <FiDownload></FiDownload> Download All
          </Button>
        </Row>
      )}
      <Row>
        <Button onClick={runCacheScript}>Build Cache</Button>
        <Button onClick={resetCacheOptions}>Reset Options</Button>
        <CopyButton>
          <Copy toCopy={getOptionsLink()}>Build Link</Copy>
        </CopyButton>
      </Row>
    </Box>
  );
})
Example #16
Source File: BottomNav.tsx    From meshtastic-web with GNU General Public License v3.0 4 votes vote down vote up
BottomNav = (): JSX.Element => {
  const [showVersionInfo, setShowVersionInfo] = useState(false);
  const dispatch = useAppDispatch();
  const meshtasticState = useAppSelector((state) => state.meshtastic);
  const appState = useAppSelector((state) => state.app);
  const primaryChannelSettings = useAppSelector(
    (state) => state.meshtastic.radio.channels,
  ).find((channel) => channel.role === Protobuf.Channel_Role.PRIMARY)?.settings;
  const metrics =
    meshtasticState.nodes[meshtasticState.radio.hardware.myNodeNum]?.metrics;

  return (
    <div className="z-20 flex justify-between divide-x divide-gray-400 border-t border-gray-400 bg-white dark:divide-gray-600 dark:border-gray-600 dark:bg-secondaryDark">
      <BottomNavItem tooltip="Meshtastic WebUI">
        <img
          title="Logo"
          className="my-auto w-5"
          src={appState.darkMode ? '/Logo_White.svg' : '/Logo_Black.svg'}
        />
      </BottomNavItem>

      <BottomNavItem
        tooltip="Connection Status"
        onClick={(): void => {
          dispatch(openConnectionModal());
        }}
        className={
          [
            Types.DeviceStatusEnum.DEVICE_CONNECTED,
            Types.DeviceStatusEnum.DEVICE_CONFIGURED,
          ].includes(meshtasticState.deviceStatus)
            ? 'bg-primary dark:bg-primary'
            : [
                Types.DeviceStatusEnum.DEVICE_CONNECTING,
                Types.DeviceStatusEnum.DEVICE_RECONNECTING,
                Types.DeviceStatusEnum.DEVICE_CONFIGURING,
              ].includes(meshtasticState.deviceStatus)
            ? 'bg-yellow-400 dark:bg-yellow-400'
            : ''
        }
      >
        {appState.connType === connType.BLE ? (
          <FiBluetooth className="h-4" />
        ) : appState.connType === connType.SERIAL ? (
          <FiCpu className="h-4" />
        ) : (
          <FiWifi className="h-4" />
        )}
        <div className="truncate text-xs font-medium">
          {meshtasticState.nodes.find(
            (node) =>
              node.data.num === meshtasticState.radio.hardware.myNodeNum,
          )?.data.user?.longName ?? 'Disconnected'}
        </div>
      </BottomNavItem>

      <BottomNavItem tooltip="Battery Level">
        {!metrics?.batteryLevel ? (
          <IoBatteryDeadOutline className="h-4" />
        ) : metrics?.batteryLevel > 50 ? (
          <IoBatteryFullOutline className="h-4" />
        ) : metrics?.batteryLevel > 0 ? (
          <IoBatteryFullOutline className="h-4" />
        ) : (
          <IoBatteryChargingOutline className="h-4" />
        )}

        <div className="truncate text-xs font-medium">
          {metrics?.batteryLevel
            ? `${metrics?.batteryLevel}% - ${metrics?.voltage}v`
            : 'No Battery'}
        </div>
      </BottomNavItem>

      <BottomNavItem tooltip="Network Utilization">
        <div className="m-auto h-3 w-3 rounded-full bg-primary" />
        <div className="truncate text-xs font-medium">
          {`${metrics?.airUtilTx ?? 0}% - Air`} |
        </div>

        <div
          className={`m-auto h-3 w-3 rounded-full ${
            !metrics?.channelUtilization
              ? 'bg-primary'
              : metrics?.channelUtilization > 50
              ? 'bg-red-400'
              : metrics?.channelUtilization > 24
              ? 'bg-yellow-400'
              : 'bg-primary'
          }`}
        />
        <div className="truncate text-xs font-medium">
          {`${metrics?.channelUtilization ?? 0}% - Ch`}
        </div>
      </BottomNavItem>

      <BottomNavItem tooltip="MQTT Status">
        {primaryChannelSettings?.uplinkEnabled &&
        primaryChannelSettings?.downlinkEnabled &&
        !meshtasticState.radio.moduleConfig.mqtt.disabled ? (
          <RiArrowUpDownLine className="h-4" />
        ) : primaryChannelSettings?.uplinkEnabled &&
          !meshtasticState.radio.moduleConfig.mqtt.disabled ? (
          <RiArrowUpLine className="h-4" />
        ) : primaryChannelSettings?.downlinkEnabled &&
          !meshtasticState.radio.moduleConfig.mqtt.disabled ? (
          <RiArrowDownLine className="h-4" />
        ) : (
          <FiX className="h-4" />
        )}
      </BottomNavItem>

      <div className="flex-grow">
        <BottomNavItem
          onClick={(): void => {
            dispatch(toggleMobileNav());
          }}
          className="md:hidden"
        >
          {appState.mobileNavOpen ? (
            <FiX className="m-auto h-4" />
          ) : (
            <FiMenu className="m-auto h-4" />
          )}
        </BottomNavItem>
      </div>

      <BottomNavItem
        tooltip={
          appState.updateAvaliable ? 'Update Avaliable' : 'Current Commit'
        }
        onClick={(): void => {
          setShowVersionInfo(true);
        }}
        className={appState.updateAvaliable ? 'animate-pulse' : ''}
      >
        {appState.updateAvaliable ? (
          <MdUpgrade className="h-4" />
        ) : (
          <FiGitBranch className="h-4" />
        )}
        <p className="text-xs opacity-60">{process.env.COMMIT_HASH}</p>
      </BottomNavItem>

      <BottomNavItem
        tooltip="Toggle Theme"
        onClick={(): void => {
          dispatch(setDarkModeEnabled(!appState.darkMode));
        }}
      >
        {appState.darkMode ? (
          <FiSun className="h-4" />
        ) : (
          <FiMoon className="h-4" />
        )}
      </BottomNavItem>

      <VersionInfo
        modalOpen={showVersionInfo}
        onClose={(): void => {
          setShowVersionInfo(false);
        }}
      />
    </div>
  );
}
Example #17
Source File: PermissionsInformation.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
PermissionsInformation = observer(() => {
  const {
    context: { daoStore, configStore, providerStore },
  } = useContext();

  const web3 = providerStore.getActiveWeb3React().library;
  const schemes = daoStore.getAllSchemes();
  const rawPermissions = daoStore.daoCache.callPermissions;
  const networkContracts = configStore.getNetworkContracts();
  const tokens = configStore.getTokensOfNetwork();
  const recommendedCalls = configStore.getRecommendedCalls();
  let addressesNames = {};
  let functionNames = {};
  addressesNames[ZERO_ADDRESS] =
    NETWORK_ASSET_SYMBOL[configStore.getActiveChainName()];
  addressesNames[ANY_ADDRESS] = 'Any Address';
  addressesNames[networkContracts.avatar] = 'Avatar';
  addressesNames[networkContracts.controller] = 'Controller';
  for (const votingMachineAddress in networkContracts.votingMachines) {
    addressesNames[votingMachineAddress] =
      networkContracts.votingMachines[votingMachineAddress].type;
  }

  functionNames[
    web3.eth.abi.encodeFunctionSignature('mintTokens(uint256,address,address)')
  ] = 'mintTokens(uint256,address,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature('unregisterSelf(address)')
  ] = 'unregisterSelf(address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature(
      'addGlobalConstraint(address,bytes32,address)'
    )
  ] = 'addGlobalConstraint(address,bytes32,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature(
      'removeGlobalConstraint(address,address)'
    )
  ] = 'removeGlobalConstraint(address,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature('upgradeController(address,address)')
  ] = 'upgradeController(address,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature('sendEther(uint256,address,address)')
  ] = 'sendEther(uint256,address,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature(
      'externalTokenTransfer(address,address,uint256,address)'
    )
  ] = 'externalTokenTransfer(address,address,uint256,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature(
      'externalTokenTransferFrom(address,address,address,uint256,address)'
    )
  ] = 'externalTokenTransferFrom(address,address,address,uint256,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature(
      'externalTokenApproval(address,address,uint256,address)'
    )
  ] = 'externalTokenApproval(address,address,uint256,address)';
  functionNames[
    web3.eth.abi.encodeFunctionSignature('metaData(string,address)')
  ] = 'metaData(string,address)';

  functionNames[ERC20_TRANSFER_SIGNATURE] = 'ERC20 Transfer';
  functionNames[ERC20_APPROVE_SIGNATURE] = 'ERC20 Approve';
  recommendedCalls.map(recommendedCall => {
    functionNames[
      web3.eth.abi.encodeFunctionSignature(recommendedCall.functionName)
    ] = recommendedCall.functionName;
  });
  schemes.map(scheme => {
    addressesNames[scheme.address] = scheme.name;
  });
  tokens.map(token => {
    addressesNames[token.address] = token.symbol;
  });

  const permissions = [];

  for (const assetAddress in rawPermissions) {
    for (const fromAddress in rawPermissions[assetAddress]) {
      for (const toAddress in rawPermissions[assetAddress][fromAddress]) {
        for (const functionSignature in rawPermissions[assetAddress][
          fromAddress
        ][toAddress]) {
          const value =
            rawPermissions[assetAddress][fromAddress][toAddress][
              functionSignature
            ].value.toString();
          permissions.push({
            asset: addressesNames[assetAddress] || assetAddress,
            from: addressesNames[fromAddress] || fromAddress,
            to: addressesNames[toAddress] || toAddress,
            functionSignature:
              functionSignature === ANY_FUNC_SIGNATURE
                ? 'Any Function'
                : functionSignature,
            value:
              value ===
              '115792089237316195423570985008687907853269984665640564039457584007913129639935'
                ? 'ANY Value'
                : value,
            fromTime:
              rawPermissions[assetAddress][fromAddress][toAddress][
                functionSignature
              ].fromTime,
          });
        }
      }
    }
  }
  return (
    <PermissionsTable>
      <TableHeader>
        <HeaderCell>Asset</HeaderCell>
        <HeaderCell>From</HeaderCell>
        <HeaderCell>To</HeaderCell>
        <HeaderCell>Function</HeaderCell>
        <HeaderCell>Value</HeaderCell>
        <HeaderCell>From Time</HeaderCell>
      </TableHeader>
      <TableBody>
        {permissions.map((permission, i) => (
          <TableRow key={`permission${i}`}>
            <DataCell>{permission.asset}</DataCell>
            <DataCell>{permission.from}</DataCell>
            <DataCell>{permission.to}</DataCell>
            <DataCell>
              {functionNames[permission.functionSignature] ||
                permission.functionSignature}
            </DataCell>
            <DataCell>{permission.value}</DataCell>
            <DataCell>
              {permission.fromTime === 0 ? (
                <FiX />
              ) : (
                timestampToDate(bnum(permission.fromTime))
              )}
            </DataCell>
          </TableRow>
        ))}
      </TableBody>
    </PermissionsTable>
  );
})
Example #18
Source File: TransactionModal.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
TransactionModal: React.FC<TransactionModalProps> = ({
  message,
  transactionHash,
  txCancelled,
  onCancel,
}) => {
  const { chainId } = useWeb3React();
  const modalView = useMemo<TransactionModalView>(() => {
    if (txCancelled) {
      return TransactionModalView.Reject;
    } else if (transactionHash) {
      return TransactionModalView.Submit;
    } else {
      return TransactionModalView.Confirm;
    }
  }, [txCancelled, transactionHash]);

  const [header, children, footerText] = useMemo(() => {
    let header: JSX.Element, children: JSX.Element, footerText: string;

    switch (modalView) {
      case TransactionModalView.Confirm:
        header = (
          <Header>
            <PendingCircle height="86px" width="86px" color="black" />
          </Header>
        );
        children = (
          <Flex>
            <Container>
              <ContainerText variant="bold">
                Waiting For Confirmation
              </ContainerText>
              <ContainerText variant="medium">{message}</ContainerText>
            </Container>
            <ContainerText variant="medium" color="grey">
              Confirm this Transaction in your Wallet
            </ContainerText>
          </Flex>
        );
        break;
      case TransactionModalView.Submit:
        header = (
          <Header>
            <Circle>
              <AiOutlineArrowUp size={40} />
            </Circle>
          </Header>
        );

        const networkName = getChains().find(
          chain => chain.id === chainId
        ).name;
        children = (
          <Flex>
            <ContainerText variant="bold">Transaction Submitted</ContainerText>
            <Container>
              <ContainerText
                as="a"
                variant="regular"
                color="grey"
                href={getBlockchainLink(transactionHash, networkName)}
                target="_blank"
              >
                View on Block Explorer
              </ContainerText>
            </Container>
          </Flex>
        );
        footerText = 'Close';
        break;
      case TransactionModalView.Reject:
        header = (
          <Header>
            <Circle>
              <FiX size={40} />
            </Circle>
          </Header>
        );
        children = (
          <Flex>
            <ContainerText variant="bold">Transaction Rejected</ContainerText>
          </Flex>
        );
        footerText = 'Dismiss';
        break;
    }

    return [header, children, footerText];
  }, [modalView, chainId, message, transactionHash]);

  return (
    <Modal
      isOpen={!!message}
      onDismiss={onCancel}
      children={children}
      contentHeader={header}
      cross
      hideHeader
      showSecondaryHeader
      onCancel={onCancel}
      maxWidth={300}
      cancelText={footerText}
      zIndex={1000}
    />
  );
}
Example #19
Source File: ERC20TransferEditor.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
Transfer: React.FC<ActionEditorProps> = ({ decodedCall, updateCall }) => {
  const [isTokenPickerOpen, setIsTokenPickerOpen] = useState(false);

  const { chainId } = useWeb3React();

  // parse transfer state from calls
  const parsedData = useMemo<TransferState>(() => {
    if (!decodedCall) return null;
    return {
      source: decodedCall.from,
      tokenAddress: decodedCall.to,
      amount: decodedCall.args._value,
      destination: decodedCall.args._to,
    };
  }, [decodedCall]);

  const validations = useMemo(() => {
    return {
      tokenAddress: utils.isAddress(parsedData?.tokenAddress),
      amount: BigNumber.isBigNumber(parsedData?.amount),
      destination: utils.isAddress(parsedData?.destination),
    };
  }, [parsedData]);

  // Get token details from the token address
  const { tokens } = useTokenList(chainId);
  const token = useMemo(() => {
    if (!parsedData?.tokenAddress || !tokens) return null;

    return tokens.find(({ address }) => address === parsedData.tokenAddress);
  }, [tokens, parsedData]);

  const { data: tokenInfo } = useERC20Info(parsedData?.tokenAddress);
  const roundedBalance = useBigNumberToNumber(
    parsedData?.amount,
    tokenInfo?.decimals,
    10
  );
  const { imageUrl: destinationAvatarUrl } = useENSAvatar(
    parsedData?.destination,
    MAINNET_ID
  );

  const setTransferAddress = (walletAddress: string) => {
    updateCall({
      ...decodedCall,
      args: {
        ...decodedCall.args,
        _to: walletAddress,
      },
    });
  };

  const setToken = (tokenAddress: string) => {
    updateCall({
      ...decodedCall,
      to: tokenAddress,
    });
  };

  const setAmount = (value: string) => {
    const amount = value
      ? utils.parseUnits(value, tokenInfo?.decimals || 18)
      : null;
    updateCall({
      ...decodedCall,
      args: {
        ...decodedCall.args,
        _value: amount,
      },
    });
  };

  return (
    <div>
      <Control>
        <ControlLabel>Recipient</ControlLabel>
        <ControlRow>
          <Input
            value={parsedData.destination || ''}
            icon={
              <div>
                {validations.destination && (
                  <Avatar
                    src={destinationAvatarUrl}
                    defaultSeed={parsedData.destination}
                    size={24}
                  />
                )}
              </div>
            }
            iconRight={
              parsedData?.destination ? (
                <ClickableIcon onClick={() => setTransferAddress('')}>
                  <FiX size={18} />
                </ClickableIcon>
              ) : null
            }
            placeholder="Ethereum address"
            onChange={e => setTransferAddress(e.target.value)}
          />
        </ControlRow>
      </Control>

      <ControlRow>
        <Control>
          <ControlLabel>Amount</ControlLabel>
          <ControlRow>
            <TransferAmountInput
              value={roundedBalance}
              onUserInput={setAmount}
            />
          </ControlRow>
        </Control>

        <Spacer />

        <Control>
          <ControlLabel>Asset</ControlLabel>
          <ControlRow onClick={() => setIsTokenPickerOpen(true)}>
            <Input
              value={tokenInfo?.symbol || ''}
              placeholder="Token"
              icon={
                <div>
                  {parsedData?.tokenAddress && (
                    <Avatar
                      src={resolveUri(token?.logoURI)}
                      defaultSeed={parsedData?.tokenAddress}
                      size={18}
                    />
                  )}
                </div>
              }
              iconRight={<FiChevronDown size={24} />}
              readOnly
            />
          </ControlRow>
        </Control>
      </ControlRow>

      <TokenPicker
        walletAddress={parsedData?.source || ''}
        isOpen={isTokenPickerOpen}
        onClose={() => setIsTokenPickerOpen(false)}
        onSelect={tokenAddress => {
          setToken(tokenAddress);
          setIsTokenPickerOpen(false);
        }}
      />
    </div>
  );
}