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

The following examples show how to use @fortawesome/free-solid-svg-icons#faChevronDown. 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: AccContractCard.tsx    From devex with GNU General Public License v3.0 6 votes vote down vote up
AccContractCard: React.FC<IProps> = ({ contract, index }) => {

  const [showContractState, setShowContractState] = useState<boolean>(false)

  return <Card className='acc-contract-card'>
    <Card.Body onClick={() => { setShowContractState((prevState) => !prevState) }} key={index}>
      <div>
        <span className='mono'>
          {`${index + 1}) `}
          {<QueryPreservingLink onClick={(e: React.MouseEvent<HTMLAnchorElement>) => { e.stopPropagation() }}
            to={`/address/${hexAddrToZilAddr(contract.address)}`}>
            {hexAddrToZilAddr(contract.address)}
          </QueryPreservingLink>}
        </span>
        <span>
          <FontAwesomeIcon icon={showContractState ? faChevronUp : faChevronDown} />
        </span>
      </div>
    </Card.Body>
    <Collapse in={showContractState}>
      <div>
        <pre className='display-block'>
          {JSON.stringify(contract.state, null, 2)}
        </pre>
      </div>
    </Collapse>
  </Card>
}
Example #2
Source File: TableHead.tsx    From solo with MIT License 6 votes vote down vote up
TableHead = <T extends object>({
  headerGroups
}: PropsWithChildren<TableHeadProps<T>>) => (
  <thead>
    {headerGroups.map(headerGroup => {
      const { key, ...rest } = headerGroup.getHeaderGroupProps();
      return (
        <tr {...rest} key={key}>
          {headerGroup.headers.map(column => {
            const { key, ...rest } = column.getHeaderProps(
              column.getSortByToggleProps()
            );
            return (
              <th {...rest} key={key}>
                <div className="display-flex flex-justify flex-align-center flex-no-wrap text-no-wrap">
                  {column.render("Header")}
                  {!column.disableSortBy && (
                    <FontAwesomeIcon
                      icon={column.isSortedDesc ? faChevronDown : faChevronUp}
                      style={{
                        visibility: column.isSorted ? "visible" : "hidden"
                      }}
                      className="margin-left-05"
                    />
                  )}
                </div>
              </th>
            );
          })}
        </tr>
      );
    })}
  </thead>
)
Example #3
Source File: ThreadPointsBar.tsx    From Full-Stack-React-TypeScript-and-Node with MIT License 5 votes vote down vote up
ThreadPointsBar: FC<ThreadPointsBarProps> = ({
  points,
  responseCount,
  threadId,
  allowUpdatePoints,
  refreshThread,
}) => {
  const { width } = useWindowDimensions();
  const { onClickDecThreadPoint, onClickIncThreadPoint } = useUpdateThreadPoint(
    refreshThread,
    threadId
  );

  if (width > 768) {
    console.log("ThreadPointsBar points", points);
    return (
      <div className="threadcard-points">
        <div className="threadcard-points-item">
          <div
            className="threadcard-points-item-btn"
            style={{ display: `${allowUpdatePoints ? "block" : "none"}` }}
          >
            <FontAwesomeIcon
              icon={faChevronUp}
              className="point-icon"
              onClick={onClickIncThreadPoint}
            />
          </div>
          {points}
          <div
            className="threadcard-points-item-btn"
            style={{ display: `${allowUpdatePoints ? "block" : "none"}` }}
          >
            <FontAwesomeIcon
              icon={faChevronDown}
              className="point-icon"
              onClick={onClickDecThreadPoint}
            />
          </div>
          <FontAwesomeIcon icon={faHeart} className="points-icon" />
        </div>
        <div className="threadcard-points-item">
          {responseCount}
          <br />
          <FontAwesomeIcon icon={faReplyAll} className="points-icon" />
        </div>
      </div>
    );
  }
  return null;
}
Example #4
Source File: ThreadPointsInline.tsx    From Full-Stack-React-TypeScript-and-Node with MIT License 5 votes vote down vote up
ThreadPointsInline: FC<ThreadPointsInlineProps> = ({
  points,
  threadId,
  threadItemId,
  allowUpdatePoints,
  refreshThread,
}) => {
  const [execUpdateThreadItemPoint] = useMutation(UpdateThreadItemPoint);
  const { onClickDecThreadPoint, onClickIncThreadPoint } = useUpdateThreadPoint(
    refreshThread,
    threadId
  );

  const onClickIncThreadItemPoint = async (
    e: React.MouseEvent<SVGSVGElement, MouseEvent>
  ) => {
    e.preventDefault();

    await execUpdateThreadItemPoint({
      variables: {
        threadItemId,
        increment: true,
      },
    });
    refreshThread && refreshThread();
  };
  const onClickDecThreadItemPoint = async (
    e: React.MouseEvent<SVGSVGElement, MouseEvent>
  ) => {
    e.preventDefault();

    await execUpdateThreadItemPoint({
      variables: {
        threadItemId,
        increment: false,
      },
    });
    refreshThread && refreshThread();
  };

  return (
    <span className="threadpointsinline-item">
      <div
        className="threadpointsinline-item-btn"
        style={{ display: `${allowUpdatePoints ? "block" : "none"}` }}
      >
        <FontAwesomeIcon
          icon={faChevronUp}
          className="point-icon"
          onClick={threadId ? onClickIncThreadPoint : onClickIncThreadItemPoint}
        />
      </div>
      {points}
      <div
        className="threadpointsinline-item-btn"
        style={{ display: `${allowUpdatePoints ? "block" : "none"}` }}
      >
        <FontAwesomeIcon
          icon={faChevronDown}
          className="point-icon"
          onClick={threadId ? onClickDecThreadPoint : onClickDecThreadItemPoint}
        />
      </div>
      <div className="threadpointsinline-item-btn">
        <FontAwesomeIcon icon={faHeart} className="points-icon" />
      </div>
    </span>
  );
}
Example #5
Source File: icons.font-awesome-solid.ts    From dayz-server-manager with MIT License 5 votes vote down vote up
fontAwesomeSolidIcons = {
    faAngleDown,
    faAngleRight,
    faArrowLeft,
    faBars,
    faBookOpen,
    faChartArea,
    faChartBar,
    faChartPie,
    faChevronDown,
    faChevronUp,
    faColumns,
    faSearch,
    faTable,
    faTachometerAlt,
    faUser,
    faExclamationTriangle,
    faSignOutAlt,
    faCalendarAlt,
    faCogs,
    faClipboardList,
    faHammer,
    faTools,
    faSync,
    faLock,
    faLockOpen,
    faTrash,
    faPlusCircle,
    faSpinner,
    faMap,
    faAnchor,
    faCity,
    faChessRook,
    faMountain,
    faCampground,
    faHome,
    faUniversity,
    faCrosshairs,
    faPlane,
    faWrench,
}
Example #6
Source File: index.tsx    From website with MIT License 5 votes vote down vote up
Hero: React.FC<HeroProps> = ({
  title,
  subtitle,
  description,
  discordButtonLabel,
  iniciativasButtonText,
  handleIniciativasClick,
}) => {
  return (
    <div className="relative py-32 mx-auto bg-white/0">
      <div className="flex items-center justify-center h-full bg-center bg-cover text-primary md:justify-around">
        <div className="z-10 w-auto text-center">
          <div className="flex flex-col items-center">
            <div className="mb-16">
              <p className="text-5xl font-black md:font-extrabold sm:text-5xl md:text-7xl xl:text-8xl font-title">
                <motion.span
                  key={title}
                  initial={{ opacity: 0, y: 20 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{
                    duration: 1,
                    type: 'spring',
                    velocity: 2,
                  }}
                  className="inline-block text-greenFec"
                >
                  {title}
                </motion.span>
              </p>
              <span
                style={{ width: 'min-content' }}
                className="text-5xl font-black md:font-extrabold sm:text-5xl md:text-7xl xl:text-8xl font-title"
              >
                {subtitle}
              </span>
              <p className="max-w-xl mx-auto mt-4 text-xl font-medium text-tertiary md:text-2xl">
                {description}
              </p>
            </div>
            <a
              target="_blank"
              href="https://discord.gg/frontendcafe"
              rel="noreferrer"
            >
              <button className="flex items-center m-auto mb-20 text-md md:px-8 md:py-3 btn btn-primary">
                {discordButtonLabel}
                <FontAwesomeIcon
                  icon={faExternalLinkAlt}
                  width="16px"
                  className="ml-3"
                />
              </button>
            </a>
            <button
              onClick={handleIniciativasClick}
              className="flex items-center self-center justify-center font-semibold text-primary"
            >
              {iniciativasButtonText}
              <FontAwesomeIcon
                icon={faChevronDown}
                width="16px"
                className="ml-3 animate-bounce"
              />
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #7
Source File: CollapsibleContent.tsx    From apps with MIT License 5 votes vote down vote up
export function ArrowToggle({ eventKey }: { eventKey: string }) {
    const currentKey = useContext(AccordionContext);
    const rotateClass = currentKey === eventKey ? "collapsible-header-rotate-arrow" : "";
    return <FontAwesomeIcon className={`collapsible-header-collapse-actions ${rotateClass}`} icon={faChevronDown} />;
}
Example #8
Source File: fa-library.ts    From eth2stats-dashboard with MIT License 5 votes vote down vote up
library.add(faBell, faChevronDown, faTimes, faArrowRight, faCheck, faPlusCircle,
    faExclamationCircle, faHeart, faCodeBranch, faMap, faList, faCircle,
    faDotCircle,
    faCheckCircle, faNetworkWired, faUsers, faCube, faSortUp, faSortDown,
    faEllipsisV, faSync, faMicrochip, faCheckDouble, faLaptopCode);
Example #9
Source File: HandshakeSubdomainGeneral.tsx    From argo-react with MIT License 4 votes vote down vote up
HandshakeSubdomainGeneral = () => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);
  const [domainName, setDomainName] = useState<string>("");
  const [deployedSite, setDeployedSite] = useState<string>("");
  const [domainLoading, setDomainLoading] = useState<boolean>(false);
  const sortedDeployments = projectLoading
    ? []
    : selectedProject?.deployments
        .filter((dep) => dep.sitePreview)
        .sort((a, b) => moment(b.createdAt).diff(moment(a.createdAt)));

  const sortedResolverSkylinks = projectLoading
    ? []
    : selectedProject?.resolverSkylinks.sort((a, b) =>
        moment(b.createdAt).diff(moment(a.createdAt)),
      );

  const addDomainDetails = () => {
    setDomainLoading(true);
    const domain = {
      orgId: selectedOrg?._id,
      projectId: selectedProject?._id,
      name: domainName,
      link: deployedSite,
      type: "handshake-subdomain",
    };
    ApiService.addDomain(domain).subscribe((result) => {
      if (result.success) {
        setDomainName("");
        setDeployedSite("");
        fetchProject(`${selectedProject?._id}`);
      } else {
        setDomainName("");
        setDeployedSite("");
      }
      setDomainLoading(false);
    });
  };

  const setTransaction = (tx: string) => {
    setDeployedSite(tx);
  };

  return (
    <div className="DomainGeneral">
      <div className="domain-general-right-container">
        <div className="domain-general-project-details">
          <div className="domain-general-project-header">
            Handshake Subdomains
            <span className="beta-badge">Beta</span>
          </div>
          <div className="domain-general-project-body">
            <div className="domain-general-project-item">
              <label className="domain-general-project-item-title">
                Configure your Handshake Subdomains
              </label>
              <label className="domain-general-project-item-subtitle">
                By default, your site is always accessible via arweave gateway based
                on transaction hash. Handshake is decentralized naming and
                certificate authority that allow you to access your site in a
                decentralized peer-to-peer root naming system.
              </label>
              <label className="domain-general-project-item-subtitle label-note">
                To resolve your Handshake Domains, connect to{" "}
                <a href="https://hdns.io" rel="noopener noreferrer" target="_blank">
                  HDNS.io
                </a>{" "}
                or use a gateway like hns.to
              </label>
              <a
                href="https://docs.spheron.network/domain-and-https/hns-domain/overview"
                rel="noopener noreferrer"
                target="_blank"
              >
                Learn more about handshake domains in our docs
                <span>
                  <FontAwesomeIcon icon={faArrowRight} />
                </span>
              </a>
              <div className="domain-general-add-domain-container">
                <input
                  type="text"
                  className="add-domain-input"
                  placeholder="mywebsite.hns"
                  value={domainName}
                  onChange={(e) => setDomainName(e.target.value)}
                />
                <div className="add-domain-select-container">
                  <select
                    className="add-domain-select"
                    value={deployedSite}
                    onChange={(e) => setTransaction(e.target.value)}
                  >
                    <option value="">Select Site</option>
                    {(sortedResolverSkylinks ? sortedResolverSkylinks : []).map(
                      (dep, index) => (
                        <option
                          value={`https://siasky.net/${dep.resolverSkylink}`}
                          key={index}
                        >
                          Resolver Skylink - {dep.name}
                        </option>
                      ),
                    )}
                    {(sortedDeployments ? sortedDeployments : []).map(
                      (dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ),
                    )}
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
                <button
                  className="add-domain-button"
                  disabled={!domainName || !deployedSite}
                  onClick={addDomainDetails}
                >
                  {domainLoading ? (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  ) : (
                    "Add"
                  )}
                </button>
              </div>
              <div className="domain-general-domain-list">
                {!projectLoading ? (
                  selectedProject?.handshakeSubdomains?.length ? (
                    selectedProject?.handshakeSubdomains?.map((subdomain, index) => (
                      <div key={index}>
                        <DomainItem
                          index={index}
                          type="filled"
                          domainId={`${subdomain._id}`}
                          domain={`${subdomain.name}`}
                          link={`${subdomain.link}`}
                          isSubdomain={true}
                          autoDns={subdomain.isLatest}
                          uuid={`${subdomain.argoKey}`}
                          ownerVerified={subdomain.verified}
                          domainType={subdomain.type}
                        />
                      </div>
                    ))
                  ) : null
                ) : (
                  <>
                    <DomainItem
                      index={1}
                      type="skeleton"
                      domainId=""
                      domain=""
                      link=""
                      uuid=""
                      isSubdomain={true}
                      autoDns={false}
                      ownerVerified={true}
                      domainType=""
                    />
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #10
Source File: index.tsx    From nouns-monorepo with GNU General Public License v3.0 4 votes vote down vote up
ProfileActivityFeed: React.FC<ProfileActivityFeedProps> = props => {
  const { nounId } = props;

  const MAX_EVENTS_SHOW_ABOVE_FOLD = 5;

  const [truncateProposals, setTruncateProposals] = useState(true);

  const { loading, error, data } = useQuery(nounVotingHistoryQuery(nounId));
  const {
    loading: proposalTimestampLoading,
    error: proposalTimestampError,
    data: proposalCreatedTimestamps,
  } = useQuery(createTimestampAllProposals());

  const nounCanVoteTimestamp = useNounCanVoteTimestamp(nounId);

  const { data: proposals } = useAllProposals();

  if (loading || !proposals || !proposals.length || proposalTimestampLoading) {
    return <></>;
  } else if (error || proposalTimestampError) {
    return (
      <div>
        <Trans>Failed to fetch Noun activity history</Trans>
      </div>
    );
  }

  const nounVotes: { [key: string]: NounVoteHistory } = data.noun.votes
    .slice(0)
    .reduce((acc: any, h: NounVoteHistory, i: number) => {
      acc[h.proposal.id] = h;
      return acc;
    }, {});

  const filteredProposals = proposals.filter((p: Proposal, id: number) => {
    return (
      parseInt(proposalCreatedTimestamps.proposals[id].createdTimestamp) >
        nounCanVoteTimestamp.toNumber() ||
      (p.id && nounVotes[p.id])
    );
  });

  return (
    <Section fullWidth={false}>
      <Col lg={{ span: 10, offset: 1 }}>
        <div className={classes.headerWrapper}>
          <h1>
            <Trans>Activity</Trans>
          </h1>
        </div>
        {filteredProposals && filteredProposals.length ? (
          <>
            <Table responsive hover className={classes.aboveTheFoldEventsTable}>
              <tbody className={classes.nounInfoPadding}>
                {filteredProposals?.length ? (
                  filteredProposals
                    .slice(0)
                    .reverse()
                    .slice(0, MAX_EVENTS_SHOW_ABOVE_FOLD)
                    .map((p: Proposal, i: number) => {
                      const vote = p.id ? nounVotes[p.id] : undefined;
                      return <NounProfileVoteRow proposal={p} vote={vote} key={i} />;
                    })
                ) : (
                  <LoadingNoun />
                )}
              </tbody>
            </Table>
            <Collapse in={!truncateProposals}>
              <div>
                <Table responsive hover>
                  <tbody className={classes.nounInfoPadding}>
                    {filteredProposals?.length ? (
                      filteredProposals
                        .slice(0)
                        .reverse()
                        .slice(MAX_EVENTS_SHOW_ABOVE_FOLD, filteredProposals.length)
                        .map((p: Proposal, i: number) => {
                          const vote = p.id ? nounVotes[p.id] : undefined;
                          return <NounProfileVoteRow proposal={p} vote={vote} key={i} />;
                        })
                    ) : (
                      <LoadingNoun />
                    )}
                  </tbody>
                </Table>
              </div>
            </Collapse>

            {filteredProposals.length <= MAX_EVENTS_SHOW_ABOVE_FOLD ? (
              <></>
            ) : (
              <>
                {truncateProposals ? (
                  <div
                    className={classes.expandCollapseCopy}
                    onClick={() => setTruncateProposals(false)}
                  >
                    <Trans>Show all {filteredProposals.length} events </Trans>{' '}
                    <FontAwesomeIcon icon={faChevronDown} />
                  </div>
                ) : (
                  <div
                    className={classes.expandCollapseCopy}
                    onClick={() => setTruncateProposals(true)}
                  >
                    <Trans>Show fewer</Trans> <FontAwesomeIcon icon={faChevronUp} />
                  </div>
                )}
              </>
            )}
          </>
        ) : (
          <div className={classes.nullStateCopy}>
            <Trans>This Noun has no activity, since it was just created. Check back soon!</Trans>
          </div>
        )}
      </Col>
    </Section>
  );
}
Example #11
Source File: ControlButton.tsx    From livekit-react with Apache License 2.0 4 votes vote down vote up
ControlButton = ({
  label,
  disabled,
  onClick,
  icon,
  className,
  menuItems,
  popoverContainerClassName,
  popoverTriggerBtnClassName,
  popoverTriggerBtnSeparatorClassName,
  onMenuItemClick,
}: ButtonProps) => {
  const [menuVisible, setMenuVisible] = useState(false);

  let classes = styles.button;
  if (className) {
    classes += ` ${className}`;
  }

  const handleMenuClick = (item: MenuItem) => {
    setMenuVisible(false);
    if (onMenuItemClick) {
      onMenuItemClick(item);
    }
  };

  let menuTrigger: ReactElement | undefined;
  let menu: ReactElement = <div />;
  if (menuItems && menuItems.length > 0) {
    classes += ` ${styles.hasDropdown}`;
    menuTrigger = (
      <button
        disabled={disabled}
        className={`${styles.button} ${popoverTriggerBtnClassName}  ${styles.dropdown}`}
        onClick={() => setMenuVisible(!menuVisible)}
      >
        <div className={`${styles.separator} ${popoverTriggerBtnSeparatorClassName}`} />
        <FontAwesomeIcon height={32} icon={faChevronDown} />
      </button>
    );

    menu = (
      <div className={`${styles.popoverMenu} ${popoverContainerClassName}`}>
        <ul className={styles.list}>
          {menuItems?.map((item, i) => {
            return (
              <li key={i} onClick={() => handleMenuClick(item)}>
                {item.label}
              </li>
            );
          })}
        </ul>
      </div>
    );
  }

  const mainContent = (
    <button
      disabled={disabled}
      className={classes}
      onClick={() => {
        setMenuVisible(false);
        if (onClick) onClick();
      }}
    >
      {icon && <FontAwesomeIcon className={styles.icon} height={32} icon={icon} />}
      {label}
    </button>
  );

  if (!menuTrigger) {
    return mainContent;
  }

  return (
    <Popover isOpen={menuVisible} positions={['top']} content={menu}>
      <div className={styles.buttonWrapper}>
        {mainContent}
        {menuTrigger}
      </div>
    </Popover>
  );
}
Example #12
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 #13
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 #14
Source File: GenerateResolverSkylink.tsx    From argo-react with MIT License 4 votes vote down vote up
GenerateResolverSkylink: React.FC<IGenerateResolverSkylinkProps> = ({
  type,
  resolver,
  close,
}) => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);

  const skylinksList = !projectLoading
    ? selectedProject
      ? selectedProject?.deployments
          .filter((deployment) => deployment?.status?.toLowerCase() === "deployed")
          .filter(
            (deployment) => deployment?.sitePreview?.indexOf("siasky.net") !== -1,
          )
          .sort((a, b) => moment(b?.createdAt).diff(moment(a?.createdAt)))
      : []
    : [];

  const [mySky, setMySky] = useState<MySky>();
  const [skynetSeed, setSkynetSeed] = useState<string>("");
  const [name, setName] = useState<string>("");
  const [resolverSkylink, setResolverSkylink] = useState<string>("");
  const [step, setStep] = useState<number>(1);
  const [userID, setUserID] = useState<string>("");
  const [useSeed, setUseSeed] = useState<boolean>(false);
  const [popupLoading, setPopupLoading] = useState<boolean>(true);
  const [skylinkLoading, setSkylinkLoading] = useState<boolean>(false);
  const [errorWarning, setErrorWarning] = useState<boolean>(false);
  const [errorMessage, setErrorMessage] = useState<string>("");
  const [latestSkylink, setLatestSkylink] = useState<string>("");
  const componentIsMounted = useRef<boolean>(true);

  useEffect(() => {
    async function initMySky() {
      setPopupLoading(true);
      try {
        const mySky = await client.loadMySky(dataDomain);
        const loggedIn = await mySky.checkLogin();
        if (componentIsMounted.current) {
          setMySky(mySky);
          if (loggedIn) {
            setUseSeed(false);
            setUserID(await mySky.userID());
            setStep(2);
            setPopupLoading(false);
          } else {
            setPopupLoading(false);
          }
        }
      } catch (e) {
        console.error(e);
        setPopupLoading(false);
      }
    }

    initMySky();

    return () => {
      handleMySkyLogout();
      componentIsMounted.current = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    if (resolver && type !== "create") {
      setName(resolver.name);
      setLatestSkylink(`https://siasky.net/${resolver.targetSkylink}/`);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [resolver]);

  const loginMySky = async () => {
    if (mySky) {
      await mySky.addPermissions(
        new Permission(
          window.location.hostname,
          dataDomain,
          PermCategory.Discoverable,
          PermType.Write,
        ),
      );
      const status = await mySky.requestLoginAccess();
      if (componentIsMounted.current) {
        if (status) {
          setUserID(await mySky.userID());
          setStep(2);
        }
      }
    }
  };

  const handleMySkyLogout = async () => {
    if (componentIsMounted.current) {
      setUserID("");
      setStep(1);
      setUseSeed(false);
    }
  };

  const generateResolverSkylink = async () => {
    try {
      setSkylinkLoading(true);
      if (!useSeed) {
        if (mySky) {
          await mySky.setDataLink(
            `${dataDomain}/${selectedProject?._id}/${name}`,
            latestSkylink.split("https://siasky.net/")[1].slice(0, -1),
          );
          const resolverSkylink = await mySky.getEntryLink(
            `${dataDomain}/${selectedProject?._id}/${name}`,
          );
          if (type === "create") {
            addResolverSkylinks(resolverSkylink);
          } else {
            editResolverSkylinks(resolverSkylink);
          }
        }
      } else {
        const { publicKey, privateKey } = genKeyPairFromSeed(skynetSeed);
        await client.db.setDataLink(
          privateKey,
          `${dataDomain}/${selectedProject?._id}/${name}`,
          latestSkylink.split("https://siasky.net/")[1].slice(0, -1),
        );
        const resolverSkylink = await client.registry.getEntryLink(
          publicKey,
          `${dataDomain}/${selectedProject?._id}/${name}`,
        );
        if (type === "create") {
          addResolverSkylinks(resolverSkylink);
        } else {
          editResolverSkylinks(resolverSkylink);
        }
      }
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log((err as Error).message);
      setErrorWarning(true);
      setErrorMessage((err as Error).message);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      setSkylinkLoading(false);
    }
  };

  const addResolverSkylinks = (resolverSkylink: string) => {
    const details = {
      orgId: selectedOrg?._id,
      projectId: selectedProject!._id,
      name,
      resolverSkylink: resolverSkylink.split("sia://")[1],
      targetSkylink: latestSkylink.split("https://siasky.net/")[1].slice(0, -1),
    };

    ApiService.addResolverSkylinks(details).subscribe(
      (result) => {
        if (result.success) {
          setName("");
          setResolverSkylink(resolverSkylink);
          setSkylinkLoading(false);
          setStep(3);
          fetchProject(`${selectedProject?._id}`);
        } else {
          setName("");
          setSkylinkLoading(false);
          setErrorWarning(true);
          setErrorMessage(result.message);
          setTimeout(() => {
            setErrorWarning(false);
            setErrorMessage("");
          }, 5000);
        }
      },
      (err) => {
        setErrorWarning(true);
        setErrorMessage(err.message);
        setTimeout(() => {
          setErrorWarning(false);
          setErrorMessage("");
        }, 5000);
      },
    );
  };

  const editResolverSkylinks = (resolverSkylink: string) => {
    const details = {
      orgId: selectedOrg?._id,
      projectId: selectedProject!._id,
      resolverSkylink: resolverSkylink.split("sia://")[1],
      targetSkylink: latestSkylink.split("https://siasky.net/")[1].slice(0, -1),
    };

    ApiService.editResolverSkylinks(resolver?._id || "", details).subscribe(
      (result) => {
        if (result.success) {
          setName("");
          setResolverSkylink(resolverSkylink);
          setSkylinkLoading(false);
          setStep(3);
          fetchProject(`${selectedProject?._id}`);
        } else {
          setSkylinkLoading(false);
          setErrorWarning(true);
          setErrorMessage(result.message);
          setTimeout(() => {
            setErrorWarning(false);
            setErrorMessage("");
          }, 5000);
        }
      },
      (err) => {
        setErrorWarning(true);
        setErrorMessage(err.message);
        setTimeout(() => {
          setErrorWarning(false);
          setErrorMessage("");
        }, 5000);
      },
    );
  };

  const deleteResolverSkylink = async () => {
    try {
      setSkylinkLoading(true);
      if (!useSeed) {
        if (mySky) {
          await mySky.setEntryData(
            `${dataDomain}/${selectedProject?._id}/${name}`,
            new Uint8Array(RAW_SKYLINK_SIZE),
          );
          removeResolverSkylink(resolver?._id || "");
        }
      } else {
        const { publicKey, privateKey } = genKeyPairFromSeed(skynetSeed);
        const reg = await client.registry.getEntry(
          publicKey,
          `${dataDomain}/${selectedProject?._id}/${name}`,
        );
        const revision = reg.entry ? reg.entry.revision + BigInt(1) : BigInt(1);
        await client.registry.setEntry(privateKey, {
          dataKey: `${dataDomain}/${selectedProject?._id}/${name}`,
          data: new Uint8Array(RAW_SKYLINK_SIZE),
          revision,
        });
        removeResolverSkylink(resolver?._id || "");
      }
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log((err as Error).message);
      setErrorWarning(true);
      setErrorMessage((err as Error).message);
      setTimeout(() => {
        setErrorWarning(false);
        setErrorMessage("");
      }, 5000);
      setSkylinkLoading(false);
    }
  };

  const removeResolverSkylink = async (id: string) => {
    ApiService.deleteResolverSkylinks(id, {
      orgId: selectedOrg?._id,
      projectId: selectedProject?._id,
    }).subscribe(
      (result) => {
        if (result.success) {
          setName("");
          setResolverSkylink(resolverSkylink);
          setSkylinkLoading(false);
          setStep(3);
          fetchProject(`${selectedProject?._id}`);
        } else {
          setSkylinkLoading(false);
          setErrorWarning(true);
          setErrorMessage(result.message);
          setTimeout(() => {
            setErrorWarning(false);
            setErrorMessage("");
          }, 5000);
        }
      },
      (err) => {
        setSkylinkLoading(false);
        setErrorWarning(true);
        setErrorMessage(err.message);
        setTimeout(() => {
          setErrorWarning(false);
          setErrorMessage("");
        }, 5000);
      },
    );
  };

  const logoutMySky = async () => {
    const mySky = await client.loadMySky(dataDomain);
    const loggedIn = await mySky.checkLogin();
    if (loggedIn) {
      await mySky.logout();
      setStep(1);
    }
  };

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

  return (
    <div className="GenerateResolverSkylink">
      <div className="close-button" onClick={(e) => close()}>
        <FontAwesomeIcon icon={faTimes}></FontAwesomeIcon>
      </div>
      <div className="modal-container">
        {!popupLoading ? (
          <div className="modal-body">
            {type === "create" && (
              <h3 className="modal-title">Generate Resolver Skylink</h3>
            )}
            {type === "update" && (
              <h3 className="modal-title">Update Resolver Skylink</h3>
            )}
            {type === "remove" && (
              <h3 className="modal-title">Remove Resolver Skylink</h3>
            )}
            {step !== 3 ? (
              <p className="modal-content">
                Resolver skylinks are a special type of skylink that enables skylinks
                whose underlying data changes. When resolver skylinks are accessed on
                Skynet, they "resolve" to other skylinks whose data is returned to
                the requester.
              </p>
            ) : null}
            {step === 1 && (
              <div className="connect-container">
                <div className="seed-phrase-container">
                  <input
                    type="text"
                    placeholder="Enter your seed phrase..."
                    className="text-input"
                    value={skynetSeed}
                    onChange={(e) => setSkynetSeed(e.target.value)}
                  />
                </div>
                <button
                  className="connect-mysky-button"
                  onClick={(e) => {
                    setUseSeed(true);
                    setStep(2);
                  }}
                  type="button"
                >
                  Login with Seed
                </button>
                <div className="or-text">Or</div>
                <div>
                  <button
                    className="connect-mysky-button"
                    onClick={loginMySky}
                    type="button"
                  >
                    Login with MySky
                  </button>
                </div>
              </div>
            )}
            {step === 2 && (
              <div className="connect-container">
                {!useSeed && (
                  <div className="user-container">
                    <div className="skylink-name-container">
                      <label>User ID</label>
                      <div className="skylink-name small-text">
                        {userID.substring(0, 51)}
                      </div>
                    </div>
                    <div className="margin-left">
                      <button
                        className="logout-mysky-button"
                        onClick={logoutMySky}
                        type="button"
                      >
                        Logout
                      </button>
                    </div>
                  </div>
                )}
                <div className="skylink-name-container">
                  <label>Name</label>
                  <div className="skylink-name">
                    {type === "create" && (
                      <input
                        type="text"
                        placeholder="eg: 'argoapp.hns' or 'my custom name'"
                        className="text-input"
                        value={name}
                        onChange={(e) => setName(e.target.value)}
                      />
                    )}
                    {(type === "update" || type === "remove") && name}
                  </div>
                </div>
                <div className="skylink-name-container">
                  <label>Skylink</label>
                  <div className="skylink-select-container">
                    <select
                      className="skylink-select"
                      value={latestSkylink}
                      disabled={type === "remove"}
                      onChange={(e) => setLatestSkylink(e.target.value)}
                    >
                      <option value="">Select Skylinks</option>
                      {(skylinksList ? skylinksList : []).map((dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ))}
                    </select>
                    <span className="select-down-icon">
                      <FontAwesomeIcon icon={faChevronDown} />
                    </span>
                  </div>
                </div>
                <div>
                  {type === "create" && (
                    <button
                      className="connect-mysky-button"
                      onClick={generateResolverSkylink}
                      disabled={!name || !latestSkylink}
                      type="button"
                    >
                      {skylinkLoading && (
                        <span className="space-between">
                          <BounceLoader size={20} color={"#fff"} loading={true} />
                        </span>
                      )}
                      Generate
                    </button>
                  )}
                  {type === "update" && (
                    <button
                      className="connect-mysky-button"
                      onClick={generateResolverSkylink}
                      disabled={!name || !latestSkylink}
                      type="button"
                    >
                      {skylinkLoading && (
                        <span className="space-between">
                          <BounceLoader size={20} color={"#fff"} loading={true} />
                        </span>
                      )}
                      Update
                    </button>
                  )}
                  {type === "remove" && (
                    <button
                      className="connect-mysky-button"
                      onClick={deleteResolverSkylink}
                      disabled={!name || !latestSkylink}
                      type="button"
                    >
                      {skylinkLoading && (
                        <span className="space-between">
                          <BounceLoader size={20} color={"#fff"} loading={true} />
                        </span>
                      )}
                      Remove
                    </button>
                  )}
                </div>
              </div>
            )}
            {step === 3 && (
              <div className="success-container">
                <div className="check-container">
                  <Lottie options={defaultOptions} height={170} />
                </div>
                <div className="header-container">Success!</div>
                <div className="text-description">
                  {type === "create" &&
                    "Resolver Skylink has been generated successfully."}
                  {type === "update" &&
                    "Resolver Skylink has been updated successfully."}
                  {type === "remove" &&
                    "Resolver Skylink has been removed successfully."}
                </div>
                <a
                  className="resolver-link"
                  href={`http://siasky.net/${resolverSkylink.split("sia://")[1]}`}
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  {resolverSkylink}
                </a>
              </div>
            )}
            {errorWarning && (
              <div className="warning-container">
                <div className="warning-header">
                  <FontAwesomeIcon icon={faExclamationCircle} /> {errorMessage}
                </div>
              </div>
            )}
          </div>
        ) : (
          <div className="loading-container">
            <GridLoader size={32} color={"#3664ae"} loading={true} />
          </div>
        )}
      </div>
    </div>
  );
}
Example #15
Source File: SubdomainGeneral.tsx    From argo-react with MIT License 4 votes vote down vote up
SubdomainGeneral = () => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);
  const [subdomainName, setSubdomainName] = useState<string>("");
  const [deployedSite, setDeployedSite] = useState<string>("");
  const [isLatest, setIsLatest] = useState<boolean>(false);
  const [domainLoading, setDomainLoading] = useState<boolean>(false);
  const sortedDeployments = projectLoading
    ? []
    : selectedProject?.deployments
        .filter((dep) => dep.sitePreview)
        .sort((a, b) => moment(b.createdAt).diff(moment(a.createdAt)));

  const sortedResolverSkylinks = projectLoading
    ? []
    : selectedProject?.resolverSkylinks.sort((a, b) =>
        moment(b.createdAt).diff(moment(a.createdAt)),
      );

  const addSubdomainDetails = () => {
    setDomainLoading(true);
    const domain = {
      orgId: selectedOrg?._id,
      projectId: selectedProject?._id,
      name: subdomainName,
      link: isLatest
        ? sortedDeployments?.length
          ? sortedDeployments[0].sitePreview
          : ""
        : deployedSite,
      isLatest,
      type: "subdomain",
    };
    ApiService.addDomain(domain).subscribe((result) => {
      if (result.success) {
        setSubdomainName("");
        setDeployedSite("");
        setIsLatest(false);
        fetchProject(`${selectedProject?._id}`);
      } else {
        setSubdomainName("");
        setDeployedSite("");
        setIsLatest(false);
      }
      setDomainLoading(false);
    });
  };

  const setTransaction = (tx: string) => {
    setDeployedSite(tx);

    if (tx === "latest") {
      setIsLatest(true);
    } else {
      setIsLatest(false);
    }
  };

  return (
    <div className="SubdomainGeneral">
      <div className="domain-general-right-container">
        <div className="domain-general-project-details">
          <div className="domain-general-project-header">Subdomains</div>
          <div className="domain-general-project-body">
            <div className="domain-general-project-item">
              <label className="domain-general-project-item-title">
                Custom Subdomains
              </label>
              <label className="domain-general-project-item-subtitle">
                By default, your site is always accessible via a arweave gateway
                based on transaction id. Custom subdomains allow you to access your
                site via one or more non-ArGo domain names.
              </label>
              {/* <a href="https://github.com/">
                Learn more about custom domains in our docs
                <span>
                  <FontAwesomeIcon icon={faArrowRight} />
                </span>
              </a> */}
              <div className="domain-general-add-domain-container">
                <input
                  type="text"
                  className="add-domain-input"
                  placeholder="subdomain.mywebsite.com"
                  value={subdomainName}
                  onChange={(e) => setSubdomainName(e.target.value)}
                />
                <div className="add-domain-select-container">
                  <select
                    className="add-domain-select"
                    value={deployedSite}
                    onChange={(e) => setTransaction(e.target.value)}
                  >
                    <option value="">Select deployment</option>
                    <option value="latest">Latest Deployed</option>
                    {(sortedResolverSkylinks ? sortedResolverSkylinks : []).map(
                      (dep, index) => (
                        <option
                          value={`https://siasky.net/${dep.resolverSkylink}`}
                          key={index}
                        >
                          Resolver Skylink - {dep.name}
                        </option>
                      ),
                    )}
                    {(sortedDeployments ? sortedDeployments : []).map(
                      (dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ),
                    )}
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
                <button
                  className="add-domain-button"
                  disabled={!subdomainName || !deployedSite}
                  onClick={addSubdomainDetails}
                >
                  {domainLoading ? (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  ) : (
                    "Add"
                  )}
                </button>
              </div>
              <div className="domain-general-domain-list">
                {!projectLoading ? (
                  selectedProject?.subdomains.length ? (
                    selectedProject?.subdomains.map((subdomain, index) => (
                      <div key={index}>
                        <DomainItem
                          index={1}
                          type="filled"
                          domainId={`${subdomain._id}`}
                          domain={`${subdomain.name}`}
                          link={`${subdomain.link}`}
                          isSubdomain={true}
                          autoDns={!!subdomain.isLatest}
                          uuid={`${subdomain.argoKey}`}
                          ownerVerified={subdomain.verified}
                          domainType={subdomain.type}
                        />
                      </div>
                    ))
                  ) : null
                ) : (
                  <>
                    <DomainItem
                      index={1}
                      type="skeleton"
                      domainId=""
                      domain=""
                      link=""
                      uuid=""
                      isSubdomain={true}
                      autoDns={false}
                      ownerVerified={true}
                      domainType=""
                    />
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #16
Source File: HandshakeDomainGeneral.tsx    From argo-react with MIT License 4 votes vote down vote up
HandshakeDomainGeneral = () => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);
  const [domainName, setDomainName] = useState<string>("");
  const [deployedSite, setDeployedSite] = useState<string>("");
  const [domainLoading, setDomainLoading] = useState<boolean>(false);
  const sortedDeployments = projectLoading
    ? []
    : selectedProject?.deployments
        .filter((dep) => dep.sitePreview)
        .sort((a, b) => moment(b.createdAt).diff(moment(a.createdAt)));
  const sortedResolverSkylinks = projectLoading
    ? []
    : selectedProject?.resolverSkylinks.sort((a, b) =>
        moment(b.createdAt).diff(moment(a.createdAt)),
      );

  const addDomainDetails = () => {
    setDomainLoading(true);
    const domain = {
      orgId: selectedOrg?._id,
      projectId: selectedProject?._id,
      name: domainName,
      link: deployedSite,
      type: "handshake-domain",
    };
    ApiService.addDomain(domain).subscribe((result) => {
      if (result.success) {
        setDomainName("");
        setDeployedSite("");
        fetchProject(`${selectedProject?._id}`);
      } else {
        setDomainName("");
        setDeployedSite("");
      }
      setDomainLoading(false);
    });
  };

  const setTransaction = (tx: string) => {
    setDeployedSite(tx);
  };

  return (
    <div className="DomainGeneral">
      <div className="domain-general-right-container">
        <div className="domain-general-project-details">
          <div className="domain-general-project-header">
            Handshake Domains
            <span className="beta-badge">Beta</span>
          </div>
          <div className="domain-general-project-body">
            <div className="domain-general-project-item">
              <label className="domain-general-project-item-title">
                Configure your Handshake Domains
              </label>
              <label className="domain-general-project-item-subtitle">
                By default, your site is always accessible via arweave gateway based
                on transaction hash. Handshake is decentralized naming and
                certificate authority that allow you to access your site in a
                decentralized peer-to-peer root naming system.
              </label>
              <label className="domain-general-project-item-subtitle label-note">
                To resolve your Handshake Domains, connect to{" "}
                <a href="https://hdns.io" rel="noopener noreferrer" target="_blank">
                  HDNS.io
                </a>{" "}
                or use a gateway like hns.to
              </label>
              <a
                href="https://docs.argoapp.live/custom-domains/handshake-domains"
                rel="noopener noreferrer"
                target="_blank"
              >
                Learn more about handshake domains in our docs
                <span>
                  <FontAwesomeIcon icon={faArrowRight} />
                </span>
              </a>
              <div className="domain-general-add-domain-container">
                <input
                  type="text"
                  className="add-domain-input"
                  placeholder="mywebsite.hns"
                  value={domainName}
                  onChange={(e) => setDomainName(e.target.value)}
                />
                <div className="add-domain-select-container">
                  <select
                    className="add-domain-select"
                    value={deployedSite}
                    onChange={(e) => setTransaction(e.target.value)}
                  >
                    <option value="">Select Site</option>
                    {(sortedResolverSkylinks ? sortedResolverSkylinks : []).map(
                      (dep, index) => (
                        <option
                          value={`https://siasky.net/${dep.resolverSkylink}`}
                          key={index}
                        >
                          Resolver Skylink - {dep.name}
                        </option>
                      ),
                    )}
                    {(sortedDeployments ? sortedDeployments : []).map(
                      (dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ),
                    )}
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
                <button
                  className="add-domain-button"
                  disabled={!domainName || !deployedSite}
                  onClick={addDomainDetails}
                >
                  {domainLoading ? (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  ) : (
                    "Add"
                  )}
                </button>
              </div>
              <div className="domain-general-domain-list">
                {!projectLoading ? (
                  selectedProject?.handshakeDomains?.length ? (
                    selectedProject?.handshakeDomains?.map((domain, index) => (
                      <div key={index}>
                        <DomainItem
                          index={index}
                          type="filled"
                          domainId={`${domain._id}`}
                          domain={`${domain.name}`}
                          link={`${domain.link}`}
                          isSubdomain={false}
                          autoDns={domain.isLatest}
                          uuid={`${domain.argoKey}`}
                          ownerVerified={domain.verified}
                          domainType={domain.type}
                        />
                      </div>
                    ))
                  ) : null
                ) : (
                  <>
                    <DomainItem
                      index={1}
                      type="skeleton"
                      domainId=""
                      domain=""
                      link=""
                      uuid=""
                      isSubdomain={false}
                      autoDns={false}
                      ownerVerified={true}
                      domainType=""
                    />
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #17
Source File: EnsDomainGeneral.tsx    From argo-react with MIT License 4 votes vote down vote up
EnsDomainGeneral = () => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);
  const [domainName, setDomainName] = useState<string>("");
  const [deployedSite, setDeployedSite] = useState<string>("");
  const [domainLoading, setDomainLoading] = useState<boolean>(false);
  const sortedDeployments = projectLoading
    ? []
    : selectedProject?.deployments
        .filter((dep) => dep.sitePreview)
        .sort((a, b) => moment(b.createdAt).diff(moment(a.createdAt)));

  const addDomainDetails = () => {
    setDomainLoading(true);
    const domain = {
      orgId: selectedOrg?._id,
      projectId: selectedProject?._id,
      name: domainName,
      link: deployedSite,
      type: "ens-domain",
    };
    ApiService.addDomain(domain).subscribe((result) => {
      if (result.success) {
        setDomainName("");
        setDeployedSite("");
        fetchProject(`${selectedProject?._id}`);
      } else {
        setDomainName("");
        setDeployedSite("");
      }
      setDomainLoading(false);
    });
  };

  const setTransaction = (tx: string) => {
    setDeployedSite(tx);
  };

  return (
    <div className="DomainGeneral">
      <div className="domain-general-right-container">
        <div className="domain-general-project-details">
          <div className="domain-general-project-header">
            ENS Domains
            <span className="beta-badge">Beta</span>
          </div>
          <div className="domain-general-project-body">
            <div className="domain-general-project-item">
              <label className="domain-general-project-item-title">
                Configure your ENS Domains/Subdomains
              </label>
              <label className="domain-general-project-item-subtitle">
                By default, your site is always accessible via arweave gateway based
                on transaction hash. ENS is an open source blockchain-based naming
                protocol.
              </label>
              <label className="domain-general-project-item-subtitle label-note">
                To resolve your ENS Domains, use a gateway like eth.link or eth.limo.
                Brave & Opera browsers have direct support for ENS Domains, so no
                gateway is required.
              </label>
              <a href="https://docs.spheron.network/">
                Learn more about ens domains from our docs
                <span>
                  <FontAwesomeIcon icon={faArrowRight} />
                </span>
              </a>
              <div className="domain-general-add-domain-container">
                <input
                  type="text"
                  className="add-domain-input"
                  placeholder="eg: mywebsite.eth or dash.mywebsite.eth"
                  value={domainName}
                  onChange={(e) => setDomainName(e.target.value)}
                />
                <div className="add-domain-select-container">
                  <select
                    className="add-domain-select"
                    value={deployedSite}
                    onChange={(e) => setTransaction(e.target.value)}
                  >
                    <option value="">Select Site</option>
                    {(sortedDeployments ? sortedDeployments : []).map(
                      (dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ),
                    )}
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
                <button
                  className="add-domain-button"
                  disabled={!domainName || !deployedSite}
                  onClick={addDomainDetails}
                >
                  {domainLoading ? (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  ) : (
                    "Add"
                  )}
                </button>
              </div>
              <div className="domain-general-domain-list">
                {!projectLoading ? (
                  selectedProject?.ensDomains?.length ? (
                    selectedProject?.ensDomains?.map((domain, index) => (
                      <div key={index}>
                        <DomainItem
                          index={index}
                          type="filled"
                          domainId={`${domain._id}`}
                          domain={`${domain.name}`}
                          link={`${domain.link}`}
                          isSubdomain={false}
                          autoDns={domain.isLatest}
                          uuid={`${domain.argoKey}`}
                          ownerVerified={domain.verified}
                          domainType={domain.type}
                        />
                      </div>
                    ))
                  ) : null
                ) : (
                  <>
                    <DomainItem
                      index={1}
                      type="skeleton"
                      domainId=""
                      domain=""
                      link=""
                      uuid=""
                      isSubdomain={false}
                      autoDns={false}
                      ownerVerified={true}
                      domainType=""
                    />
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #18
Source File: DomainGeneral.tsx    From argo-react with MIT License 4 votes vote down vote up
DomainGeneral = () => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);
  const [domainName, setDomainName] = useState<string>("");
  const [deployedSite, setDeployedSite] = useState<string>("");
  const [isLatest, setIsLatest] = useState<boolean>(false);
  const [domainLoading, setDomainLoading] = useState<boolean>(false);
  const sortedDeployments = projectLoading
    ? []
    : selectedProject?.deployments
        .filter((dep) => dep.sitePreview)
        .sort((a, b) => moment(b.createdAt).diff(moment(a.createdAt)));
  const sortedResolverSkylinks = projectLoading
    ? []
    : selectedProject?.resolverSkylinks.sort((a, b) =>
        moment(b.createdAt).diff(moment(a.createdAt)),
      );

  const addDomainDetails = () => {
    setDomainLoading(true);
    const domain = {
      orgId: selectedOrg?._id,
      projectId: selectedProject?._id,
      name: domainName,
      link: isLatest
        ? sortedDeployments?.length
          ? sortedDeployments[0].sitePreview
          : ""
        : deployedSite,
      isLatest,
      type: "domain",
    };
    ApiService.addDomain(domain).subscribe((result) => {
      if (result.success) {
        setDomainName("");
        setDeployedSite("");
        setIsLatest(false);
        fetchProject(`${selectedProject?._id}`);
      } else {
        setDomainName("");
        setDeployedSite("");
        setIsLatest(false);
      }
      setDomainLoading(false);
    });
  };

  const setTransaction = (tx: string) => {
    setDeployedSite(tx);

    if (tx === "latest") {
      setIsLatest(true);
    } else {
      setIsLatest(false);
    }
  };

  return (
    <div className="DomainGeneral">
      <div className="domain-general-right-container">
        <div className="domain-general-project-details">
          <div className="domain-general-project-header">Domains</div>
          <div className="domain-general-project-body">
            <div className="domain-general-project-item">
              <label className="domain-general-project-item-title">
                Custom Domains
              </label>
              <label className="domain-general-project-item-subtitle">
                By default, your site is always accessible via arweave gateway based
                on transaction hash. Custom domains allow you to access your site via
                one or more non-ArGo domain names.
              </label>
              {/* <a href="https://github.com/">
                Learn more about custom domains in our docs
                <span>
                  <FontAwesomeIcon icon={faArrowRight} />
                </span>
              </a> */}
              <div className="domain-general-add-domain-container">
                <input
                  type="text"
                  className="add-domain-input"
                  placeholder="mywebsite.com"
                  value={domainName}
                  onChange={(e) => setDomainName(e.target.value)}
                />
                <div className="add-domain-select-container">
                  <select
                    className="add-domain-select"
                    disabled={projectLoading}
                    value={deployedSite}
                    onChange={(e) => setTransaction(e.target.value)}
                  >
                    <option value="">Select Site</option>
                    <option value="latest">Latest Deployed</option>
                    {(sortedResolverSkylinks ? sortedResolverSkylinks : []).map(
                      (dep, index) => (
                        <option
                          value={`https://siasky.net/${dep.resolverSkylink}`}
                          key={index}
                        >
                          Resolver Skylink - {dep.name}
                        </option>
                      ),
                    )}
                    {(sortedDeployments ? sortedDeployments : []).map(
                      (dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ),
                    )}
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
                <button
                  className="add-domain-button"
                  disabled={!domainName || !deployedSite}
                  onClick={addDomainDetails}
                >
                  {domainLoading ? (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  ) : (
                    "Add"
                  )}
                </button>
              </div>
              <div className="domain-general-domain-list">
                {!projectLoading ? (
                  selectedProject?.domains.length ? (
                    selectedProject?.domains.map((domain, index) => (
                      <div key={index}>
                        <DomainItem
                          index={index}
                          type="filled"
                          domainId={`${domain._id}`}
                          domain={`${domain.name}`}
                          link={`${domain.link}`}
                          isSubdomain={false}
                          autoDns={domain.isLatest}
                          uuid={`${domain.argoKey}`}
                          ownerVerified={domain.verified}
                          domainType={domain.type}
                        />
                      </div>
                    ))
                  ) : null
                ) : (
                  <>
                    <DomainItem
                      index={1}
                      type="skeleton"
                      domainId=""
                      domain=""
                      link=""
                      uuid=""
                      isSubdomain={false}
                      autoDns={false}
                      ownerVerified={true}
                      domainType=""
                    />
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #19
Source File: DomainItem.tsx    From argo-react with MIT License 4 votes vote down vote up
DomainItem: React.FC<IDeploymentItemProps> = ({
  index,
  type,
  domainId,
  domain,
  link,
  isSubdomain,
  autoDns,
  uuid,
  ownerVerified,
  domainType,
}) => {
  const { projectLoading, selectedProject, selectedOrg } =
    useContext<IStateModel>(StateContext);
  const { fetchProject } = useContext<IActionModel>(ActionContext);

  const [editMode, setEditMode] = useState<boolean>(false);
  const [editDomainLoading, setEditDomainLoading] = useState<boolean>(false);
  const [verifyDomainLoading, setVerifyDomainLoading] = useState<boolean>(false);
  const [updateDomainLoading, setUpdateDomainLoading] = useState<boolean>(false);
  const [deleteDomainLoading, setDeleteDomainLoading] = useState<boolean>(false);
  const [editDomainName, setEditDomainName] = useState<string>(domain);
  const [isLatest, setIsLatest] = useState<boolean>(false);
  const [deployedSite, setDeployedSite] = useState<string>("");
  const sortedDeployments = projectLoading
    ? []
    : selectedProject?.deployments
        .filter((dep) => dep.sitePreview)
        .sort((a, b) => moment(b.createdAt).diff(moment(a.createdAt)));

  let separator = {
    base: "",
    sep: "",
  };

  if (link.indexOf("arweave.net") !== -1) {
    separator = {
      base: "arweave",
      sep: "https://arweave.net/",
    };
  } else if (link.indexOf("siasky.net") !== -1) {
    separator = {
      base: "sia",
      sep: "https://siasky.net/",
    };
  } else if (link.indexOf("ipfs.infura.io") !== -1) {
    separator = {
      base: "ipfs",
      sep: "https://ipfs.infura.io/ipfs/",
    };
  }

  useEffect(() => {
    if (domain) {
      setEditDomainName(domain);
    }
    if (link) {
      setDeployedSite(autoDns ? "latest" : link);
    }
  }, [domain, link, autoDns]);

  const editDomainDetails = () => {
    setEditDomainLoading(true);
    const domainBody = {
      orgId: selectedOrg?._id,
      name: editDomainName !== domain ? editDomainName : undefined,
      link:
        deployedSite === "latest"
          ? (sortedDeployments || [{ sitePreview: undefined }])[0]?.sitePreview
          : deployedSite !== link
          ? deployedSite
          : undefined,
      isLatest,
      projectId: selectedProject?._id,
      type: domainType,
    };
    ApiService.editDomain(domainId, domainBody).subscribe((result) => {
      if (result.success) {
        setEditMode(false);
        setEditDomainName("");
        setDeployedSite("");
        fetchProject(`${selectedProject?._id}`);
      } else {
        setEditMode(false);
        setEditDomainName("");
        setDeployedSite("");
      }
      setEditDomainLoading(false);
    });
  };

  const deleteDomain = () => {
    setDeleteDomainLoading(true);
    ApiService.deleteDomain(domainId).subscribe((result) => {
      if (result.success) {
        setEditDomainName("");
        setDeployedSite("");
        fetchProject(`${selectedProject?._id}`);
      } else {
        setEditDomainName("");
        setDeployedSite("");
      }
      setDeleteDomainLoading(false);
    });
  };

  const verifyDomain = () => {
    setVerifyDomainLoading(true);
    const verify = {
      id: domainId,
    };
    ApiService.verifyDomain(verify).subscribe((result) => {
      if (result.verified) {
        setEditDomainName("");
        setDeployedSite("");
        setVerifyDomainLoading(false);
        fetchProject(`${selectedProject?._id}`);
      } else {
        setEditDomainName("");
        setDeployedSite("");
        setVerifyDomainLoading(false);
      }
    });
  };

  const updateHnsDomain = () => {
    setUpdateDomainLoading(true);
    let records: string = "";
    if (!isSubdomain) {
      const records_json = [
        {
          type: "TXT",
          host: "_contenthash",
          value: `${separator.base}://${link.split(separator.sep)[1].split("/")[0]}`,
          ttl: 60,
        },
        {
          type: "ALIAS",
          host: "@",
          value: `${separator.base}.namebase.io.`,
          ttl: 3600,
        },
      ];

      records = btoa(JSON.stringify(records_json));
    } else {
      const records_json = [
        {
          type: "TXT",
          host: `_contenthash.${domain.substring(0, domain.lastIndexOf("."))}`,
          value: `${separator.base}://${link.split(separator.sep)[1].split("/")[0]}`,
          ttl: 60,
        },
        {
          type: "CNAME",
          host: domain.substring(0, domain.lastIndexOf(".")),
          value: `${separator.base}.namebase.io.`,
          ttl: 3600,
        },
      ];

      records = btoa(JSON.stringify(records_json));
    }
    const url = new URL(
      `https://namebase.io/next/domain-manager/${domain.substring(
        domain.lastIndexOf(".") + 1,
        domain.length,
      )}/records`,
    );
    const redirectUrl = window.location.href;
    const encodedRedirectUrl = encodeURIComponent(
      encodeURIComponent(redirectUrl.toString()),
    );

    url.searchParams.append("records", records);
    url.searchParams.append("redirect", encodedRedirectUrl);
    setUpdateDomainLoading(false);

    // console.log(url)
    window.location.href = url.toString();
  };

  const updateEnsDomain = async () => {
    try {
      await Web3Service.updateEnsContentHash(
        domain,
        `${separator.base}://${link.split(separator.sep)[1].split("/")[0]}`,
      );
    } catch (error) {}
  };

  const setTransaction = (tx: string) => {
    setDeployedSite(tx);

    if (tx === "latest") {
      setIsLatest(true);
    } else {
      setIsLatest(false);
    }
  };

  useEffect(() => {
    return () => {
      Web3Service.disconnect();
    };
  }, []);

  return (
    <div className="domain-item" key={index}>
      {type === "filled" &&
        (!editMode ? (
          <>
            <div className="domain-general-domain-item-header-container">
              <div className="domain-general-domain-item-header">
                <div className="domain-general-domain-item-header-left">
                  <div>
                    <a
                      href={`${
                        domainType.indexOf("handshake") !== -1 ? "http" : "https"
                      }://${domain}`}
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      {domain}
                      <span>
                        <FontAwesomeIcon icon={faExternalLinkAlt} />
                      </span>
                    </a>
                  </div>
                  {autoDns ? (
                    <div className="domain-tag-container">
                      <span className="domain-tag">Automated</span>
                    </div>
                  ) : null}
                </div>
                <div className="domain-general-domain-item-header-right">
                  <button className="edit-button" onClick={(e) => setEditMode(true)}>
                    Edit
                  </button>
                  <button
                    className="remove-button"
                    disabled={deleteDomainLoading}
                    onClick={deleteDomain}
                  >
                    <span>Remove</span>
                    {deleteDomainLoading ? (
                      <BounceLoader size={20} color={"#ee0902"} loading={true} />
                    ) : null}
                  </button>
                </div>
              </div>
            </div>
            <div className="domain-general-domain-item-body-container">
              <div className="domain-general-domain-item-body">
                <div className="domain-general-domain-item-body-item">
                  {!isSubdomain ? (
                    <>
                      <h3>Domain Configuration</h3>
                      {domainType.indexOf("handshake") === -1 &&
                      domainType.indexOf("ens") === -1 ? (
                        <p>
                          Set the following record on your DNS provider to configure
                          your domain and verify your ownership:
                        </p>
                      ) : domainType.indexOf("handshake") !== -1 ? (
                        <p>
                          Update the following record on Namebase to configure your
                          HNS domain and verify domain records:
                        </p>
                      ) : (
                        <p>
                          Update the following record on ENS Dashboard to configure
                          your ENS domain and verify domain records:
                        </p>
                      )}
                    </>
                  ) : (
                    <>
                      <h3>Subdomain Configuration</h3>
                      {domainType.indexOf("handshake") === -1 &&
                      domainType.indexOf("ens") === -1 ? (
                        <p>
                          Set the following record on your DNS provider to configure
                          your subdomain and verify your ownership:
                        </p>
                      ) : domainType.indexOf("handshake") !== -1 ? (
                        <p>
                          Update the following record on Namebase to configure your
                          HNS subdomain and verify subdomain records:
                        </p>
                      ) : (
                        <p>
                          Update the following record on ENS Dashboard to configure
                          your ENS subdomain and verify domain records:
                        </p>
                      )}
                    </>
                  )}
                  <div className="configure-domain-records-table">
                    <div className="thead">
                      <div className="tr">
                        <div
                          className={`th ${
                            domainType.indexOf("ens") !== -1 ? "more-width" : ""
                          }`}
                        >
                          Type
                        </div>
                        <div
                          className={`th ${
                            domainType.indexOf("ens") !== -1 ? "less-width" : ""
                          }`}
                        >
                          Name
                        </div>
                        <div className="th">Value</div>
                      </div>
                    </div>
                    {domainType.indexOf("handshake") === -1 &&
                    domainType.indexOf("ens") === -1 ? (
                      <div className="tbody">
                        <div className="tr">
                          <div className="td">A</div>
                          <div className="td">{domain}</div>
                          <div className="td">35.202.158.174</div>
                        </div>
                        <div className="tr">
                          <div className="td">TXT</div>
                          <div className="td">{domain}</div>
                          <div className="td">argo={uuid}</div>
                        </div>
                      </div>
                    ) : domainType.indexOf("ens") !== -1 ? (
                      <div className="tbody">
                        <div className="tr">
                          <div className="td more-width">CONTENT</div>
                          <div className="td less-width">{domain}</div>
                          <div className="td">
                            {separator.base}://
                            {link.split(separator.sep)[1].split("/")[0]}
                          </div>
                        </div>
                      </div>
                    ) : !isSubdomain ? (
                      <div className="tbody">
                        <div className="tr">
                          <div className="td">A</div>
                          <div className="td">@</div>
                          <div className="td">{separator.base}.namebase.io.</div>
                        </div>
                        <div className="tr">
                          <div className="td">TXT</div>
                          <div className="td">_contenthash</div>
                          <div className="td">
                            {separator.base}://
                            {link.split(separator.sep)[1].split("/")[0]}
                          </div>
                        </div>
                      </div>
                    ) : (
                      <div className="tbody">
                        <div className="tr">
                          <div className="td">CNAME</div>
                          <div className="td">{domain}</div>
                          <div className="td">{separator.base}.namebase.io.</div>
                        </div>
                        <div className="tr">
                          <div className="td">TXT</div>
                          <div className="td">
                            _contenthash.
                            {domain.substring(0, domain.lastIndexOf("."))}
                          </div>
                          <div className="td">
                            {separator.base}://
                            {link.split(separator.sep)[1].split("/")[0]}
                          </div>
                        </div>
                      </div>
                    )}
                  </div>
                  {!ownerVerified ? (
                    <div className="verify-domain-container">
                      <div className="verify-domain-text">
                        <span>
                          <FontAwesomeIcon icon={faTimesCircle}></FontAwesomeIcon>
                        </span>
                        <span>Update Records and Verify</span>
                      </div>
                      <div className="verify-domain-button-container">
                        {domainType.indexOf("handshake") !== -1 ? (
                          <button
                            className="update-domain-button"
                            disabled={updateDomainLoading}
                            onClick={updateHnsDomain}
                          >
                            Update
                            {updateDomainLoading ? (
                              <BounceLoader
                                size={20}
                                color={"#fff"}
                                loading={true}
                              />
                            ) : null}
                          </button>
                        ) : null}
                        {domainType.indexOf("ens") !== -1 ? (
                          <button
                            className="update-domain-button"
                            disabled={updateDomainLoading}
                            onClick={updateEnsDomain}
                          >
                            Update
                            {updateDomainLoading ? (
                              <BounceLoader
                                size={20}
                                color={"#fff"}
                                loading={true}
                              />
                            ) : null}
                          </button>
                        ) : null}
                        <button
                          className="verify-domain-button"
                          disabled={verifyDomainLoading}
                          onClick={verifyDomain}
                        >
                          Verify
                          {verifyDomainLoading ? (
                            <BounceLoader size={20} color={"#fff"} loading={true} />
                          ) : null}
                        </button>
                      </div>
                    </div>
                  ) : null}
                </div>
              </div>
            </div>
          </>
        ) : (
          <div className="domain-general-domain-item-edit">
            <div className="domain-general-domain-item-edit-container">
              <div className="domain-general-domain-item-edit-form">
                <span className="form-label">Domain</span>
                <input
                  type="text"
                  className="form-input"
                  placeholder="mywebsite.com"
                  value={editDomainName}
                  onChange={(e) => setEditDomainName(e.target.value)}
                />
              </div>
              <div className="domain-general-domain-item-edit-form">
                <span className="form-label">Site</span>
                <div className="form-select-container">
                  <select
                    className="form-select"
                    value={deployedSite}
                    onChange={(e) => setTransaction(e.target.value)}
                  >
                    <option value="">Select Site</option>
                    {domainType.indexOf("handshake") === -1 &&
                      domainType.indexOf("ens") === -1 && (
                        <option value="latest">Latest Deployed</option>
                      )}
                    {(sortedDeployments ? sortedDeployments : []).map(
                      (dep, index) => (
                        <option value={dep.sitePreview} key={index}>
                          {dep.sitePreview}
                        </option>
                      ),
                    )}
                  </select>
                  <span className="select-down-icon">
                    <FontAwesomeIcon icon={faChevronDown} />
                  </span>
                </div>
              </div>
              <div className="domain-general-domain-item-edit-button">
                <button
                  className="save-button"
                  disabled={!editDomainName || !deployedSite}
                  onClick={editDomainDetails}
                >
                  {editDomainLoading && (
                    <BounceLoader size={20} color={"#fff"} loading={true} />
                  )}
                  Save
                </button>
                <button
                  className="cancel-button"
                  onClick={(e) => setEditMode(false)}
                >
                  Cancel
                </button>
              </div>
            </div>
          </div>
        ))}
      {type === "skeleton" && (
        <>
          <div className="domain-general-domain-item-header-container">
            <div className="domain-general-domain-item-header">
              <div className="domain-general-domain-item-header-left">
                <Skeleton width={300} duration={2} />
              </div>
              <div className="domain-general-domain-item-header-right">
                <Skeleton width={120} duration={2} />
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
}
Example #20
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 #21
Source File: FolderBrowse.tsx    From frontend.ro with MIT License 4 votes vote down vote up
render() {
    const {
      folderKey,
      folderStructure,
      ctxMenuKey,
      readOnly,
      renamedAsset,
      selectFile,
      openMenu,
      enterEditMode,
      onRename,
      saveAsset,
      selectedFileKey,
      feedbacks,
    } = this.props;
    let { folders, files, name } = folderStructure.getFolder(folderKey).folder;
    const { isOpen } = this.state;

    files = files.map((f) => ({ ...f, icon: FileIcons.getIcon(f.name) }));

    return (
      <div className={`
        ${styles['folder-browse']}
        ${isOpen ? styles['is--open'] : ''}
        ${this.containsFileWithFeedback() ? styles['has--file-with-feedback'] : ''}`}
      >
        <div
          onClick={() => this.toggle()}
          onContextMenu={this.onContextMenu}
          data-key={folderKey}
          className={`
            ${styles['folder-button']} 
            btn--transparent 
            ellipsis-overflow
            ${renamedAsset.key === folderKey ? 'is-being-renamed' : ''}
            ${folderKey === ctxMenuKey ? 'is--ctx-selected' : ''}`}
        >
          <form noValidate onSubmit={saveAsset} className="d-flex align-items-center">
            <>
              {isOpen
                ? <FontAwesomeIcon style={{ marginRight: '0.5em' }} icon={faChevronDown} width="18" height="18" />
                : <FontAwesomeIcon style={{ marginRight: '0.5em' }} icon={faChevronRight} width="18" height="18" /> }
            </>
            <input
              className={styles['folder-input']}
              type="text"
              value={renamedAsset.key === folderKey ? renamedAsset.name : name}
              disabled={renamedAsset.key !== folderKey}
              onChange={onRename}
              // eslint-disable-next-line jsx-a11y/no-autofocus
              autoFocus={renamedAsset.key === folderKey}
              onBlur={saveAsset}
            />
            {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
            <Button hidden disabled={renamedAsset.key !== folderKey} type="submit" />
          </form>
        </div>
        {folders.map((folder) => (
          <FolderBrowse
            key={folder.key}
            folderKey={folder.key}
            folderStructure={folderStructure}
            feedbacks={feedbacks}
            readOnly={readOnly}
            selectFile={selectFile}
            selectedFileKey={selectedFileKey}
            renamedAsset={renamedAsset}
            ctxMenuKey={ctxMenuKey}
            openMenu={openMenu}
            enterEditMode={enterEditMode}
            onRename={onRename}
            saveAsset={saveAsset}
          />
        ))}
        <FilesList
          readOnly={readOnly}
          files={files}
          feedbacks={feedbacks}
          ctxMenuKey={ctxMenuKey}
          selectFile={selectFile}
          selectedFileKey={selectedFileKey}
          enterEditMode={enterEditMode}
          openMenu={openMenu}
          renamedAsset={renamedAsset}
          onRename={onRename}
          saveAsset={saveAsset}
        />
      </div>
    );
  }