Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
16 kB
1
Indexable
Never
import React, { useEffect, useState, useContext } from "react";
import Breadcrumbs, { BreadcrumbsItem } from "@atlaskit/breadcrumbs";
import { Dropdown, Menu, message, Space } from "antd";
import { DownOutlined, UserOutlined } from "@ant-design/icons";
import ArrowUpCircleIcon from "@atlaskit/icon/glyph/arrow-up-circle";
import HomeIcon from "@atlaskit/icon/glyph/home";
import Select from "../SelectBox";
import { Link, useLocation, useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import CreateJournalModal from "../Modals/CreateJournalModal";
import UpdateBadge from "@atlaskit/badge";
import { router } from "@forge/bridge";
import ReportsDrawer from "../Reports Drawer";
import SettingsDrawer from "../SettingsDrawer";
import ExportComponent from "../Export";
import Button from "@atlaskit/button/standard-button";
import UpArrowIcon from "../../assets/Images/arrow-up.svg";
import PlaceHolderImage from "../../assets/Images/homePagePlaceHolder.svg";
import AddIcon from "../../assets/Images/addIcon.svg";
import drawerIcon from "../../assets/Images/minimizeIcon.svg";
import exportIcon from "../../assets/Images/exportIcon.svg";
import refreshIcon from "../../assets/Images/refresh.svg";
import dots from "../../assets/Images/threeDotIcon.svg";
import Loading from "../PageLoader";
import { MyContext } from "../../context/useContext";
import {
  getIssues,
  getIssuesByPriority,
  getCreatedVsResolvedIssues,
  getUnReleasedVersions,
  getAllSprints,
  getStoryPointsKey,
  getUpdatesOfLastViewedJorunals,
  getStatuses,
  getFields,
} from "../../components/persistence/utils/JiraUtils";
import { getJournals } from "../../components/persistence/utils/StorageUtils";
import Reports from "../Tabs/Reports";
import Updates from "../Tabs/Updates";
import { useDetails } from "../../hooks/useDetails";
import { useRequestJira } from "../../hooks/useRequestJira";
import {
  GET_MYSELF_QUERY,
  DEFAULT_CREATED_VS_RESOLVED_DAYS,
} from "../../constants";
import SettingsIcon from "@atlaskit/icon/glyph/settings";
import ExportIcon from "@atlaskit/icon/glyph/export";
import GraphBarIcon from "@atlaskit/icon/glyph/graph-bar";
import MediaServicesAddCommentIcon from "@atlaskit/icon/glyph/media-services/add-comment";
import {
  UPDATES_TAB_TEXT,
  REPORTS_TAB_TEXT,
  SETTINGS_TAB_TEXT,
  PROJECT_HUB,
  PROJECT_HOME_PAGE,
  SCROLL_TO_THE_TOP_LABEL,
  REFRESH,
  EXPORT,
  ADD_REPORTS,
  PLEASE_SELECT_A_HUB,
  YOU_DONT_HAVE_ANY_HUBS,
  NOTIFICATION_LABEL,
  ERROR_LABEL,
  YOU_HAVE_SUCCESSFULLY_CREATED_LABEL,
  ERROR_CREATING_THE_REPORT_LABEL,
  NEW_COPY_HUB,
  NEW_HUB,
  COPY_HUB,
  DELETE_HUB,
} from "../../messages";
import { Flex, Text } from "../Basic";
import Tooltip from "../Tooltip";
import { getReportQuery } from "../persistence/utils/ReportQuery";
import Modal from "antd/es/modal/Modal";
import Notification from "antd/lib/notification";

import { successfulNotification, errorNotification } from "../Notification";
import DeleteModal from "../journalListDelete";

const DetailsPage = () => {
  const [user, setUser] = useState(null);
  const [selectedTab, setSelectedTab] = useState(0);
  const { search } = useLocation();
  const [loading, setLoading] = useState(false);
  const [updateBadges, setUpdateBadges] = useState(null);
  const [showExport, setShowExport] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [journal, setJournal] = useState(null);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [reportsDrawerOpen, setReportsDrawerOpen] = useState(false);
  const [journalToBeDuplicated, setJournalToBeDuplicated] = useState(null);
  const [settingsDrawerOpen, setSettingsDrawerOpen] = useState(false);
  const [api, contextHolder] = Notification.useNotification();
  const [dropDownOpen, setDropDownOpen] = useState(false);

  const [deleteModal, setDeleteModal] = useState(false);
  const {
    addId,
    addSprints,
    setStoryPointsKey,
    addFields,
    addStatuses,
    id,
    currentJournal,
    addCurrentJournal,
    journals,
    addUser,
    addJournals,
    minAllReports,
  } = useContext(MyContext);

  const { projectKey } = useDetails();

  useEffect(() => {
    if (projectKey) {
      setIsLoading(true);
      getJournals(projectKey)
        .then((data) => {
          addJournals(data);
        })
        .finally(() => {
          setIsLoading(false);
        });
    }
  }, [projectKey]);
  
  useEffect(() => {
    const savedId = localStorage.getItem("selectedJournalId");
    if (savedId) {
      addId(savedId);
      addCurrentJournal(journals?.find((journal) => journal.id === savedId));
    } 
  }, [journals]);

  useEffect(() => {
    if (journals.length > 0 && id) {
      if (journals?.find((journal) => journal.id === id)) {
        addCurrentJournal(journals?.find((journal) => journal.id === id));
      }
    }
  }, [id]);

  useEffect(() => {
    localStorage.setItem("selectedJournalId", id);
  }, [id]);

  useEffect(() => {
    useRequestJira(GET_MYSELF_QUERY).then((res) => addUser(res.accountId));
  }, []);

  const [showScrollButton, setShowScrollButton] = useState(false);

  const scrollToTopButton = document.getElementById("scrollToTopButton");

  window.onscroll = function () {
    scrollFunction();
  };
  function scrollFunction() {
    if (
      document.body.scrollTop > 50 ||
      document.documentElement.scrollTop > 50
    ) {
      scrollToTopButton.style.display = "block";
    } else {
      scrollToTopButton.style.display = "none";
    }
  }

  const handleScroll = () => {
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    setShowScrollButton(scrollTop > 0);
  };

  const handleScrollToTop = () => {
    window.scrollTo({
      top: 0,
      behavior: "smooth",
    });
  };

  useEffect(() => {
    window.addEventListener("scroll", handleScroll);
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  useEffect(() => {
    setJournal(currentJournal);
  }, [journals, currentJournal]);

  useEffect(() => {
    if (search.includes("settings")) {
      journal?.settings?.updates ? setSelectedTab(3) : setSelectedTab(2);
    } else if (search.includes("exports")) {
      journal?.settings?.updates ? setSelectedTab(2) : setSelectedTab(1);
    }
  }, [search, journal?.settings]);

  useEffect(() => {
    useRequestJira(GET_MYSELF_QUERY).then((res) => setUser(res.accountId));
    if (projectKey) {
      fetchAllData(
        addSprints,
        setStoryPointsKey,
        addFields,
        addStatuses,
      );
    }
    if (journals && user) {
      getUpdatesOfLastViewedJorunals(journals, user).then((res) => {
        setUpdateBadges(res);
      });
    }
  }, [projectKey, id, user]);

  const handleRefresh = () => {
    router.reload();
  };

  const onClick = ({ key }) => {
    switch (key) {
      case "configure":
        setSettingsDrawerOpen(true);
        setDropDownOpen(false);
        break;
      case "copyHub":
        setIsModalOpen(true);
        setJournalToBeDuplicated(currentJournal);
        setDropDownOpen(false);
        break;
      case "deleteHub":
        setDeleteModal(true);
        setDropDownOpen(false);
        break;
      default:
        break;
    }
  };

  const items = [
    {
      label: "Configure",
      key: "configure",
    },
    {
      label: "Copy hub",
      key: "copyHub",
    },
    {
      label: "Delete hub",
      key: "deleteHub",
    },
  ];

  return (
    <Flex
      alignItems="flex-start"
      flexDirection="column"
      width="96vw"
      height="fit-content"
    >
      {isModalOpen && (
        <CreateJournalModal
          isModalOpen={isModalOpen}
          ModalCloseHandler={() => setIsModalOpen(!isModalOpen)}
          journalToBeDuplicated={journalToBeDuplicated}
          setJournalToBeDuplicated={setJournalToBeDuplicated}
        />
      )}

      {deleteModal && (
        <DeleteModal
          loading={loading}
          setLoading={setLoading}
          journal={currentJournal}
          setDeleteModal={setDeleteModal}
        />
      )}
      {contextHolder}
      <Flex justifyContent="space-between" gap="10px">
        <Flex
          flexDirection="column"
          width="fit-content"
          gap="10px"
          alignItems="flex-start"
        >
          <Flex width="fit-content" gap="10px">
            {journals.length > 0 && (
              <Select
                value={id}
                loading={isLoading}
                onChange={(value) => {
                  addId(value);
                }}
                options={journals?.map((journal) => {
                  return {
                    label: journal.name,
                    value: journal.id,
                  };
                })}
                defaultValue={journal?.id}
                width="300px"
                placeholder={PROJECT_HOME_PAGE}
              />
            )}

            <Button
              style={{
                background: " #FFAB00",
                color: "#000",
              }}
              onClick={() => setIsModalOpen(true)}
            >
              <Flex gap="5px" style={{ color: "#172B4D" }}>
                {NEW_HUB}
              </Flex>
            </Button>
          </Flex>
          <Text fontSize="25px" fontWeight="400">
            {currentJournal &&
              Object.keys(currentJournal).length > 0 &&
              currentJournal?.name}
          </Text>
        </Flex>
        <Flex width="fit-content" gap="10px"></Flex>
      </Flex>
      <br />
      {id && (
        <ReportsDrawer
          open={reportsDrawerOpen}
          onClose={() => setReportsDrawerOpen(false)}
          journal={journal || currentJournal || {}}
          api={api}
          successfulNotification={successfulNotification}
          errorNotification={errorNotification}
        />
      )}
      {id && (
        <SettingsDrawer
          open={settingsDrawerOpen}
          onClose={() => setSettingsDrawerOpen(false)}
          setSettingsDrawerOpen={setSettingsDrawerOpen}
          journal={journal || currentJournal || {}}
        />
      )}
      {(settingsDrawerOpen || reportsDrawerOpen) && (
        <div
          onClick={() => {
            setSettingsDrawerOpen(false);
            setReportsDrawerOpen(false);
          }}
          style={{
            inset: "0px",
            position: "fixed",
            height: "100vh",
            width: "100vw",
            zIndex: "100",
            backgroundColor: "rgba(0,0,0,0.5)",
          }}
        ></div>
      )}

      <div
        style={{
          position: "fixed",
          top: "20px",
          right: "20px",
          gap: "20px",
          zIndex: "100",
          backgroundColor: "white",
          display: "flex",
          flexDirection: "column",
          width: "fit-content",
        }}
      >
        <div
          style={{
            background: dropDownOpen ? "#EBECF0" : "transparent",
            borderRadius: "5px",
            width: "32px",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            transition: "all 0.3s ease-in-out",
            cursor: "pointer",
            marginBottom: "40px",
        
          }}
        >
          <Dropdown
            onOpenChange={(open) => {
              setDropDownOpen(open);
          
            }}
            trigger={["click"]}
            menu={{ items, onClick }}
          >
            <img
              src={dots}
              alt="dots"
              style={{
                cursor: id ? "pointer" : "not-allowed",
                filter: !id && "invert(0.6)",
                transform: "rotate(90deg)",
              }}
            />
          </Dropdown>
        </div>
        <div onClick={() => setReportsDrawerOpen(true)}>
          <img
            src={AddIcon}
            alt="drawerIcon"
            style={{
              cursor: id ? "pointer" : "not-allowed",
              filter: !id && "invert(0.6)",
            }}
          />
        </div>
        <div onClick={handleRefresh}>
          <img
            src={refreshIcon}
            alt="refreshIcon"
            style={{
              cursor: id ? "pointer" : "not-allowed",
              filter: !id && "invert(0.6)",
            }}
          />
        </div>
        <div
          onClick={() => {
            setShowExport(true);
          }}
        >
          <img
            src={exportIcon}
            alt="exportIcon"
            style={{
              cursor: id ? "pointer" : "not-allowed",
              filter: !id && "invert(0.6)",
            }}
          />
        </div>
        <div
          onClick={() => {
            minAllReports();
          }}
        >
          <img
            src={drawerIcon}
            alt="dots"
            style={{
              cursor: id ? "pointer" : "not-allowed",
              filter: !id && "invert(0.6)",
            }}
          />
        </div>
      </div>
      <div
        id="scrollToTopButton"
        onClick={handleScrollToTop}
        style={{
          position: "fixed",
          bottom: "100px",
          right: "20px",
          zIndex: "100",
          backgroundColor: "white",
          display: "block",
          width: "fit-content",
        }}
      >
        <img
          src={UpArrowIcon}
          alt="UpArrowIcon"
          style={{
            cursor: id ? "pointer" : "not-allowed",
            filter: !id && "invert(0.6)",
          }}
        />
      </div>

      {id && !isLoading && (
        <div
          style={{
           
            marginBottom: "100px",
          }}
        >
          {journal && Object.keys(journal).length > 0 && (
            <Reports isLoading={isLoading} journal={journal} />
          )}
        </div>
      )}

      <Modal
        visible={showExport}
        onCancel={() => setShowExport(false)}
        footer={null}
        width="fit-content"
        style={{
          top: "10px",
        }}
      >
        <ExportComponent />
      </Modal>

      {isLoading ? (
        <div style={{ position: "absolute", top: "40%", left: "50%" }}>
          <Loading size="xlarge" appearance="inherit" />
        </div>
      ) : (
        !isLoading &&
        !id && (
          <Flex alignItems="center" justifyContent="center" height="80vh">
            <Flex
              flexDirection="column"
              alignItems="center"
              justifyContent="center"
              gap="10px"
              height="fit-content"
              width="fit-content"
            >
              <img src={PlaceHolderImage} alt="Group-1" border="0" />
              {journals.length == 0 || !journal ? (
                <Text
                  style={{
                    textAlign: "center",
                    fontWeight: "bold",
                  }}
                  >{YOU_DONT_HAVE_ANY_HUBS}</Text>
              ) : (
                <Text
                  style={{
                    textAlign: "center",
                    fontWeight:'bold'
                  }}
                  >{PLEASE_SELECT_A_HUB}</Text>
              )}
            </Flex>
          </Flex>
        )
      )}
    </Flex>
  );
};

export default DetailsPage;

DetailsPage.propTypes = {
  setPages: PropTypes.func,
  pages: PropTypes.array,
  name: PropTypes.string,
  path: PropTypes.string,
  element: PropTypes.element,
  key: PropTypes.string,
  match: PropTypes.object,
};

const fetchAllData = async (
  addSprints,
  setStoryPointsKey,
  addFields,
  addStatuses,
) => {

  const promises = [];

  promises.push(
    getStoryPointsKey().then((data) => {
      setStoryPointsKey(data);
    })
  );

  promises.push(
    getFields().then((data) => {
      addFields(data);
    })
  );

  promises.push(
    getStatuses().then((data) => {
      addStatuses(data);
    })
  );

  promises.push(
    getAllSprints().then((data) => {
      addSprints(data);
    })
  );

  try {
    await Promise.all(promises);
  } catch (error) {
    console.error("An error occurred:", error);
  }
};