fix: calendar view mutation (#1042)

This commit is contained in:
Aaryan Khandelwal 2023-05-15 11:35:07 +05:30 committed by GitHub
parent dbbd9add99
commit 290318603d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 337 additions and 207 deletions

View File

@ -1,4 +1,17 @@
import React from "react";
// headless ui
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 {
addMonths,
addSevenDaysToDate,
@ -14,26 +27,17 @@ import {
updateDateWithMonth,
updateDateWithYear,
} from "helpers/calendar.helper";
import React from "react";
// constants
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 = {
isMonthlyView: boolean;
setIsMonthlyView: React.Dispatch<React.SetStateAction<boolean>>;
currentDate: Date;
setCurrentDate: React.Dispatch<React.SetStateAction<Date>>;
setCalendarDateRange: React.Dispatch<React.SetStateAction<ICalendarRange>>;
showWeekEnds: boolean;
setShowWeekEnds: React.Dispatch<React.SetStateAction<boolean>>;
changeDateRange: (startDate: Date, endDate: Date) => void;
};
export const CalendarHeader: React.FC<Props> = ({
@ -41,18 +45,16 @@ export const CalendarHeader: React.FC<Props> = ({
isMonthlyView,
currentDate,
setCurrentDate,
setCalendarDateRange,
showWeekEnds,
setShowWeekEnds,
changeDateRange,
}) => {
const updateDate = (date: Date) => {
setCurrentDate(date);
setCalendarDateRange({
startDate: startOfWeek(date),
endDate: lastDayOfWeek(date),
});
changeDateRange(startOfWeek(date), lastDayOfWeek(date));
};
return (
<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 ">
@ -93,9 +95,13 @@ export const CalendarHeader: React.FC<Props> = ({
<div className="grid grid-cols-4 border-t border-brand-base px-2">
{MONTHS_LIST.map((month) => (
<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 ${
isSameMonth(`${month.value}`, currentDate) ? "font-medium text-brand-base" : ""
isSameMonth(`${month.value}`, currentDate)
? "font-medium text-brand-base"
: ""
}`}
>
{month.label}
@ -116,10 +122,10 @@ export const CalendarHeader: React.FC<Props> = ({
updateDate(subtractMonths(currentDate, 1));
} else {
setCurrentDate(subtract7DaysToDate(currentDate));
setCalendarDateRange({
startDate: getCurrentWeekStartDate(subtract7DaysToDate(currentDate)),
endDate: getCurrentWeekEndDate(subtract7DaysToDate(currentDate)),
});
changeDateRange(
getCurrentWeekStartDate(subtract7DaysToDate(currentDate)),
getCurrentWeekEndDate(subtract7DaysToDate(currentDate))
);
}
}}
>
@ -132,10 +138,10 @@ export const CalendarHeader: React.FC<Props> = ({
updateDate(addMonths(currentDate, 1));
} else {
setCurrentDate(addSevenDaysToDate(currentDate));
setCalendarDateRange({
startDate: getCurrentWeekStartDate(addSevenDaysToDate(currentDate)),
endDate: getCurrentWeekEndDate(addSevenDaysToDate(currentDate)),
});
changeDateRange(
getCurrentWeekStartDate(addSevenDaysToDate(currentDate)),
getCurrentWeekEndDate(addSevenDaysToDate(currentDate))
);
}
}}
>
@ -152,10 +158,10 @@ export const CalendarHeader: React.FC<Props> = ({
updateDate(new Date());
} else {
setCurrentDate(new Date());
setCalendarDateRange({
startDate: getCurrentWeekStartDate(new Date()),
endDate: getCurrentWeekEndDate(new Date()),
});
changeDateRange(
getCurrentWeekStartDate(new Date()),
getCurrentWeekEndDate(new Date())
);
}
}}
>
@ -173,10 +179,7 @@ export const CalendarHeader: React.FC<Props> = ({
<CustomMenu.MenuItem
onClick={() => {
setIsMonthlyView(true);
setCalendarDateRange({
startDate: startOfWeek(currentDate),
endDate: lastDayOfWeek(currentDate),
});
changeDateRange(startOfWeek(currentDate), lastDayOfWeek(currentDate));
}}
className="w-52 text-sm text-brand-secondary"
>
@ -190,10 +193,10 @@ export const CalendarHeader: React.FC<Props> = ({
<CustomMenu.MenuItem
onClick={() => {
setIsMonthlyView(false);
setCalendarDateRange({
startDate: getCurrentWeekStartDate(currentDate),
endDate: getCurrentWeekEndDate(currentDate),
});
changeDateRange(
getCurrentWeekStartDate(currentDate),
getCurrentWeekEndDate(currentDate)
);
}}
className="w-52 text-sm text-brand-secondary"
>

View File

@ -1,28 +1,20 @@
import React, { useState } from "react";
// swr
import useSWR, { mutate } from "swr";
import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
// ui
import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd";
import { SingleCalendarDate, CalendarHeader } from "components/core";
import { mutate } from "swr";
import { Spinner } from "components/ui";
// hooks
import useIssuesView from "hooks/use-issues-view";
// react-beautiful-dnd
import { DragDropContext, DropResult } from "react-beautiful-dnd";
// services
import issuesService from "services/issues.service";
import cyclesService from "services/cycles.service";
import modulesService from "services/modules.service";
// fetch key
import {
CYCLE_CALENDAR_ISSUES,
MODULE_CALENDAR_ISSUES,
PROJECT_CALENDAR_ISSUES,
} from "constants/fetch-keys";
// helper
// hooks
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
// components
import { SingleCalendarDate, CalendarHeader } from "components/core";
// ui
import { Spinner } from "components/ui";
// helpers
import { renderDateFormat } from "helpers/date-time.helper";
import {
startOfWeek,
@ -31,8 +23,15 @@ import {
weekDayInterval,
formatDate,
} from "helpers/calendar.helper";
// type
// 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 = {
handleEditIssue: (issue: IIssue) => void;
@ -53,93 +52,31 @@ export const CalendarView: React.FC<Props> = ({
const [currentDate, setCurrentDate] = useState(new Date());
const [isMonthlyView, setIsMonthlyView] = useState(true);
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
const { params } = useIssuesView();
const [calendarDateRange, setCalendarDateRange] = useState<ICalendarRange>({
const [calendarDates, setCalendarDates] = useState<ICalendarRange>({
startDate: startOfWeek(currentDate),
endDate: lastDayOfWeek(currentDate),
});
const { data: projectCalendarIssues } = useSWR(
workspaceSlug && projectId ? PROJECT_CALENDAR_ISSUES(projectId as string) : null,
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 router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
const { data: cycleCalendarIssues } = useSWR(
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 { calendarIssues, params, setCalendarDateRange } = useCalendarIssuesView();
const totalDate = eachDayOfInterval({
start: calendarDateRange.startDate,
end: calendarDateRange.endDate,
start: calendarDates.startDate,
end: calendarDates.endDate,
});
const onlyWeekDays = weekDayInterval({
start: calendarDateRange.startDate,
end: calendarDateRange.endDate,
start: calendarDates.startDate,
end: calendarDates.endDate,
});
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 filterIssue =
calendarIssues && calendarIssues.length > 0
calendarIssues.length > 0
? calendarIssues.filter(
(issue) =>
issue.target_date && renderDateFormat(issue.target_date) === renderDateFormat(date)
@ -170,13 +107,16 @@ export const CalendarView: React.FC<Props> = ({
const { source, destination, draggableId } = result;
if (!destination || !workspaceSlug || !projectId) return;
if (source.droppableId === destination.droppableId) return;
const fetchKey = cycleId
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
: moduleId
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
: PROJECT_CALENDAR_ISSUES(projectId as string);
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
: viewId
? VIEW_ISSUES(viewId.toString(), params)
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params);
mutate<IIssue[]>(
fetchKey,
@ -187,16 +127,38 @@ export const CalendarView: React.FC<Props> = ({
...p,
target_date: destination.droppableId,
};
return p;
}),
false
);
issuesService.patchIssue(workspaceSlug as string, projectId as string, draggableId, {
target_date: destination?.droppableId,
});
issuesService
.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;
return calendarIssues ? (
@ -210,7 +172,7 @@ export const CalendarView: React.FC<Props> = ({
setShowWeekEnds={setShowWeekEnds}
currentDate={currentDate}
setCurrentDate={setCurrentDate}
setCalendarDateRange={setCalendarDateRange}
changeDateRange={changeDateRange}
/>
<div

View File

@ -10,6 +10,7 @@ import { DraggableProvided, DraggableStateSnapshot } from "react-beautiful-dnd";
// services
import issuesService from "services/issues.service";
// hooks
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
import useIssuesProperties from "hooks/use-issue-properties";
import useToast from "hooks/use-toast";
// components
@ -29,9 +30,10 @@ import { copyTextToClipboard, truncateText } from "helpers/string.helper";
import { IIssue } from "types";
// fetch-keys
import {
CYCLE_CALENDAR_ISSUES,
MODULE_CALENDAR_ISSUES,
PROJECT_CALENDAR_ISSUES,
CYCLE_ISSUES_WITH_PARAMS,
MODULE_ISSUES_WITH_PARAMS,
PROJECT_ISSUES_LIST_WITH_PARAMS,
VIEW_ISSUES,
} from "constants/fetch-keys";
type Props = {
@ -54,10 +56,12 @@ export const SingleCalendarIssue: React.FC<Props> = ({
isNotAllowed,
}) => {
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
const { setToastAlert } = useToast();
const { params } = useCalendarIssuesView();
const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string);
const partialUpdateIssue = useCallback(
@ -65,20 +69,25 @@ export const SingleCalendarIssue: React.FC<Props> = ({
if (!workspaceSlug || !projectId) return;
const fetchKey = cycleId
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
: moduleId
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
: PROJECT_CALENDAR_ISSUES(projectId as string);
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
: viewId
? VIEW_ISSUES(viewId.toString(), params)
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params);
mutate<IIssue[]>(
fetchKey,
(prevData) =>
(prevData ?? []).map((p) => {
if (p.id === issueId)
if (p.id === issueId) {
return {
...p,
formData,
...formData,
assignees: formData?.assignees_list ?? p.assignees,
};
}
return p;
}),
false
@ -87,13 +96,13 @@ export const SingleCalendarIssue: React.FC<Props> = ({
issuesService
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData)
.then(() => {
mutate<IIssue[]>(fetchKey);
mutate(fetchKey);
})
.catch((error) => {
console.log(error);
});
},
[workspaceSlug, projectId, cycleId, moduleId]
[workspaceSlug, projectId, cycleId, moduleId, params]
);
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"
>
<span
className="h-1.5 w-1.5 rounded-full"
className="h-1.5 w-1.5 rounded-full"
style={{
backgroundColor: label?.color && label.color !== "" ? label.color : "#000",
}}

View File

@ -9,22 +9,21 @@ import { Dialog, Transition } from "@headlessui/react";
// services
import issueServices from "services/issues.service";
// hooks
import useToast from "hooks/use-toast";
import useIssuesView from "hooks/use-issues-view";
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
import useToast from "hooks/use-toast";
// icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui
import { SecondaryButton, DangerButton } from "components/ui";
// types
import type { CycleIssueResponse, IIssue, ModuleIssueResponse } from "types";
import type { IIssue } from "types";
// fetch-keys
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";
type Props = {
@ -37,9 +36,10 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
const { issueView, params } = useIssuesView();
const { params: calendarParams } = useCalendarIssuesView();
const { setToastAlert } = useToast();
@ -61,12 +61,18 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
.then(() => {
if (issueView === "calendar") {
const calendarFetchKey = cycleId
? CYCLE_CALENDAR_ISSUES(projectId as string, cycleId as string)
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), calendarParams)
: moduleId
? MODULE_CALENDAR_ISSUES(projectId as string, moduleId as string)
: PROJECT_CALENDAR_ISSUES(projectId as string);
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), calendarParams)
: 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 {
if (cycleId) mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
else if (moduleId) mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params));

View File

@ -12,14 +12,14 @@ import modulesService from "services/modules.service";
import issuesService from "services/issues.service";
// hooks
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";
// components
import { IssueForm } from "components/issues";
// hooks
import useIssuesView from "hooks/use-issues-view";
// types
import type { IIssue } from "types";
// fetch keys
// fetch-keys
import {
PROJECT_ISSUES_DETAILS,
PROJECT_ISSUES_LIST,
@ -31,9 +31,7 @@ import {
MODULE_ISSUES_WITH_PARAMS,
CYCLE_DETAILS,
MODULE_DETAILS,
PROJECT_CALENDAR_ISSUES,
CYCLE_CALENDAR_ISSUES,
MODULE_CALENDAR_ISSUES,
VIEW_ISSUES,
} from "constants/fetch-keys";
export interface IssuesModalProps {
@ -56,9 +54,10 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
const [activeProject, setActiveProject] = useState<string | null>(null);
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
const { issueView, params } = useIssuesView();
const { params: calendarParams } = useCalendarIssuesView();
if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId 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>) => {
await issuesService
.createIssues(workspaceSlug as string, activeProject ?? "", payload)
.then((res) => {
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.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();
setToastAlert({
@ -173,29 +173,8 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
if (isUpdatingSingleIssue) {
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
} else {
if (issueView === "calendar") {
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, (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 (issueView === "calendar") mutate(calendarFetchKey);
else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
}
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);

View File

@ -1,13 +1,14 @@
import { IAnalyticsParams, IJiraMetadata } from "types";
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 priorityKey = priority ? priority.split(",") : [];
let assigneesKey = assignees ? assignees.split(",") : [];
let createdByKey = created_by ? created_by.split(",") : [];
let labelsKey = labels ? labels.split(",") : [];
const targetDateKey = target_date ?? "";
const type = params.type ? params.type.toUpperCase() : "NULL";
const groupBy = params.group_by ? params.group_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("_");
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";
@ -148,14 +149,6 @@ export const GITHUB_REPOSITORY_INFO = (workspaceSlug: string, repoName: string)
export const SLACK_CHANNEL_INFO = (workspaceSlug: string, projectId: string) =>
`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
export const RECENT_PAGES_LIST = (projectId: string) =>
`RECENT_PAGES_LIST_${projectId.toUpperCase()}`;

View File

@ -34,6 +34,7 @@ type IssueViewProps = {
groupByProperty: TIssueGroupByOptions;
orderBy: TIssueOrderByOptions;
showEmptyGroups: boolean;
calendarDateRange: string;
filters: IIssueFilterOptions;
};
@ -43,6 +44,7 @@ type ReducerActionType = {
| "SET_ISSUE_VIEW"
| "SET_ORDER_BY_PROPERTY"
| "SET_SHOW_EMPTY_STATES"
| "SET_CALENDAR_DATE_RANGE"
| "SET_FILTERS"
| "SET_GROUP_BY_PROPERTY"
| "RESET_TO_DEFAULT";
@ -53,6 +55,7 @@ type ContextType = IssueViewProps & {
setGroupByProperty: (property: TIssueGroupByOptions) => void;
setOrderBy: (property: TIssueOrderByOptions) => void;
setShowEmptyGroups: (property: boolean) => void;
setCalendarDateRange: (property: string) => void;
setFilters: (filters: Partial<IIssueFilterOptions>, saveToServer?: boolean) => void;
resetFilterToDefault: () => void;
setNewFilterDefaultView: () => void;
@ -64,6 +67,7 @@ type StateType = {
groupByProperty: TIssueGroupByOptions;
orderBy: TIssueOrderByOptions;
showEmptyGroups: boolean;
calendarDateRange: string;
filters: IIssueFilterOptions;
};
type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;
@ -73,6 +77,7 @@ export const initialState: StateType = {
groupByProperty: null,
orderBy: "-created_at",
showEmptyGroups: true,
calendarDateRange: "",
filters: {
type: 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": {
const newState = {
...state,
@ -410,6 +427,37 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
[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(
(property: Partial<IIssueFilterOptions>, saveToServer = true) => {
Object.keys(property).forEach((key) => {
@ -577,6 +625,8 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
setGroupByProperty,
orderBy: state.orderBy,
showEmptyGroups: state.showEmptyGroups,
calendarDateRange: state.calendarDateRange,
setCalendarDateRange,
setOrderBy,
setShowEmptyGroups,
filters: state.filters,

View 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;

View File

@ -33,6 +33,8 @@ const useIssuesView = () => {
setOrderBy,
showEmptyGroups,
setShowEmptyGroups,
calendarDateRange,
setCalendarDateRange,
filters,
setFilters,
resetFilterToDefault,
@ -175,6 +177,8 @@ const useIssuesView = () => {
setOrderBy,
showEmptyGroups,
setShowEmptyGroups,
calendarDateRange,
setCalendarDateRange,
filters,
setFilters,
params,

View File

@ -273,7 +273,6 @@ export interface IIssueViewOptions {
group_by: TIssueGroupByOptions;
order_by: TIssueOrderByOptions;
filters: IIssueFilterOptions;
target_date: string;
}
export interface IIssueAttachment {

View File

@ -55,6 +55,7 @@ type ProjectViewTheme = {
issueView: TIssueViewOptions;
groupByProperty: TIssueGroupByOptions;
orderBy: TIssueOrderByOptions;
calendarDateRange: string;
filters: IIssueFilterOptions;
};