Compare commits

...

4 Commits

15 changed files with 157 additions and 88 deletions

View File

@ -16,7 +16,6 @@ import {
IViewIssuesFilterStore,
IViewIssuesStore,
} from "store/issues";
import { IIssueCalendarViewStore } from "store/issue";
import { IQuickActionProps } from "../list/list-view-types";
import { EIssueActions } from "../types";
import { IGroupedIssues } from "store/issues/types";
@ -28,7 +27,6 @@ interface IBaseCalendarRoot {
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
calendarViewStore: IIssueCalendarViewStore;
QuickActions: FC<IQuickActionProps>;
issueActions: {
[EIssueActions.DELETE]: (issue: IIssue) => Promise<void>;
@ -77,13 +75,14 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
<div className="h-full w-full pt-4 bg-custom-background-100 overflow-hidden">
<DragDropContext onDragEnd={onDragEnd}>
<CalendarChart
issuesFilterStore={issuesFilterStore}
issues={issues}
groupedIssueIds={groupedIssueIds}
layout={displayFilters?.calendar?.layout}
showWeekends={displayFilters?.calendar?.show_weekends ?? false}
quickActions={(issue, customActionButton) => (
<QuickActions
customActionButton={customActionButton}
customActionButton={customActionButton}
issue={issue}
handleDelete={async () => handleIssues(issue.target_date ?? "", issue, EIssueActions.DELETE)}
handleUpdate={

View File

@ -10,8 +10,19 @@ import { Spinner } from "@plane/ui";
import { ICalendarWeek } from "./types";
import { IIssue } from "types";
import { IGroupedIssues, IIssueResponse } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
type Props = {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
issues: IIssueResponse | undefined;
groupedIssueIds: IGroupedIssues;
layout: "month" | "week" | undefined;
@ -27,7 +38,8 @@ type Props = {
};
export const CalendarChart: React.FC<Props> = observer((props) => {
const { issues, groupedIssueIds, layout, showWeekends, quickActions, quickAddCallback, viewId } = props;
const { issuesFilterStore, issues, groupedIssueIds, layout, showWeekends, quickActions, quickAddCallback, viewId } =
props;
const { calendar: calendarStore } = useMobxStore();
@ -45,7 +57,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
return (
<>
<div className="h-full w-full flex flex-col overflow-hidden">
<CalendarHeader />
<CalendarHeader issuesFilterStore={issuesFilterStore} />
<CalendarWeekHeader isLoading={!issues} showWeekends={showWeekends} />
<div className="h-full w-full overflow-y-auto">
{layout === "month" && (
@ -53,6 +65,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
{allWeeksOfActiveMonth &&
Object.values(allWeeksOfActiveMonth).map((week: ICalendarWeek, weekIndex) => (
<CalendarWeekDays
issuesFilterStore={issuesFilterStore}
key={weekIndex}
week={week}
issues={issues}
@ -67,6 +80,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
)}
{layout === "week" && (
<CalendarWeekDays
issuesFilterStore={issuesFilterStore}
week={calendarStore.allDaysOfActiveWeek}
issues={issues}
groupedIssueIds={groupedIssueIds}

View File

@ -11,8 +11,19 @@ import { renderDateFormat } from "helpers/date-time.helper";
import { MONTHS_LIST } from "constants/calendar";
import { IIssue } from "types";
import { IGroupedIssues, IIssueResponse } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
type Props = {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
date: ICalendarDate;
issues: IIssueResponse | undefined;
groupedIssueIds: IGroupedIssues;
@ -28,11 +39,18 @@ type Props = {
};
export const CalendarDayTile: React.FC<Props> = observer((props) => {
const { date, issues, groupedIssueIds, quickActions, enableQuickIssueCreate, quickAddCallback, viewId } = props;
const {
issuesFilterStore,
date,
issues,
groupedIssueIds,
quickActions,
enableQuickIssueCreate,
quickAddCallback,
viewId,
} = props;
const { issueFilter: issueFilterStore } = useMobxStore();
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const issueIdList = groupedIssueIds ? groupedIssueIds[renderDateFormat(date.date)] : null;

View File

@ -13,12 +13,29 @@ import { Check, ChevronUp } from "lucide-react";
import { TCalendarLayouts } from "types";
// constants
import { CALENDAR_LAYOUTS } from "constants/calendar";
import { EFilterType } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
interface ICalendarHeader {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
}
export const CalendarOptionsDropdown: React.FC<ICalendarHeader> = observer((props) => {
const { issuesFilterStore } = props;
export const CalendarOptionsDropdown: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { issueFilter: issueFilterStore, calendar: calendarStore } = useMobxStore();
const { calendar: calendarStore } = useMobxStore();
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
@ -35,18 +52,16 @@ export const CalendarOptionsDropdown: React.FC = observer(() => {
],
});
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
const calendarLayout = issuesFilterStore.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
const handleLayoutChange = (layout: TCalendarLayouts) => {
if (!workspaceSlug || !projectId) return;
issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), {
display_filters: {
calendar: {
...issueFilterStore.userDisplayFilters.calendar,
layout,
},
issuesFilterStore.updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.DISPLAY_FILTERS, {
calendar: {
...issuesFilterStore.issueFilters?.displayFilters?.calendar,
layout,
},
});
@ -56,16 +71,14 @@ export const CalendarOptionsDropdown: React.FC = observer(() => {
};
const handleToggleWeekends = () => {
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
if (!workspaceSlug || !projectId) return;
issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), {
display_filters: {
calendar: {
...issueFilterStore.userDisplayFilters.calendar,
show_weekends: !showWeekends,
},
issuesFilterStore.updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.DISPLAY_FILTERS, {
calendar: {
...issuesFilterStore.issueFilters?.displayFilters?.calendar,
show_weekends: !showWeekends,
},
});
};

View File

@ -6,11 +6,27 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { CalendarMonthsDropdown, CalendarOptionsDropdown } from "components/issues";
// icons
import { ChevronLeft, ChevronRight } from "lucide-react";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
export const CalendarHeader: React.FC = observer(() => {
const { issueFilter: issueFilterStore, calendar: calendarStore } = useMobxStore();
interface ICalendarHeader {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
}
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
export const CalendarHeader: React.FC<ICalendarHeader> = observer((props) => {
const { issuesFilterStore } = props;
const { calendar: calendarStore } = useMobxStore();
const calendarLayout = issuesFilterStore.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const { activeMonthDate, activeWeekDate } = calendarStore.calendarFilters;
@ -91,7 +107,7 @@ export const CalendarHeader: React.FC = observer(() => {
>
Today
</button>
<CalendarOptionsDropdown />
<CalendarOptionsDropdown issuesFilterStore={issuesFilterStore} />
</div>
</div>
);

View File

@ -13,7 +13,6 @@ export const CycleCalendarLayout: React.FC = observer(() => {
const {
cycleIssues: cycleIssueStore,
cycleIssuesFilter: cycleIssueFilterStore,
cycleIssueCalendarView: cycleIssueCalendarViewStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore();
@ -62,7 +61,6 @@ export const CycleCalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot
issueStore={cycleIssueStore}
issuesFilterStore={cycleIssueFilterStore}
calendarViewStore={cycleIssueCalendarViewStore}
QuickActions={CycleIssueQuickActions}
issueActions={issueActions}
viewId={cycleId.toString()}

View File

@ -13,7 +13,6 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
const {
moduleIssues: moduleIssueStore,
moduleIssuesFilter: moduleIssueFilterStore,
moduleIssueCalendarView: moduleIssueCalendarViewStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore();
@ -56,7 +55,6 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot
issueStore={moduleIssueStore}
issuesFilterStore={moduleIssueFilterStore}
calendarViewStore={moduleIssueCalendarViewStore}
QuickActions={ModuleIssueQuickActions}
issueActions={issueActions}
viewId={moduleId}

View File

@ -14,7 +14,6 @@ export const CalendarLayout: React.FC = observer(() => {
const {
projectIssues: issueStore,
issueCalendarView: issueCalendarViewStore,
projectIssuesFilter: projectIssueFiltersStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore();
@ -49,7 +48,6 @@ export const CalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot
issueStore={issueStore}
issuesFilterStore={projectIssueFiltersStore}
calendarViewStore={issueCalendarViewStore}
QuickActions={ProjectIssueQuickActions}
issueActions={issueActions}
handleDragDrop={handleDragDrop}

View File

@ -13,7 +13,6 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
const {
viewIssues: projectViewIssuesStore,
viewIssuesFilter: projectIssueViewFiltersStore,
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore();
@ -50,7 +49,6 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot
issueStore={projectViewIssuesStore}
issuesFilterStore={projectIssueViewFiltersStore}
calendarViewStore={projectViewIssueCalendarViewStore}
QuickActions={ProjectIssueQuickActions}
issueActions={issueActions}
handleDragDrop={handleDragDrop}

View File

@ -1,7 +1,4 @@
import { observer } from "mobx-react-lite";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { CalendarDayTile } from "components/issues";
// helpers
@ -10,8 +7,19 @@ import { renderDateFormat } from "helpers/date-time.helper";
import { ICalendarDate, ICalendarWeek } from "./types";
import { IIssue } from "types";
import { IGroupedIssues, IIssueResponse } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
type Props = {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
issues: IIssueResponse | undefined;
groupedIssueIds: IGroupedIssues;
week: ICalendarWeek | undefined;
@ -27,12 +35,19 @@ type Props = {
};
export const CalendarWeekDays: React.FC<Props> = observer((props) => {
const { issues, groupedIssueIds, week, quickActions, enableQuickIssueCreate, quickAddCallback, viewId } = props;
const {
issuesFilterStore,
issues,
groupedIssueIds,
week,
quickActions,
enableQuickIssueCreate,
quickAddCallback,
viewId,
} = props;
const { issueFilter: issueFilterStore } = useMobxStore();
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const showWeekends = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
if (!week) return null;
@ -47,6 +62,7 @@ export const CalendarWeekDays: React.FC<Props> = observer((props) => {
return (
<CalendarDayTile
issuesFilterStore={issuesFilterStore}
key={renderDateFormat(date.date)}
date={date}
issues={issues}

View File

@ -147,22 +147,22 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
</div>
)}
</Droppable>
</div>
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
{enableQuickIssueCreate && (
<KanBanQuickAddIssueForm
formKey="name"
groupId={getValueFromObject(_list, listKey) as string}
subGroupId={sub_group_id}
prePopulatedData={{
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
}}
quickAddCallback={quickAddCallback}
viewId={viewId}
/>
)}
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
{enableQuickIssueCreate && (
<KanBanQuickAddIssueForm
formKey="name"
groupId={getValueFromObject(_list, listKey) as string}
subGroupId={sub_group_id}
prePopulatedData={{
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
}}
quickAddCallback={quickAddCallback}
viewId={viewId}
/>
)}
</div>
</div>
{/* {isDragStarted && isDragDisabled && (

View File

@ -24,6 +24,7 @@ export const IssueBlocksList: FC<Props> = (props) => {
{issueIds && issueIds.length > 0 ? (
issueIds.map(
(issueId: string) =>
issueId != undefined &&
issues[issueId] && (
<IssueBlock
key={issues[issueId].id}

View File

@ -48,10 +48,11 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
const {
user: { currentProjectRole },
issueDetail: { fetchPeekIssueDetails },
project: { getProjectById },
} = useMobxStore();
const router = useRouter();
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const { workspaceSlug, projectId } = router.query;
const { setToastAlert } = useToast();
@ -138,7 +139,7 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
const handleCycleOrModuleChange = async () => {
if (!workspaceSlug || !projectId) return;
await fetchPeekIssueDetails(workspaceSlug, projectId, issue.id);
await fetchPeekIssueDetails(workspaceSlug.toString(), projectId.toString(), issue.id);
};
const handleEditLink = (link: ILinkDetails) => {
@ -167,6 +168,9 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
});
};
const projectDetails = workspaceSlug ? getProjectById(workspaceSlug.toString(), issue.project) : null;
const isEstimateEnabled = projectDetails?.estimate;
const minDate = issue.start_date ? new Date(issue.start_date) : null;
minDate?.setDate(minDate.getDate());
@ -230,19 +234,21 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
</div>
{/* estimate */}
<div className="flex items-center gap-2 w-full">
<div className="flex items-center gap-2 w-40 text-sm flex-shrink-0">
<Triangle className="h-4 w-4 flex-shrink-0 " />
<p>Estimate</p>
{isEstimateEnabled && (
<div className="flex items-center gap-2 w-full">
<div className="flex items-center gap-2 w-40 text-sm flex-shrink-0">
<Triangle className="h-4 w-4 flex-shrink-0 " />
<p>Estimate</p>
</div>
<div>
<SidebarEstimateSelect
value={issue.estimate_point}
onChange={handleEstimate}
disabled={disableUserActions}
/>
</div>
</div>
<div>
<SidebarEstimateSelect
value={issue.estimate_point}
onChange={handleEstimate}
disabled={disableUserActions}
/>
</div>
</div>
)}
{/* start date */}
<div className="flex items-center gap-2 w-full">

View File

@ -5,7 +5,7 @@ import { IssueBaseStore } from "store/issues";
import { IssueService } from "services/issue";
import { CycleService } from "services/cycle.service";
// types
import { CycleIssueResponse, TIssueGroupByOptions } from "types";
import { TIssueGroupByOptions } from "types";
import { IIssue } from "types/issues";
import { IIssueResponse, TLoader, IGroupedIssues, ISubGroupedIssues, TUnGroupedIssues, ViewFlags } from "../../types";
import { RootStore } from "store/root";
@ -83,9 +83,6 @@ export class CycleIssuesStore extends IssueBaseStore implements ICycleIssuesStor
cycleService;
issueService;
//projectId
currentProjectId: string | undefined;
//viewData
viewFlags = {
enableQuickAdd: true,
@ -174,8 +171,6 @@ export class CycleIssuesStore extends IssueBaseStore implements ICycleIssuesStor
try {
this.loader = loadType;
this.currentProjectId = projectId;
const params = this.rootStore?.cycleIssuesFilter?.appliedFilters;
const response = await this.cycleService.getCycleIssuesWithParams(workspaceSlug, projectId, cycleId, params);
@ -322,9 +317,10 @@ export class CycleIssuesStore extends IssueBaseStore implements ICycleIssuesStor
fetchAfterAddition = true,
projectId?: string
) => {
if (!this.currentProjectId && !projectId) return;
const activeProjectId = this.rootStore.project.projectId;
if (!activeProjectId && !projectId) return;
const projectIdToUpdate: string = this.currentProjectId || projectId || "";
const projectIdToUpdate: string = projectId || activeProjectId || "";
try {
const issueToCycle = await this.issueService.addIssueToCycle(workspaceSlug, projectIdToUpdate, cycleId, {

View File

@ -76,8 +76,6 @@ export class ModuleIssuesStore extends IssueBaseStore implements IModuleIssuesSt
moduleService;
issueService;
currentProjectId: string | undefined;
//viewData
viewFlags = {
enableQuickAdd: true,
@ -162,7 +160,6 @@ export class ModuleIssuesStore extends IssueBaseStore implements IModuleIssuesSt
) => {
if (!moduleId) return undefined;
this.currentProjectId = projectId;
try {
this.loader = loadType;
@ -314,9 +311,10 @@ export class ModuleIssuesStore extends IssueBaseStore implements IModuleIssuesSt
fetchAfterAddition = true,
projectId?: string
) => {
if (!this.currentProjectId && !projectId) return;
const activeProjectId = this.rootStore.project.projectId;
if (!activeProjectId && !projectId) return;
const projectIdToUpdate: string = this.currentProjectId || projectId || "";
const projectIdToUpdate: string = projectId || activeProjectId || "";
try {
const issueToModule = await this.moduleService.addIssuesToModule(workspaceSlug, projectIdToUpdate, moduleId, {