From f73a6032269008b7cab646fd4a25e158eb7d4679 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:54:44 +0530 Subject: [PATCH] [WEB-2380] chore: cycle sidebar refactor (#5759) * chore: cycle sidebar refactor * chore: code splitting * chore: code refactor * chore: code refactor --- .../cycles/analytics-sidebar/base.tsx | 69 +++++++++++++++++++ .../cycles/analytics-sidebar/index.ts | 2 +- .../cycles/analytics-sidebar/root.tsx | 12 ++++ .../analytics-sidebar/sidebar-chart.tsx | 57 --------------- .../analytics-sidebar/issue-progress.tsx | 41 ++++------- .../analytics-sidebar/sidebar-details.tsx | 4 +- 6 files changed, 98 insertions(+), 87 deletions(-) create mode 100644 web/ce/components/cycles/analytics-sidebar/base.tsx create mode 100644 web/ce/components/cycles/analytics-sidebar/root.tsx delete mode 100644 web/ce/components/cycles/analytics-sidebar/sidebar-chart.tsx diff --git a/web/ce/components/cycles/analytics-sidebar/base.tsx b/web/ce/components/cycles/analytics-sidebar/base.tsx new file mode 100644 index 00000000000..94609bc1f63 --- /dev/null +++ b/web/ce/components/cycles/analytics-sidebar/base.tsx @@ -0,0 +1,69 @@ +"use client"; +import { FC, Fragment } from "react"; +import { observer } from "mobx-react"; +// plane ui +import { Loader } from "@plane/ui"; +// components +import ProgressChart from "@/components/core/sidebar/progress-chart"; +import { validateCycleSnapshot } from "@/components/cycles"; +// helpers +import { getDate } from "@/helpers/date-time.helper"; +// hooks +import { useCycle } from "@/hooks/store"; + +type ProgressChartProps = { + workspaceSlug: string; + projectId: string; + cycleId: string; +}; +export const SidebarChart: FC = observer((props) => { + const { workspaceSlug, projectId, cycleId } = props; + + // hooks + const { getEstimateTypeByCycleId, getCycleById } = useCycle(); + + // derived data + const cycleDetails = validateCycleSnapshot(getCycleById(cycleId)); + const cycleStartDate = getDate(cycleDetails?.start_date); + const cycleEndDate = getDate(cycleDetails?.end_date); + const totalEstimatePoints = cycleDetails?.total_estimate_points || 0; + const totalIssues = cycleDetails?.total_issues || 0; + const estimateType = getEstimateTypeByCycleId(cycleId); + + const chartDistributionData = + estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution || undefined; + + const completionChartDistributionData = chartDistributionData?.completion_chart || undefined; + + if (!workspaceSlug || !projectId || !cycleId) return null; + + return ( +
+
+
+ + Ideal +
+
+ + Current +
+
+ {cycleStartDate && cycleEndDate && completionChartDistributionData ? ( + + + + ) : ( + + + + )} +
+ ); +}); diff --git a/web/ce/components/cycles/analytics-sidebar/index.ts b/web/ce/components/cycles/analytics-sidebar/index.ts index 3ba38c61be5..1efe34c51ec 100644 --- a/web/ce/components/cycles/analytics-sidebar/index.ts +++ b/web/ce/components/cycles/analytics-sidebar/index.ts @@ -1 +1 @@ -export * from "./sidebar-chart"; +export * from "./root"; diff --git a/web/ce/components/cycles/analytics-sidebar/root.tsx b/web/ce/components/cycles/analytics-sidebar/root.tsx new file mode 100644 index 00000000000..d18f9168dcf --- /dev/null +++ b/web/ce/components/cycles/analytics-sidebar/root.tsx @@ -0,0 +1,12 @@ +"use client"; +import React, { FC } from "react"; +// components +import { SidebarChart } from "./base"; + +type Props = { + workspaceSlug: string; + projectId: string; + cycleId: string; +}; + +export const SidebarChartRoot: FC = (props) => ; diff --git a/web/ce/components/cycles/analytics-sidebar/sidebar-chart.tsx b/web/ce/components/cycles/analytics-sidebar/sidebar-chart.tsx deleted file mode 100644 index e5b69ef24b1..00000000000 --- a/web/ce/components/cycles/analytics-sidebar/sidebar-chart.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { Fragment } from "react"; -import { TCycleDistribution, TCycleEstimateDistribution } from "@plane/types"; -import { Loader } from "@plane/ui"; -import ProgressChart from "@/components/core/sidebar/progress-chart"; - -type ProgressChartProps = { - chartDistributionData: TCycleEstimateDistribution | TCycleDistribution | undefined; - cycleStartDate: Date | undefined; - cycleEndDate: Date | undefined; - totalEstimatePoints: number; - totalIssues: number; - plotType: string; -}; -export const SidebarBaseChart = (props: ProgressChartProps) => { - const { chartDistributionData, cycleStartDate, cycleEndDate, totalEstimatePoints, totalIssues, plotType } = props; - const completionChartDistributionData = chartDistributionData?.completion_chart || undefined; - - return ( -
-
-
- - Ideal -
-
- - Current -
-
- {cycleStartDate && cycleEndDate && completionChartDistributionData ? ( - - {plotType === "points" ? ( - - ) : ( - - )} - - ) : ( - - - - )} -
- ); -}; diff --git a/web/core/components/cycles/analytics-sidebar/issue-progress.tsx b/web/core/components/cycles/analytics-sidebar/issue-progress.tsx index 2f9b4b79e9d..55178ed2171 100644 --- a/web/core/components/cycles/analytics-sidebar/issue-progress.tsx +++ b/web/core/components/cycles/analytics-sidebar/issue-progress.tsx @@ -1,6 +1,6 @@ "use client"; -import { FC, Fragment, useCallback, useMemo, useState } from "react"; +import { FC, Fragment, useCallback, useMemo } from "react"; import isEmpty from "lodash/isEmpty"; import isEqual from "lodash/isEqual"; import { observer } from "mobx-react"; @@ -16,10 +16,9 @@ import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue"; // helpers import { getDate } from "@/helpers/date-time.helper"; // hooks -import { useIssues, useCycle, useProjectEstimates } from "@/hooks/store"; -// plane web constants -import { SidebarBaseChart } from "@/plane-web/components/cycles/analytics-sidebar"; -import { EEstimateSystem } from "@/plane-web/constants/estimates"; +import { useIssues, useCycle } from "@/hooks/store"; +// plane web components +import { SidebarChartRoot } from "@/plane-web/components/cycles"; type TCycleAnalyticsProgress = { workspaceSlug: string; @@ -27,7 +26,7 @@ type TCycleAnalyticsProgress = { cycleId: string; }; -const validateCycleSnapshot = (cycleDetails: ICycle | null): ICycle | null => { +export const validateCycleSnapshot = (cycleDetails: ICycle | null): ICycle | null => { if (!cycleDetails || cycleDetails === null) return cycleDetails; const updatedCycleDetails: any = { ...cycleDetails }; @@ -60,12 +59,9 @@ export const CycleAnalyticsProgress: FC = observer((pro // router const searchParams = useSearchParams(); const peekCycle = searchParams.get("peekCycle") || undefined; - // hooks - const { areEstimateEnabledByProjectId, currentActiveEstimateId, estimateById } = useProjectEstimates(); const { getPlotTypeByCycleId, getEstimateTypeByCycleId, - setPlotType, getCycleById, fetchCycleDetails, fetchArchivedCycleDetails, @@ -74,17 +70,11 @@ export const CycleAnalyticsProgress: FC = observer((pro const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.CYCLE); - // state - const [loader, setLoader] = useState(false); // derived values const cycleDetails = validateCycleSnapshot(getCycleById(cycleId)); const plotType: TCyclePlotType = getPlotTypeByCycleId(cycleId); const estimateType = getEstimateTypeByCycleId(cycleId); - const isCurrentProjectEstimateEnabled = projectId && areEstimateEnabledByProjectId(projectId) ? true : false; - const estimateDetails = - isCurrentProjectEstimateEnabled && currentActiveEstimateId && estimateById(currentActiveEstimateId); - const isCurrentEstimateTypeIsPoints = estimateDetails && estimateDetails?.type === EEstimateSystem.POINTS; const completedIssues = cycleDetails?.completed_issues || 0; const totalIssues = cycleDetails?.total_issues || 0; @@ -132,15 +122,13 @@ export const CycleAnalyticsProgress: FC = observer((pro setEstimateType(cycleId, value); if (!workspaceSlug || !projectId || !cycleId) return; try { - setLoader(true); if (isArchived) { await fetchArchivedCycleDetails(workspaceSlug, projectId, cycleId); } else { await fetchCycleDetails(workspaceSlug, projectId, cycleId); } - setLoader(false); - } catch (error) { - setLoader(false); + } catch (err) { + console.error(err); setEstimateType(cycleId, estimateType); } }; @@ -218,16 +206,15 @@ export const CycleAnalyticsProgress: FC = observer((pro ))} +
+
+ Done + {progressHeaderPercentage}% +
+
- +
{/* progress detailed view */} {chartDistributionData && ( diff --git a/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx b/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx index 0c6ad1fd81f..708b9c217b3 100644 --- a/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx +++ b/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx @@ -3,10 +3,10 @@ import React, { FC } from "react"; import isEmpty from "lodash/isEmpty"; import { observer } from "mobx-react"; import { LayersIcon, SquareUser, Users } from "lucide-react"; -// ui +// types import { ICycle } from "@plane/types"; +// ui import { Avatar, AvatarGroup, TextArea } from "@plane/ui"; -// types // hooks import { useMember, useProjectEstimates } from "@/hooks/store"; // plane web