crane-cloud/frontend

View on GitHub
src/pages/AdminAppDetail/index.js

Summary

Maintainability
A
3 hrs
Test Coverage
F
0%
import React, { useState, useEffect, useCallback } from "react";
import { useParams } from "react-router-dom";
import { handleGetRequest } from "../../apis/apis.js";
import InformationBar from "../../components/InformationBar";
import PrimaryButton from "../../components/PrimaryButton";
import { DisplayDateTime } from "../../helpers/dateConstants";
import Header from "../../components/Header";
import styles from "./AdminAppDetail.module.css";
import { handlePostRequestWithOutDataObject } from "../../apis/apis.js";
import { useDispatch, useSelector } from "react-redux";
import getAppRevisions, {
  clearFetchAppRevisionsState,
} from "../../redux/actions/getRevisions.js";
import Spinner from "../../components/Spinner/index.js";

const AdminAppDetail = () => {
  const dispatch = useDispatch();
  const { appID } = useParams();
  const [appDetail, setAppDetail] = useState({});

  const { revisions, isFetching } = useSelector(
    (state) => state.appRevisionsReducer
  );

  useEffect(() => {
    getAppDetails(appID);
  }, [appID]);

  const applicationRevisions = useCallback(
    () => dispatch(getAppRevisions(appID)),
    [dispatch, appID]
  );

  useEffect(() => {
    applicationRevisions();
    return () => {
      dispatch(clearFetchAppRevisionsState());
    };
  }, [applicationRevisions, dispatch]);

  useEffect(() => {
    dispatch(getAppRevisions(appID));
    return () => {
      dispatch(clearFetchAppRevisionsState());
    };
  }, [appID, dispatch]);

  const getAppDetails = async (appID) => {
    try {
      const response = await handleGetRequest(`/apps/${appID}`);
      if (response.data.status === "success") {
        setAppDetail(response.data.data);
      } else {
        throw new Error("No App detail found");
      }
    } catch (error) {
      throw new Error("Failed to fetch app detail, please try again");
    }
  };

  const handleEnableButtonClick = () => {
    try {
      if (appDetail?.apps?.disabled) {
        handlePostRequestWithOutDataObject(appID, `/apps/${appID}/enable`)
          .then(() => {
            window.location.reload();
          })
          .catch((error) => {
            console.error("API call error:", error);
            // setError(error);
            window.location.reload();
          });
      } else {
        handlePostRequestWithOutDataObject(appID, `/apps/${appID}/disable`)
          .then(() => {
            window.location.reload();
          })
          .catch((error) => {
            console.error("API call error:", error);
            // setError(error);
            window.location.reload();
          });
      }
    } catch (error) {
      console.error("API call error:", error);
    }
  };

  return (
    <div className={styles.Page}>
      <div className="TopRow">
        <Header />
        <InformationBar header="App Detail" showBackBtn />
      </div>

      <div className="TitleContainer">
        <div className="TitleArea">
          <div className="SectionTitle" style={{ paddingTop: "1rem" }}>
            <b>Application Detail</b>{" "}
            <PrimaryButton
              onClick={handleEnableButtonClick}
              color={
                appDetail?.apps?.disabled ? "primary-outline" : "red-outline"
              }
            >
              {appDetail?.apps?.disabled ? "Enable" : "Disable"}
            </PrimaryButton>
          </div>
        </div>
      </div>

      <div className={styles.DetailContainer}>
        <div className={styles.DetailFirst}>
          <div className={styles.DetailFirstTitle}>App Information</div>
          <div className={styles.DetailFirstDetail}>
            {isFetching ? (
              <div className={styles.SpinnerArea}>
                <Spinner size={"big"} />
              </div>
            ) : (
              <>
                <div class="list-group">
                  <div className={styles.listItem}>
                    <strong>Name:</strong> {appDetail?.apps?.name}
                  </div>
                  <div className={styles.listItem}>
                    <strong>ID:</strong> {appDetail?.apps?.id}
                  </div>
                  <div className={styles.listItem}>
                    <strong>URL:</strong>{" "}
                    <a
                      href={appDetail?.apps?.url}
                      target="_blank"
                      rel="noreferrer"
                    >
                      {appDetail?.apps?.url}
                    </a>
                  </div>
                  <div className={styles.listItem}>
                    <strong>Port:</strong> {appDetail?.apps?.port}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Custom Domain:</strong>{" "}
                    {appDetail?.apps?.has_custom_domain === "true"
                      ? "Yes"
                      : "No"}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Date Created:</strong>{" "}
                    {DisplayDateTime(new Date(appDetail?.apps?.date_created))}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Command:</strong>{" "}
                    {appDetail?.apps?.command
                      ? appDetail?.apps?.command
                      : "None"}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Private Image:</strong>{" "}
                    {appDetail?.apps?.private_image === "true" ? "Yes" : "No"}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Age:</strong> {appDetail?.apps?.age}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Alias:</strong> {appDetail?.apps?.alias}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Image:</strong> {appDetail?.apps?.image}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Replicas:</strong> {appDetail?.apps?.replicas}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Running Status:</strong>{" "}
                    {appDetail?.apps?.app_running_status}
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
        <div className={styles.DetailSecond}>
          <div className={styles.DetailFirstTitle}>Revision History</div>
          <div className={styles.DetailSecondColumn}>
            <div className={styles.Revision}>Current Revision</div>
            {isFetching ? (
              <div className={styles.SpinnerArea}>
                <Spinner size={"small"} />
              </div>
            ) : (
              <>
                <div class="list-group">
                  <div className={styles.listItem}>
                    <strong>Revision No:</strong>{" "}
                    {revisions?.length > 0 ? revisions[0].revision : "N/A"}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Revision ID:</strong>{" "}
                    {revisions?.length > 0 ? revisions[0].revision_id : "N/A"}
                  </div>
                  <div className={styles.listItem}>
                    <strong>Created:</strong>{" "}
                    {revisions?.length > 0
                      ? DisplayDateTime(new Date(revisions[0].created_at))
                      : "N/A"}
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
      </div>
      <div className="FooterRow">
        <p>
          Copyright {new Date().getFullYear()} Crane Cloud. All Rights Reserved.
        </p>
      </div>
    </div>
  );
};

export default AdminAppDetail;