[WEB-2681] fix: module progress indicator (#5842)

* fix: module progress indicator

* fix: module progress indicator
This commit is contained in:
Anmol Singh Bhatia 2024-10-21 15:48:35 +05:30 committed by GitHub
parent b833e3b10c
commit 6f8df3279c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 56 deletions

View file

@ -7,12 +7,21 @@ import { useParams, usePathname, useSearchParams } from "next/navigation";
import { Info, SquareUser } from "lucide-react";
// ui
import { IModule } from "@plane/types";
import { Card, FavoriteStar, LayersIcon, LinearProgressIndicator, TOAST_TYPE, Tooltip, setPromiseToast, setToast } from "@plane/ui";
import {
Card,
FavoriteStar,
LayersIcon,
LinearProgressIndicator,
TOAST_TYPE,
Tooltip,
setPromiseToast,
setToast,
} from "@plane/ui";
// components
import { DateRangeDropdown } from "@/components/dropdowns";
import { ButtonAvatars } from "@/components/dropdowns/member/avatar";
import { ModuleQuickActions } from "@/components/modules";
import { ModuleStatusDropdown } from "@/components/modules/module-status-dropdown";
import { ModuleStatusDropdown } from "@/components/modules/module-status-dropdown";
// constants
import { PROGRESS_STATE_GROUPS_DETAILS } from "@/constants/common";
import { MODULE_FAVORITED, MODULE_UNFAVORITED } from "@/constants/event-tracker";
@ -21,11 +30,10 @@ import { MODULE_STATUS } from "@/constants/module";
import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper";
import { generateQueryParams } from "@/helpers/router.helper";
// hooks
import { useEventTracker, useMember, useModule, useProjectEstimates, useUserPermissions } from "@/hooks/store";
import { useEventTracker, useMember, useModule, useUserPermissions } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
import { usePlatformOS } from "@/hooks/use-platform-os";
// plane web constants
import { EEstimateSystem } from "@/plane-web/constants/estimates";
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
type Props = {
@ -46,7 +54,6 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
const { getModuleById, addModuleToFavorites, removeModuleFromFavorites, updateModuleDetails } = useModule();
const { getUserDetails } = useMember();
const { captureEvent } = useEventTracker();
const { currentActiveEstimateId, areEstimateEnabledByProjectId, estimateById } = useProjectEstimates();
// derived values
const moduleDetails = getModuleById(moduleId);
@ -57,7 +64,6 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
const isDisabled = !isEditingAllowed || !!moduleDetails?.archived_at;
const renderIcon = Boolean(moduleDetails?.start_date) || Boolean(moduleDetails?.target_date);
const { isMobile } = usePlatformOS();
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
@ -156,29 +162,14 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
if (!moduleDetails) return null;
/**
* NOTE: This completion percentage calculation is based on the total issues count.
* when estimates are available and estimate type is points, we should consider the estimate point count
* when estimates are available and estimate type is not points, then by default we consider the issue count
*/
const isEstimateEnabled =
projectId &&
currentActiveEstimateId &&
areEstimateEnabledByProjectId(projectId.toString()) &&
estimateById(currentActiveEstimateId)?.type === EEstimateSystem.POINTS;
const moduleTotalIssues = isEstimateEnabled
? moduleDetails?.total_estimate_points || 0
: moduleDetails.backlog_issues +
moduleDetails.unstarted_issues +
moduleDetails.started_issues +
moduleDetails.completed_issues +
moduleDetails.cancelled_issues;
const moduleCompletedIssues = isEstimateEnabled
? moduleDetails?.completed_estimate_points || 0
: moduleDetails.completed_issues;
const moduleTotalIssues =
moduleDetails.backlog_issues +
moduleDetails.unstarted_issues +
moduleDetails.started_issues +
moduleDetails.completed_issues +
moduleDetails.cancelled_issues;
const moduleCompletedIssues = moduleDetails.completed_issues;
// const areYearsEqual = startDate.getFullYear() === endDate.getFullYear();
@ -186,11 +177,11 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
const issueCount = module
? !moduleTotalIssues || moduleTotalIssues === 0
? `0 ${isEstimateEnabled ? `Point` : `Issue`}`
? `0 Issue`
: moduleTotalIssues === moduleCompletedIssues
? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? `s` : ``}`
: `${moduleCompletedIssues}/${moduleTotalIssues} ${isEstimateEnabled ? `Points` : `Issues`}`
: `0 ${isEstimateEnabled ? `Point` : `Issue`}`;
: `${moduleCompletedIssues}/${moduleTotalIssues} Issues`
: `0 Issue`;
const moduleLeadDetails = moduleDetails.lead_id ? getUserDetails(moduleDetails.lead_id) : undefined;
@ -213,9 +204,9 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
<div className="flex items-center gap-2" onClick={handleEventPropagation}>
{moduleStatus && (
<ModuleStatusDropdown
isDisabled={isDisabled}
moduleDetails={moduleDetails}
handleModuleDetailsChange={handleModuleDetailsChange}
isDisabled={isDisabled}
moduleDetails={moduleDetails}
handleModuleDetailsChange={handleModuleDetailsChange}
/>
)}
<button onClick={openModuleOverview}>
@ -252,9 +243,9 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
}}
onSelect={(val) => {
handleModuleDetailsChange({
start_date: (val?.from ? renderFormattedPayloadDate(val.from) : null),
target_date: (val?.to ? renderFormattedPayloadDate(val.to) : null)
})
start_date: val?.from ? renderFormattedPayloadDate(val.from) : null,
target_date: val?.to ? renderFormattedPayloadDate(val.to) : null,
});
}}
placeholder={{
from: "Start date",
@ -288,4 +279,4 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
</div>
</div>
);
});
});

View file

@ -13,11 +13,9 @@ import { ModuleListItemAction, ModuleQuickActions } from "@/components/modules";
// helpers
import { generateQueryParams } from "@/helpers/router.helper";
// hooks
import { useModule, useProjectEstimates } from "@/hooks/store";
import { useModule } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
import { usePlatformOS } from "@/hooks/use-platform-os";
// plane web constants
import { EEstimateSystem } from "@/plane-web/constants/estimates";
type Props = {
moduleId: string;
@ -35,27 +33,14 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
// store hooks
const { getModuleById } = useModule();
const { isMobile } = usePlatformOS();
const { currentActiveEstimateId, areEstimateEnabledByProjectId, estimateById } = useProjectEstimates();
// derived values
const moduleDetails = getModuleById(moduleId);
if (!moduleDetails) return null;
/**
* NOTE: This completion percentage calculation is based on the total issues count.
* when estimates are available and estimate type is points, we should consider the estimate point count
* when estimates are available and estimate type is not points, then by default we consider the issue count
*/
const isEstimateEnabled =
projectId &&
currentActiveEstimateId &&
areEstimateEnabledByProjectId(projectId?.toString()) &&
estimateById(currentActiveEstimateId)?.type === EEstimateSystem.POINTS;
const completionPercentage = isEstimateEnabled
? ((moduleDetails?.completed_estimate_points || 0) / (moduleDetails?.total_estimate_points || 0)) * 100
: ((moduleDetails.completed_issues + moduleDetails.cancelled_issues) / moduleDetails.total_issues) * 100;
const completionPercentage =
((moduleDetails.completed_issues + moduleDetails.cancelled_issues) / moduleDetails.total_issues) * 100;
const progress = isNaN(completionPercentage) ? 0 : Math.floor(completionPercentage);