diff --git a/web/components/issues/issue-layouts/kanban/block.tsx b/web/components/issues/issue-layouts/kanban/block.tsx index d9165aa2773..9d4c8aedd23 100644 --- a/web/components/issues/issue-layouts/kanban/block.tsx +++ b/web/components/issues/issue-layouts/kanban/block.tsx @@ -42,7 +42,7 @@ export const KanbanIssueBlock: React.FC = (props) => { return ( <> - + {(provided, snapshot) => (
= observer((props) => { @@ -38,6 +41,7 @@ const GroupByKanBan: React.FC = observer((props) => { issues, sub_group_by, group_by, + order_by, sub_group_id = "null", list, listKey, @@ -49,6 +53,7 @@ const GroupByKanBan: React.FC = observer((props) => { kanBanToggle, handleKanBanToggle, enableQuickIssueCreate, + isDragStarted, } = props; const verticalAlignPosition = (_list: any) => @@ -59,7 +64,9 @@ const GroupByKanBan: React.FC = observer((props) => { {list && list.length > 0 && list.map((_list: any) => ( -
+
{sub_group_by === null && (
= observer((props) => { verticalAlignPosition(_list) ? `w-[0px] overflow-hidden` : `w-full transition-all` }`} > - + {(provided: any, snapshot: any) => (
= observer((props) => { /> ) : ( isDragDisabled && ( -
+
{/*
Drop here
*/}
) )} + {provided.placeholder}
)}
- {enableQuickIssueCreate && ( - + +
+ {enableQuickIssueCreate && ( + + )} +
+ + {isDragStarted && isDragDisabled && ( +
+
+ {`This board is ordered by "${replaceUnderscoreIfSnakeCase( + order_by ? (order_by[0] === "-" ? order_by.slice(1) : order_by) : "created_at" + )}"`} +
+
)}
))} @@ -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 = observer((props) => { @@ -158,6 +183,7 @@ export const KanBan: React.FC = 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 = observer((props) => { members, projects, enableQuickIssueCreate, + isDragStarted, } = props; const { issueKanBanView: issueKanBanViewStore } = useMobxStore(); @@ -182,6 +209,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )} @@ -201,6 +230,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )} @@ -220,6 +251,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )} @@ -239,6 +272,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )} @@ -258,6 +293,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )} @@ -277,6 +314,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )} @@ -296,6 +335,7 @@ export const KanBan: React.FC = observer((props) => { = observer((props) => { kanBanToggle={kanBanToggle} handleKanBanToggle={handleKanBanToggle} enableQuickIssueCreate={enableQuickIssueCreate} + isDragStarted={isDragStarted} /> )}
diff --git a/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx b/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx index 82f4920c091..facf2ec9437 100644 --- a/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/cycle-root.tsx @@ -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(false); + + const onDragStart = () => { + setIsDragStarted(true); + }; + const onDragEnd = (result: any) => { + setIsDragStarted(false); + if (!result) return; if ( @@ -99,60 +110,72 @@ export const CycleKanBanLayout: React.FC = observer(() => { : null; return ( -
- - {currentKanBanView === "default" ? ( - ( - 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")} + <> + {cycleIssueStore.loader ? ( +
+ +
+ ) : ( +
+ + {currentKanBanView === "default" ? ( + ( + 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} - 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} - /> - ) : ( - ( - 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")} + ) : ( + ( + 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} - 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} - /> - )} - -
+
+
+ )} + ); }); diff --git a/web/components/issues/issue-layouts/kanban/roots/module-root.tsx b/web/components/issues/issue-layouts/kanban/roots/module-root.tsx index be40c6bcab4..c37cc555034 100644 --- a/web/components/issues/issue-layouts/kanban/roots/module-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/module-root.tsx @@ -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(false); + + const onDragStart = () => { + setIsDragStarted(true); + }; + const onDragEnd = (result: any) => { + setIsDragStarted(false); if (!result) return; if ( @@ -98,60 +108,72 @@ export const ModuleKanBanLayout: React.FC = observer(() => { : null; return ( -
- - {currentKanBanView === "default" ? ( - ( - 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")} + <> + {moduleIssueStore.loader ? ( +
+ +
+ ) : ( +
+ + {currentKanBanView === "default" ? ( + ( + 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} - 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} - /> - ) : ( - ( - 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")} + ) : ( + ( + 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} - 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} - /> - )} - -
+
+
+ )} + ); }); diff --git a/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx b/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx index 2849315b4dd..8d0cf172976 100644 --- a/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/profile-issues-root.tsx @@ -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(false); + + const onDragStart = () => { + setIsDragStarted(true); + }; + const onDragEnd = (result: any) => { + setIsDragStarted(false); if (!result) return; if ( @@ -83,58 +93,70 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => { const projects = projectStore?.workspaceProjects || null; return ( -
- - {currentKanBanView === "default" ? ( - ( - handleIssues(sub_group_by, group_by, issue, "delete")} - handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} + <> + {profileIssuesStore.loader ? ( +
+ +
+ ) : ( +
+ + {currentKanBanView === "default" ? ( + ( + 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} - 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} - /> - ) : ( - ( - handleIssues(sub_group_by, group_by, issue, "delete")} - handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} + ) : ( + ( + 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} - 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} - /> - )} - -
+
+
+ )} + ); }); diff --git a/web/components/issues/issue-layouts/kanban/roots/project-root.tsx b/web/components/issues/issue-layouts/kanban/roots/project-root.tsx index 179d628b4b0..52e60813e39 100644 --- a/web/components/issues/issue-layouts/kanban/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/kanban/roots/project-root.tsx @@ -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(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,59 +100,71 @@ export const KanBanLayout: React.FC = observer(() => { : null; return ( -
- - {currentKanBanView === "default" ? ( - ( - handleIssues(sub_group_by, group_by, issue, "delete")} - handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} + <> + {issueStore.loader ? ( +
+ +
+ ) : ( +
+ + {currentKanBanView === "default" ? ( + ( + 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} /> - )} - 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} - /> - ) : ( - ( - handleIssues(sub_group_by, group_by, issue, "delete")} - handleUpdate={async (data) => handleIssues(sub_group_by, group_by, data, "update")} + ) : ( + ( + 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} - 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} - /> - )} - -
+
+
+ )} + ); }); diff --git a/web/components/issues/issue-layouts/kanban/swimlanes.tsx b/web/components/issues/issue-layouts/kanban/swimlanes.tsx index 662a9723475..e25ddea3d66 100644 --- a/web/components/issues/issue-layouts/kanban/swimlanes.tsx +++ b/web/components/issues/issue-layouts/kanban/swimlanes.tsx @@ -58,6 +58,7 @@ const SubGroupSwimlaneHeader: React.FC = ({ }; 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 = observer((props) => { const { issues, sub_group_by, group_by, + order_by, list, listKey, handleIssues, @@ -96,6 +99,7 @@ const SubGroupSwimlane: React.FC = observer((props) => { labels, members, projects, + isDragStarted, } = props; const calculateIssueCount = (column_id: string) => { @@ -133,6 +137,7 @@ const SubGroupSwimlane: React.FC = 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 = observer((props) => { members={members} projects={projects} enableQuickIssueCreate + isDragStarted={isDragStarted} />
)} @@ -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 = observer((props) => { @@ -184,6 +192,7 @@ export const KanBanSwimLanes: React.FC = observer((props) => { issues, sub_group_by, group_by, + order_by, handleIssues, quickActions, displayProperties, @@ -196,6 +205,7 @@ export const KanBanSwimLanes: React.FC = observer((props) => { labels, members, projects, + isDragStarted, } = props; return ( @@ -291,6 +301,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -313,6 +325,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -335,6 +349,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -357,6 +373,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -379,6 +397,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -401,6 +421,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -423,6 +445,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )} @@ -445,6 +469,7 @@ export const KanBanSwimLanes: React.FC = 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 = observer((props) => { labels={labels} members={members} projects={projects} + isDragStarted={isDragStarted} /> )}
diff --git a/web/components/issues/issue-layouts/list/roots/project-root.tsx b/web/components/issues/issue-layouts/list/roots/project-root.tsx index 6a832f835e6..8ed96d54ce0 100644 --- a/web/components/issues/issue-layouts/list/roots/project-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/project-root.tsx @@ -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,29 +57,37 @@ export const ListLayout: FC = observer(() => { : null; return ( -
- ( - handleIssues(group_by, issue, "delete")} - handleUpdate={async (data) => handleIssues(group_by, data, "update")} + <> + {issueStore.loader ? ( +
+ +
+ ) : ( +
+ ( + 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} /> - )} - 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} - /> -
+
+ )} + ); }); diff --git a/web/components/issues/issue-layouts/roots/project-layout-root.tsx b/web/components/issues/issue-layouts/roots/project-layout-root.tsx index 6990c43ef00..0f5cac86b83 100644 --- a/web/components/issues/issue-layouts/roots/project-layout-root.tsx +++ b/web/components/issues/issue-layouts/roots/project-layout-root.tsx @@ -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 () => { - if (workspaceSlug && projectId) { - await issueFilterStore.fetchUserProjectFilters(workspaceSlug.toString(), projectId.toString()); - - await issueStore.fetchIssues(workspaceSlug.toString(), projectId.toString()); + 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; diff --git a/web/store/cycle/cycle_issue_calendar_view.store.ts b/web/store/cycle/cycle_issue_calendar_view.store.ts index fa80f39ac24..3b695d69778 100644 --- a/web/store/cycle/cycle_issue_calendar_view.store.ts +++ b/web/store/cycle/cycle_issue_calendar_view.store.ts @@ -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; diff --git a/web/store/cycle/cycle_issue_kanban_view.store.ts b/web/store/cycle/cycle_issue_kanban_view.store.ts index b007e11ad23..0ecc96e60ad 100644 --- a/web/store/cycle/cycle_issue_kanban_view.store.ts +++ b/web/store/cycle/cycle_issue_kanban_view.store.ts @@ -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; diff --git a/web/store/issue/issue_calendar_view.store.ts b/web/store/issue/issue_calendar_view.store.ts index 5f9cc89bf1c..881e2ee836d 100644 --- a/web/store/issue/issue_calendar_view.store.ts +++ b/web/store/issue/issue_calendar_view.store.ts @@ -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; diff --git a/web/store/issue/issue_kanban_view.store.ts b/web/store/issue/issue_kanban_view.store.ts index 25d217b7fb6..827972694ea 100644 --- a/web/store/issue/issue_kanban_view.store.ts +++ b/web/store/issue/issue_kanban_view.store.ts @@ -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; diff --git a/web/store/module/module_issue_calendar_view.store.ts b/web/store/module/module_issue_calendar_view.store.ts index 313745a18d7..3bfed3140a9 100644 --- a/web/store/module/module_issue_calendar_view.store.ts +++ b/web/store/module/module_issue_calendar_view.store.ts @@ -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; diff --git a/web/store/module/module_issue_kanban_view.store.ts b/web/store/module/module_issue_kanban_view.store.ts index a8584a7ff2a..82e210f29ff 100644 --- a/web/store/module/module_issue_kanban_view.store.ts +++ b/web/store/module/module_issue_kanban_view.store.ts @@ -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; diff --git a/web/store/project-view/project_view_issue_calendar_view.store.ts b/web/store/project-view/project_view_issue_calendar_view.store.ts index 2f70df136d6..9bce218aee8 100644 --- a/web/store/project-view/project_view_issue_calendar_view.store.ts +++ b/web/store/project-view/project_view_issue_calendar_view.store.ts @@ -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;