chore: implemented CRUD operations in all the layouts (#2505)

* chore: basic crud operations added to the list view

* refactor: cycle details page

* refactor: module details page

* chore: added quick actions to kanban issue block

* chore: implement quick actions in calendar layout

* fix: custom menu component

* chore: separate quick action dropdowns implemented

* style: loader for calendar

* fix: build errors
This commit is contained in:
Aaryan Khandelwal 2023-10-20 17:07:46 +05:30 committed by GitHub
parent 9bddd2eb67
commit d78b4dccf3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 2336 additions and 1153 deletions

View file

@ -1,73 +1,73 @@
// react beautiful dnd
import { Draggable } from "@hello-pangea/dnd";
// components
import { KanBanProperties } from "./properties";
// types
import { IIssue } from "types";
interface IssueBlockProps {
sub_group_id: string;
columnId: string;
issues: any;
index: number;
issue: IIssue;
isDragDisabled: boolean;
handleIssues?: (sub_group_by: string | null, group_by: string | null, issue: any) => void;
display_properties: any;
handleIssues: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
action: "update" | "delete"
) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
displayProperties: any;
}
export const IssueBlock = ({
sub_group_id,
columnId,
issues,
isDragDisabled,
handleIssues,
display_properties,
}: IssueBlockProps) => (
<>
{issues && issues.length > 0 ? (
<>
{issues.map((issue: any, index: any) => (
<Draggable
key={`issue-blocks-${sub_group_id}-${columnId}-${issue.id}`}
draggableId={`${issue.id}`}
index={index}
isDragDisabled={isDragDisabled}
export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
const { sub_group_id, columnId, index, issue, isDragDisabled, handleIssues, quickActions, displayProperties } = props;
const updateIssue = (sub_group_by: string | null, group_by: string | null, issueToUpdate: IIssue) => {
if (issueToUpdate) handleIssues(sub_group_by, group_by, issueToUpdate, "update");
};
return (
<>
<Draggable draggableId={issue.id} index={index} isDragDisabled={isDragDisabled}>
{(provided, snapshot) => (
<div
className="group/kanban-block relative p-1.5 hover:cursor-default"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
{(provided: any, snapshot: any) => (
<div
key={issue.id}
className="p-1.5 hover:cursor-default"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div
className={`text-sm rounded p-2 px-3 shadow-custom-shadow-2xs space-y-[8px] border transition-all bg-custom-background-100 hover:cursor-grab ${
snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`
}`}
>
{display_properties && display_properties?.key && (
<div className="text-xs line-clamp-1 text-custom-text-300">ONE-{issue.sequence_id}</div>
)}
<div className="line-clamp-2 h-[40px] text-sm font-medium text-custom-text-100">{issue.name}</div>
<div>
<KanBanProperties
sub_group_id={sub_group_id}
columnId={columnId}
issue={issue}
handleIssues={handleIssues}
display_properties={display_properties}
/>
</div>
<div className="absolute top-3 right-3 hidden group-hover/kanban-block:block">
{quickActions(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!columnId && columnId === "null" ? null : columnId,
issue
)}
</div>
<div
className={`text-sm rounded p-2 px-3 shadow-custom-shadow-2xs space-y-[8px] border transition-all bg-custom-background-100 hover:cursor-grab ${
snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`
}`}
>
{displayProperties && displayProperties?.key && (
<div className="text-xs line-clamp-1 text-custom-text-300">
{issue.project_detail.identifier}-{issue.sequence_id}
</div>
)}
<div className="line-clamp-2 h-[40px] text-sm font-medium text-custom-text-100">{issue.name}</div>
<div>
<KanBanProperties
sub_group_id={sub_group_id}
columnId={columnId}
issue={issue}
handleIssues={updateIssue}
display_properties={displayProperties}
/>
</div>
)}
</Draggable>
))}
</>
) : (
!isDragDisabled && (
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div>
)
)}
</>
);
</div>
</div>
)}
</Draggable>
</>
);
};

View file

@ -0,0 +1,50 @@
// components
import { KanbanIssueBlock } from "components/issues";
import { IIssue } from "types";
interface IssueBlocksListProps {
sub_group_id: string;
columnId: string;
issues: IIssue[];
isDragDisabled: boolean;
handleIssues: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
action: "update" | "delete"
) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
display_properties: any;
}
export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = (props) => {
const { sub_group_id, columnId, issues, isDragDisabled, handleIssues, quickActions, display_properties } = props;
return (
<>
{issues && issues.length > 0 ? (
<>
{issues.map((issue, index) => (
<KanbanIssueBlock
key={`kanban-issue-block-${issue.id}`}
index={index}
issue={issue}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={display_properties}
columnId={columnId}
sub_group_id={sub_group_id}
isDragDisabled={isDragDisabled}
/>
))}
</>
) : (
!isDragDisabled && (
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div>
)
)}
</>
);
};

View file

@ -1,14 +1,15 @@
import React from "react";
// react beautiful dnd
import { DragDropContext } from "@hello-pangea/dnd";
// mobx
import React, { useCallback } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { DragDropContext } from "@hello-pangea/dnd";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanSwimLanes } from "./swimlanes";
import { KanBan } from "./default";
// store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
import { CycleIssueQuickActions } from "components/issues";
// types
import { IIssue } from "types";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
@ -20,7 +21,11 @@ export const CycleKanBanLayout: React.FC = observer(() => {
cycleIssue: cycleIssueStore,
issueFilter: issueFilterStore,
cycleIssueKanBanView: cycleIssueKanBanViewStore,
}: RootStore = useMobxStore();
issueDetail: issueDetailStore,
} = useMobxStore();
const router = useRouter();
const { workspaceSlug, cycleId } = router.query;
const issues = cycleIssueStore?.getIssues;
@ -50,9 +55,27 @@ export const CycleKanBanLayout: React.FC = observer(() => {
: cycleIssueKanBanViewStore?.handleSwimlaneDragDrop(result.source, result.destination);
};
const updateIssue = (sub_group_by: string | null, group_by: string | null, issue: any) => {
cycleIssueStore.updateIssueStructure(group_by, sub_group_by, issue);
};
const handleIssues = useCallback(
(sub_group_by: string | null, group_by: string | null, issue: IIssue, action: "update" | "delete" | "remove") => {
if (!workspaceSlug || !cycleId) return;
if (action === "update") {
cycleIssueStore.updateIssueStructure(group_by, null, issue);
issueDetailStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
}
if (action === "delete") cycleIssueStore.deleteIssue(group_by, null, issue);
if (action === "remove" && issue.bridge_id) {
cycleIssueStore.deleteIssue(group_by, null, issue);
cycleIssueStore.removeIssueFromCycle(
workspaceSlug.toString(),
issue.project,
cycleId.toString(),
issue.bridge_id
);
}
},
[cycleIssueStore, issueDetailStore, cycleId, workspaceSlug]
);
const handleKanBanToggle = (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => {
cycleIssueKanBanViewStore.handleKanBanToggle(toggle, value);
@ -74,7 +97,15 @@ export const CycleKanBanLayout: React.FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<CycleIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
handleRemoveFromCycle={async () => handleIssues(sub_group_by, group_by, issue, "remove")}
/>
)}
display_properties={display_properties}
kanBanToggle={cycleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -91,7 +122,15 @@ export const CycleKanBanLayout: React.FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<CycleIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
handleRemoveFromCycle={async () => handleIssues(sub_group_by, group_by, issue, "remove")}
/>
)}
display_properties={display_properties}
kanBanToggle={cycleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}

View file

@ -1,16 +1,15 @@
import React from "react";
// react beautiful dnd
import { observer } from "mobx-react-lite";
import { Droppable } from "@hello-pangea/dnd";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanGroupByHeaderRoot } from "./headers/group-by-root";
import { IssueBlock } from "./block";
import { KanbanIssueBlocksList } from "components/issues";
// types
import { IIssue } from "types";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES, getValueFromObject } from "constants/issue";
// mobx
import { observer } from "mobx-react-lite";
// mobx
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
export interface IGroupByKanBan {
issues: any;
@ -20,14 +19,20 @@ export interface IGroupByKanBan {
list: any;
listKey: string;
isDragDisabled: boolean;
handleIssues?: (sub_group_by: string | null, group_by: string | null, issue: any) => void;
handleIssues: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
action: "update" | "delete"
) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
display_properties: any;
kanBanToggle: any;
handleKanBanToggle: any;
}
const GroupByKanBan: React.FC<IGroupByKanBan> = observer(
({
const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
const {
issues,
sub_group_by,
group_by,
@ -36,74 +41,76 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer(
listKey,
isDragDisabled,
handleIssues,
quickActions,
display_properties,
kanBanToggle,
handleKanBanToggle,
}) => {
const verticalAlignPosition = (_list: any) =>
kanBanToggle?.groupByHeaderMinMax.includes(getValueFromObject(_list, listKey) as string);
} = props;
return (
<div className="relative w-full h-full flex">
{list &&
list.length > 0 &&
list.map((_list: any) => (
<div className={`flex-shrink-0 flex flex-col ${!verticalAlignPosition(_list) ? `w-[340px]` : ``}`}>
{sub_group_by === null && (
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky top-0 z-[2]">
<KanBanGroupByHeaderRoot
column_id={getValueFromObject(_list, listKey) as string}
column_value={_list}
sub_group_by={sub_group_by}
group_by={group_by}
issues_count={issues?.[getValueFromObject(_list, listKey) as string]?.length || 0}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
</div>
)}
const verticalAlignPosition = (_list: any) =>
kanBanToggle?.groupByHeaderMinMax.includes(getValueFromObject(_list, listKey) as string);
<div
className={`min-h-[150px] h-full ${
verticalAlignPosition(_list) ? `w-[0px] overflow-hidden` : `w-full transition-all`
}`}
>
<Droppable droppableId={`${getValueFromObject(_list, listKey) as string}__${sub_group_id}`}>
{(provided: any, snapshot: any) => (
<div
className={`w-full h-full relative transition-all ${
snapshot.isDraggingOver ? `bg-custom-background-80` : ``
}`}
{...provided.droppableProps}
ref={provided.innerRef}
>
{issues ? (
<IssueBlock
sub_group_id={sub_group_id}
columnId={getValueFromObject(_list, listKey) as string}
issues={issues[getValueFromObject(_list, listKey) as string]}
isDragDisabled={isDragDisabled}
handleIssues={handleIssues}
display_properties={display_properties}
/>
) : (
isDragDisabled && (
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div>
)
)}
{provided.placeholder}
</div>
)}
</Droppable>
return (
<div className="relative w-full h-full flex">
{list &&
list.length > 0 &&
list.map((_list: any) => (
<div className={`flex-shrink-0 flex flex-col ${!verticalAlignPosition(_list) ? `w-[340px]` : ``}`}>
{sub_group_by === null && (
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky top-0 z-[2]">
<KanBanGroupByHeaderRoot
column_id={getValueFromObject(_list, listKey) as string}
column_value={_list}
sub_group_by={sub_group_by}
group_by={group_by}
issues_count={issues?.[getValueFromObject(_list, listKey) as string]?.length || 0}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
</div>
)}
<div
className={`min-h-[150px] h-full ${
verticalAlignPosition(_list) ? `w-[0px] overflow-hidden` : `w-full transition-all`
}`}
>
<Droppable droppableId={`${getValueFromObject(_list, listKey) as string}__${sub_group_id}`}>
{(provided: any, snapshot: any) => (
<div
className={`w-full h-full relative transition-all ${
snapshot.isDraggingOver ? `bg-custom-background-80` : ``
}`}
{...provided.droppableProps}
ref={provided.innerRef}
>
{issues ? (
<KanbanIssueBlocksList
sub_group_id={sub_group_id}
columnId={getValueFromObject(_list, listKey) as string}
issues={issues[getValueFromObject(_list, listKey) as string]}
isDragDisabled={isDragDisabled}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
/>
) : (
isDragDisabled && (
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div>
)
)}
{provided.placeholder}
</div>
)}
</Droppable>
</div>
))}
</div>
);
}
);
</div>
))}
</div>
);
});
export interface IKanBan {
issues: any;
@ -111,7 +118,13 @@ export interface IKanBan {
group_by: string | null;
sub_group_id?: string;
handleDragDrop?: (result: any) => void | undefined;
handleIssues?: (sub_group_by: string | null, group_by: string | null, issue: any) => void;
handleIssues: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
action: "update" | "delete"
) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
display_properties: any;
kanBanToggle: any;
handleKanBanToggle: any;
@ -132,6 +145,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
group_by,
sub_group_id = "null",
handleIssues,
quickActions,
display_properties,
kanBanToggle,
handleKanBanToggle,
@ -144,7 +158,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
estimates,
} = props;
const { project: projectStore, issueKanBanView: issueKanBanViewStore }: RootStore = useMobxStore();
const { project: projectStore, issueKanBanView: issueKanBanViewStore } = useMobxStore();
return (
<div className="relative w-full h-full">
@ -158,6 +172,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
listKey={`id`}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -174,6 +189,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
listKey={`key`}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -190,6 +206,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
listKey={`key`}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -206,6 +223,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
listKey={`id`}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -222,6 +240,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
listKey={`member.id`}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -238,6 +257,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
listKey={`member.id`}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}

View file

@ -1,3 +1,5 @@
export * from "./block";
export * from "./blocks-list";
export * from "./cycle-root";
export * from "./module-root";
export * from "./root";

View file

@ -1,14 +1,15 @@
import React from "react";
// react beautiful dnd
import { DragDropContext } from "@hello-pangea/dnd";
// mobx
import React, { useCallback } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { DragDropContext } from "@hello-pangea/dnd";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanSwimLanes } from "./swimlanes";
import { KanBan } from "./default";
// store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
import { ModuleIssueQuickActions } from "components/issues";
// types
import { IIssue } from "types";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
@ -20,7 +21,11 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
moduleIssue: moduleIssueStore,
issueFilter: issueFilterStore,
moduleIssueKanBanView: moduleIssueKanBanViewStore,
}: RootStore = useMobxStore();
issueDetail: issueDetailStore,
} = useMobxStore();
const router = useRouter();
const { workspaceSlug, moduleId } = router.query;
const issues = moduleIssueStore?.getIssues;
@ -50,9 +55,27 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
: moduleIssueKanBanViewStore?.handleSwimlaneDragDrop(result.source, result.destination);
};
const updateIssue = (sub_group_by: string | null, group_by: string | null, issue: any) => {
moduleIssueStore.updateIssueStructure(group_by, sub_group_by, issue);
};
const handleIssues = useCallback(
(sub_group_by: string | null, group_by: string | null, issue: IIssue, action: "update" | "delete" | "remove") => {
if (!workspaceSlug || !moduleId) return;
if (action === "update") {
moduleIssueStore.updateIssueStructure(group_by, sub_group_by, issue);
issueDetailStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
}
if (action === "delete") moduleIssueStore.deleteIssue(group_by, sub_group_by, issue);
if (action === "remove" && issue.bridge_id) {
moduleIssueStore.deleteIssue(group_by, null, issue);
moduleIssueStore.removeIssueFromModule(
workspaceSlug.toString(),
issue.project,
moduleId.toString(),
issue.bridge_id
);
}
},
[moduleIssueStore, issueDetailStore, moduleId, workspaceSlug]
);
const handleKanBanToggle = (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => {
moduleIssueKanBanViewStore.handleKanBanToggle(toggle, value);
@ -74,7 +97,15 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<ModuleIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
handleRemoveFromModule={async () => handleIssues(sub_group_by, group_by, issue, "remove")}
/>
)}
display_properties={display_properties}
kanBanToggle={moduleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -91,7 +122,15 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<ModuleIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
handleRemoveFromModule={async () => handleIssues(sub_group_by, group_by, issue, "remove")}
/>
)}
display_properties={display_properties}
kanBanToggle={moduleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}

View file

@ -1,15 +1,17 @@
import { FC } from "react";
import { DragDropContext } from "@hello-pangea/dnd";
// mobx
import { FC, useCallback } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { DragDropContext } from "@hello-pangea/dnd";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanSwimLanes } from "./swimlanes";
import { KanBan } from "./default";
// store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
import { ProjectIssueQuickActions } from "components/issues";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
// types
import { IIssue } from "types";
export interface IProfileIssuesKanBanLayout {}
@ -20,7 +22,11 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
profileIssues: profileIssuesStore,
profileIssueFilters: profileIssueFiltersStore,
issueKanBanView: issueKanBanViewStore,
}: RootStore = useMobxStore();
issueDetail: issueDetailStore,
} = useMobxStore();
const router = useRouter();
const { workspaceSlug } = router.query;
const issues = profileIssuesStore?.getIssues;
@ -50,9 +56,18 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
: issueKanBanViewStore?.handleSwimlaneDragDrop(result.source, result.destination);
};
const updateIssue = (sub_group_by: string | null, group_by: string | null, issue: any) => {
profileIssuesStore.updateIssueStructure(group_by, sub_group_by, issue);
};
const handleIssues = useCallback(
(sub_group_by: string | null, group_by: string | null, issue: IIssue, action: "update" | "delete") => {
if (!workspaceSlug) return;
if (action === "update") {
profileIssuesStore.updateIssueStructure(group_by, sub_group_by, issue);
issueDetailStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
}
if (action === "delete") profileIssuesStore.deleteIssue(group_by, sub_group_by, issue);
},
[profileIssuesStore, issueDetailStore, workspaceSlug]
);
const handleKanBanToggle = (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => {
issueKanBanViewStore.handleKanBanToggle(toggle, value);
@ -74,7 +89,14 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<ProjectIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
/>
)}
display_properties={display_properties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -91,7 +113,14 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<ProjectIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
/>
)}
display_properties={display_properties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}

View file

@ -1,24 +1,31 @@
import { FC } from "react";
import { FC, useCallback } from "react";
import { useRouter } from "next/router";
import { DragDropContext } from "@hello-pangea/dnd";
import { observer } from "mobx-react-lite";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanSwimLanes } from "./swimlanes";
import { KanBan } from "./default";
// store
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
import { ProjectIssueQuickActions } from "components/issues";
// types
import { IIssue } from "types";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
export interface IKanBanLayout {}
export const KanBanLayout: FC = observer(() => {
const router = useRouter();
const { workspaceSlug } = router.query;
const {
project: projectStore,
issue: issueStore,
issueFilter: issueFilterStore,
issueKanBanView: issueKanBanViewStore,
}: RootStore = useMobxStore();
issueDetail: issueDetailStore,
} = useMobxStore();
const issues = issueStore?.getIssues;
@ -48,9 +55,18 @@ export const KanBanLayout: FC = observer(() => {
: issueKanBanViewStore?.handleSwimlaneDragDrop(result.source, result.destination);
};
const updateIssue = (sub_group_by: string | null, group_by: string | null, issue: any) => {
issueStore.updateIssueStructure(group_by, sub_group_by, issue);
};
const handleIssues = useCallback(
(sub_group_by: string | null, group_by: string | null, issue: IIssue, action: "update" | "delete") => {
if (!workspaceSlug) return;
if (action === "update") {
issueStore.updateIssueStructure(group_by, sub_group_by, issue);
issueDetailStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue);
}
if (action === "delete") issueStore.deleteIssue(group_by, sub_group_by, issue);
},
[issueStore, issueDetailStore, workspaceSlug]
);
const handleKanBanToggle = (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => {
issueKanBanViewStore.handleKanBanToggle(toggle, value);
@ -72,7 +88,14 @@ export const KanBanLayout: FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<ProjectIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
/>
)}
display_properties={display_properties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -89,7 +112,14 @@ export const KanBanLayout: FC = observer(() => {
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue) => (
<ProjectIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")}
/>
)}
display_properties={display_properties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}

View file

@ -1,15 +1,15 @@
import React from "react";
import { observer } from "mobx-react-lite";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanGroupByHeaderRoot } from "./headers/group-by-root";
import { KanBanSubGroupByHeaderRoot } from "./headers/sub-group-by-root";
import { KanBan } from "./default";
// types
import { IIssue } from "types";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES, getValueFromObject } from "constants/issue";
// mobx
import { observer } from "mobx-react-lite";
// mobx
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
interface ISubGroupSwimlaneHeader {
issues: any;
@ -61,7 +61,13 @@ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = ({
interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
issues: any;
handleIssues?: (sub_group_by: string | null, group_by: string | null, issue: any) => void;
handleIssues: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
action: "update" | "delete"
) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
display_properties: any;
kanBanToggle: any;
handleKanBanToggle: any;
@ -81,6 +87,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
list,
listKey,
handleIssues,
quickActions,
display_properties,
kanBanToggle,
handleKanBanToggle,
@ -130,6 +137,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
group_by={group_by}
sub_group_id={getValueFromObject(_list, listKey) as string}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -153,7 +161,13 @@ export interface IKanBanSwimLanes {
issues: any;
sub_group_by: string | null;
group_by: string | null;
handleIssues?: (sub_group_by: string | null, group_by: string | null, issue: any) => void;
handleIssues: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
action: "update" | "delete"
) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
display_properties: any;
kanBanToggle: any;
handleKanBanToggle: any;
@ -172,6 +186,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
sub_group_by,
group_by,
handleIssues,
quickActions,
display_properties,
kanBanToggle,
handleKanBanToggle,
@ -184,7 +199,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
estimates,
} = props;
const { project: projectStore }: RootStore = useMobxStore();
const { project: projectStore } = useMobxStore();
return (
<div className="relative">
@ -270,6 +285,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={projectStore?.projectStates}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -291,6 +307,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={ISSUE_STATE_GROUPS}
listKey={`key`}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -312,6 +329,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={ISSUE_PRIORITIES}
listKey={`key`}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -333,6 +351,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={projectStore?.projectLabels}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -354,6 +373,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={projectStore?.projectMembers}
listKey={`member.id`}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
@ -375,6 +395,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
list={projectStore?.projectMembers}
listKey={`member.id`}
handleIssues={handleIssues}
quickActions={quickActions}
display_properties={display_properties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}

View file

@ -62,45 +62,47 @@ export const ViewKanBanLayout: React.FC = observer(() => {
const projects = projectStore?.projectStates || null;
const estimates = null;
return (
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
<DragDropContext onDragEnd={onDragEnd}>
{currentKanBanView === "default" ? (
<KanBan
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
display_properties={display_properties}
kanBanToggle={() => {}}
handleKanBanToggle={() => {}}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
estimates={estimates}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
handleIssues={updateIssue}
display_properties={display_properties}
kanBanToggle={() => {}}
handleKanBanToggle={() => {}}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
estimates={estimates}
/>
)}
</DragDropContext>
</div>
);
return null;
// return (
// <div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
// <DragDropContext onDragEnd={onDragEnd}>
// {currentKanBanView === "default" ? (
// <KanBan
// issues={issues}
// sub_group_by={sub_group_by}
// group_by={group_by}
// handleIssues={updateIssue}
// display_properties={display_properties}
// kanBanToggle={() => {}}
// handleKanBanToggle={() => {}}
// states={states}
// stateGroups={stateGroups}
// priorities={priorities}
// labels={labels}
// members={members}
// projects={projects}
// estimates={estimates}
// />
// ) : (
// <KanBanSwimLanes
// issues={issues}
// sub_group_by={sub_group_by}
// group_by={group_by}
// handleIssues={updateIssue}
// display_properties={display_properties}
// kanBanToggle={() => {}}
// handleKanBanToggle={() => {}}
// states={states}
// stateGroups={stateGroups}
// priorities={priorities}
// labels={labels}
// members={members}
// projects={projects}
// estimates={estimates}
// />
// )}
// </DragDropContext>
// </div>
// );
});