mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
d6abb87a3a
* fix: Implemented new workflow in the issue store and updated the quick add workflow in list layout * fix: initial load and mutaion of issues in list layout * dev: implemented the new project issues store with grouped, subGrouped and unGrouped issue computed functions * dev: default display properties data made as a function * conflict: merge conflict resolved * dev: implemented quick add logic in kanban * chore: implemented quick add logic in calendar and spreadsheet layout * fix: spreadsheet layout quick add fix * dev: optimised the issues workflow and handled the issues order_by filter * dev: project issue CRUD operations in new issue store architecture * dev: issues filtering in calendar layout * fix: build error * dev/issue_filters_store * chore: updated filters computed structure * conflict: merge conflicts resolved in project issues * dev: implemented gantt chart for project issues using the new mobx store * dev: initialized cycle and module issue filters store * dev: issue store and list layout store updates * dev: quick add and update, delete issue in the list * refactor list root changes * dev: store new structure * refactor spreadsheet and gnatt project roots * fix errors for base gantt and spreadsheet roots * connect Calendar project view * minor house keeping * connect Kanban View to th enew store * generalise base calendar issue actions * dev: store project issues and issue filters * dev: store project issues and filters * dev: updated undefined with displayFilters in project issue store * Add Quick add to all the layouts * connect module views to store * dev: Rendering list issues in project issues * dev: removed console log * dev: module filters store * fix errors and connect modules list and quick add for list * dev: module issue store * dev: modle filter store issue fixed and updates cycle issue filters * minor house keeping changes * dev: cycle issues and cycle filters * connecty cycles to teh store * dev: project view issues and issue filtrs * connect project views * dev: updated applied filters in layouts * dev: replaced project id with view id in project views * dev: in cycle and module store made cycledId and moduleId as optional * fix minor issues and build errots * dev: project draft and archived issues store and filters --------- Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so> Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com> Co-authored-by: rahulramesha <rahulramesham@gmail.com>
172 lines
6.7 KiB
TypeScript
172 lines
6.7 KiB
TypeScript
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 { GanttInlineCreateIssueForm, IssueGanttSidebarBlock } from "components/issues";
|
|
// helpers
|
|
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
|
// types
|
|
import { IGanttBlock, IBlockUpdateData } from "components/gantt-chart/types";
|
|
import { IIssue } from "types";
|
|
|
|
type Props = {
|
|
title: string;
|
|
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
|
|
blocks: IGanttBlock[] | null;
|
|
enableReorder: boolean;
|
|
enableQuickIssueCreate?: boolean;
|
|
quickAddCallback?: (
|
|
workspaceSlug: string,
|
|
projectId: string,
|
|
data: IIssue,
|
|
viewId?: string
|
|
) => Promise<IIssue | undefined>;
|
|
viewId?: string;
|
|
};
|
|
|
|
export const IssueGanttSidebar: React.FC<Props> = (props) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const { title, blockUpdateHandler, blocks, enableReorder, enableQuickIssueCreate, quickAddCallback, viewId } = 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}
|
|
</>
|
|
{enableQuickIssueCreate && (
|
|
<GanttInlineCreateIssueForm quickAddCallback={quickAddCallback} viewId={viewId} />
|
|
)}
|
|
</div>
|
|
)}
|
|
</StrictModeDroppable>
|
|
</DragDropContext>
|
|
);
|
|
};
|