mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: In kanban issues can be shifted between the column in order_by (#2676)
This commit is contained in:
parent
46f307fed5
commit
984b36f45a
@ -42,7 +42,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Draggable draggableId={issue.id} index={index} isDragDisabled={isDragDisabled}>
|
||||
<Draggable draggableId={issue.id} index={index}>
|
||||
{(provided, snapshot) => (
|
||||
<div
|
||||
className="group/kanban-block relative p-1.5 hover:cursor-default"
|
||||
|
@ -10,11 +10,13 @@ import { KanbanIssueBlocksList, BoardInlineCreateIssueForm } from "components/is
|
||||
import { IIssueDisplayProperties, IIssue } from "types";
|
||||
// constants
|
||||
import { getValueFromObject } from "constants/issue";
|
||||
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
||||
|
||||
export interface IGroupByKanBan {
|
||||
issues: any;
|
||||
sub_group_by: string | null;
|
||||
group_by: string | null;
|
||||
order_by: string | null;
|
||||
sub_group_id: string;
|
||||
list: any;
|
||||
listKey: string;
|
||||
@ -31,6 +33,7 @@ export interface IGroupByKanBan {
|
||||
kanBanToggle: any;
|
||||
handleKanBanToggle: any;
|
||||
enableQuickIssueCreate?: boolean;
|
||||
isDragStarted?: boolean;
|
||||
}
|
||||
|
||||
const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
@ -38,6 +41,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
issues,
|
||||
sub_group_by,
|
||||
group_by,
|
||||
order_by,
|
||||
sub_group_id = "null",
|
||||
list,
|
||||
listKey,
|
||||
@ -49,6 +53,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
kanBanToggle,
|
||||
handleKanBanToggle,
|
||||
enableQuickIssueCreate,
|
||||
isDragStarted,
|
||||
} = props;
|
||||
|
||||
const verticalAlignPosition = (_list: any) =>
|
||||
@ -59,7 +64,9 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
{list &&
|
||||
list.length > 0 &&
|
||||
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 && (
|
||||
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky top-0 z-[2]">
|
||||
<KanBanGroupByHeaderRoot
|
||||
@ -79,7 +86,10 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
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) => (
|
||||
<div
|
||||
className={`w-full h-full relative transition-all ${
|
||||
@ -101,16 +111,19 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
/>
|
||||
) : (
|
||||
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>
|
||||
)
|
||||
)}
|
||||
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</div>
|
||||
|
||||
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
|
||||
{enableQuickIssueCreate && (
|
||||
<BoardInlineCreateIssueForm
|
||||
groupId={getValueFromObject(_list, listKey) as string}
|
||||
@ -122,6 +135,17 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
/>
|
||||
)}
|
||||
</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;
|
||||
sub_group_by: string | null;
|
||||
group_by: string | null;
|
||||
order_by: string | null;
|
||||
sub_group_id?: string;
|
||||
handleDragDrop?: (result: any) => void | undefined;
|
||||
handleIssues: (
|
||||
sub_group_by: string | null,
|
||||
group_by: string | null,
|
||||
@ -151,6 +175,7 @@ export interface IKanBan {
|
||||
members: any;
|
||||
projects: any;
|
||||
enableQuickIssueCreate?: boolean;
|
||||
isDragStarted?: boolean;
|
||||
}
|
||||
|
||||
export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
@ -158,6 +183,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
issues,
|
||||
sub_group_by,
|
||||
group_by,
|
||||
order_by,
|
||||
sub_group_id = "null",
|
||||
handleIssues,
|
||||
quickActions,
|
||||
@ -172,6 +198,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
members,
|
||||
projects,
|
||||
enableQuickIssueCreate,
|
||||
isDragStarted,
|
||||
} = props;
|
||||
|
||||
const { issueKanBanView: issueKanBanViewStore } = useMobxStore();
|
||||
@ -182,6 +209,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={projects}
|
||||
@ -194,6 +222,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -201,6 +230,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={states}
|
||||
@ -213,6 +243,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -220,6 +251,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={stateGroups}
|
||||
@ -232,6 +264,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -239,6 +272,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={priorities}
|
||||
@ -251,6 +285,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -258,6 +293,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={labels ? [...labels, { id: "None", name: "None" }] : labels}
|
||||
@ -270,6 +306,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -277,6 +314,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={members ? [...members, { id: "None", display_name: "None" }] : members}
|
||||
@ -289,6 +327,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -296,6 +335,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
<GroupByKanBan
|
||||
issues={issues}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_by={sub_group_by}
|
||||
sub_group_id={sub_group_id}
|
||||
list={members}
|
||||
@ -308,6 +348,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
kanBanToggle={kanBanToggle}
|
||||
handleKanBanToggle={handleKanBanToggle}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useCallback } from "react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { KanBanSwimLanes } from "../swimlanes";
|
||||
import { KanBan } from "../default";
|
||||
import { CycleIssueQuickActions } from "components/issues";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// helpers
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
@ -37,6 +38,8 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
|
||||
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 displayProperties = issueFilterStore?.userDisplayProperties || null;
|
||||
@ -45,7 +48,15 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
? "swimlanes"
|
||||
: "default";
|
||||
|
||||
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
|
||||
|
||||
const onDragStart = () => {
|
||||
setIsDragStarted(true);
|
||||
};
|
||||
|
||||
const onDragEnd = (result: any) => {
|
||||
setIsDragStarted(false);
|
||||
|
||||
if (!result) return;
|
||||
|
||||
if (
|
||||
@ -99,6 +110,12 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{cycleIssueStore.loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
{currentKanBanView === "default" ? (
|
||||
@ -106,6 +123,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
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
|
||||
@ -125,12 +143,14 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
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
|
||||
@ -150,9 +170,12 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
||||
members={members?.map((m) => m.member) ?? null}
|
||||
projects={projects}
|
||||
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
</DragDropContext>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useCallback } from "react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { KanBanSwimLanes } from "../swimlanes";
|
||||
import { KanBan } from "../default";
|
||||
import { ModuleIssueQuickActions } from "components/issues";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// helpers
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
@ -36,6 +37,8 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
|
||||
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 displayProperties = issueFilterStore?.userDisplayProperties || null;
|
||||
@ -44,7 +47,14 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
? "swimlanes"
|
||||
: "default";
|
||||
|
||||
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
|
||||
|
||||
const onDragStart = () => {
|
||||
setIsDragStarted(true);
|
||||
};
|
||||
|
||||
const onDragEnd = (result: any) => {
|
||||
setIsDragStarted(false);
|
||||
if (!result) return;
|
||||
|
||||
if (
|
||||
@ -98,6 +108,12 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{moduleIssueStore.loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
{currentKanBanView === "default" ? (
|
||||
@ -105,6 +121,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
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
|
||||
@ -124,12 +141,14 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
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
|
||||
@ -149,9 +168,12 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
||||
members={members?.map((m) => m.member) ?? null}
|
||||
projects={projects}
|
||||
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
</DragDropContext>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FC, useCallback } from "react";
|
||||
import { FC, useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { KanBanSwimLanes } from "../swimlanes";
|
||||
import { KanBan } from "../default";
|
||||
import { ProjectIssueQuickActions } from "components/issues";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// constants
|
||||
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
|
||||
// types
|
||||
@ -34,6 +35,8 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
||||
|
||||
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 displayProperties = profileIssueFiltersStore?.userDisplayProperties || null;
|
||||
@ -42,7 +45,14 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
||||
? "swimlanes"
|
||||
: "default";
|
||||
|
||||
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
|
||||
|
||||
const onDragStart = () => {
|
||||
setIsDragStarted(true);
|
||||
};
|
||||
|
||||
const onDragEnd = (result: any) => {
|
||||
setIsDragStarted(false);
|
||||
if (!result) return;
|
||||
|
||||
if (
|
||||
@ -83,6 +93,12 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
||||
const projects = projectStore?.workspaceProjects || null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{profileIssuesStore.loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
{currentKanBanView === "default" ? (
|
||||
@ -90,6 +106,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
||||
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
|
||||
@ -108,12 +125,14 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
||||
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
|
||||
@ -132,9 +151,12 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
||||
members={members?.map((m) => m.member) ?? null}
|
||||
projects={projects}
|
||||
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
</DragDropContext>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
import { observer } from "mobx-react-lite";
|
||||
@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { KanBanSwimLanes } from "../swimlanes";
|
||||
import { KanBan } from "../default";
|
||||
import { ProjectIssueQuickActions } from "components/issues";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
// constants
|
||||
@ -34,6 +35,8 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
|
||||
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 displayProperties = issueFilterStore?.userDisplayProperties || null;
|
||||
@ -42,12 +45,22 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
? "swimlanes"
|
||||
: "default";
|
||||
|
||||
const [isDragStarted, setIsDragStarted] = useState<boolean>(false);
|
||||
|
||||
const onDragStart = () => {
|
||||
setIsDragStarted(true);
|
||||
};
|
||||
|
||||
const onDragEnd = (result: any) => {
|
||||
setIsDragStarted(false);
|
||||
|
||||
if (!result) return;
|
||||
|
||||
if (
|
||||
result.destination &&
|
||||
result.source &&
|
||||
result.source.droppableId &&
|
||||
result.destination.droppableId &&
|
||||
result.destination.droppableId === result.source.droppableId &&
|
||||
result.destination.index === result.source.index
|
||||
)
|
||||
@ -87,13 +100,20 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{issueStore.loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<div className={`relative min-w-full w-max min-h-full h-max bg-custom-background-90 px-3`}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
|
||||
{currentKanBanView === "default" ? (
|
||||
<KanBan
|
||||
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
|
||||
@ -113,12 +133,14 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
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
|
||||
@ -137,9 +159,12 @@ export const KanBanLayout: React.FC = observer(() => {
|
||||
members={members?.map((m) => m.member) ?? null}
|
||||
projects={projects}
|
||||
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
</DragDropContext>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -58,6 +58,7 @@ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = ({
|
||||
};
|
||||
|
||||
interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
|
||||
order_by: string | null;
|
||||
showEmptyGroup: boolean;
|
||||
states: IState[] | null;
|
||||
stateGroups: any;
|
||||
@ -76,12 +77,14 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
|
||||
displayProperties: IIssueDisplayProperties;
|
||||
kanBanToggle: any;
|
||||
handleKanBanToggle: any;
|
||||
isDragStarted?: boolean;
|
||||
}
|
||||
const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
const {
|
||||
issues,
|
||||
sub_group_by,
|
||||
group_by,
|
||||
order_by,
|
||||
list,
|
||||
listKey,
|
||||
handleIssues,
|
||||
@ -96,6 +99,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
labels,
|
||||
members,
|
||||
projects,
|
||||
isDragStarted,
|
||||
} = props;
|
||||
|
||||
const calculateIssueCount = (column_id: string) => {
|
||||
@ -133,6 +137,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
issues={issues?.[getValueFromObject(_list, listKey) as string]}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
sub_group_id={getValueFromObject(_list, listKey) as string}
|
||||
handleIssues={handleIssues}
|
||||
quickActions={quickActions}
|
||||
@ -147,6 +152,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
members={members}
|
||||
projects={projects}
|
||||
enableQuickIssueCreate
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -160,6 +166,7 @@ export interface IKanBanSwimLanes {
|
||||
issues: any;
|
||||
sub_group_by: string | null;
|
||||
group_by: string | null;
|
||||
order_by: string | null;
|
||||
handleIssues: (
|
||||
sub_group_by: string | null,
|
||||
group_by: string | null,
|
||||
@ -177,6 +184,7 @@ export interface IKanBanSwimLanes {
|
||||
labels: IIssueLabels[] | null;
|
||||
members: IUserLite[] | null;
|
||||
projects: IProject[] | null;
|
||||
isDragStarted?: boolean;
|
||||
}
|
||||
|
||||
export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
@ -184,6 +192,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues,
|
||||
sub_group_by,
|
||||
group_by,
|
||||
order_by,
|
||||
handleIssues,
|
||||
quickActions,
|
||||
displayProperties,
|
||||
@ -196,6 +205,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels,
|
||||
members,
|
||||
projects,
|
||||
isDragStarted,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@ -291,6 +301,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={projects}
|
||||
listKey={`id`}
|
||||
handleIssues={handleIssues}
|
||||
@ -305,6 +316,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -313,6 +325,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={states}
|
||||
listKey={`id`}
|
||||
handleIssues={handleIssues}
|
||||
@ -327,6 +340,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -335,6 +349,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={states}
|
||||
listKey={`id`}
|
||||
handleIssues={handleIssues}
|
||||
@ -349,6 +364,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -357,6 +373,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={stateGroups}
|
||||
listKey={`key`}
|
||||
handleIssues={handleIssues}
|
||||
@ -371,6 +388,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -379,6 +397,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={priorities}
|
||||
listKey={`key`}
|
||||
handleIssues={handleIssues}
|
||||
@ -393,6 +412,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -401,6 +421,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={labels ? [...labels, { id: "None", name: "None" }] : labels}
|
||||
listKey={`id`}
|
||||
handleIssues={handleIssues}
|
||||
@ -415,6 +436,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -423,6 +445,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={members ? [...members, { id: "None", display_name: "None" }] : members}
|
||||
listKey={`id`}
|
||||
handleIssues={handleIssues}
|
||||
@ -437,6 +460,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -445,6 +469,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
issues={issues}
|
||||
sub_group_by={sub_group_by}
|
||||
group_by={group_by}
|
||||
order_by={order_by}
|
||||
list={members}
|
||||
listKey={`id`}
|
||||
handleIssues={handleIssues}
|
||||
@ -459,6 +484,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
labels={labels}
|
||||
members={members}
|
||||
projects={projects}
|
||||
isDragStarted={isDragStarted}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { List } from "../default";
|
||||
import { ProjectIssueQuickActions } from "components/issues";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// helpers
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
@ -56,6 +57,12 @@ export const ListLayout: FC = observer(() => {
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{issueStore.loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<div className="relative w-full h-full bg-custom-background-90">
|
||||
<List
|
||||
issues={issues}
|
||||
@ -80,5 +87,7 @@ export const ListLayout: FC = observer(() => {
|
||||
showEmptyGroup={userDisplayFilters.show_empty_groups}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -22,13 +22,19 @@ export const ProjectLayoutRoot: React.FC = observer(() => {
|
||||
|
||||
const { issue: issueStore, issueFilter: issueFilterStore } = useMobxStore();
|
||||
|
||||
useSWR(workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null, async () => {
|
||||
const { isLoading } = useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_FILTERS_AND_ISSUES_${projectId.toString()}` : null,
|
||||
async () => {
|
||||
if (workspaceSlug && projectId) {
|
||||
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;
|
||||
|
||||
|
@ -36,8 +36,8 @@ export class CycleIssueCalendarViewStore implements ICycleIssueCalendarViewStore
|
||||
projectId: projectId,
|
||||
};
|
||||
|
||||
const droppableSourceColumnId = source.droppableId;
|
||||
const droppableDestinationColumnId = destination.droppableId;
|
||||
const droppableSourceColumnId = source?.droppableId || null;
|
||||
const droppableDestinationColumnId = destination?.droppableId || null;
|
||||
|
||||
if (droppableSourceColumnId === droppableDestinationColumnId) return;
|
||||
|
||||
|
@ -95,9 +95,9 @@ export class CycleIssueKanBanViewStore implements ICycleIssueKanBanViewStore {
|
||||
};
|
||||
|
||||
// source, destination group and sub group id
|
||||
let droppableSourceColumnId = source.droppableId;
|
||||
let droppableSourceColumnId = source?.droppableId || null;
|
||||
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
|
||||
let droppableDestinationColumnId = destination.droppableId;
|
||||
let droppableDestinationColumnId = destination?.droppableId || null;
|
||||
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
|
||||
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
|
||||
|
||||
@ -315,9 +315,9 @@ export class CycleIssueKanBanViewStore implements ICycleIssueKanBanViewStore {
|
||||
};
|
||||
|
||||
// source, destination group and sub group id
|
||||
let droppableSourceColumnId = source.droppableId;
|
||||
let droppableSourceColumnId = source?.droppableId || null;
|
||||
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
|
||||
let droppableDestinationColumnId = destination.droppableId;
|
||||
let droppableDestinationColumnId = destination?.droppableId || null;
|
||||
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
|
||||
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
|
||||
|
||||
|
@ -35,8 +35,8 @@ export class IssueCalendarViewStore implements IIssueCalendarViewStore {
|
||||
projectId: projectId,
|
||||
};
|
||||
|
||||
const droppableSourceColumnId = source.droppableId;
|
||||
const droppableDestinationColumnId = destination.droppableId;
|
||||
const droppableSourceColumnId = source?.droppableId || null;
|
||||
const droppableDestinationColumnId = destination?.droppableId || null;
|
||||
|
||||
if (droppableSourceColumnId === droppableDestinationColumnId) return;
|
||||
|
||||
|
@ -95,9 +95,9 @@ export class IssueKanBanViewStore implements IIssueKanBanViewStore {
|
||||
};
|
||||
|
||||
// source, destination group and sub group id
|
||||
let droppableSourceColumnId = source.droppableId;
|
||||
let droppableSourceColumnId = source?.droppableId || null;
|
||||
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
|
||||
let droppableDestinationColumnId = destination.droppableId;
|
||||
let droppableDestinationColumnId = destination?.droppableId || null;
|
||||
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
|
||||
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
|
||||
|
||||
@ -315,9 +315,9 @@ export class IssueKanBanViewStore implements IIssueKanBanViewStore {
|
||||
};
|
||||
|
||||
// source, destination group and sub group id
|
||||
let droppableSourceColumnId = source.droppableId;
|
||||
let droppableSourceColumnId = source?.droppableId || null;
|
||||
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
|
||||
let droppableDestinationColumnId = destination.droppableId;
|
||||
let droppableDestinationColumnId = destination?.droppableId || null;
|
||||
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
|
||||
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
|
||||
|
||||
|
@ -36,8 +36,8 @@ export class ModuleIssueCalendarViewStore implements IModuleIssueCalendarViewSto
|
||||
projectId: projectId,
|
||||
};
|
||||
|
||||
const droppableSourceColumnId = source.droppableId;
|
||||
const droppableDestinationColumnId = destination.droppableId;
|
||||
const droppableSourceColumnId = source?.droppableId || null;
|
||||
const droppableDestinationColumnId = destination?.droppableId || null;
|
||||
|
||||
if (droppableSourceColumnId === droppableDestinationColumnId) return;
|
||||
|
||||
|
@ -95,9 +95,9 @@ export class ModuleIssueKanBanViewStore implements IModuleIssueKanBanViewStore {
|
||||
};
|
||||
|
||||
// source, destination group and sub group id
|
||||
let droppableSourceColumnId = source.droppableId;
|
||||
let droppableSourceColumnId = source?.droppableId || null;
|
||||
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
|
||||
let droppableDestinationColumnId = destination.droppableId;
|
||||
let droppableDestinationColumnId = destination?.droppableId || null;
|
||||
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
|
||||
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
|
||||
|
||||
@ -315,9 +315,9 @@ export class ModuleIssueKanBanViewStore implements IModuleIssueKanBanViewStore {
|
||||
};
|
||||
|
||||
// source, destination group and sub group id
|
||||
let droppableSourceColumnId = source.droppableId;
|
||||
let droppableSourceColumnId = source?.droppableId || null;
|
||||
droppableSourceColumnId = droppableSourceColumnId ? droppableSourceColumnId.split("__") : null;
|
||||
let droppableDestinationColumnId = destination.droppableId;
|
||||
let droppableDestinationColumnId = destination?.droppableId || null;
|
||||
droppableDestinationColumnId = droppableDestinationColumnId ? droppableDestinationColumnId.split("__") : null;
|
||||
if (!droppableSourceColumnId || !droppableDestinationColumnId) return null;
|
||||
|
||||
|
@ -36,8 +36,8 @@ export class ProjectViewIssueCalendarViewStore implements IProjectViewIssueCalen
|
||||
projectId: projectId,
|
||||
};
|
||||
|
||||
const droppableSourceColumnId = source.droppableId;
|
||||
const droppableDestinationColumnId = destination.droppableId;
|
||||
const droppableSourceColumnId = source?.droppableId || null;
|
||||
const droppableDestinationColumnId = destination?.droppableId || null;
|
||||
|
||||
if (droppableSourceColumnId === droppableDestinationColumnId) return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user