crane-cloud/frontend

View on GitHub
src/pages/ClusterPage/index.jsx

Summary

Maintainability
A
2 hrs
Test Coverage
F
51%
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import InformationBar from "../../components/InformationBar";
import PrimaryButton from "../../components/PrimaryButton";
import Spinner from "../../components/Spinner";
import BlackInputText from "../../components/BlackInputText";
import Modal from "../../components/Modal";
import ClustersList from "../../components/ClustersList";
import Header from "../../components/Header";
import addCluster, {
  clearAddClusterState,
} from "../../redux/actions/addCluster";
import Feedback from "../../components/Feedback";
import styles from "./ClusterPage.module.css";
import getClustersList from "../../redux/actions/clusters";
import { handleGetRequest } from "../../apis/apis.js";

const ClusterPage = ({
  creatingCluster,
  isAdded,
  isFailed,
  addCluster,
  message,
  clearAddClusterState,
  clusters,
}) => {
  const [name, setName] = useState("");
  const [host, setHost] = useState("");
  const [token, setToken] = useState("");
  const [openModal, setOpenModal] = useState(false);
  const [error, setError] = useState("");
  const [description, setDescription] = useState("");
  const [prometheus_url, setPrometheus_url] = useState("");
  const [summary, setSummary] = useState({});
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    getClustersList();
    getAllMetrics();
  }, []);

  const getAllMetrics = async () => {
    setLoading(true);
    try {
      const response = await handleGetRequest("/system_summary");
      if (response.data.status === "success") {
        setSummary(response.data.data);
        setLoading(false);
      }
    } catch (error) {
      setError("Failed to fetch summary metrics, please try again");
    } finally {
      setLoading(false);
    }
  };

  const showForm = () => setOpenModal(true);

  const hideForm = () => {
    clearAddClusterState();
    setOpenModal(false);
  };

  const handleSubmit = () => {
    // input validation
    if (!host || !name || !token || !description || !prometheus_url) {
      setError("Please provide all the information");
    } else {
      const cluster = {
        host,
        name,
        token,
        description,
        prometheus_url,
      };

      addCluster(cluster);
    }
  };

  return (
    <div className={styles.Page}>
      <div className="TopRow">
        <Header />
        <InformationBar
          header="Overview"
          showBtn
          buttontext="+ New Cluster"
          btnAction={showForm}
          adminRoute={true}
          adminProjects={true}
        />
      </div>

      <div className="TitleContainer">
        <div className="TitleArea">
          <div className="SectionTitle" style={{ paddingTop: "1rem" }}>
            <b>Summary</b>
          </div>
        </div>
      </div>

      {summary && Object.keys(summary).length > 0 ? (
        <div className={styles.OtherCards}>
          <Link to="/accounts" className={styles.ResourceCard}>
            <div className={styles.columnCardSection}>
              <div className={styles.CardHeader}>Users</div>
              <div className={styles.ResourceDigit}>
                {summary?.Users?.total_count}
              </div>
            </div>
            <div className={styles.rowCardSection}>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Verified</div>
                <div className={styles.rowResourceDigit}>
                  {summary?.Users?.verified}
                </div>
              </div>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Unverified</div>
                <div
                  className={`${styles.rowResourceDigit} ${styles.rightTextAlign}`}
                >
                  {parseInt(
                    parseInt(summary?.Users?.total_count) -
                      parseInt(summary?.Users?.verified)
                  )}
                </div>
              </div>
            </div>
          </Link>
          <Link to="/projects-overview" className={styles.ResourceCard}>
            <div className={styles.columnCardSection}>
              <div className={styles.CardHeader}>Projects</div>
              <div className={styles.ResourceDigit}>
                {summary?.Projects?.total_count}
              </div>
            </div>
            <div className={styles.rowCardSection}>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Active</div>
                <div className={styles.rowResourceDigit}>
                  {summary?.Projects?.total_count - summary?.Projects?.disabled}
                </div>
              </div>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Disabled</div>
                <div
                  className={`${styles.rowResourceDigit} ${styles.rightTextAlign}`}
                >
                  {summary?.Projects?.disabled}
                </div>
              </div>
            </div>
          </Link>
          <Link to="/databases" className={styles.ResourceCard}>
            <div className={styles.columnCardSection}>
              <div className={styles.CardHeader}>Databases</div>
              <div className={styles.ResourceDigit}>
                {summary?.Databases?.total_count}
              </div>
            </div>
            <div className={styles.rowCardSection}>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>MySql</div>
                <div className={styles.rowResourceDigit}>
                  {summary?.Databases?.mysql}
                </div>
              </div>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Postgresql</div>
                <div
                  className={`${styles.rowResourceDigit} ${styles.rightTextAlign}`}
                >
                  {summary?.Databases?.postgres}
                </div>
              </div>
            </div>
          </Link>
          <Link to="/apps" className={styles.ResourceCard}>
            <div className={styles.columnCardSection}>
              <div className={styles.CardHeader}>Apps</div>
              <div className={styles.ResourceDigit}>
                {summary ? summary?.Apps?.total_count : 0}
              </div>
            </div>
            <div className={styles.rowCardSection}>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Up</div>
                <div className={styles.rowResourceDigit}>
                  {summary?.Apps?.total_count}
                </div>
              </div>
              <div className={styles.columnCardSection}>
                <div className={styles.innerCardHeader}>Down</div>
                <div
                  className={`${styles.rowResourceDigit} ${styles.rightTextAlign}`}
                >
                  {0}
                </div>
              </div>
            </div>
          </Link>
        </div>
      ) : loading ? (
        <div className={styles.LoadingArea}>
          <Spinner size="big" />
        </div>
      ) : (
        <div className="NoResourcesMessage">{error}</div>
      )}

      <div className="TitleContainer">
        <div className="TitleArea">
          <div className="SectionTitle" style={{ paddingTop: "2rem" }}>
            <b>Select Infrastructure ({clusters?.metadata?.cluster_count})</b>
          </div>
        </div>
      </div>

      <div className="MainRow">
        <ClustersList newClusterAdded={isAdded} />
      </div>

      <div style={{ paddingLeft: "1.8rem" }}>
        <p>
          Copyright {new Date().getFullYear()} Crane Cloud. All Rights Reserved.
        </p>
      </div>

      <Modal showModal={openModal} onClickAway={hideForm}>
        <div className="ModalForm">
          <div className="ModalFormHeading">
            <h2>Add a cluster</h2>
          </div>
          <div className="ModalFormInputs">
            <div className="ModalFormInputsBasic">
              <BlackInputText
                required
                placeholder="Host"
                name="host"
                value={host}
                onChange={(e) => setHost(e.target.value)}
              />
              <BlackInputText
                required
                placeholder="Token"
                name="token"
                value={token}
                onChange={(e) => setToken(e.target.value)}
              />
              <BlackInputText
                required
                placeholder="Name"
                name="name"
                value={name}
                onChange={(e) => setName(e.target.value)}
              />
              <BlackInputText
                required
                placeholder="Prometheus Url"
                name="prometheus_url"
                value={prometheus_url}
                onChange={(e) => setPrometheus_url(e.target.value)}
              />
              <BlackInputText
                required
                placeholder="Description"
                name="description"
                value={description}
                onChange={(e) => setDescription(e.target.value)}
              />

              {error && <Feedback type="error" message={error} />}

              <div className="ModalFormButtons AddAddButtons">
                <PrimaryButton className="CancelBtn" onClick={hideForm}>
                  Cancel
                </PrimaryButton>
                <PrimaryButton onClick={handleSubmit}>
                  {creatingCluster ? <Spinner /> : "add"}
                </PrimaryButton>
              </div>

              {(isFailed || isAdded) && (
                <Feedback
                  type={isAdded ? "success" : "error"}
                  message={message}
                />
              )}
            </div>
          </div>
        </div>
      </Modal>
    </div>
  );
};

export const mapStateToProps = (state) => {
  const { creatingCluster, isAdded, isFailed, errorOccured, message } =
    state.addClusterReducer;
  const { user } = state.user;
  const { clusters } = state.clustersReducer;

  return {
    user,
    creatingCluster,
    isAdded,
    isFailed,
    errorOccured,
    message,
    clusters,
  };
};

const mapDispatchToProps = {
  addCluster,
  clearAddClusterState,
  getClustersList,
};

export default connect(mapStateToProps, mapDispatchToProps)(ClusterPage);