fix: In kanban issues can be shifted between the column in order_by (#2676)

This commit is contained in:
guru_sainath 2023-11-06 21:00:36 +05:30 committed by GitHub
parent 46f307fed5
commit 984b36f45a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 450 additions and 276 deletions

View File

@ -42,7 +42,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
return ( return (
<> <>
<Draggable draggableId={issue.id} index={index} isDragDisabled={isDragDisabled}> <Draggable draggableId={issue.id} index={index}>
{(provided, snapshot) => ( {(provided, snapshot) => (
<div <div
className="group/kanban-block relative p-1.5 hover:cursor-default" className="group/kanban-block relative p-1.5 hover:cursor-default"

View File

@ -10,11 +10,13 @@ import { KanbanIssueBlocksList, BoardInlineCreateIssueForm } from "components/is
import { IIssueDisplayProperties, IIssue } from "types"; import { IIssueDisplayProperties, IIssue } from "types";
// constants // constants
import { getValueFromObject } from "constants/issue"; import { getValueFromObject } from "constants/issue";
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
export interface IGroupByKanBan { export interface IGroupByKanBan {
issues: any; issues: any;
sub_group_by: string | null; sub_group_by: string | null;
group_by: string | null; group_by: string | null;
order_by: string | null;
sub_group_id: string; sub_group_id: string;
list: any; list: any;
listKey: string; listKey: string;
@ -31,6 +33,7 @@ export interface IGroupByKanBan {
kanBanToggle: any; kanBanToggle: any;
handleKanBanToggle: any; handleKanBanToggle: any;
enableQuickIssueCreate?: boolean; enableQuickIssueCreate?: boolean;
isDragStarted?: boolean;
} }
const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => { const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
@ -38,6 +41,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
issues, issues,
sub_group_by, sub_group_by,
group_by, group_by,
order_by,
sub_group_id = "null", sub_group_id = "null",
list, list,
listKey, listKey,
@ -49,6 +53,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
kanBanToggle, kanBanToggle,
handleKanBanToggle, handleKanBanToggle,
enableQuickIssueCreate, enableQuickIssueCreate,
isDragStarted,
} = props; } = props;
const verticalAlignPosition = (_list: any) => const verticalAlignPosition = (_list: any) =>
@ -59,7 +64,9 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
{list && {list &&
list.length > 0 && list.length > 0 &&
list.map((_list: any) => ( list.map((_list: any) => (
<div className={`flex-shrink-0 flex flex-col ${!verticalAlignPosition(_list) ? `w-[340px]` : ``}`}> <div
className={`relative flex-shrink-0 flex flex-col ${!verticalAlignPosition(_list) ? `w-[340px]` : ``} group`}
>
{sub_group_by === null && ( {sub_group_by === null && (
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky top-0 z-[2]"> <div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky top-0 z-[2]">
<KanBanGroupByHeaderRoot <KanBanGroupByHeaderRoot
@ -79,7 +86,10 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
verticalAlignPosition(_list) ? `w-[0px] overflow-hidden` : `w-full transition-all` verticalAlignPosition(_list) ? `w-[0px] overflow-hidden` : `w-full transition-all`
}`} }`}
> >
<Droppable droppableId={`${getValueFromObject(_list, listKey) as string}__${sub_group_id}`}> <Droppable
droppableId={`${getValueFromObject(_list, listKey) as string}__${sub_group_id}`}
isDropDisabled={isDragDisabled}
>
{(provided: any, snapshot: any) => ( {(provided: any, snapshot: any) => (
<div <div
className={`w-full h-full relative transition-all ${ className={`w-full h-full relative transition-all ${
@ -101,25 +111,39 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
/> />
) : ( ) : (
isDragDisabled && ( isDragDisabled && (
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center"> <div className="absolute top-0 left-0 w-full h-full flex items-center justify-center text-sm">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */} {/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div> </div>
) )
)} )}
{provided.placeholder} {provided.placeholder}
</div> </div>
)} )}
</Droppable> </Droppable>
</div> </div>
{enableQuickIssueCreate && (
<BoardInlineCreateIssueForm <div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
groupId={getValueFromObject(_list, listKey) as string} {enableQuickIssueCreate && (
subGroupId={sub_group_id} <BoardInlineCreateIssueForm
prePopulatedData={{ groupId={getValueFromObject(_list, listKey) as string}
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }), subGroupId={sub_group_id}
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }), prePopulatedData={{
}} ...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
/> ...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
}}
/>
)}
</div>
{isDragStarted && isDragDisabled && (
<div className="invisible group-hover:visible transition-all text-sm absolute top-12 bottom-10 left-0 right-0 bg-custom-background-100/40 text-center">
<div className="rounded inline-flex mt-80 h-8 px-3 justify-center items-center bg-custom-background-80 text-custom-text-100 font-medium">
{`This board is ordered by "${replaceUnderscoreIfSnakeCase(
order_by ? (order_by[0] === "-" ? order_by.slice(1) : order_by) : "created_at"
)}"`}
</div>
</div>
)} )}
</div> </div>
))} ))}
@ -131,8 +155,8 @@ export interface IKanBan {
issues: any; issues: any;
sub_group_by: string | null; sub_group_by: string | null;
group_by: string | null; group_by: string | null;
order_by: string | null;
sub_group_id?: string; sub_group_id?: string;
handleDragDrop?: (result: any) => void | undefined;
handleIssues: ( handleIssues: (
sub_group_by: string | null, sub_group_by: string | null,
group_by: string | null, group_by: string | null,
@ -151,6 +175,7 @@ export interface IKanBan {
members: any; members: any;
projects: any; projects: any;
enableQuickIssueCreate?: boolean; enableQuickIssueCreate?: boolean;
isDragStarted?: boolean;
} }
export const KanBan: React.FC<IKanBan> = observer((props) => { export const KanBan: React.FC<IKanBan> = observer((props) => {
@ -158,6 +183,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
issues, issues,
sub_group_by, sub_group_by,
group_by, group_by,
order_by,
sub_group_id = "null", sub_group_id = "null",
handleIssues, handleIssues,
quickActions, quickActions,
@ -172,6 +198,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
members, members,
projects, projects,
enableQuickIssueCreate, enableQuickIssueCreate,
isDragStarted,
} = props; } = props;
const { issueKanBanView: issueKanBanViewStore } = useMobxStore(); const { issueKanBanView: issueKanBanViewStore } = useMobxStore();
@ -182,6 +209,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={projects} list={projects}
@ -194,6 +222,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
@ -201,6 +230,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={states} list={states}
@ -213,6 +243,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
@ -220,6 +251,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={stateGroups} list={stateGroups}
@ -232,6 +264,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
@ -239,6 +272,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={priorities} list={priorities}
@ -251,6 +285,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
@ -258,6 +293,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={labels ? [...labels, { id: "None", name: "None" }] : labels} list={labels ? [...labels, { id: "None", name: "None" }] : labels}
@ -270,6 +306,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
@ -277,6 +314,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={members ? [...members, { id: "None", display_name: "None" }] : members} list={members ? [...members, { id: "None", display_name: "None" }] : members}
@ -289,6 +327,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
@ -296,6 +335,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
<GroupByKanBan <GroupByKanBan
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
sub_group_id={sub_group_id} sub_group_id={sub_group_id}
list={members} list={members}
@ -308,6 +348,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle={kanBanToggle} kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle} handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate} enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
/> />
)} )}
</div> </div>

View File

@ -1,4 +1,4 @@
import React, { useCallback } from "react"; import React, { useCallback, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { DragDropContext } from "@hello-pangea/dnd"; import { DragDropContext } from "@hello-pangea/dnd";
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { KanBanSwimLanes } from "../swimlanes"; import { KanBanSwimLanes } from "../swimlanes";
import { KanBan } from "../default"; import { KanBan } from "../default";
import { CycleIssueQuickActions } from "components/issues"; import { CycleIssueQuickActions } from "components/issues";
import { Spinner } from "@plane/ui";
// helpers // helpers
import { orderArrayBy } from "helpers/array.helper"; import { orderArrayBy } from "helpers/array.helper";
// types // types
@ -37,6 +38,8 @@ export const CycleKanBanLayout: React.FC = observer(() => {
const group_by: string | null = issueFilterStore?.userDisplayFilters?.group_by || null; const group_by: string | null = issueFilterStore?.userDisplayFilters?.group_by || null;
const order_by: string | null = issueFilterStore?.userDisplayFilters?.order_by || null;
const userDisplayFilters = issueFilterStore?.userDisplayFilters || null; const userDisplayFilters = issueFilterStore?.userDisplayFilters || null;
const displayProperties = issueFilterStore?.userDisplayProperties || null; const displayProperties = issueFilterStore?.userDisplayProperties || null;
@ -45,7 +48,15 @@ export const CycleKanBanLayout: React.FC = observer(() => {
? "swimlanes" ? "swimlanes"
: "default"; : "default";
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => {
setIsDragStarted(true);
};
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false);
if (!result) return; if (!result) return;
if ( if (
@ -99,60 +110,72 @@ export const CycleKanBanLayout: React.FC = observer(() => {
: null; : null;
return ( return (
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}> <>
<DragDropContext onDragEnd={onDragEnd}> {cycleIssueStore.loader ? (
{currentKanBanView === "default" ? ( <div className="w-full h-full flex justify-center items-center">
<KanBan <Spinner />
issues={issues} </div>
sub_group_by={sub_group_by} ) : (
group_by={group_by} <div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
handleIssues={handleIssues} <DragDropContext onDragEnd={onDragEnd}>
quickActions={(sub_group_by, group_by, issue) => ( {currentKanBanView === "default" ? (
<CycleIssueQuickActions <KanBan
issue={issue} issues={issues}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")} sub_group_by={sub_group_by}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} group_by={group_by}
handleRemoveFromCycle={async () => handleIssues(sub_group_by, group_by, issue, "remove")} order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={cycleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={cycleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/> />
)} )}
displayProperties={displayProperties} </DragDropContext>
kanBanToggle={cycleIssueKanBanViewStore?.kanBanToggle} </div>
handleKanBanToggle={handleKanBanToggle} )}
states={states} </>
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={cycleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
)}
</DragDropContext>
</div>
); );
}); });

View File

@ -1,4 +1,4 @@
import React, { useCallback } from "react"; import React, { useCallback, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { DragDropContext } from "@hello-pangea/dnd"; import { DragDropContext } from "@hello-pangea/dnd";
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { KanBanSwimLanes } from "../swimlanes"; import { KanBanSwimLanes } from "../swimlanes";
import { KanBan } from "../default"; import { KanBan } from "../default";
import { ModuleIssueQuickActions } from "components/issues"; import { ModuleIssueQuickActions } from "components/issues";
import { Spinner } from "@plane/ui";
// helpers // helpers
import { orderArrayBy } from "helpers/array.helper"; import { orderArrayBy } from "helpers/array.helper";
// types // types
@ -36,6 +37,8 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
const group_by: string | null = issueFilterStore?.userDisplayFilters?.group_by || null; const group_by: string | null = issueFilterStore?.userDisplayFilters?.group_by || null;
const order_by: string | null = issueFilterStore?.userDisplayFilters?.order_by || null;
const userDisplayFilters = issueFilterStore?.userDisplayFilters || null; const userDisplayFilters = issueFilterStore?.userDisplayFilters || null;
const displayProperties = issueFilterStore?.userDisplayProperties || null; const displayProperties = issueFilterStore?.userDisplayProperties || null;
@ -44,7 +47,14 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
? "swimlanes" ? "swimlanes"
: "default"; : "default";
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => {
setIsDragStarted(true);
};
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false);
if (!result) return; if (!result) return;
if ( if (
@ -98,60 +108,72 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
: null; : null;
return ( return (
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}> <>
<DragDropContext onDragEnd={onDragEnd}> {moduleIssueStore.loader ? (
{currentKanBanView === "default" ? ( <div className="w-full h-full flex justify-center items-center">
<KanBan <Spinner />
issues={issues} </div>
sub_group_by={sub_group_by} ) : (
group_by={group_by} <div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
handleIssues={handleIssues} <DragDropContext onDragEnd={onDragEnd}>
quickActions={(sub_group_by, group_by, issue) => ( {currentKanBanView === "default" ? (
<ModuleIssueQuickActions <KanBan
issue={issue} issues={issues}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")} sub_group_by={sub_group_by}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} group_by={group_by}
handleRemoveFromModule={async () => handleIssues(sub_group_by, group_by, issue, "remove")} order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={moduleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={moduleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/> />
)} )}
displayProperties={displayProperties} </DragDropContext>
kanBanToggle={moduleIssueKanBanViewStore?.kanBanToggle} </div>
handleKanBanToggle={handleKanBanToggle} )}
states={states} </>
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={moduleIssueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
)}
</DragDropContext>
</div>
); );
}); });

View File

@ -1,4 +1,4 @@
import { FC, useCallback } from "react"; import { FC, useCallback, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { DragDropContext } from "@hello-pangea/dnd"; import { DragDropContext } from "@hello-pangea/dnd";
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { KanBanSwimLanes } from "../swimlanes"; import { KanBanSwimLanes } from "../swimlanes";
import { KanBan } from "../default"; import { KanBan } from "../default";
import { ProjectIssueQuickActions } from "components/issues"; import { ProjectIssueQuickActions } from "components/issues";
import { Spinner } from "@plane/ui";
// constants // constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue"; import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
// types // types
@ -34,6 +35,8 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
const group_by: string | null = profileIssueFiltersStore?.userDisplayFilters?.group_by || null; const group_by: string | null = profileIssueFiltersStore?.userDisplayFilters?.group_by || null;
const order_by: string | null = profileIssueFiltersStore?.userDisplayFilters?.order_by || null;
const userDisplayFilters = profileIssueFiltersStore?.userDisplayFilters || null; const userDisplayFilters = profileIssueFiltersStore?.userDisplayFilters || null;
const displayProperties = profileIssueFiltersStore?.userDisplayProperties || null; const displayProperties = profileIssueFiltersStore?.userDisplayProperties || null;
@ -42,7 +45,14 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
? "swimlanes" ? "swimlanes"
: "default"; : "default";
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => {
setIsDragStarted(true);
};
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false);
if (!result) return; if (!result) return;
if ( if (
@ -83,58 +93,70 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
const projects = projectStore?.workspaceProjects || null; const projects = projectStore?.workspaceProjects || null;
return ( return (
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}> <>
<DragDropContext onDragEnd={onDragEnd}> {profileIssuesStore.loader ? (
{currentKanBanView === "default" ? ( <div className="w-full h-full flex justify-center items-center">
<KanBan <Spinner />
issues={issues} </div>
sub_group_by={sub_group_by} ) : (
group_by={group_by} <div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
handleIssues={handleIssues} <DragDropContext onDragEnd={onDragEnd}>
quickActions={(sub_group_by, group_by, issue) => ( {currentKanBanView === "default" ? (
<ProjectIssueQuickActions <KanBan
issue={issue} issues={issues}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")} sub_group_by={sub_group_by}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} group_by={group_by}
order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/> />
)} )}
displayProperties={displayProperties} </DragDropContext>
kanBanToggle={issueKanBanViewStore?.kanBanToggle} </div>
handleKanBanToggle={handleKanBanToggle} )}
states={states} </>
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
)}
</DragDropContext>
</div>
); );
}); });

View File

@ -1,4 +1,4 @@
import { useCallback } from "react"; import { useCallback, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { DragDropContext } from "@hello-pangea/dnd"; import { DragDropContext } from "@hello-pangea/dnd";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { KanBanSwimLanes } from "../swimlanes"; import { KanBanSwimLanes } from "../swimlanes";
import { KanBan } from "../default"; import { KanBan } from "../default";
import { ProjectIssueQuickActions } from "components/issues"; import { ProjectIssueQuickActions } from "components/issues";
import { Spinner } from "@plane/ui";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
// constants // constants
@ -34,6 +35,8 @@ export const KanBanLayout: React.FC = observer(() => {
const group_by: string | null = issueFilterStore?.userDisplayFilters?.group_by || null; const group_by: string | null = issueFilterStore?.userDisplayFilters?.group_by || null;
const order_by: string | null = issueFilterStore?.userDisplayFilters?.order_by || null;
const userDisplayFilters = issueFilterStore?.userDisplayFilters || null; const userDisplayFilters = issueFilterStore?.userDisplayFilters || null;
const displayProperties = issueFilterStore?.userDisplayProperties || null; const displayProperties = issueFilterStore?.userDisplayProperties || null;
@ -42,12 +45,22 @@ export const KanBanLayout: React.FC = observer(() => {
? "swimlanes" ? "swimlanes"
: "default"; : "default";
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
const onDragStart = () => {
setIsDragStarted(true);
};
const onDragEnd = (result: any) => { const onDragEnd = (result: any) => {
setIsDragStarted(false);
if (!result) return; if (!result) return;
if ( if (
result.destination && result.destination &&
result.source && result.source &&
result.source.droppableId &&
result.destination.droppableId &&
result.destination.droppableId === result.source.droppableId && result.destination.droppableId === result.source.droppableId &&
result.destination.index === result.source.index result.destination.index === result.source.index
) )
@ -87,59 +100,71 @@ export const KanBanLayout: React.FC = observer(() => {
: null; : null;
return ( return (
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}> <>
<DragDropContext onDragEnd={onDragEnd}> {issueStore.loader ? (
{currentKanBanView === "default" ? ( <div className="w-full h-full flex justify-center items-center">
<KanBan <Spinner />
issues={issues} </div>
sub_group_by={sub_group_by} ) : (
group_by={group_by} <div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
handleIssues={handleIssues} <DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
quickActions={(sub_group_by, group_by, issue) => ( {currentKanBanView === "default" ? (
<ProjectIssueQuickActions <KanBan
issue={issue} issues={issues}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, "delete")} sub_group_by={sub_group_by}
handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} group_by={group_by}
order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
enableQuickIssueCreate
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
/> />
)} )}
displayProperties={displayProperties} </DragDropContext>
kanBanToggle={issueKanBanViewStore?.kanBanToggle} </div>
handleKanBanToggle={handleKanBanToggle} )}
states={states} </>
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
enableQuickIssueCreate
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
) : (
<KanBanSwimLanes
issues={issues}
sub_group_by={sub_group_by}
group_by={group_by}
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")}
/>
)}
displayProperties={displayProperties}
kanBanToggle={issueKanBanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
/>
)}
</DragDropContext>
</div>
); );
}); });

View File

@ -58,6 +58,7 @@ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = ({
}; };
interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader { interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
order_by: string | null;
showEmptyGroup: boolean; showEmptyGroup: boolean;
states: IState[] | null; states: IState[] | null;
stateGroups: any; stateGroups: any;
@ -76,12 +77,14 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
displayProperties: IIssueDisplayProperties; displayProperties: IIssueDisplayProperties;
kanBanToggle: any; kanBanToggle: any;
handleKanBanToggle: any; handleKanBanToggle: any;
isDragStarted?: boolean;
} }
const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => { const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
const { const {
issues, issues,
sub_group_by, sub_group_by,
group_by, group_by,
order_by,
list, list,
listKey, listKey,
handleIssues, handleIssues,
@ -96,6 +99,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
labels, labels,
members, members,
projects, projects,
isDragStarted,
} = props; } = props;
const calculateIssueCount = (column_id: string) => { const calculateIssueCount = (column_id: string) => {
@ -133,6 +137,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
issues={issues?.[getValueFromObject(_list, listKey) as string]} issues={issues?.[getValueFromObject(_list, listKey) as string]}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
sub_group_id={getValueFromObject(_list, listKey) as string} sub_group_id={getValueFromObject(_list, listKey) as string}
handleIssues={handleIssues} handleIssues={handleIssues}
quickActions={quickActions} quickActions={quickActions}
@ -147,6 +152,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
members={members} members={members}
projects={projects} projects={projects}
enableQuickIssueCreate enableQuickIssueCreate
isDragStarted={isDragStarted}
/> />
</div> </div>
)} )}
@ -160,6 +166,7 @@ export interface IKanBanSwimLanes {
issues: any; issues: any;
sub_group_by: string | null; sub_group_by: string | null;
group_by: string | null; group_by: string | null;
order_by: string | null;
handleIssues: ( handleIssues: (
sub_group_by: string | null, sub_group_by: string | null,
group_by: string | null, group_by: string | null,
@ -177,6 +184,7 @@ export interface IKanBanSwimLanes {
labels: IIssueLabels[] | null; labels: IIssueLabels[] | null;
members: IUserLite[] | null; members: IUserLite[] | null;
projects: IProject[] | null; projects: IProject[] | null;
isDragStarted?: boolean;
} }
export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => { export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
@ -184,6 +192,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues, issues,
sub_group_by, sub_group_by,
group_by, group_by,
order_by,
handleIssues, handleIssues,
quickActions, quickActions,
displayProperties, displayProperties,
@ -196,6 +205,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels, labels,
members, members,
projects, projects,
isDragStarted,
} = props; } = props;
return ( return (
@ -291,6 +301,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={projects} list={projects}
listKey={`id`} listKey={`id`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -305,6 +316,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -313,6 +325,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={states} list={states}
listKey={`id`} listKey={`id`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -327,6 +340,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -335,6 +349,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={states} list={states}
listKey={`id`} listKey={`id`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -349,6 +364,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -357,6 +373,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={stateGroups} list={stateGroups}
listKey={`key`} listKey={`key`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -371,6 +388,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -379,6 +397,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={priorities} list={priorities}
listKey={`key`} listKey={`key`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -393,6 +412,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -401,6 +421,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={labels ? [...labels, { id: "None", name: "None" }] : labels} list={labels ? [...labels, { id: "None", name: "None" }] : labels}
listKey={`id`} listKey={`id`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -415,6 +436,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -423,6 +445,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={members ? [...members, { id: "None", display_name: "None" }] : members} list={members ? [...members, { id: "None", display_name: "None" }] : members}
listKey={`id`} listKey={`id`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -437,6 +460,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
@ -445,6 +469,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
issues={issues} issues={issues}
sub_group_by={sub_group_by} sub_group_by={sub_group_by}
group_by={group_by} group_by={group_by}
order_by={order_by}
list={members} list={members}
listKey={`id`} listKey={`id`}
handleIssues={handleIssues} handleIssues={handleIssues}
@ -459,6 +484,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
labels={labels} labels={labels}
members={members} members={members}
projects={projects} projects={projects}
isDragStarted={isDragStarted}
/> />
)} )}
</div> </div>

View File

@ -6,6 +6,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { List } from "../default"; import { List } from "../default";
import { ProjectIssueQuickActions } from "components/issues"; import { ProjectIssueQuickActions } from "components/issues";
import { Spinner } from "@plane/ui";
// helpers // helpers
import { orderArrayBy } from "helpers/array.helper"; import { orderArrayBy } from "helpers/array.helper";
// types // types
@ -56,29 +57,37 @@ export const ListLayout: FC = observer(() => {
: null; : null;
return ( return (
<div className="relative w-full h-full bg-custom-background-90"> <>
<List {issueStore.loader ? (
issues={issues} <div className="w-full h-full flex justify-center items-center">
group_by={group_by} <Spinner />
handleIssues={handleIssues} </div>
quickActions={(group_by, issue) => ( ) : (
<ProjectIssueQuickActions <div className="relative w-full h-full bg-custom-background-90">
issue={issue} <List
handleDelete={async () => handleIssues(group_by, issue, "delete")} issues={issues}
handleUpdate={async (data) => handleIssues(group_by, data, "update")} group_by={group_by}
handleIssues={handleIssues}
quickActions={(group_by, issue) => (
<ProjectIssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(group_by, issue, "delete")}
handleUpdate={async (data) => handleIssues(group_by, data, "update")}
/>
)}
displayProperties={displayProperties}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
enableQuickIssueCreate
estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null}
showEmptyGroup={userDisplayFilters.show_empty_groups}
/> />
)} </div>
displayProperties={displayProperties} )}
states={states} </>
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members?.map((m) => m.member) ?? null}
projects={projects}
enableQuickIssueCreate
estimates={estimates?.points ? orderArrayBy(estimates.points, "key") : null}
showEmptyGroup={userDisplayFilters.show_empty_groups}
/>
</div>
); );
}); });

View File

@ -22,13 +22,19 @@ export const ProjectLayoutRoot: React.FC = observer(() => {
const { issue: issueStore, issueFilter: issueFilterStore } = useMobxStore(); const { issue: issueStore, issueFilter: issueFilterStore } = useMobxStore();
useSWR(workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null, async () => { const { isLoading } = useSWR(
if (workspaceSlug && projectId) { workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null,
await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString()); async () => {
if (workspaceSlug && projectId) {
await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString()); await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString());
await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString());
}
} }
}); );
console.log("--");
console.log("isLoading -- -->", isLoading);
console.log("--");
const activeLayout = issueFilterStore.userDisplayFilters.layout; const activeLayout = issueFilterStore.userDisplayFilters.layout;

View File

@ -36,8 +36,8 @@ export class CycleIssueCalendarViewStore implements ICycleIssueCalendarViewStore
projectId: projectId, projectId: projectId,
}; };
const droppableSourceColumnId = source.droppableId; const droppableSourceColumnId = source?.droppableId || null;
const droppableDestinationColumnId = destination.droppableId; const droppableDestinationColumnId = destination?.droppableId || null;
if (droppableSourceColumnId === droppableDestinationColumnId) return; if (droppableSourceColumnId === droppableDestinationColumnId) return;

View File

@ -95,9 +95,9 @@ export class CycleIssueKanBanViewStore implements ICycleIssueKanBanViewStore {
}; };
// source, destination group and sub group id // source, destination group and sub group id
let droppableSourceColumnId = source.droppableId; let droppableSourceColumnId = source?.droppableId || null;
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null; droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
let droppableDestinationColumnId = destination.droppableId; let droppableDestinationColumnId = destination?.droppableId || null;
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null; droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null; if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
@ -315,9 +315,9 @@ export class CycleIssueKanBanViewStore implements ICycleIssueKanBanViewStore {
}; };
// source, destination group and sub group id // source, destination group and sub group id
let droppableSourceColumnId = source.droppableId; let droppableSourceColumnId = source?.droppableId || null;
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null; droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
let droppableDestinationColumnId = destination.droppableId; let droppableDestinationColumnId = destination?.droppableId || null;
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null; droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null; if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;

View File

@ -35,8 +35,8 @@ export class IssueCalendarViewStore implements IIssueCalendarViewStore {
projectId: projectId, projectId: projectId,
}; };
const droppableSourceColumnId = source.droppableId; const droppableSourceColumnId = source?.droppableId || null;
const droppableDestinationColumnId = destination.droppableId; const droppableDestinationColumnId = destination?.droppableId || null;
if (droppableSourceColumnId === droppableDestinationColumnId) return; if (droppableSourceColumnId === droppableDestinationColumnId) return;

View File

@ -95,9 +95,9 @@ export class IssueKanBanViewStore implements IIssueKanBanViewStore {
}; };
// source, destination group and sub group id // source, destination group and sub group id
let droppableSourceColumnId = source.droppableId; let droppableSourceColumnId = source?.droppableId || null;
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null; droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
let droppableDestinationColumnId = destination.droppableId; let droppableDestinationColumnId = destination?.droppableId || null;
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null; droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null; if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
@ -315,9 +315,9 @@ export class IssueKanBanViewStore implements IIssueKanBanViewStore {
}; };
// source, destination group and sub group id // source, destination group and sub group id
let droppableSourceColumnId = source.droppableId; let droppableSourceColumnId = source?.droppableId || null;
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null; droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
let droppableDestinationColumnId = destination.droppableId; let droppableDestinationColumnId = destination?.droppableId || null;
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null; droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null; if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;

View File

@ -36,8 +36,8 @@ export class ModuleIssueCalendarViewStore implements IModuleIssueCalendarViewSto
projectId: projectId, projectId: projectId,
}; };
const droppableSourceColumnId = source.droppableId; const droppableSourceColumnId = source?.droppableId || null;
const droppableDestinationColumnId = destination.droppableId; const droppableDestinationColumnId = destination?.droppableId || null;
if (droppableSourceColumnId === droppableDestinationColumnId) return; if (droppableSourceColumnId === droppableDestinationColumnId) return;

View File

@ -95,9 +95,9 @@ export class ModuleIssueKanBanViewStore implements IModuleIssueKanBanViewStore {
}; };
// source, destination group and sub group id // source, destination group and sub group id
let droppableSourceColumnId = source.droppableId; let droppableSourceColumnId = source?.droppableId || null;
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null; droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
let droppableDestinationColumnId = destination.droppableId; let droppableDestinationColumnId = destination?.droppableId || null;
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null; droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null; if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
@ -315,9 +315,9 @@ export class ModuleIssueKanBanViewStore implements IModuleIssueKanBanViewStore {
}; };
// source, destination group and sub group id // source, destination group and sub group id
let droppableSourceColumnId = source.droppableId; let droppableSourceColumnId = source?.droppableId || null;
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null; droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
let droppableDestinationColumnId = destination.droppableId; let droppableDestinationColumnId = destination?.droppableId || null;
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null; droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null; if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;

View File

@ -36,8 +36,8 @@ export class ProjectViewIssueCalendarViewStore implements IProjectViewIssueCalen
projectId: projectId, projectId: projectId,
}; };
const droppableSourceColumnId = source.droppableId; const droppableSourceColumnId = source?.droppableId || null;
const droppableDestinationColumnId = destination.droppableId; const droppableDestinationColumnId = destination?.droppableId || null;
if (droppableSourceColumnId === droppableDestinationColumnId) return; if (droppableSourceColumnId === droppableDestinationColumnId) return;