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

The following examples show how to use @fortawesome/free-solid-svg-icons#faInfoCircle. 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: LessonSelect.tsx    From frontend.ro with MIT License 6 votes vote down vote up
function LessonSelect({ selectedId, onChange } : Props) {
  const chapterLessonPairs = LESSONS
    .filter((lesson) => lesson.written)
    .map((lesson) => ({
      value: {
        chapter: lesson.type,
        // FIXME
        id: lesson.url.split('/').pop(),
      },
      label: `${lesson.type}/${lesson.title}`,
    }));

  const defaultValue = chapterLessonPairs.find((pair) => pair.label === selectedId);

  return (
    <div className={styles['lesson-select']}>
      <p>
        <FontAwesomeIcon width="16" height="16" icon={faInfoCircle} />
        Dacă vrei să sugerezi acest exercițiu pentru una din lecțiile existente,
        alege de mai jos:
      </p>
      <ReactSelect
        isSearchable
        placeholder=""
        onChange={onChange}
        className={styles.select}
        defaultValue={defaultValue}
        options={chapterLessonPairs}
      />
    </div>
  );
}
Example #2
Source File: index.tsx    From MagicUI with Apache License 2.0 6 votes vote down vote up
ToolBar: React.FC = (props) => {
  const user = useSelector((state: IStoreState) => state.user);
  const handleAvatarClick = () => {
    Bridge.open(WidgetType.USER, user);
  };

  return (
    <div className={style.header_navigation}>
      <div className={style.right_content}>
        <div className={style.tools_bar}>
          <button className={style.help_btn} onClick={() => history.push(Routers.HELP)}>
            <FontAwesomeIcon icon={faInfoCircle}/>
          </button>
          <button className={style.todo_btn}>
            <FontAwesomeIcon icon={faCalendarCheck}/>
          </button>
          <button className={style.msg_btn}>
            <FontAwesomeIcon icon={faBell}/>
          </button>
          <button className={style.chart_btn}>
            <FontAwesomeIcon icon={faChartBar}/>
          </button>
        </div>
        <div className={style.avatar_wrapper}>
          <Avatar src={user.avatar as string} onClick={handleAvatarClick}/>
        </div>
      </div>
    </div>
  );
}
Example #3
Source File: index.tsx    From bad-cards-game with GNU Affero General Public License v3.0 6 votes vote down vote up
library.add(
  faDotCircle,
  faCircle,
  faBars,
  faTimes,
  faInfoCircle,
  faTrophy,
  faShareSquare,
  faHeart,
  faInstagram,
  faTwitter,
  faGithub,
  faFacebook,
  faHandPointRight,
  faEdit,
  faSave,
  faCamera,
  faPlus,
  faMinus,
  faRandom,
);
Example #4
Source File: Info.tsx    From longwave with MIT License 6 votes vote down vote up
export function Info(props: { children: string | ReactElement<any> }) {
  return (
    <Tippy content={props.children} placement="bottom">
      <div style={{ margin: 8 }}>
        <FontAwesomeIcon icon={faInfoCircle} />
      </div>
    </Tippy>
  );
}
Example #5
Source File: PrivacyControls.tsx    From frontend.ro with MIT License 6 votes vote down vote up
function PrivacyControls(props: Props) {
  // ceva
  const { isPrivate, onPrivacyChange, form } = props;

  return (
    <div className={styles['privacy-controls']}>
      <Checkbox
        form={form}
        className="d-block"
        type="radio"
        name="private"
        onChange={() => onPrivacyChange(false)}
        checked={!isPrivate}
        value="false"
      >
        Public
      </Checkbox>
      <Checkbox
        form={form}
        className="d-block"
        type="radio"
        name="private"
        onChange={() => onPrivacyChange(true)}
        checked={isPrivate}
        value="true"
      >
        Privat
      </Checkbox>
      <p>
        <FontAwesomeIcon width="16" icon={faInfoCircle} />
        {isPrivate ? PRIVATE_INFO : PUBLIC_INFO}
      </p>
    </div>
  );
}
Example #6
Source File: create-position.component.ts    From 1x.ag with MIT License 5 votes vote down vote up
info = faInfoCircle;
Example #7
Source File: NetworkSwitcher.tsx    From devex with GNU General Public License v3.0 5 votes vote down vote up
NetworkSwitcher: React.FC = () => {

  const history = useHistory()
  const networkName = useNetworkName()
  const networkUrl = useNetworkUrl()

  const userPrefContext = useContext(UserPrefContext)
  const { networkMap } = userPrefContext!

  const [showDropdown, setShowDropdown] = useState(false)
  const [currentNetwork, setCurrentNetwork] = useState(networkName)

  useEffect(() => {
    setCurrentNetwork(networkName)
  }, [networkName])

  const changeNetwork = useCallback((k: string) => {
    history.push({
      pathname: '/',
      search: '?' + new URLSearchParams({ network: k }).toString()
    })
  }, [history])

  return (
    <Nav style={{ minWidth: '120px' }}>
      <OverlayTrigger placement='left'
        overlay={<Tooltip id={'network-tt'}> {networkUrl} </Tooltip>}>
        <FontAwesomeIcon className='info-icon' icon={faInfoCircle} />
      </OverlayTrigger>
      <NavDropdown onToggle={(e: boolean) => { setShowDropdown(e) }}
        show={showDropdown} title={currentNetwork} id="header-network-dropdown">
        {networkMap.size === 0
          ? <div className='text-center'>
            No networks
          </div>
          : Array.from(networkMap, ([k, v]) => (
            <div key={k} className='node-div'>
              <NavDropdown.Item className='node-item' onClick={() => {
                if (currentNetwork !== v) {
                  changeNetwork(k)
                }
              }}>
                {v}
              </NavDropdown.Item>
            </div>
          ))}
      </NavDropdown>
    </Nav>
  )
}
Example #8
Source File: main.ts    From snip with MIT License 5 votes vote down vote up
library.add(faLink, faHandPeace, faCopy, faInfoCircle);
Example #9
Source File: index.tsx    From nouns-monorepo with GNU General Public License v3.0 5 votes vote down vote up
SettleManuallyBtn: React.FC<{
  settleAuctionHandler: () => void;
  auction: Auction;
}> = props => {
  const { settleAuctionHandler, auction } = props;

  const MINS_TO_ENABLE_MANUAL_SETTLEMENT = 5;

  const [settleEnabled, setSettleEnabled] = useState(false);
  const [auctionTimer, setAuctionTimer] = useState(MINS_TO_ENABLE_MANUAL_SETTLEMENT * 60);
  const auctionTimerRef = useRef(auctionTimer); // to access within setTimeout
  auctionTimerRef.current = auctionTimer;

  const timerDuration = dayjs.duration(auctionTimerRef.current, 's');

  // timer logic
  useEffect(() => {
    // Allow immediate manual settlement when testing
    if (CHAIN_ID !== 1) {
      setSettleEnabled(true);
      setAuctionTimer(0);
      return;
    }

    // prettier-ignore
    const timeLeft = MINS_TO_ENABLE_MANUAL_SETTLEMENT * 60 - (dayjs().unix() - (auction && Number(auction.endTime)));

    setAuctionTimer(auction && timeLeft);

    if (auction && timeLeft <= 0) {
      setSettleEnabled(true);
      setAuctionTimer(0);
    } else {
      const timer = setTimeout(() => {
        setAuctionTimer(auctionTimerRef.current - 1);
      }, 1_000);

      return () => {
        clearTimeout(timer);
      };
    }
  }, [auction, auctionTimer]);

  const mins = timerDuration.minutes();

  return (
    <p className={classes.emergencySettleWrapper}>
      <button
        onClick={settleAuctionHandler}
        className={classes.emergencySettleButton}
        disabled={!settleEnabled}
      >
        {settleEnabled ? (
          <>
            <Trans>Settle manually</Trans>
          </>
        ) : (
          <>
            <FontAwesomeIcon icon={faInfoCircle} />
            {mins !== 0 ? (
              <Trans>You can settle manually in {mins + 1} minutes</Trans>
            ) : (
              <Trans>You can settle manually in 1 minute</Trans>
            )}
          </>
        )}
      </button>
    </p>
  );
}
Example #10
Source File: InfoTooltip.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
InfoTooltip = ({ className, ...props }: ITooltipProps) =>
  <BootstrapTooltip placement="top" {...props} className={className}>
    <Box component="span" sx={{ cursor: "help" }}><FontAwesomeIcon icon={faInfoCircle} /></Box>
  </BootstrapTooltip>
Example #11
Source File: icon.service.ts    From WowUp with GNU General Public License v3.0 5 votes vote down vote up
public constructor(private _matIconRegistry: MatIconRegistry, private _sanitizer: DomSanitizer) {
    this.addSvg(faAngleDoubleDown);
    this.addSvg(faArrowUp);
    this.addSvg(faArrowDown);
    this.addSvg(faSyncAlt);
    this.addSvg(faTimes);
    this.addSvg(faExternalLinkAlt);
    this.addSvg(faQuestionCircle);
    this.addSvg(faPlay);
    this.addSvg(faClock);
    this.addSvg(faBug);
    this.addSvg(faLink);
    this.addSvg(faDiscord);
    this.addSvg(faGithub);
    this.addSvg(faInfoCircle);
    this.addSvg(faCodeBranch);
    this.addSvg(faCaretDown);
    this.addSvg(faExclamationTriangle);
    this.addSvg(faCode);
    this.addSvg(faPatreon);
    this.addSvg(faCoins);
    this.addSvg(faCompressArrowsAlt);
    this.addSvg(faPencilAlt);
    this.addSvg(faCheckCircle);
    this.addSvg(faDiceD6);
    this.addSvg(faSearch);
    this.addSvg(faInfoCircle);
    this.addSvg(faNewspaper);
    this.addSvg(faCog);
    this.addSvg(faAngleUp);
    this.addSvg(faAngleDown);
    this.addSvg(faChevronRight);
    this.addSvg(faUserCircle);
    this.addSvg(faEllipsisV);
    this.addSvg(faCopy);
    this.addSvg(farCheckCircle);
    this.addSvg(faExclamation);
    this.addSvg(faTrash);
    this.addSvg(faHistory);
    this.addSvg(faCaretSquareRight);
    this.addSvg(faCaretSquareLeft);
    this.addSvg(faMinimize);
    this.addSvg(faUpRightFromSquare);
  }
Example #12
Source File: SkillBreakdown.tsx    From apps with MIT License 5 votes vote down vote up
render() {
        const skill = this.props.skill;
        const skillAdd =
            this.props.skill.skillAdd.length > 0 ? (
                <Tooltip id="skillAdd-tooltip" style={{ fontSize: "1em" }} lang={Manager.lang()}>
                    {getRubyText(this.props.region, skill.skillAdd[0].name, skill.skillAdd[0].ruby, true)}
                </Tooltip>
            ) : null;

        return (
            <div>
                <h3>
                    <SkillDescriptor region={this.props.region} skill={skill} iconHeight={33} />
                    {skillAdd !== null ? (
                        <>
                            {" "}
                            <OverlayTrigger overlay={skillAdd}>
                                <FontAwesomeIcon icon={faInfoCircle} style={{ fontSize: "0.75em" }} />
                            </OverlayTrigger>
                        </>
                    ) : null}
                </h3>

                {this.props.rankUp !== undefined ? (
                    <Alert variant={"primary"}>Rank Up +{this.props.rankUp}</Alert>
                ) : null}

                {skill.condQuestId && skill.condQuestPhase ? (
                    <Alert variant={"primary"}>
                        Available after{" "}
                        <QuestDescriptor
                            region={this.props.region}
                            questId={skill.condQuestId}
                            questPhase={
                                ["91", "94"].includes(skill.condQuestId.toString().slice(0, 2))
                                    ? 1
                                    : skill.condQuestPhase
                            }
                        />
                    </Alert>
                ) : null}

                <p className="newline">{skill.detail}</p>

                {this.props.extraPassiveCond && skill.extraPassive.length > 0 ? (
                    <>
                        <ExtraPassiveCondition region={this.props.region} extraPassive={skill.extraPassive[0]} />
                    </>
                ) : null}

                <EffectBreakdown
                    region={this.props.region}
                    cooldowns={this.props.cooldowns ? skill.coolDown : undefined}
                    funcs={skill.functions}
                    triggerSkillIdStack={[skill.id]}
                    levels={this.props.levels}
                    scripts={skill.script}
                    additionalSkillId={skill.script.additionalSkillId}
                />
            </div>
        );
    }
Example #13
Source File: QuestEnemy.tsx    From apps with MIT License 5 votes vote down vote up
QuestDropDescriptor = ({ region, drops }: { region: Region; drops: QuestEnemy.EnemyDrop[] }) => {
    return (
        <Alert variant="success">
            <ul style={{ marginBottom: 0 }}>
                {drops.map((drop) => {
                    const dummyGift = {
                        ...drop,
                        id: 0,
                        priority: 0,
                        giftAdds: [],
                    };
                    let ciText = <></>;
                    if (drop.runs > 1) {
                        const c = quantile(0.975, drop.runs - 1);
                        const stdDevOverRuns = Math.sqrt(drop.dropVariance / drop.runs);
                        const lower = drop.dropExpected - c * stdDevOverRuns;
                        const upper = drop.dropExpected + c * stdDevOverRuns;
                        ciText = (
                            <>
                                <br />
                                95% CI: {numToPct(lower)} – {numToPct(upper)}
                            </>
                        );
                    }
                    const tooltip = (
                        <Tooltip id={`drop-detail-tooltip`} style={{ fontSize: "1em" }}>
                            {drop.dropCount.toLocaleString()} drops / {drop.runs.toLocaleString()} runs
                            {ciText}
                        </Tooltip>
                    );
                    return (
                        <li key={`${drop.type}-${drop.objectId}-${drop.num}`}>
                            <GiftDescriptor region={region} gift={dummyGift} />:{" "}
                            <span>{numToPct(drop.dropExpected)}</span>{" "}
                            <OverlayTrigger overlay={tooltip}>
                                <FontAwesomeIcon icon={faInfoCircle} />
                            </OverlayTrigger>
                        </li>
                    );
                })}
            </ul>
        </Alert>
    );
}
Example #14
Source File: WalletRecharge.tsx    From argo-react with MIT License 4 votes vote down vote up
function WalletRecharge() {
  const history = useHistory();
  const { fetchUser } = useContext<IActionModel>(ActionContext);
  const { selectedOrg, orgLoading } = useContext<IStateModel>(StateContext);

  const [wallet, setWallet] = useState<string>("");
  const [walletBal, setWalletBal] = useState<number>(0);
  const [walletApproval, setWalletApproval] = useState<number>(0);
  const [rechargeAmount, setRechargeAmount] = useState<string>("");
  const [walletLoader, setWalletLoader] = useState<boolean>(false);
  const [rechargeLoader, setRechargeLoader] = useState<boolean>(false);
  const [walletLoading, setWalletLoading] = useState<boolean>(false);
  const [orgWallet, setOrgWallet] = useState<string>("");
  const [errorWarning, setErrorWarning] = useState<boolean>(false);
  const [errorMessage, setErrorMessage] = useState<string>("");
  const componentIsMounted = useRef(true);

  useEffect(() => {
    if (selectedOrg && !orgLoading) {
      setWalletLoading(true);
      if (componentIsMounted.current) {
        setOrgWallet(selectedOrg.wallet.address);
        setWalletLoading(false);
      }
    } else {
      if (orgLoading) {
        setWalletLoading(true);
      } else {
        setWalletLoading(false);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedOrg, orgLoading]);

  const rechargeArGo = async () => {
    setErrorWarning(false);
    try {
      if (!wallet) {
        setWalletLoader(true);
        const wallet = await Web3Service.getPolygonAccount();
        setWallet(wallet);
        if (wallet) {
          const walletBal = await Web3Service.getArgoBalance(wallet);
          const walletApproval = await Web3Service.getArgoAllowances(wallet);
          setWalletBal(walletBal);
          setWalletApproval(walletApproval);
        }
        setWalletLoader(false);
      } else {
        setRechargeLoader(true);
        await Web3Service.giveAllowance(rechargeAmount);
        setRechargeLoader(false);
        fetchUser();
        history.goBack();
      }
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log(err);
      setWalletLoader(false);
      setRechargeLoader(false);
      setErrorMessage((err as any).message);
      setErrorWarning(true);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      // window.location.reload();
    }
  };

  const refreshWallet = async () => {
    try {
      setErrorWarning(false);
      setWalletLoader(true);
      const wallet = await Web3Service.getPolygonCurrentAccount();
      const walletBal = await Web3Service.getArgoBalance(wallet);
      const walletApproval = await Web3Service.getArgoAllowances(wallet);
      setWallet(wallet);
      setWalletBal(walletBal);
      setWalletApproval(walletApproval);
      setWalletLoader(false);
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log(err);
      setWalletLoader(false);
      setErrorMessage((err as any).message);
      setErrorWarning(true);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      // window.location.reload();
    }
  };

  useEffect(() => {
    return () => {
      componentIsMounted.current = false;
      Web3Service.disconnectPolygon();
    };
  }, []);

  const rechargeDisable =
    rechargeLoader || wallet ? !rechargeAmount || wallet !== orgWallet : false;

  return (
    <div className="WalletRecharge">
      <RootHeader parent={"CreateOrg"} />
      <main className="app-main">
        <div className="wallet-recharge-container">
          <div className="wallet-recharge-card">
            <div className="wallet-recharge-card-inner">
              <h1 className="wallet-recharge-title">Set Allowance</h1>
              <div className="wallet-recharge-form">
                <label className="wallet-recharge-form-title">Your wallet</label>
                <label className="wallet-chain-info">
                  <FontAwesomeIcon
                    icon={faInfoCircle}
                    style={{ marginRight: 7 }}
                  ></FontAwesomeIcon>
                  We currently support Matic Mumbai Testnet. Please add Matic Mumbai
                  chain in your metamask.
                </label>
                <label className="wallet-recharge-form-subtitle">
                  Please approve more than minimum $ARGO tokens to our Payment Smart
                  Contract. Approval transaction is <b>Gassless</b>, no need to hold
                  $MATIC tokens for approval.
                </label>
                <label className="wallet-recharge-form-subtitle">
                  To start deploying your application, minimum allowance required is
                  60 $ARGO and minimum balance required is 60 $ARGO tokens.
                </label>
                <label className="wallet-recharge-form-subtitle">
                  To get <b>Matic Testnet $ARGO Tokens</b>, please visit{" "}
                  <a
                    href="https://faucet.spheron.network/"
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    https://faucet.spheron.network
                  </a>
                  .
                </label>
                <div className="current-wallet-details">
                  <div className="current-wallet-details-title">Owner Address:</div>
                  <div className="current-wallet-details-desc">
                    {!walletLoading ? (
                      `${orgWallet}`
                    ) : (
                      <Skeleton width={150} duration={2} />
                    )}
                  </div>
                </div>
              </div>
              {wallet && (
                <>
                  <div className="wallet-recharge-form">
                    <div className="wallet-recharge-form-title-container">
                      <label className="wallet-recharge-form-title">
                        Wallet Details
                      </label>
                      <div className="refresh-control" onClick={refreshWallet}>
                        <FontAwesomeIcon icon={faSyncAlt}></FontAwesomeIcon>
                      </div>
                    </div>
                    <div className="wallet-details-container">
                      <div className="wallet-details-items">
                        <div className="wallet-details-item-title">
                          Wallet Address
                        </div>
                        <div className="wallet-details-item-desc">
                          {!walletLoader ? (
                            wallet
                          ) : (
                            <Skeleton width={300} duration={2} />
                          )}
                        </div>
                      </div>
                      <div className="wallet-details-items">
                        <div className="wallet-details-item-title">ARGO Balance</div>
                        <div className="wallet-details-item-desc">
                          {!walletLoader ? (
                            `${walletBal} $ARGO`
                          ) : (
                            <Skeleton width={150} duration={2} />
                          )}
                        </div>
                      </div>
                      <div className="wallet-details-items">
                        <div className="wallet-details-item-title">
                          ARGO Allowance
                        </div>
                        <div className="wallet-details-item-desc">
                          {!walletLoader ? (
                            `${walletApproval} $ARGO`
                          ) : (
                            <Skeleton width={150} duration={2} />
                          )}
                        </div>
                      </div>
                    </div>
                  </div>
                  <div className="wallet-recharge-form">
                    <label className="wallet-recharge-form-title">
                      Approval Amount
                    </label>
                    <label className="wallet-recharge-form-subtitle">
                      Please provide the approval amount.
                    </label>
                    <input
                      type="number"
                      className="wallet-recharge-form-input"
                      value={rechargeAmount}
                      onChange={(e) => setRechargeAmount(e.target.value)}
                    />
                  </div>
                </>
              )}
              {wallet && wallet !== orgWallet ? (
                <div className="note-container">
                  Note: We currently support Matic Mumbai Testnet. Only owner of this
                  wallet can increase allowance
                </div>
              ) : null}
              <div className="button-container">
                <button
                  type="button"
                  className="primary-button"
                  disabled={rechargeDisable}
                  onClick={rechargeArGo}
                >
                  {rechargeLoader && (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  )}
                  {!wallet ? "Connect" : "Approve"}
                </button>
                <button
                  type="button"
                  className="cancel-button"
                  onClick={(e) => history.goBack()}
                >
                  Cancel
                </button>
              </div>
              {errorWarning ? (
                <div className="warning-container">
                  <div className="warning-header">
                    <FontAwesomeIcon icon={faExclamationCircle} /> {errorMessage}
                  </div>
                </div>
              ) : null}
            </div>
          </div>
        </div>
      </main>
    </div>
  );
}
Example #15
Source File: index.tsx    From nouns-monorepo with GNU General Public License v3.0 4 votes vote down vote up
AuctionActivity: React.FC<AuctionActivityProps> = (props: AuctionActivityProps) => {
  const {
    auction,
    isFirstAuction,
    isLastAuction,
    onPrevAuctionClick,
    onNextAuctionClick,
    displayGraphDepComps,
  } = props;

  const isCool = useAppSelector(state => state.application.isCoolBackground);

  const [auctionEnded, setAuctionEnded] = useState(false);
  const [auctionTimer, setAuctionTimer] = useState(false);

  const [showBidHistoryModal, setShowBidHistoryModal] = useState(false);
  const showBidModalHandler = () => {
    setShowBidHistoryModal(true);
  };
  const dismissBidModalHanlder = () => {
    setShowBidHistoryModal(false);
  };

  // timer logic - check auction status every 30 seconds, until five minutes remain, then check status every second
  useEffect(() => {
    if (!auction) return;

    const timeLeft = Number(auction.endTime) - Math.floor(Date.now() / 1000);

    if (auction && timeLeft <= 0) {
      setAuctionEnded(true);
    } else {
      setAuctionEnded(false);
      const timer = setTimeout(
        () => {
          setAuctionTimer(!auctionTimer);
        },
        timeLeft > 300 ? 30000 : 1000,
      );

      return () => {
        clearTimeout(timer);
      };
    }
  }, [auctionTimer, auction]);

  if (!auction) return null;

  return (
    <>
      {showBidHistoryModal && (
        <BidHistoryModal onDismiss={dismissBidModalHanlder} auction={auction} />
      )}

      <AuctionActivityWrapper>
        <div className={classes.informationRow}>
          <Row className={classes.activityRow}>
            <AuctionTitleAndNavWrapper>
              {displayGraphDepComps && (
                <AuctionNavigation
                  isFirstAuction={isFirstAuction}
                  isLastAuction={isLastAuction}
                  onNextAuctionClick={onNextAuctionClick}
                  onPrevAuctionClick={onPrevAuctionClick}
                />
              )}
              <AuctionActivityDateHeadline startTime={auction.startTime} />
            </AuctionTitleAndNavWrapper>
            <Col lg={12}>
              <AuctionActivityNounTitle isCool={isCool} nounId={auction.nounId} />
            </Col>
          </Row>
          <Row className={classes.activityRow}>
            <Col lg={4} className={classes.currentBidCol}>
              <CurrentBid
                currentBid={new BigNumber(auction.amount.toString())}
                auctionEnded={auctionEnded}
              />
            </Col>
            <Col lg={6} className={classes.auctionTimerCol}>
              {auctionEnded ? (
                <Winner winner={auction.bidder} />
              ) : (
                <AuctionTimer auction={auction} auctionEnded={auctionEnded} />
              )}
            </Col>
          </Row>
        </div>
        {!auctionEnded && (
          <Row className={classes.activityRow}>
            <Col lg={12} className={classes.fomoNounsLink}>
              <FontAwesomeIcon icon={faInfoCircle} />
              <a href={'https://fomonouns.wtf'} target={'_blank'} rel="noreferrer">
                <Trans>Help mint the next Noun</Trans>
              </a>
            </Col>
          </Row>
        )}
        {isLastAuction && (
          <>
            <Row className={classes.activityRow}>
              <Col lg={12}>
                <Bid auction={auction} auctionEnded={auctionEnded} />
              </Col>
            </Row>
          </>
        )}
        <Row className={classes.activityRow}>
          <Col lg={12}>
            {!isLastAuction ? (
              <NounInfoCard
                nounId={auction.nounId.toNumber()}
                bidHistoryOnClickHandler={showBidModalHandler}
              />
            ) : (
              displayGraphDepComps && (
                <BidHistory
                  auctionId={auction.nounId.toString()}
                  max={3}
                  classes={bidHistoryClasses}
                />
              )
            )}
            {/* If no bids, show nothing. If bids avail:graph is stable? show bid history modal,
            else show etherscan contract link */}
            {isLastAuction &&
              !auction.amount.eq(0) &&
              (displayGraphDepComps ? (
                <BidHistoryBtn onClick={showBidModalHandler} />
              ) : (
                <BidHistoryBtn onClick={openEtherscanBidHistory} />
              ))}
          </Col>
        </Row>
      </AuctionActivityWrapper>
    </>
  );
}
Example #16
Source File: index.tsx    From prism-frontend with MIT License 4 votes vote down vote up
function NavBar({ classes }: NavBarProps) {
  const { t } = useSafeTranslation();

  const rightSideLinks = [
    {
      title: t('about'),
      icon: faInfoCircle,
      href: 'https://innovation.wfp.org/project/prism',
    },
    {
      title: 'GitHub',
      icon: faGithub,
      href: 'https://github.com/oviohub/prism-frontend',
    },
  ];

  const [openMobileMenu, setOpenMobileMenu] = useState(false);
  const menu = menuList.map(({ title, ...category }) => (
    <MenuItem key={title} title={title} {...category} />
  ));

  // menu for mobile, 1 active accordion at a time so I put the state in here
  const [expanded, setExpanded] = useState('');
  const selectAccordion = (title: string) => {
    setExpanded(title);
  };
  const menuMobile = menuList.map(({ title, ...category }) => (
    <MenuItemMobile
      expanded={expanded}
      selectAccordion={selectAccordion}
      key={title}
      title={title}
      {...category}
    />
  ));

  const buttons = rightSideLinks.map(({ title, icon, href }) => (
    <Grid item key={title}>
      <Typography
        variant="body2"
        component="a"
        target="_blank"
        href={href}
        onClick={() => setOpenMobileMenu(false)}
      >
        <FontAwesomeIcon icon={icon} /> {title}
      </Typography>
    </Grid>
  ));

  return (
    <AppBar position="static" className={classes.appBar}>
      <Toolbar variant="dense">
        <Grid container>
          <Grid item xs={3} className={classes.logoContainer}>
            <Typography
              variant="h6"
              className={classes.logo}
              component={Link}
              to="/"
            >
              {t('Prism')}
            </Typography>
          </Grid>

          <Hidden smDown>
            <Grid className={classes.menuContainer} item xs={6}>
              {menu}
            </Grid>

            <Grid
              spacing={3}
              container
              justify="flex-end"
              alignItems="center"
              item
              xs={3}
            >
              {buttons}
              <LanguageSelector />
            </Grid>
          </Hidden>

          <Hidden mdUp>
            <Grid item xs={9} className={classes.mobileMenuContainer}>
              <Button
                onClick={() => setOpenMobileMenu(prevOpen => !prevOpen)}
                aria-controls={openMobileMenu ? 'mobile-menu-list' : undefined}
                aria-haspopup="true"
                className={classes.menuBars}
              >
                <FontAwesomeIcon icon={faBars} />
              </Button>

              <Drawer
                anchor="right"
                open={openMobileMenu}
                onClose={() => setOpenMobileMenu(false)}
              >
                <div className={classes.mobileDrawerContent}>
                  <Grid container spacing={3}>
                    <Grid container justify="space-around" item>
                      {buttons}
                    </Grid>
                    <Grid container direction="column" item>
                      {menuMobile}
                    </Grid>
                  </Grid>
                </div>
              </Drawer>
            </Grid>
          </Hidden>
        </Grid>
      </Toolbar>
    </AppBar>
  );
}
Example #17
Source File: War.tsx    From apps with MIT License 4 votes vote down vote up
warFaq = (region: Region) => {
    const whatIsAWar = (
        <>
            You can think of a war as a container for the various quests in game. The{" "}
            <Link to={`/${region}/war/100`}>Fuyuki Singularity</Link>, <Link to={`/${region}/war/301`}>Lostbelt 1</Link>
            , the map for <Link to={`/${region}/war/8290`}>Battle in New York</Link>, and even the lists of{" "}
            <Link to={`/${region}/war/8290`}>Daily Quests</Link> or <Link to={`/${region}/war/1003`}>Interludes</Link>{" "}
            that you see on the main page of FGO are wars. It is important to note that wars are distinct from events,
            which have their own page on the Atlas Academy DB. While an event may have a war attached to it, such as
            GudaGuda, the event itself is not a war, nor do all events have wars. A half AP event in FGO, for example,
            does not have a war attached. See the event section for more details on events.
        </>
    );

    const warBreakDown = (
        <>
            An example war to look at is{" "}
            <Link to={`/${region}/war/100`}>Singularity F: Flame Contaminated City: Fuyuki</Link>. You'll see that the
            page is broken into several sections. The first section, as represented below, includes general information
            about the war, including:
            <ul>
                <li>
                    <b>Name</b>
                </li>
                <li>
                    <b>Age</b>: Time of the war in game, such as 2004 for Fuyuki
                </li>
                <li>
                    <b>Event</b>: The event that the war is tied to (if any)
                </li>
                <li>
                    <b>Opening Scripts</b>: story sequences that appear when first opening the war
                </li>
                <li>
                    <b>Banner</b>: the war's icon on your terminal
                </li>
                <li>
                    <b>BGM</b>: the war's main background music
                </li>
            </ul>
            You will also see buttons for the raw data of the war itself that is used to render the page, either in Nice
            or Raw format.
            <img alt="War Page Main Info" src={war_page_main_info} width="100%" />
            Beneath the war's general information you will find the main quests associated with the war, if any. Each
            quest will tell you the following information:
            <ul>
                <li>
                    <b>Section</b>: chapter in game
                </li>
                <li>
                    <b>ID</b>
                </li>
                <li>
                    <b>Name</b>
                </li>
                <li>
                    <b>Spot</b>: node, or location on a map in game
                </li>
                <li>
                    <b>Phases</b>: the different arrows or parts to a quest, such as 1-1, 1-2, 1-3 etc.
                </li>
                <li>
                    <b>Completion Reward</b> (if applicable)
                </li>
                <li>
                    <b>Scripts</b>: any story sections that the quest has
                </li>
            </ul>
            Clicking on the quest's ID or name will take you to that quest's page, and clicking on any individual phase
            will take you directly to that phase of the quest. A dragon symbol <FontAwesomeIcon icon={faDragon} /> by a
            phase indicates it has enemies; a book symbol <FontAwesomeIcon icon={faBook} /> indicates it is story only.
            <img alt="War Page Main Quests" src={war_page_main_quests} width="100%" />
            Beneath the main quests you will find, if applicable, <b>free quests</b>, <b>interludes</b>,{" "}
            <b>event quests</b>, or any other type of available quests, each sorted into its own dropdown. Within each
            dropdown, the quests are ordered within their respective nodes, then by quest ID.
            <img alt="War Page Free Quests" src={war_page_free_quests} width="100%" />
        </>
    );

    const whatIsAQuest = (
        <>
            Quests are the individual containers for dialogue or battle sequences in FGO. When you click on a map
            location within a singularity or event, the options that you have, be it the next part of the story, a free
            quest, or an interlude, are quests.
        </>
    );

    const questBreakDown = (
        <>
            An example quest to look at is <Link to={`/${region}/quest/1000001/1`}>Burning City</Link>. You'll see that
            like the war page, it is broken into several sections. The first section, as represented below, includes
            general information about the quest, including, among other things:
            <ul>
                <li>
                    <b>Type</b>: free quest, main quest, interlude etc.
                </li>
                <li>
                    <b>Cost</b>: AP or any other currency required to complete the quest
                </li>
                <li>
                    <b>Rewards</b>: First clear rewards for completing the quest (if applicable)
                </li>
                <li>
                    <b>Opening</b> and <b>Closing</b> times (in your local time)
                </li>
                <li>
                    <b>Individuality</b>: whether it is a sun field, city field, a specific event field, etc.
                </li>
            </ul>
            Many quests have multiple phases, or parts to the quest. These are seen as 1-1, 1-2, 1-3, etc. in game, with
            each piece being its own phase. For quests with multiple phases, you can navigate between them using the
            arrows or numbers in the <b>Phases</b> row.
            <img alt="Quest Page Main Info" src={quest_page_main_info} width="100%" />
            Beneath the general information, you will see a list of the scripts for the phase you are on (if any), as
            well as any pre-battle messages and drop data if available. Mouse over the{" "}
            <FontAwesomeIcon icon={faInfoCircle} /> to see a tooltip indicating how many runs the drop data is based on.
            The more runs worth of data, the more accurate it is.
            <img alt="Quest Page Script and Drop data" src={quest_page_script_drop_data} width="100%" />
            Finally, below the drop data you will see a list of stages, or battle waves, as well as the enemies within
            them if available. Please note that enemy data is not available for all quests. The enemy data includes a
            list of the drops of each particular mob if available, as well as all the general information regarding each
            enemy, including their, among other things:
            <ul>
                <li>
                    <b>Stats</b>: such as HP, NP bars, death rate, etc.
                </li>
                <li>
                    <b>Skills</b>
                </li>
                <li>
                    <b>Traits</b>
                </li>
                <li>
                    <b>AI</b>: used to determine how enemies will act in battle
                </li>
            </ul>
            You may also see a <b>Field AI</b> before the enemies. This refers to effects tied to the field itself
            rather than any individual enemy.
            <img alt="Quest Page Enemy" src={quest_page_enemy} width="100%" />
        </>
    );

    const huntingQuest = (
        <>
            Hunting and Trial quests can be found in <Link to={`/${region}/war/999`}>War 9999: Chaldea Gate</Link>.
        </>
    );

    const whatIsAnEvent = (
        <>
            As noted in the Wars section, Events and Wars, while sometimes sounding similar, are very different things.
            If one thinks of Saber Wars for an example, there are two separate components: the{" "}
            <Link to={`/${region}/war/8095`}>War</Link>, or the actual Saber Wars map with nodes and quests on it, and
            the <Link to={`/${region}/event/80008`}>Event</Link> behind it. The event is where you can find information
            like the lottery, point ladder, or shop tied to an in-game event. Note that some events may not have these,
            such as a 1/2 AP or bonus FP event.
        </>
    );

    const eventBreakDown = (
        <>
            Like the other pages, the Event page is broken down into sections. The top section provides general
            information about the event, including:
            <ul>
                <li>
                    <b>ID</b>
                </li>
                <li>
                    <b>Name</b>
                </li>
                <li>
                    <b>Wars</b>: any Wars tied to the event
                </li>
                <li>
                    <b>Status</b>: whether the event is ongoing or not
                </li>
                <li>
                    <b>Status</b> and <b>End</b> times (in your local time)
                </li>
            </ul>
            <img alt="Event Page Main Info" src={event_page_main_info} width="100%" />
            Beneath the general information will be any point ladders, shops, or lotteries if applicable. For shops in
            particular, you are able to utilize the planner to calculate the amount of event currency you will need for
            what you want. To enable the planner feature, click the green edit button on the right side of the currency
            bar, pictured below:
            <img alt="Event Page Shop Planner" src={event_page_shop_planner} width="100%" />
            Once you have enabled planner mode, you have several options. You can utilize the <b>Quick Toggles</b> in
            order to instantly select or deselect all items, and you can also filter out commonly excluded items from
            the calculated totals, such as gems, monuments, or pieces. In addition to the Quick Toggles, you can also
            individually select items that you want. The two rightmost columns for each item are <b>Limit</b> and
            <b>Target</b>. Limit refers to the maximum amount of an item that can be purchased, while Target allows you
            to indicate how many of that item you wish to purchase. For each item you set with Target, the total cost of
            that item is added to the cost bar above the shop. In the image below, you will see that two "Purely Bloom"
            craft essences which cost 150 Vacuum Tubes each have been selected via the Target column, and the total cost
            of 300 Vacuum Tubes is represented in the cost bar.
            <img alt="Event Page Shop Planner Exclude" src={event_page_shop_planner_exclude} width="100%" />
        </>
    );

    const findAScript = (
        <>
            Story text on the Atlas Academy DB is known as a <b>Script</b>. There are several ways you can find a
            particular quest's script on the DB.
            <ol>
                <li>
                    <b>Script Search</b>
                    <br />
                    You can find the <Link to={`/${region}/scripts`}>Script Search</Link> page from the "Search"
                    dropdown in the navigation bar at the top of the DB page.
                    <img alt="Script Search Page Navigation" src={script_search_page} width="100%" />
                    This page allows you to search through the contents of all the scripts in the game to find the one
                    you are looking for. Make sure to pay attention to the search syntax listed on the page to refine
                    your searches.{" "}
                    <b>
                        Please keep in mind which region you are using the script page on. You cannot search a script
                        using English on the JP page and vice versa.
                    </b>
                </li>
                <li>
                    <b>Via the Wars Page</b>
                    <br />
                    If you don't remember exactly what was said in the script in question to find it via search, but you
                    do remember the singularity or event it was in, you can navigate to the{" "}
                    <Link to={`/${region}/wars`}>Wars</Link> page on the navigation bar, and select the war in question.
                    There, on the rightmost side of each quest, you will see the scripts that quest has available, and
                    can select the one you want. They are sorted into phases, so if the list says <b>1: 10, 11</b>, then
                    you know those two scripts come from phase 1 of the quest. For more details about when the scripts
                    appear in the quest, you can go to the quest's page.
                </li>
                <li>
                    <b>Via the Quests Page</b>
                    <br />
                    If you know what quest your script comes from, you can either utilize the{" "}
                    <Link to={`/${region}/quests`}>Quest Search</Link>, or utilize the{" "}
                    <Link to={`/${region}/wars`}>Wars</Link> page to navigate to the quest you have in mind. There, for
                    each phase of the quest, you can see which scripts are available and when they play in the quest
                    beneath the general quest information. Use the phase row to navigate between phases.
                </li>
            </ol>
        </>
    );

    return {
        id: "wars-quests-events",
        title: "Wars, Quests, Events and Scripts",
        subSections: [
            {
                id: "what-is-a-war",
                title: "What is a War?",
                content: whatIsAWar,
            },
            {
                id: "breakdown-of-the-war-page",
                title: "Breakdown of the War Page",
                content: warBreakDown,
            },
            {
                id: "what-is-a-quest",
                title: "What is a Quest?",
                content: whatIsAQuest,
            },
            {
                id: "breakdown-of-the-quest-page",
                title: "Breakdown of the Quest Page",
                content: questBreakDown,
            },
            {
                id: "where-can-i-find-hunting-and-trial-quests",
                title: "Where can I find Hunting Quests / Trial Quests?",
                content: huntingQuest,
            },
            {
                id: "what-is-an-event",
                title: "What is an Event / How are Events and Wars Different?",
                content: whatIsAnEvent,
            },
            {
                id: "breakdown-of-the-event-page",
                title: "Breakdown of the Events Page",
                content: eventBreakDown,
            },
            {
                id: "how-can-i-find-story-text",
                title: "How Can I Find Story Text?",
                content: findAScript,
            },
        ],
    };
}
Example #18
Source File: WebhookItem.tsx    From argo-react with MIT License 4 votes vote down vote up
WebhookItem: React.FC<IWebhookItemProps> = ({
  id,
  name,
  branch,
  protocol,
  workspace,
  framework,
  packageManager,
  buildCommand,
  publishDirectory,
  selectedProject,
  type,
}) => {
  const { selectedOrg } = useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);

  const [editMode, setEditMode] = useState<boolean>(false);

  const [removeWebhookLoading, setRemoveWebhookLoading] = useState<boolean>(false);
  const [updateWebhookLoading, setUpdateWebhookLoading] = useState<boolean>(false);

  const [repoBranches, setRepoBranches] = useState<any[]>([]);
  const [repoBranchesLoading, setRepoBranchesLoading] = useState<boolean>(true);
  const [editName, setEditName] = useState<string>("");
  const [editBranch, setEditBranch] = useState<string>("");
  const [editProtocol, setEditProtocol] = useState<string>("");
  const [editWorkspace, setEditWorkspace] = useState<string>("");
  const [editPackageManager, setEditPackageManager] = useState<string>("");
  const [editBuildCommand, setEditBuildCommand] = useState<string>("");
  const [editPublishDirectory, setEditPublishDirectory] = useState<string>("");

  const [webhookDisabled, setWebhookDisabled] = useState<boolean>(false);

  useEffect(() => {
    if (name) {
      setEditName(name);
    }
    if (branch) {
      setEditBranch(branch);
    }
    if (protocol) {
      setEditProtocol(protocol);
    }
    if (workspace) {
      setEditWorkspace(workspace);
    }
    if (packageManager) {
      setEditPackageManager(packageManager);
    }
    if (buildCommand) {
      setEditBuildCommand(buildCommand);
    }
    if (publishDirectory) {
      setEditPublishDirectory(publishDirectory);
    }
  }, [
    name,
    branch,
    protocol,
    workspace,
    packageManager,
    buildCommand,
    publishDirectory,
  ]);

  const componentIsMounted = useRef(true);

  useEffect(() => {
    return () => {
      componentIsMounted.current = false;
    };
  }, []);

  useEffect(() => {
    if (
      framework !== "static" &&
      (name !== editName ||
        branch !== editBranch ||
        packageManager !== editPackageManager ||
        buildCommand !== editBuildCommand ||
        publishDirectory !== editPublishDirectory ||
        protocol !== editProtocol ||
        workspace !== editWorkspace)
    ) {
      setWebhookDisabled(false);
    } else {
      if (
        framework === "static" &&
        (name !== editName ||
          branch !== editBranch ||
          protocol !== editProtocol ||
          workspace !== editWorkspace)
      ) {
        setWebhookDisabled(false);
      } else {
        setWebhookDisabled(true);
      }
    }
  }, [
    branch,
    framework,
    packageManager,
    buildCommand,
    publishDirectory,
    selectedOrg,
    protocol,
    name,
    editName,
    editBranch,
    editPackageManager,
    editBuildCommand,
    editPublishDirectory,
    editProtocol,
    workspace,
    editWorkspace,
  ]);

  useEffect(() => {
    if (selectedProject && editMode) {
      const repoName = selectedProject?.githubUrl
        .substring(19, selectedProject?.githubUrl.length - 4)
        .split("/")[1];
      const ownerName = selectedProject?.githubUrl
        .substring(19, selectedProject?.githubUrl.length - 4)
        .split("/")[0];
      const branchUrl = `https://api.github.com/repos/${ownerName}/${repoName}/branches`;

      ApiService.getGithubRepoBranches(branchUrl).subscribe((res) => {
        if (componentIsMounted.current) {
          setRepoBranches(res.branches);
          setRepoBranchesLoading(false);
        }
      });
    }
  }, [selectedProject, editMode]);

  let buildCommandPrefix: string = "";
  if (packageManager === "npm") {
    buildCommandPrefix = "npm run";
  } else {
    buildCommandPrefix = "yarn";
  }

  const removeWebhook = () => {
    setRemoveWebhookLoading(true);
    ApiService.removeWebhook(id, { orgId: selectedOrg?._id }).subscribe((result) => {
      if (result.success) {
        setEditName("");
        setEditBranch("");
        setEditProtocol("");
        setEditWorkspace("");
        setEditPackageManager("");
        setEditBuildCommand("");
        setEditPublishDirectory("");
        fetchProject(`${selectedProject?._id}`);
      } else {
        setEditName("");
        setEditBranch("");
        setEditProtocol("");
        setEditWorkspace("");
        setEditPackageManager("");
        setEditBuildCommand("");
        setEditPublishDirectory("");
      }
      setRemoveWebhookLoading(false);
    });
  };

  const updateWebhook = () => {
    setUpdateWebhookLoading(true);
    const configuration = {
      framework,
      workspace: editWorkspace,
      packageManager: editPackageManager,
      buildCommand: editBuildCommand,
      publishDir: editPublishDirectory,
      branch: editBranch,
      protocol: editProtocol,
    };
    ApiService.createConfiguration(configuration).subscribe((confResult) => {
      if (componentIsMounted.current) {
        const webhookMeta = {
          orgId: selectedOrg?._id,
          name: editName !== name ? editName : undefined,
          branch: editBranch !== branch ? editBranch : undefined,
          configurationId: confResult._id,
        };
        ApiService.editWebhook(id, webhookMeta).subscribe((result) => {
          if (result.success) {
            setEditName("");
            setEditBranch("");
            setEditProtocol("");
            setEditWorkspace("");
            setEditPackageManager("");
            setEditBuildCommand("");
            setEditPublishDirectory("");
            fetchProject(`${selectedProject?._id}`);
          } else {
            setEditName("");
            setEditBranch("");
            setEditProtocol("");
            setEditWorkspace("");
            setEditPackageManager("");
            setEditBuildCommand("");
            setEditPublishDirectory("");
          }
          setUpdateWebhookLoading(false);
        });
      }
    });
  };

  return (
    <div className="webhook-item" key={id}>
      {type === "filled" && (
        <div className="webhook-item-container">
          <ReactTooltip />
          <div className="webhook-header">
            <div className="webhook-header-left">
              <div>
                <LazyLoadedImage height={24} once>
                  <img
                    src={require("../../../../../../../../assets/svg/cd.svg")}
                    alt="webhook-icon"
                    className="webhook-icon"
                    height={24}
                    width={24}
                    loading="lazy"
                  />
                </LazyLoadedImage>
              </div>
              <div>{!editMode ? name.toUpperCase() : "Edit"}</div>
            </div>
            <div className="webhook-header-right">
              {!editMode ? (
                <button className="edit-button" onClick={(e) => setEditMode(true)}>
                  Edit
                </button>
              ) : (
                <button
                  className="save-button"
                  disabled={webhookDisabled}
                  onClick={updateWebhook}
                >
                  <span style={{ marginRight: 4 }}>Save</span>
                  {updateWebhookLoading && (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  )}
                </button>
              )}
              {!editMode ? (
                <button
                  className="remove-button"
                  disabled={removeWebhookLoading}
                  onClick={removeWebhook}
                >
                  <span>Remove</span>
                  {removeWebhookLoading ? (
                    <BounceLoader size={20} color={"#ee0902"} loading={true} />
                  ) : null}
                </button>
              ) : (
                <button
                  className="cancel-button"
                  onClick={(e) => setEditMode(false)}
                >
                  Cancel
                </button>
              )}
            </div>
          </div>
          <div className="deploy-site-item-form">
            {editMode && (
              <div className="deploy-site-item-form-item">
                <label>
                  Name
                  <span
                    className="tooltip"
                    data-tip="name of your CD pipeline (e.g. PROD, DEV, TESTING)."
                  >
                    <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                  </span>
                </label>
                <input
                  type="text"
                  className="deploy-site-item-input"
                  value={editName}
                  onChange={(e) => setEditName(e.target.value)}
                />
              </div>
            )}
            <div className="deploy-site-item-form-item">
              <label>Branch to deploy</label>
              {!editMode ? (
                <span>{branch}</span>
              ) : (
                <div className="deploy-site-item-select-container">
                  <select
                    className="deploy-site-item-select"
                    value={editBranch}
                    onChange={(e) => setEditBranch(e.target.value)}
                  >
                    {repoBranches.map((branch, index) => (
                      <option value={branch.name} key={index}>
                        {branch.name}
                      </option>
                    ))}
                  </select>
                  <span className="select-down-icon">
                    {!repoBranchesLoading ? (
                      <FontAwesomeIcon icon={faChevronDown} />
                    ) : (
                      <BounceLoader size={20} color={"#0a3669"} loading={true} />
                    )}
                  </span>
                </div>
              )}
            </div>
            <div className="deploy-site-item-form-item">
              <label>
                Protocol
                <span
                  className="tooltip"
                  data-tip="The framework that your app is built upon."
                >
                  <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                </span>
              </label>
              {!editMode ? (
                <span>{protocol}</span>
              ) : (
                <div className="deploy-site-item-select-container">
                  <select
                    className="deploy-site-item-select"
                    value={editProtocol}
                    onChange={(e) => setEditProtocol(e.target.value)}
                  >
                    <option value="arweave">Arweave</option>
                    <option value="skynet">Skynet</option>
                    <option value="ipfs-filecoin">IPFS-Filecoin</option>
                    <option value="ipfs-pinata">IPFS-Pinata</option>
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
              )}
            </div>
            <div className="deploy-site-item-form-item">
              <label>
                Workspace to deploy
                <span
                  className="tooltip"
                  data-tip="If your app is a monorepo, then you can specify your app directory you want to deploy using the workspace."
                >
                  <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                </span>
              </label>
              {!editMode ? (
                <span>{workspace ? workspace : "N.A"}</span>
              ) : (
                <input
                  type="text"
                  className="deploy-site-item-input"
                  value={editWorkspace}
                  onChange={(e) => setEditWorkspace(e.target.value)}
                />
              )}
            </div>
            {framework !== "static" && (
              <>
                <div className="deploy-site-item-form-item">
                  <label>
                    Package Manager
                    <span
                      className="tooltip"
                      data-tip="The package manager that you want your app to be built with."
                    >
                      <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                    </span>
                  </label>
                  {!editMode ? (
                    <span>{packageManager}</span>
                  ) : (
                    <div className="deploy-site-item-select-container">
                      <select
                        className="deploy-site-item-select"
                        value={editPackageManager}
                        onChange={(e) => setEditPackageManager(e.target.value)}
                      >
                        <option value="npm">NPM</option>
                        <option value="yarn">YARN</option>
                      </select>
                      <span className="select-down-icon">
                        <FontAwesomeIcon icon={faChevronDown} />
                      </span>
                    </div>
                  )}
                </div>
                <div className="deploy-site-item-form-item">
                  <label>
                    Build command
                    <span
                      className="tooltip"
                      data-tip="The command your frontend framework provides for compiling your code."
                    >
                      <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                    </span>
                  </label>
                  {!editMode ? (
                    <span>
                      {packageManager === "npm" ? "npm run " : "yarn "}{" "}
                      {buildCommand}
                    </span>
                  ) : framework !== "next" ? (
                    <div className="deploy-site-item-input-container">
                      <input
                        type="text"
                        className="deploy-site-item-input-disabled"
                        value={buildCommandPrefix}
                        disabled
                      />
                      <input
                        type="text"
                        className="deploy-site-item-input-build"
                        value={editBuildCommand}
                        onChange={(e) => setEditBuildCommand(e.target.value)}
                      />
                    </div>
                  ) : (
                    <input
                      type="text"
                      className="deploy-site-item-input"
                      value={editBuildCommand}
                      onChange={(e) => setEditBuildCommand(e.target.value)}
                    />
                  )}
                </div>
                <div className="deploy-site-item-form-item">
                  <label>
                    Publish directory
                    <span
                      className="tooltip"
                      data-tip="The directory in which your compiled frontend will be located."
                    >
                      <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                    </span>
                  </label>
                  {!editMode ? (
                    <span>{publishDirectory}</span>
                  ) : (
                    <input
                      type="text"
                      className="deploy-site-item-input"
                      value={editPublishDirectory}
                      onChange={(e) => setEditPublishDirectory(e.target.value)}
                    />
                  )}
                </div>
              </>
            )}
          </div>
        </div>
      )}
      {type === "skeleton" && (
        <div className="webhook-item-container">
          <div className="webhook-header">
            <Skeleton width={250} duration={2} />
          </div>
          <div className="deploy-site-item-form">
            <div className="deploy-site-item-form-item">
              <label>
                <Skeleton width={80} duration={2} />
              </label>
              <span>
                <Skeleton width={150} duration={2} />
              </span>
            </div>
            <div className="deploy-site-item-form-item">
              <label>
                <Skeleton width={80} duration={2} />
              </label>
              <span>
                <Skeleton width={150} duration={2} />
              </span>
            </div>
            <div className="deploy-site-item-form-item">
              <label>
                <Skeleton width={80} duration={2} />
              </label>
              <span>
                <Skeleton width={150} duration={2} />
              </span>
            </div>
            {framework !== "static" && (
              <>
                <div className="deploy-site-item-form-item">
                  <label>
                    <Skeleton width={80} duration={2} />
                  </label>
                  <span>
                    <Skeleton width={150} duration={2} />
                  </span>
                </div>
                <div className="deploy-site-item-form-item">
                  <label>
                    <Skeleton width={80} duration={2} />
                  </label>
                  <span>
                    <Skeleton width={150} duration={2} />
                  </span>
                </div>
                <div className="deploy-site-item-form-item">
                  <label>
                    <Skeleton width={80} duration={2} />
                  </label>
                  <span>
                    <Skeleton width={150} duration={2} />
                  </span>
                </div>
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
Example #19
Source File: ContinuousDeployment.tsx    From argo-react with MIT License 4 votes vote down vote up
ContinuousDeployment = () => {
  const { selectedProject, projectLoading, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);

  const [repoBranches, setRepoBranches] = useState<any[]>([]);
  const [repoBranchesLoading, setRepoBranchesLoading] = useState<boolean>(true);
  const [addWebhookLoading, setAddWebhookLoading] = useState<boolean>(false);

  const [installationId, setInstallationId] = useState<number>(0);

  const [branch, setBranch] = useState<string>("");
  const [name, setName] = useState<string>("");
  const [workspace, setWorkspace] = useState<string>("");
  const [framework, setFramework] = useState<string>("static");
  const [packageManager, setPackageManager] = useState<string>("npm");
  const [buildCommand, setBuildCommand] = useState<string>("");
  const [publishDirectory, setPublishDirectory] = useState<string>("");
  const [protocol, setProtocol] = useState<string>("");

  const [webhookDisabled, setWebhookDisabled] = useState<boolean>(false);

  const componentIsMounted = useRef(true);

  useEffect(() => {
    return () => {
      componentIsMounted.current = false;
    };
  }, []);

  let buildCommandPrefix: string = "";
  if (packageManager === "npm") {
    buildCommandPrefix = "npm run";
  } else {
    buildCommandPrefix = "yarn";
  }

  useEffect(() => {
    if (
      name &&
      branch &&
      framework !== "static" &&
      packageManager &&
      buildCommand &&
      publishDirectory &&
      protocol &&
      installationId
    ) {
      setWebhookDisabled(false);
    } else {
      if (name && branch && framework === "static" && protocol && installationId) {
        setWebhookDisabled(false);
      } else {
        setWebhookDisabled(true);
      }
    }
  }, [
    branch,
    framework,
    packageManager,
    buildCommand,
    publishDirectory,
    selectedOrg,
    protocol,
    name,
    installationId,
  ]);

  useEffect(() => {
    if (framework === "static") {
      setPackageManager("");
      setBuildCommand("");
      setPublishDirectory("");
    } else if (framework === "react") {
      setPackageManager("npm");
      setBuildCommand("build");
      setPublishDirectory("build");
    } else if (framework === "vue") {
      setPackageManager("npm");
      setBuildCommand("build");
      setPublishDirectory("dist");
    } else if (framework === "angular") {
      setPackageManager("npm");
      setBuildCommand("build");
      setPublishDirectory("dist/your-app-name");
    } else if (framework === "next") {
      setPackageManager("yarn");
      setBuildCommand("next build && next export");
      setPublishDirectory("out");
    }
  }, [framework]);

  useEffect(() => {
    if (selectedProject) {
      const repoName = selectedProject?.githubUrl
        .substring(19, selectedProject?.githubUrl.length - 4)
        .split("/")[1];
      const ownerName = selectedProject?.githubUrl
        .substring(19, selectedProject?.githubUrl.length - 4)
        .split("/")[0];
      const branchUrl = `https://api.github.com/repos/${ownerName}/${repoName}/branches`;

      ApiService.getGithubRepoBranches(branchUrl).subscribe((res) => {
        if (componentIsMounted.current) {
          setRepoBranches(res.branches);
          setBranch(res.branches[0].name);
          setRepoBranchesLoading(false);
        }
      });

      ApiService.getAllGithubAppInstallation().subscribe((res) => {
        if (componentIsMounted.current) {
          const repoOwners: any[] = res.installations.map((installation: any) => ({
            name: installation.account.login,
            avatar: installation.account.avatar_url,
            installationId: installation.id,
          }));
          if (repoOwners.length) {
            const newRepoOwner = repoOwners.filter(
              (repoOwner) => repoOwner.name === ownerName,
            )[0];
            setInstallationId(newRepoOwner.installationId);
          }
        }
      });

      const framework = selectedProject.latestDeployment?.configuration.framework;
      const protocol = selectedProject.latestDeployment?.configuration.protocol;
      setFramework(framework ? framework : "");
      setProtocol(protocol ? protocol : "");
    }
  }, [selectedProject]);

  const addWebhook = () => {
    setAddWebhookLoading(true);
    const configuration = {
      framework,
      workspace,
      packageManager,
      buildCommand,
      publishDir: publishDirectory,
      branch,
      protocol,
    };
    ApiService.createConfiguration(configuration).subscribe((confResult) => {
      if (componentIsMounted.current) {
        const webhook = {
          orgId: selectedOrg?._id,
          projectId: selectedProject?._id,
          installationId,
        };
        ApiService.connectWebhook(webhook).subscribe((result) => {
          if (componentIsMounted.current) {
            const webhookMeta = {
              orgId: selectedOrg?._id,
              name,
              projectId: selectedProject?._id,
              configurationId: confResult._id,
              installationId,
            };
            ApiService.createWebhook(webhookMeta).subscribe((result) => {
              if (componentIsMounted.current) {
                setName("");
                setBranch(repoBranches[0].name);
                setWorkspace("");
                setFramework("static");
                setPackageManager("npm");
                setBuildCommand("");
                setPublishDirectory("");
                setProtocol("");
                setAddWebhookLoading(false);
                fetchProject(`${selectedProject?._id}`);
              }
            });
          }
        });
      }
    });
  };

  return (
    <div className="ContinuousDeployment">
      <ReactTooltip />
      <div className="settings-right-container">
        <div className="settings-project-details">
          <div className="settings-project-header">Continuous Deployment</div>
          <div className="settings-project-body">
            <div className="settings-project-header-subtitle">
              Settings for Continuous Deployment from a Git repository
            </div>
            <div className="settings-project-add-webhook-conf">
              <div className="webhook-header">Add new</div>
              <div className="deploy-site-item-form">
                <div className="deploy-site-item-form-item">
                  <label>
                    Name
                    <span
                      className="tooltip"
                      data-tip="name of your CD pipeline (e.g. PROD, DEV, TESTING)."
                    >
                      <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                    </span>
                  </label>
                  <input
                    type="text"
                    className="deploy-site-item-input"
                    value={name}
                    onChange={(e) => setName(e.target.value)}
                  />
                </div>
                <div className="deploy-site-item-form-item">
                  <label>Branch to deploy</label>
                  <div className="deploy-site-item-select-container">
                    <select
                      className="deploy-site-item-select"
                      value={branch}
                      onChange={(e) => setBranch(e.target.value)}
                    >
                      {repoBranches.map((branch, index) => (
                        <option value={branch.name} key={index}>
                          {branch.name}
                        </option>
                      ))}
                    </select>
                    <span className="select-down-icon">
                      {!repoBranchesLoading ? (
                        <FontAwesomeIcon icon={faChevronDown} />
                      ) : (
                        <BounceLoader size={20} color={"#0a3669"} loading={true} />
                      )}
                    </span>
                  </div>
                </div>
                <div className="deploy-site-item-form-item">
                  <label>
                    Protocol
                    <span
                      className="tooltip"
                      data-tip="The framework that your app is built upon."
                    >
                      <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                    </span>
                  </label>
                  <div className="deploy-site-item-select-container">
                    <select
                      className="deploy-site-item-select"
                      value={protocol}
                      onChange={(e) => setProtocol(e.target.value)}
                    >
                      <option value="arweave">Arweave</option>
                      <option value="skynet">Skynet</option>
                      <option value="ipfs-filecoin">IPFS-Filecoin</option>
                      <option value="ipfs-pinata">IPFS-Pinata</option>
                    </select>
                    <span className="select-down-icon">
                      <FontAwesomeIcon icon={faChevronDown} />
                    </span>
                  </div>
                </div>
                <div className="deploy-site-item-form-item">
                  <label>
                    Workspace to deploy
                    <span
                      className="tooltip"
                      data-tip="If your app is a monorepo, then you can specify your app directory you want to deploy using the workspace."
                    >
                      <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                    </span>
                  </label>
                  <input
                    type="text"
                    className="deploy-site-item-input"
                    value={workspace}
                    onChange={(e) => setWorkspace(e.target.value)}
                  />
                </div>
                {framework !== "static" && (
                  <>
                    <div className="deploy-site-item-form-item">
                      <label>
                        Package Manager
                        <span
                          className="tooltip"
                          data-tip="The package manager that you want your app to be built with."
                        >
                          <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                        </span>
                      </label>
                      <div className="deploy-site-item-select-container">
                        <select
                          className="deploy-site-item-select"
                          value={packageManager}
                          onChange={(e) => setPackageManager(e.target.value)}
                        >
                          <option value="npm">NPM</option>
                          <option value="yarn">YARN</option>
                        </select>
                        <span className="select-down-icon">
                          <FontAwesomeIcon icon={faChevronDown} />
                        </span>
                      </div>
                    </div>
                    <div className="deploy-site-item-form-item">
                      <label>
                        Build command
                        <span
                          className="tooltip"
                          data-tip="The command your frontend framework provides for compiling your code."
                        >
                          <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                        </span>
                      </label>
                      {framework !== "next" ? (
                        <div className="deploy-site-item-input-container">
                          <input
                            type="text"
                            className="deploy-site-item-input-disabled"
                            value={buildCommandPrefix}
                            disabled
                          />
                          <input
                            type="text"
                            className="deploy-site-item-input-build"
                            value={buildCommand}
                            onChange={(e) => setBuildCommand(e.target.value)}
                          />
                        </div>
                      ) : (
                        <input
                          type="text"
                          className="deploy-site-item-input"
                          value={buildCommand}
                          onChange={(e) => setBuildCommand(e.target.value)}
                        />
                      )}
                    </div>
                    <div className="deploy-site-item-form-item">
                      <label>
                        Publish directory
                        <span
                          className="tooltip"
                          data-tip="The directory in which your compiled frontend will be located."
                        >
                          <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                        </span>
                      </label>
                      <input
                        type="text"
                        className="deploy-site-item-input"
                        value={publishDirectory}
                        onChange={(e) => setPublishDirectory(e.target.value)}
                      />
                    </div>
                  </>
                )}
              </div>
              <div className="button-container">
                <button
                  type="button"
                  className="primary-button"
                  onClick={addWebhook}
                  disabled={webhookDisabled}
                >
                  {addWebhookLoading && (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  )}
                  Add
                </button>
              </div>
            </div>
            <div>
              {!projectLoading ? (
                selectedProject?.webHooks.length ? (
                  <>
                    <div className="continuous-deployment-list-heading">
                      Your Configured Continuous Deployments
                    </div>
                    {selectedProject?.webHooks.map((hook) => (
                      <WebhookItem
                        type="filled"
                        id={hook._id}
                        name={hook.name}
                        branch={hook.branch}
                        protocol={hook.configurationId.protocol}
                        framework={hook.configurationId.framework}
                        workspace={hook.configurationId.workspace}
                        buildCommand={hook.configurationId.buildCommand}
                        publishDirectory={hook.configurationId.publishDir}
                        packageManager={hook.configurationId.packageManager}
                        selectedProject={selectedProject}
                      />
                    ))}
                  </>
                ) : null
              ) : (
                <>
                  <div className="continuous-deployment-list-heading">
                    Your Configured Continuous Deployments
                  </div>
                  <WebhookItem
                    type="skeleton"
                    id={"1"}
                    name={""}
                    branch={""}
                    protocol={""}
                    framework={""}
                    workspace={""}
                    buildCommand={""}
                    publishDirectory={""}
                    packageManager={""}
                    selectedProject={selectedProject}
                  />
                </>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #20
Source File: Deployment.tsx    From argo-react with MIT License 4 votes vote down vote up
Deployment = () => {
  const timeAgo = new TimeAgo("en-US");

  const history = useHistory();
  const params = useParams<any>();

  const defaultOptions = {
    loop: true,
    autoplay: true,
    animationData,
    rendererSettings: {
      preserveAspectRatio: "xMidYMid",
    },
  };

  const { currentSiteDeployConfig, currentSiteDeployLogs, selectedProject } =
    useContext<IStateModel>(StateContext);
  const { setLatestDeploymentLogs, setLatestDeploymentConfig, fetchProject } =
    useContext<IActionModel>(ActionContext);

  const [deploymentStatus, setDeploymentStatus] = useState<string>("pending");
  const [buildTime, setBuildTime] = useState<{ min: number; sec: number }>({
    min: 0,
    sec: 0,
  });
  const [paymentStatus, setPaymentStatus] = useState<string>("waiting");
  const [livePaymentStatus, setlivePaymentStatus] = useState<string>("waiting");
  const [paymentMessage, setPaymentMessage] = useState<string>("");
  const [paymentDetails, setPaymentDetails] = useState<{
    providerFee: number;
    argoFee: number;
    discount: number;
    finalArgoFee: number;
    token: string;
  }>({ providerFee: 0, argoFee: 0, discount: 0, finalArgoFee: 0, token: "ARGO" });
  const [deployedLink, setDeployedLink] = useState<string>("");
  const [deploymentLoading, setDeploymentLoading] = useState<boolean>(true);
  const [confettiStart, setConfettiStart] = useState<boolean>(false);
  const [pinDetailLoading, setPinDetailLoading] = useState<boolean>(true);
  const [pinDetail, setPinDetail] = useState<any>({ cid: "N.A", isPinned: false });
  const componentIsMounted = useRef(true);

  let socket: any = null;
  let deploymentSvc: any = null;

  useEffect(() => {
    fetchProject(params.siteid);
    deploymentStartup();
    return () => {
      if (socket) {
        socket.disconnect();
      }
      if (deploymentSvc) {
        deploymentSvc.unsubscribe();
      }
      componentIsMounted.current = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const deploymentStartup = async () => {
    setDeploymentLoading(true);
    setLatestDeploymentLogs([]);
    setDeploymentStatus("pending");
    setPaymentStatus("waiting");
    setPaymentDetails({
      providerFee: 0,
      argoFee: 0,
      discount: 0,
      finalArgoFee: 0,
      token: "ARGO",
    });
    setBuildTime({
      min: 0,
      sec: 0,
    });
    socket = socketIOClient(config.urls.API_URL);
    deploymentSvc = ApiService.getDeployment(params.deploymentid).subscribe(
      (result) => {
        if (componentIsMounted.current) {
          const deployment = {
            githubUrl: result.deployment.project.githubUrl,
            branch: result.deployment.configuration.branch,
            createdAt: result.deployment.createdAt,
            updatedAt: result.deployment.updatedAt,
            protocol: result.deployment.configuration.protocol,
            commitHash: result.deployment.commitId,
            commitMessage: result.deployment.commitMessage,
          };
          setLatestDeploymentConfig(deployment);
          currentSiteDeployLogs.splice(0, currentSiteDeployLogs.length);
          result.deployment.logs.forEach((logItem: any) => {
            logItem.log.split("\n").forEach((line: string) => {
              if (line.trim()) {
                currentSiteDeployLogs.push({
                  log: line,
                  time: moment(logItem.time).format("hh:mm:ss A MM-DD-YYYY"),
                });
              }
            });
            setLatestDeploymentLogs(currentSiteDeployLogs);
            scrollToWithContainer(currentSiteDeployLogs.length - 1);
          });
          if (result.deployment.status.toLowerCase() === "pending") {
            socket.on(`deployment.${result.deployment.topic}`, (stream: any) => {
              if (stream.type === 1) {
                stream.data.split("\n").forEach((line: string) => {
                  if (line.trim()) {
                    if (
                      currentSiteDeployLogs
                        .map((l) => l.log)
                        .indexOf(line.trim()) === -1
                    ) {
                      currentSiteDeployLogs.push({
                        log: line,
                        time: moment().format("hh:mm:ss A MM-DD-YYYY"),
                      });
                    }
                  }
                });
                setDeploymentStatus("pending");
                setLatestDeploymentLogs(currentSiteDeployLogs);
                scrollToWithContainer(currentSiteDeployLogs.length - 1);
              } else if (stream.type === 2) {
                const protocolLink = stream.data.logsToCapture.sitePreview;
                setDeployedLink(protocolLink);
                setDeploymentStatus(protocolLink ? "deployed" : "failed");
                const buildMins = Number.parseInt(`${stream.data.buildTime / 60}`);
                const buildSecs = Number.parseInt(`${stream.data.buildTime % 60}`);
                setBuildTime({ min: buildMins, sec: buildSecs });
              } else if (stream.type === 3) {
                setDeployedLink("");
                setDeploymentStatus("failed");
                setBuildTime({ min: 0, sec: 0 });
              }
            });
          } else {
            setDeployedLink(result.deployment.sitePreview);
            setDeploymentStatus(result.deployment.status.toLowerCase());
            const buildMins = Number.parseInt(`${result.deployment.buildTime / 60}`);
            const buildSecs = Number.parseInt(`${result.deployment.buildTime % 60}`);
            setBuildTime({ min: buildMins, sec: buildSecs });
          }
          const paymentSocketOpeningCondition = result.deployment.payment
            ? result.deployment.payment.status !== "success" &&
              result.deployment.payment.status !== "failed"
            : true;
          if (paymentSocketOpeningCondition) {
            if (result.deployment.payment) {
              setPaymentStatus(result.deployment.payment.status);
            }
            socket.on(`payment.${result.deployment.topic}`, (stream: any) => {
              if (stream.type === 1) {
                setPaymentStatus("started");
              } else if (stream.type === 2) {
                const paymentDetails = stream.payload;
                if (paymentDetails.status === "success") {
                  setPaymentDetails(paymentDetails);
                  setlivePaymentStatus("success");
                } else {
                  setPaymentMessage(paymentDetails.failedMessage);
                }
                setPaymentStatus(paymentDetails.status);
              }
            });
          } else {
            if (result.deployment.payment.status === "success") {
              const paymentDetails = {
                providerFee: result.deployment.payment.providerFee,
                argoFee: result.deployment.payment.argoFee,
                discount: result.deployment.payment.discount,
                finalArgoFee: result.deployment.payment.finalArgoFee,
                token: result.deployment.payment.token,
              };
              setPaymentDetails(paymentDetails);
              setPaymentStatus("success");
            } else {
              setPaymentStatus("failed");
              setPaymentMessage(result.deployment.payment.failedMessage);
            }
          }
          setDeploymentLoading(false);
        }
      },
    );
  };

  useEffect(() => {
    if (deploymentStatus === "deployed" && livePaymentStatus === "success") {
      setConfettiStart(true);
    }
  }, [deploymentStatus, livePaymentStatus]);

  let displayGithubRepo = "";
  let githubBranchLink = "";
  let githubCommitLink = "";
  if (currentSiteDeployConfig) {
    displayGithubRepo = currentSiteDeployConfig.githubUrl.substring(
      19,
      currentSiteDeployConfig.githubUrl.length - 4,
    );

    githubBranchLink = `${currentSiteDeployConfig.githubUrl.substring(
      0,
      currentSiteDeployConfig.githubUrl.length - 4,
    )}/tree/${currentSiteDeployConfig.branch}`;

    githubCommitLink = `${currentSiteDeployConfig.githubUrl.substring(
      0,
      currentSiteDeployConfig.githubUrl.length - 4,
    )}/commit/${currentSiteDeployConfig.commitHash}`;
  }

  const domains =
    selectedProject && deployedLink
      ? selectedProject.domains.filter((d) => deployedLink.indexOf(d.link) !== -1)
      : [];

  const subdomains =
    selectedProject && deployedLink
      ? selectedProject.subdomains.filter((d) => deployedLink.indexOf(d.link) !== -1)
      : [];

  const hnsDomains =
    selectedProject && deployedLink
      ? selectedProject.handshakeDomains.filter(
          (d) => deployedLink.indexOf(d.link) !== -1,
        )
      : [];

  const hnsSubdomains =
    selectedProject && deployedLink
      ? selectedProject.handshakeSubdomains.filter(
          (d) => deployedLink.indexOf(d.link) !== -1,
        )
      : [];

  const ensDomains =
    selectedProject && deployedLink
      ? selectedProject.ensDomains.filter((d) => deployedLink.indexOf(d.link) !== -1)
      : [];

  const isDomainOrSubPresent =
    [...domains, ...subdomains, ...hnsDomains, ...hnsSubdomains, ...ensDomains]
      .length > 0;

  const scrollToWithContainer = (index: number) => {
    window.scrollTo({
      top: document.getElementById("deploy-logs-container")?.scrollHeight,
      left: 0,
      behavior: "smooth",
    });
    var myElement = document.getElementById(`deploy-logs-items-${index}`);
    var topPos = myElement?.offsetTop;
    if (document && document.getElementById("deploy-logs-list")) {
      (document as any).getElementById("deploy-logs-list").scrollTop = topPos
        ? topPos
        : 0;
    }
  };

  const showProtocolImage = (protocol: string) => {
    switch (protocol) {
      case "arweave":
        return (
          <img
            src={require("../../../../assets/png/ar_light.png")}
            alt="arweave"
            className="site-deployment-logo"
            height={24}
            width={24}
            loading="lazy"
          />
        );
      case "skynet":
        return (
          <img
            src={require("../../../../assets/png/skynet.png")}
            alt="skynet"
            className="site-deployment-logo"
            height={24}
            width={24}
            loading="lazy"
          />
        );
      case "ipfs-filecoin":
        return (
          <img
            src={require("../../../../assets/png/filecoin.png")}
            alt="skynet"
            className="site-deployment-logo"
            height={24}
            width={24}
            loading="lazy"
          />
        );
      case "ipfs-pinata":
        return (
          <img
            src={require("../../../../assets/svg/pinata.svg")}
            alt="skynet"
            className="site-deployment-logo"
            height={24}
            width={24}
            loading="lazy"
          />
        );
      case "neofs":
        return (
          <img
            src={require("../../../../assets/png/neo-light.png")}
            alt="neofs"
            className="site-deployment-logo"
            height={24}
            width={24}
            loading="lazy"
          />
        );

      default:
        return (
          <img
            src={require("../../../../assets/png/question_mark.png")}
            alt="?"
            className="site-deployment-logo"
            height={24}
            width={24}
            loading="lazy"
          />
        );
    }
  };

  const showProtocolText = (protocol: string) => {
    switch (protocol) {
      case "arweave":
        return (
          <span className="site-deployment-link">
            Deploying on Arweave, Preview in a minute
          </span>
        );
      case "skynet":
        return (
          <span className="site-deployment-link">
            Deploying on Skynet, Preview in a minute
          </span>
        );
      case "ipfs-filecoin":
        return (
          <span className="site-deployment-link">
            Deploying on IPFS with Filecoin, Preview in a minute
          </span>
        );
      case "ipfs-pinata":
        return (
          <span className="site-deployment-link">
            Deploying on IPFS with Pinata, Preview in a minute
          </span>
        );
      case "neofs":
        return (
          <span className="site-deployment-link">
            Deploying on NeoFS, Preview in a minute
          </span>
        );

      default:
        return (
          <span className="site-deployment-link">
            Cannot find Protocol to Deploy
          </span>
        );
    }
  };

  const showProtocolPrice = (protocol: string) => {
    switch (protocol) {
      case "arweave":
        return <span>{paymentDetails?.providerFee || 0} AR</span>;
      case "skynet":
        return <span>N.A</span>;
      case "neofs":
        return <span>{paymentDetails?.providerFee || 0} NEO</span>;
      case "ipfs-filecoin":
        return <span>{paymentDetails?.providerFee || 0} FIL</span>;
      case "ipfs-pinata":
        return <span>N.A</span>;
      default:
        return <span>{paymentDetails?.providerFee || 0} ?</span>;
    }
  };

  useEffect(() => {
    if (deploymentStatus === "deployed") {
      if (currentSiteDeployConfig?.protocol === "ipfs-filecoin") {
        getFilecoinPinDetais();
      } else if (currentSiteDeployConfig?.protocol === "ipfs-pinata") {
        getPinataPinDetais();
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [deploymentStatus, currentSiteDeployConfig?.protocol]);

  const getFilecoinPinDetais = async () => {
    setPinDetailLoading(true);
    if (deployedLink) {
      const cid = deployedLink.split("https://ipfs.infura.io/ipfs/")[1];
      ApiService.getFilecoinPinDetails(cid).subscribe((data) => {
        if (componentIsMounted.current) {
          setPinDetail(data);
          setPinDetailLoading(false);
        }
      });
    } else {
      setPinDetailLoading(false);
    }
  };
  const getPinataPinDetais = async () => {
    setPinDetailLoading(true);
    if (deployedLink) {
      const cid = deployedLink.split("https://ipfs.infura.io/ipfs/")[1];
      ApiService.getPinataPinDetails(cid).subscribe((data) => {
        if (componentIsMounted.current) {
          setPinDetail(data);
          setPinDetailLoading(false);
        }
      });
    } else {
      setPinDetailLoading(false);
    }
  };

  const [width, height] = useWindowSize();

  const confettiStyles = {
    zIndex: 2,
    position: "fixed" as "fixed",
    pointerEvents: "none" as "none",
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  };

  return (
    <div className="SiteDeployment">
      {confettiStart && (
        <div className="confetti-container">
          <Confetti
            width={width}
            height={height}
            style={confettiStyles}
            numberOfPieces={700}
            recycle={false}
          />
        </div>
      )}
      <div
        className="site-deployment-back"
        onClick={(e) => {
          fetchProject(params.siteid);
          history.push(`/org/${params.orgid}/sites/${params.siteid}/deployments/`);
        }}
      >
        <span>
          <FontAwesomeIcon icon={faChevronLeft} />
        </span>
        <span>All Deploys</span>
      </div>
      <div className="site-deployment-card-container max-width-set">
        <div className="site-deployment-card-header">
          <h2 className="site-deployment-card-header-title">
            {!deploymentLoading ? (
              <>
                <span>
                  {deploymentStatus === "pending" ? (
                    "Deploy in Progress"
                  ) : deploymentStatus === "deployed" ? (
                    <div>Deployment successful</div>
                  ) : (
                    "Deployment failed"
                  )}
                </span>
                {deploymentStatus === "pending" ? (
                  <Lottie options={defaultOptions} height={54} width={76} />
                ) : deploymentStatus === "deployed" ? (
                  <LazyLoadedImage height={24} once>
                    <img
                      src={require("../../../../assets/svg/rocket_background.svg")}
                      alt="rocket"
                      className="rocket-icon"
                      height={24}
                      width={24}
                      loading="lazy"
                    />
                  </LazyLoadedImage>
                ) : deploymentStatus === "failed" ? (
                  <LazyLoadedImage height={24} once>
                    <img
                      src={require("../../../../assets/svg/error.svg")}
                      alt="rocket"
                      className="rocket-icon"
                      height={24}
                      width={24}
                      loading="lazy"
                    />
                  </LazyLoadedImage>
                ) : null}
              </>
            ) : (
              <Skeleton width={200} duration={2} />
            )}
          </h2>
          <p className="site-deployment-card-header-description">
            {!deploymentLoading ? (
              <>
                <u>Production</u>: {currentSiteDeployConfig?.branch}
                {currentSiteDeployConfig.commitHash ? (
                  <>
                    @
                    <a
                      href={githubCommitLink}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="commit-link"
                    >
                      {currentSiteDeployConfig.commitHash.substr(0, 7)}{" "}
                      {currentSiteDeployConfig.commitMessage
                        ? `- ${currentSiteDeployConfig.commitMessage.substr(
                            0,
                            84,
                          )}...`
                        : ""}
                    </a>
                  </>
                ) : null}
              </>
            ) : (
              <Skeleton width={400} duration={2} />
            )}
          </p>
          <p className="site-deployment-card-header-description">
            {!deploymentLoading ? (
              <>
                {deploymentStatus === "pending"
                  ? currentSiteDeployLogs[0]?.time
                    ? `Deployment started ${timeAgo.format(
                        moment(`${currentSiteDeployConfig.createdAt}`).toDate(),
                      )}`
                    : null
                  : `Deployment done at ${moment(
                      currentSiteDeployConfig.updatedAt,
                    ).format("MMM DD, YYYY hh:mm a")}`}
              </>
            ) : (
              <Skeleton width={400} duration={2} />
            )}
          </p>
        </div>
        <div className="site-deployment-card-content">
          {isDomainOrSubPresent && (
            <div className="site-deployment-card-fields">
              <span className="site-deployment-github-icon">
                <FontAwesomeIcon icon={faGlobe} />
              </span>
              {!deploymentLoading ? (
                <>
                  {domains.map((d: IDomain, i: number, a: IDomain[]) => (
                    <>
                      <a
                        href={`https://${d.name}`}
                        className="site-deployment-link"
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {d.name}
                      </a>
                      {(i !== a.length - 1 ||
                        subdomains.length > 0 ||
                        hnsDomains.length > 0 ||
                        hnsSubdomains.length > 0 ||
                        ensDomains.length > 0) && (
                        <span className="comma-sep">,</span>
                      )}
                    </>
                  ))}
                  {subdomains.map((s: IDomain, i: number, a: IDomain[]) => (
                    <>
                      <a
                        href={`https://${s.name}`}
                        className="site-deployment-link"
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {s.name}
                      </a>
                      {(i !== a.length - 1 ||
                        hnsDomains.length > 0 ||
                        hnsSubdomains.length > 0 ||
                        ensDomains.length > 0) && (
                        <span className="comma-sep">,</span>
                      )}
                    </>
                  ))}
                  {hnsDomains.map((s: IDomain, i: number, a: IDomain[]) => (
                    <>
                      <a
                        href={`http://${s.name}`}
                        className="site-deployment-link"
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {s.name}
                      </a>
                      {(i !== a.length - 1 ||
                        hnsSubdomains.length > 0 ||
                        ensDomains.length > 0) && (
                        <span className="comma-sep">,</span>
                      )}
                    </>
                  ))}
                  {hnsSubdomains.map((s: IDomain, i: number, a: IDomain[]) => (
                    <>
                      <a
                        href={`http://${s.name}`}
                        className="site-deployment-link"
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {s.name}
                      </a>
                      {(i !== a.length - 1 || ensDomains.length > 0) && (
                        <span className="comma-sep">,</span>
                      )}
                    </>
                  ))}
                  {ensDomains.map((s: IDomain, i: number, a: IDomain[]) => (
                    <>
                      <a
                        href={`http://${s.name}`}
                        className="site-deployment-link"
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {s.name}
                      </a>
                      {i !== a.length - 1 && <span className="comma-sep">,</span>}
                    </>
                  ))}
                </>
              ) : (
                <Skeleton width={300} duration={2} />
              )}
            </div>
          )}
          <div className="site-deployment-card-fields">
            <span className="site-deployment-github-icon">
              <FontAwesomeIcon icon={faGithub} />
            </span>
            {!deploymentLoading ? (
              <a
                href={githubBranchLink}
                className="site-deployment-link"
                target="_blank"
                rel="noopener noreferrer"
              >
                {displayGithubRepo} (branch: {currentSiteDeployConfig?.branch})
              </a>
            ) : (
              <Skeleton width={300} duration={2} />
            )}
          </div>
          <div className="site-deployment-card-fields">
            <LazyLoadedImage height={24} once>
              {showProtocolImage(currentSiteDeployConfig?.protocol)}
            </LazyLoadedImage>
            {!deploymentLoading ? (
              deploymentStatus === "deployed" ? (
                <a
                  href={deployedLink}
                  className="site-deployment-link"
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  Preview deploy
                </a>
              ) : deploymentStatus === "pending" ? (
                showProtocolText(currentSiteDeployConfig?.protocol)
              ) : (
                <span className="site-deployment-link">
                  Deploying failed, no link available
                </span>
              )
            ) : (
              <Skeleton width={200} duration={2} />
            )}
          </div>
          {paymentStatus === "success" && deploymentStatus === "deployed" && (
            <div className="site-deployment-card-fields">
              <div className="button-container">
                <SharePopup
                  isOpen={confettiStart}
                  link={deployedLink}
                  protocol={currentSiteDeployConfig.protocol}
                  paymentStatus={paymentStatus}
                />
              </div>
            </div>
          )}
        </div>
      </div>
      {deploymentStatus !== "pending" && (
        <div className="site-deployment-card-container deploy-container">
          <div className="site-deployment-header-title">Deploy Summary</div>
          <div className="deploy-summary-item">
            <div className="deploy-summary-item-info-icon">
              <FontAwesomeIcon icon={faInfoCircle} />
            </div>
            <div className="deploy-summary-item-info-container">
              <div className="deploy-summary-item-info-title">
                Total time to Build & Deploy: {buildTime?.min}m {buildTime?.sec}s
              </div>
              {(buildTime?.min !== 0 || buildTime?.sec !== 0) && (
                <div className="deploy-summary-item-info-description">
                  Build started at {currentSiteDeployLogs[0]?.time} and ended at{" "}
                  {currentSiteDeployLogs[currentSiteDeployLogs.length - 1]?.time}.
                </div>
              )}
            </div>
          </div>
        </div>
      )}
      {deploymentStatus !== "pending" && (
        <div className="site-deployment-card-container deploy-container">
          <div className="site-deployment-header-title">Payment Summary</div>
          <div className="site-deployment-body">
            {paymentStatus === "waiting" && (
              <div className="payment-loading">
                <span>
                  <PulseLoader size={20} color={"#3664ae"} />
                </span>
                <span>Waiting for the payment to be processed...</span>
              </div>
            )}
            {paymentStatus === "started" && (
              <div className="payment-loading">
                <span>
                  <PulseLoader size={20} color={"#3664ae"} />
                </span>
                <span>Processing Payment...</span>
              </div>
            )}
            {paymentStatus === "failed" && (
              <div className="payment-failed">
                <span>
                  <LazyLoadedImage height={24} once>
                    <img
                      src={require("../../../../assets/svg/error.svg")}
                      alt="rocket"
                      className="rocket-icon"
                      height={36}
                      width={36}
                      loading="lazy"
                    />
                  </LazyLoadedImage>
                </span>
                <span>{paymentMessage}</span>
                {paymentMessage ===
                  "Payment failed due to insufficient allowance." && (
                  <button
                    className="set-allowance"
                    onClick={() => history.push("/wallet/recharge")}
                  >
                    Set Allowance
                  </button>
                )}
              </div>
            )}
            {paymentStatus === "success" && (
              <>
                <div className="site-deployment-body-item">
                  <label>Build Time:</label>
                  <span>
                    {buildTime?.min}m {buildTime?.sec}s
                  </span>
                </div>
                <div className="site-deployment-body-item">
                  <label>Provider Fee:</label>
                  {showProtocolPrice(currentSiteDeployConfig?.protocol)}
                </div>
                <div className="site-deployment-body-item">
                  <label>Total Fee:</label>
                  <span>
                    {paymentDetails?.argoFee || 0} ${paymentDetails?.token || "ARGO"}
                  </span>
                </div>
                <div className="site-deployment-body-item">
                  <label>Discount:</label>
                  <span>
                    {paymentDetails?.discount || 0} $
                    {paymentDetails?.token || "ARGO"}
                  </span>
                </div>
                <div className="site-deployment-body-item">
                  <label>Final Payment:</label>
                  <span>
                    {paymentDetails?.finalArgoFee || 0} $
                    {paymentDetails?.token || "ARGO"}
                  </span>
                </div>
              </>
            )}
          </div>
        </div>
      )}
      {deploymentStatus === "deployed" &&
        currentSiteDeployConfig?.protocol === "ipfs-filecoin" && (
          <div className="site-deployment-card-container deploy-container">
            <div className="site-deployment-header-title">
              Filecoin Pinning Details
            </div>
            <div className="site-deployment-body">
              <div className="site-deployment-body-item">
                <label>Filecoin CID:</label>
                <span>
                  {!pinDetailLoading ? (
                    pinDetail.cid
                  ) : (
                    <Skeleton width={200} duration={2} />
                  )}
                </span>
              </div>
              <div className="site-deployment-body-item">
                <label>Filecoin Pinning Status:</label>
                <span>
                  {!pinDetailLoading ? (
                    pinDetail.isPinned ? (
                      "Pinned"
                    ) : (
                      "Not Pinned"
                    )
                  ) : (
                    <Skeleton width={200} duration={2} />
                  )}
                </span>
              </div>
              {!pinDetailLoading && pinDetail.isPinned && (
                <div className="site-deployment-body-item">
                  <label>Filecoin Pinned Date:</label>
                  <span>
                    {!pinDetailLoading ? (
                      moment(pinDetail.pinnedDate).format("MMM DD, YYYY hh:mm A")
                    ) : (
                      <Skeleton width={200} duration={2} />
                    )}
                  </span>
                </div>
              )}
            </div>
          </div>
        )}
      {deploymentStatus === "deployed" &&
        currentSiteDeployConfig?.protocol === "ipfs-pinata" && (
          <div className="site-deployment-card-container deploy-container">
            <div className="site-deployment-header-title">
              Pinata Pinning Details
            </div>
            <div className="site-deployment-body">
              <div className="site-deployment-body-item">
                <label>IPFS CID:</label>
                <span>
                  {!pinDetailLoading ? (
                    pinDetail.cid
                  ) : (
                    <Skeleton width={200} duration={2} />
                  )}
                </span>
              </div>
              <div className="site-deployment-body-item">
                <label>IPFS Pinning Status:</label>
                <span>
                  {!pinDetailLoading ? (
                    pinDetail.isPinned ? (
                      "Pinned"
                    ) : (
                      "Not Pinned"
                    )
                  ) : (
                    <Skeleton width={200} duration={2} />
                  )}
                </span>
              </div>
              {!pinDetailLoading && pinDetail.isPinned && (
                <div className="site-deployment-body-item">
                  <label>IPFS Pinned Date:</label>
                  <span>
                    {!pinDetailLoading ? (
                      moment(pinDetail.pinnedDate).format("MMM DD, YYYY hh:mm A")
                    ) : (
                      <Skeleton width={200} duration={2} />
                    )}
                  </span>
                </div>
              )}
            </div>
          </div>
        )}
      <div
        className="site-deployment-card-container deploy-container"
        id="deploy-logs-container"
      >
        <div className="card-header-title deploy-logs-card-title">
          <div className="card-header-deploy-title-container">
            <div className="card-header-deploy-title">Deploy Logs</div>
            <div className="card-header-deploy-subtitle">
              Please note that the realtime log streaming may not show all the logs
              based on your connection bandwidth. Please refresh if you don't see
              some logs
            </div>
          </div>
          {/* <button className="copy-to-clipboard-button">Copy to clipboard</button> */}
          <div className="refresh-control" onClick={deploymentStartup}>
            <FontAwesomeIcon icon={faSyncAlt}></FontAwesomeIcon>
          </div>
        </div>
        <div className="deploy-logs-container" id="deploy-logs-list">
          {
            <div className="deploy-logs-items" id={`deploy-logs-items-${1}`} key={1}>
              {currentSiteDeployLogs?.map((currLog, i) => (
                <div
                  className="deploy-logs-items"
                  id={`deploy-logs-items-${i}`}
                  key={i}
                >
                  {currLog.time}:{" "}
                  {currLog.log.indexOf("https://arweave.net/") !== -1 ||
                  currLog.log.indexOf("https://siasky.net/") !== -1 ||
                  currLog.log.indexOf("https://http.fs.neo.org/") !== -1 ||
                  currLog.log.indexOf("https://ipfs.infura.io/ipfs/") !== -1 ? (
                    <a
                      href={currLog.log.trim()}
                      className="log-site-link"
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      {currLog.log}
                    </a>
                  ) : (
                    currLog.log
                  )}
                </div>
              ))}
            </div>
          }
        </div>
      </div>
    </div>
  );
}
Example #21
Source File: DeploySiteConfig.tsx    From argo-react with MIT License 4 votes vote down vote up
function DeploySiteConfig() {
  const history = useHistory();

  const {
    user,
    selectedOrg,
    selectedRepoForTriggerDeployment,
    orgLoading,
    userLoading,
  } = useContext<IStateModel>(StateContext);
  const { setLatestDeploymentConfig, setSelectedOrganization } =
    useContext<IActionModel>(ActionContext);

  const [createDeployProgress, setCreateDeployProgress] = useState(1);
  const [showRepoOrgDropdown, setShowRepoOrgDropdown] = useState<boolean>(false);
  const [reposOwnerDetails, setReposOwnerDetails] = useState<any[]>([]);
  const [reposSelectedOwnerRepoDetails, setReposSelectedOwnerRepoDetails] = useState<
    any[]
  >([]);
  const [selectedRepoOwner, setSelectedRepoOwner] = useState<any>();
  const [currentRepoOwner, setCurrentRepoOwner] = useState<string>("");
  const [ownerLoading, setOwnerLoading] = useState<boolean>(true);
  const [repoLoading, setRepoLoading] = useState<boolean>(true);
  const [repoBranches, setRepoBranches] = useState<any[]>([]);
  const [buildEnv, setBuildEnv] = useState<any[]>([]);
  const [repoBranchesLoading, setRepoBranchesLoading] = useState<boolean>(true);

  const [autoPublish, setAutoPublish] = useState<boolean>(true);
  const [selectedRepo, setSelectedRepo] = useState<any>();
  const [owner, setOwner] = useState<any>();
  const [branch, setBranch] = useState<string>("master");
  const [workspace, setWorkspace] = useState<string>();
  const [framework, setFramework] = useState<string>("react");
  const [packageManager, setPackageManager] = useState<string>("npm");
  const [buildCommand, setBuildCommand] = useState<string>("");
  const [publishDirectory, setPublishDirectory] = useState<string>("");
  const [protocol, setProtocol] = useState<string>("");
  const [startDeploymentLoading, setStartDeploymentLoading] =
    useState<boolean>(false);
  const [deployDisabled, setDeployDisabled] = useState<boolean>(false);
  const [showGithubRepos, setShowGithubRepos] = useState<boolean>(false);
  const [errorWarning, setErrorWarning] = useState<boolean>(false);
  const [errorMessage, setErrorMessage] = useState<string>("");

  const componentIsMounted = useRef(true);

  useEffect(() => {
    return () => {
      componentIsMounted.current = false;
    };
  }, []);

  useEffect(() => {
    if (
      selectedRepo &&
      owner &&
      branch &&
      framework !== "static" &&
      packageManager &&
      buildCommand &&
      publishDirectory &&
      protocol &&
      selectedOrg?.wallet &&
      !orgLoading
    ) {
      setDeployDisabled(false);
    } else {
      if (
        selectedRepo &&
        owner &&
        branch &&
        framework === "static" &&
        protocol &&
        selectedOrg?.wallet &&
        !orgLoading
      ) {
        setDeployDisabled(false);
      } else {
        setDeployDisabled(true);
      }
    }
  }, [
    selectedRepo,
    owner,
    branch,
    framework,
    packageManager,
    buildCommand,
    publishDirectory,
    user,
    selectedOrg,
    orgLoading,
    protocol,
  ]);

  useEffect(() => {
    if (framework === "static") {
      setPackageManager("");
      setBuildCommand("");
      setPublishDirectory("");
    } else if (framework === "react") {
      setPackageManager("npm");
      setBuildCommand("build");
      setPublishDirectory("build");
    } else if (framework === "vue") {
      setPackageManager("npm");
      setBuildCommand("build");
      setPublishDirectory("dist");
    } else if (framework === "angular") {
      setPackageManager("npm");
      setBuildCommand("build");
      setPublishDirectory("dist/your-app-name");
    } else if (framework === "next") {
      setPackageManager("yarn");
      setBuildCommand("next build && next export");
      setPublishDirectory("out");
    }
  }, [framework]);

  useEffect(() => {
    if (selectedOrg) {
      setOwner(selectedOrg);
    } else if (user?.organizations && user.organizations[0]) {
      setOwner(user.organizations[0]);
    }
  }, [user, selectedOrg]);

  useEffect(() => {
    if (selectedRepoForTriggerDeployment) {
      const repoName = selectedRepoForTriggerDeployment.github_url
        .substring(19, selectedRepoForTriggerDeployment.github_url.length - 4)
        .split("/")[1];
      const ownerName = selectedRepoForTriggerDeployment.github_url
        .substring(19, selectedRepoForTriggerDeployment.github_url.length - 4)
        .split("/")[0];

      setSelectedRepo({
        name: repoName,
        clone_url: selectedRepoForTriggerDeployment.github_url,
      });
      setCurrentRepoOwner(ownerName);
      setFramework(selectedRepoForTriggerDeployment.framework);
      setWorkspace(selectedRepoForTriggerDeployment.workspace);
      setPackageManager(selectedRepoForTriggerDeployment.package_manager);
      setBuildCommand(selectedRepoForTriggerDeployment.build_command);
      setPublishDirectory(selectedRepoForTriggerDeployment.publish_dir);
      setProtocol(selectedRepoForTriggerDeployment.protocol);
      setCreateDeployProgress(3);

      const branchUrl = `https://api.github.com/repos/${ownerName}/${repoName}/branches`;
      ApiService.getGithubRepoBranches(branchUrl).subscribe((res) => {
        if (componentIsMounted.current) {
          setRepoBranches(res.branches);
          setBranch(selectedRepoForTriggerDeployment.branch);
          setRepoBranchesLoading(false);
        }
      });
    }
  }, [selectedRepoForTriggerDeployment]);

  useEffect(() => {
    if (currentRepoOwner && selectedRepoForTriggerDeployment) {
      ApiService.getAllGithubAppInstallation().subscribe((res) => {
        if (componentIsMounted.current) {
          const repoOwners: any[] = res.installations.map((installation: any) => ({
            name: installation.account.login,
            avatar: installation.account.avatar_url,
            installationId: installation.id,
          }));
          if (repoOwners.length) {
            const newRepoOwner = repoOwners.filter(
              (repoOwner) => repoOwner.name === currentRepoOwner,
            )[0];
            setSelectedRepoOwner(newRepoOwner);
          }
        }
      });
    }
  }, [currentRepoOwner, selectedRepoForTriggerDeployment]);

  useEffect(() => {
    const bc = new BroadcastChannel("github_app_auth");
    bc.onmessage = (msg: string) => {
      if (msg === "authorized") {
        setShowGithubRepos(true);
        getAllGithubInstallations();
      }
    };
    return () => {
      bc.close();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const getAllGithubInstallations = () => {
    setOwnerLoading(true);
    setRepoLoading(true);
    ApiService.getAllGithubAppInstallation().subscribe((res) => {
      if (componentIsMounted.current) {
        const repoOwners: any[] = res.installations.map((installation: any) => ({
          name: installation.account.login,
          avatar: installation.account.avatar_url,
          installationId: installation.id,
        }));
        setReposOwnerDetails(repoOwners);
        if (repoOwners.length) {
          let newRepoOwner = null;
          if (selectedRepoOwner) {
            newRepoOwner = repoOwners.filter(
              (repoOwner) => repoOwner.name === selectedRepoOwner.name,
            )[0];
          } else {
            newRepoOwner = repoOwners[0];
          }
          setSelectedRepoOwner(newRepoOwner);
          setOwnerLoading(false);
          getOwnerRepos(newRepoOwner.installationId);
        } else {
          setOwnerLoading(false);
        }
      }
    });
  };

  const getOwnerRepos = (installationId: string) => {
    setRepoLoading(true);
    ApiService.getAllOwnerRepos(installationId).subscribe((res) => {
      if (componentIsMounted.current) {
        const repositories: any[] = res.repositories.map((repo: any) => ({
          clone_url: repo.clone_url,
          branches_url: repo.branches_url.split("{")[0],
          name: repo.name,
          fullName: repo.full_name,
          private: repo.private,
          repositoryId: repo.id,
        }));
        setReposSelectedOwnerRepoDetails(repositories);
        setRepoLoading(false);
      }
    });
  };

  const selectRepoOwner = (repoOwner: any) => {
    getOwnerRepos(repoOwner.installationId);
    setSelectedRepoOwner(repoOwner);
    setShowRepoOrgDropdown(false);
  };

  const selectRepositories = (repo: any) => {
    setSelectedRepo(repo);
    setCreateDeployProgress(2);
    setRepoBranchesLoading(true);
    ApiService.getGithubRepoBranches(repo.branches_url).subscribe((res) => {
      if (componentIsMounted.current) {
        setRepoBranches(res.branches);
        setBranch(res.branches[0].name);
        setRepoBranchesLoading(false);
      }
    });
  };

  const startDeployment = async () => {
    setErrorWarning(false);
    setErrorMessage("");
    setStartDeploymentLoading(true);
    const configuration = {
      framework,
      workspace,
      packageManager,
      buildCommand,
      publishDir: publishDirectory,
      branch,
      protocol,
    };
    ApiService.createConfiguration(configuration).subscribe(
      (result) => {
        if (componentIsMounted.current) {
          const uniqueTopicId = uuidv4();

          const deployment = {
            orgId: selectedOrg?._id,
            githubUrl: selectedRepo.clone_url,
            folderName: selectedRepo.name,
            owner: selectedRepoOwner.name,
            installationId: selectedRepoOwner.installationId,
            repositoryId: selectedRepo.repositoryId,
            organizationId: owner._id,
            uniqueTopicId,
            configurationId: result._id,
            env: mapBuildEnv(buildEnv),
            createDefaultWebhook: autoPublish,
          };

          ApiService.startDeployment(deployment).subscribe(
            (result) => {
              if (result.success) {
                if (componentIsMounted.current) {
                  setLatestDeploymentConfig(deployment);
                  setStartDeploymentLoading(false);
                  history.push(
                    `/org/${selectedOrg?._id}/sites/${result.projectId}/deployments/${result.deploymentId}`,
                  );
                }
              } else {
                setErrorMessage(result.message);
                setErrorWarning(true);
                setTimeout(() => {
                  setErrorWarning(false);
                  setErrorMessage("");
                }, 5000);
                setStartDeploymentLoading(false);
              }
            },
            (error) => {
              setErrorMessage(error.message);
              setErrorWarning(true);
              setTimeout(() => {
                setErrorWarning(false);
                setErrorMessage("");
              }, 5000);
              setStartDeploymentLoading(false);
            },
          );
        }
      },
      (error) => {
        setErrorMessage(error.message);
        setErrorWarning(true);
        setTimeout(() => {
          setErrorWarning(false);
          setErrorMessage("");
        }, 5000);
        setStartDeploymentLoading(false);
      },
    );
  };

  const mapBuildEnv = (buildEnv: any[]): any => {
    const buildEnvObj = {};
    buildEnv.forEach((env) => {
      Object.assign(buildEnvObj, { [env.key]: env.value });
    });
    return buildEnvObj;
  };

  const openGithubAppAuth = async () => {
    const githubSignInUrl = `${window.location.origin}/#/github/app/${user?._id}`;
    window.open(githubSignInUrl, "_blank");
  };

  const goBackAction = () => {
    if (createDeployProgress === 1) {
      history.goBack();
    } else if (createDeployProgress === 2) {
      setCreateDeployProgress(1);
    } else {
      setCreateDeployProgress(2);
    }
  };

  let buildCommandPrefix: string = "";
  if (packageManager === "npm") {
    buildCommandPrefix = "npm run";
  } else {
    buildCommandPrefix = "yarn";
  }

  const selectProtocol = (selectedProtocol: string) => {
    setProtocol(selectedProtocol);
    setCreateDeployProgress(3);
  };

  const addBuildEnv = () => {
    setBuildEnv([...buildEnv, { key: "", value: "" }]);
  };

  const removeBuildEnvItem = (id: number) => {
    setBuildEnv(buildEnv.filter((item, i) => i !== id));
  };

  const fillEnvKey = (value: string, id: number) => {
    setBuildEnv(
      buildEnv.map((item, i) =>
        i === id ? { key: value, value: item.value } : item,
      ),
    );
  };

  const fillEnvValue = (value: string, id: number) => {
    setBuildEnv(
      buildEnv.map((item, i) => (i === id ? { key: item.key, value } : item)),
    );
  };

  return (
    <div className="DeploySiteConfig">
      <RootHeader parent={"DeploySiteConfig"} />
      <main className="app-main">
        <div className="deploy-site-container">
          <div className="deploy-site-card">
            <div className="deploy-site-card-inner">
              <div className="go-back" onClick={goBackAction}>
                <span>
                  <FontAwesomeIcon icon={faArrowLeft} />
                </span>
                <span>Back</span>
              </div>
              <h1 className="deploy-site-title">Create a new site</h1>
              <div className="deploy-site-subtitle">
                Just follow these 2 step to deploy your website to ArGo
              </div>
              <div className="deploy-site-progress-bar">
                <div className="deploy-site-progress-number-container">
                  {createDeployProgress <= 1 ? (
                    <div
                      className={`deploy-site-progress-number ${
                        createDeployProgress === 1 ? "active" : ""
                      }`}
                    >
                      1
                    </div>
                  ) : (
                    <div className="deploy-site-progress-done">
                      <FontAwesomeIcon icon={faCheck} />
                    </div>
                  )}
                  <div
                    className={`deploy-site-progress-text ${
                      createDeployProgress === 1
                        ? "deploy-site-progress-text-active"
                        : ""
                    }`}
                  >
                    Pick a repository
                  </div>
                </div>
                <div className="deploy-site-progress-number-container">
                  {createDeployProgress <= 2 ? (
                    <div
                      className={`deploy-site-progress-number ${
                        createDeployProgress === 2 ? "active" : ""
                      }`}
                    >
                      2
                    </div>
                  ) : (
                    <div className="deploy-site-progress-done">
                      <FontAwesomeIcon icon={faCheck} />
                    </div>
                  )}
                  <div
                    className={`deploy-site-progress-text ${
                      createDeployProgress === 2
                        ? "deploy-site-progress-text-active"
                        : ""
                    }`}
                  >
                    Pick a Protocol
                  </div>
                </div>
                <div className="deploy-site-progress-number-container">
                  {createDeployProgress <= 3 ? (
                    <div
                      className={`deploy-site-progress-number ${
                        createDeployProgress === 3 ? "active" : ""
                      }`}
                    >
                      3
                    </div>
                  ) : (
                    <div className="deploy-site-progress-done">
                      <FontAwesomeIcon icon={faCheck} />
                    </div>
                  )}
                  <div
                    className={`deploy-site-progress-text ${
                      createDeployProgress === 3
                        ? "deploy-site-progress-text-active"
                        : ""
                    }`}
                  >
                    Build options, and deploy!
                  </div>
                </div>
              </div>
              <div className="deploy-site-form-container">
                {createDeployProgress === 1 && (
                  <div className="deploy-site-form-item">
                    <label className="deploy-site-item-title">
                      {/* Continuous Deployment: GitHub Webhook */}
                      Choose repository
                    </label>
                    <label className="deploy-site-item-subtitle">
                      Choose the repository you want to link to your site on ArGo.
                    </label>
                    {!showGithubRepos ? (
                      <div className="deployment-provider-container">
                        <div className="deployment-provider-title">
                          Connect with your favorite provider
                        </div>
                        <div className="deployment-provider-buttons">
                          <button
                            className="github-button"
                            disabled={userLoading}
                            onClick={openGithubAppAuth}
                          >
                            <span className="github-icon">
                              <GithubIcon />
                            </span>
                            <span>Github</span>
                          </button>
                        </div>
                      </div>
                    ) : reposOwnerDetails.length || ownerLoading ? (
                      <div className="deploy-site-item-repo-list-container">
                        <div className="deploy-site-item-repo-header">
                          <div
                            className="deploy-site-item-repo-header-left"
                            onClick={(e) =>
                              !ownerLoading ? setShowRepoOrgDropdown(true) : null
                            }
                          >
                            {!ownerLoading ? (
                              <LazyLoadedImage height={32} once>
                                <img
                                  src={selectedRepoOwner.avatar}
                                  alt="camera"
                                  className="deploy-site-item-repo-org-avatar"
                                  height={32}
                                  width={32}
                                  loading="lazy"
                                />
                              </LazyLoadedImage>
                            ) : (
                              <Skeleton
                                circle={true}
                                height={32}
                                width={32}
                                duration={2}
                              />
                            )}
                            <span className="deploy-site-item-repo-org-name">
                              {!ownerLoading ? (
                                selectedRepoOwner.name
                              ) : (
                                <Skeleton width={140} height={24} duration={2} />
                              )}
                            </span>
                            <span className="deploy-site-item-repo-down">
                              <FontAwesomeIcon
                                icon={
                                  showRepoOrgDropdown ? faChevronUp : faChevronDown
                                }
                              />
                            </span>
                          </div>
                          <div className="deploy-site-item-repo-header-right">
                            {/* <div className="deploy-site-item-repo-search-container">
                              <span className="deploy-site-item-repo-search-icon">
                                <FontAwesomeIcon icon={faSearch}></FontAwesomeIcon>
                              </span>
                              <input
                                type="text"
                                className="deploy-site-item-repo-search-input"
                                placeholder="Search repos"
                              />
                            </div> */}
                            <div
                              className="refresh-control"
                              onClick={getAllGithubInstallations}
                            >
                              <FontAwesomeIcon icon={faSyncAlt}></FontAwesomeIcon>
                            </div>
                          </div>
                          {showRepoOrgDropdown && (
                            <MemoRepoOrgDropdown
                              setShowDropdown={setShowRepoOrgDropdown}
                              repoOwner={reposOwnerDetails}
                              selectedRepoOwner={selectedRepoOwner}
                              setSelectedRepoOwner={selectRepoOwner}
                            />
                          )}
                        </div>
                        <div className="deploy-site-item-repo-body">
                          {!repoLoading ? (
                            reposSelectedOwnerRepoDetails.map(
                              (repo: any, index: number) => (
                                <MemoRepoItem
                                  skeleton={false}
                                  name={repo.fullName}
                                  privateRepo={repo.private}
                                  key={index}
                                  onClick={() => selectRepositories(repo)}
                                />
                              ),
                            )
                          ) : (
                            <>
                              <MemoRepoItem
                                skeleton={true}
                                name={""}
                                privateRepo={false}
                                onClick={() => null}
                              />
                              <MemoRepoItem
                                skeleton={true}
                                name={""}
                                privateRepo={false}
                                onClick={() => null}
                              />
                            </>
                          )}
                        </div>
                        <div className="deploy-site-item-repo-body">
                          Can’t see your repo here?
                          <a
                            href={`${config.urls.API_URL}/auth/github/app/new`}
                            // eslint-disable-next-line react/jsx-no-target-blank
                            target="_blank"
                            rel="noopener noreferrer"
                          >
                            Configure the ArGo app on GitHub.
                          </a>
                        </div>
                      </div>
                    ) : (
                      <div className="deployment-provider-container">
                        <div className="deployment-provider-title">
                          You don't have any configured owner, Configure it now to
                          view your repositories
                        </div>
                        <div className="deployment-provider-buttons">
                          <button
                            className="github-button"
                            onClick={openGithubAppAuth}
                          >
                            <span className="github-icon">
                              <GithubIcon />
                            </span>
                            <span>Github</span>
                          </button>
                        </div>
                      </div>
                    )}
                  </div>
                )}
                {createDeployProgress === 2 && (
                  <>
                    <div className="deploy-site-form-item">
                      <label className="deploy-site-item-title">
                        Select the protocol to deploy {selectedRepo.name}
                      </label>
                      <label className="deploy-site-item-subtitle">
                        Click on the protocol in which you want ArGo to deploy your
                        site.
                      </label>
                      <div className="deploy-protocol-list-container">
                        <ul className="deploy-protocol-list">
                          <div
                            className="deploy-protocol-image"
                            onClick={(e) => selectProtocol("arweave")}
                          >
                            <LazyLoadedImage height={50} once>
                              <img
                                src={require("../../assets/png/arweave_logo.png")}
                                alt="Arweave"
                                className="deploy-protocol-item-avatar"
                                height={50}
                                width={200}
                                loading="lazy"
                              />
                            </LazyLoadedImage>
                          </div>
                          <div
                            className="deploy-protocol-image"
                            onClick={(e) => selectProtocol("skynet")}
                          >
                            <LazyLoadedImage height={50} once>
                              <img
                                src={require("../../assets/png/skynet_logo.png")}
                                alt="Skynet"
                                className="deploy-protocol-item-avatar"
                                height={50}
                                width={200}
                                loading="lazy"
                              />
                            </LazyLoadedImage>
                            <div className="new-protocol-tag">New</div>
                          </div>
                          <div
                            className="deploy-protocol-image"
                            onClick={(e) => selectProtocol("ipfs-filecoin")}
                          >
                            <LazyLoadedImage height={50} once>
                              <img
                                src={require("../../assets/png/filecoin-full.png")}
                                alt="filecoin"
                                className="deploy-protocol-item-avatar"
                                height={50}
                                width={200}
                                loading="lazy"
                              />
                            </LazyLoadedImage>
                            <div className="new-protocol-tag">New</div>
                          </div>
                          <div
                            className="deploy-protocol-image"
                            onClick={(e) => selectProtocol("ipfs-pinata")}
                          >
                            <LazyLoadedImage height={50} once>
                              <img
                                src={require("../../assets/svg/pinata-full.svg")}
                                alt="filecoin"
                                className="deploy-protocol-item-avatar"
                                height={62}
                                width={220}
                                loading="lazy"
                              />
                            </LazyLoadedImage>
                            <div className="new-protocol-tag">New</div>
                          </div>
                          {/* <div
                            className="deploy-protocol-image"
                            onClick={(e) => selectProtocol("neofs")}
                          >
                            <LazyLoadedImage height={50} once>
                              <img
                                src={require("../../assets/svg/neofs_logo.svg")}
                                alt="neoFS"
                                className="deploy-protocol-item-avatar"
                                height={50}
                                width={200}
                                loading="lazy"
                              />
                            </LazyLoadedImage>
                            <div className="new-protocol-tag">New</div>
                          </div> */}
                        </ul>
                      </div>
                    </div>
                    <div className="button-container">
                      <button
                        type="button"
                        className="cancel-button"
                        onClick={(e) => setCreateDeployProgress(1)}
                      >
                        Back
                      </button>
                    </div>
                  </>
                )}
                {createDeployProgress === 3 && (
                  <>
                    <ReactTooltip />
                    <div className="deploy-site-form-item">
                      <label className="deploy-site-item-title">
                        Deploy settings for {selectedRepo.name}
                      </label>
                      <label className="deploy-site-item-subtitle">
                        Get more control over how ArGo builds and deploys your site
                        with these settings.
                      </label>
                      <div className="deploy-site-item-form">
                        <div className="deploy-site-item-form-item">
                          <label>Owner</label>
                          <div className="deploy-site-item-select-container">
                            <select
                              className="deploy-site-item-select"
                              value={owner._id}
                              onChange={(e) => {
                                const selOrg = user
                                  ? user.organizations
                                    ? user.organizations.filter(
                                        (org) => org._id === e.target.value,
                                      )[0]
                                    : null
                                  : null;
                                setSelectedOrganization(selOrg as any);
                                setOwner(e.target.value);
                              }}
                            >
                              {user?.organizations &&
                                user?.organizations.map((organization, index) => (
                                  <option value={organization._id} key={index}>
                                    {organization.profile.name}
                                  </option>
                                ))}
                            </select>
                            <span className="select-down-icon">
                              <FontAwesomeIcon icon={faChevronDown} />
                            </span>
                          </div>
                        </div>
                        <div className="deploy-site-item-form-item">
                          <label>Branch to deploy</label>
                          <div className="deploy-site-item-select-container">
                            <select
                              className="deploy-site-item-select"
                              value={branch}
                              onChange={(e) => setBranch(e.target.value)}
                            >
                              {repoBranches.map((branch, index) => (
                                <option value={branch.name} key={index}>
                                  {branch.name}
                                </option>
                              ))}
                            </select>
                            <span className="select-down-icon">
                              {!repoBranchesLoading ? (
                                <FontAwesomeIcon icon={faChevronDown} />
                              ) : (
                                <BounceLoader
                                  size={20}
                                  color={"#0a3669"}
                                  loading={true}
                                />
                              )}
                            </span>
                          </div>
                        </div>
                        <div className="deploy-site-item-form-item">
                          <label>
                            Workspace to deploy
                            <span
                              className="tooltip"
                              data-tip="If your app is a monorepo, then you can specify your app directory you want to deploy using the workspace."
                            >
                              <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                            </span>
                          </label>
                          <input
                            type="text"
                            className="deploy-site-item-input"
                            value={workspace}
                            onChange={(e) => setWorkspace(e.target.value)}
                          />
                        </div>
                      </div>
                    </div>
                    <div className="deploy-site-form-item">
                      <label className="deploy-site-item-title">
                        Basic build settings
                      </label>
                      <label className="deploy-site-item-subtitle">
                        If you’re using a static site generator or build tool, we’ll
                        need these settings to build your site.
                      </label>
                      <div className="deploy-site-item-form">
                        <div className="deploy-site-item-form-item">
                          <label>
                            Framework
                            <span
                              className="tooltip"
                              data-tip="The framework that your app is built upon."
                            >
                              <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                            </span>
                          </label>
                          <div className="deploy-site-item-select-container">
                            <select
                              className="deploy-site-item-select"
                              value={framework}
                              onChange={(e) => setFramework(e.target.value)}
                            >
                              <option value="static">
                                No Framework - Simple JavaScript App
                              </option>
                              <option value="react">Create React App</option>
                              <option value="vue">Vue App</option>
                              <option value="angular">Angular App</option>
                              {protocol !== "skynet" && (
                                <option value="next">Next.js App</option>
                              )}
                            </select>
                            <span className="select-down-icon">
                              <FontAwesomeIcon icon={faChevronDown} />
                            </span>
                          </div>
                        </div>
                        {framework !== "static" && (
                          <>
                            <div className="deploy-site-item-form-item">
                              <label>
                                Package Manager
                                <span
                                  className="tooltip"
                                  data-tip="The package manager that you want your app to be built with."
                                >
                                  <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                                </span>
                              </label>
                              <div className="deploy-site-item-select-container">
                                <select
                                  className="deploy-site-item-select"
                                  value={packageManager}
                                  onChange={(e) => setPackageManager(e.target.value)}
                                >
                                  <option value="npm">NPM</option>
                                  <option value="yarn">YARN</option>
                                </select>
                                <span className="select-down-icon">
                                  <FontAwesomeIcon icon={faChevronDown} />
                                </span>
                              </div>
                            </div>
                            <div className="deploy-site-item-form-item">
                              <label>
                                Build command
                                <span
                                  className="tooltip"
                                  data-tip="The command your frontend framework provides for compiling your code."
                                >
                                  <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                                </span>
                              </label>
                              {framework !== "next" ? (
                                <div className="deploy-site-item-input-container">
                                  <input
                                    type="text"
                                    className="deploy-site-item-input-disabled"
                                    value={buildCommandPrefix}
                                    disabled
                                  />
                                  <input
                                    type="text"
                                    className="deploy-site-item-input-build"
                                    value={buildCommand}
                                    onChange={(e) => setBuildCommand(e.target.value)}
                                  />
                                </div>
                              ) : (
                                <input
                                  type="text"
                                  className="deploy-site-item-input"
                                  value={buildCommand}
                                  onChange={(e) => setBuildCommand(e.target.value)}
                                />
                              )}
                            </div>
                            <div className="deploy-site-item-form-item">
                              <label>
                                Publish directory
                                <span
                                  className="tooltip"
                                  data-tip="The directory in which your compiled frontend will be located."
                                >
                                  <FontAwesomeIcon size="sm" icon={faInfoCircle} />
                                </span>
                              </label>
                              <input
                                type="text"
                                className="deploy-site-item-input"
                                value={publishDirectory}
                                onChange={(e) => setPublishDirectory(e.target.value)}
                              />
                            </div>
                          </>
                        )}
                      </div>
                    </div>
                    <div className="deploy-site-form-item">
                      <label className="deploy-site-item-title">
                        Advanced build settings
                      </label>
                      <label className="deploy-site-item-subtitle">
                        Define environment variables for more control and flexibility
                        over your build.
                      </label>

                      <div className="deploy-site-item-form">
                        <div className="deploy-site-item-form-item">
                          <label>
                            Continuous Deployment{" "}
                            <span className="new-item-tag">NEW</span>
                          </label>
                          <label className="deploy-site-item-subtitle">
                            Enabling this will automatically create a production CD
                            pipeline for your selected branch. When you push any new
                            code to GitHub, we will run our build tool and deploy the
                            result.
                          </label>
                        </div>
                        <div className="webhook-confirm-container">
                          <span className="confirm-checkbox">
                            <input
                              type="checkbox"
                              checked={autoPublish}
                              onChange={(e) => setAutoPublish(e.target.checked)}
                            />
                          </span>
                          <span>
                            <div className="webhook-title">
                              Do you want to enable Continuous Deployment?
                            </div>
                            <div className="webhook-note">
                              Note: If the project already has CD enabled, this won't
                              overwrite the existing configuration. To change this,
                              you have to go to Project Settings.
                            </div>
                          </span>
                        </div>
                      </div>
                      <div className="deploy-site-item-form">
                        <div className="deploy-site-item-form-item">
                          <label>Environment Variables</label>
                          <label className="deploy-site-item-subtitle">
                            Note that adding environment variables here won't work if
                            project already exists, you have to add environment
                            variables by going to your Project Settings {"->"}{" "}
                            Environment Variables
                          </label>
                        </div>
                        {buildEnv.length !== 0 && (
                          <div className="deploy-site-item-form-item">
                            <div className="deploy-site-env-title">
                              <label className="deploy-site-env-title-item">
                                Key
                              </label>
                              <label className="deploy-site-env-title-item">
                                Value
                              </label>
                            </div>
                            {buildEnv.map((env, i) => (
                              <div
                                className="deploy-site-item-env-container"
                                key={i}
                              >
                                <input
                                  type="text"
                                  className="deploy-site-env-input"
                                  placeholder="VARIABLE_NAME"
                                  value={env.key}
                                  onChange={(e) => fillEnvKey(e.target.value, i)}
                                />
                                <input
                                  type="text"
                                  className="deploy-site-env-input"
                                  placeholder="somevalue"
                                  value={env.value}
                                  onChange={(e) => fillEnvValue(e.target.value, i)}
                                />
                                <span
                                  className="remove-env-item"
                                  onClick={(e) => removeBuildEnvItem(i)}
                                >
                                  <FontAwesomeIcon
                                    icon={faTimesCircle}
                                  ></FontAwesomeIcon>
                                </span>
                              </div>
                            ))}
                          </div>
                        )}
                        <button
                          type="button"
                          className="add-new-var-button"
                          onClick={(e) => addBuildEnv()}
                        >
                          New Variable
                        </button>
                      </div>
                      {!selectedOrg?.wallet && !orgLoading ? (
                        <div className="wallet-details-container">
                          <div className="wallet-details-items">
                            <span className="exclamation-icon">
                              <FontAwesomeIcon
                                icon={faExclamationCircle}
                              ></FontAwesomeIcon>
                            </span>
                            <span>
                              You have to enable your organization wallet before you
                              can deploy your project.
                              <Link to="/dashboard/wallet">Enable now</Link>
                            </span>
                          </div>
                        </div>
                      ) : null}
                    </div>
                    <div className="button-container">
                      <button
                        type="button"
                        className="primary-button"
                        onClick={startDeployment}
                        disabled={deployDisabled}
                      >
                        {startDeploymentLoading && (
                          <BounceLoader size={20} color={"#fff"} loading={true} />
                        )}
                        Deploy
                      </button>
                      <button
                        type="button"
                        className="cancel-button"
                        onClick={(e) => setCreateDeployProgress(2)}
                      >
                        Back
                      </button>
                    </div>
                    {errorWarning ? (
                      <div className="warning-container">
                        <div className="warning-header">
                          <FontAwesomeIcon icon={faExclamationCircle} />{" "}
                          {errorMessage}
                        </div>
                      </div>
                    ) : null}
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </main>
    </div>
  );
}
Example #22
Source File: Wallet.tsx    From argo-react with MIT License 4 votes vote down vote up
Wallet = () => {
  const history = useHistory();
  const { userLoading, selectedOrg, orgLoading } =
    useContext<IStateModel>(StateContext);
  const { fetchUser } = useContext<IActionModel>(ActionContext);
  const [paymentsLoading, setPaymentsLoading] = useState<boolean>(false);
  const [walletLoading, setWalletLoading] = useState<boolean>(false);
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const [payments, setPayments] = useState<IPaymentModel[]>([]);
  const [orgWallet, setOrgWallet] = useState<string>("");
  const [wallet, setWallet] = useState<string>("");
  const [walletBal, setWalletBal] = useState<number>(0);
  const [argoAllowance, setArgoAllowance] = useState<number>(-1);
  const [walletLoader, setWalletLoader] = useState<boolean>(false);
  const [enableLoader, setEnableLoader] = useState<boolean>(false);
  const [removalLoader, setRemovalLoader] = useState<boolean>(false);
  const [errorWarning, setErrorWarning] = useState<boolean>(false);
  const [errorMessage, setErrorMessage] = useState<string>("");

  const componentIsMounted = useRef(true);

  const isWalletPresent = !!selectedOrg?.wallet;

  useEffect(() => {
    if (selectedOrg && !orgLoading) {
      setPaymentsLoading(true);
      setWalletLoading(true);
      // eslint-disable-next-line react-hooks/exhaustive-deps
      if (componentIsMounted.current) {
        setOrgWallet(selectedOrg.wallet ? selectedOrg.wallet.address : "");
        setWalletLoading(false);
        setPayments(selectedOrg.payments || []);
        setPaymentsLoading(false);
      }
    } else {
      if (orgLoading) {
        setPaymentsLoading(true);
        setWalletLoading(true);
      } else {
        setPaymentsLoading(false);
        setWalletLoading(false);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedOrg, orgLoading]);

  useEffect(() => {
    return () => {
      componentIsMounted.current = false;
      Web3Service.disconnectPolygon();
    };
  }, []);

  const connectWallet = async () => {
    setWalletLoader(true);
    try {
      const wallet = await Web3Service.getPolygonAccount();
      setWallet(wallet);
      let walletBal = 0;
      walletBal = await Web3Service.getArgoBalance(wallet);

      setWalletBal(walletBal);
      setWalletLoader(false);
    } catch (err) {
      setErrorMessage((err as any).message);
      setErrorWarning(true);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      setWalletLoader(false);
      // eslint-disable-next-line no-console
      console.log(err);
    }
  };

  const checkAllowance = async () => {
    setWalletLoader(true);
    try {
      await Web3Service.getPolygonAccount();
      let walletApproval = 0;
      walletApproval = await Web3Service.getArgoAllowances(orgWallet);
      setArgoAllowance(walletApproval);
      setWalletLoader(false);
    } catch (err) {
      setErrorMessage((err as any).message);
      setErrorWarning(true);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      setWalletLoader(false);
      // eslint-disable-next-line no-console
      console.log(err);
    }
  };

  const enableWallet = async () => {
    setEnableLoader(true);
    const walletBody = {
      address: wallet,
      orgId: selectedOrg?._id,
    };
    ApiService.enableWallet(walletBody).subscribe(
      (res) => {
        if (componentIsMounted.current) {
          setEnableLoader(false);
          fetchUser();
        }
      },
      (err) => {
        setErrorMessage((err as any).message);
        setErrorWarning(true);
        setTimeout(() => {
          setErrorWarning(false);
          setErrorMessage("");
        }, 5000);
      },
    );
  };

  const removeWallet = async () => {
    setRemovalLoader(true);
    try {
      await Web3Service.getPolygonAccount();
      const signature = await Web3Service.signRemoveWallet();
      const removeBody = {
        id: selectedOrg?.wallet._id,
        signature,
      };
      ApiService.removeWallet(removeBody).subscribe(
        (res) => {
          if (componentIsMounted.current) {
            setRemovalLoader(false);
            fetchUser();
          }
        },
        (err) => {
          setErrorMessage((err as any).message);
          setErrorWarning(true);
          setTimeout(() => {
            setErrorWarning(false);
            setErrorMessage("");
          }, 5000);
        },
      );
    } catch (err) {
      setErrorMessage((err as any).message);
      setErrorWarning(true);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      setRemovalLoader(false);
      // eslint-disable-next-line no-console
      console.log(err);
    }
  };
  const showProtocolPrice = (protocol: string) => {
    switch (protocol) {
      case "arweave":
        return "AR";
      case "skynet":
        return "SC";
      case "neofs":
        return "NEO";
      case "ipfs-filecoin":
        return "FIL";
      case "ipfs-pinata":
        return "USD";

      default:
    }
  };

  return (
    <div className="Wallet">
      {errorWarning ? (
        <div className="warning-container">
          <div className="warning-header">
            <FontAwesomeIcon icon={faExclamationCircle} /> {errorMessage}
          </div>
        </div>
      ) : null}
      <div className="wallet-container">
        <div className="wallet-details">
          <div className="wallet-header">
            <span>Organisation Wallet</span>
          </div>
          <div className="wallet-body">
            {!isWalletPresent && !walletLoading ? (
              <>
                <div className="wallet-subtitle">
                  Enable your wallet for <b>{selectedOrg?.profile.name}</b>
                </div>
                <div className="wallet-info">
                  <FontAwesomeIcon
                    icon={faInfoCircle}
                    style={{ marginRight: 7 }}
                  ></FontAwesomeIcon>
                  We currently support Matic Mumbai Testnet. Please add Matic Mumbai
                  chain in your metamask.
                </div>
                {!wallet ? (
                  <button
                    type="button"
                    className="primary-button"
                    disabled={userLoading}
                    onClick={connectWallet}
                  >
                    Connect
                  </button>
                ) : (
                  <div className="wallet-recharge-form">
                    <label className="wallet-recharge-form-title">
                      Wallet Details
                    </label>
                    <div className="wallet-details-container">
                      <div className="wallet-details-items">
                        <div className="wallet-details-item-title">
                          Wallet Address
                        </div>
                        <div className="wallet-details-item-desc">
                          {!walletLoader ? (
                            wallet
                          ) : (
                            <Skeleton width={300} duration={2} />
                          )}
                        </div>
                      </div>
                      <div className="wallet-details-items">
                        <div className="wallet-details-item-title">ARGO Balance</div>
                        <div className="wallet-details-item-desc">
                          {!walletLoader ? (
                            `${walletBal} $ARGO`
                          ) : (
                            <Skeleton width={150} duration={2} />
                          )}
                        </div>
                      </div>
                    </div>
                    <div className="wallet-details-button">
                      <button
                        type="button"
                        className="primary-button"
                        disabled={enableLoader}
                        onClick={enableWallet}
                      >
                        {enableLoader && (
                          <BounceLoader size={20} color={"#fff"} loading={true} />
                        )}
                        Save
                      </button>
                    </div>
                  </div>
                )}
              </>
            ) : (
              <>
                <div className="wallet-body-header">
                  <div>
                    <div className="wallet-body-title">Wallet Details</div>
                    <div className="wallet-note">
                      Note: Only owner of this wallet can increase allowance
                    </div>
                  </div>
                  <div className="button-container">
                    {!walletLoading && (
                      <>
                        <button
                          type="button"
                          className="primary-button remove-button"
                          disabled={walletLoading}
                          onClick={removeWallet}
                        >
                          {removalLoader && (
                            <BounceLoader size={20} color={"#fff"} loading={true} />
                          )}
                          Remove Wallet
                        </button>
                        <button
                          type="button"
                          className="primary-button"
                          disabled={walletLoading}
                          onClick={() => history.push("/wallet/recharge")}
                        >
                          Set Allowance
                        </button>
                      </>
                    )}
                  </div>
                </div>
                <div className="wallet-details-body">
                  <div className="wallet-details-item">
                    <label>Address</label>
                    <span>
                      {!walletLoading ? (
                        `${orgWallet}`
                      ) : (
                        <Skeleton width={150} duration={2} />
                      )}
                    </span>
                  </div>
                  <div className="wallet-details-item">
                    <label>Allowance</label>
                    <span>
                      {!walletLoading ? (
                        <div>
                          {argoAllowance === -1 ? (
                            <button
                              type="button"
                              className="primary-button"
                              disabled={walletLoader}
                              onClick={checkAllowance}
                            >
                              {walletLoader && (
                                <BounceLoader
                                  size={20}
                                  color={"#fff"}
                                  loading={true}
                                />
                              )}
                              Check Allowance
                            </button>
                          ) : (
                            `${argoAllowance} $ARGO`
                          )}
                        </div>
                      ) : (
                        <Skeleton width={150} duration={2} />
                      )}
                    </span>
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
        <div className="payment-details">
          <div className="payment-header">
            <span>Payments</span>
          </div>
          <div className="payment-body">
            <div className="table">
              <div className="thead">
                <div className="tr">
                  <div className="th">Project Name</div>
                  <div className="th">Deployment Id</div>
                  <div className="th">Build Time</div>
                  <div className="th">Upload Fee</div>
                  <div className="th">Amount</div>
                  <div className="th">Date</div>
                </div>
              </div>
              {!paymentsLoading ? (
                <div className="tbody">
                  <ReactTooltip delayShow={50} />
                  {payments.length > 0 ? (
                    payments.map((payment: IPaymentModel, index: number) => (
                      <div className="tr" key={index}>
                        <div className="td">
                          <div className="user-container">
                            <div className="user-text">
                              <span
                                className="tooltip"
                                data-tip={payment?.projectName}
                              >
                                {payment?.projectName}
                              </span>
                            </div>
                          </div>
                        </div>
                        <div className="td">
                          <div className="user-container">
                            <div className="user-text">
                              <span
                                className="tooltip"
                                data-tip={payment?.deploymentId}
                              >
                                {payment?.deploymentId}
                              </span>
                            </div>
                          </div>
                        </div>
                        <div className="td">
                          <div className="user-container">
                            <div className="user-text">{payment?.buildTime} s</div>
                          </div>
                        </div>
                        <div className="td">
                          <div className="user-container">
                            <div className="user-text">
                              <span
                                className="tooltip"
                                data-tip={`${
                                  payment?.providerFee
                                } ${showProtocolPrice(payment?.protocol)}`}
                              >
                                {payment?.providerFee.toFixed(5)}{" "}
                                {showProtocolPrice(payment?.protocol)}
                              </span>
                            </div>
                          </div>
                        </div>
                        <div className="td">
                          <div className="user-container">
                            <div className="user-text">
                              <span
                                className="tooltip"
                                data-tip={`${payment?.finalArgoFee} $${payment.token}`}
                              >
                                {payment?.finalArgoFee.toFixed(3)} ${payment.token}
                              </span>
                            </div>
                          </div>
                        </div>
                        <div className="td">
                          <div className="user-container">
                            <div className="user-text">
                              {moment(payment?.createdAt).format(
                                "DD-MM-YYYY hh:mm A",
                              )}
                            </div>
                          </div>
                        </div>
                      </div>
                    ))
                  ) : (
                    <div className="tr tr-center">No payments to show</div>
                  )}
                </div>
              ) : (
                <div className="tbody">
                  <div className="tr">
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={80} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={90} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={50} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={50} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={50} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={80} duration={2} />
                        </div>
                      </div>
                    </div>
                  </div>
                  <div className="tr">
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={80} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={90} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={50} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={50} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={50} duration={2} />
                        </div>
                      </div>
                    </div>
                    <div className="td">
                      <div className="user-container">
                        <div className="user-text">
                          <Skeleton width={80} duration={2} />
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #23
Source File: BCInfo.tsx    From devex with GNU General Public License v3.0 4 votes vote down vote up
BCInfo: React.FC = () => {

  const networkContext = useContext(NetworkContext)
  const { dataService, networkUrl } = networkContext!

  const [data, setData] = useState<BlockchainInfo | null>(null)
  const [state, setState] = useState<BCInfoState>(defaultBCInfoState)

  useEffect(() => { setData(null); setState(defaultBCInfoState) }, [networkUrl]) // Unset data on url change

  useEffect(() => {
    if (!data) return

    setState((prevState: BCInfoState) => {
      const newState: BCInfoState = { ...prevState }
      if (!prevState.startTxBlock)
        newState.startTxBlock = parseInt(data.NumTxBlocks, 10) - 1
      if (!prevState.maxTPS || prevState.maxTPS <= data.TransactionRate) {
        newState.maxTPS = data.TransactionRate
        newState.maxTPSTxBlockNum = parseInt(data.NumTxBlocks, 10) - 1
      }
      if (!prevState.maxTxnCount || prevState.maxTxnCount <= parseInt(data.NumTxnsTxEpoch, 10)) {
        newState.maxTxnCount = parseInt(data.NumTxnsTxEpoch, 10)
        newState.maxTxnCountTxBlockNum = parseInt(data.NumTxBlocks, 10) - 1
      }
      return newState
    })
  }, [data])

  // Fetch data
  useEffect(() => {
    let isCancelled = false
    if (!dataService) return

    let receivedData: BlockchainInfo
    const getData = async () => {
      try {
        receivedData = await dataService.getBlockchainInfo()
        if (!isCancelled && receivedData)
          setData(receivedData)
      } catch (e) {
        if (!isCancelled)
          console.log(e)
      }
    }
    getData()
    const getDataTimer = setInterval(async () => {
      await getData()
    }, refreshRate)
    return () => {
      isCancelled = true
      clearInterval(getDataTimer)
    }
  }, [dataService])

  return <>
    <Card className='bcstats-card'>
      <Card.Body>
        {data
          ? <Container>
            <Row className='mb-3'>
              <Col>
                <span className='subtext'>Current Tx Epoch:</span>
                <br />
                <span>{parseInt(data.NumTxBlocks).toLocaleString('en')}</span>
              </Col>
              <Col>
                <span className='subtext'>Number of Transactions:</span>
                <br />
                <span>{parseInt(data.NumTransactions).toLocaleString('en')}</span>
              </Col>
              <Col>
                <span className='subtext'>Peers:</span>
                <br />
                <span>{data.NumPeers.toLocaleString('en')}</span>
              </Col>
              <Col>
                <span className='subtext'>Sharding Structure:</span>
                <br />
                <span>[{data.ShardingStructure && data.ShardingStructure.NumPeers
                      ? data.ShardingStructure.NumPeers.toString()
                      : "no shards"}]</span>
              </Col>
            </Row>
            <Row className='mb-3'>
              <Col>
                <span className='subtext'>Current DS Epoch:</span>
                <br />
                <span>{parseInt(data.CurrentDSEpoch).toLocaleString('en')}</span>
              </Col>
              <Col>
                <span className='subtext'>DS Block Rate:</span>
                <br />
                <span>{data.DSBlockRate.toFixed(5)}</span>
              </Col>
              <Col>
                <span className='subtext'>Tx Block Rate:</span>
                <br />
                <span>{data.TxBlockRate.toFixed(5)}</span>
              </Col>
              <Col>
                <span className='subtext'>TPS:</span>
                <br />
                <span>{data.TransactionRate.toFixed(5)}</span>
              </Col>
            </Row>
            <Row>
              <Col>
                <span className='subtext'>Number of Txns in DS Epoch:</span>
                <br />
                <span>{parseInt(data.NumTxnsDSEpoch).toLocaleString('en')}</span>
              </Col>
              <Col>
                <span className='subtext'>Number of Txns in Txn Epoch:</span>
                <br />
                <span>{parseInt(data.NumTxnsTxEpoch).toLocaleString('en')}</span>
              </Col>
              <Col>
                <OverlayTrigger placement='left'
                  overlay={<Tooltip id={'tt'}>This statistic is accurate from TxBlock {state.startTxBlock}. Requires user to stay on the Home Page</Tooltip>}>
                  <FontAwesomeIcon className='info-icon' icon={faInfoCircle} />
                </OverlayTrigger>
                {' '}
                <span className='subtext'>Recent Max Observed TPS:</span>
                <br />
                <span>{state.maxTPS && state.maxTPS.toFixed(5)}</span>
                <span>
                  {' '}
                  <small className='text-nowrap subtext'>
                    (on TxBlock <QueryPreservingLink to={`/txbk/${state.maxTPSTxBlockNum}`}>{state.maxTPSTxBlockNum}</QueryPreservingLink>)
                  </small>
                </span>
              </Col>
              <Col>
                <OverlayTrigger placement='left'
                  overlay={<Tooltip id={'tt'}>This statistic is accurate from TxBlock {state.startTxBlock}. Requires user to stay on the Home Page</Tooltip>}>
                  <FontAwesomeIcon className='info-icon' icon={faInfoCircle} />
                </OverlayTrigger>
                {' '}
                <span className='subtext'>Recent Max Observed Txn Count:</span>
                <br />
                <span>{state.maxTxnCount}
                  {' '}
                  <small className='text-nowrap subtext'>
                    (on TxBlock <QueryPreservingLink to={`/txbk/${state.maxTxnCountTxBlockNum}`}>{state.maxTxnCountTxBlockNum}</QueryPreservingLink>)
                  </small>
                </span>
              </Col>
            </Row>
          </Container>
          : <Spinner animation="border" role="status" />
        }
      </Card.Body>
    </Card>
  </>
}