Untitled
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); } };