fix: breaking cycle issues and replacing router.push with Links (#3330)

* fix cycle creation and active cycle map

* minor fix in cycle store

* create cycle breaking fix

* replace last possible bits of router.push with Link

---------

Co-authored-by: Rahul R <rahulr@Rahuls-MacBook-Pro.local>
This commit is contained in:
rahulramesha 2024-01-08 19:20:42 +05:30 committed by sriram veeraghanta
parent 12a3392722
commit 1257a88089
14 changed files with 161 additions and 158 deletions

View File

@ -2,6 +2,7 @@ import { useRouter } from "next/router";
import { Command } from "cmdk";
// icons
import { SettingIcon } from "components/icons";
import Link from "next/link";
type Props = {
closePalette: () => void;
@ -13,48 +14,55 @@ export const CommandPaletteWorkspaceSettingsActions: React.FC<Props> = (props) =
const router = useRouter();
const { workspaceSlug } = router.query;
const redirect = (path: string) => {
closePalette();
router.push(path);
};
return (
<>
<Command.Item onSelect={() => redirect(`/${workspaceSlug}/settings`)} className="focus:outline-none">
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
General
</div>
<Command.Item onSelect={closePalette} className="focus:outline-none">
<Link href={`/${workspaceSlug}/settings`}>
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
General
</div>
</Link>
</Command.Item>
<Command.Item onSelect={() => redirect(`/${workspaceSlug}/settings/members`)} className="focus:outline-none">
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Members
</div>
<Command.Item onSelect={closePalette} className="focus:outline-none">
<Link href={`/${workspaceSlug}/settings/members`}>
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Members
</div>
</Link>
</Command.Item>
<Command.Item onSelect={() => redirect(`/${workspaceSlug}/settings/billing`)} className="focus:outline-none">
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Billing and Plans
</div>
<Command.Item onSelect={closePalette} className="focus:outline-none">
<Link href={`/${workspaceSlug}/settings/billing`}>
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Billing and Plans
</div>
</Link>
</Command.Item>
<Command.Item onSelect={() => redirect(`/${workspaceSlug}/settings/integrations`)} className="focus:outline-none">
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Integrations
</div>
<Command.Item onSelect={closePalette} className="focus:outline-none">
<Link href={`/${workspaceSlug}/settings/integrations`}>
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Integrations
</div>
</Link>
</Command.Item>
<Command.Item onSelect={() => redirect(`/${workspaceSlug}/settings/imports`)} className="focus:outline-none">
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Import
</div>
<Command.Item onSelect={closePalette} className="focus:outline-none">
<Link href={`/${workspaceSlug}/settings/imports`}>
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Import
</div>
</Link>
</Command.Item>
<Command.Item onSelect={() => redirect(`/${workspaceSlug}/settings/exports`)} className="focus:outline-none">
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Export
</div>
<Command.Item onSelect={closePalette} className="focus:outline-none">
<Link href={`/${workspaceSlug}/settings/exports`}>
<div className="flex items-center gap-2 text-custom-text-200">
<SettingIcon className="h-4 w-4 text-custom-text-200" />
Export
</div>
</Link>
</Command.Item>
</>
);

View File

@ -1,5 +1,5 @@
import React from "react";
import { eachDayOfInterval } from "date-fns";
import { eachDayOfInterval, isValid } from "date-fns";
// ui
import { LineGraph } from "components/ui";
// helpers
@ -47,7 +47,13 @@ const ProgressChart: React.FC<Props> = ({ distribution, startDate, endDate, tota
}));
const generateXAxisTickValues = () => {
const dates = eachDayOfInterval({ start: new Date(startDate), end: new Date(endDate) });
const start = new Date(startDate);
const end = new Date(endDate);
let dates: Date[] = [];
if (isValid(start) && isValid(end)) {
dates = eachDayOfInterval({ start, end });
}
const maxDates = 4;
const totalDates = dates.length;

View File

@ -33,6 +33,7 @@ import { truncateText } from "helpers/string.helper";
import { ICycle } from "@plane/types";
import { EIssuesStoreType } from "constants/issue";
import { ACTIVE_CYCLE_ISSUES } from "store/issue/cycle";
import { CYCLE_ISSUES_WITH_PARAMS } from "constants/fetch-keys";
const stateGroups = [
{
@ -73,7 +74,7 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
const { workspaceSlug, projectId } = props;
const {
issues: { issues },
issues: { issues, fetchActiveCycleIssues },
issueMap,
} = useIssues(EIssuesStoreType.CYCLE);
// store hooks
@ -99,13 +100,14 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
const activeCycle = currentProjectActiveCycleId ? getActiveCycleById(currentProjectActiveCycleId) : null;
const issueIds = issues?.[ACTIVE_CYCLE_ISSUES];
// useSWR(
// workspaceSlug && projectId && cycleId ? CYCLE_ISSUES_WITH_PARAMS(cycleId, { priority: "urgent,high" }) : null,
// workspaceSlug && projectId && cycleId
// ? () =>
// fetchActiveCycleIssues(workspaceSlug, projectId, )
// : null
// );
useSWR(
workspaceSlug && projectId && currentProjectActiveCycleId
? CYCLE_ISSUES_WITH_PARAMS(currentProjectActiveCycleId, { priority: "urgent,high" })
: null,
workspaceSlug && projectId && currentProjectActiveCycleId
? () => fetchActiveCycleIssues(workspaceSlug, projectId, currentProjectActiveCycleId)
: null
);
if (!activeCycle && isLoading)
return (
@ -382,9 +384,9 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
{issueIds ? (
issueIds.length > 0 ? (
issueIds.map((issue: any) => (
<div
<Link
key={issue.id}
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`)}
href={`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`}
className="flex cursor-pointer flex-wrap items-center justify-between gap-2 rounded-md border border-custom-border-200 bg-custom-background-90 px-3 py-1.5"
>
<div className="flex flex-col gap-1">
@ -427,7 +429,7 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
)}
</div>
</div>
</div>
</Link>
))
) : (
<div className="grid place-items-center text-center text-sm text-custom-text-200">

View File

@ -1,6 +1,7 @@
import { useCallback, useState } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import Link from "next/link";
// hooks
import {
useApplication,
@ -41,14 +42,11 @@ const CycleDropdownOption: React.FC<{ cycleId: string }> = ({ cycleId }) => {
if (!cycle) return null;
return (
<CustomMenu.MenuItem
key={cycle.id}
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`)}
>
<div className="flex items-center gap-1.5">
<CustomMenu.MenuItem key={cycle.id}>
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`} className="flex items-center gap-1.5">
<ContrastIcon className="h-3 w-3" />
{truncateText(cycle.name, 40)}
</div>
</Link>
</CustomMenu.MenuItem>
);
};

View File

@ -1,6 +1,7 @@
import { useCallback, useState } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import Link from "next/link";
// hooks
import {
useApplication,
@ -41,14 +42,14 @@ const ModuleDropdownOption: React.FC<{ moduleId: string }> = ({ moduleId }) => {
if (!moduleDetail) return null;
return (
<CustomMenu.MenuItem
key={moduleDetail.id}
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/modules/${moduleDetail.id}`)}
>
<div className="flex items-center gap-1.5">
<CustomMenu.MenuItem key={moduleDetail.id}>
<Link
href={`/${workspaceSlug}/projects/${projectId}/modules/${moduleDetail.id}`}
className="flex items-center gap-1.5"
>
<DiceIcon className="h-3 w-3" />
{truncateText(moduleDetail.name, 40)}
</div>
</Link>
</CustomMenu.MenuItem>
);
};

View File

@ -2,6 +2,7 @@ import { useCallback } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { Plus } from "lucide-react";
import Link from "next/link";
// hooks
import {
useApplication,
@ -154,14 +155,14 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
if (!view) return;
return (
<CustomMenu.MenuItem
key={viewId}
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/views/${viewId}`)}
>
<div className="flex items-center gap-1.5">
<CustomMenu.MenuItem key={viewId}>
<Link
href={`/${workspaceSlug}/projects/${projectId}/views/${viewId}`}
className="flex items-center gap-1.5"
>
<PhotoFilterIcon height={12} width={12} />
{truncateText(view.name, 40)}
</div>
</Link>
</CustomMenu.MenuItem>
);
})}

View File

@ -2,6 +2,7 @@ import React from "react";
import Image from "next/image";
import { useRouter } from "next/router";
import { ArchiveRestore, Clock, MessageSquare, User2 } from "lucide-react";
import Link from "next/link";
// hooks
import useToast from "hooks/use-toast";
// icons
@ -10,17 +11,14 @@ import { ArchiveIcon, CustomMenu, Tooltip } from "@plane/ui";
import { snoozeOptions } from "constants/notification";
// helper
import { replaceUnderscoreIfSnakeCase, truncateText, stripAndTruncateHTML } from "helpers/string.helper";
import {
calculateTimeAgo,
renderFormattedTime,
renderFormattedDate,
} from "helpers/date-time.helper";
import { calculateTimeAgo, renderFormattedTime, renderFormattedDate } from "helpers/date-time.helper";
// type
import type { IUserNotification } from "@plane/types";
type NotificationCardProps = {
notification: IUserNotification;
isSnoozedTabOpen: boolean;
closePopover: () => void;
markNotificationReadStatus: (notificationId: string) => Promise<void>;
markNotificationReadStatusToggle: (notificationId: string) => Promise<void>;
markNotificationArchivedStatus: (notificationId: string) => Promise<void>;
@ -32,6 +30,7 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
const {
notification,
isSnoozedTabOpen,
closePopover,
markNotificationReadStatus,
markNotificationReadStatusToggle,
markNotificationArchivedStatus,
@ -47,15 +46,14 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
if (isSnoozedTabOpen && new Date(notification.snoozed_till!) < new Date()) return null;
return (
<div
<Link
onClick={() => {
markNotificationReadStatus(notification.id);
router.push(
`/${workspaceSlug}/projects/${notification.project}/${
notification.data.issue_activity.field === "archived_at" ? "archived-issues" : "issues"
}/${notification.data.issue.id}`
);
closePopover();
}}
href={`/${workspaceSlug}/projects/${notification.project}/${
notification.data.issue_activity.field === "archived_at" ? "archived-issues" : "issues"
}/${notification.data.issue.id}`}
className={`group relative flex w-full cursor-pointer items-center gap-4 p-3 pl-6 ${
notification.read_at === null ? "bg-custom-primary-70/5" : "hover:bg-custom-background-200"
}`}
@ -149,7 +147,8 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
<p className="flex flex-shrink-0 items-center justify-end gap-x-1 text-custom-text-300">
<Clock className="h-4 w-4" />
<span>
Till {renderFormattedDate(notification.snoozed_till)}, {renderFormattedTime(notification.snoozed_till, '12-hour')}
Till {renderFormattedDate(notification.snoozed_till)},{" "}
{renderFormattedTime(notification.snoozed_till, "12-hour")}
</span>
</p>
) : (
@ -195,6 +194,8 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
type="button"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
item.onClick();
}}
key={item.id}
@ -204,7 +205,6 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
</button>
</Tooltip>
))}
<Tooltip tooltipContent="Snooze">
<CustomMenu
className="flex items-center"
@ -223,6 +223,7 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
key={item.label}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
if (!item.value) {
setSelectedNotificationForSnooze(notification.id);
@ -243,6 +244,6 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
</CustomMenu>
</Tooltip>
</div>
</div>
</Link>
);
};

View File

@ -119,6 +119,7 @@ export const NotificationPopover = observer(() => {
<NotificationCard
key={notification.id}
isSnoozedTabOpen={snoozed}
closePopover={closePopover}
notification={notification}
markNotificationArchivedStatus={markNotificationArchivedStatus}
markNotificationReadStatus={markNotificationAsRead}

View File

@ -2,6 +2,7 @@ import React, { useState } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { LinkIcon, Lock, Pencil, Star } from "lucide-react";
import Link from "next/link";
// hooks
import { useProject } from "hooks/store";
import useToast from "hooks/use-toast";
@ -74,7 +75,7 @@ export const ProjectCard: React.FC<ProjectCardProps> = observer((props) => {
});
};
const projectMembersIds = project.members.map((member) => member.member_id);
const projectMembersIds = project.members?.map((member) => member.member_id);
return (
<>
@ -178,7 +179,7 @@ export const ProjectCard: React.FC<ProjectCardProps> = observer((props) => {
}
position="top"
>
{projectMembersIds.length > 0 ? (
{projectMembersIds && projectMembersIds.length > 0 ? (
<div className="flex cursor-pointer items-center gap-2 text-custom-text-200">
<AvatarGroup showTooltip={false}>
{projectMembersIds.map((memberId) => {
@ -195,17 +196,15 @@ export const ProjectCard: React.FC<ProjectCardProps> = observer((props) => {
)}
</Tooltip>
{(isOwner || isMember) && (
<button
<Link
className="flex items-center justify-center rounded p-1 text-custom-text-400 hover:bg-custom-background-80 hover:text-custom-text-200"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
router.push(`/${workspaceSlug}/projects/${project.id}/settings`);
}}
href={`/${workspaceSlug}/projects/${project.id}/settings`}
>
<Pencil className="h-3.5 w-3.5" />
</button>
</Link>
)}
{!project.is_member ? (

View File

@ -45,28 +45,39 @@ type EmptySpaceItemProps = {
title: string;
description?: React.ReactNode | string;
Icon: any;
action: () => void;
action?: () => void;
href?: string;
};
const EmptySpaceItem: React.FC<EmptySpaceItemProps> = ({ title, description, Icon, action }) => (
<>
<li className="cursor-pointer" onClick={action} role="button">
<div className={`group relative flex ${description ? "items-start" : "items-center"} space-x-3 py-4`}>
<div className="flex-shrink-0">
<span className="inline-flex h-10 w-10 items-center justify-center rounded-lg bg-custom-primary">
<Icon className="h-6 w-6 text-white" aria-hidden="true" />
</span>
</div>
<div className="min-w-0 flex-1 text-custom-text-200">
<div className="text-sm font-medium group-hover:text-custom-text-100">{title}</div>
{description ? <div className="text-sm">{description}</div> : null}
</div>
<div className="flex-shrink-0 self-center">
<ChevronRight className="h-5 w-5 text-custom-text-200 group-hover:text-custom-text-100" aria-hidden="true" />
</div>
const EmptySpaceItem: React.FC<EmptySpaceItemProps> = ({ title, description, Icon, action, href }) => {
let spaceItem = (
<div className={`group relative flex ${description ? "items-start" : "items-center"} space-x-3 py-4`}>
<div className="flex-shrink-0">
<span className="inline-flex h-10 w-10 items-center justify-center rounded-lg bg-custom-primary">
<Icon className="h-6 w-6 text-white" aria-hidden="true" />
</span>
</div>
</li>
</>
);
<div className="min-w-0 flex-1 text-custom-text-200">
<div className="text-sm font-medium group-hover:text-custom-text-100">{title}</div>
{description ? <div className="text-sm">{description}</div> : null}
</div>
<div className="flex-shrink-0 self-center">
<ChevronRight className="h-5 w-5 text-custom-text-200 group-hover:text-custom-text-100" aria-hidden="true" />
</div>
</div>
);
if (href) {
spaceItem = <Link href={href}>{spaceItem}</Link>;
}
return (
<>
<li className="cursor-pointer" onClick={action} role="button">
{spaceItem}
</li>
</>
);
};
export { EmptySpace, EmptySpaceItem };

View File

@ -1,6 +1,7 @@
import { FC, ReactNode } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import Link from "next/link";
// hooks
import { useUser } from "hooks/store";
// components
@ -31,14 +32,12 @@ export const ProjectSettingLayout: FC<IProjectSettingLayout> = observer((props)
<NotAuthorizedView
type="project"
actionButton={
<Button
variant="primary"
size="md"
prependIcon={<LayersIcon />}
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/issues`)}
>
Go to issues
</Button>
//TODO: Create a new component called Button Link to handle such scenarios
<Link href={`/${workspaceSlug}/projects/${projectId}/issues`}>
<Button variant="primary" size="md" prependIcon={<LayersIcon />}>
Go to issues
</Button>
</Link>
}
/>
) : (

View File

@ -3,6 +3,7 @@ import { useRouter } from "next/router";
import Image from "next/image";
import { useTheme } from "next-themes";
import { observer } from "mobx-react-lite";
import Link from "next/link";
// hooks
import { useUser } from "hooks/store";
// layouts
@ -39,9 +40,9 @@ const CreateWorkspacePage: NextPageWithLayout = observer(() => {
<div className="flex h-full flex-col gap-y-2 overflow-hidden sm:flex-row sm:gap-y-0">
<div className="relative h-1/6 flex-shrink-0 sm:w-2/12 md:w-3/12 lg:w-1/5">
<div className="absolute left-0 top-1/2 h-[0.5px] w-full -translate-y-1/2 border-b-[0.5px] border-custom-border-200 sm:left-1/2 sm:top-0 sm:h-screen sm:w-[0.5px] sm:-translate-x-1/2 sm:translate-y-0 sm:border-r-[0.5px] md:left-1/3" />
<button
<Link
className="absolute left-5 top-1/2 grid -translate-y-1/2 place-items-center bg-custom-background-100 px-3 sm:left-1/2 sm:top-12 sm:-translate-x-[15px] sm:translate-y-0 sm:px-0 sm:py-5 md:left-1/3"
onClick={() => router.push("/")}
href="/"
>
<div className="h-[30px] w-[133px]">
{theme === "light" ? (
@ -50,7 +51,7 @@ const CreateWorkspacePage: NextPageWithLayout = observer(() => {
<Image src={WhiteHorizontalLogo} alt="Plane white logo" />
)}
</div>
</button>
</Link>
<div className="absolute right-4 top-1/4 -translate-y-1/2 text-sm text-custom-text-100 sm:fixed sm:right-16 sm:top-12 sm:translate-y-0 sm:py-5">
{currentUser?.email}
</div>

View File

@ -81,7 +81,7 @@ const WorkspaceInvitationPage: NextPageWithLayout = observer(() => {
title={`You are already a member of ${invitationDetail.workspace.name}`}
description="Your workspace is where you'll create projects, collaborate on your issues, and organize different streams of work in your Plane account."
>
<EmptySpaceItem Icon={Boxes} title="Continue to Dashboard" action={() => router.push("/")} />
<EmptySpaceItem Icon={Boxes} title="Continue to Dashboard" href="/" />
</EmptySpace>
</>
) : (
@ -103,35 +103,15 @@ const WorkspaceInvitationPage: NextPageWithLayout = observer(() => {
link={{ text: "Or start from an empty project", href: "/" }}
>
{!currentUser ? (
<EmptySpaceItem
Icon={User2}
title="Sign in to continue"
action={() => {
router.push("/");
}}
/>
<EmptySpaceItem Icon={User2} title="Sign in to continue" href="/" />
) : (
<EmptySpaceItem
Icon={Boxes}
title="Continue to Dashboard"
action={() => {
router.push("/");
}}
/>
<EmptySpaceItem Icon={Boxes} title="Continue to Dashboard" href="/" />
)}
<EmptySpaceItem
Icon={Star}
title="Star us on GitHub"
action={() => {
router.push("https://github.com/makeplane");
}}
/>
<EmptySpaceItem Icon={Star} title="Star us on GitHub" href="https://github.com/makeplane" />
<EmptySpaceItem
Icon={Share2}
title="Join our community of active creators"
action={() => {
router.push("https://discord.com/invite/8SR2N9PAcJ");
}}
href="https://discord.com/invite/8SR2N9PAcJ"
/>
</EmptySpace>
) : (

View File

@ -14,7 +14,7 @@ import { CycleService } from "services/cycle.service";
export interface ICycleStore {
// observables
cycleMap: Record<string, ICycle>;
activeCycleMap: Record<string, ICycle>; // TODO: Merge these two into single map
activeCycleIdMap: Record<string, boolean>;
// computed
currentProjectCycleIds: string[] | null;
currentProjectCompletedCycleIds: string[] | null;
@ -49,7 +49,7 @@ export interface ICycleStore {
export class CycleStore implements ICycleStore {
// observables
cycleMap: Record<string, ICycle> = {};
activeCycleMap: Record<string, ICycle> = {};
activeCycleIdMap: Record<string, boolean> = {};
// root store
rootStore;
// services
@ -61,7 +61,7 @@ export class CycleStore implements ICycleStore {
makeObservable(this, {
// observables
cycleMap: observable,
activeCycleMap: observable,
activeCycleIdMap: observable,
// computed
currentProjectCycleIds: computed,
currentProjectCompletedCycleIds: computed,
@ -168,8 +168,8 @@ export class CycleStore implements ICycleStore {
get currentProjectActiveCycleId() {
const projectId = this.rootStore.app.router.projectId;
if (!projectId) return null;
const activeCycle = Object.keys(this.activeCycleMap ?? {}).find(
(cycleId) => this.activeCycleMap?.[cycleId]?.project === projectId
const activeCycle = Object.keys(this.activeCycleIdMap ?? {}).find(
(cycleId) => this.cycleMap?.[cycleId]?.project === projectId
);
return activeCycle || null;
}
@ -186,7 +186,8 @@ export class CycleStore implements ICycleStore {
* @param cycleId
* @returns
*/
getActiveCycleById = (cycleId: string): ICycle | null => this.activeCycleMap?.[cycleId] ?? null;
getActiveCycleById = (cycleId: string): ICycle | null =>
this.activeCycleIdMap?.[cycleId] && this.cycleMap?.[cycleId] ? this.cycleMap?.[cycleId] : null;
/**
* @description returns list of cycle ids of the project id passed as argument
@ -235,7 +236,8 @@ export class CycleStore implements ICycleStore {
await this.cycleService.getCyclesWithParams(workspaceSlug, projectId, "current").then((response) => {
runInAction(() => {
response.forEach((cycle) => {
set(this.activeCycleMap, [cycle.id], cycle);
set(this.activeCycleIdMap, [cycle.id], true);
set(this.cycleMap, [cycle.id], cycle);
});
});
return response;
@ -252,7 +254,6 @@ export class CycleStore implements ICycleStore {
await this.cycleService.getCycleDetails(workspaceSlug, projectId, cycleId).then((response) => {
runInAction(() => {
set(this.cycleMap, [response.id], { ...this.cycleMap?.[response.id], ...response });
set(this.activeCycleMap, [response.id], { ...this.activeCycleMap?.[response.id], ...response });
});
return response;
});
@ -268,7 +269,6 @@ export class CycleStore implements ICycleStore {
await this.cycleService.createCycle(workspaceSlug, projectId, data).then((response) => {
runInAction(() => {
set(this.cycleMap, [response.id], response);
set(this.activeCycleMap, [response.id], response);
});
return response;
});
@ -285,7 +285,6 @@ export class CycleStore implements ICycleStore {
try {
runInAction(() => {
set(this.cycleMap, [cycleId], { ...this.cycleMap?.[cycleId], ...data });
set(this.activeCycleMap, [cycleId], { ...this.activeCycleMap?.[cycleId], ...data });
});
const response = await this.cycleService.patchCycle(workspaceSlug, projectId, cycleId, data);
return response;
@ -307,7 +306,7 @@ export class CycleStore implements ICycleStore {
await this.cycleService.deleteCycle(workspaceSlug, projectId, cycleId).then(() => {
runInAction(() => {
delete this.cycleMap[cycleId];
delete this.activeCycleMap[cycleId];
delete this.activeCycleIdMap[cycleId];
});
});
@ -324,7 +323,6 @@ export class CycleStore implements ICycleStore {
try {
runInAction(() => {
if (currentCycle) set(this.cycleMap, [cycleId, "is_favorite"], true);
if (currentActiveCycle) set(this.activeCycleMap, [cycleId, "is_favorite"], true);
});
// updating through api.
const response = await this.cycleService.addCycleToFavorites(workspaceSlug, projectId, { cycle: cycleId });
@ -332,7 +330,6 @@ export class CycleStore implements ICycleStore {
} catch (error) {
runInAction(() => {
if (currentCycle) set(this.cycleMap, [cycleId, "is_favorite"], false);
if (currentActiveCycle) set(this.activeCycleMap, [cycleId, "is_favorite"], false);
});
throw error;
}
@ -351,14 +348,12 @@ export class CycleStore implements ICycleStore {
try {
runInAction(() => {
if (currentCycle) set(this.cycleMap, [cycleId, "is_favorite"], false);
if (currentActiveCycle) set(this.activeCycleMap, [cycleId, "is_favorite"], false);
});
const response = await this.cycleService.removeCycleFromFavorites(workspaceSlug, projectId, cycleId);
return response;
} catch (error) {
runInAction(() => {
if (currentCycle) set(this.cycleMap, [cycleId, "is_favorite"], true);
if (currentActiveCycle) set(this.activeCycleMap, [cycleId, "is_favorite"], true);
});
throw error;
}