forked from github/plane
fix: peekoverview (#2603)
* fix: peekoverview mutation fix * fix: peekoverview mutation fix * fix: sub-issue peekoverview
This commit is contained in:
parent
4512651f8b
commit
0072160891
@ -85,8 +85,8 @@ export const CyclesListGanttChartView: FC<Props> = ({ cycles, mutateCycles }) =>
|
|||||||
loaderTitle="Cycles"
|
loaderTitle="Cycles"
|
||||||
blocks={cycles ? blockFormat(cycles) : null}
|
blocks={cycles ? blockFormat(cycles) : null}
|
||||||
blockUpdateHandler={(block, payload) => handleCycleUpdate(block, payload)}
|
blockUpdateHandler={(block, payload) => handleCycleUpdate(block, payload)}
|
||||||
SidebarBlockRender={CycleGanttSidebarBlock}
|
blockToRender={(data: ICycle) => <CycleGanttBlock data={data} />}
|
||||||
BlockRender={CycleGanttBlock}
|
sidebarBlockToRender={(data: ICycle) => <CycleGanttSidebarBlock data={data} />}
|
||||||
enableBlockLeftResize={false}
|
enableBlockLeftResize={false}
|
||||||
enableBlockRightResize={false}
|
enableBlockRightResize={false}
|
||||||
enableBlockMove={false}
|
enableBlockMove={false}
|
||||||
|
@ -11,7 +11,7 @@ import { IBlockUpdateData, IGanttBlock } from "../types";
|
|||||||
export const GanttChartBlocks: FC<{
|
export const GanttChartBlocks: FC<{
|
||||||
itemsContainerWidth: number;
|
itemsContainerWidth: number;
|
||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
BlockRender: React.FC<any>;
|
blockToRender: (data: any) => React.ReactNode;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
enableBlockLeftResize: boolean;
|
enableBlockLeftResize: boolean;
|
||||||
enableBlockRightResize: boolean;
|
enableBlockRightResize: boolean;
|
||||||
@ -19,7 +19,7 @@ export const GanttChartBlocks: FC<{
|
|||||||
}> = ({
|
}> = ({
|
||||||
itemsContainerWidth,
|
itemsContainerWidth,
|
||||||
blocks,
|
blocks,
|
||||||
BlockRender,
|
blockToRender,
|
||||||
blockUpdateHandler,
|
blockUpdateHandler,
|
||||||
enableBlockLeftResize,
|
enableBlockLeftResize,
|
||||||
enableBlockRightResize,
|
enableBlockRightResize,
|
||||||
@ -49,11 +49,9 @@ export const GanttChartBlocks: FC<{
|
|||||||
const updatedTargetDate = new Date(originalTargetDate);
|
const updatedTargetDate = new Date(originalTargetDate);
|
||||||
|
|
||||||
// update the start date on left resize
|
// update the start date on left resize
|
||||||
if (dragDirection === "left")
|
if (dragDirection === "left") updatedStartDate.setDate(originalStartDate.getDate() - totalBlockShifts);
|
||||||
updatedStartDate.setDate(originalStartDate.getDate() - totalBlockShifts);
|
|
||||||
// update the target date on right resize
|
// update the target date on right resize
|
||||||
else if (dragDirection === "right")
|
else if (dragDirection === "right") updatedTargetDate.setDate(originalTargetDate.getDate() + totalBlockShifts);
|
||||||
updatedTargetDate.setDate(originalTargetDate.getDate() + totalBlockShifts);
|
|
||||||
// update both the dates on x-axis move
|
// update both the dates on x-axis move
|
||||||
else if (dragDirection === "move") {
|
else if (dragDirection === "move") {
|
||||||
updatedStartDate.setDate(originalStartDate.getDate() + totalBlockShifts);
|
updatedStartDate.setDate(originalStartDate.getDate() + totalBlockShifts);
|
||||||
@ -86,7 +84,7 @@ export const GanttChartBlocks: FC<{
|
|||||||
>
|
>
|
||||||
<ChartDraggable
|
<ChartDraggable
|
||||||
block={block}
|
block={block}
|
||||||
BlockRender={BlockRender}
|
blockToRender={blockToRender}
|
||||||
handleBlock={(...args) => handleChartBlockPosition(block, ...args)}
|
handleBlock={(...args) => handleChartBlockPosition(block, ...args)}
|
||||||
enableBlockLeftResize={enableBlockLeftResize}
|
enableBlockLeftResize={enableBlockLeftResize}
|
||||||
enableBlockRightResize={enableBlockRightResize}
|
enableBlockRightResize={enableBlockRightResize}
|
||||||
|
@ -39,8 +39,8 @@ type ChartViewRootProps = {
|
|||||||
loaderTitle: string;
|
loaderTitle: string;
|
||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
SidebarBlockRender: React.FC<any>;
|
blockToRender: (data: any) => React.ReactNode;
|
||||||
BlockRender: React.FC<any>;
|
sidebarBlockToRender: (block: any) => React.ReactNode;
|
||||||
enableBlockLeftResize: boolean;
|
enableBlockLeftResize: boolean;
|
||||||
enableBlockRightResize: boolean;
|
enableBlockRightResize: boolean;
|
||||||
enableBlockMove: boolean;
|
enableBlockMove: boolean;
|
||||||
@ -54,8 +54,8 @@ export const ChartViewRoot: FC<ChartViewRootProps> = ({
|
|||||||
blocks = null,
|
blocks = null,
|
||||||
loaderTitle,
|
loaderTitle,
|
||||||
blockUpdateHandler,
|
blockUpdateHandler,
|
||||||
SidebarBlockRender,
|
sidebarBlockToRender,
|
||||||
BlockRender,
|
blockToRender,
|
||||||
enableBlockLeftResize,
|
enableBlockLeftResize,
|
||||||
enableBlockRightResize,
|
enableBlockRightResize,
|
||||||
enableBlockMove,
|
enableBlockMove,
|
||||||
@ -289,7 +289,7 @@ export const ChartViewRoot: FC<ChartViewRootProps> = ({
|
|||||||
title={title}
|
title={title}
|
||||||
blockUpdateHandler={blockUpdateHandler}
|
blockUpdateHandler={blockUpdateHandler}
|
||||||
blocks={chartBlocks}
|
blocks={chartBlocks}
|
||||||
SidebarBlockRender={SidebarBlockRender}
|
sidebarBlockToRender={sidebarBlockToRender}
|
||||||
enableReorder={enableReorder}
|
enableReorder={enableReorder}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -311,7 +311,7 @@ export const ChartViewRoot: FC<ChartViewRootProps> = ({
|
|||||||
<GanttChartBlocks
|
<GanttChartBlocks
|
||||||
itemsContainerWidth={itemsContainerWidth}
|
itemsContainerWidth={itemsContainerWidth}
|
||||||
blocks={chartBlocks}
|
blocks={chartBlocks}
|
||||||
BlockRender={BlockRender}
|
blockToRender={blockToRender}
|
||||||
blockUpdateHandler={blockUpdateHandler}
|
blockUpdateHandler={blockUpdateHandler}
|
||||||
enableBlockLeftResize={enableBlockLeftResize}
|
enableBlockLeftResize={enableBlockLeftResize}
|
||||||
enableBlockRightResize={enableBlockRightResize}
|
enableBlockRightResize={enableBlockRightResize}
|
||||||
|
@ -9,7 +9,7 @@ import { IGanttBlock } from "../types";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: IGanttBlock;
|
block: IGanttBlock;
|
||||||
BlockRender: React.FC<any>;
|
blockToRender: (data: any) => React.ReactNode;
|
||||||
handleBlock: (totalBlockShifts: number, dragDirection: "left" | "right" | "move") => void;
|
handleBlock: (totalBlockShifts: number, dragDirection: "left" | "right" | "move") => void;
|
||||||
enableBlockLeftResize: boolean;
|
enableBlockLeftResize: boolean;
|
||||||
enableBlockRightResize: boolean;
|
enableBlockRightResize: boolean;
|
||||||
@ -18,7 +18,7 @@ type Props = {
|
|||||||
|
|
||||||
export const ChartDraggable: React.FC<Props> = ({
|
export const ChartDraggable: React.FC<Props> = ({
|
||||||
block,
|
block,
|
||||||
BlockRender,
|
blockToRender,
|
||||||
handleBlock,
|
handleBlock,
|
||||||
enableBlockLeftResize,
|
enableBlockLeftResize,
|
||||||
enableBlockRightResize,
|
enableBlockRightResize,
|
||||||
@ -286,7 +286,7 @@ export const ChartDraggable: React.FC<Props> = ({
|
|||||||
className={`relative z-[2] rounded h-8 w-full flex items-center ${isMoving ? "pointer-events-none" : ""}`}
|
className={`relative z-[2] rounded h-8 w-full flex items-center ${isMoving ? "pointer-events-none" : ""}`}
|
||||||
onMouseDown={handleBlockMove}
|
onMouseDown={handleBlockMove}
|
||||||
>
|
>
|
||||||
<BlockRender data={block.data} />
|
{blockToRender(block.data)}
|
||||||
</div>
|
</div>
|
||||||
{/* right resize drag handle */}
|
{/* right resize drag handle */}
|
||||||
{enableBlockRightResize && (
|
{enableBlockRightResize && (
|
||||||
|
@ -12,8 +12,8 @@ type GanttChartRootProps = {
|
|||||||
loaderTitle: string;
|
loaderTitle: string;
|
||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
SidebarBlockRender: FC<any>;
|
blockToRender: (data: any) => React.ReactNode;
|
||||||
BlockRender: FC<any>;
|
sidebarBlockToRender: (block: any) => React.ReactNode;
|
||||||
enableBlockLeftResize?: boolean;
|
enableBlockLeftResize?: boolean;
|
||||||
enableBlockRightResize?: boolean;
|
enableBlockRightResize?: boolean;
|
||||||
enableBlockMove?: boolean;
|
enableBlockMove?: boolean;
|
||||||
@ -27,8 +27,8 @@ export const GanttChartRoot: FC<GanttChartRootProps> = ({
|
|||||||
blocks,
|
blocks,
|
||||||
loaderTitle = "blocks",
|
loaderTitle = "blocks",
|
||||||
blockUpdateHandler,
|
blockUpdateHandler,
|
||||||
SidebarBlockRender,
|
sidebarBlockToRender,
|
||||||
BlockRender,
|
blockToRender,
|
||||||
enableBlockLeftResize = true,
|
enableBlockLeftResize = true,
|
||||||
enableBlockRightResize = true,
|
enableBlockRightResize = true,
|
||||||
enableBlockMove = true,
|
enableBlockMove = true,
|
||||||
@ -42,8 +42,8 @@ export const GanttChartRoot: FC<GanttChartRootProps> = ({
|
|||||||
blocks={blocks}
|
blocks={blocks}
|
||||||
loaderTitle={loaderTitle}
|
loaderTitle={loaderTitle}
|
||||||
blockUpdateHandler={blockUpdateHandler}
|
blockUpdateHandler={blockUpdateHandler}
|
||||||
SidebarBlockRender={SidebarBlockRender}
|
sidebarBlockToRender={sidebarBlockToRender}
|
||||||
BlockRender={BlockRender}
|
blockToRender={blockToRender}
|
||||||
enableBlockLeftResize={enableBlockLeftResize}
|
enableBlockLeftResize={enableBlockLeftResize}
|
||||||
enableBlockRightResize={enableBlockRightResize}
|
enableBlockRightResize={enableBlockRightResize}
|
||||||
enableBlockMove={enableBlockMove}
|
enableBlockMove={enableBlockMove}
|
||||||
|
@ -17,14 +17,14 @@ type Props = {
|
|||||||
title: string;
|
title: string;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
SidebarBlockRender: React.FC<any>;
|
sidebarBlockToRender: (block: any) => React.ReactNode;
|
||||||
enableReorder: boolean;
|
enableReorder: boolean;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GanttSidebar: React.FC<Props> = (props) => {
|
export const GanttSidebar: React.FC<Props> = (props) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const { title, blockUpdateHandler, blocks, SidebarBlockRender, enableReorder, enableQuickIssueCreate } = props;
|
const { title, blockUpdateHandler, blocks, sidebarBlockToRender, enableReorder, enableQuickIssueCreate } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId } = router.query;
|
const { cycleId } = router.query;
|
||||||
@ -130,9 +130,7 @@ export const GanttSidebar: React.FC<Props> = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<div className="flex-grow truncate h-full flex items-center justify-between gap-2">
|
<div className="flex-grow truncate h-full flex items-center justify-between gap-2">
|
||||||
<div className="flex-grow truncate">
|
<div className="flex-grow truncate">{sidebarBlockToRender(block.data)}</div>
|
||||||
<SidebarBlockRender data={block.data} />
|
|
||||||
</div>
|
|
||||||
<div className="flex-shrink-0 text-sm text-custom-text-200">
|
<div className="flex-shrink-0 text-sm text-custom-text-200">
|
||||||
{duration} day{duration > 1 ? "s" : ""}
|
{duration} day{duration > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,11 +15,12 @@ type Props = {
|
|||||||
issues: IIssueGroupedStructure | null;
|
issues: IIssueGroupedStructure | null;
|
||||||
layout: "month" | "week" | undefined;
|
layout: "month" | "week" | undefined;
|
||||||
showWeekends: boolean;
|
showWeekends: boolean;
|
||||||
|
handleIssues: (date: string, issue: IIssue, action: "update" | "delete") => void;
|
||||||
quickActions: (issue: IIssue) => React.ReactNode;
|
quickActions: (issue: IIssue) => React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CalendarChart: React.FC<Props> = observer((props) => {
|
export const CalendarChart: React.FC<Props> = observer((props) => {
|
||||||
const { issues, layout, showWeekends, quickActions } = props;
|
const { issues, layout, showWeekends, handleIssues, quickActions } = props;
|
||||||
|
|
||||||
const { calendar: calendarStore } = useMobxStore();
|
const { calendar: calendarStore } = useMobxStore();
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
|||||||
week={week}
|
week={week}
|
||||||
issues={issues}
|
issues={issues}
|
||||||
enableQuickIssueCreate
|
enableQuickIssueCreate
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={quickActions}
|
quickActions={quickActions}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@ -59,6 +61,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
|||||||
week={calendarStore.allDaysOfActiveWeek}
|
week={calendarStore.allDaysOfActiveWeek}
|
||||||
issues={issues}
|
issues={issues}
|
||||||
enableQuickIssueCreate
|
enableQuickIssueCreate
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={quickActions}
|
quickActions={quickActions}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -16,12 +16,13 @@ import { IIssue } from "types";
|
|||||||
type Props = {
|
type Props = {
|
||||||
date: ICalendarDate;
|
date: ICalendarDate;
|
||||||
issues: IIssueGroupedStructure | null;
|
issues: IIssueGroupedStructure | null;
|
||||||
|
handleIssues: (date: string, issue: IIssue, action: "update" | "delete") => void;
|
||||||
quickActions: (issue: IIssue) => React.ReactNode;
|
quickActions: (issue: IIssue) => React.ReactNode;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CalendarDayTile: React.FC<Props> = observer((props) => {
|
export const CalendarDayTile: React.FC<Props> = observer((props) => {
|
||||||
const { date, issues, quickActions, enableQuickIssueCreate } = props;
|
const { date, issues, handleIssues, quickActions, enableQuickIssueCreate } = props;
|
||||||
|
|
||||||
const { issueFilter: issueFilterStore } = useMobxStore();
|
const { issueFilter: issueFilterStore } = useMobxStore();
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ export const CalendarDayTile: React.FC<Props> = observer((props) => {
|
|||||||
{...provided.droppableProps}
|
{...provided.droppableProps}
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
>
|
>
|
||||||
<CalendarIssueBlocks issues={issuesList} quickActions={quickActions} />
|
<CalendarIssueBlocks issues={issuesList} handleIssues={handleIssues} quickActions={quickActions} />
|
||||||
{enableQuickIssueCreate && (
|
{enableQuickIssueCreate && (
|
||||||
<div className="py-1 px-2">
|
<div className="py-1 px-2">
|
||||||
<CalendarInlineCreateIssueForm
|
<CalendarInlineCreateIssueForm
|
||||||
|
@ -2,16 +2,20 @@ import Link from "next/link";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Draggable } from "@hello-pangea/dnd";
|
import { Draggable } from "@hello-pangea/dnd";
|
||||||
|
// components
|
||||||
|
import { IssuePeekOverview } from "components/issues/issue-peek-overview";
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
issues: IIssue[] | null;
|
issues: IIssue[] | null;
|
||||||
|
handleIssues: (date: string, issue: IIssue, action: "update" | "delete") => void;
|
||||||
quickActions: (issue: IIssue) => React.ReactNode;
|
quickActions: (issue: IIssue) => React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
||||||
const { issues, quickActions } = props;
|
const { issues, handleIssues, quickActions } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
@ -47,7 +51,19 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
<div className="text-xs text-custom-text-300 flex-shrink-0">
|
<div className="text-xs text-custom-text-300 flex-shrink-0">
|
||||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||||
</div>
|
</div>
|
||||||
<h6 className="text-xs flex-grow truncate">{issue.name}</h6>
|
<IssuePeekOverview
|
||||||
|
workspaceSlug={issue?.workspace_detail?.slug}
|
||||||
|
projectId={issue?.project_detail?.id}
|
||||||
|
issueId={issue?.id}
|
||||||
|
// TODO: add the logic here
|
||||||
|
handleIssue={(issueToUpdate) => {
|
||||||
|
handleIssues(issue.target_date ?? "", { ...issue, ...issueToUpdate }, "update");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
||||||
|
<span className="text-xs flex-grow truncate">{issue.name}</span>
|
||||||
|
</Tooltip>
|
||||||
|
</IssuePeekOverview>
|
||||||
<div className="hidden group-hover/calendar-block:block">{quickActions(issue)}</div>
|
<div className="hidden group-hover/calendar-block:block">{quickActions(issue)}</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -64,6 +64,7 @@ export const CycleCalendarLayout: React.FC = observer(() => {
|
|||||||
issues={issues as IIssueGroupedStructure | null}
|
issues={issues as IIssueGroupedStructure | null}
|
||||||
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
||||||
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={(issue) => (
|
quickActions={(issue) => (
|
||||||
<CycleIssueQuickActions
|
<CycleIssueQuickActions
|
||||||
issue={issue}
|
issue={issue}
|
||||||
|
@ -66,6 +66,7 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
|
|||||||
issues={issues as IIssueGroupedStructure | null}
|
issues={issues as IIssueGroupedStructure | null}
|
||||||
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
||||||
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={(issue) => (
|
quickActions={(issue) => (
|
||||||
<ModuleIssueQuickActions
|
<ModuleIssueQuickActions
|
||||||
issue={issue}
|
issue={issue}
|
||||||
|
@ -57,6 +57,7 @@ export const CalendarLayout: React.FC = observer(() => {
|
|||||||
issues={issues as IIssueGroupedStructure | null}
|
issues={issues as IIssueGroupedStructure | null}
|
||||||
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
||||||
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={(issue) => (
|
quickActions={(issue) => (
|
||||||
<ProjectIssueQuickActions
|
<ProjectIssueQuickActions
|
||||||
issue={issue}
|
issue={issue}
|
||||||
|
@ -57,6 +57,7 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
|
|||||||
issues={issues as IIssueGroupedStructure | null}
|
issues={issues as IIssueGroupedStructure | null}
|
||||||
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
layout={issueFilterStore.userDisplayFilters.calendar?.layout}
|
||||||
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
showWeekends={issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false}
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={(issue) => (
|
quickActions={(issue) => (
|
||||||
<ProjectIssueQuickActions
|
<ProjectIssueQuickActions
|
||||||
issue={issue}
|
issue={issue}
|
||||||
|
@ -14,12 +14,13 @@ import { IIssue } from "types";
|
|||||||
type Props = {
|
type Props = {
|
||||||
issues: IIssueGroupedStructure | null;
|
issues: IIssueGroupedStructure | null;
|
||||||
week: ICalendarWeek | undefined;
|
week: ICalendarWeek | undefined;
|
||||||
|
handleIssues: (date: string, issue: IIssue, action: "update" | "delete") => void;
|
||||||
quickActions: (issue: IIssue) => React.ReactNode;
|
quickActions: (issue: IIssue) => React.ReactNode;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CalendarWeekDays: React.FC<Props> = observer((props) => {
|
export const CalendarWeekDays: React.FC<Props> = observer((props) => {
|
||||||
const { issues, week, quickActions, enableQuickIssueCreate } = props;
|
const { issues, week, handleIssues, quickActions, enableQuickIssueCreate } = props;
|
||||||
|
|
||||||
const { issueFilter: issueFilterStore } = useMobxStore();
|
const { issueFilter: issueFilterStore } = useMobxStore();
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ export const CalendarWeekDays: React.FC<Props> = observer((props) => {
|
|||||||
key={renderDateFormat(date.date)}
|
key={renderDateFormat(date.date)}
|
||||||
date={date}
|
date={date}
|
||||||
issues={issues}
|
issues={issues}
|
||||||
|
handleIssues={handleIssues}
|
||||||
quickActions={quickActions}
|
quickActions={quickActions}
|
||||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||||
/>
|
/>
|
||||||
|
@ -1,29 +1,28 @@
|
|||||||
import { useRouter } from "next/router";
|
|
||||||
|
|
||||||
// ui
|
// ui
|
||||||
import { Tooltip, StateGroupIcon } from "@plane/ui";
|
import { Tooltip, StateGroupIcon } from "@plane/ui";
|
||||||
|
import { IssuePeekOverview } from "components/issues/issue-peek-overview";
|
||||||
|
import { IBlockUpdateData } from "components/gantt-chart";
|
||||||
// helpers
|
// helpers
|
||||||
import { renderShortDate } from "helpers/date-time.helper";
|
import { renderShortDate } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const IssueGanttBlock = ({ data }: { data: IIssue }) => {
|
export const IssueGanttBlock = ({
|
||||||
const router = useRouter();
|
data,
|
||||||
|
handleIssue,
|
||||||
const openPeekOverview = () => {
|
}: {
|
||||||
const { query } = router;
|
data: IIssue;
|
||||||
|
handleIssue: (block: IIssue, payload: IBlockUpdateData) => void;
|
||||||
router.push({
|
}) => (
|
||||||
pathname: router.pathname,
|
<IssuePeekOverview
|
||||||
query: { ...query, peekIssue: data.id },
|
workspaceSlug={data?.workspace_detail?.slug}
|
||||||
});
|
projectId={data?.project_detail?.id}
|
||||||
};
|
issueId={data?.id}
|
||||||
|
handleIssue={(issueToUpdate) => handleIssue({ ...data, ...issueToUpdate }, {})}
|
||||||
return (
|
>
|
||||||
<div
|
<div
|
||||||
className="flex items-center relative h-full w-full rounded cursor-pointer"
|
className="flex items-center relative h-full w-full rounded cursor-pointer"
|
||||||
style={{ backgroundColor: data?.state_detail?.color }}
|
style={{ backgroundColor: data?.state_detail?.color }}
|
||||||
onClick={openPeekOverview}
|
|
||||||
>
|
>
|
||||||
<div className="absolute top-0 left-0 h-full w-full bg-custom-background-100/50" />
|
<div className="absolute top-0 left-0 h-full w-full bg-custom-background-100/50" />
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -37,32 +36,36 @@ export const IssueGanttBlock = ({ data }: { data: IIssue }) => {
|
|||||||
}
|
}
|
||||||
position="top-left"
|
position="top-left"
|
||||||
>
|
>
|
||||||
<div className="relative text-custom-text-100 text-sm truncate py-1 px-2.5 w-full">{data?.name}</div>
|
<Tooltip tooltipHeading="Title" tooltipContent={data.name}>
|
||||||
|
<div className="relative text-custom-text-100 text-sm truncate py-1 px-2.5 w-full">{data?.name}</div>
|
||||||
|
</Tooltip>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
);
|
</IssuePeekOverview>
|
||||||
};
|
);
|
||||||
|
|
||||||
// rendering issues on gantt sidebar
|
// rendering issues on gantt sidebar
|
||||||
export const IssueGanttSidebarBlock = ({ data }: { data: IIssue }) => {
|
export const IssueGanttSidebarBlock = ({
|
||||||
const router = useRouter();
|
data,
|
||||||
|
handleIssue,
|
||||||
const openPeekOverview = () => {
|
}: {
|
||||||
const { query } = router;
|
data: IIssue;
|
||||||
|
handleIssue: (block: IIssue, payload: IBlockUpdateData) => void;
|
||||||
router.push({
|
}) => (
|
||||||
pathname: router.pathname,
|
<IssuePeekOverview
|
||||||
query: { ...query, peekIssue: data.id },
|
workspaceSlug={data?.workspace_detail?.slug}
|
||||||
});
|
projectId={data?.project_detail?.id}
|
||||||
};
|
issueId={data?.id}
|
||||||
|
handleIssue={(issueToUpdate) => handleIssue({ ...data, ...issueToUpdate }, {})}
|
||||||
return (
|
>
|
||||||
<div className="relative w-full flex items-center gap-2 h-full cursor-pointer" onClick={openPeekOverview}>
|
<div className="relative w-full flex items-center gap-2 h-full cursor-pointer">
|
||||||
<StateGroupIcon stateGroup={data?.state_detail?.group} color={data?.state_detail?.color} />
|
<StateGroupIcon stateGroup={data?.state_detail?.group} color={data?.state_detail?.color} />
|
||||||
<div className="text-xs text-custom-text-300 flex-shrink-0">
|
<div className="text-xs text-custom-text-300 flex-shrink-0">
|
||||||
{data?.project_detail?.identifier} {data?.sequence_id}
|
{data?.project_detail?.identifier} {data?.sequence_id}
|
||||||
</div>
|
</div>
|
||||||
<h6 className="text-sm font-medium flex-grow truncate">{data?.name}</h6>
|
<Tooltip tooltipHeading="Title" tooltipContent={data.name}>
|
||||||
|
<span className="text-sm font-medium flex-grow truncate">{data?.name}</span>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
);
|
</IssuePeekOverview>
|
||||||
};
|
);
|
||||||
|
@ -8,6 +8,7 @@ import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "co
|
|||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const CycleGanttLayout: React.FC = observer(() => {
|
export const CycleGanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -38,8 +39,8 @@ export const CycleGanttLayout: React.FC = observer(() => {
|
|||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
BlockRender={IssueGanttBlock}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -8,6 +8,7 @@ import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "co
|
|||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const ModuleGanttLayout: React.FC = observer(() => {
|
export const ModuleGanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -38,8 +39,8 @@ export const ModuleGanttLayout: React.FC = observer(() => {
|
|||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
BlockRender={IssueGanttBlock}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -10,6 +10,7 @@ import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "co
|
|||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const ProjectViewGanttLayout: React.FC = observer(() => {
|
export const ProjectViewGanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -40,8 +41,8 @@ export const ProjectViewGanttLayout: React.FC = observer(() => {
|
|||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
BlockRender={IssueGanttBlock}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import React from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// hooks
|
// hooks
|
||||||
@ -8,6 +9,7 @@ import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "co
|
|||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const GanttLayout: React.FC = observer(() => {
|
export const GanttLayout: React.FC = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -21,7 +23,7 @@ export const GanttLayout: React.FC = observer(() => {
|
|||||||
|
|
||||||
const issues = issueStore.getIssues;
|
const issues = issueStore.getIssues;
|
||||||
|
|
||||||
const updateIssue = (block: any, payload: IBlockUpdateData) => {
|
const updateIssue = (block: IIssue, payload: IBlockUpdateData) => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
issueStore.updateGanttIssueStructure(workspaceSlug.toString(), block, payload);
|
issueStore.updateGanttIssueStructure(workspaceSlug.toString(), block, payload);
|
||||||
@ -38,8 +40,8 @@ export const GanttLayout: React.FC = observer(() => {
|
|||||||
loaderTitle="Issues"
|
loaderTitle="Issues"
|
||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
BlockRender={IssueGanttBlock}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
SidebarBlockRender={IssueGanttSidebarBlock}
|
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Draggable } from "@hello-pangea/dnd";
|
import { Draggable } from "@hello-pangea/dnd";
|
||||||
// components
|
// components
|
||||||
import { KanBanProperties } from "./properties";
|
import { KanBanProperties } from "./properties";
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
|
import { IssuePeekOverview } from "components/issues/issue-peek-overview";
|
||||||
// types
|
// types
|
||||||
import { IIssueDisplayProperties, IIssue } from "types";
|
import { IIssueDisplayProperties, IIssue } from "types";
|
||||||
|
|
||||||
@ -57,7 +59,23 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
|
|||||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="line-clamp-2 text-sm font-medium text-custom-text-100">{issue.name}</div>
|
<IssuePeekOverview
|
||||||
|
workspaceSlug={issue?.workspace_detail?.slug}
|
||||||
|
projectId={issue?.project_detail?.id}
|
||||||
|
issueId={issue?.id}
|
||||||
|
handleIssue={(issueToUpdate) => {
|
||||||
|
handleIssues(
|
||||||
|
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
|
||||||
|
!columnId && columnId === "null" ? null : columnId,
|
||||||
|
{ ...issue, ...issueToUpdate },
|
||||||
|
"update"
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
||||||
|
<div className="line-clamp-2 text-sm font-medium text-custom-text-100">{issue.name}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</IssuePeekOverview>
|
||||||
<div>
|
<div>
|
||||||
<KanBanProperties
|
<KanBanProperties
|
||||||
sub_group_id={sub_group_id}
|
sub_group_id={sub_group_id}
|
||||||
|
@ -36,8 +36,9 @@ export const IssueBlock: React.FC<IssueBlockProps> = (props) => {
|
|||||||
workspaceSlug={issue?.workspace_detail?.slug}
|
workspaceSlug={issue?.workspace_detail?.slug}
|
||||||
projectId={issue?.project_detail?.id}
|
projectId={issue?.project_detail?.id}
|
||||||
issueId={issue?.id}
|
issueId={issue?.id}
|
||||||
// TODO: add the logic here
|
handleIssue={(issueToUpdate) => {
|
||||||
handleIssue={() => {}}
|
handleIssues(!columnId && columnId === "null" ? null : columnId, issueToUpdate as IIssue, "update");
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
||||||
<div className="line-clamp-1 text-sm font-medium text-custom-text-100 w-full">{issue.name}</div>
|
<div className="line-clamp-1 text-sm font-medium text-custom-text-100 w-full">{issue.name}</div>
|
||||||
|
@ -4,6 +4,9 @@ import { Popover2 } from "@blueprintjs/popover2";
|
|||||||
import { MoreHorizontal, Pencil, Trash2, ChevronRight, Link } from "lucide-react";
|
import { MoreHorizontal, Pencil, Trash2, ChevronRight, Link } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
|
// components
|
||||||
|
import { IssuePeekOverview } from "components/issues/issue-peek-overview";
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { copyUrlToClipboard } from "helpers/string.helper";
|
import { copyUrlToClipboard } from "helpers/string.helper";
|
||||||
// types
|
// types
|
||||||
@ -13,6 +16,7 @@ type Props = {
|
|||||||
issue: IIssue;
|
issue: IIssue;
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
handleToggleExpand: (issueId: string) => void;
|
handleToggleExpand: (issueId: string) => void;
|
||||||
|
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||||
properties: IIssueDisplayProperties;
|
properties: IIssueDisplayProperties;
|
||||||
handleEditIssue: (issue: IIssue) => void;
|
handleEditIssue: (issue: IIssue) => void;
|
||||||
handleDeleteIssue: (issue: IIssue) => void;
|
handleDeleteIssue: (issue: IIssue) => void;
|
||||||
@ -24,6 +28,7 @@ export const IssueColumn: React.FC<Props> = ({
|
|||||||
issue,
|
issue,
|
||||||
expanded,
|
expanded,
|
||||||
handleToggleExpand,
|
handleToggleExpand,
|
||||||
|
handleUpdateIssue,
|
||||||
properties,
|
properties,
|
||||||
handleEditIssue,
|
handleEditIssue,
|
||||||
handleDeleteIssue,
|
handleDeleteIssue,
|
||||||
@ -38,15 +43,6 @@ export const IssueColumn: React.FC<Props> = ({
|
|||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const openPeekOverview = () => {
|
|
||||||
const { query } = router;
|
|
||||||
|
|
||||||
router.push({
|
|
||||||
pathname: router.pathname,
|
|
||||||
query: { ...query, peekIssue: issue.id },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCopyText = () => {
|
const handleCopyText = () => {
|
||||||
copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() => {
|
copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
@ -142,15 +138,20 @@ export const IssueColumn: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<span className="flex items-center px-4 py-2.5 h-full truncate flex-grow">
|
<IssuePeekOverview
|
||||||
<button
|
workspaceSlug={issue?.workspace_detail?.slug}
|
||||||
type="button"
|
projectId={issue?.project_detail?.id}
|
||||||
className="truncate text-custom-text-100 text-left cursor-pointer w-full text-[0.825rem]"
|
issueId={issue?.id}
|
||||||
onClick={openPeekOverview}
|
handleIssue={(issueToUpdate) => handleUpdateIssue(issueToUpdate as IIssue, issueToUpdate)}
|
||||||
>
|
>
|
||||||
{issue.name}
|
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
||||||
</button>
|
<span className="flex items-center px-4 py-2.5 h-full truncate flex-grow">
|
||||||
</span>
|
<div className="truncate text-custom-text-100 text-left cursor-pointer w-full text-[0.825rem]">
|
||||||
|
{issue.name}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</IssuePeekOverview>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,7 @@ type Props = {
|
|||||||
issue: IIssue;
|
issue: IIssue;
|
||||||
expandedIssues: string[];
|
expandedIssues: string[];
|
||||||
setExpandedIssues: React.Dispatch<React.SetStateAction<string[]>>;
|
setExpandedIssues: React.Dispatch<React.SetStateAction<string[]>>;
|
||||||
|
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||||
properties: IIssueDisplayProperties;
|
properties: IIssueDisplayProperties;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
@ -21,6 +22,7 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
|
|||||||
issue,
|
issue,
|
||||||
expandedIssues,
|
expandedIssues,
|
||||||
setExpandedIssues,
|
setExpandedIssues,
|
||||||
|
handleUpdateIssue,
|
||||||
properties,
|
properties,
|
||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
disableUserActions,
|
disableUserActions,
|
||||||
@ -49,6 +51,7 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
|
|||||||
expanded={isExpanded}
|
expanded={isExpanded}
|
||||||
handleToggleExpand={handleToggleExpand}
|
handleToggleExpand={handleToggleExpand}
|
||||||
properties={properties}
|
properties={properties}
|
||||||
|
handleUpdateIssue={handleUpdateIssue}
|
||||||
handleEditIssue={() => handleIssueAction(issue, "edit")}
|
handleEditIssue={() => handleIssueAction(issue, "edit")}
|
||||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||||
disableUserActions={disableUserActions}
|
disableUserActions={disableUserActions}
|
||||||
@ -64,6 +67,7 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
|
|||||||
key={subIssue.id}
|
key={subIssue.id}
|
||||||
issue={subIssue}
|
issue={subIssue}
|
||||||
expandedIssues={expandedIssues}
|
expandedIssues={expandedIssues}
|
||||||
|
handleUpdateIssue={handleUpdateIssue}
|
||||||
setExpandedIssues={setExpandedIssues}
|
setExpandedIssues={setExpandedIssues}
|
||||||
properties={properties}
|
properties={properties}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
@ -104,6 +104,7 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
|
|||||||
key={`${issue.id}_${index}`}
|
key={`${issue.id}_${index}`}
|
||||||
issue={issue}
|
issue={issue}
|
||||||
expandedIssues={expandedIssues}
|
expandedIssues={expandedIssues}
|
||||||
|
handleUpdateIssue={handleUpdateIssue}
|
||||||
setExpandedIssues={setExpandedIssues}
|
setExpandedIssues={setExpandedIssues}
|
||||||
properties={displayProperties}
|
properties={displayProperties}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
@ -22,10 +22,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||||||
const { issueDetail: issueDetailStore }: RootStore = useMobxStore();
|
const { issueDetail: issueDetailStore }: RootStore = useMobxStore();
|
||||||
|
|
||||||
const issueUpdate = (_data: Partial<IIssue>) => {
|
const issueUpdate = (_data: Partial<IIssue>) => {
|
||||||
if (handleIssue) {
|
handleIssue(_data);
|
||||||
handleIssue(_data);
|
|
||||||
issueDetailStore.updateIssue(workspaceSlug, projectId, issueId, _data);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const issueReactionCreate = (reaction: string) =>
|
const issueReactionCreate = (reaction: string) =>
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
// next imports
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
// swr
|
|
||||||
import { mutate } from "swr";
|
|
||||||
// lucide icons
|
// lucide icons
|
||||||
import { ChevronDown, ChevronRight, X, Pencil, Trash, Link as LinkIcon, Loader } from "lucide-react";
|
import { ChevronDown, ChevronRight, X, Pencil, Trash, Link as LinkIcon, Loader } from "lucide-react";
|
||||||
// components
|
// components
|
||||||
import { IssuePeekOverview } from "components/issues/peek-overview";
|
import { IssuePeekOverview } from "../issue-peek-overview";
|
||||||
import { SubIssuesRootList } from "./issues-list";
|
import { SubIssuesRootList } from "./issues-list";
|
||||||
import { IssueProperty } from "./properties";
|
import { IssueProperty } from "./properties";
|
||||||
// ui
|
// ui
|
||||||
@ -15,7 +12,6 @@ import { CustomMenu, Tooltip } from "@plane/ui";
|
|||||||
import { IUser, IIssue } from "types";
|
import { IUser, IIssue } from "types";
|
||||||
import { ISubIssuesRootLoaders, ISubIssuesRootLoadersHandler } from "./root";
|
import { ISubIssuesRootLoaders, ISubIssuesRootLoadersHandler } from "./root";
|
||||||
// fetch keys
|
// fetch keys
|
||||||
import { SUB_ISSUES } from "constants/fetch-keys";
|
|
||||||
|
|
||||||
export interface ISubIssues {
|
export interface ISubIssues {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
@ -34,6 +30,7 @@ export interface ISubIssues {
|
|||||||
issueId: string,
|
issueId: string,
|
||||||
issue?: IIssue | null
|
issue?: IIssue | null
|
||||||
) => void;
|
) => void;
|
||||||
|
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SubIssues: React.FC<ISubIssues> = ({
|
export const SubIssues: React.FC<ISubIssues> = ({
|
||||||
@ -49,49 +46,47 @@ export const SubIssues: React.FC<ISubIssues> = ({
|
|||||||
handleIssuesLoader,
|
handleIssuesLoader,
|
||||||
copyText,
|
copyText,
|
||||||
handleIssueCrudOperation,
|
handleIssueCrudOperation,
|
||||||
}) => {
|
handleUpdateIssue,
|
||||||
const router = useRouter();
|
}) => (
|
||||||
const { query } = router;
|
<div>
|
||||||
const { peekIssue } = query as { peekIssue: string };
|
{issue && (
|
||||||
|
<div
|
||||||
|
className="relative flex items-center gap-2 py-1 px-2 w-full h-full hover:bg-custom-background-90 group transition-all border-b border-custom-border-100"
|
||||||
|
style={{ paddingLeft: `${spacingLeft}px` }}
|
||||||
|
>
|
||||||
|
<div className="flex-shrink-0 w-[22px] h-[22px]">
|
||||||
|
{issue?.sub_issues_count > 0 && (
|
||||||
|
<>
|
||||||
|
{issuesLoader.sub_issues.includes(issue?.id) ? (
|
||||||
|
<div className="w-full h-full flex justify-center items-center rounded-sm bg-custom-background-80 transition-all cursor-not-allowed">
|
||||||
|
<Loader width={14} strokeWidth={2} className="animate-spin" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="w-full h-full flex justify-center items-center rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer"
|
||||||
|
onClick={() => handleIssuesLoader({ key: "visibility", issueId: issue?.id })}
|
||||||
|
>
|
||||||
|
{issuesLoader && issuesLoader.visibility.includes(issue?.id) ? (
|
||||||
|
<ChevronDown width={14} strokeWidth={2} />
|
||||||
|
) : (
|
||||||
|
<ChevronRight width={14} strokeWidth={2} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
const openPeekOverview = (issue_id: string) => {
|
<IssuePeekOverview
|
||||||
router.push({
|
workspaceSlug={issue?.workspace_detail?.slug}
|
||||||
pathname: router.pathname,
|
projectId={issue?.project_detail?.id}
|
||||||
query: { ...query, peekIssue: issue_id },
|
issueId={issue?.id}
|
||||||
});
|
handleIssue={(issueToUpdate) => {
|
||||||
};
|
console.log("issueToUpdate", issueToUpdate);
|
||||||
|
handleUpdateIssue(issue, { ...issue, ...issueToUpdate });
|
||||||
return (
|
}}
|
||||||
<div>
|
|
||||||
{issue && (
|
|
||||||
<div
|
|
||||||
className="relative flex items-center gap-2 py-1 px-2 w-full h-full hover:bg-custom-background-90 group transition-all border-b border-custom-border-100"
|
|
||||||
style={{ paddingLeft: `${spacingLeft}px` }}
|
|
||||||
>
|
>
|
||||||
<div className="flex-shrink-0 w-[22px] h-[22px]">
|
<div className="w-full flex items-center gap-2 cursor-pointer">
|
||||||
{issue?.sub_issues_count > 0 && (
|
|
||||||
<>
|
|
||||||
{issuesLoader.sub_issues.includes(issue?.id) ? (
|
|
||||||
<div className="w-full h-full flex justify-center items-center rounded-sm bg-custom-background-80 transition-all cursor-not-allowed">
|
|
||||||
<Loader width={14} strokeWidth={2} className="animate-spin" />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
className="w-full h-full flex justify-center items-center rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer"
|
|
||||||
onClick={() => handleIssuesLoader({ key: "visibility", issueId: issue?.id })}
|
|
||||||
>
|
|
||||||
{issuesLoader && issuesLoader.visibility.includes(issue?.id) ? (
|
|
||||||
<ChevronDown width={14} strokeWidth={2} />
|
|
||||||
) : (
|
|
||||||
<ChevronRight width={14} strokeWidth={2} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="w-full flex items-center gap-2 cursor-pointer" onClick={() => openPeekOverview(issue?.id)}>
|
|
||||||
<div
|
<div
|
||||||
className="flex-shrink-0 w-[6px] h-[6px] rounded-full"
|
className="flex-shrink-0 w-[6px] h-[6px] rounded-full"
|
||||||
style={{
|
style={{
|
||||||
@ -105,94 +100,86 @@ export const SubIssues: React.FC<ISubIssues> = ({
|
|||||||
<div className="line-clamp-1 text-xs text-custom-text-100 pr-2">{issue?.name}</div>
|
<div className="line-clamp-1 text-xs text-custom-text-100 pr-2">{issue?.name}</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
</IssuePeekOverview>
|
||||||
|
|
||||||
<div className="flex-shrink-0 text-sm">
|
<div className="flex-shrink-0 text-sm">
|
||||||
<IssueProperty
|
<IssueProperty
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
parentIssue={parentIssue}
|
parentIssue={parentIssue}
|
||||||
issue={issue}
|
issue={issue}
|
||||||
user={user}
|
user={user}
|
||||||
editable={editable}
|
editable={editable}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-shrink-0 text-sm">
|
<div className="flex-shrink-0 text-sm">
|
||||||
<CustomMenu width="auto" ellipsis>
|
<CustomMenu width="auto" ellipsis>
|
||||||
{editable && (
|
{editable && (
|
||||||
<CustomMenu.MenuItem onClick={() => handleIssueCrudOperation("edit", parentIssue?.id, issue)}>
|
<CustomMenu.MenuItem onClick={() => handleIssueCrudOperation("edit", parentIssue?.id, issue)}>
|
||||||
<div className="flex items-center justify-start gap-2">
|
|
||||||
<Pencil width={14} strokeWidth={2} />
|
|
||||||
<span>Edit issue</span>
|
|
||||||
</div>
|
|
||||||
</CustomMenu.MenuItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{editable && (
|
|
||||||
<CustomMenu.MenuItem onClick={() => handleIssueCrudOperation("delete", parentIssue?.id, issue)}>
|
|
||||||
<div className="flex items-center justify-start gap-2">
|
|
||||||
<Trash width={14} strokeWidth={2} />
|
|
||||||
<span>Delete issue</span>
|
|
||||||
</div>
|
|
||||||
</CustomMenu.MenuItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<CustomMenu.MenuItem
|
|
||||||
onClick={() => copyText(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`)}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<LinkIcon width={14} strokeWidth={2} />
|
<Pencil width={14} strokeWidth={2} />
|
||||||
<span>Copy issue link</span>
|
<span>Edit issue</span>
|
||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
</CustomMenu>
|
)}
|
||||||
</div>
|
|
||||||
|
|
||||||
{editable && (
|
{editable && (
|
||||||
<>
|
<CustomMenu.MenuItem onClick={() => handleIssueCrudOperation("delete", parentIssue?.id, issue)}>
|
||||||
{issuesLoader.delete.includes(issue?.id) ? (
|
<div className="flex items-center justify-start gap-2">
|
||||||
<div className="flex-shrink-0 w-[22px] h-[22px] rounded-sm bg-red-200/10 text-red-500 transition-all cursor-not-allowed overflow-hidden flex justify-center items-center">
|
<Trash width={14} strokeWidth={2} />
|
||||||
<Loader width={14} strokeWidth={2} className="animate-spin" />
|
<span>Delete issue</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</CustomMenu.MenuItem>
|
||||||
<div
|
)}
|
||||||
className="flex-shrink-0 invisible group-hover:visible w-[22px] h-[22px] rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer overflow-hidden flex justify-center items-center"
|
|
||||||
onClick={() => {
|
<CustomMenu.MenuItem
|
||||||
handleIssuesLoader({ key: "delete", issueId: issue?.id });
|
onClick={() => copyText(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`)}
|
||||||
removeIssueFromSubIssues(parentIssue?.id, issue);
|
>
|
||||||
}}
|
<div className="flex items-center justify-start gap-2">
|
||||||
>
|
<LinkIcon width={14} strokeWidth={2} />
|
||||||
<X width={14} strokeWidth={2} />
|
<span>Copy issue link</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</CustomMenu.MenuItem>
|
||||||
</>
|
</CustomMenu>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{issuesLoader.visibility.includes(issue?.id) && issue?.sub_issues_count > 0 && (
|
{editable && (
|
||||||
<SubIssuesRootList
|
<>
|
||||||
workspaceSlug={workspaceSlug}
|
{issuesLoader.delete.includes(issue?.id) ? (
|
||||||
projectId={projectId}
|
<div className="flex-shrink-0 w-[22px] h-[22px] rounded-sm bg-red-200/10 text-red-500 transition-all cursor-not-allowed overflow-hidden flex justify-center items-center">
|
||||||
parentIssue={issue}
|
<Loader width={14} strokeWidth={2} className="animate-spin" />
|
||||||
spacingLeft={spacingLeft + 22}
|
</div>
|
||||||
user={user}
|
) : (
|
||||||
editable={editable}
|
<div
|
||||||
removeIssueFromSubIssues={removeIssueFromSubIssues}
|
className="flex-shrink-0 invisible group-hover:visible w-[22px] h-[22px] rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer overflow-hidden flex justify-center items-center"
|
||||||
issuesLoader={issuesLoader}
|
onClick={() => {
|
||||||
handleIssuesLoader={handleIssuesLoader}
|
handleIssuesLoader({ key: "delete", issueId: issue?.id });
|
||||||
copyText={copyText}
|
removeIssueFromSubIssues(parentIssue?.id, issue);
|
||||||
handleIssueCrudOperation={handleIssueCrudOperation}
|
}}
|
||||||
/>
|
>
|
||||||
)}
|
<X width={14} strokeWidth={2} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{peekIssue && peekIssue === issue?.id && (
|
{issuesLoader.visibility.includes(issue?.id) && issue?.sub_issues_count > 0 && (
|
||||||
<IssuePeekOverview
|
<SubIssuesRootList
|
||||||
handleMutation={() => parentIssue && parentIssue?.id && mutate(SUB_ISSUES(parentIssue?.id))}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={issue?.project ?? ""}
|
projectId={projectId}
|
||||||
workspaceSlug={workspaceSlug ?? ""}
|
parentIssue={issue}
|
||||||
readOnly={!editable}
|
spacingLeft={spacingLeft + 22}
|
||||||
/>
|
user={user}
|
||||||
)}
|
editable={editable}
|
||||||
</div>
|
removeIssueFromSubIssues={removeIssueFromSubIssues}
|
||||||
);
|
issuesLoader={issuesLoader}
|
||||||
};
|
handleIssuesLoader={handleIssuesLoader}
|
||||||
|
copyText={copyText}
|
||||||
|
handleIssueCrudOperation={handleIssueCrudOperation}
|
||||||
|
handleUpdateIssue={handleUpdateIssue}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
@ -27,6 +27,7 @@ export interface ISubIssuesRootList {
|
|||||||
issueId: string,
|
issueId: string,
|
||||||
issue?: IIssue | null
|
issue?: IIssue | null
|
||||||
) => void;
|
) => void;
|
||||||
|
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
@ -43,6 +44,7 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
|
|||||||
handleIssuesLoader,
|
handleIssuesLoader,
|
||||||
copyText,
|
copyText,
|
||||||
handleIssueCrudOperation,
|
handleIssueCrudOperation,
|
||||||
|
handleUpdateIssue,
|
||||||
}) => {
|
}) => {
|
||||||
const { data: issues, isLoading } = useSWR(
|
const { data: issues, isLoading } = useSWR(
|
||||||
workspaceSlug && projectId && parentIssue && parentIssue?.id ? SUB_ISSUES(parentIssue?.id) : null,
|
workspaceSlug && projectId && parentIssue && parentIssue?.id ? SUB_ISSUES(parentIssue?.id) : null,
|
||||||
@ -82,6 +84,7 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
|
|||||||
handleIssuesLoader={handleIssuesLoader}
|
handleIssuesLoader={handleIssuesLoader}
|
||||||
copyText={copyText}
|
copyText={copyText}
|
||||||
handleIssueCrudOperation={handleIssueCrudOperation}
|
handleIssueCrudOperation={handleIssueCrudOperation}
|
||||||
|
handleUpdateIssue={handleUpdateIssue}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, { useCallback } from "react";
|
||||||
// next imports
|
// next imports
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// swr
|
// swr
|
||||||
@ -13,6 +13,7 @@ import { ProgressBar } from "./progressbar";
|
|||||||
// ui
|
// ui
|
||||||
import { CustomMenu } from "@plane/ui";
|
import { CustomMenu } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import { useProjectMyMembership } from "contexts/project-member.context";
|
import { useProjectMyMembership } from "contexts/project-member.context";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// helpers
|
// helpers
|
||||||
@ -49,6 +50,8 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user }) =
|
|||||||
peekIssue: string;
|
peekIssue: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { issue: issueStore, issueDetail: issueDetailStore } = useMobxStore();
|
||||||
|
|
||||||
const { memberRole } = useProjectMyMembership();
|
const { memberRole } = useProjectMyMembership();
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
@ -158,6 +161,21 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user }) =
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUpdateIssue = useCallback(
|
||||||
|
(issue: IIssue, data: Partial<IIssue>) => {
|
||||||
|
if (!workspaceSlug || !projectId || !user) return;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
...issue,
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
|
||||||
|
issueStore.updateIssueStructure(null, null, payload);
|
||||||
|
issueDetailStore.updateIssue(workspaceSlug.toString(), projectId.toString(), issue.id, data);
|
||||||
|
},
|
||||||
|
[issueStore, issueDetailStore, projectId, user, workspaceSlug]
|
||||||
|
);
|
||||||
|
|
||||||
const isEditable = memberRole?.isGuest || memberRole?.isViewer ? false : true;
|
const isEditable = memberRole?.isGuest || memberRole?.isViewer ? false : true;
|
||||||
|
|
||||||
const mutateSubIssues = (parentIssueId: string | null) => {
|
const mutateSubIssues = (parentIssueId: string | null) => {
|
||||||
@ -228,6 +246,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user }) =
|
|||||||
handleIssuesLoader={handleIssuesLoader}
|
handleIssuesLoader={handleIssuesLoader}
|
||||||
copyText={copyText}
|
copyText={copyText}
|
||||||
handleIssueCrudOperation={handleIssueCrudOperation}
|
handleIssueCrudOperation={handleIssueCrudOperation}
|
||||||
|
handleUpdateIssue={handleUpdateIssue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -45,8 +45,8 @@ export const ModulesListGanttChartView: React.FC = observer(() => {
|
|||||||
loaderTitle="Modules"
|
loaderTitle="Modules"
|
||||||
blocks={modules ? blockFormat(modules) : null}
|
blocks={modules ? blockFormat(modules) : null}
|
||||||
blockUpdateHandler={(block, payload) => handleModuleUpdate(block, payload)}
|
blockUpdateHandler={(block, payload) => handleModuleUpdate(block, payload)}
|
||||||
SidebarBlockRender={ModuleGanttSidebarBlock}
|
sidebarBlockToRender={ModuleGanttSidebarBlock}
|
||||||
BlockRender={ModuleGanttBlock}
|
blockToRender={(data: IModule) => <ModuleGanttBlock data={data} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -265,9 +265,10 @@ export class IssueStore implements IIssueStore {
|
|||||||
...i,
|
...i,
|
||||||
...(i.id === issue.id
|
...(i.id === issue.id
|
||||||
? {
|
? {
|
||||||
|
...issue,
|
||||||
sort_order: payload.sort_order?.newSortOrder ?? i.sort_order,
|
sort_order: payload.sort_order?.newSortOrder ?? i.sort_order,
|
||||||
start_date: payload.start_date,
|
start_date: payload.start_date ?? i.start_date,
|
||||||
target_date: payload.target_date,
|
target_date: payload.target_date ?? i.target_date,
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
}));
|
}));
|
||||||
@ -288,7 +289,7 @@ export class IssueStore implements IIssueStore {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const newPayload: any = { ...payload };
|
const newPayload: any = { ...issue, ...payload };
|
||||||
|
|
||||||
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user