forked from github/plane
fix: calendar view mutation (#1042)
This commit is contained in:
parent
dbbd9add99
commit
290318603d
@ -1,4 +1,17 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
// headless ui
|
||||||
import { Popover, Transition } from "@headlessui/react";
|
import { Popover, Transition } from "@headlessui/react";
|
||||||
|
// ui
|
||||||
|
import { CustomMenu, ToggleSwitch } from "components/ui";
|
||||||
|
// icons
|
||||||
|
import {
|
||||||
|
CheckIcon,
|
||||||
|
ChevronDownIcon,
|
||||||
|
ChevronLeftIcon,
|
||||||
|
ChevronRightIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
|
// helpers
|
||||||
import {
|
import {
|
||||||
addMonths,
|
addMonths,
|
||||||
addSevenDaysToDate,
|
addSevenDaysToDate,
|
||||||
@ -14,26 +27,17 @@ import {
|
|||||||
updateDateWithMonth,
|
updateDateWithMonth,
|
||||||
updateDateWithYear,
|
updateDateWithYear,
|
||||||
} from "helpers/calendar.helper";
|
} from "helpers/calendar.helper";
|
||||||
import React from "react";
|
// constants
|
||||||
import { MONTHS_LIST, YEARS_LIST } from "constants/calendar";
|
import { MONTHS_LIST, YEARS_LIST } from "constants/calendar";
|
||||||
|
|
||||||
import { ICalendarRange } from "types";
|
|
||||||
import {
|
|
||||||
CheckIcon,
|
|
||||||
ChevronDownIcon,
|
|
||||||
ChevronLeftIcon,
|
|
||||||
ChevronRightIcon,
|
|
||||||
} from "@heroicons/react/24/outline";
|
|
||||||
import { CustomMenu, ToggleSwitch } from "components/ui";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isMonthlyView: boolean;
|
isMonthlyView: boolean;
|
||||||
setIsMonthlyView: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsMonthlyView: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
currentDate: Date;
|
currentDate: Date;
|
||||||
setCurrentDate: React.Dispatch<React.SetStateAction<Date>>;
|
setCurrentDate: React.Dispatch<React.SetStateAction<Date>>;
|
||||||
setCalendarDateRange: React.Dispatch<React.SetStateAction<ICalendarRange>>;
|
|
||||||
showWeekEnds: boolean;
|
showWeekEnds: boolean;
|
||||||
setShowWeekEnds: React.Dispatch<React.SetStateAction<boolean>>;
|
setShowWeekEnds: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
changeDateRange: (startDate: Date, endDate: Date) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CalendarHeader: React.FC<Props> = ({
|
export const CalendarHeader: React.FC<Props> = ({
|
||||||
@ -41,18 +45,16 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
isMonthlyView,
|
isMonthlyView,
|
||||||
currentDate,
|
currentDate,
|
||||||
setCurrentDate,
|
setCurrentDate,
|
||||||
setCalendarDateRange,
|
|
||||||
showWeekEnds,
|
showWeekEnds,
|
||||||
setShowWeekEnds,
|
setShowWeekEnds,
|
||||||
|
changeDateRange,
|
||||||
}) => {
|
}) => {
|
||||||
const updateDate = (date: Date) => {
|
const updateDate = (date: Date) => {
|
||||||
setCurrentDate(date);
|
setCurrentDate(date);
|
||||||
|
|
||||||
setCalendarDateRange({
|
changeDateRange(startOfWeek(date), lastDayOfWeek(date));
|
||||||
startDate: startOfWeek(date),
|
|
||||||
endDate: lastDayOfWeek(date),
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
<div className="relative flex h-full w-full items-center justify-start gap-2 text-sm ">
|
<div className="relative flex h-full w-full items-center justify-start gap-2 text-sm ">
|
||||||
@ -93,9 +95,13 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
<div className="grid grid-cols-4 border-t border-brand-base px-2">
|
<div className="grid grid-cols-4 border-t border-brand-base px-2">
|
||||||
{MONTHS_LIST.map((month) => (
|
{MONTHS_LIST.map((month) => (
|
||||||
<button
|
<button
|
||||||
onClick={() => updateDate(updateDateWithMonth(`${month.value}`, currentDate))}
|
onClick={() =>
|
||||||
|
updateDate(updateDateWithMonth(`${month.value}`, currentDate))
|
||||||
|
}
|
||||||
className={`px-2 py-2 text-xs text-brand-secondary hover:font-medium hover:text-brand-base ${
|
className={`px-2 py-2 text-xs text-brand-secondary hover:font-medium hover:text-brand-base ${
|
||||||
isSameMonth(`${month.value}`, currentDate) ? "font-medium text-brand-base" : ""
|
isSameMonth(`${month.value}`, currentDate)
|
||||||
|
? "font-medium text-brand-base"
|
||||||
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{month.label}
|
{month.label}
|
||||||
@ -116,10 +122,10 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
updateDate(subtractMonths(currentDate, 1));
|
updateDate(subtractMonths(currentDate, 1));
|
||||||
} else {
|
} else {
|
||||||
setCurrentDate(subtract7DaysToDate(currentDate));
|
setCurrentDate(subtract7DaysToDate(currentDate));
|
||||||
setCalendarDateRange({
|
changeDateRange(
|
||||||
startDate: getCurrentWeekStartDate(subtract7DaysToDate(currentDate)),
|
getCurrentWeekStartDate(subtract7DaysToDate(currentDate)),
|
||||||
endDate: getCurrentWeekEndDate(subtract7DaysToDate(currentDate)),
|
getCurrentWeekEndDate(subtract7DaysToDate(currentDate))
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -132,10 +138,10 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
updateDate(addMonths(currentDate, 1));
|
updateDate(addMonths(currentDate, 1));
|
||||||
} else {
|
} else {
|
||||||
setCurrentDate(addSevenDaysToDate(currentDate));
|
setCurrentDate(addSevenDaysToDate(currentDate));
|
||||||
setCalendarDateRange({
|
changeDateRange(
|
||||||
startDate: getCurrentWeekStartDate(addSevenDaysToDate(currentDate)),
|
getCurrentWeekStartDate(addSevenDaysToDate(currentDate)),
|
||||||
endDate: getCurrentWeekEndDate(addSevenDaysToDate(currentDate)),
|
getCurrentWeekEndDate(addSevenDaysToDate(currentDate))
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -152,10 +158,10 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
updateDate(new Date());
|
updateDate(new Date());
|
||||||
} else {
|
} else {
|
||||||
setCurrentDate(new Date());
|
setCurrentDate(new Date());
|
||||||
setCalendarDateRange({
|
changeDateRange(
|
||||||
startDate: getCurrentWeekStartDate(new Date()),
|
getCurrentWeekStartDate(new Date()),
|
||||||
endDate: getCurrentWeekEndDate(new Date()),
|
getCurrentWeekEndDate(new Date())
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -173,10 +179,7 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
<CustomMenu.MenuItem
|
<CustomMenu.MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsMonthlyView(true);
|
setIsMonthlyView(true);
|
||||||
setCalendarDateRange({
|
changeDateRange(startOfWeek(currentDate), lastDayOfWeek(currentDate));
|
||||||
startDate: startOfWeek(currentDate),
|
|
||||||
endDate: lastDayOfWeek(currentDate),
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
className="w-52 text-sm text-brand-secondary"
|
className="w-52 text-sm text-brand-secondary"
|
||||||
>
|
>
|
||||||
@ -190,10 +193,10 @@ export const CalendarHeader: React.FC<Props> = ({
|
|||||||
<CustomMenu.MenuItem
|
<CustomMenu.MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsMonthlyView(false);
|
setIsMonthlyView(false);
|
||||||
setCalendarDateRange({
|
changeDateRange(
|
||||||
startDate: getCurrentWeekStartDate(currentDate),
|
getCurrentWeekStartDate(currentDate),
|
||||||
endDate: getCurrentWeekEndDate(currentDate),
|
getCurrentWeekEndDate(currentDate)
|
||||||
});
|
);
|
||||||
}}
|
}}
|
||||||
className="w-52 text-sm text-brand-secondary"
|
className="w-52 text-sm text-brand-secondary"
|
||||||
>
|
>
|
||||||
|
@ -1,28 +1,20 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
// swr
|
|
||||||
import useSWR, { mutate } from "swr";
|
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
// ui
|
import { mutate } from "swr";
|
||||||
import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd";
|
|
||||||
import { SingleCalendarDate, CalendarHeader } from "components/core";
|
|
||||||
|
|
||||||
import { Spinner } from "components/ui";
|
// react-beautiful-dnd
|
||||||
// hooks
|
import { DragDropContext, DropResult } from "react-beautiful-dnd";
|
||||||
import useIssuesView from "hooks/use-issues-view";
|
|
||||||
// services
|
// services
|
||||||
import issuesService from "services/issues.service";
|
import issuesService from "services/issues.service";
|
||||||
import cyclesService from "services/cycles.service";
|
// hooks
|
||||||
import modulesService from "services/modules.service";
|
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
|
||||||
// fetch key
|
// components
|
||||||
import {
|
import { SingleCalendarDate, CalendarHeader } from "components/core";
|
||||||
CYCLE_CALENDAR_ISSUES,
|
// ui
|
||||||
MODULE_CALENDAR_ISSUES,
|
import { Spinner } from "components/ui";
|
||||||
PROJECT_CALENDAR_ISSUES,
|
// helpers
|
||||||
} from "constants/fetch-keys";
|
|
||||||
// helper
|
|
||||||
import { renderDateFormat } from "helpers/date-time.helper";
|
import { renderDateFormat } from "helpers/date-time.helper";
|
||||||
import {
|
import {
|
||||||
startOfWeek,
|
startOfWeek,
|
||||||
@ -31,8 +23,15 @@ import {
|
|||||||
weekDayInterval,
|
weekDayInterval,
|
||||||
formatDate,
|
formatDate,
|
||||||
} from "helpers/calendar.helper";
|
} from "helpers/calendar.helper";
|
||||||
// type
|
// types
|
||||||
import { ICalendarRange, IIssue, UserAuth } from "types";
|
import { ICalendarRange, IIssue, UserAuth } from "types";
|
||||||
|
// fetch-keys
|
||||||
|
import {
|
||||||
|
CYCLE_ISSUES_WITH_PARAMS,
|
||||||
|
MODULE_ISSUES_WITH_PARAMS,
|
||||||
|
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||||
|
VIEW_ISSUES,
|
||||||
|
} from "constants/fetch-keys";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
handleEditIssue: (issue: IIssue) => void;
|
handleEditIssue: (issue: IIssue) => void;
|
||||||
@ -53,93 +52,31 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
const [currentDate, setCurrentDate] = useState(new Date());
|
const [currentDate, setCurrentDate] = useState(new Date());
|
||||||
const [isMonthlyView, setIsMonthlyView] = useState(true);
|
const [isMonthlyView, setIsMonthlyView] = useState(true);
|
||||||
|
|
||||||
const router = useRouter();
|
const [calendarDates, setCalendarDates] = useState<ICalendarRange>({
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
|
||||||
|
|
||||||
const { params } = useIssuesView();
|
|
||||||
|
|
||||||
const [calendarDateRange, setCalendarDateRange] = useState<ICalendarRange>({
|
|
||||||
startDate: startOfWeek(currentDate),
|
startDate: startOfWeek(currentDate),
|
||||||
endDate: lastDayOfWeek(currentDate),
|
endDate: lastDayOfWeek(currentDate),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: projectCalendarIssues } = useSWR(
|
const router = useRouter();
|
||||||
workspaceSlug && projectId ? PROJECT_CALENDAR_ISSUES(projectId as string) : null,
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
workspaceSlug && projectId
|
|
||||||
? () =>
|
|
||||||
issuesService.getIssuesWithParams(workspaceSlug as string, projectId as string, {
|
|
||||||
...params,
|
|
||||||
target_date: `${renderDateFormat(calendarDateRange.startDate)};after,${renderDateFormat(
|
|
||||||
calendarDateRange.endDate
|
|
||||||
)};before`,
|
|
||||||
group_by: null,
|
|
||||||
})
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: cycleCalendarIssues } = useSWR(
|
const { calendarIssues, params, setCalendarDateRange } = useCalendarIssuesView();
|
||||||
workspaceSlug && projectId && cycleId
|
|
||||||
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
|
|
||||||
: null,
|
|
||||||
workspaceSlug && projectId && cycleId
|
|
||||||
? () =>
|
|
||||||
cyclesService.getCycleIssuesWithParams(
|
|
||||||
workspaceSlug as string,
|
|
||||||
projectId as string,
|
|
||||||
cycleId as string,
|
|
||||||
{
|
|
||||||
...params,
|
|
||||||
target_date: `${renderDateFormat(
|
|
||||||
calendarDateRange.startDate
|
|
||||||
)};after,${renderDateFormat(calendarDateRange.endDate)};before`,
|
|
||||||
group_by: null,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: moduleCalendarIssues } = useSWR(
|
|
||||||
workspaceSlug && projectId && moduleId
|
|
||||||
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
|
|
||||||
: null,
|
|
||||||
workspaceSlug && projectId && moduleId
|
|
||||||
? () =>
|
|
||||||
modulesService.getModuleIssuesWithParams(
|
|
||||||
workspaceSlug as string,
|
|
||||||
projectId as string,
|
|
||||||
moduleId as string,
|
|
||||||
{
|
|
||||||
...params,
|
|
||||||
target_date: `${renderDateFormat(
|
|
||||||
calendarDateRange.startDate
|
|
||||||
)};after,${renderDateFormat(calendarDateRange.endDate)};before`,
|
|
||||||
group_by: null,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
const totalDate = eachDayOfInterval({
|
const totalDate = eachDayOfInterval({
|
||||||
start: calendarDateRange.startDate,
|
start: calendarDates.startDate,
|
||||||
end: calendarDateRange.endDate,
|
end: calendarDates.endDate,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onlyWeekDays = weekDayInterval({
|
const onlyWeekDays = weekDayInterval({
|
||||||
start: calendarDateRange.startDate,
|
start: calendarDates.startDate,
|
||||||
end: calendarDateRange.endDate,
|
end: calendarDates.endDate,
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentViewDays = showWeekEnds ? totalDate : onlyWeekDays;
|
const currentViewDays = showWeekEnds ? totalDate : onlyWeekDays;
|
||||||
|
|
||||||
const calendarIssues = cycleId
|
|
||||||
? (cycleCalendarIssues as IIssue[])
|
|
||||||
: moduleId
|
|
||||||
? (moduleCalendarIssues as IIssue[])
|
|
||||||
: (projectCalendarIssues as IIssue[]);
|
|
||||||
|
|
||||||
const currentViewDaysData = currentViewDays.map((date: Date) => {
|
const currentViewDaysData = currentViewDays.map((date: Date) => {
|
||||||
const filterIssue =
|
const filterIssue =
|
||||||
calendarIssues && calendarIssues.length > 0
|
calendarIssues.length > 0
|
||||||
? calendarIssues.filter(
|
? calendarIssues.filter(
|
||||||
(issue) =>
|
(issue) =>
|
||||||
issue.target_date && renderDateFormat(issue.target_date) === renderDateFormat(date)
|
issue.target_date && renderDateFormat(issue.target_date) === renderDateFormat(date)
|
||||||
@ -170,13 +107,16 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
const { source, destination, draggableId } = result;
|
const { source, destination, draggableId } = result;
|
||||||
|
|
||||||
if (!destination || !workspaceSlug || !projectId) return;
|
if (!destination || !workspaceSlug || !projectId) return;
|
||||||
|
|
||||||
if (source.droppableId === destination.droppableId) return;
|
if (source.droppableId === destination.droppableId) return;
|
||||||
|
|
||||||
const fetchKey = cycleId
|
const fetchKey = cycleId
|
||||||
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
|
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
|
||||||
: moduleId
|
: moduleId
|
||||||
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
|
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
|
||||||
: PROJECT_CALENDAR_ISSUES(projectId as string);
|
: viewId
|
||||||
|
? VIEW_ISSUES(viewId.toString(), params)
|
||||||
|
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params);
|
||||||
|
|
||||||
mutate<IIssue[]>(
|
mutate<IIssue[]>(
|
||||||
fetchKey,
|
fetchKey,
|
||||||
@ -187,16 +127,38 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
...p,
|
...p,
|
||||||
target_date: destination.droppableId,
|
target_date: destination.droppableId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}),
|
}),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
issuesService.patchIssue(workspaceSlug as string, projectId as string, draggableId, {
|
issuesService
|
||||||
target_date: destination?.droppableId,
|
.patchIssue(workspaceSlug as string, projectId as string, draggableId, {
|
||||||
});
|
target_date: destination?.droppableId,
|
||||||
|
})
|
||||||
|
.then(() => mutate(fetchKey));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeDateRange = (startDate: Date, endDate: Date) => {
|
||||||
|
setCalendarDates({
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
setCalendarDateRange(
|
||||||
|
`${renderDateFormat(startDate)};after,${renderDateFormat(endDate)};before`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCalendarDateRange(
|
||||||
|
`${renderDateFormat(startOfWeek(currentDate))};after,${renderDateFormat(
|
||||||
|
lastDayOfWeek(currentDate)
|
||||||
|
)};before`
|
||||||
|
);
|
||||||
|
}, [currentDate]);
|
||||||
|
|
||||||
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || isCompleted;
|
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || isCompleted;
|
||||||
|
|
||||||
return calendarIssues ? (
|
return calendarIssues ? (
|
||||||
@ -210,7 +172,7 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
setShowWeekEnds={setShowWeekEnds}
|
setShowWeekEnds={setShowWeekEnds}
|
||||||
currentDate={currentDate}
|
currentDate={currentDate}
|
||||||
setCurrentDate={setCurrentDate}
|
setCurrentDate={setCurrentDate}
|
||||||
setCalendarDateRange={setCalendarDateRange}
|
changeDateRange={changeDateRange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -10,6 +10,7 @@ import { DraggableProvided, DraggableStateSnapshot } from "react-beautiful-dnd";
|
|||||||
// services
|
// services
|
||||||
import issuesService from "services/issues.service";
|
import issuesService from "services/issues.service";
|
||||||
// hooks
|
// hooks
|
||||||
|
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
|
||||||
import useIssuesProperties from "hooks/use-issue-properties";
|
import useIssuesProperties from "hooks/use-issue-properties";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// components
|
// components
|
||||||
@ -29,9 +30,10 @@ import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
|||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import {
|
import {
|
||||||
CYCLE_CALENDAR_ISSUES,
|
CYCLE_ISSUES_WITH_PARAMS,
|
||||||
MODULE_CALENDAR_ISSUES,
|
MODULE_ISSUES_WITH_PARAMS,
|
||||||
PROJECT_CALENDAR_ISSUES,
|
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||||
|
VIEW_ISSUES,
|
||||||
} from "constants/fetch-keys";
|
} from "constants/fetch-keys";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -54,10 +56,12 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
isNotAllowed,
|
isNotAllowed,
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
|
const { params } = useCalendarIssuesView();
|
||||||
|
|
||||||
const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string);
|
const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string);
|
||||||
|
|
||||||
const partialUpdateIssue = useCallback(
|
const partialUpdateIssue = useCallback(
|
||||||
@ -65,20 +69,25 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
if (!workspaceSlug || !projectId) return;
|
if (!workspaceSlug || !projectId) return;
|
||||||
|
|
||||||
const fetchKey = cycleId
|
const fetchKey = cycleId
|
||||||
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
|
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
|
||||||
: moduleId
|
: moduleId
|
||||||
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
|
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
|
||||||
: PROJECT_CALENDAR_ISSUES(projectId as string);
|
: viewId
|
||||||
|
? VIEW_ISSUES(viewId.toString(), params)
|
||||||
|
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params);
|
||||||
|
|
||||||
mutate<IIssue[]>(
|
mutate<IIssue[]>(
|
||||||
fetchKey,
|
fetchKey,
|
||||||
(prevData) =>
|
(prevData) =>
|
||||||
(prevData ?? []).map((p) => {
|
(prevData ?? []).map((p) => {
|
||||||
if (p.id === issueId)
|
if (p.id === issueId) {
|
||||||
return {
|
return {
|
||||||
...p,
|
...p,
|
||||||
formData,
|
...formData,
|
||||||
|
assignees: formData?.assignees_list ?? p.assignees,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}),
|
}),
|
||||||
false
|
false
|
||||||
@ -87,13 +96,13 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
issuesService
|
issuesService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData)
|
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate<IIssue[]>(fetchKey);
|
mutate(fetchKey);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, projectId, cycleId, moduleId]
|
[workspaceSlug, projectId, cycleId, moduleId, params]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCopyText = () => {
|
const handleCopyText = () => {
|
||||||
@ -205,7 +214,7 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
className="group flex items-center gap-1 rounded-2xl border border-brand-base px-2 py-0.5 text-xs text-brand-secondary"
|
className="group flex items-center gap-1 rounded-2xl border border-brand-base px-2 py-0.5 text-xs text-brand-secondary"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="h-1.5 w-1.5 rounded-full"
|
className="h-1.5 w-1.5 rounded-full"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: label?.color && label.color !== "" ? label.color : "#000",
|
backgroundColor: label?.color && label.color !== "" ? label.color : "#000",
|
||||||
}}
|
}}
|
||||||
|
@ -9,22 +9,21 @@ import { Dialog, Transition } from "@headlessui/react";
|
|||||||
// services
|
// services
|
||||||
import issueServices from "services/issues.service";
|
import issueServices from "services/issues.service";
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
|
||||||
import useIssuesView from "hooks/use-issues-view";
|
import useIssuesView from "hooks/use-issues-view";
|
||||||
|
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
|
||||||
|
import useToast from "hooks/use-toast";
|
||||||
// icons
|
// icons
|
||||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||||
// ui
|
// ui
|
||||||
import { SecondaryButton, DangerButton } from "components/ui";
|
import { SecondaryButton, DangerButton } from "components/ui";
|
||||||
// types
|
// types
|
||||||
import type { CycleIssueResponse, IIssue, ModuleIssueResponse } from "types";
|
import type { IIssue } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import {
|
import {
|
||||||
CYCLE_CALENDAR_ISSUES,
|
|
||||||
CYCLE_ISSUES_WITH_PARAMS,
|
CYCLE_ISSUES_WITH_PARAMS,
|
||||||
MODULE_CALENDAR_ISSUES,
|
|
||||||
MODULE_ISSUES_WITH_PARAMS,
|
MODULE_ISSUES_WITH_PARAMS,
|
||||||
PROJECT_CALENDAR_ISSUES,
|
|
||||||
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||||
|
VIEW_ISSUES,
|
||||||
} from "constants/fetch-keys";
|
} from "constants/fetch-keys";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -37,9 +36,10 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
|
|||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
const { issueView, params } = useIssuesView();
|
const { issueView, params } = useIssuesView();
|
||||||
|
const { params: calendarParams } = useCalendarIssuesView();
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
@ -61,12 +61,18 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
if (issueView === "calendar") {
|
if (issueView === "calendar") {
|
||||||
const calendarFetchKey = cycleId
|
const calendarFetchKey = cycleId
|
||||||
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
|
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), calendarParams)
|
||||||
: moduleId
|
: moduleId
|
||||||
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
|
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), calendarParams)
|
||||||
: PROJECT_CALENDAR_ISSUES(projectId as string);
|
: viewId
|
||||||
|
? VIEW_ISSUES(viewId.toString(), calendarParams)
|
||||||
|
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), calendarParams);
|
||||||
|
|
||||||
mutate<IIssue[]>(calendarFetchKey);
|
mutate<IIssue[]>(
|
||||||
|
calendarFetchKey,
|
||||||
|
(prevData) => (prevData ?? []).filter((p) => p.id !== data.id),
|
||||||
|
false
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
if (cycleId) mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
if (cycleId) mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
|
||||||
else if (moduleId) mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params));
|
else if (moduleId) mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params));
|
||||||
|
@ -12,14 +12,14 @@ import modulesService from "services/modules.service";
|
|||||||
import issuesService from "services/issues.service";
|
import issuesService from "services/issues.service";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "hooks/use-user";
|
import useUser from "hooks/use-user";
|
||||||
|
import useIssuesView from "hooks/use-issues-view";
|
||||||
|
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// components
|
// components
|
||||||
import { IssueForm } from "components/issues";
|
import { IssueForm } from "components/issues";
|
||||||
// hooks
|
|
||||||
import useIssuesView from "hooks/use-issues-view";
|
|
||||||
// types
|
// types
|
||||||
import type { IIssue } from "types";
|
import type { IIssue } from "types";
|
||||||
// fetch keys
|
// fetch-keys
|
||||||
import {
|
import {
|
||||||
PROJECT_ISSUES_DETAILS,
|
PROJECT_ISSUES_DETAILS,
|
||||||
PROJECT_ISSUES_LIST,
|
PROJECT_ISSUES_LIST,
|
||||||
@ -31,9 +31,7 @@ import {
|
|||||||
MODULE_ISSUES_WITH_PARAMS,
|
MODULE_ISSUES_WITH_PARAMS,
|
||||||
CYCLE_DETAILS,
|
CYCLE_DETAILS,
|
||||||
MODULE_DETAILS,
|
MODULE_DETAILS,
|
||||||
PROJECT_CALENDAR_ISSUES,
|
VIEW_ISSUES,
|
||||||
CYCLE_CALENDAR_ISSUES,
|
|
||||||
MODULE_CALENDAR_ISSUES,
|
|
||||||
} from "constants/fetch-keys";
|
} from "constants/fetch-keys";
|
||||||
|
|
||||||
export interface IssuesModalProps {
|
export interface IssuesModalProps {
|
||||||
@ -56,9 +54,10 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
|||||||
const [activeProject, setActiveProject] = useState<string | null>(null);
|
const [activeProject, setActiveProject] = useState<string | null>(null);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
const { issueView, params } = useIssuesView();
|
const { issueView, params } = useIssuesView();
|
||||||
|
const { params: calendarParams } = useCalendarIssuesView();
|
||||||
|
|
||||||
if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId as string };
|
if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId as string };
|
||||||
if (moduleId) prePopulateData = { ...prePopulateData, module: moduleId as string };
|
if (moduleId) prePopulateData = { ...prePopulateData, module: moduleId as string };
|
||||||
@ -128,23 +127,24 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const calendarFetchKey = cycleId
|
||||||
|
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), calendarParams)
|
||||||
|
: moduleId
|
||||||
|
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), calendarParams)
|
||||||
|
: viewId
|
||||||
|
? VIEW_ISSUES(viewId.toString(), calendarParams)
|
||||||
|
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId?.toString() ?? "", calendarParams);
|
||||||
|
|
||||||
const createIssue = async (payload: Partial<IIssue>) => {
|
const createIssue = async (payload: Partial<IIssue>) => {
|
||||||
await issuesService
|
await issuesService
|
||||||
.createIssues(workspaceSlug as string, activeProject ?? "", payload)
|
.createIssues(workspaceSlug as string, activeProject ?? "", payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
||||||
|
if (issueView === "calendar") mutate(calendarFetchKey);
|
||||||
|
|
||||||
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
|
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
|
||||||
if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module);
|
if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module);
|
||||||
|
|
||||||
const calendarFetchKey = cycleId
|
|
||||||
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
|
|
||||||
: moduleId
|
|
||||||
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
|
|
||||||
: PROJECT_CALENDAR_ISSUES(projectId as string);
|
|
||||||
|
|
||||||
mutate<IIssue[]>(calendarFetchKey);
|
|
||||||
|
|
||||||
if (!createMore) handleClose();
|
if (!createMore) handleClose();
|
||||||
|
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
@ -173,29 +173,8 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
|||||||
if (isUpdatingSingleIssue) {
|
if (isUpdatingSingleIssue) {
|
||||||
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
||||||
} else {
|
} else {
|
||||||
if (issueView === "calendar") {
|
if (issueView === "calendar") mutate(calendarFetchKey);
|
||||||
const calendarFetchKey = cycleId
|
else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
||||||
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
|
|
||||||
: moduleId
|
|
||||||
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
|
|
||||||
: PROJECT_CALENDAR_ISSUES(projectId as string);
|
|
||||||
|
|
||||||
mutate<IIssue[]>(calendarFetchKey, (prevData) =>
|
|
||||||
(prevData ?? []).map((i) => {
|
|
||||||
if (i.id === res.id) return { ...i, ...res };
|
|
||||||
return i;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
mutate<IIssue[]>(
|
|
||||||
PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params),
|
|
||||||
(prevData) =>
|
|
||||||
(prevData ?? []).map((i) => {
|
|
||||||
if (i.id === res.id) return { ...i, ...res };
|
|
||||||
return i;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
|
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { IAnalyticsParams, IJiraMetadata } from "types";
|
import { IAnalyticsParams, IJiraMetadata } from "types";
|
||||||
|
|
||||||
const paramsToKey = (params: any) => {
|
const paramsToKey = (params: any) => {
|
||||||
const { state, priority, assignees, created_by, labels } = params;
|
const { state, priority, assignees, created_by, labels, target_date } = params;
|
||||||
|
|
||||||
let stateKey = state ? state.split(",") : [];
|
let stateKey = state ? state.split(",") : [];
|
||||||
let priorityKey = priority ? priority.split(",") : [];
|
let priorityKey = priority ? priority.split(",") : [];
|
||||||
let assigneesKey = assignees ? assignees.split(",") : [];
|
let assigneesKey = assignees ? assignees.split(",") : [];
|
||||||
let createdByKey = created_by ? created_by.split(",") : [];
|
let createdByKey = created_by ? created_by.split(",") : [];
|
||||||
let labelsKey = labels ? labels.split(",") : [];
|
let labelsKey = labels ? labels.split(",") : [];
|
||||||
|
const targetDateKey = target_date ?? "";
|
||||||
const type = params.type ? params.type.toUpperCase() : "NULL";
|
const type = params.type ? params.type.toUpperCase() : "NULL";
|
||||||
const groupBy = params.group_by ? params.group_by.toUpperCase() : "NULL";
|
const groupBy = params.group_by ? params.group_by.toUpperCase() : "NULL";
|
||||||
const orderBy = params.order_by ? params.order_by.toUpperCase() : "NULL";
|
const orderBy = params.order_by ? params.order_by.toUpperCase() : "NULL";
|
||||||
@ -19,7 +20,7 @@ const paramsToKey = (params: any) => {
|
|||||||
createdByKey = createdByKey.sort().join("_");
|
createdByKey = createdByKey.sort().join("_");
|
||||||
labelsKey = labelsKey.sort().join("_");
|
labelsKey = labelsKey.sort().join("_");
|
||||||
|
|
||||||
return `${stateKey}_${priorityKey}_${assigneesKey}_${createdByKey}_${type}_${groupBy}_${orderBy}_${labelsKey}`;
|
return `${stateKey}_${priorityKey}_${assigneesKey}_${createdByKey}_${type}_${groupBy}_${orderBy}_${labelsKey}_${targetDateKey}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CURRENT_USER = "CURRENT_USER";
|
export const CURRENT_USER = "CURRENT_USER";
|
||||||
@ -148,14 +149,6 @@ export const GITHUB_REPOSITORY_INFO = (workspaceSlug: string, repoName: string)
|
|||||||
export const SLACK_CHANNEL_INFO = (workspaceSlug: string, projectId: string) =>
|
export const SLACK_CHANNEL_INFO = (workspaceSlug: string, projectId: string) =>
|
||||||
`SLACK_CHANNEL_INFO_${workspaceSlug.toString().toUpperCase()}_${projectId.toUpperCase()}`;
|
`SLACK_CHANNEL_INFO_${workspaceSlug.toString().toUpperCase()}_${projectId.toUpperCase()}`;
|
||||||
|
|
||||||
// Calendar
|
|
||||||
export const PROJECT_CALENDAR_ISSUES = (projectId: string) =>
|
|
||||||
`CALENDAR_ISSUES_${projectId.toUpperCase()}`;
|
|
||||||
export const CYCLE_CALENDAR_ISSUES = (projectId: string, cycleId: string) =>
|
|
||||||
`CALENDAR_ISSUES_${projectId.toUpperCase()}_${cycleId.toUpperCase()}`;
|
|
||||||
export const MODULE_CALENDAR_ISSUES = (projectId: string, moduleId: string) =>
|
|
||||||
`CALENDAR_ISSUES_${projectId.toUpperCase()}_${moduleId.toUpperCase()}`;
|
|
||||||
|
|
||||||
// Pages
|
// Pages
|
||||||
export const RECENT_PAGES_LIST = (projectId: string) =>
|
export const RECENT_PAGES_LIST = (projectId: string) =>
|
||||||
`RECENT_PAGES_LIST_${projectId.toUpperCase()}`;
|
`RECENT_PAGES_LIST_${projectId.toUpperCase()}`;
|
||||||
|
@ -34,6 +34,7 @@ type IssueViewProps = {
|
|||||||
groupByProperty: TIssueGroupByOptions;
|
groupByProperty: TIssueGroupByOptions;
|
||||||
orderBy: TIssueOrderByOptions;
|
orderBy: TIssueOrderByOptions;
|
||||||
showEmptyGroups: boolean;
|
showEmptyGroups: boolean;
|
||||||
|
calendarDateRange: string;
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ type ReducerActionType = {
|
|||||||
| "SET_ISSUE_VIEW"
|
| "SET_ISSUE_VIEW"
|
||||||
| "SET_ORDER_BY_PROPERTY"
|
| "SET_ORDER_BY_PROPERTY"
|
||||||
| "SET_SHOW_EMPTY_STATES"
|
| "SET_SHOW_EMPTY_STATES"
|
||||||
|
| "SET_CALENDAR_DATE_RANGE"
|
||||||
| "SET_FILTERS"
|
| "SET_FILTERS"
|
||||||
| "SET_GROUP_BY_PROPERTY"
|
| "SET_GROUP_BY_PROPERTY"
|
||||||
| "RESET_TO_DEFAULT";
|
| "RESET_TO_DEFAULT";
|
||||||
@ -53,6 +55,7 @@ type ContextType = IssueViewProps & {
|
|||||||
setGroupByProperty: (property: TIssueGroupByOptions) => void;
|
setGroupByProperty: (property: TIssueGroupByOptions) => void;
|
||||||
setOrderBy: (property: TIssueOrderByOptions) => void;
|
setOrderBy: (property: TIssueOrderByOptions) => void;
|
||||||
setShowEmptyGroups: (property: boolean) => void;
|
setShowEmptyGroups: (property: boolean) => void;
|
||||||
|
setCalendarDateRange: (property: string) => void;
|
||||||
setFilters: (filters: Partial<IIssueFilterOptions>, saveToServer?: boolean) => void;
|
setFilters: (filters: Partial<IIssueFilterOptions>, saveToServer?: boolean) => void;
|
||||||
resetFilterToDefault: () => void;
|
resetFilterToDefault: () => void;
|
||||||
setNewFilterDefaultView: () => void;
|
setNewFilterDefaultView: () => void;
|
||||||
@ -64,6 +67,7 @@ type StateType = {
|
|||||||
groupByProperty: TIssueGroupByOptions;
|
groupByProperty: TIssueGroupByOptions;
|
||||||
orderBy: TIssueOrderByOptions;
|
orderBy: TIssueOrderByOptions;
|
||||||
showEmptyGroups: boolean;
|
showEmptyGroups: boolean;
|
||||||
|
calendarDateRange: string;
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
};
|
};
|
||||||
type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;
|
type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;
|
||||||
@ -73,6 +77,7 @@ export const initialState: StateType = {
|
|||||||
groupByProperty: null,
|
groupByProperty: null,
|
||||||
orderBy: "-created_at",
|
orderBy: "-created_at",
|
||||||
showEmptyGroups: true,
|
showEmptyGroups: true,
|
||||||
|
calendarDateRange: "",
|
||||||
filters: {
|
filters: {
|
||||||
type: null,
|
type: null,
|
||||||
priority: null,
|
priority: null,
|
||||||
@ -144,6 +149,18 @@ export const reducer: ReducerFunctionType = (state, action) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "SET_CALENDAR_DATE_RANGE": {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
calendarDateRange: payload?.calendarDateRange || "",
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...newState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case "SET_FILTERS": {
|
case "SET_FILTERS": {
|
||||||
const newState = {
|
const newState = {
|
||||||
...state,
|
...state,
|
||||||
@ -410,6 +427,37 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
[projectId, workspaceSlug, state, mutateMyViewProps]
|
[projectId, workspaceSlug, state, mutateMyViewProps]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setCalendarDateRange = useCallback(
|
||||||
|
(value: string) => {
|
||||||
|
dispatch({
|
||||||
|
type: "SET_CALENDAR_DATE_RANGE",
|
||||||
|
payload: {
|
||||||
|
calendarDateRange: value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!workspaceSlug || !projectId) return;
|
||||||
|
|
||||||
|
mutateMyViewProps((prevData) => {
|
||||||
|
if (!prevData) return prevData;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...prevData,
|
||||||
|
view_props: {
|
||||||
|
...state,
|
||||||
|
calendarDateRange: value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
saveDataToServer(workspaceSlug as string, projectId as string, {
|
||||||
|
...state,
|
||||||
|
calendarDateRange: value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[projectId, workspaceSlug, state, mutateMyViewProps]
|
||||||
|
);
|
||||||
|
|
||||||
const setFilters = useCallback(
|
const setFilters = useCallback(
|
||||||
(property: Partial<IIssueFilterOptions>, saveToServer = true) => {
|
(property: Partial<IIssueFilterOptions>, saveToServer = true) => {
|
||||||
Object.keys(property).forEach((key) => {
|
Object.keys(property).forEach((key) => {
|
||||||
@ -577,6 +625,8 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
setGroupByProperty,
|
setGroupByProperty,
|
||||||
orderBy: state.orderBy,
|
orderBy: state.orderBy,
|
||||||
showEmptyGroups: state.showEmptyGroups,
|
showEmptyGroups: state.showEmptyGroups,
|
||||||
|
calendarDateRange: state.calendarDateRange,
|
||||||
|
setCalendarDateRange,
|
||||||
setOrderBy,
|
setOrderBy,
|
||||||
setShowEmptyGroups,
|
setShowEmptyGroups,
|
||||||
filters: state.filters,
|
filters: state.filters,
|
||||||
|
124
apps/app/hooks/use-calendar-issues-view.tsx
Normal file
124
apps/app/hooks/use-calendar-issues-view.tsx
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
// contexts
|
||||||
|
import { issueViewContext } from "contexts/issue-view.context";
|
||||||
|
// services
|
||||||
|
import issuesService from "services/issues.service";
|
||||||
|
import cyclesService from "services/cycles.service";
|
||||||
|
import modulesService from "services/modules.service";
|
||||||
|
// types
|
||||||
|
import { IIssue } from "types";
|
||||||
|
// fetch-keys
|
||||||
|
import {
|
||||||
|
CYCLE_ISSUES_WITH_PARAMS,
|
||||||
|
MODULE_ISSUES_WITH_PARAMS,
|
||||||
|
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||||
|
VIEW_ISSUES,
|
||||||
|
} from "constants/fetch-keys";
|
||||||
|
|
||||||
|
const useCalendarIssuesView = () => {
|
||||||
|
const {
|
||||||
|
issueView,
|
||||||
|
calendarDateRange,
|
||||||
|
setCalendarDateRange,
|
||||||
|
filters,
|
||||||
|
setFilters,
|
||||||
|
resetFilterToDefault,
|
||||||
|
setNewFilterDefaultView,
|
||||||
|
setIssueView,
|
||||||
|
} = useContext(issueViewContext);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
|
const params: any = {
|
||||||
|
assignees: filters?.assignees ? filters?.assignees.join(",") : undefined,
|
||||||
|
state: filters?.state ? filters?.state.join(",") : undefined,
|
||||||
|
priority: filters?.priority ? filters?.priority.join(",") : undefined,
|
||||||
|
type: filters?.type ? filters?.type : undefined,
|
||||||
|
labels: filters?.labels ? filters?.labels.join(",") : undefined,
|
||||||
|
issue__assignees__id: filters?.issue__assignees__id
|
||||||
|
? filters?.issue__assignees__id.join(",")
|
||||||
|
: undefined,
|
||||||
|
issue__labels__id: filters?.issue__labels__id
|
||||||
|
? filters?.issue__labels__id.join(",")
|
||||||
|
: undefined,
|
||||||
|
created_by: filters?.created_by ? filters?.created_by.join(",") : undefined,
|
||||||
|
target_date: calendarDateRange,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data: projectCalendarIssues } = useSWR(
|
||||||
|
workspaceSlug && projectId
|
||||||
|
? PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params)
|
||||||
|
: null,
|
||||||
|
workspaceSlug && projectId
|
||||||
|
? () =>
|
||||||
|
issuesService.getIssuesWithParams(workspaceSlug.toString(), projectId.toString(), params)
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: cycleCalendarIssues } = useSWR(
|
||||||
|
workspaceSlug && projectId && cycleId
|
||||||
|
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
|
||||||
|
: null,
|
||||||
|
workspaceSlug && projectId && cycleId
|
||||||
|
? () =>
|
||||||
|
cyclesService.getCycleIssuesWithParams(
|
||||||
|
workspaceSlug.toString(),
|
||||||
|
projectId.toString(),
|
||||||
|
cycleId.toString(),
|
||||||
|
params
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: moduleCalendarIssues } = useSWR(
|
||||||
|
workspaceSlug && projectId && moduleId
|
||||||
|
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
|
||||||
|
: null,
|
||||||
|
workspaceSlug && projectId && moduleId
|
||||||
|
? () =>
|
||||||
|
modulesService.getModuleIssuesWithParams(
|
||||||
|
workspaceSlug.toString(),
|
||||||
|
projectId.toString(),
|
||||||
|
moduleId.toString(),
|
||||||
|
params
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: viewCalendarIssues } = useSWR(
|
||||||
|
workspaceSlug && projectId && viewId && params ? VIEW_ISSUES(viewId.toString(), params) : null,
|
||||||
|
workspaceSlug && projectId && viewId && params
|
||||||
|
? () =>
|
||||||
|
issuesService.getIssuesWithParams(workspaceSlug.toString(), projectId.toString(), params)
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
const calendarIssues = cycleId
|
||||||
|
? (cycleCalendarIssues as IIssue[])
|
||||||
|
: moduleId
|
||||||
|
? (moduleCalendarIssues as IIssue[])
|
||||||
|
: viewId
|
||||||
|
? (viewCalendarIssues as IIssue[])
|
||||||
|
: (projectCalendarIssues as IIssue[]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
issueView,
|
||||||
|
calendarIssues: calendarIssues ?? [],
|
||||||
|
calendarDateRange,
|
||||||
|
setCalendarDateRange,
|
||||||
|
filters,
|
||||||
|
setFilters,
|
||||||
|
params,
|
||||||
|
resetFilterToDefault,
|
||||||
|
setNewFilterDefaultView,
|
||||||
|
setIssueView,
|
||||||
|
} as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useCalendarIssuesView;
|
@ -33,6 +33,8 @@ const useIssuesView = () => {
|
|||||||
setOrderBy,
|
setOrderBy,
|
||||||
showEmptyGroups,
|
showEmptyGroups,
|
||||||
setShowEmptyGroups,
|
setShowEmptyGroups,
|
||||||
|
calendarDateRange,
|
||||||
|
setCalendarDateRange,
|
||||||
filters,
|
filters,
|
||||||
setFilters,
|
setFilters,
|
||||||
resetFilterToDefault,
|
resetFilterToDefault,
|
||||||
@ -175,6 +177,8 @@ const useIssuesView = () => {
|
|||||||
setOrderBy,
|
setOrderBy,
|
||||||
showEmptyGroups,
|
showEmptyGroups,
|
||||||
setShowEmptyGroups,
|
setShowEmptyGroups,
|
||||||
|
calendarDateRange,
|
||||||
|
setCalendarDateRange,
|
||||||
filters,
|
filters,
|
||||||
setFilters,
|
setFilters,
|
||||||
params,
|
params,
|
||||||
|
1
apps/app/types/issues.d.ts
vendored
1
apps/app/types/issues.d.ts
vendored
@ -273,7 +273,6 @@ export interface IIssueViewOptions {
|
|||||||
group_by: TIssueGroupByOptions;
|
group_by: TIssueGroupByOptions;
|
||||||
order_by: TIssueOrderByOptions;
|
order_by: TIssueOrderByOptions;
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
target_date: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IIssueAttachment {
|
export interface IIssueAttachment {
|
||||||
|
1
apps/app/types/projects.d.ts
vendored
1
apps/app/types/projects.d.ts
vendored
@ -55,6 +55,7 @@ type ProjectViewTheme = {
|
|||||||
issueView: TIssueViewOptions;
|
issueView: TIssueViewOptions;
|
||||||
groupByProperty: TIssueGroupByOptions;
|
groupByProperty: TIssueGroupByOptions;
|
||||||
orderBy: TIssueOrderByOptions;
|
orderBy: TIssueOrderByOptions;
|
||||||
|
calendarDateRange: string;
|
||||||
filters: IIssueFilterOptions;
|
filters: IIssueFilterOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user