fix: horizontal scroll in gantt chart while dragging (#3664)

* fix horizontal scroll in gantt chart while dragging

* add aline indicator for quick add

* add border color for line above quick add in gantt to make it look better in dark mode
This commit is contained in:
rahulramesha 2024-02-14 18:15:13 +05:30 committed by GitHub
parent b827a1af27
commit 489555f788
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 25 additions and 40 deletions

View File

@ -33,6 +33,7 @@ type Props = {
sidebarToRender: (props: any) => React.ReactNode; sidebarToRender: (props: any) => React.ReactNode;
title: string; title: string;
updateCurrentViewRenderPayload: (direction: "left" | "right", currentView: TGanttViews) => void; updateCurrentViewRenderPayload: (direction: "left" | "right", currentView: TGanttViews) => void;
quickAdd?: React.JSX.Element | undefined;
}; };
export const GanttChartMainContent: React.FC<Props> = (props) => { export const GanttChartMainContent: React.FC<Props> = (props) => {
@ -52,6 +53,7 @@ export const GanttChartMainContent: React.FC<Props> = (props) => {
sidebarToRender, sidebarToRender,
title, title,
updateCurrentViewRenderPayload, updateCurrentViewRenderPayload,
quickAdd,
} = props; } = props;
// chart hook // chart hook
const { currentView, currentViewData, updateScrollLeft } = useChart(); const { currentView, currentViewData, updateScrollLeft } = useChart();
@ -101,6 +103,7 @@ export const GanttChartMainContent: React.FC<Props> = (props) => {
enableReorder={enableReorder} enableReorder={enableReorder}
sidebarToRender={sidebarToRender} sidebarToRender={sidebarToRender}
title={title} title={title}
quickAdd={quickAdd}
/> />
<div className="relative min-h-full h-max flex-shrink-0 flex-grow"> <div className="relative min-h-full h-max flex-shrink-0 flex-grow">
<ActiveChartView /> <ActiveChartView />

View File

@ -31,6 +31,7 @@ type ChartViewRootProps = {
enableAddBlock: boolean; enableAddBlock: boolean;
bottomSpacing: boolean; bottomSpacing: boolean;
showAllBlocks: boolean; showAllBlocks: boolean;
quickAdd?: React.JSX.Element | undefined;
}; };
export const ChartViewRoot: FC<ChartViewRootProps> = (props) => { export const ChartViewRoot: FC<ChartViewRootProps> = (props) => {
@ -49,6 +50,7 @@ export const ChartViewRoot: FC<ChartViewRootProps> = (props) => {
enableAddBlock, enableAddBlock,
bottomSpacing, bottomSpacing,
showAllBlocks, showAllBlocks,
quickAdd,
} = props; } = props;
// states // states
const [itemsContainerWidth, setItemsContainerWidth] = useState(0); const [itemsContainerWidth, setItemsContainerWidth] = useState(0);
@ -200,6 +202,7 @@ export const ChartViewRoot: FC<ChartViewRootProps> = (props) => {
sidebarToRender={sidebarToRender} sidebarToRender={sidebarToRender}
title={title} title={title}
updateCurrentViewRenderPayload={updateCurrentViewRenderPayload} updateCurrentViewRenderPayload={updateCurrentViewRenderPayload}
quickAdd={quickAdd}
/> />
</div> </div>
); );

View File

@ -12,6 +12,7 @@ type GanttChartRootProps = {
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void; blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
blockToRender: (data: any) => React.ReactNode; blockToRender: (data: any) => React.ReactNode;
sidebarToRender: (props: any) => React.ReactNode; sidebarToRender: (props: any) => React.ReactNode;
quickAdd?: React.JSX.Element | undefined;
enableBlockLeftResize?: boolean; enableBlockLeftResize?: boolean;
enableBlockRightResize?: boolean; enableBlockRightResize?: boolean;
enableBlockMove?: boolean; enableBlockMove?: boolean;
@ -37,6 +38,7 @@ export const GanttChartRoot: FC<GanttChartRootProps> = (props) => {
enableAddBlock = false, enableAddBlock = false,
bottomSpacing = false, bottomSpacing = false,
showAllBlocks = false, showAllBlocks = false,
quickAdd,
} = props; } = props;
return ( return (
@ -56,6 +58,7 @@ export const GanttChartRoot: FC<GanttChartRootProps> = (props) => {
enableAddBlock={enableAddBlock} enableAddBlock={enableAddBlock}
bottomSpacing={bottomSpacing} bottomSpacing={bottomSpacing}
showAllBlocks={showAllBlocks} showAllBlocks={showAllBlocks}
quickAdd={quickAdd}
/> />
</ChartContextProvider> </ChartContextProvider>
); );

View File

@ -7,42 +7,23 @@ import { useIssueDetail } from "hooks/store";
// ui // ui
import { Loader } from "@plane/ui"; import { Loader } from "@plane/ui";
// components // components
import { GanttQuickAddIssueForm, IssueGanttSidebarBlock } from "components/issues"; import { IssueGanttSidebarBlock } from "components/issues";
// helpers // helpers
import { findTotalDaysInRange } from "helpers/date-time.helper"; import { findTotalDaysInRange } from "helpers/date-time.helper";
import { cn } from "helpers/common.helper"; import { cn } from "helpers/common.helper";
// types // types
import { IGanttBlock, IBlockUpdateData } from "components/gantt-chart/types"; import { IGanttBlock, IBlockUpdateData } from "components/gantt-chart/types";
import { TIssue } from "@plane/types";
import { BLOCK_HEIGHT } from "../constants"; import { BLOCK_HEIGHT } from "../constants";
type Props = { type Props = {
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void; blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
blocks: IGanttBlock[] | null; blocks: IGanttBlock[] | null;
enableReorder: boolean; enableReorder: boolean;
enableQuickIssueCreate?: boolean;
quickAddCallback?: (
workspaceSlug: string,
projectId: string,
data: TIssue,
viewId?: string
) => Promise<TIssue | undefined>;
viewId?: string;
disableIssueCreation?: boolean;
showAllBlocks?: boolean; showAllBlocks?: boolean;
}; };
export const IssueGanttSidebar: React.FC<Props> = observer((props) => { export const IssueGanttSidebar: React.FC<Props> = observer((props: Props) => {
const { const { blockUpdateHandler, blocks, enableReorder, showAllBlocks = false } = props;
blockUpdateHandler,
blocks,
enableReorder,
enableQuickIssueCreate,
quickAddCallback,
viewId,
disableIssueCreation,
showAllBlocks = false,
} = props;
const { activeBlock, dispatch } = useChart(); const { activeBlock, dispatch } = useChart();
const { peekIssue } = useIssueDetail(); const { peekIssue } = useIssueDetail();
@ -187,9 +168,6 @@ export const IssueGanttSidebar: React.FC<Props> = observer((props) => {
)} )}
</Droppable> </Droppable>
</DragDropContext> </DragDropContext>
{enableQuickIssueCreate && !disableIssueCreation && (
<GanttQuickAddIssueForm quickAddCallback={quickAddCallback} viewId={viewId} />
)}
</> </>
); );
}); });

View File

@ -9,16 +9,17 @@ type Props = {
enableReorder: boolean; enableReorder: boolean;
sidebarToRender: (props: any) => React.ReactNode; sidebarToRender: (props: any) => React.ReactNode;
title: string; title: string;
quickAdd?: React.JSX.Element | undefined;
}; };
export const GanttChartSidebar: React.FC<Props> = (props) => { export const GanttChartSidebar: React.FC<Props> = (props) => {
const { blocks, blockUpdateHandler, enableReorder, sidebarToRender, title } = props; const { blocks, blockUpdateHandler, enableReorder, sidebarToRender, title, quickAdd } = props;
return ( return (
<div <div
// DO NOT REMOVE THE ID // DO NOT REMOVE THE ID
id="gantt-sidebar" id="gantt-sidebar"
className="sticky top-0 left-0 z-10 min-h-full h-max flex-shrink-0 border-r-[0.5px] border-custom-border-200 bg-custom-background-100" className="sticky left-0 z-10 min-h-full h-max flex-shrink-0 border-r-[0.5px] border-custom-border-200 bg-custom-background-100"
style={{ style={{
width: `${SIDEBAR_WIDTH}px`, width: `${SIDEBAR_WIDTH}px`,
}} }}
@ -33,9 +34,10 @@ export const GanttChartSidebar: React.FC<Props> = (props) => {
<h6>Duration</h6> <h6>Duration</h6>
</div> </div>
<div className="min-h-full h-max bg-custom-background-100"> <div className="min-h-full h-max bg-custom-background-100 overflow-x-hidden overflow-y-auto">
{sidebarToRender && sidebarToRender({ title, blockUpdateHandler, blocks, enableReorder })} {sidebarToRender && sidebarToRender({ title, blockUpdateHandler, blocks, enableReorder })}
</div> </div>
{quickAdd ? quickAdd : null}
</div> </div>
); );
}; };

View File

@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite";
// hooks // hooks
import { useIssues, useUser } from "hooks/store"; import { useIssues, useUser } from "hooks/store";
// components // components
import { IssueGanttBlock } from "components/issues"; import { GanttQuickAddIssueForm, IssueGanttBlock } from "components/issues";
import { import {
GanttChartRoot, GanttChartRoot,
IBlockUpdateData, IBlockUpdateData,
@ -70,21 +70,17 @@ export const BaseGanttRoot: React.FC<IBaseGanttRoot> = observer((props: IBaseGan
blocks={issues ? renderIssueBlocksStructure(issues as TIssue[]) : null} blocks={issues ? renderIssueBlocksStructure(issues as TIssue[]) : null}
blockUpdateHandler={updateIssueBlockStructure} blockUpdateHandler={updateIssueBlockStructure}
blockToRender={(data: TIssue) => <IssueGanttBlock issueId={data.id} />} blockToRender={(data: TIssue) => <IssueGanttBlock issueId={data.id} />}
sidebarToRender={(props) => ( sidebarToRender={(props) => <IssueGanttSidebar {...props} showAllBlocks />}
<IssueGanttSidebar
{...props}
quickAddCallback={issueStore.quickAddIssue}
viewId={viewId}
enableQuickIssueCreate
disableIssueCreation={!enableIssueCreation || !isAllowed}
showAllBlocks
/>
)}
enableBlockLeftResize={isAllowed} enableBlockLeftResize={isAllowed}
enableBlockRightResize={isAllowed} enableBlockRightResize={isAllowed}
enableBlockMove={isAllowed} enableBlockMove={isAllowed}
enableReorder={appliedDisplayFilters?.order_by === "sort_order" && isAllowed} enableReorder={appliedDisplayFilters?.order_by === "sort_order" && isAllowed}
enableAddBlock={isAllowed} enableAddBlock={isAllowed}
quickAdd={
enableIssueCreation && isAllowed ? (
<GanttQuickAddIssueForm quickAddCallback={issueStore.quickAddIssue} viewId={viewId} />
) : undefined
}
showAllBlocks showAllBlocks
/> />
</div> </div>

View File

@ -159,7 +159,7 @@ export const GanttQuickAddIssueForm: React.FC<IGanttQuickAddIssueForm> = observe
) : ( ) : (
<button <button
type="button" type="button"
className="sticky bottom-0 z-[1] flex w-full cursor-pointer items-center gap-2 p-3 py-3 text-custom-primary-100 bg-custom-background-100" className="sticky bottom-0 z-[1] flex w-full cursor-pointer items-center gap-2 p-3 py-3 text-custom-primary-100 bg-custom-background-100 border-custom-border-200 border-t-[1px]"
onClick={() => setIsOpen(true)} onClick={() => setIsOpen(true)}
> >
<PlusIcon className="h-3.5 w-3.5 stroke-2" /> <PlusIcon className="h-3.5 w-3.5 stroke-2" />