forked from github/plane
refactor: gantt sidebar (#2705)
* refactor: gantt sidebar * fix: exception error fix: file placement * refactor: not passing sidebar block as props
This commit is contained in:
parent
79df59f618
commit
34bccd7e06
@ -10,7 +10,7 @@ import { CycleService } from "services/cycle.service";
|
|||||||
import useUser from "hooks/use-user";
|
import useUser from "hooks/use-user";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, CycleGanttSidebar } from "components/gantt-chart";
|
||||||
import { CycleGanttBlock, CycleGanttSidebarBlock } from "components/cycles";
|
import { CycleGanttBlock, CycleGanttSidebarBlock } from "components/cycles";
|
||||||
// types
|
// types
|
||||||
import { ICycle } from "types";
|
import { ICycle } from "types";
|
||||||
@ -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)}
|
||||||
|
sidebarToRender={(props) => <CycleGanttSidebar {...props} />}
|
||||||
blockToRender={(data: ICycle) => <CycleGanttBlock data={data} />}
|
blockToRender={(data: ICycle) => <CycleGanttBlock data={data} />}
|
||||||
sidebarBlockToRender={(data: ICycle) => <CycleGanttSidebarBlock data={data} />}
|
|
||||||
enableBlockLeftResize={false}
|
enableBlockLeftResize={false}
|
||||||
enableBlockRightResize={false}
|
enableBlockRightResize={false}
|
||||||
enableBlockMove={false}
|
enableBlockMove={false}
|
||||||
|
@ -2,7 +2,7 @@ import { FC, useEffect, useState } from "react";
|
|||||||
// icons
|
// icons
|
||||||
// components
|
// components
|
||||||
import { GanttChartBlocks } from "components/gantt-chart";
|
import { GanttChartBlocks } from "components/gantt-chart";
|
||||||
import { GanttSidebar } from "../sidebar";
|
// import { GanttSidebar } from "../sidebar";
|
||||||
// import { HourChartView } from "./hours";
|
// import { HourChartView } from "./hours";
|
||||||
// import { DayChartView } from "./day";
|
// import { DayChartView } from "./day";
|
||||||
// import { WeekChartView } from "./week";
|
// import { WeekChartView } from "./week";
|
||||||
@ -40,7 +40,7 @@ type ChartViewRootProps = {
|
|||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
blockToRender: (data: any) => React.ReactNode;
|
blockToRender: (data: any) => React.ReactNode;
|
||||||
sidebarBlockToRender: (block: any) => React.ReactNode;
|
sidebarToRender: (props: any) => React.ReactNode;
|
||||||
enableBlockLeftResize: boolean;
|
enableBlockLeftResize: boolean;
|
||||||
enableBlockRightResize: boolean;
|
enableBlockRightResize: boolean;
|
||||||
enableBlockMove: boolean;
|
enableBlockMove: boolean;
|
||||||
@ -54,7 +54,7 @@ export const ChartViewRoot: FC<ChartViewRootProps> = ({
|
|||||||
blocks = null,
|
blocks = null,
|
||||||
loaderTitle,
|
loaderTitle,
|
||||||
blockUpdateHandler,
|
blockUpdateHandler,
|
||||||
sidebarBlockToRender,
|
sidebarToRender,
|
||||||
blockToRender,
|
blockToRender,
|
||||||
enableBlockLeftResize,
|
enableBlockLeftResize,
|
||||||
enableBlockRightResize,
|
enableBlockRightResize,
|
||||||
@ -285,13 +285,8 @@ export const ChartViewRoot: FC<ChartViewRootProps> = ({
|
|||||||
<h6>{title}</h6>
|
<h6>{title}</h6>
|
||||||
<h6>Duration</h6>
|
<h6>Duration</h6>
|
||||||
</div>
|
</div>
|
||||||
<GanttSidebar
|
|
||||||
title={title}
|
{sidebarToRender && sidebarToRender({ title, blockUpdateHandler, blocks, enableReorder })}
|
||||||
blockUpdateHandler={blockUpdateHandler}
|
|
||||||
blocks={chartBlocks}
|
|
||||||
sidebarBlockToRender={sidebarBlockToRender}
|
|
||||||
enableReorder={enableReorder}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="relative flex h-full w-full flex-1 flex-col overflow-hidden overflow-x-auto horizontal-scroll-enable"
|
className="relative flex h-full w-full flex-1 flex-col overflow-hidden overflow-x-auto horizontal-scroll-enable"
|
||||||
|
@ -3,3 +3,4 @@ export * from "./helpers";
|
|||||||
export * from "./hooks";
|
export * from "./hooks";
|
||||||
export * from "./root";
|
export * from "./root";
|
||||||
export * from "./types";
|
export * from "./types";
|
||||||
|
export * from "./sidebar";
|
||||||
|
@ -13,7 +13,7 @@ type GanttChartRootProps = {
|
|||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
blockToRender: (data: any) => React.ReactNode;
|
blockToRender: (data: any) => React.ReactNode;
|
||||||
sidebarBlockToRender: (block: any) => React.ReactNode;
|
sidebarToRender: (props: any) => React.ReactNode;
|
||||||
enableBlockLeftResize?: boolean;
|
enableBlockLeftResize?: boolean;
|
||||||
enableBlockRightResize?: boolean;
|
enableBlockRightResize?: boolean;
|
||||||
enableBlockMove?: boolean;
|
enableBlockMove?: boolean;
|
||||||
@ -27,7 +27,7 @@ export const GanttChartRoot: FC<GanttChartRootProps> = ({
|
|||||||
blocks,
|
blocks,
|
||||||
loaderTitle = "blocks",
|
loaderTitle = "blocks",
|
||||||
blockUpdateHandler,
|
blockUpdateHandler,
|
||||||
sidebarBlockToRender,
|
sidebarToRender,
|
||||||
blockToRender,
|
blockToRender,
|
||||||
enableBlockLeftResize = true,
|
enableBlockLeftResize = true,
|
||||||
enableBlockRightResize = true,
|
enableBlockRightResize = true,
|
||||||
@ -42,7 +42,7 @@ export const GanttChartRoot: FC<GanttChartRootProps> = ({
|
|||||||
blocks={blocks}
|
blocks={blocks}
|
||||||
loaderTitle={loaderTitle}
|
loaderTitle={loaderTitle}
|
||||||
blockUpdateHandler={blockUpdateHandler}
|
blockUpdateHandler={blockUpdateHandler}
|
||||||
sidebarBlockToRender={sidebarBlockToRender}
|
sidebarToRender={sidebarToRender}
|
||||||
blockToRender={blockToRender}
|
blockToRender={blockToRender}
|
||||||
enableBlockLeftResize={enableBlockLeftResize}
|
enableBlockLeftResize={enableBlockLeftResize}
|
||||||
enableBlockRightResize={enableBlockRightResize}
|
enableBlockRightResize={enableBlockRightResize}
|
||||||
|
@ -3,25 +3,26 @@ import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
|||||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
import { MoreVertical } from "lucide-react";
|
import { MoreVertical } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useChart } from "./hooks";
|
import { useChart } from "components/gantt-chart/hooks";
|
||||||
// ui
|
// ui
|
||||||
import { Loader } from "@plane/ui";
|
import { Loader } from "@plane/ui";
|
||||||
|
// components
|
||||||
|
import { CycleGanttSidebarBlock } from "components/cycles";
|
||||||
// helpers
|
// helpers
|
||||||
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { IBlockUpdateData, IGanttBlock } from "./types";
|
import { IBlockUpdateData, IGanttBlock } from "components/gantt-chart/types";
|
||||||
|
|
||||||
type Props = {
|
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>;
|
|
||||||
enableReorder: boolean;
|
enableReorder: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GanttSidebar: React.FC<Props> = (props) => {
|
export const CycleGanttSidebar: 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 } = props;
|
const { title, blockUpdateHandler, blocks, enableReorder } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId } = router.query;
|
const { cycleId } = router.query;
|
||||||
@ -128,7 +129,7 @@ export const GanttSidebar: React.FC<Props> = (props) => {
|
|||||||
)}
|
)}
|
||||||
<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">
|
||||||
<SidebarBlockRender data={block.data} />
|
<CycleGanttSidebarBlock data={block.data} />
|
||||||
</div>
|
</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" : ""}
|
4
web/components/gantt-chart/sidebar/index.ts
Normal file
4
web/components/gantt-chart/sidebar/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from "./cycle-sidebar";
|
||||||
|
export * from "./module-sidebar";
|
||||||
|
export * from "./sidebar";
|
||||||
|
export * from "./project-view-sidebar";
|
@ -3,25 +3,26 @@ import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
|||||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
import { MoreVertical } from "lucide-react";
|
import { MoreVertical } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useChart } from "./hooks";
|
import { useChart } from "components/gantt-chart/hooks";
|
||||||
// ui
|
// ui
|
||||||
import { Loader } from "@plane/ui";
|
import { Loader } from "@plane/ui";
|
||||||
|
// components
|
||||||
|
import { ModuleGanttSidebarBlock } from "components/modules";
|
||||||
// helpers
|
// helpers
|
||||||
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { IBlockUpdateData, IGanttBlock } from "./types";
|
import { IBlockUpdateData, IGanttBlock } from "components/gantt-chart";
|
||||||
|
|
||||||
type Props = {
|
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>;
|
|
||||||
enableReorder: boolean;
|
enableReorder: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GanttSidebar: React.FC<Props> = (props) => {
|
export const ModuleGanttSidebar: 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 } = props;
|
const { title, blockUpdateHandler, blocks, enableReorder } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId } = router.query;
|
const { cycleId } = router.query;
|
||||||
@ -128,7 +129,7 @@ export const GanttSidebar: React.FC<Props> = (props) => {
|
|||||||
)}
|
)}
|
||||||
<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">
|
||||||
<SidebarBlockRender data={block.data} />
|
<ModuleGanttSidebarBlock data={block.data} />
|
||||||
</div>
|
</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" : ""}
|
160
web/components/gantt-chart/sidebar/project-view-sidebar.tsx
Normal file
160
web/components/gantt-chart/sidebar/project-view-sidebar.tsx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
||||||
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
|
import { MoreVertical } from "lucide-react";
|
||||||
|
// hooks
|
||||||
|
import { useChart } from "components/gantt-chart/hooks";
|
||||||
|
// ui
|
||||||
|
import { Loader } from "@plane/ui";
|
||||||
|
// components
|
||||||
|
import { IssueGanttSidebarBlock } from "components/issues";
|
||||||
|
// helpers
|
||||||
|
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
||||||
|
// types
|
||||||
|
import { IBlockUpdateData, IGanttBlock } from "components/gantt-chart/types";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
title: string;
|
||||||
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
|
blocks: IGanttBlock[] | null;
|
||||||
|
enableReorder: boolean;
|
||||||
|
enableQuickIssueCreate?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ProjectViewGanttSidebar: React.FC<Props> = (props) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { title, blockUpdateHandler, blocks, enableReorder } = props;
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const { cycleId } = router.query;
|
||||||
|
|
||||||
|
const { activeBlock, dispatch } = useChart();
|
||||||
|
|
||||||
|
// update the active block on hover
|
||||||
|
const updateActiveBlock = (block: IGanttBlock | null) => {
|
||||||
|
dispatch({
|
||||||
|
type: "PARTIAL_UPDATE",
|
||||||
|
payload: {
|
||||||
|
activeBlock: block,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOrderChange = (result: DropResult) => {
|
||||||
|
if (!blocks) return;
|
||||||
|
|
||||||
|
const { source, destination } = result;
|
||||||
|
|
||||||
|
// return if dropped outside the list
|
||||||
|
if (!destination) return;
|
||||||
|
|
||||||
|
// return if dropped on the same index
|
||||||
|
if (source.index === destination.index) return;
|
||||||
|
|
||||||
|
let updatedSortOrder = blocks[source.index].sort_order;
|
||||||
|
|
||||||
|
// update the sort order to the lowest if dropped at the top
|
||||||
|
if (destination.index === 0) updatedSortOrder = blocks[0].sort_order - 1000;
|
||||||
|
// update the sort order to the highest if dropped at the bottom
|
||||||
|
else if (destination.index === blocks.length - 1) updatedSortOrder = blocks[blocks.length - 1].sort_order + 1000;
|
||||||
|
// update the sort order to the average of the two adjacent blocks if dropped in between
|
||||||
|
else {
|
||||||
|
const destinationSortingOrder = blocks[destination.index].sort_order;
|
||||||
|
const relativeDestinationSortingOrder =
|
||||||
|
source.index < destination.index
|
||||||
|
? blocks[destination.index + 1].sort_order
|
||||||
|
: blocks[destination.index - 1].sort_order;
|
||||||
|
|
||||||
|
updatedSortOrder = (destinationSortingOrder + relativeDestinationSortingOrder) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract the element from the source index and insert it at the destination index without updating the entire array
|
||||||
|
const removedElement = blocks.splice(source.index, 1)[0];
|
||||||
|
blocks.splice(destination.index, 0, removedElement);
|
||||||
|
|
||||||
|
// call the block update handler with the updated sort order, new and old index
|
||||||
|
blockUpdateHandler(removedElement.data, {
|
||||||
|
sort_order: {
|
||||||
|
destinationIndex: destination.index,
|
||||||
|
newSortOrder: updatedSortOrder,
|
||||||
|
sourceIndex: source.index,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DragDropContext onDragEnd={handleOrderChange}>
|
||||||
|
<StrictModeDroppable droppableId="gantt-sidebar">
|
||||||
|
{(droppableProvided) => (
|
||||||
|
<div
|
||||||
|
id={`gantt-sidebar-${cycleId}`}
|
||||||
|
className="max-h-full overflow-y-auto pl-2.5 mt-3"
|
||||||
|
ref={droppableProvided.innerRef}
|
||||||
|
{...droppableProvided.droppableProps}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
{blocks ? (
|
||||||
|
blocks.map((block, index) => {
|
||||||
|
const duration = findTotalDaysInRange(block.start_date ?? "", block.target_date ?? "", true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Draggable
|
||||||
|
key={`sidebar-block-${block.id}`}
|
||||||
|
draggableId={`sidebar-block-${block.id}`}
|
||||||
|
index={index}
|
||||||
|
isDragDisabled={!enableReorder}
|
||||||
|
>
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
className={`h-11 ${snapshot.isDragging ? "bg-custom-background-80 rounded" : ""}`}
|
||||||
|
onMouseEnter={() => updateActiveBlock(block)}
|
||||||
|
onMouseLeave={() => updateActiveBlock(null)}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
id={`sidebar-block-${block.id}`}
|
||||||
|
className={`group h-full w-full flex items-center gap-2 rounded-l px-2 pr-4 ${
|
||||||
|
activeBlock?.id === block.id ? "bg-custom-background-80" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{enableReorder && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="rounded p-0.5 text-custom-sidebar-text-200 flex flex-shrink-0 opacity-0 group-hover:opacity-100"
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
>
|
||||||
|
<MoreVertical className="h-3.5 w-3.5" />
|
||||||
|
<MoreVertical className="h-3.5 w-3.5 -ml-5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<div className="flex-grow truncate h-full flex items-center justify-between gap-2">
|
||||||
|
<div className="flex-grow truncate">
|
||||||
|
<IssueGanttSidebarBlock data={block.data} handleIssue={blockUpdateHandler} />
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 text-sm text-custom-text-200">
|
||||||
|
{duration} day{duration > 1 ? "s" : ""}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<Loader className="pr-2 space-y-3">
|
||||||
|
<Loader.Item height="34px" />
|
||||||
|
<Loader.Item height="34px" />
|
||||||
|
<Loader.Item height="34px" />
|
||||||
|
<Loader.Item height="34px" />
|
||||||
|
</Loader>
|
||||||
|
)}
|
||||||
|
{droppableProvided.placeholder}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</StrictModeDroppable>
|
||||||
|
</DragDropContext>
|
||||||
|
);
|
||||||
|
};
|
@ -3,28 +3,27 @@ import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
|||||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
import { MoreVertical } from "lucide-react";
|
import { MoreVertical } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useChart } from "./hooks";
|
import { useChart } from "components/gantt-chart/hooks";
|
||||||
// ui
|
// ui
|
||||||
import { Loader } from "@plane/ui";
|
import { Loader } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { GanttInlineCreateIssueForm } from "components/issues";
|
import { GanttInlineCreateIssueForm, IssueGanttSidebarBlock } from "components/issues";
|
||||||
// helpers
|
// helpers
|
||||||
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { IBlockUpdateData, IGanttBlock } from "./types";
|
import { IGanttBlock, IBlockUpdateData } from "components/gantt-chart/types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string;
|
title: string;
|
||||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
||||||
blocks: IGanttBlock[] | null;
|
blocks: IGanttBlock[] | null;
|
||||||
sidebarBlockToRender: (block: any) => React.ReactNode;
|
|
||||||
enableReorder: boolean;
|
enableReorder: boolean;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GanttSidebar: React.FC<Props> = (props) => {
|
export const IssueGanttSidebar: 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, sidebarBlockToRender, enableReorder, enableQuickIssueCreate } = props;
|
const { title, blockUpdateHandler, blocks, enableReorder, enableQuickIssueCreate } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId } = router.query;
|
const { cycleId } = router.query;
|
||||||
@ -130,7 +129,9 @@ 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">{sidebarBlockToRender(block.data)}</div>
|
<div className="flex-grow truncate">
|
||||||
|
<IssueGanttSidebarBlock data={block.data} handleIssue={blockUpdateHandler} />
|
||||||
|
</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>
|
||||||
@ -151,7 +152,7 @@ export const GanttSidebar: React.FC<Props> = (props) => {
|
|||||||
)}
|
)}
|
||||||
{droppableProvided.placeholder}
|
{droppableProvided.placeholder}
|
||||||
</>
|
</>
|
||||||
<GanttInlineCreateIssueForm />
|
{enableQuickIssueCreate && <GanttInlineCreateIssueForm />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</StrictModeDroppable>
|
</StrictModeDroppable>
|
@ -4,8 +4,13 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { IssueGanttBlock } from "components/issues";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import {
|
||||||
|
GanttChartRoot,
|
||||||
|
IBlockUpdateData,
|
||||||
|
renderIssueBlocksStructure,
|
||||||
|
IssueGanttSidebar,
|
||||||
|
} from "components/gantt-chart";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
@ -40,7 +45,7 @@ export const CycleGanttLayout: React.FC = observer(() => {
|
|||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
sidebarToRender={(props) => <IssueGanttSidebar {...props} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -4,8 +4,13 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
||||||
|
import {
|
||||||
|
GanttChartRoot,
|
||||||
|
IBlockUpdateData,
|
||||||
|
renderIssueBlocksStructure,
|
||||||
|
IssueGanttSidebar,
|
||||||
|
} from "components/gantt-chart";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
@ -39,8 +44,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}
|
||||||
|
sidebarToRender={(data) => <IssueGanttSidebar {...data} />}
|
||||||
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -6,8 +6,13 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
// hooks
|
// hooks
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { IssueGanttBlock } from "components/issues";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import {
|
||||||
|
GanttChartRoot,
|
||||||
|
IBlockUpdateData,
|
||||||
|
renderIssueBlocksStructure,
|
||||||
|
ProjectViewGanttSidebar,
|
||||||
|
} from "components/gantt-chart";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
@ -42,7 +47,7 @@ export const ProjectViewGanttLayout: React.FC = observer(() => {
|
|||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
sidebarToRender={(props) => <ProjectViewGanttSidebar {...props} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -5,8 +5,13 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { IssueGanttBlock } from "components/issues";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import {
|
||||||
|
GanttChartRoot,
|
||||||
|
IBlockUpdateData,
|
||||||
|
renderIssueBlocksStructure,
|
||||||
|
IssueGanttSidebar,
|
||||||
|
} from "components/gantt-chart";
|
||||||
// types
|
// types
|
||||||
import { IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueUnGroupedStructure } from "store/issue";
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
@ -41,7 +46,7 @@ export const GanttLayout: React.FC = observer(() => {
|
|||||||
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null}
|
||||||
blockUpdateHandler={updateIssue}
|
blockUpdateHandler={updateIssue}
|
||||||
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
blockToRender={(data: IIssue) => <IssueGanttBlock data={data} handleIssue={updateIssue} />}
|
||||||
sidebarBlockToRender={(data: IIssue) => <IssueGanttSidebarBlock data={data} handleIssue={updateIssue} />}
|
sidebarToRender={(props) => <IssueGanttSidebar {...props} enableQuickIssueCreate />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
enableBlockMove={isAllowed}
|
enableBlockMove={isAllowed}
|
||||||
|
@ -3,8 +3,8 @@ import { observer } from "mobx-react-lite";
|
|||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, ModuleGanttSidebar } from "components/gantt-chart";
|
||||||
import { ModuleGanttBlock, ModuleGanttSidebarBlock } from "components/modules";
|
import { ModuleGanttBlock } from "components/modules";
|
||||||
// types
|
// types
|
||||||
import { IModule } from "types";
|
import { IModule } from "types";
|
||||||
|
|
||||||
@ -44,8 +44,8 @@ export const ModulesListGanttChartView: React.FC = observer(() => {
|
|||||||
title="Modules"
|
title="Modules"
|
||||||
loaderTitle="Modules"
|
loaderTitle="Modules"
|
||||||
blocks={modules ? blockFormat(modules) : null}
|
blocks={modules ? blockFormat(modules) : null}
|
||||||
|
sidebarToRender={(props) => <ModuleGanttSidebar {...props} />}
|
||||||
blockUpdateHandler={(block, payload) => handleModuleUpdate(block, payload)}
|
blockUpdateHandler={(block, payload) => handleModuleUpdate(block, payload)}
|
||||||
sidebarBlockToRender={ModuleGanttSidebarBlock}
|
|
||||||
blockToRender={(data: IModule) => <ModuleGanttBlock data={data} />}
|
blockToRender={(data: IModule) => <ModuleGanttBlock data={data} />}
|
||||||
enableBlockLeftResize={isAllowed}
|
enableBlockLeftResize={isAllowed}
|
||||||
enableBlockRightResize={isAllowed}
|
enableBlockRightResize={isAllowed}
|
||||||
|
Loading…
Reference in New Issue
Block a user