chore: cycles endpoint updated and code refactor (#1135)

* chore: cycles endpoint updated and code refactor

* chore: incomplete cycle endpoint updated

* chore: code refactor
This commit is contained in:
Anmol Singh Bhatia 2023-05-26 15:38:56 +05:30 committed by GitHub
parent 4ce0ac6ea1
commit 394f0bf555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 226 additions and 462 deletions

View File

@ -40,20 +40,14 @@ import {
} from "helpers/date-time.helper"; } from "helpers/date-time.helper";
import { truncateText } from "helpers/string.helper"; import { truncateText } from "helpers/string.helper";
// types // types
import { import { ICycle, IIssue } from "types";
CompletedCyclesResponse,
CurrentAndUpcomingCyclesResponse,
DraftCyclesResponse,
ICycle,
IIssue,
} from "types";
// fetch-keys // fetch-keys
import { import {
CYCLE_COMPLETE_LIST, CYCLE_COMPLETE_LIST,
CYCLE_CURRENT_AND_UPCOMING_LIST, CYCLE_CURRENT_LIST,
CYCLE_DETAILS,
CYCLE_DRAFT_LIST, CYCLE_DRAFT_LIST,
CYCLE_ISSUES, CYCLE_ISSUES,
CYCLE_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
type TSingleStatProps = { type TSingleStatProps = {
@ -111,51 +105,18 @@ export const ActiveCycleDetails: React.FC<TSingleStatProps> = ({ cycle, isComple
const handleAddToFavorites = () => { const handleAddToFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return; if (!workspaceSlug || !projectId || !cycle) return;
switch (cycleStatus) { mutate<ICycle[]>(
case "current": CYCLE_CURRENT_LIST(projectId as string),
case "upcoming": (prevData) =>
mutate<CurrentAndUpcomingCyclesResponse>( (prevData ?? []).map((c) => ({
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
(prevData) => ({
current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
...c, ...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite, is_favorite: c.id === cycle.id ? true : c.is_favorite,
})), })),
upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false false
); );
break;
case "completed":
mutate<CompletedCyclesResponse>(
CYCLE_COMPLETE_LIST(projectId as string),
(prevData) => ({
completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false
);
break;
case "draft":
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => ({
draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false
);
break;
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => (prevData: any) =>
(prevData ?? []).map((c: any) => ({ (prevData ?? []).map((c: any) => ({
...c, ...c,
@ -180,51 +141,18 @@ export const ActiveCycleDetails: React.FC<TSingleStatProps> = ({ cycle, isComple
const handleRemoveFromFavorites = () => { const handleRemoveFromFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return; if (!workspaceSlug || !projectId || !cycle) return;
switch (cycleStatus) { mutate<ICycle[]>(
case "current": CYCLE_CURRENT_LIST(projectId as string),
case "upcoming": (prevData) =>
mutate<CurrentAndUpcomingCyclesResponse>( (prevData ?? []).map((c) => ({
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
(prevData) => ({
current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
...c, ...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite, is_favorite: c.id === cycle.id ? false : c.is_favorite,
})), })),
upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false false
); );
break;
case "completed":
mutate<CompletedCyclesResponse>(
CYCLE_COMPLETE_LIST(projectId as string),
(prevData) => ({
completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false
);
break;
case "draft":
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => ({
draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false
);
break;
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => (prevData: any) =>
(prevData ?? []).map((c: any) => ({ (prevData ?? []).map((c: any) => ({
...c, ...c,

View File

@ -38,7 +38,10 @@ export const CompletedCycles: React.FC<CompletedCyclesListProps> = ({
const { data: completedCycles } = useSWR( const { data: completedCycles } = useSWR(
workspaceSlug && projectId ? CYCLE_COMPLETE_LIST(projectId as string) : null, workspaceSlug && projectId ? CYCLE_COMPLETE_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cyclesService.getCompletedCycles(workspaceSlug as string, projectId as string) ? () =>
cyclesService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "completed",
})
: null : null
); );
@ -64,7 +67,7 @@ export const CompletedCycles: React.FC<CompletedCyclesListProps> = ({
data={selectedCycleForDelete} data={selectedCycleForDelete}
/> />
{completedCycles ? ( {completedCycles ? (
completedCycles.completed_cycles.length > 0 ? ( completedCycles.length > 0 ? (
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<div className="flex items-center gap-2 text-sm text-brand-secondary"> <div className="flex items-center gap-2 text-sm text-brand-secondary">
<ExclamationIcon <ExclamationIcon
@ -76,7 +79,7 @@ export const CompletedCycles: React.FC<CompletedCyclesListProps> = ({
</div> </div>
{cycleView === "list" && ( {cycleView === "list" && (
<div> <div>
{completedCycles.completed_cycles.map((cycle) => ( {completedCycles.map((cycle) => (
<div className="hover:bg-brand-surface-2"> <div className="hover:bg-brand-surface-2">
<div className="flex flex-col border-brand-base"> <div className="flex flex-col border-brand-base">
<SingleCycleList <SingleCycleList
@ -93,7 +96,7 @@ export const CompletedCycles: React.FC<CompletedCyclesListProps> = ({
)} )}
{cycleView === "board" && ( {cycleView === "board" && (
<div className="grid grid-cols-1 gap-9 md:grid-cols-2 lg:grid-cols-3"> <div className="grid grid-cols-1 gap-9 md:grid-cols-2 lg:grid-cols-3">
{completedCycles.completed_cycles.map((cycle) => ( {completedCycles.map((cycle) => (
<SingleCycleCard <SingleCycleCard
key={cycle.id} key={cycle.id}
cycle={cycle} cycle={cycle}

View File

@ -18,26 +18,23 @@ import { EmptyState, Loader } from "components/ui";
import { ChartBarIcon, ListBulletIcon, Squares2X2Icon } from "@heroicons/react/24/outline"; import { ChartBarIcon, ListBulletIcon, Squares2X2Icon } from "@heroicons/react/24/outline";
import emptyCycle from "public/empty-state/empty-cycle.svg"; import emptyCycle from "public/empty-state/empty-cycle.svg";
// types // types
import { import { SelectCycleType, ICycle } from "types";
SelectCycleType,
ICycle,
CurrentAndUpcomingCyclesResponse,
DraftCyclesResponse,
} from "types";
type Props = { type Props = {
setSelectedCycle: React.Dispatch<React.SetStateAction<SelectCycleType>>; setSelectedCycle: React.Dispatch<React.SetStateAction<SelectCycleType>>;
setCreateUpdateCycleModal: React.Dispatch<React.SetStateAction<boolean>>; setCreateUpdateCycleModal: React.Dispatch<React.SetStateAction<boolean>>;
cyclesCompleteList: ICycle[] | undefined; cyclesCompleteList: ICycle[] | undefined;
currentAndUpcomingCycles: CurrentAndUpcomingCyclesResponse | undefined; currentCycle: ICycle[] | undefined;
draftCycles: DraftCyclesResponse | undefined; upcomingCycles: ICycle[] | undefined;
draftCycles: ICycle[] | undefined;
}; };
export const CyclesView: React.FC<Props> = ({ export const CyclesView: React.FC<Props> = ({
setSelectedCycle, setSelectedCycle,
setCreateUpdateCycleModal, setCreateUpdateCycleModal,
cyclesCompleteList, cyclesCompleteList,
currentAndUpcomingCycles, currentCycle,
upcomingCycles,
draftCycles, draftCycles,
}) => { }) => {
const { storedValue: cycleTab, setValue: setCycleTab } = useLocalStorage("cycleTab", "All"); const { storedValue: cycleTab, setValue: setCycleTab } = useLocalStorage("cycleTab", "All");
@ -182,8 +179,8 @@ export const CyclesView: React.FC<Props> = ({
</Tab.Panel> </Tab.Panel>
{cyclesView !== "gantt_chart" && ( {cyclesView !== "gantt_chart" && (
<Tab.Panel as="div" className="mt-7 space-y-5"> <Tab.Panel as="div" className="mt-7 space-y-5">
{currentAndUpcomingCycles?.current_cycle?.[0] ? ( {currentCycle?.[0] ? (
<ActiveCycleDetails cycle={currentAndUpcomingCycles?.current_cycle?.[0]} /> <ActiveCycleDetails cycle={currentCycle?.[0]} />
) : ( ) : (
<EmptyState <EmptyState
type="cycle" type="cycle"
@ -197,7 +194,7 @@ export const CyclesView: React.FC<Props> = ({
<Tab.Panel as="div" className="mt-7 space-y-5 h-full overflow-y-auto"> <Tab.Panel as="div" className="mt-7 space-y-5 h-full overflow-y-auto">
{cyclesView === "list" && ( {cyclesView === "list" && (
<AllCyclesList <AllCyclesList
cycles={currentAndUpcomingCycles?.upcoming_cycle} cycles={upcomingCycles}
setCreateUpdateCycleModal={setCreateUpdateCycleModal} setCreateUpdateCycleModal={setCreateUpdateCycleModal}
setSelectedCycle={setSelectedCycle} setSelectedCycle={setSelectedCycle}
type="upcoming" type="upcoming"
@ -205,14 +202,14 @@ export const CyclesView: React.FC<Props> = ({
)} )}
{cyclesView === "board" && ( {cyclesView === "board" && (
<AllCyclesBoard <AllCyclesBoard
cycles={currentAndUpcomingCycles?.upcoming_cycle} cycles={upcomingCycles}
setCreateUpdateCycleModal={setCreateUpdateCycleModal} setCreateUpdateCycleModal={setCreateUpdateCycleModal}
setSelectedCycle={setSelectedCycle} setSelectedCycle={setSelectedCycle}
type="upcoming" type="upcoming"
/> />
)} )}
{cyclesView === "gantt_chart" && ( {cyclesView === "gantt_chart" && (
<CyclesListGanttChartView cycles={currentAndUpcomingCycles?.upcoming_cycle ?? []} /> <CyclesListGanttChartView cycles={upcomingCycles ?? []} />
)} )}
</Tab.Panel> </Tab.Panel>
<Tab.Panel as="div" className="mt-7 space-y-5"> <Tab.Panel as="div" className="mt-7 space-y-5">
@ -226,7 +223,7 @@ export const CyclesView: React.FC<Props> = ({
<Tab.Panel as="div" className="mt-7 space-y-5"> <Tab.Panel as="div" className="mt-7 space-y-5">
{cyclesView === "list" && ( {cyclesView === "list" && (
<AllCyclesList <AllCyclesList
cycles={draftCycles?.draft_cycles} cycles={draftCycles}
setCreateUpdateCycleModal={setCreateUpdateCycleModal} setCreateUpdateCycleModal={setCreateUpdateCycleModal}
setSelectedCycle={setSelectedCycle} setSelectedCycle={setSelectedCycle}
type="draft" type="draft"
@ -234,7 +231,7 @@ export const CyclesView: React.FC<Props> = ({
)} )}
{cyclesView === "board" && ( {cyclesView === "board" && (
<AllCyclesBoard <AllCyclesBoard
cycles={draftCycles?.draft_cycles} cycles={draftCycles}
setCreateUpdateCycleModal={setCreateUpdateCycleModal} setCreateUpdateCycleModal={setCreateUpdateCycleModal}
setSelectedCycle={setSelectedCycle} setSelectedCycle={setSelectedCycle}
type="draft" type="draft"

View File

@ -14,12 +14,7 @@ import { DangerButton, SecondaryButton } from "components/ui";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// types // types
import type { import type { ICycle } from "types";
CompletedCyclesResponse,
CurrentAndUpcomingCyclesResponse,
DraftCyclesResponse,
ICycle,
} from "types";
type TConfirmCycleDeletionProps = { type TConfirmCycleDeletionProps = {
isOpen: boolean; isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>; setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
@ -28,10 +23,10 @@ type TConfirmCycleDeletionProps = {
// fetch-keys // fetch-keys
import { import {
CYCLE_COMPLETE_LIST, CYCLE_COMPLETE_LIST,
CYCLE_CURRENT_AND_UPCOMING_LIST, CYCLE_CURRENT_LIST,
CYCLE_DETAILS,
CYCLE_DRAFT_LIST, CYCLE_DRAFT_LIST,
CYCLE_LIST, CYCLE_LIST,
CYCLE_UPCOMING_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
import { getDateRangeStatus } from "helpers/date-time.helper"; import { getDateRangeStatus } from "helpers/date-time.helper";
@ -60,63 +55,28 @@ export const DeleteCycleModal: React.FC<TConfirmCycleDeletionProps> = ({
await cycleService await cycleService
.deleteCycle(workspaceSlug as string, data.project, data.id) .deleteCycle(workspaceSlug as string, data.project, data.id)
.then(() => { .then(() => {
switch (getDateRangeStatus(data.start_date, data.end_date)) { const cycleType = getDateRangeStatus(data.start_date, data.end_date);
case "completed": const fetchKey =
mutate<CompletedCyclesResponse>( cycleType === "current"
CYCLE_COMPLETE_LIST(projectId as string), ? CYCLE_CURRENT_LIST(projectId as string)
: cycleType === "upcoming"
? CYCLE_UPCOMING_LIST(projectId as string)
: cycleType === "completed"
? CYCLE_COMPLETE_LIST(projectId as string)
: CYCLE_DRAFT_LIST(projectId as string);
mutate<ICycle[]>(
fetchKey,
(prevData) => { (prevData) => {
if (!prevData) return; if (!prevData) return;
return { return prevData.filter((cycle) => cycle.id !== data?.id);
completed_cycles: prevData.completed_cycles?.filter(
(cycle) => cycle.id !== data?.id
),
};
}, },
false false
); );
break;
case "current":
mutate<CurrentAndUpcomingCyclesResponse>(
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
(prevData) => {
if (!prevData) return;
return {
current_cycle: prevData.current_cycle?.filter((c) => c.id !== data?.id),
upcoming_cycle: prevData.upcoming_cycle,
};
},
false
);
break;
case "upcoming":
mutate<CurrentAndUpcomingCyclesResponse>(
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
(prevData) => {
if (!prevData) return;
return {
current_cycle: prevData.current_cycle,
upcoming_cycle: prevData.upcoming_cycle?.filter((c) => c.id !== data?.id),
};
},
false
);
break;
default:
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => {
if (!prevData) return;
return {
draft_cycles: prevData.draft_cycles?.filter((cycle) => cycle.id !== data?.id),
};
},
false
);
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => { (prevData: any) => {
if (!prevData) return; if (!prevData) return;
return prevData.filter((cycle: any) => cycle.id !== data?.id); return prevData.filter((cycle: any) => cycle.id !== data?.id);

View File

@ -19,10 +19,11 @@ import type { ICycle } from "types";
// fetch keys // fetch keys
import { import {
CYCLE_COMPLETE_LIST, CYCLE_COMPLETE_LIST,
CYCLE_CURRENT_AND_UPCOMING_LIST, CYCLE_CURRENT_LIST,
CYCLE_DETAILS,
CYCLE_DRAFT_LIST, CYCLE_DRAFT_LIST,
CYCLE_INCOMPLETE_LIST, CYCLE_INCOMPLETE_LIST,
CYCLE_LIST,
CYCLE_UPCOMING_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
type CycleModalProps = { type CycleModalProps = {
@ -50,16 +51,16 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
mutate(CYCLE_COMPLETE_LIST(projectId as string)); mutate(CYCLE_COMPLETE_LIST(projectId as string));
break; break;
case "current": case "current":
mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); mutate(CYCLE_CURRENT_LIST(projectId as string));
break; break;
case "upcoming": case "upcoming":
mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); mutate(CYCLE_UPCOMING_LIST(projectId as string));
break; break;
default: default:
mutate(CYCLE_DRAFT_LIST(projectId as string)); mutate(CYCLE_DRAFT_LIST(projectId as string));
} }
mutate(CYCLE_INCOMPLETE_LIST(projectId as string)); mutate(CYCLE_INCOMPLETE_LIST(projectId as string));
mutate(CYCLE_DETAILS(projectId as string)); mutate(CYCLE_LIST(projectId as string));
handleClose(); handleClose();
setToastAlert({ setToastAlert({
@ -86,15 +87,15 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
mutate(CYCLE_COMPLETE_LIST(projectId as string)); mutate(CYCLE_COMPLETE_LIST(projectId as string));
break; break;
case "current": case "current":
mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); mutate(CYCLE_CURRENT_LIST(projectId as string));
break; break;
case "upcoming": case "upcoming":
mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); mutate(CYCLE_UPCOMING_LIST(projectId as string));
break; break;
default: default:
mutate(CYCLE_DRAFT_LIST(projectId as string)); mutate(CYCLE_DRAFT_LIST(projectId as string));
} }
mutate(CYCLE_DETAILS(projectId as string)); mutate(CYCLE_LIST(projectId as string));
if ( if (
getDateRangeStatus(data?.start_date, data?.end_date) != getDateRangeStatus(data?.start_date, data?.end_date) !=
getDateRangeStatus(res.start_date, res.end_date) getDateRangeStatus(res.start_date, res.end_date)
@ -104,10 +105,10 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
mutate(CYCLE_COMPLETE_LIST(projectId as string)); mutate(CYCLE_COMPLETE_LIST(projectId as string));
break; break;
case "current": case "current":
mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); mutate(CYCLE_CURRENT_LIST(projectId as string));
break; break;
case "upcoming": case "upcoming":
mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string)); mutate(CYCLE_UPCOMING_LIST(projectId as string));
break; break;
default: default:
mutate(CYCLE_DRAFT_LIST(projectId as string)); mutate(CYCLE_DRAFT_LIST(projectId as string));

View File

@ -38,7 +38,10 @@ export const CycleSelect: React.FC<IssueCycleSelectProps> = ({
const { data: cycles } = useSWR( const { data: cycles } = useSWR(
workspaceSlug && projectId ? CYCLE_LIST(projectId) : null, workspaceSlug && projectId ? CYCLE_LIST(projectId) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cycleServices.getCycles(workspaceSlug as string, projectId) ? () =>
cycleServices.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "all",
})
: null : null
); );

View File

@ -41,18 +41,14 @@ import {
} from "helpers/date-time.helper"; } from "helpers/date-time.helper";
import { copyTextToClipboard, truncateText } from "helpers/string.helper"; import { copyTextToClipboard, truncateText } from "helpers/string.helper";
// types // types
import { import { ICycle } from "types";
CompletedCyclesResponse,
CurrentAndUpcomingCyclesResponse,
DraftCyclesResponse,
ICycle,
} from "types";
// fetch-keys // fetch-keys
import { import {
CYCLE_COMPLETE_LIST, CYCLE_COMPLETE_LIST,
CYCLE_CURRENT_AND_UPCOMING_LIST, CYCLE_CURRENT_LIST,
CYCLE_DETAILS,
CYCLE_DRAFT_LIST, CYCLE_DRAFT_LIST,
CYCLE_LIST,
CYCLE_UPCOMING_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
type TSingleStatProps = { type TSingleStatProps = {
@ -108,51 +104,27 @@ export const SingleCycleCard: React.FC<TSingleStatProps> = ({
const handleAddToFavorites = () => { const handleAddToFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return; if (!workspaceSlug || !projectId || !cycle) return;
switch (cycleStatus) { const fetchKey =
case "current": cycleStatus === "current"
case "upcoming": ? CYCLE_CURRENT_LIST(projectId as string)
mutate<CurrentAndUpcomingCyclesResponse>( : cycleStatus === "upcoming"
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), ? CYCLE_UPCOMING_LIST(projectId as string)
(prevData) => ({ : cycleStatus === "completed"
current_cycle: (prevData?.current_cycle ?? []).map((c) => ({ ? CYCLE_COMPLETE_LIST(projectId as string)
: CYCLE_DRAFT_LIST(projectId as string);
mutate<ICycle[]>(
fetchKey,
(prevData) =>
(prevData ?? []).map((c) => ({
...c, ...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite, is_favorite: c.id === cycle.id ? true : c.is_favorite,
})), })),
upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false false
); );
break;
case "completed":
mutate<CompletedCyclesResponse>(
CYCLE_COMPLETE_LIST(projectId as string),
(prevData) => ({
completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false
);
break;
case "draft":
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => ({
draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false
);
break;
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => (prevData: any) =>
(prevData ?? []).map((c: any) => ({ (prevData ?? []).map((c: any) => ({
...c, ...c,
@ -177,51 +149,27 @@ export const SingleCycleCard: React.FC<TSingleStatProps> = ({
const handleRemoveFromFavorites = () => { const handleRemoveFromFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return; if (!workspaceSlug || !projectId || !cycle) return;
switch (cycleStatus) { const fetchKey =
case "current": cycleStatus === "current"
case "upcoming": ? CYCLE_CURRENT_LIST(projectId as string)
mutate<CurrentAndUpcomingCyclesResponse>( : cycleStatus === "upcoming"
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), ? CYCLE_UPCOMING_LIST(projectId as string)
(prevData) => ({ : cycleStatus === "completed"
current_cycle: (prevData?.current_cycle ?? []).map((c) => ({ ? CYCLE_COMPLETE_LIST(projectId as string)
: CYCLE_DRAFT_LIST(projectId as string);
mutate<ICycle[]>(
fetchKey,
(prevData) =>
(prevData ?? []).map((c) => ({
...c, ...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite, is_favorite: c.id === cycle.id ? false : c.is_favorite,
})), })),
upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false false
); );
break;
case "completed":
mutate<CompletedCyclesResponse>(
CYCLE_COMPLETE_LIST(projectId as string),
(prevData) => ({
completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false
);
break;
case "draft":
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => ({
draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false
);
break;
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => (prevData: any) =>
(prevData ?? []).map((c: any) => ({ (prevData ?? []).map((c: any) => ({
...c, ...c,

View File

@ -32,18 +32,14 @@ import {
} from "helpers/date-time.helper"; } from "helpers/date-time.helper";
import { copyTextToClipboard, truncateText } from "helpers/string.helper"; import { copyTextToClipboard, truncateText } from "helpers/string.helper";
// types // types
import { import { ICycle } from "types";
CompletedCyclesResponse,
CurrentAndUpcomingCyclesResponse,
DraftCyclesResponse,
ICycle,
} from "types";
// fetch-keys // fetch-keys
import { import {
CYCLE_COMPLETE_LIST, CYCLE_COMPLETE_LIST,
CYCLE_CURRENT_AND_UPCOMING_LIST, CYCLE_CURRENT_LIST,
CYCLE_DETAILS,
CYCLE_DRAFT_LIST, CYCLE_DRAFT_LIST,
CYCLE_LIST,
CYCLE_UPCOMING_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
import { type } from "os"; import { type } from "os";
@ -142,51 +138,27 @@ export const SingleCycleList: React.FC<TSingleStatProps> = ({
const handleAddToFavorites = () => { const handleAddToFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return; if (!workspaceSlug || !projectId || !cycle) return;
switch (cycleStatus) { const fetchKey =
case "current": cycleStatus === "current"
case "upcoming": ? CYCLE_CURRENT_LIST(projectId as string)
mutate<CurrentAndUpcomingCyclesResponse>( : cycleStatus === "upcoming"
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), ? CYCLE_UPCOMING_LIST(projectId as string)
(prevData) => ({ : cycleStatus === "completed"
current_cycle: (prevData?.current_cycle ?? []).map((c) => ({ ? CYCLE_COMPLETE_LIST(projectId as string)
: CYCLE_DRAFT_LIST(projectId as string);
mutate<ICycle[]>(
fetchKey,
(prevData) =>
(prevData ?? []).map((c) => ({
...c, ...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite, is_favorite: c.id === cycle.id ? true : c.is_favorite,
})), })),
upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false false
); );
break;
case "completed":
mutate<CompletedCyclesResponse>(
CYCLE_COMPLETE_LIST(projectId as string),
(prevData) => ({
completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false
);
break;
case "draft":
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => ({
draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? true : c.is_favorite,
})),
}),
false
);
break;
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => (prevData: any) =>
(prevData ?? []).map((c: any) => ({ (prevData ?? []).map((c: any) => ({
...c, ...c,
@ -211,51 +183,27 @@ export const SingleCycleList: React.FC<TSingleStatProps> = ({
const handleRemoveFromFavorites = () => { const handleRemoveFromFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return; if (!workspaceSlug || !projectId || !cycle) return;
switch (cycleStatus) { const fetchKey =
case "current": cycleStatus === "current"
case "upcoming": ? CYCLE_CURRENT_LIST(projectId as string)
mutate<CurrentAndUpcomingCyclesResponse>( : cycleStatus === "upcoming"
CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), ? CYCLE_UPCOMING_LIST(projectId as string)
(prevData) => ({ : cycleStatus === "completed"
current_cycle: (prevData?.current_cycle ?? []).map((c) => ({ ? CYCLE_COMPLETE_LIST(projectId as string)
: CYCLE_DRAFT_LIST(projectId as string);
mutate<ICycle[]>(
fetchKey,
(prevData) =>
(prevData ?? []).map((c) => ({
...c, ...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite, is_favorite: c.id === cycle.id ? false : c.is_favorite,
})), })),
upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false false
); );
break;
case "completed":
mutate<CompletedCyclesResponse>(
CYCLE_COMPLETE_LIST(projectId as string),
(prevData) => ({
completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false
);
break;
case "draft":
mutate<DraftCyclesResponse>(
CYCLE_DRAFT_LIST(projectId as string),
(prevData) => ({
draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
...c,
is_favorite: c.id === cycle.id ? false : c.is_favorite,
})),
}),
false
);
break;
}
mutate( mutate(
CYCLE_DETAILS(projectId as string), CYCLE_LIST(projectId as string),
(prevData: any) => (prevData: any) =>
(prevData ?? []).map((c: any) => ({ (prevData ?? []).map((c: any) => ({
...c, ...c,

View File

@ -59,7 +59,10 @@ export const TransferIssuesModal: React.FC<Props> = ({ isOpen, handleClose }) =>
const { data: incompleteCycles } = useSWR( const { data: incompleteCycles } = useSWR(
workspaceSlug && projectId ? CYCLE_INCOMPLETE_LIST(projectId as string) : null, workspaceSlug && projectId ? CYCLE_INCOMPLETE_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cyclesService.getIncompleteCycles(workspaceSlug as string, projectId as string) ? () =>
cyclesService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "incomplete",
})
: null : null
); );

View File

@ -35,7 +35,10 @@ export const SidebarCycleSelect: React.FC<Props> = ({
const { data: incompleteCycles } = useSWR( const { data: incompleteCycles } = useSWR(
workspaceSlug && projectId ? CYCLE_INCOMPLETE_LIST(projectId as string) : null, workspaceSlug && projectId ? CYCLE_INCOMPLETE_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cyclesService.getIncompleteCycles(workspaceSlug as string, projectId as string) ? () =>
cyclesService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "incomplete",
})
: null : null
); );

View File

@ -83,8 +83,11 @@ export const CYCLE_ISSUES_WITH_PARAMS = (cycleId: string, params?: any) => {
return `CYCLE_ISSUES_WITH_PARAMS_${cycleId.toUpperCase()}_${paramsKey.toUpperCase()}`; return `CYCLE_ISSUES_WITH_PARAMS_${cycleId.toUpperCase()}_${paramsKey.toUpperCase()}`;
}; };
export const CYCLE_DETAILS = (cycleId: string) => `CYCLE_DETAILS_${cycleId.toUpperCase()}`; export const CYCLE_DETAILS = (cycleId: string) => `CYCLE_DETAILS_${cycleId.toUpperCase()}`;
export const CYCLE_CURRENT_AND_UPCOMING_LIST = (projectId: string) =>
`CYCLE_CURRENT_AND_UPCOMING_LIST_${projectId.toUpperCase()}`; export const CYCLE_CURRENT_LIST = (projectId: string) =>
`CYCLE_CURRENT_LIST${projectId.toUpperCase()}`;
export const CYCLE_UPCOMING_LIST = (projectId: string) =>
`CYCLE_UPCOMING_LIST${projectId.toUpperCase()}`;
export const CYCLE_DRAFT_LIST = (projectId: string) => export const CYCLE_DRAFT_LIST = (projectId: string) =>
`CYCLE_DRAFT_LIST_${projectId.toUpperCase()}`; `CYCLE_DRAFT_LIST_${projectId.toUpperCase()}`;
export const CYCLE_COMPLETE_LIST = (projectId: string) => export const CYCLE_COMPLETE_LIST = (projectId: string) =>

View File

@ -56,7 +56,10 @@ const SingleCycle: React.FC = () => {
const { data: cycles } = useSWR( const { data: cycles } = useSWR(
workspaceSlug && projectId ? CYCLE_LIST(projectId as string) : null, workspaceSlug && projectId ? CYCLE_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cycleServices.getCycles(workspaceSlug as string, projectId as string) ? () =>
cycleServices.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "all",
})
: null : null
); );

View File

@ -21,10 +21,11 @@ import { SelectCycleType } from "types";
import type { NextPage } from "next"; import type { NextPage } from "next";
// fetch-keys // fetch-keys
import { import {
CYCLE_CURRENT_AND_UPCOMING_LIST,
CYCLE_DRAFT_LIST, CYCLE_DRAFT_LIST,
PROJECT_DETAILS, PROJECT_DETAILS,
CYCLE_DETAILS, CYCLE_UPCOMING_LIST,
CYCLE_CURRENT_LIST,
CYCLE_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
const ProjectCycles: NextPage = () => { const ProjectCycles: NextPage = () => {
@ -44,21 +45,40 @@ const ProjectCycles: NextPage = () => {
const { data: draftCycles } = useSWR( const { data: draftCycles } = useSWR(
workspaceSlug && projectId ? CYCLE_DRAFT_LIST(projectId as string) : null, workspaceSlug && projectId ? CYCLE_DRAFT_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cycleService.getDraftCycles(workspaceSlug as string, projectId as string) ? () =>
cycleService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "draft",
})
: null : null
); );
const { data: currentAndUpcomingCycles } = useSWR( const { data: currentCycle } = useSWR(
workspaceSlug && projectId ? CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string) : null, workspaceSlug && projectId ? CYCLE_CURRENT_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cycleService.getCurrentAndUpcomingCycles(workspaceSlug as string, projectId as string) ? () =>
cycleService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "current",
})
: null
);
const { data: upcomingCycles } = useSWR(
workspaceSlug && projectId ? CYCLE_UPCOMING_LIST(projectId as string) : null,
workspaceSlug && projectId
? () =>
cycleService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "upcoming",
})
: null : null
); );
const { data: cyclesCompleteList } = useSWR( const { data: cyclesCompleteList } = useSWR(
workspaceSlug && projectId ? CYCLE_DETAILS(projectId as string) : null, workspaceSlug && projectId ? CYCLE_LIST(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => cycleService.getCycles(workspaceSlug as string, projectId as string) ? () =>
cycleService.getCyclesWithParams(workspaceSlug as string, projectId as string, {
cycle_view: "all",
})
: null : null
); );
@ -121,7 +141,8 @@ const ProjectCycles: NextPage = () => {
setSelectedCycle={setSelectedCycle} setSelectedCycle={setSelectedCycle}
setCreateUpdateCycleModal={setCreateUpdateCycleModal} setCreateUpdateCycleModal={setCreateUpdateCycleModal}
cyclesCompleteList={cyclesCompleteList} cyclesCompleteList={cyclesCompleteList}
currentAndUpcomingCycles={currentAndUpcomingCycles} currentCycle={currentCycle}
upcomingCycles={upcomingCycles}
draftCycles={draftCycles} draftCycles={draftCycles}
/> />
</div> </div>

View File

@ -3,15 +3,7 @@ import APIService from "services/api.service";
import trackEventServices from "services/track-event.service"; import trackEventServices from "services/track-event.service";
// types // types
import type { import type { ICycle, IIssue, IIssueViewOptions } from "types";
CycleIssueResponse,
CompletedCyclesResponse,
CurrentAndUpcomingCyclesResponse,
DraftCyclesResponse,
ICycle,
IIssue,
IIssueViewOptions,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env; const { NEXT_PUBLIC_API_BASE_URL } = process.env;
@ -34,16 +26,14 @@ class ProjectCycleServices extends APIService {
}); });
} }
async getCycles(workspaceSlug: string, projectId: string): Promise<ICycle[]> { async getCyclesWithParams(
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`) workspaceSlug: string,
.then((response) => response?.data) projectId: string,
.catch((error) => { queries: any
throw error?.response?.data; ): Promise<ICycle[]> {
}); return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, {
} params: queries,
})
async getIncompleteCycles(workspaceSlug: string, projectId: string): Promise<ICycle[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/incomplete-cycles/`)
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {
throw error?.response?.data; throw error?.response?.data;
@ -159,40 +149,6 @@ class ProjectCycleServices extends APIService {
}); });
} }
async getCurrentAndUpcomingCycles(
workspaceSlug: string,
projectId: string
): Promise<CurrentAndUpcomingCyclesResponse> {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/current-upcoming-cycles/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getDraftCycles(workspaceSlug: string, projectId: string): Promise<DraftCyclesResponse> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/draft-cycles/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getCompletedCycles(
workspaceSlug: string,
projectId: string
): Promise<CompletedCyclesResponse> {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/completed-cycles/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async addCycleToFavorites( async addCycleToFavorites(
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,

View File

@ -38,19 +38,6 @@ export interface ICycle {
workspace_detail: IWorkspaceLite; workspace_detail: IWorkspaceLite;
} }
export interface CurrentAndUpcomingCyclesResponse {
current_cycle: ICycle[];
upcoming_cycle: ICycle[];
}
export interface DraftCyclesResponse {
draft_cycles: ICycle[];
}
export interface CompletedCyclesResponse {
completed_cycles: ICycle[];
}
export interface CycleIssueResponse { export interface CycleIssueResponse {
id: string; id: string;
issue_detail: IIssue; issue_detail: IIssue;