crane-cloud/frontend

View on GitHub
src/components/AdminProjectDetails/index.js

Summary

Maintainability
B
6 hrs
Test Coverage
F
0%
import React, { useState, useEffect, useCallback } from "react";
import { Link, useParams } from "react-router-dom";
import InformationBar from "../InformationBar";
import Header from "../Header";
import SideNav from "../SideNav";
import styles from "./AdminProjectDetails.module.css";
import PrimaryButton from "../PrimaryButton";
import {
  handleGetRequest,
  handlePostRequestWithOutDataObject,
} from "../../apis/apis.js";
import Avatar from "../Avatar";
// import ActivityLogs from "../ActivityLogs";
import Spinner from "../Spinner";
import { dateInWords } from "../../helpers/dateConstants";
import Modal from "../Modal";
import Feedback from "../Feedback";
import NewResourceCard from "../NewResourceCard";
import { useLocation } from "react-router-dom";
import AppFooter from "../appFooter";
import SettingsActionRow from "../SettingsActionRow/index.jsx";

const AdminProjectDetails = () => {
  const clusterID = localStorage.getItem("clusterID");
  const clusterName = localStorage.getItem("clusterName");
  const location = useLocation();
  const isOverviewProject = location.pathname.includes("/projects-overview");

  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(false);
  const [details, setDetails] = useState({});

  const [disablingProject, setDisablingProject] = useState(false);
  const [disableProjectError, setDisableProjectError] = useState("");
  const [openDisableProjectModel, setOpenDisableProjectModel] = useState(false);

  //need to get all current project details
  const { projectID } = useParams();

  const projectCount = {
    apps: details?.apps_count,
    databases: details?.databases?.length,
    members: details?.users?.length,
  };

  const fetchProjectDetails = useCallback(() => {
    handleGetRequest(`/projects/${projectID}`)
      .then((response) => {
        setDetails(response.data.data.project);
      })
      .catch((error) => {
        setError("Failed to fetch project detail please refresh");
      })
      .finally(() => {
        setLoading(false);
      });
  }, [projectID]);

  useEffect(() => {
    fetchProjectDetails();
  }, [fetchProjectDetails]);

  const handleDisableProject = (e, disabled) => {
    e.preventDefault();
    setDisablingProject(true);
    let apiEndpoint;
    if (disabled) {
      apiEndpoint = `/projects/${projectID}/enable`;
    } else {
      apiEndpoint = `/projects/${projectID}/disable`;
    }
    handlePostRequestWithOutDataObject({}, apiEndpoint)
      .then(() => {
        //reset to projects page to re populate redux
        window.location.href = `/projects/${projectID}/details`;
      })
      .catch((error) => {
        setDisableProjectError("Process failed, please try again.");
        setDisablingProject(false);
      });
  };

  const handleEnableButtonClick = () => {
    // let { projectDetails } = this.state;
    // const { projectID } = this.props.match.params;
    console.log(details);

    try {
      if (details.disabled) {
        handlePostRequestWithOutDataObject({}, `/projects/${projectID}/enable`)
          .then(() => {
            window.location.reload();
          })
          .catch((error) => {
            setError(error);
          });
      } else {
        handlePostRequestWithOutDataObject({}, `/projects/${projectID}/disable`)
          .then(() => {
            window.location.reload();
          })
          .catch((error) => {
            setError(error);
          });
      }
    } catch (error) {
      console.error("API call error:", error);
    }
  };

  return (
    <div className="MainPage">
      <div className={styles.TopBarSection}>
        <Header />
      </div>
      <div className={isOverviewProject ? "Mainsection" : styles.MainSection}>
        {!isOverviewProject && (
          <div className={styles.SideBarSection}>
            <SideNav clusterName={clusterName} clusterId={clusterID} />
          </div>
        )}
        <div className={styles.MainContentSection}>
          <div className="InformationBarSection">
            <InformationBar
              header={
                <span>
                  <Link
                    className="breadcrumb"
                    to={
                      isOverviewProject
                        ? `/projects-overview`
                        : `/clusters/${clusterID}/projects-listing`
                    }
                  >
                    Projects
                  </Link>
                  / {details?.name}
                </span>
              }
              showBtn={false}
              showBackBtn
            />
          </div>
          <div
            className={
              isOverviewProject
                ? "LeftAlignContainer"
                : styles.CustomSmallContainer
            }
          >
            {loading || Object.keys(details).length === 0 ? (
              <div className={styles.ResourceSpinnerWrapper}>
                <Spinner size="big" />
              </div>
            ) : Object.keys(details).length > 0 ? (
              <>
                <div>
                  {/* Project information */}
                  <section className={styles.DetailsSection}>
                    <div className="SectionTitle">Project Information</div>
                    <div className={styles.ProjectInstructions}>
                      <div className={styles.ProjectInfo}>
                        <div className={styles.ProjectInfoHeader}>
                          <div className={styles.AvatarName}>
                            <Avatar
                              name={details?.name}
                              className={styles.avatar_author}
                            />
                          </div>
                          <div>
                            <div className={styles.flex_name_status}>
                              <div className={styles.ProjectName}>
                                {details?.name}
                              </div>
                              <div className={styles.ProjectStatus}>
                                {details?.disabled ? (
                                  <div
                                    className={`${styles.font_status} ${styles.disabled}`}
                                  >
                                    Disabled
                                  </div>
                                ) : (
                                  <div
                                    className={`${styles.font_status} ${styles.active}`}
                                  >
                                    Active
                                  </div>
                                )}
                              </div>
                            </div>
                            <div className={styles.ProjectDescription}>
                              {details?.description}
                            </div>
                          </div>
                        </div>
                        <div className={styles.ProjectInfoBody}>
                          <div className={styles.ProjectInfoOwner}>
                            <div className={styles.project_details_type}>
                              Project Type:{" "}
                              <span className={styles.boldStyle}>
                                {details?.project_type}
                              </span>
                            </div>
                            <div className={styles.line_between}></div>
                            <div className={styles.project_details_type}>
                              Organization:{" "}
                              <span className={styles.boldStyle}>
                                {details?.organisation}
                              </span>
                            </div>
                            <div className={styles.line_between}></div>
                            <div className={styles.project_details_type}>
                              Created:{" "}
                              <span className={styles.boldStyle}>
                                {dateInWords(details?.date_created)}
                              </span>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </section>
                  {/* Project Metrics */}
                  <section className={styles.DetailsSection}>
                    <div className="SectionTitle">Project Metrics</div>
                    <div className={styles.flex_metrics}>
                      {Object.keys(projectCount).map((key, index) => (
                        <NewResourceCard
                          key={index}
                          title={key}
                          count={projectCount[key]}
                        />
                      ))}
                    </div>
                  </section>
                  {/* Membership */}
                  <section className={styles.DetailsSection}>
                    <div className="SectionTitle">Membership</div>
                    <div className={styles.ProjectInstructions}>
                      <>
                        <div className={styles.MembershipHeader}>
                          <div className={styles.MemberSection}>
                            <div className={styles.SettingsSectionInfoHeader}>
                              {details?.users?.length === 1 ? (
                                <div className="SectionSubTitle">
                                  Project has 1 Team Member
                                </div>
                              ) : (
                                <div>
                                  Project has {details?.users?.length} Team
                                  Members
                                </div>
                              )}
                            </div>
                            <div className="SubText">
                              Members that have accounts on crane cloud can
                              perform different operations on the project
                              depending on their permission.
                            </div>
                          </div>
                        </div>
                        <div className={styles.MemberTable}>
                          <div className={styles.MemberBody}>
                            {details?.users?.map((entry, index) => (
                              <div
                                className={styles.MemberTableRow}
                                key={index}
                              >
                                <div className={styles.MemberInfo}>
                                  <Avatar
                                    name={entry.user.name}
                                    className={styles.MemberAvatar}
                                  />
                                  <div className={styles.MemberNameEmail}>
                                    <div className={styles.UserHeader}>
                                      {entry.user.name}
                                    </div>
                                    <div className={styles.Wrap}>
                                      {entry.user.email}
                                    </div>
                                  </div>
                                </div>
                                {entry.role !== "RolesList.owner" &&
                                  entry.accepted_collaboration_invite ===
                                    false && (
                                    <div className="SubText">
                                      Invite pending.
                                    </div>
                                  )}
                                <div className={styles.MemberOptions}>
                                  <div className={styles.MemberRole}>
                                    <span>Role:</span>
                                    {entry.role.split(".").pop()}
                                  </div>
                                </div>
                              </div>
                            ))}
                          </div>
                        </div>
                      </>
                    </div>
                  </section>

                  <div className="AdminDBSections">
                    <div className="SectionTitle">Manage Project</div>
                    <div className="ProjectInstructions">
                      <div className="MemberBody">
                        <SettingsActionRow
                          title={`${
                            details?.disabled ? "Enable" : "Disable"
                          } project`}
                          content={
                            details?.disabled
                              ? "Enable and make all project resources accessible (apps, and databases) to the user."
                              : "Disable and make all project resources inaccessible (apps, and databases) to the user."
                          }
                          buttonLabel={details?.disabled ? "Enable" : "Disable"}
                          buttonColor={details?.disabled ? "primary" : "red"}
                          onButtonClick={handleEnableButtonClick}
                        />
                      </div>
                    </div>
                  </div>
                </div>
              </>
            ) : (
              <div className="NoResourcesMessage">{error}</div>
            )}
          </div>
          <AppFooter />
        </div>
      </div>
      {openDisableProjectModel && (
        <div className={styles.ProjectDeleteModel}>
          <Modal
            showModal={openDisableProjectModel}
            onClickAway={() => {
              setOpenDisableProjectModel(false);
            }}
          >
            <div className={styles.DeleteProjectModel}>
              <div className={styles.DeleteProjectModalUpperSection}>
                <div className={styles.WarningContainer}>
                  <div className={styles.DeleteDescription}>
                    Are you sure you want to{" "}
                    {details?.admin_disabled ? "enable" : "disable"}&nbsp;
                    <span>{details?.name}</span>
                    &nbsp;?
                  </div>
                  <div className={styles.DisableSubDescription}>
                    This will {details?.disabled ? "enable" : "disable"} billing
                    and external access of resources in this project.
                  </div>
                </div>
              </div>
              <div className={styles.DeleteProjectModalLowerSection}>
                <div className={styles.DeleteProjectModelButtons}>
                  <PrimaryButton
                    className="CancelBtn"
                    onClick={() => {
                      setOpenDisableProjectModel(false);
                    }}
                  >
                    Cancel
                  </PrimaryButton>
                  <PrimaryButton
                    color={details?.disabled ? "primary" : "red"}
                    onClick={(e) => handleDisableProject(e, details?.disabled)}
                  >
                    {disablingProject ? (
                      <Spinner />
                    ) : details?.disabled === true ? (
                      "Enable"
                    ) : (
                      "Disable"
                    )}
                  </PrimaryButton>
                </div>

                {disableProjectError && (
                  <Feedback message={disableProjectError} type="error" />
                )}
              </div>
            </div>
          </Modal>
        </div>
      )}
    </div>
  );
};

export default AdminProjectDetails;