forked from github/plane
[WEB-914]: fix: Exception due to cycles and modules for undefined fields (#4127)
* fix cycle types * fix module types
This commit is contained in:
parent
62dac421dc
commit
90609b306f
17
packages/types/src/cycle/cycle.d.ts
vendored
17
packages/types/src/cycle/cycle.d.ts
vendored
@ -6,8 +6,8 @@ export interface ICycle {
|
|||||||
backlog_issues: number;
|
backlog_issues: number;
|
||||||
cancelled_issues: number;
|
cancelled_issues: number;
|
||||||
completed_issues: number;
|
completed_issues: number;
|
||||||
created_at: Date;
|
created_at?: string;
|
||||||
created_by: string;
|
created_by?: string;
|
||||||
description: string;
|
description: string;
|
||||||
distribution?: {
|
distribution?: {
|
||||||
assignees: TAssigneesDistribution[];
|
assignees: TAssigneesDistribution[];
|
||||||
@ -16,23 +16,22 @@ export interface ICycle {
|
|||||||
};
|
};
|
||||||
end_date: string | null;
|
end_date: string | null;
|
||||||
id: string;
|
id: string;
|
||||||
is_favorite: boolean;
|
is_favorite?: boolean;
|
||||||
issue: string;
|
|
||||||
name: string;
|
name: string;
|
||||||
owned_by_id: string;
|
owned_by_id: string;
|
||||||
progress_snapshot: TProgressSnapshot;
|
progress_snapshot: TProgressSnapshot;
|
||||||
project_id: string;
|
project_id: string;
|
||||||
status: TCycleGroups;
|
status?: TCycleGroups;
|
||||||
sort_order: number;
|
sort_order: number;
|
||||||
start_date: string | null;
|
start_date: string | null;
|
||||||
started_issues: number;
|
started_issues: number;
|
||||||
sub_issues: number;
|
sub_issues?: number;
|
||||||
total_issues: number;
|
total_issues: number;
|
||||||
unstarted_issues: number;
|
unstarted_issues: number;
|
||||||
updated_at: Date;
|
updated_at?: string;
|
||||||
updated_by: string;
|
updated_by?: string;
|
||||||
archived_at: string | null;
|
archived_at: string | null;
|
||||||
assignee_ids: string[];
|
assignee_ids?: string[];
|
||||||
view_props: {
|
view_props: {
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
};
|
};
|
||||||
|
16
packages/types/src/module/modules.d.ts
vendored
16
packages/types/src/module/modules.d.ts
vendored
@ -12,33 +12,33 @@ export interface IModule {
|
|||||||
backlog_issues: number;
|
backlog_issues: number;
|
||||||
cancelled_issues: number;
|
cancelled_issues: number;
|
||||||
completed_issues: number;
|
completed_issues: number;
|
||||||
created_at: Date;
|
created_at: string;
|
||||||
created_by: string;
|
created_by?: string;
|
||||||
description: string;
|
description: string;
|
||||||
description_text: any;
|
description_text: any;
|
||||||
description_html: any;
|
description_html: any;
|
||||||
distribution: {
|
distribution?: {
|
||||||
assignees: TAssigneesDistribution[];
|
assignees: TAssigneesDistribution[];
|
||||||
completion_chart: TCompletionChartDistribution;
|
completion_chart: TCompletionChartDistribution;
|
||||||
labels: TLabelsDistribution[];
|
labels: TLabelsDistribution[];
|
||||||
};
|
};
|
||||||
id: string;
|
id: string;
|
||||||
lead_id: string | null;
|
lead_id: string | null;
|
||||||
link_module: ILinkDetails[];
|
link_module?: ILinkDetails[];
|
||||||
member_ids: string[];
|
member_ids: string[];
|
||||||
is_favorite: boolean;
|
is_favorite: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
project_id: string;
|
project_id: string;
|
||||||
sort_order: number;
|
sort_order: number;
|
||||||
sub_issues: number;
|
sub_issues?: number;
|
||||||
start_date: string | null;
|
start_date: string | null;
|
||||||
started_issues: number;
|
started_issues: number;
|
||||||
status: TModuleStatus;
|
status?: TModuleStatus;
|
||||||
target_date: string | null;
|
target_date: string | null;
|
||||||
total_issues: number;
|
total_issues: number;
|
||||||
unstarted_issues: number;
|
unstarted_issues: number;
|
||||||
updated_at: Date;
|
updated_at: string;
|
||||||
updated_by: string;
|
updated_by?: string;
|
||||||
archived_at: string | null;
|
archived_at: string | null;
|
||||||
view_props: {
|
view_props: {
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
|
@ -22,11 +22,13 @@ import emptyMembers from "public/empty-state/empty_members.svg";
|
|||||||
// types
|
// types
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
distribution: {
|
distribution:
|
||||||
assignees: TAssigneesDistribution[];
|
| {
|
||||||
completion_chart: TCompletionChartDistribution;
|
assignees: TAssigneesDistribution[];
|
||||||
labels: TLabelsDistribution[];
|
completion_chart: TCompletionChartDistribution;
|
||||||
};
|
labels: TLabelsDistribution[];
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
groupedIssues: {
|
groupedIssues: {
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
};
|
};
|
||||||
@ -129,7 +131,7 @@ export const SidebarProgressStats: React.FC<Props> = ({
|
|||||||
as="div"
|
as="div"
|
||||||
className="flex w-full flex-col gap-1.5 overflow-y-auto pt-3.5 vertical-scrollbar scrollbar-sm"
|
className="flex w-full flex-col gap-1.5 overflow-y-auto pt-3.5 vertical-scrollbar scrollbar-sm"
|
||||||
>
|
>
|
||||||
{distribution?.assignees.length > 0 ? (
|
{distribution && distribution?.assignees.length > 0 ? (
|
||||||
distribution.assignees.map((assignee, index) => {
|
distribution.assignees.map((assignee, index) => {
|
||||||
if (assignee.assignee_id)
|
if (assignee.assignee_id)
|
||||||
return (
|
return (
|
||||||
@ -189,7 +191,7 @@ export const SidebarProgressStats: React.FC<Props> = ({
|
|||||||
as="div"
|
as="div"
|
||||||
className="flex w-full flex-col gap-1.5 overflow-y-auto pt-3.5 vertical-scrollbar scrollbar-sm"
|
className="flex w-full flex-col gap-1.5 overflow-y-auto pt-3.5 vertical-scrollbar scrollbar-sm"
|
||||||
>
|
>
|
||||||
{distribution?.labels.length > 0 ? (
|
{distribution && distribution?.labels.length > 0 ? (
|
||||||
distribution.labels.map((label, index) => (
|
distribution.labels.map((label, index) => (
|
||||||
<SingleProgressStats
|
<SingleProgressStats
|
||||||
key={label.label_id ?? `no-label-${index}`}
|
key={label.label_id ?? `no-label-${index}`}
|
||||||
|
@ -23,14 +23,14 @@ export const ActiveCycleHeader: FC<ActiveCycleHeaderProps> = (props) => {
|
|||||||
const cycleOwnerDetails = cycle && cycle.owned_by_id ? getUserDetails(cycle.owned_by_id) : undefined;
|
const cycleOwnerDetails = cycle && cycle.owned_by_id ? getUserDetails(cycle.owned_by_id) : undefined;
|
||||||
|
|
||||||
const daysLeft = findHowManyDaysLeft(cycle.end_date) ?? 0;
|
const daysLeft = findHowManyDaysLeft(cycle.end_date) ?? 0;
|
||||||
const currentCycleStatus = cycle.status.toLocaleLowerCase() as TCycleGroups;
|
const currentCycleStatus = cycle.status?.toLocaleLowerCase() as TCycleGroups | undefined;
|
||||||
|
|
||||||
const cycleAssignee = (cycle.distribution?.assignees ?? []).filter((assignee) => assignee.display_name);
|
const cycleAssignee = (cycle.distribution?.assignees ?? []).filter((assignee) => assignee.display_name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between px-3 py-1.5 rounded border-[0.5px] border-custom-border-100 bg-custom-background-90">
|
<div className="flex items-center justify-between px-3 py-1.5 rounded border-[0.5px] border-custom-border-100 bg-custom-background-90">
|
||||||
<div className="flex items-center gap-2 cursor-default">
|
<div className="flex items-center gap-2 cursor-default">
|
||||||
<CycleGroupIcon cycleGroup={currentCycleStatus} className="h-4 w-4" />
|
<CycleGroupIcon cycleGroup={currentCycleStatus ?? "draft"} className="h-4 w-4" />
|
||||||
<Tooltip tooltipContent={cycle.name} position="top-left">
|
<Tooltip tooltipContent={cycle.name} position="top-left">
|
||||||
<h3 className="break-words text-lg font-medium">{truncateText(cycle.name, 70)}</h3>
|
<h3 className="break-words text-lg font-medium">{truncateText(cycle.name, 70)}</h3>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@ -99,7 +99,7 @@ export const UpcomingCycleListItem: React.FC<Props> = observer((props) => {
|
|||||||
{renderFormattedDate(cycle.start_date)} - {renderFormattedDate(cycle.end_date)}
|
{renderFormattedDate(cycle.start_date)} - {renderFormattedDate(cycle.end_date)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{cycle.assignee_ids?.length > 0 ? (
|
{cycle.assignee_ids && cycle.assignee_ids?.length > 0 ? (
|
||||||
<AvatarGroup showTooltip={false}>
|
<AvatarGroup showTooltip={false}>
|
||||||
{cycle.assignee_ids?.map((assigneeId) => {
|
{cycle.assignee_ids?.map((assigneeId) => {
|
||||||
const member = getUserDetails(assigneeId);
|
const member = getUserDetails(assigneeId);
|
||||||
|
@ -46,7 +46,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
|
|||||||
|
|
||||||
if (!cycleDetails) return null;
|
if (!cycleDetails) return null;
|
||||||
|
|
||||||
const cycleStatus = cycleDetails.status.toLocaleLowerCase();
|
const cycleStatus = cycleDetails.status?.toLocaleLowerCase();
|
||||||
// const isCompleted = cycleStatus === "completed";
|
// const isCompleted = cycleStatus === "completed";
|
||||||
const endDate = getDate(cycleDetails.end_date);
|
const endDate = getDate(cycleDetails.end_date);
|
||||||
const startDate = getDate(cycleDetails.start_date);
|
const startDate = getDate(cycleDetails.start_date);
|
||||||
@ -189,7 +189,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
|
|||||||
<LayersIcon className="h-4 w-4 text-custom-text-300" />
|
<LayersIcon className="h-4 w-4 text-custom-text-300" />
|
||||||
<span className="text-xs text-custom-text-300">{issueCount}</span>
|
<span className="text-xs text-custom-text-300">{issueCount}</span>
|
||||||
</div>
|
</div>
|
||||||
{cycleDetails.assignee_ids.length > 0 && (
|
{cycleDetails.assignee_ids && cycleDetails.assignee_ids.length > 0 && (
|
||||||
<Tooltip tooltipContent={`${cycleDetails.assignee_ids.length} Members`} isMobile={isMobile}>
|
<Tooltip tooltipContent={`${cycleDetails.assignee_ids.length} Members`} isMobile={isMobile}>
|
||||||
<div className="flex cursor-default items-center gap-1">
|
<div className="flex cursor-default items-center gap-1">
|
||||||
<AvatarGroup showTooltip={false}>
|
<AvatarGroup showTooltip={false}>
|
||||||
|
@ -25,7 +25,7 @@ export const CycleGanttBlock: React.FC<Props> = observer((props) => {
|
|||||||
// derived values
|
// derived values
|
||||||
const cycleDetails = getCycleById(cycleId);
|
const cycleDetails = getCycleById(cycleId);
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
const cycleStatus = cycleDetails?.status.toLocaleLowerCase();
|
const cycleStatus = cycleDetails?.status?.toLocaleLowerCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -35,12 +35,12 @@ export const CycleGanttBlock: React.FC<Props> = observer((props) => {
|
|||||||
cycleStatus === "current"
|
cycleStatus === "current"
|
||||||
? "#09a953"
|
? "#09a953"
|
||||||
: cycleStatus === "upcoming"
|
: cycleStatus === "upcoming"
|
||||||
? "#f7ae59"
|
? "#f7ae59"
|
||||||
: cycleStatus === "completed"
|
: cycleStatus === "completed"
|
||||||
? "#3f76ff"
|
? "#3f76ff"
|
||||||
: cycleStatus === "draft"
|
: cycleStatus === "draft"
|
||||||
? "rgb(var(--color-text-200))"
|
? "rgb(var(--color-text-200))"
|
||||||
: "",
|
: "",
|
||||||
}}
|
}}
|
||||||
onClick={() => router.push(`/${workspaceSlug}/projects/${cycleDetails?.project_id}/cycles/${cycleDetails?.id}`)}
|
onClick={() => router.push(`/${workspaceSlug}/projects/${cycleDetails?.project_id}/cycles/${cycleDetails?.id}`)}
|
||||||
>
|
>
|
||||||
@ -74,7 +74,7 @@ export const CycleGanttSidebarBlock: React.FC<Props> = observer((props) => {
|
|||||||
// derived values
|
// derived values
|
||||||
const cycleDetails = getCycleById(cycleId);
|
const cycleDetails = getCycleById(cycleId);
|
||||||
|
|
||||||
const cycleStatus = cycleDetails?.status.toLocaleLowerCase();
|
const cycleStatus = cycleDetails?.status?.toLocaleLowerCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
@ -87,12 +87,12 @@ export const CycleGanttSidebarBlock: React.FC<Props> = observer((props) => {
|
|||||||
cycleStatus === "current"
|
cycleStatus === "current"
|
||||||
? "#09a953"
|
? "#09a953"
|
||||||
: cycleStatus === "upcoming"
|
: cycleStatus === "upcoming"
|
||||||
? "#f7ae59"
|
? "#f7ae59"
|
||||||
: cycleStatus === "completed"
|
: cycleStatus === "completed"
|
||||||
? "#3f76ff"
|
? "#3f76ff"
|
||||||
: cycleStatus === "draft"
|
: cycleStatus === "draft"
|
||||||
? "rgb(var(--color-text-200))"
|
? "rgb(var(--color-text-200))"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
<h6 className="flex-grow truncate text-sm font-medium">{cycleDetails?.name}</h6>
|
<h6 className="flex-grow truncate text-sm font-medium">{cycleDetails?.name}</h6>
|
||||||
|
@ -216,7 +216,7 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
|
|||||||
<div className="relative flex flex-shrink-0 items-center gap-3">
|
<div className="relative flex flex-shrink-0 items-center gap-3">
|
||||||
<Tooltip tooltipContent={`${cycleDetails.assignee_ids?.length} Members`} isMobile={isMobile}>
|
<Tooltip tooltipContent={`${cycleDetails.assignee_ids?.length} Members`} isMobile={isMobile}>
|
||||||
<div className="flex w-10 cursor-default items-center justify-center">
|
<div className="flex w-10 cursor-default items-center justify-center">
|
||||||
{cycleDetails.assignee_ids?.length > 0 ? (
|
{cycleDetails.assignee_ids && cycleDetails.assignee_ids?.length > 0 ? (
|
||||||
<AvatarGroup showTooltip={false}>
|
<AvatarGroup showTooltip={false}>
|
||||||
{cycleDetails.assignee_ids?.map((assignee_id) => {
|
{cycleDetails.assignee_ids?.map((assignee_id) => {
|
||||||
const member = getUserDetails(assignee_id);
|
const member = getUserDetails(assignee_id);
|
||||||
|
@ -37,7 +37,7 @@ export const CycleQuickActions: React.FC<Props> = observer((props) => {
|
|||||||
const { getCycleById, restoreCycle } = useCycle();
|
const { getCycleById, restoreCycle } = useCycle();
|
||||||
// derived values
|
// derived values
|
||||||
const cycleDetails = getCycleById(cycleId);
|
const cycleDetails = getCycleById(cycleId);
|
||||||
const isCompleted = cycleDetails?.status.toLowerCase() === "completed";
|
const isCompleted = cycleDetails?.status?.toLowerCase() === "completed";
|
||||||
// auth
|
// auth
|
||||||
const isEditingAllowed =
|
const isEditingAllowed =
|
||||||
!!currentWorkspaceAllProjectsRole && currentWorkspaceAllProjectsRole[projectId] >= EUserProjectRoles.MEMBER;
|
!!currentWorkspaceAllProjectsRole && currentWorkspaceAllProjectsRole[projectId] >= EUserProjectRoles.MEMBER;
|
||||||
|
@ -211,7 +211,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
// [workspaceSlug, projectId, cycleId, issueFilters, updateFilters]
|
// [workspaceSlug, projectId, cycleId, issueFilters, updateFilters]
|
||||||
// );
|
// );
|
||||||
|
|
||||||
const cycleStatus = cycleDetails?.status.toLocaleLowerCase();
|
const cycleStatus = cycleDetails?.status?.toLocaleLowerCase();
|
||||||
const isCompleted = cycleStatus === "completed";
|
const isCompleted = cycleStatus === "completed";
|
||||||
|
|
||||||
const startDate = getDate(cycleDetails?.start_date);
|
const startDate = getDate(cycleDetails?.start_date);
|
||||||
|
@ -134,9 +134,11 @@ export const TransferIssuesModal: React.FC<Props> = observer((props) => {
|
|||||||
<ContrastIcon className="h-5 w-5" />
|
<ContrastIcon className="h-5 w-5" />
|
||||||
<div className="flex w-full justify-between">
|
<div className="flex w-full justify-between">
|
||||||
<span>{cycleDetails?.name}</span>
|
<span>{cycleDetails?.name}</span>
|
||||||
<span className=" flex items-center rounded-full bg-custom-background-80 px-2 capitalize">
|
{cycleDetails.status && (
|
||||||
{cycleDetails.status.toLocaleLowerCase()}
|
<span className=" flex items-center rounded-full bg-custom-background-80 px-2 capitalize">
|
||||||
</span>
|
{cycleDetails.status.toLocaleLowerCase()}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@ -146,7 +146,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
|||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
|
|
||||||
const issueCount = cycleDetails
|
const issueCount = cycleDetails
|
||||||
? issueFilters?.displayFilters?.sub_issue
|
? issueFilters?.displayFilters?.sub_issue && cycleDetails?.sub_issues
|
||||||
? cycleDetails.total_issues + cycleDetails?.sub_issues
|
? cycleDetails.total_issues + cycleDetails?.sub_issues
|
||||||
: cycleDetails.total_issues
|
: cycleDetails.total_issues
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -147,7 +147,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
|||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
|
|
||||||
const issueCount = moduleDetails
|
const issueCount = moduleDetails
|
||||||
? issueFilters?.displayFilters?.sub_issue
|
? issueFilters?.displayFilters?.sub_issue && moduleDetails.sub_issues
|
||||||
? moduleDetails.total_issues + moduleDetails.sub_issues
|
? moduleDetails.total_issues + moduleDetails.sub_issues
|
||||||
: moduleDetails.total_issues
|
: moduleDetails.total_issues
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -62,7 +62,7 @@ export const CycleEmptyState: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const isCompletedCycleSnapshotAvailable = !isEmpty(cycleDetails?.progress_snapshot ?? {});
|
const isCompletedCycleSnapshotAvailable = !isEmpty(cycleDetails?.progress_snapshot ?? {});
|
||||||
|
|
||||||
const isCompletedAndEmpty = isCompletedCycleSnapshotAvailable || cycleDetails?.status.toLowerCase() === "completed";
|
const isCompletedAndEmpty = isCompletedCycleSnapshotAvailable || cycleDetails?.status?.toLowerCase() === "completed";
|
||||||
|
|
||||||
const emptyStateType = isCompletedAndEmpty
|
const emptyStateType = isCompletedAndEmpty
|
||||||
? EmptyStateType.PROJECT_CYCLE_COMPLETED_NO_ISSUES
|
? EmptyStateType.PROJECT_CYCLE_COMPLETED_NO_ISSUES
|
||||||
|
@ -51,7 +51,8 @@ export const FilterCycle: React.FC<Props> = observer((props) => {
|
|||||||
else setItemsToRender(sortedOptions.length);
|
else setItemsToRender(sortedOptions.length);
|
||||||
};
|
};
|
||||||
|
|
||||||
const cycleStatus = (status: TCycleGroups) => (status ? status.toLocaleLowerCase() : "draft") as TCycleGroups;
|
const cycleStatus = (status: TCycleGroups | undefined) =>
|
||||||
|
(status ? status.toLocaleLowerCase() : "draft") as TCycleGroups;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -41,7 +41,7 @@ export const ModuleQuickActions: React.FC<Props> = observer((props) => {
|
|||||||
const isEditingAllowed =
|
const isEditingAllowed =
|
||||||
!!currentWorkspaceAllProjectsRole && currentWorkspaceAllProjectsRole[projectId] >= EUserProjectRoles.MEMBER;
|
!!currentWorkspaceAllProjectsRole && currentWorkspaceAllProjectsRole[projectId] >= EUserProjectRoles.MEMBER;
|
||||||
|
|
||||||
const moduleState = moduleDetails?.status.toLocaleLowerCase();
|
const moduleState = moduleDetails?.status?.toLocaleLowerCase();
|
||||||
const isInArchivableGroup = !!moduleState && ["completed", "cancelled"].includes(moduleState);
|
const isInArchivableGroup = !!moduleState && ["completed", "cancelled"].includes(moduleState);
|
||||||
|
|
||||||
const handleCopyText = (e: React.MouseEvent<HTMLButtonElement>) => {
|
const handleCopyText = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
@ -84,7 +84,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
const { setTrackElement, captureModuleEvent, captureEvent } = useEventTracker();
|
const { setTrackElement, captureModuleEvent, captureEvent } = useEventTracker();
|
||||||
const moduleDetails = getModuleById(moduleId);
|
const moduleDetails = getModuleById(moduleId);
|
||||||
|
|
||||||
const moduleState = moduleDetails?.status.toLocaleLowerCase();
|
const moduleState = moduleDetails?.status?.toLocaleLowerCase();
|
||||||
const isInArchivableGroup = !!moduleState && ["completed", "cancelled"].includes(moduleState);
|
const isInArchivableGroup = !!moduleState && ["completed", "cancelled"].includes(moduleState);
|
||||||
|
|
||||||
const { reset, control } = useForm({
|
const { reset, control } = useForm({
|
||||||
|
@ -13,6 +13,7 @@ import { ICycle, TCycleFilters } from "@plane/types";
|
|||||||
export const orderCycles = (cycles: ICycle[]): ICycle[] => {
|
export const orderCycles = (cycles: ICycle[]): ICycle[] => {
|
||||||
if (cycles.length === 0) return [];
|
if (cycles.length === 0) return [];
|
||||||
|
|
||||||
|
const acceptedStatuses = ["current", "upcoming", "draft"];
|
||||||
const STATUS_ORDER: {
|
const STATUS_ORDER: {
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
} = {
|
} = {
|
||||||
@ -21,10 +22,10 @@ export const orderCycles = (cycles: ICycle[]): ICycle[] => {
|
|||||||
draft: 3,
|
draft: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
let filteredCycles = cycles.filter((c) => c.status.toLowerCase() !== "completed");
|
let filteredCycles = cycles.filter((c) => acceptedStatuses.includes(c.status?.toLowerCase() ?? ""));
|
||||||
filteredCycles = sortBy(filteredCycles, [
|
filteredCycles = sortBy(filteredCycles, [
|
||||||
(c) => STATUS_ORDER[c.status.toLowerCase()],
|
(c) => STATUS_ORDER[c.status?.toLowerCase() ?? ""],
|
||||||
(c) => (c.status.toLowerCase() === "upcoming" ? c.start_date : c.name.toLowerCase()),
|
(c) => (c.status?.toLowerCase() === "upcoming" ? c.start_date : c.name.toLowerCase()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return filteredCycles;
|
return filteredCycles;
|
||||||
@ -41,7 +42,7 @@ export const shouldFilterCycle = (cycle: ICycle, filter: TCycleFilters): boolean
|
|||||||
Object.keys(filter).forEach((key) => {
|
Object.keys(filter).forEach((key) => {
|
||||||
const filterKey = key as keyof TCycleFilters;
|
const filterKey = key as keyof TCycleFilters;
|
||||||
if (filterKey === "status" && filter.status && filter.status.length > 0)
|
if (filterKey === "status" && filter.status && filter.status.length > 0)
|
||||||
fallsInFilters = fallsInFilters && filter.status.includes(cycle.status.toLowerCase());
|
fallsInFilters = fallsInFilters && filter.status.includes(cycle.status?.toLowerCase() ?? "");
|
||||||
if (filterKey === "start_date" && filter.start_date && filter.start_date.length > 0) {
|
if (filterKey === "start_date" && filter.start_date && filter.start_date.length > 0) {
|
||||||
const startDate = getDate(cycle.start_date);
|
const startDate = getDate(cycle.start_date);
|
||||||
filter.start_date.forEach((dateFilter) => {
|
filter.start_date.forEach((dateFilter) => {
|
||||||
|
@ -55,7 +55,7 @@ export const shouldFilterModule = (
|
|||||||
Object.keys(filters).forEach((key) => {
|
Object.keys(filters).forEach((key) => {
|
||||||
const filterKey = key as keyof TModuleFilters;
|
const filterKey = key as keyof TModuleFilters;
|
||||||
if (filterKey === "status" && filters.status && filters.status.length > 0)
|
if (filterKey === "status" && filters.status && filters.status.length > 0)
|
||||||
fallsInFilters = fallsInFilters && filters.status.includes(module.status.toLowerCase());
|
fallsInFilters = fallsInFilters && filters.status.includes(module.status?.toLowerCase() ?? "");
|
||||||
if (filterKey === "lead" && filters.lead && filters.lead.length > 0)
|
if (filterKey === "lead" && filters.lead && filters.lead.length > 0)
|
||||||
fallsInFilters = fallsInFilters && filters.lead.includes(`${module.lead_id}`);
|
fallsInFilters = fallsInFilters && filters.lead.includes(`${module.lead_id}`);
|
||||||
if (filterKey === "members" && filters.members && filters.members.length > 0) {
|
if (filterKey === "members" && filters.members && filters.members.length > 0) {
|
||||||
|
@ -256,7 +256,7 @@ export class CycleStore implements ICycleStore {
|
|||||||
(c) =>
|
(c) =>
|
||||||
c.project_id === projectId &&
|
c.project_id === projectId &&
|
||||||
!c.archived_at &&
|
!c.archived_at &&
|
||||||
c.status.toLowerCase() === "completed" &&
|
c.status?.toLowerCase() === "completed" &&
|
||||||
c.name.toLowerCase().includes(searchQuery.toLowerCase()) &&
|
c.name.toLowerCase().includes(searchQuery.toLowerCase()) &&
|
||||||
shouldFilterCycle(c, filters ?? {})
|
shouldFilterCycle(c, filters ?? {})
|
||||||
);
|
);
|
||||||
|
@ -380,7 +380,7 @@ export class ModulesStore implements IModuleStore {
|
|||||||
) => {
|
) => {
|
||||||
const originalModuleDetails = this.getModuleById(moduleId);
|
const originalModuleDetails = this.getModuleById(moduleId);
|
||||||
try {
|
try {
|
||||||
const linkModules = originalModuleDetails?.link_module.map((link) =>
|
const linkModules = originalModuleDetails?.link_module?.map((link) =>
|
||||||
link.id === linkId ? { ...link, ...data } : link
|
link.id === linkId ? { ...link, ...data } : link
|
||||||
);
|
);
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
@ -407,7 +407,7 @@ export class ModulesStore implements IModuleStore {
|
|||||||
deleteModuleLink = async (workspaceSlug: string, projectId: string, moduleId: string, linkId: string) =>
|
deleteModuleLink = async (workspaceSlug: string, projectId: string, moduleId: string, linkId: string) =>
|
||||||
await this.moduleService.deleteModuleLink(workspaceSlug, projectId, moduleId, linkId).then(() => {
|
await this.moduleService.deleteModuleLink(workspaceSlug, projectId, moduleId, linkId).then(() => {
|
||||||
const moduleDetails = this.getModuleById(moduleId);
|
const moduleDetails = this.getModuleById(moduleId);
|
||||||
const linkModules = moduleDetails?.link_module.filter((link) => link.id !== linkId);
|
const linkModules = moduleDetails?.link_module?.filter((link) => link.id !== linkId);
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
set(this.moduleMap, [moduleId, "link_module"], linkModules);
|
set(this.moduleMap, [moduleId, "link_module"], linkModules);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user