diff --git a/web/ce/store/timeline/base-timeline.store.ts b/web/ce/store/timeline/base-timeline.store.ts index 71169ddada..3e15d124db 100644 --- a/web/ce/store/timeline/base-timeline.store.ts +++ b/web/ce/store/timeline/base-timeline.store.ts @@ -44,7 +44,11 @@ export interface IBaseTimelineStore { updateActiveBlockId: (blockId: string | null) => void; updateRenderView: (data: any) => void; updateAllBlocksOnChartChangeWhileDragging: (addedWidth: number) => void; - getUpdatedPositionAfterDrag: (id: string, ignoreDependencies?: boolean) => IBlockUpdateDependencyData[]; + getUpdatedPositionAfterDrag: ( + id: string, + shouldUpdateHalfBlock: boolean, + ignoreDependencies?: boolean + ) => IBlockUpdateDependencyData[]; updateBlockPosition: (id: string, deltaLeft: number, deltaWidth: number, ignoreDependencies?: boolean) => void; getNumberOfDaysFromPosition: (position: number | undefined) => number | undefined; setIsDragging: (isDragging: boolean) => void; @@ -271,24 +275,30 @@ export class BaseTimeLineStore implements IBaseTimelineStore { /** * returns updates dates of blocks post drag. * @param id + * @param shouldUpdateHalfBlock if is a half block then update the incomplete block only if this is true * @returns */ - getUpdatedPositionAfterDrag = action((id: string) => { + getUpdatedPositionAfterDrag = action((id: string, shouldUpdateHalfBlock: boolean) => { const currBlock = this.blocksMap[id]; if (!currBlock?.position || !this.currentViewData) return []; - return [ - { - id, - start_date: renderFormattedPayloadDate( - getDateFromPositionOnGantt(currBlock.position.marginLeft, this.currentViewData) - ), - target_date: renderFormattedPayloadDate( - getDateFromPositionOnGantt(currBlock.position.marginLeft + currBlock.position.width, this.currentViewData, -1) - ), - }, - ] as IBlockUpdateDependencyData[]; + const updatePayload: IBlockUpdateDependencyData = { id }; + + // If shouldUpdateHalfBlock or the start date is available then update start date + if (shouldUpdateHalfBlock || currBlock.start_date) { + updatePayload.start_date = renderFormattedPayloadDate( + getDateFromPositionOnGantt(currBlock.position.marginLeft, this.currentViewData) + ); + } + // If shouldUpdateHalfBlock or the target date is available then update target date + if (shouldUpdateHalfBlock || currBlock.target_date) { + updatePayload.target_date = renderFormattedPayloadDate( + getDateFromPositionOnGantt(currBlock.position.marginLeft + currBlock.position.width, this.currentViewData, -1) + ); + } + + return [updatePayload]; }); /** diff --git a/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts b/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts index a8c93a8041..e6a1a887e0 100644 --- a/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts +++ b/web/core/components/gantt-chart/helpers/blockResizables/use-gantt-resizable.ts @@ -4,7 +4,7 @@ import { setToast } from "@plane/ui"; // hooks import { useTimeLineChartStore } from "@/hooks/use-timeline-chart"; // -import { SIDEBAR_WIDTH } from "../../constants"; +import { DEFAULT_BLOCK_WIDTH, SIDEBAR_WIDTH } from "../../constants"; import { IBlockUpdateDependencyData, IGanttBlock } from "../../types"; export const useGanttResizable = ( @@ -75,10 +75,19 @@ export const useGanttResizable = ( const prevWidth = parseFloat(resizableDiv.style.width.slice(0, -2)); // calculate new width const marginDelta = prevMarginLeft - marginLeft; - width = prevWidth + marginDelta; + // If target date does not exist while dragging with left handle the revert to default width + width = block.target_date ? prevWidth + marginDelta : DEFAULT_BLOCK_WIDTH; } else if (dragDirection === "right") { // calculate new width and update the initialMarginLeft using += width = Math.round(mouseX / dayWidth) * dayWidth - marginLeft; + + // If start date does not exist while dragging with right handle the revert to default width and adjust marginLeft accordingly + if (!block.start_date) { + // calculate new right and update the marginLeft to the newly calculated one + const marginRight = Math.round(mouseX / dayWidth) * dayWidth; + marginLeft = marginRight - DEFAULT_BLOCK_WIDTH; + width = DEFAULT_BLOCK_WIDTH; + } } else if (dragDirection === "move") { // calculate new marginLeft and update the initial marginLeft using -= marginLeft = Math.round((mouseX - initialPositionRef.current.offsetX) / dayWidth) * dayWidth; @@ -105,8 +114,12 @@ export const useGanttResizable = ( ganttContainerElement.removeEventListener("scroll", handleOnScroll); document.removeEventListener("mouseup", handleMouseUp); + // update half blocks only when the missing side of the block is directly dragged + const shouldUpdateHalfBlock = + (dragDirection === "left" && !block.start_date) || (dragDirection === "right" && !block.target_date); + try { - const blockUpdates = getUpdatedPositionAfterDrag(block.id, dragDirection !== "move"); + const blockUpdates = getUpdatedPositionAfterDrag(block.id, shouldUpdateHalfBlock, dragDirection !== "move"); updateBlockDates && updateBlockDates(blockUpdates); } catch (e) { setToast; diff --git a/web/core/components/gantt-chart/views/helpers.ts b/web/core/components/gantt-chart/views/helpers.ts index 54b1a43be1..81064bd469 100644 --- a/web/core/components/gantt-chart/views/helpers.ts +++ b/web/core/components/gantt-chart/views/helpers.ts @@ -99,7 +99,7 @@ export const getItemPositionWidth = (chartData: ChartDataType, itemData: IGanttB // get scroll position from the number of days and width of each day scrollPosition = itemStartDate ? getPositionFromDate(chartData, itemStartDate, 0) - : getPositionFromDate(chartData, itemTargetDate!, -1 * DEFAULT_BLOCK_WIDTH); + : getPositionFromDate(chartData, itemTargetDate!, -1 * DEFAULT_BLOCK_WIDTH + chartData.data.dayWidth); if (itemStartDate && itemTargetDate) { // get width of block