chore: implemented drag and drop between dates for project issues, cycle, module, and project views for calendar layout (#2535)

This commit is contained in:
guru_sainath 2023-10-25 16:09:50 +05:30 committed by GitHub
parent cea39c758e
commit a6d741e784
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 492 additions and 63 deletions

View File

@ -29,35 +29,46 @@ export const CalendarDayTile: React.FC<Props> = observer((props) => {
const issuesList = issues ? (issues as IIssueGroupedStructure)[renderDateFormat(date.date)] : null; const issuesList = issues ? (issues as IIssueGroupedStructure)[renderDateFormat(date.date)] : null;
return ( return (
<Droppable droppableId={renderDateFormat(date.date)}> <>
{(provided, snapshot) => ( <div className="w-full h-full relative flex flex-col bg-custom-background-90">
{/* header */}
<div <div
className={`flex-grow p-2 space-y-1 w-full flex flex-col overflow-hidden ${ className={`text-xs text-right flex-shrink-0 py-1 px-2 ${
snapshot.isDraggingOver || date.date.getDay() === 0 || date.date.getDay() === 6 calendarLayout === "month" // if month layout, highlight current month days
? date.is_current_month
? "font-medium"
: "text-custom-text-300"
: "font-medium" // if week layout, highlight all days
} ${
date.date.getDay() === 0 || date.date.getDay() === 6
? "bg-custom-background-90" ? "bg-custom-background-90"
: "bg-custom-background-100" : "bg-custom-background-100"
} ${calendarLayout === "month" ? "min-h-[9rem]" : ""}`} }`}
{...provided.droppableProps}
ref={provided.innerRef}
> >
<> {date.date.getDate() === 1 && MONTHS_LIST[date.date.getMonth() + 1].shortTitle + " "}
<div {date.date.getDate()}
className={`text-xs text-right ${
calendarLayout === "month" // if month layout, highlight current month days
? date.is_current_month
? "font-medium"
: "text-custom-text-300"
: "font-medium" // if week layout, highlight all days
}`}
>
{date.date.getDate() === 1 && MONTHS_LIST[date.date.getMonth() + 1].shortTitle + " "}
{date.date.getDate()}
</div>
<CalendarIssueBlocks issues={issuesList} quickActions={quickActions} />
{provided.placeholder}
</>
</div> </div>
)}
</Droppable> {/* content */}
<div className="w-full h-full">
<Droppable droppableId={renderDateFormat(date.date)} isDropDisabled={false}>
{(provided, snapshot) => (
<div
className={`h-full w-full overflow-y-auto select-none ${
snapshot.isDraggingOver || date.date.getDay() === 0 || date.date.getDay() === 6
? "bg-custom-background-90"
: "bg-custom-background-100"
} ${calendarLayout === "month" ? "min-h-[9rem]" : ""}`}
{...provided.droppableProps}
ref={provided.innerRef}
>
<CalendarIssueBlocks issues={issuesList} quickActions={quickActions} />
{provided.placeholder}
</div>
)}
</Droppable>
</div>
</div>
</>
); );
}); });

View File

@ -17,42 +17,46 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
return ( return (
<div className="space-y-2 h-full w-full overflow-y-auto p-0.5"> <>
{issues?.map((issue, index) => ( {issues?.map((issue, index) => (
<Draggable key={issue.id} draggableId={issue.id} index={index}> <Draggable key={issue.id} draggableId={issue.id} index={index}>
{(provided, snapshot) => ( {(provided, snapshot) => (
<Link href={`/${workspaceSlug?.toString()}/projects/${issue.project}/issues/${issue.id}`}> <div
<a className="p-1 px-2"
className={`group/calendar-block h-8 w-full shadow-custom-shadow-2xs rounded py-1.5 px-1 flex items-center gap-1.5 border-[0.5px] border-custom-border-100 ${ {...provided.draggableProps}
snapshot.isDragging {...provided.dragHandleProps}
? "shadow-custom-shadow-rg bg-custom-background-90" ref={provided.innerRef}
: "bg-custom-background-100 hover:bg-custom-background-90" >
}`} <Link href={`/${workspaceSlug?.toString()}/projects/${issue.project}/issues/${issue.id}`}>
{...provided.draggableProps} <a
{...provided.dragHandleProps} className={`group/calendar-block h-8 w-full shadow-custom-shadow-2xs rounded py-1.5 px-1 flex items-center gap-1.5 border-[0.5px] border-custom-border-100 ${
ref={provided.innerRef} snapshot.isDragging
> ? "shadow-custom-shadow-rg bg-custom-background-90"
<span : "bg-custom-background-100 hover:bg-custom-background-90"
className="h-full w-0.5 rounded flex-shrink-0" }`}
style={{ >
backgroundColor: issue.state_detail.color, <span
}} className="h-full w-0.5 rounded flex-shrink-0"
/> style={{
<div className="text-xs text-custom-text-300 flex-shrink-0"> backgroundColor: issue.state_detail.color,
{issue.project_detail.identifier}-{issue.sequence_id} }}
</div> />
<h6 className="text-xs flex-grow truncate">{issue.name}</h6> <div className="text-xs text-custom-text-300 flex-shrink-0">
<div className="hidden group-hover/calendar-block:block">{quickActions(issue)}</div> {issue.project_detail.identifier}-{issue.sequence_id}
{/* <IssueQuickActions </div>
<h6 className="text-xs flex-grow truncate">{issue.name}</h6>
<div className="hidden group-hover/calendar-block:block">{quickActions(issue)}</div>
{/* <IssueQuickActions
issue={issue} issue={issue}
handleDelete={async () => handleIssues(issue.target_date ?? "", issue, "delete")} handleDelete={async () => handleIssues(issue.target_date ?? "", issue, "delete")}
handleUpdate={async (data) => handleIssues(issue.target_date ?? "", data, "update")} handleUpdate={async (data) => handleIssues(issue.target_date ?? "", data, "update")}
/> */} /> */}
</a> </a>
</Link> </Link>
</div>
)} )}
</Draggable> </Draggable>
))} ))}
</div> </>
); );
}); });

View File

@ -11,12 +11,16 @@ import { IIssueGroupedStructure } from "store/issue";
import { IIssue } from "types"; import { IIssue } from "types";
export const CycleCalendarLayout: React.FC = observer(() => { export const CycleCalendarLayout: React.FC = observer(() => {
const { cycleIssue: cycleIssueStore, issueFilter: issueFilterStore, issueDetail: issueDetailStore } = useMobxStore(); const {
cycleIssue: cycleIssueStore,
issueFilter: issueFilterStore,
issueDetail: issueDetailStore,
cycleIssueCalendarView: cycleIssueCalendarViewStore,
} = useMobxStore();
const router = useRouter(); const router = useRouter();
const { workspaceSlug, cycleId } = router.query; const { workspaceSlug, cycleId } = router.query;
// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => { const onDragEnd = (result: DropResult) => {
if (!result) return; if (!result) return;
@ -26,7 +30,7 @@ export const CycleCalendarLayout: React.FC = observer(() => {
// return if dropped on the same date // return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return; if (result.destination.droppableId === result.source.droppableId) return;
// issueKanBanViewStore?.handleDragDrop(result.source, result.destination); cycleIssueCalendarViewStore?.handleDragDrop(result.source, result.destination);
}; };
const issues = cycleIssueStore.getIssues; const issues = cycleIssueStore.getIssues;

View File

@ -15,12 +15,12 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
moduleIssue: moduleIssueStore, moduleIssue: moduleIssueStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
moduleIssueCalendarView: moduleIssueCalendarViewStore,
} = useMobxStore(); } = useMobxStore();
const router = useRouter(); const router = useRouter();
const { workspaceSlug, moduleId } = router.query; const { workspaceSlug, moduleId } = router.query;
// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => { const onDragEnd = (result: DropResult) => {
if (!result) return; if (!result) return;
@ -30,7 +30,7 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
// return if dropped on the same date // return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return; if (result.destination.droppableId === result.source.droppableId) return;
// issueKanBanViewStore?.handleDragDrop(result.source, result.destination); moduleIssueCalendarViewStore?.handleDragDrop(result.source, result.destination);
}; };
const issues = moduleIssueStore.getIssues; const issues = moduleIssueStore.getIssues;

View File

@ -11,12 +11,16 @@ import { IIssueGroupedStructure } from "store/issue";
import { IIssue } from "types"; import { IIssue } from "types";
export const CalendarLayout: React.FC = observer(() => { export const CalendarLayout: React.FC = observer(() => {
const { issue: issueStore, issueFilter: issueFilterStore, issueDetail: issueDetailStore } = useMobxStore(); const {
issue: issueStore,
issueFilter: issueFilterStore,
issueDetail: issueDetailStore,
issueCalendarView: issueCalendarViewStore,
} = useMobxStore();
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => { const onDragEnd = (result: DropResult) => {
if (!result) return; if (!result) return;
@ -26,7 +30,7 @@ export const CalendarLayout: React.FC = observer(() => {
// return if dropped on the same date // return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return; if (result.destination.droppableId === result.source.droppableId) return;
// issueKanBanViewStore?.handleDragDrop(result.source, result.destination); issueCalendarViewStore?.handleDragDrop(result.source, result.destination);
}; };
const issues = issueStore.getIssues; const issues = issueStore.getIssues;

View File

@ -15,12 +15,12 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
projectViewIssues: projectViewIssuesStore, projectViewIssues: projectViewIssuesStore,
issueFilter: issueFilterStore, issueFilter: issueFilterStore,
issueDetail: issueDetailStore, issueDetail: issueDetailStore,
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
} = useMobxStore(); } = useMobxStore();
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => { const onDragEnd = (result: DropResult) => {
if (!result) return; if (!result) return;
@ -30,7 +30,7 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
// return if dropped on the same date // return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return; if (result.destination.droppableId === result.source.droppableId) return;
// issueKanBanViewStore?.handleDragDrop(result.source, result.destination); projectViewIssueCalendarViewStore?.handleDragDrop(result.source, result.destination);
}; };
const issues = projectViewIssuesStore.getIssues; const issues = projectViewIssuesStore.getIssues;

View File

@ -0,0 +1,89 @@
import { action, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IIssueType } from "./cycle_issue.store";
export interface ICycleIssueCalendarViewStore {
// actions
handleDragDrop: (source: any, destination: any) => void;
}
export class CycleIssueCalendarViewStore implements ICycleIssueCalendarViewStore {
// root store
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// actions
handleDragDrop: action,
});
this.rootStore = _rootStore;
}
handleDragDrop = async (source: any, destination: any) => {
const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
const projectId = this.rootStore?.project?.projectId;
const cycleId = this.rootStore?.cycle?.cycleId;
const issueType: IIssueType | null = this.rootStore?.cycleIssue?.getIssueType;
const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
const currentIssues: any = this.rootStore.cycleIssue.getIssues;
if (workspaceSlug && projectId && cycleId && issueType && issueLayout === "calendar" && currentIssues) {
// update issue payload
let updateIssue: any = {
workspaceSlug: workspaceSlug,
projectId: projectId,
};
const droppableSourceColumnId = source.droppableId;
const droppableDestinationColumnId = destination.droppableId;
if (droppableSourceColumnId === droppableDestinationColumnId) return;
if (droppableSourceColumnId != droppableDestinationColumnId) {
// horizontal
const _sourceIssues = currentIssues[droppableSourceColumnId];
let _destinationIssues = currentIssues[droppableDestinationColumnId] || [];
const [removed] = _sourceIssues.splice(source.index, 1);
if (_destinationIssues && _destinationIssues.length > 0)
_destinationIssues.splice(destination.index, 0, {
...removed,
target_date: droppableDestinationColumnId,
});
else _destinationIssues = [..._destinationIssues, { ...removed, target_date: droppableDestinationColumnId }];
updateIssue = { ...updateIssue, issueId: removed?.id, target_date: droppableDestinationColumnId };
currentIssues[droppableSourceColumnId] = _sourceIssues;
currentIssues[droppableDestinationColumnId] = _destinationIssues;
}
const reorderedIssues = {
...this.rootStore?.cycleIssue.issues,
[cycleId]: {
...this.rootStore?.cycleIssue.issues?.[cycleId],
[issueType]: {
...this.rootStore?.cycleIssue.issues?.[cycleId]?.[issueType],
[issueType]: currentIssues,
},
},
};
runInAction(() => {
this.rootStore.cycleIssue.issues = { ...reorderedIssues };
});
this.rootStore.issueDetail?.updateIssue(
updateIssue.workspaceSlug,
updateIssue.projectId,
updateIssue.issueId,
updateIssue
);
}
return;
};
}

View File

@ -1,4 +1,5 @@
export * from "./cycle_issue_filters.store"; export * from "./cycle_issue_filters.store";
export * from "./cycle_issue_kanban_view.store"; export * from "./cycle_issue_kanban_view.store";
export * from "./cycle_issue_calendar_view.store";
export * from "./cycle_issue.store"; export * from "./cycle_issue.store";
export * from "./cycles.store"; export * from "./cycles.store";

View File

@ -2,4 +2,5 @@ export * from "./issue_detail.store";
export * from "./issue_draft.store"; export * from "./issue_draft.store";
export * from "./issue_filters.store"; export * from "./issue_filters.store";
export * from "./issue_kanban_view.store"; export * from "./issue_kanban_view.store";
export * from "./issue_calendar_view.store";
export * from "./issue.store"; export * from "./issue.store";

View File

@ -0,0 +1,88 @@
import { action, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IIssueType } from "./issue.store";
export interface IIssueCalendarViewStore {
// actions
handleDragDrop: (source: any, destination: any) => void;
}
export class IssueCalendarViewStore implements IIssueCalendarViewStore {
// root store
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// actions
handleDragDrop: action,
});
this.rootStore = _rootStore;
}
handleDragDrop = async (source: any, destination: any) => {
const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
const projectId = this.rootStore?.project?.projectId;
const issueType: IIssueType | null = this.rootStore?.issue?.getIssueType;
const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
const currentIssues: any = this.rootStore.issue.getIssues;
if (workspaceSlug && projectId && issueType && issueLayout === "calendar" && currentIssues) {
// update issue payload
let updateIssue: any = {
workspaceSlug: workspaceSlug,
projectId: projectId,
};
const droppableSourceColumnId = source.droppableId;
const droppableDestinationColumnId = destination.droppableId;
if (droppableSourceColumnId === droppableDestinationColumnId) return;
// horizontal
if (droppableSourceColumnId != droppableDestinationColumnId) {
const _sourceIssues = currentIssues[droppableSourceColumnId];
let _destinationIssues = currentIssues[droppableDestinationColumnId] || [];
const [removed] = _sourceIssues.splice(source.index, 1);
if (_destinationIssues && _destinationIssues.length > 0)
_destinationIssues.splice(destination.index, 0, {
...removed,
target_date: droppableDestinationColumnId,
});
else _destinationIssues = [..._destinationIssues, { ...removed, target_date: droppableDestinationColumnId }];
updateIssue = { ...updateIssue, issueId: removed?.id, target_date: droppableDestinationColumnId };
currentIssues[droppableSourceColumnId] = _sourceIssues;
currentIssues[droppableDestinationColumnId] = _destinationIssues;
}
const reorderedIssues = {
...this.rootStore?.issue.issues,
[projectId]: {
...this.rootStore?.issue.issues?.[projectId],
[issueType]: {
...this.rootStore?.issue.issues?.[projectId]?.[issueType],
[issueType]: currentIssues,
},
},
};
runInAction(() => {
this.rootStore.issue.issues = { ...reorderedIssues };
});
this.rootStore.issueDetail?.updateIssue(
updateIssue.workspaceSlug,
updateIssue.projectId,
updateIssue.issueId,
updateIssue
);
}
return;
};
}

View File

@ -1,4 +1,5 @@
export * from "./module_filters.store"; export * from "./module_filters.store";
export * from "./module_issue_kanban_view.store"; export * from "./module_issue_kanban_view.store";
export * from "./module_issue_calendar_view.store";
export * from "./module_issue.store"; export * from "./module_issue.store";
export * from "./modules.store"; export * from "./modules.store";

View File

@ -0,0 +1,89 @@
import { action, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IIssueType } from "./module_issue.store";
export interface IModuleIssueCalendarViewStore {
// actions
handleDragDrop: (source: any, destination: any) => void;
}
export class ModuleIssueCalendarViewStore implements IModuleIssueCalendarViewStore {
// root store
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// actions
handleDragDrop: action,
});
this.rootStore = _rootStore;
}
handleDragDrop = async (source: any, destination: any) => {
const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
const projectId = this.rootStore?.project?.projectId;
const moduleId = this.rootStore?.module?.moduleId;
const issueType: IIssueType | null = this.rootStore?.moduleIssue?.getIssueType;
const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
const currentIssues: any = this.rootStore.moduleIssue.getIssues;
if (workspaceSlug && projectId && moduleId && issueType && issueLayout === "calendar" && currentIssues) {
// update issue payload
let updateIssue: any = {
workspaceSlug: workspaceSlug,
projectId: projectId,
};
const droppableSourceColumnId = source.droppableId;
const droppableDestinationColumnId = destination.droppableId;
if (droppableSourceColumnId === droppableDestinationColumnId) return;
if (droppableSourceColumnId != droppableDestinationColumnId) {
// horizontal
const _sourceIssues = currentIssues[droppableSourceColumnId];
let _destinationIssues = currentIssues[droppableDestinationColumnId] || [];
const [removed] = _sourceIssues.splice(source.index, 1);
if (_destinationIssues && _destinationIssues.length > 0)
_destinationIssues.splice(destination.index, 0, {
...removed,
target_date: droppableDestinationColumnId,
});
else _destinationIssues = [..._destinationIssues, { ...removed, target_date: droppableDestinationColumnId }];
updateIssue = { ...updateIssue, issueId: removed?.id, target_date: droppableDestinationColumnId };
currentIssues[droppableSourceColumnId] = _sourceIssues;
currentIssues[droppableDestinationColumnId] = _destinationIssues;
}
const reorderedIssues = {
...this.rootStore?.moduleIssue.issues,
[moduleId]: {
...this.rootStore?.moduleIssue.issues?.[moduleId],
[issueType]: {
...this.rootStore?.moduleIssue.issues?.[moduleId]?.[issueType],
[issueType]: currentIssues,
},
},
};
runInAction(() => {
this.rootStore.moduleIssue.issues = { ...reorderedIssues };
});
this.rootStore.issueDetail?.updateIssue(
updateIssue.workspaceSlug,
updateIssue.projectId,
updateIssue.issueId,
updateIssue
);
}
return;
};
}

View File

@ -1,3 +1,5 @@
export * from "./project_view_filters.store"; export * from "./project_view_filters.store";
export * from "./project_view_issues.store"; export * from "./project_view_issues.store";
export * from "./project_views.store"; export * from "./project_views.store";
export * from "./project_view_issue_calendar_view.store";

View File

@ -0,0 +1,89 @@
import { action, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IIssueType } from "./project_view_issues.store";
export interface IProjectViewIssueCalendarViewStore {
// actions
handleDragDrop: (source: any, destination: any) => void;
}
export class ProjectViewIssueCalendarViewStore implements IProjectViewIssueCalendarViewStore {
// root store
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// actions
handleDragDrop: action,
});
this.rootStore = _rootStore;
}
handleDragDrop = async (source: any, destination: any) => {
const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
const projectId = this.rootStore?.project?.projectId;
const viewId = this.rootStore?.projectViews?.viewId;
const issueType: IIssueType | null = this.rootStore?.projectViewIssues?.getIssueType;
const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
const currentIssues: any = this.rootStore.projectViewIssues.getIssues;
if (workspaceSlug && projectId && viewId && issueType && issueLayout === "calendar" && currentIssues) {
// update issue payload
let updateIssue: any = {
workspaceSlug: workspaceSlug,
projectId: projectId,
};
const droppableSourceColumnId = source.droppableId;
const droppableDestinationColumnId = destination.droppableId;
if (droppableSourceColumnId === droppableDestinationColumnId) return;
if (droppableSourceColumnId != droppableDestinationColumnId) {
// horizontal
const _sourceIssues = currentIssues[droppableSourceColumnId];
let _destinationIssues = currentIssues[droppableDestinationColumnId] || [];
const [removed] = _sourceIssues.splice(source.index, 1);
if (_destinationIssues && _destinationIssues.length > 0)
_destinationIssues.splice(destination.index, 0, {
...removed,
target_date: droppableDestinationColumnId,
});
else _destinationIssues = [..._destinationIssues, { ...removed, target_date: droppableDestinationColumnId }];
updateIssue = { ...updateIssue, issueId: removed?.id, target_date: droppableDestinationColumnId };
currentIssues[droppableSourceColumnId] = _sourceIssues;
currentIssues[droppableDestinationColumnId] = _destinationIssues;
}
const reorderedIssues = {
...this.rootStore?.projectViewIssues.viewIssues,
[viewId]: {
...this.rootStore?.projectViewIssues.viewIssues?.[viewId],
[issueType]: {
...this.rootStore?.projectViewIssues.viewIssues?.[viewId]?.[issueType],
[issueType]: currentIssues,
},
},
};
runInAction(() => {
this.rootStore.projectViewIssues.viewIssues = { ...reorderedIssues };
});
this.rootStore.issueDetail?.updateIssue(
updateIssue.workspaceSlug,
updateIssue.projectId,
updateIssue.issueId,
updateIssue
);
}
return;
};
}

View File

@ -6,10 +6,18 @@ import { handleIssueQueryParamsByLayout } from "helpers/issue.helper";
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers"; import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
// types // types
import { RootStore } from "../root"; import { RootStore } from "../root";
import { IIssueGroupWithSubGroupsStructure, IIssueGroupedStructure, IIssueUnGroupedStructure } from "store/issue";
import { IIssue, IIssueFilterOptions } from "types"; import { IIssue, IIssueFilterOptions } from "types";
import { IBlockUpdateData } from "components/gantt-chart"; import { IBlockUpdateData } from "components/gantt-chart";
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped";
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] };
export type IIssueGroupWithSubGroupsStructure = {
[group_id: string]: {
[sub_group_id: string]: IIssue[];
};
};
export type IIssueUnGroupedStructure = IIssue[];
export interface IProjectViewIssuesStore { export interface IProjectViewIssuesStore {
// states // states
loader: boolean; loader: boolean;
@ -37,6 +45,7 @@ export interface IProjectViewIssuesStore {
// computed // computed
getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null; getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null;
getIssueType: IIssueType | null;
} }
export class ProjectViewIssuesStore implements IProjectViewIssuesStore { export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
@ -75,6 +84,7 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
fetchViewIssues: action, fetchViewIssues: action,
// computed // computed
getIssueType: computed,
getIssues: computed, getIssues: computed,
}); });
@ -108,6 +118,26 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
return computedFilters; return computedFilters;
}; };
get getIssueType() {
const groupedLayouts = ["kanban", "list", "calendar"];
const ungroupedLayouts = ["spreadsheet", "gantt_chart"];
const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
const issueSubGroup = this.rootStore?.issueFilter?.userDisplayFilters?.sub_group_by || null;
if (!issueLayout) return null;
const _issueState = groupedLayouts.includes(issueLayout)
? issueSubGroup
? "groupWithSubGroups"
: "grouped"
: ungroupedLayouts.includes(issueLayout)
? "ungrouped"
: null;
return _issueState || null;
}
get getIssues() { get getIssues() {
const viewId: string | null = this.rootStore.projectViews.viewId; const viewId: string | null = this.rootStore.projectViews.viewId;
const issueType = this.rootStore.issue.getIssueType; const issueType = this.rootStore.issue.getIssueType;

View File

@ -12,6 +12,8 @@ import {
IssueDetailStore, IssueDetailStore,
IssueFilterStore, IssueFilterStore,
IssueKanBanViewStore, IssueKanBanViewStore,
IIssueCalendarViewStore,
IssueCalendarViewStore,
IssueStore, IssueStore,
} from "store/issue"; } from "store/issue";
import { IWorkspaceFilterStore, IWorkspaceStore, WorkspaceFilterStore, WorkspaceStore } from "store/workspace"; import { IWorkspaceFilterStore, IWorkspaceStore, WorkspaceFilterStore, WorkspaceStore } from "store/workspace";
@ -24,6 +26,8 @@ import {
ModuleFilterStore, ModuleFilterStore,
ModuleIssueKanBanViewStore, ModuleIssueKanBanViewStore,
ModuleIssueStore, ModuleIssueStore,
IModuleIssueCalendarViewStore,
ModuleIssueCalendarViewStore,
ModuleStore, ModuleStore,
} from "store/module"; } from "store/module";
import { import {
@ -33,6 +37,8 @@ import {
CycleStore, CycleStore,
ICycleIssueFilterStore, ICycleIssueFilterStore,
ICycleIssueKanBanViewStore, ICycleIssueKanBanViewStore,
ICycleIssueCalendarViewStore,
CycleIssueCalendarViewStore,
ICycleIssueStore, ICycleIssueStore,
ICycleStore, ICycleStore,
} from "store/cycle"; } from "store/cycle";
@ -43,6 +49,8 @@ import {
ProjectViewFiltersStore, ProjectViewFiltersStore,
ProjectViewIssuesStore, ProjectViewIssuesStore,
ProjectViewsStore, ProjectViewsStore,
IProjectViewIssueCalendarViewStore,
ProjectViewIssueCalendarViewStore,
} from "store/project-view"; } from "store/project-view";
import CalendarStore, { ICalendarStore } from "store/calendar.store"; import CalendarStore, { ICalendarStore } from "store/calendar.store";
import { import {
@ -95,19 +103,23 @@ export class RootStore {
moduleIssue: IModuleIssueStore; moduleIssue: IModuleIssueStore;
moduleFilter: IModuleFilterStore; moduleFilter: IModuleFilterStore;
moduleIssueKanBanView: IModuleIssueKanBanViewStore; moduleIssueKanBanView: IModuleIssueKanBanViewStore;
moduleIssueCalendarView: IModuleIssueCalendarViewStore;
cycle: ICycleStore; cycle: ICycleStore;
cycleIssue: ICycleIssueStore; cycleIssue: ICycleIssueStore;
cycleIssueFilter: ICycleIssueFilterStore; cycleIssueFilter: ICycleIssueFilterStore;
cycleIssueKanBanView: ICycleIssueKanBanViewStore; cycleIssueKanBanView: ICycleIssueKanBanViewStore;
cycleIssueCalendarView: ICycleIssueCalendarViewStore;
projectViews: IProjectViewsStore; projectViews: IProjectViewsStore;
projectViewIssues: IProjectViewIssuesStore; projectViewIssues: IProjectViewIssuesStore;
projectViewFilters: IProjectViewFiltersStore; projectViewFilters: IProjectViewFiltersStore;
projectViewIssueCalendarView: IProjectViewIssueCalendarViewStore;
issueFilter: IIssueFilterStore; issueFilter: IIssueFilterStore;
issueDetail: IIssueDetailStore; issueDetail: IIssueDetailStore;
issueKanBanView: IIssueKanBanViewStore; issueKanBanView: IIssueKanBanViewStore;
issueCalendarView: IIssueCalendarViewStore;
draftIssuesStore: DraftIssuesStore; draftIssuesStore: DraftIssuesStore;
calendar: ICalendarStore; calendar: ICalendarStore;
@ -145,20 +157,24 @@ export class RootStore {
this.moduleIssue = new ModuleIssueStore(this); this.moduleIssue = new ModuleIssueStore(this);
this.moduleFilter = new ModuleFilterStore(this); this.moduleFilter = new ModuleFilterStore(this);
this.moduleIssueKanBanView = new ModuleIssueKanBanViewStore(this); this.moduleIssueKanBanView = new ModuleIssueKanBanViewStore(this);
this.moduleIssueCalendarView = new ModuleIssueCalendarViewStore(this);
this.cycle = new CycleStore(this); this.cycle = new CycleStore(this);
this.cycleIssue = new CycleIssueStore(this); this.cycleIssue = new CycleIssueStore(this);
this.cycleIssueFilter = new CycleIssueFilterStore(this); this.cycleIssueFilter = new CycleIssueFilterStore(this);
this.cycleIssueKanBanView = new CycleIssueKanBanViewStore(this); this.cycleIssueKanBanView = new CycleIssueKanBanViewStore(this);
this.cycleIssueCalendarView = new CycleIssueCalendarViewStore(this);
this.projectViews = new ProjectViewsStore(this); this.projectViews = new ProjectViewsStore(this);
this.projectViewIssues = new ProjectViewIssuesStore(this); this.projectViewIssues = new ProjectViewIssuesStore(this);
this.projectViewFilters = new ProjectViewFiltersStore(this); this.projectViewFilters = new ProjectViewFiltersStore(this);
this.projectViewIssueCalendarView = new ProjectViewIssueCalendarViewStore(this);
this.issue = new IssueStore(this); this.issue = new IssueStore(this);
this.issueFilter = new IssueFilterStore(this); this.issueFilter = new IssueFilterStore(this);
this.issueDetail = new IssueDetailStore(this); this.issueDetail = new IssueDetailStore(this);
this.issueKanBanView = new IssueKanBanViewStore(this); this.issueKanBanView = new IssueKanBanViewStore(this);
this.issueCalendarView = new IssueCalendarViewStore(this);
this.draftIssuesStore = new DraftIssuesStore(this); this.draftIssuesStore = new DraftIssuesStore(this);
this.calendar = new CalendarStore(this); this.calendar = new CalendarStore(this);