react-icons/fi#FiCheckCircle TypeScript Examples

The following examples show how to use react-icons/fi#FiCheckCircle. 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: Transaction.tsx    From dxvote with GNU Affero General Public License v3.0 6 votes vote down vote up
Transaction: React.FC<TransactionProps> = ({ transaction }) => {
  const { chainId } = useWeb3React();
  const networkName = getChains().find(chain => chain.id === chainId).name;
  return (
    <TransactionContainer>
      <Link
        href={getBlockchainLink(transaction.hash, networkName)}
        target="_blank"
      >
        {transaction.summary} <FiArrowUpRight />
      </Link>
      <Icon>
        {!transaction.receipt ? (
          <PendingCircle height="16px" width="16px" color="#000" />
        ) : transaction.receipt?.status === 1 ? (
          <FiCheckCircle />
        ) : (
          <FiXCircle />
        )}
      </Icon>
    </TransactionContainer>
  );
}
Example #2
Source File: Copy.tsx    From dxvote with GNU Affero General Public License v3.0 6 votes vote down vote up
export default function CopyHelper({ toCopy, children = null }) {
  const [isCopied, setCopied] = useCopyClipboard();

  return (
    <CopyIcon onClick={() => setCopied(toCopy)}>
      <TransactionStatusText>
        {children} {isCopied ? <FiCheckCircle /> : <FiCopy />}
      </TransactionStatusText>
    </CopyIcon>
  );
}
Example #3
Source File: Timeline.tsx    From portfolio with MIT License 6 votes vote down vote up
TimelineItem: React.FC<TimelineItemProps> = ({
  icon = FiCheckCircle,
  boxProps = {},
  skipTrail = false,
  children,
  ...props
}) => {
  const color = useColorModeValue("gray.700", "gray.500");
  return (
    <Flex minH={20} {...props}>
      <Flex flexDir="column" alignItems="center" mr={4} pos="relative">
        <Circle
          size={12}
          bg={useColorModeValue("gray.600", "gray.500")}
          opacity={useColorModeValue(0.07, 0.15)}
          sx={{}}
        />
        <Box
          as={icon}
          size="1.25rem"
          color={color}
          pos="absolute"
          left="0.875rem"
          top="0.875rem"
        />
        {!skipTrail && <Box w="1px" flex={1} bg={color} my={1} />}
      </Flex>
      <Box pt={3} {...boxProps}>
        {children}
      </Box>
    </Flex>
  );
}
Example #4
Source File: index.tsx    From GoBarber with MIT License 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  error: <FiAlertCircle size={24} />,
  success: <FiCheckCircle size={24} />,
}
Example #5
Source File: index.tsx    From gobarber-project with MIT License 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  error: <FiAlertCircle size={24} />,
  success: <FiCheckCircle size={24} />,
}
Example #6
Source File: index.tsx    From vagasExplorer with MIT License 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  error: <FiAlertCircle size={24} />,
  sucess: <FiCheckCircle size={24} />,
}
Example #7
Source File: index.tsx    From rocketredis with MIT License 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  success: <FiCheckCircle size={24} />,
  error: <FiAlertCircle size={24} />
}
Example #8
Source File: index.tsx    From front-entenda-direito with GNU General Public License v3.0 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  success: <FiCheckCircle size={24} />,
  error: <FiAlertCircle size={24} />,
}
Example #9
Source File: index.tsx    From front-entenda-direito with GNU General Public License v3.0 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  success: <FiCheckCircle size={24} />,
  error: <FiAlertCircle size={24} />,
}
Example #10
Source File: index.tsx    From ecoleta with MIT License 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  error: <FiAlertCircle size={24} />,
  success: <FiCheckCircle size={24} />,
}
Example #11
Source File: story-timeline.tsx    From portfolio with MIT License 5 votes vote down vote up
StoryTimeline: React.FC<StoryTimelineProps> = ({
  icon = FiCheckCircle,
  boxProps = {},
  index,
  year,
  skipTrail = false,
  children,
  ...props
}) => {
  const [isOpen, setIsOpen] = React.useState(true);
  const open = () => setIsOpen(!isOpen);
  const close = () => setIsOpen(false);
  const color = useColorModeValue("gray.700", "gray.200");
  let place = index % 2 === 0 ? "right" : "left";

  return (
    <Flex minH={20} {...props}>
      <Flex flexDir="column" alignItems={"center"} minHeight={"8rem"} mr={4}>
        <Popover
          returnFocusOnClose={false}
          isOpen={isOpen}
          onClose={close}
          placement={place}
          closeOnBlur={false}
          // variant="responsive"
          width={["9.3rem", "13rem", "15rem", "100%"]}
        >
          <PopoverTrigger>
            <Box onClick={open} position="relative">
              <Circle
                size={12}
                bg={useColorModeValue("gray.600", "gray.500")}
                opacity={useColorModeValue(0.07, 0.15)}
                sx={{}}
              />
              {year ? (
                <Box
                  fontSize={15}
                  fontWeight={"bold"}
                  color={color}
                  pos="absolute"
                  left="0.5rem"
                  top="0.875rem"
                >
                  {year}
                </Box>
              ) : (
                <Box
                  as={icon}
                  size="1.25rem"
                  color={color}
                  pos="absolute"
                  left="0.875rem"
                  top="0.875rem"
                />
              )}
            </Box>
          </PopoverTrigger>
          <Box fontSize={15}>
            {!year && (
              <PopoverContent padding={["0.2rem", "0.2rem", "0.7rem"]}>
                <PopoverArrow />
                {/* <PopoverCloseButton /> */}
                <PopoverBody>
                  <Box overflow="scroll">{children}</Box>
                </PopoverBody>
              </PopoverContent>
            )}
          </Box>
        </Popover>
        {!skipTrail && <Box w="1px" flex={1} bg={color} />}
      </Flex>
    </Flex>
  );
}
Example #12
Source File: index.tsx    From gobarber-web with MIT License 5 votes vote down vote up
icons = {
  info: <FiInfo size={24} />,
  error: <FiAlertCircle size={24} />,
  success: <FiCheckCircle size={24} />,
}
Example #13
Source File: index.tsx    From dxvote with GNU Affero General Public License v3.0 5 votes vote down vote up
IconMap = {
  [ResultState.SUCCESS]: FiCheckCircle,
  [ResultState.ERROR]: FiXOctagon,
  [ResultState.INFO]: FiHelpCircle,
  [ResultState.WARNING]: FiAlertTriangle,
}
Example #14
Source File: WalletInfoBox.tsx    From dxvote with GNU Affero General Public License v3.0 5 votes vote down vote up
export default function WalletInfoBox({ openOptions }: Props) {
  const { account, connector, chainId } = useWeb3React();
  const { ensName, imageUrl } = useENSAvatar(account, MAINNET_ID);
  const [isCopied, copyAddress] = useClipboard(account, 3000);

  const networkName = NETWORK_NAMES[chainId];

  return (
    <Wrapper>
      <ConnectionStatusRow>
        <ConnectionStatusText>
          <LiveIndicator />
          Connected to {findWalletType(connector)}
        </ConnectionStatusText>
        {isDesktop && (
          <div>
            <Button onClick={openOptions}>Change</Button>
          </div>
        )}
      </ConnectionStatusRow>

      <WalletAddressRow>
        <IconHolder>
          <Avatar src={imageUrl} defaultSeed={account} size={24} />
        </IconHolder>
        <AddressText>{ensName || shortenAddress(account)}</AddressText>
      </WalletAddressRow>

      <Row>
        <ConnectionActionButton
          variant="minimal"
          onClick={copyAddress}
          iconLeft
        >
          {isCopied ? <FiCheckCircle /> : <FiCopy />}
          {isCopied ? 'Copied Address!' : 'Copy Address'}
        </ConnectionActionButton>

        <ExternalLink
          href={getBlockchainLink(account, networkName, 'address')}
          target="_blank"
        >
          <ConnectionActionButton variant="minimal" iconLeft>
            <FiExternalLink />
            View on Explorer
          </ConnectionActionButton>
        </ExternalLink>
      </Row>
      {isMobile && (
        <CenteredButton onClick={openOptions}>Change Connection</CenteredButton>
      )}
    </Wrapper>
  );
}
Example #15
Source File: index.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
ProposalsPage = observer(() => {
  const {
    context: { daoStore, configStore, providerStore },
  } = useContext();

  const { getRep } = useRep();

  const votingMachines = configStore.getNetworkContracts().votingMachines;
  const networkName = configStore.getActiveChainName();
  const { account } = providerStore.getActiveWeb3React();
  const userEvents = daoStore.getUserEvents(account);

  const {
    proposals,
    loading,
    titleFilter,
    setTitleFilter,
    stateFilter,
    setStateFilter,
    schemesFilter,
    setSchemesFilter,
  } = useFilteredProposals();

  const allProposals = daoStore.getAllProposals();
  const activeProposalsCount = allProposals.filter(
    proposal =>
      proposal.stateInVotingMachine > VotingMachineProposalState.Executed
  ).length;

  const history = useHistory();
  return (
    <ProposalsWrapper>
      <SidebarWrapper>
        <ProposalTableHeaderActions>
          <NewProposalButton>
            <LinkButton route={`/${networkName}/create/type`} width="200px">
              + New Proposal
            </LinkButton>
          </NewProposalButton>
          <TitleSearch value={titleFilter} onFilter={setTitleFilter} />
          <StatusSearch value={stateFilter} onFilter={setStateFilter} />
          <SchemeSearch value={schemesFilter} onFilter={setSchemesFilter} />
          <strong style={{ alignSelf: 'center' }}>
            {allProposals.length} Total Proposals
          </strong>
          <strong style={{ alignSelf: 'center' }}>
            {activeProposalsCount} Active Proposals
          </strong>
        </ProposalTableHeaderActions>
        <FooterWrap>
          <ProposalsExporter />
          <Footer />
        </FooterWrap>
      </SidebarWrapper>
      {loading && (
        <LoadingBox>
          <div className="loader">
            <PulsingIcon size={80} inactive={false} />
          </div>
        </LoadingBox>
      )}
      {!loading && (
        <TableProposal>
          <TableHeader>
            <TableRow>
              <HeaderCell>Title</HeaderCell>
              <HeaderCell>Scheme</HeaderCell>
              <HeaderCell>Status</HeaderCell>
              <HeaderCell>Stakes</HeaderCell>
              <HeaderCell>Votes</HeaderCell>
            </TableRow>
          </TableHeader>
          <TableBody>
            {proposals.map((proposal, i) => {
              const positiveStake = formatNumberValue(
                normalizeBalance(proposal.positiveStakes, 18),
                1
              );
              const negativeStake = formatNumberValue(
                normalizeBalance(proposal.negativeStakes, 18),
                1
              );

              const repAtCreation = getRep(
                proposal.creationEvent.blockNumber
              ).totalSupply;

              const positiveVotesPercentage = formatPercentage(
                proposal.positiveVotes.div(repAtCreation),
                2
              );
              const negativeVotesPercentage = formatPercentage(
                proposal.negativeVotes.div(repAtCreation),
                2
              );
              const timeToBoost = timeToTimestamp(proposal.boostTime);
              const timeToFinish = timeToTimestamp(proposal.finishTime);

              const votingMachineTokenName =
                votingMachines[
                  daoStore.getVotingMachineOfProposal(proposal.id).address
                ].type == 'DXDVotingMachine'
                  ? 'DXD'
                  : 'GEN';

              const voted =
                userEvents.votes.findIndex(
                  event => event.proposalId === proposal.id
                ) > -1;
              const staked =
                userEvents.stakes.findIndex(
                  event => event.proposalId === proposal.id
                ) > -1;
              const created =
                userEvents.newProposal.findIndex(
                  event => event.proposalId === proposal.id
                ) > -1;

              const proposerVotedDown =
                daoStore
                  .getVotesOfProposal(proposal.id)
                  .findIndex(
                    vote =>
                      vote.voter === proposal.proposer && isVoteNo(vote.vote)
                  ) > -1;

              return (
                <StyledTableRow
                  onClick={() =>
                    history.push(`/${networkName}/proposal/${proposal.id}`)
                  }
                  key={`row-${i}`}
                >
                  <DataCell
                    weight="800"
                    wrapText="true"
                    fontSize="inherit"
                    align="left"
                  >
                    <Link
                      to={`/${networkName}/proposal/${proposal.id}`}
                      component={UnstyledAnchor}
                    >
                      {created && (
                        <FiFeather
                          style={{ minWidth: '15px', margin: '0px 2px' }}
                          title="You created"
                        />
                      )}
                      {voted && (
                        <FiCheckCircle
                          style={{ minWidth: '15px', margin: '0px 2px' }}
                          title="You voted"
                        />
                      )}
                      {staked && (
                        <FiCheckSquare
                          style={{ minWidth: '15px', margin: '0px 2px' }}
                          title="You staked"
                        />
                      )}

                      {proposerVotedDown && (
                        <FiAlertTriangle
                          style={{ minWidth: '15px', margin: '0px 2px' }}
                          title="The proposer downvoted this proposal. It may be incorrect."
                        />
                      )}

                      {proposal.title.length > 0 ? proposal.title : proposal.id}
                    </Link>
                  </DataCell>
                  <DataCell>
                    {daoStore.daoCache.schemes[proposal.scheme].name}
                  </DataCell>
                  <DataCell>
                    <span>
                      {proposal.status} <br />
                      {timeToBoost !== '' ? (
                        <small>
                          Boost {timeToBoost} <br />
                        </small>
                      ) : (
                        <span></span>
                      )}
                      {timeToFinish !== '' ? (
                        <small>Finish {timeToFinish} </small>
                      ) : (
                        <span></span>
                      )}
                      {proposal.pendingAction === PendingAction.Execute ||
                      proposal.pendingAction === PendingAction.Finish ? (
                        <small> Pending Finish Execution </small>
                      ) : (
                        <span></span>
                      )}
                    </span>
                  </DataCell>
                  <DataCell>
                    <Positive>
                      {positiveStake.toString()} {votingMachineTokenName}{' '}
                    </Positive>
                    <Separator>|</Separator>
                    <Negative>
                      {negativeStake.toString()} {votingMachineTokenName}
                    </Negative>
                  </DataCell>
                  <DataCell>
                    <Positive>{positiveVotesPercentage} </Positive>
                    <Separator>|</Separator>
                    <Negative>{negativeVotesPercentage}</Negative>
                  </DataCell>
                </StyledTableRow>
              );
            })}
          </TableBody>
        </TableProposal>
      )}
    </ProposalsWrapper>
  );
})
Example #16
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 #17
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 #18
Source File: Upload.tsx    From tobira with Apache License 2.0 4 votes vote down vote up
UploadMain: React.FC = () => {
    // TODO: on first mount, send an `ocRequest` to `info/me.json` and make sure
    // that connection works. That way we can show an error very early, before
    // the user selected a file.

    const { t } = useTranslation();
    const relayEnv = useRelayEnvironment();

    const [files, setFiles] = useState<FileList | null>(null);
    const [uploadState, setUploadState] = useRefState<UploadState | null>(null);
    const [metadata, setMetadata] = useRefState<Metadata | null>(null);

    const progressHistory = useRef<ProgressHistory>([]);

    useNavBlocker(() => !!uploadState.current && uploadState.current.state !== "done");

    // Get user info
    const user = useUser();
    if (user === "none" || user === "unknown") {
        // TODO: if not logged in, suggest doing so
        return <div css={{ textAlign: "center" }}>
            <ErrorBox>{t("upload.not-authorized")}</ErrorBox>
        </div>;
    }

    /** Called when the files are selected. Starts uploading those files. */
    const onFileSelect = async (files: FileList) => {
        setFiles(files);

        const onProgressCallback = (progress: Progress): void => {
            if (uploadState.current === null) {
                return unreachable("no upload state after calling `startUpload`");
            }
            onProgress(progress, progressHistory.current, uploadState.current, setUploadState);
        };
        const onDone = (mediaPackage: string) => {
            if (metadata.current === null) {
                setUploadState({ state: "waiting-for-metadata", mediaPackage });
            } else {
                finishUpload(relayEnv, mediaPackage, metadata.current, user, setUploadState);
            }
        };
        startUpload(relayEnv, files, setUploadState, onProgressCallback, onDone);
    };

    if (files === null) {
        return <FileSelect onSelect={onFileSelect} />;
    } else if (uploadState.current === null) {
        // This never happens as, when files are selected, the upload is
        // instantly started and the state is set to `starting`. Check the only
        // use of `setFiles` above and notice how the upload state is set
        // immediately afterwards.
        return unreachable("upload state is null, but there are files");
    } else if (uploadState.current.state === "done") {
        return <div css={{
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            marginTop: "max(16px, 10vh - 50px)",
            gap: 32,
        }}>
            <FiCheckCircle css={{ fontSize: 64, color: "var(--happy-color-lighter)" }} />
            {t("upload.finished")}
        </div>;
    } else {
        const onMetadataSave = (metadata: Metadata): void => {
            if (uploadState.current === null) {
                return bug("uploadState === null on metadata save");
            }

            setMetadata(metadata);
            if (uploadState.current.state === "waiting-for-metadata") {
                // The tracks have already been uploaded, so we can finish the upload now.
                const mediaPackage = uploadState.current.mediaPackage;
                finishUpload(relayEnv, mediaPackage, metadata, user, setUploadState);
            }
        };
        const hasUploadError = uploadState.current.state === "error";

        return (
            <div css={{
                display: "flex",
                flexDirection: "column",
                alignItems: "stretch",
                gap: 32,
                width: "100%",
                maxWidth: 800,
                margin: "0 auto",
            }}>
                <UploadState state={uploadState.current} />
                <div css={{ overflowY: "auto" }}>
                    {/* TODO: Show something after saving metadata.
                        - Just saying "saved" is kind of misleading because the data is only local.
                        - Maybe just show the form, but disable all inputs?
                        - ...
                    */}
                    {!metadata.current
                        ? <MetaDataEdit onSave={onMetadataSave} disabled={hasUploadError} />
                        : !hasUploadError && (
                            <div css={{ margin: "0 auto", maxWidth: 500 }}>
                                <Card kind="info">{t("upload.still-uploading")}</Card>
                            </div>
                        )
                    }
                </div>
            </div>
        );
    }
}
Example #19
Source File: transactions.tsx    From dxvote with GNU Affero General Public License v3.0 4 votes vote down vote up
TransactionsProvider = ({ children }) => {
  const { chainId, account } = useWeb3React();

  const [transactions, setTransactions] = useLocalStorage<TransactionState>(
    `transactions/${account}`,
    {}
  );
  const [pendingTransaction, setPendingTransaction] =
    useState<PendingTransaction>(null);

  // Get the transactions from the current chain
  const allTransactions = useMemo(() => {
    return transactions[chainId] ? Object.values(transactions[chainId]) : [];
  }, [transactions, chainId]);

  const addTransaction = (
    txResponse: providers.TransactionResponse,
    summary?: string
  ) => {
    if (!txResponse.hash) return;

    const transaction: Transaction = {
      hash: txResponse.hash,
      from: txResponse.from,
      summary,
      addedTime: Date.now(),
    };

    setTransactions(prevState => ({
      ...prevState,
      [chainId]: {
        ...prevState[chainId],
        [transaction.hash]: transaction,
      },
    }));
  };

  const clearAllTransactions = () => {
    setTransactions(prevState => ({
      ...prevState,
      [chainId]: {},
    }));
  };

  const finalizeTransaction = useCallback(
    (hash: string, receipt: providers.TransactionReceipt) => {
      if (!transactions[chainId] || !transactions[chainId][hash]) {
        return;
      }

      setTransactions(prevState => ({
        ...prevState,
        [chainId]: {
          ...prevState[chainId],
          [hash]: {
            ...prevState[chainId][hash],
            receipt: {
              transactionHash: receipt.transactionHash,
              blockNumber: receipt.blockNumber,
              status: receipt.status,
            },
            confirmedTime: Date.now(),
          },
        },
      }));
    },
    [transactions, chainId, setTransactions]
  );

  // Mark the transactions as finalized when they are mined
  const provider = useJsonRpcProvider();
  useEffect(() => {
    let isSubscribed = true;

    allTransactions
      .filter(transaction => !transaction.receipt)
      .forEach(transaction => {
        provider.waitForTransaction(transaction.hash).then(receipt => {
          if (isSubscribed) finalizeTransaction(transaction.hash, receipt);
        });
      });

    return () => {
      isSubscribed = false;
    };
  }, [allTransactions, finalizeTransaction, provider]);

  // Update the pending transaction notifications when finalized
  useEffect(() => {
    allTransactions.forEach(transaction => {
      if (transaction.receipt && toast.isActive(transaction.hash)) {
        if (transaction.receipt.status === 1) {
          toast.update(transaction.hash, {
            isLoading: false,
            render: (
              <TransactionOutcome
                summary={transaction.summary}
                chainId={chainId}
                transactionHash={transaction.hash}
              />
            ),
            icon: <FiCheckCircle />,
            type: toast.TYPE.SUCCESS,
            autoClose: 15000,
          });
        } else {
          toast.update(transaction.hash, {
            isLoading: false,
            render: (
              <TransactionOutcome
                summary={transaction.summary}
                chainId={chainId}
                transactionHash={transaction.hash}
              />
            ),
            icon: <FiXCircle />,
            type: toast.TYPE.ERROR,
            autoClose: 15000,
          });
        }
      }
    });
  }, [allTransactions, chainId]);

  // Trigger a new transaction request to the user wallet and track its progress
  const createTransaction = async (
    summary: string,
    txFunction: () => Promise<providers.TransactionResponse>,
    showModal: boolean = true
  ) => {
    setPendingTransaction({
      summary,
      showModal,
      cancelled: false,
      transactionHash: null,
    });
    let transactionHash = null;
    try {
      const txResponse = await txFunction();
      transactionHash = txResponse.hash;
      addTransaction(txResponse, summary);
      setPendingTransaction(pendingTransaction => ({
        ...pendingTransaction,
        transactionHash,
      }));
      toast(<TransactionPending summary={summary} />, {
        toastId: transactionHash,
        autoClose: false,
        isLoading: true,
      });
    } catch (e) {
      console.error('Transaction execution failed', e);
      setPendingTransaction(pendingTransaction => ({
        ...pendingTransaction,
        cancelled: true,
      }));
    }
  };

  return (
    <TransactionsContext.Provider
      value={{
        transactions: allTransactions,
        pendingTransaction,
        createTransaction,
        clearAllTransactions,
      }}
    >
      {children}

      <TransactionModal
        message={pendingTransaction?.summary}
        transactionHash={pendingTransaction?.transactionHash}
        onCancel={() => setPendingTransaction(null)}
        txCancelled={pendingTransaction?.cancelled}
      />
    </TransactionsContext.Provider>
  );
}