mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
[WEB-823] fix: quick add flicker and dropdown placement in calendar layout (#4054)
* chore: placement prop added in quick action menu * fix: calenar layout quick action menu placement * fix: calendar quick add flicker
This commit is contained in:
parent
9f9e508bb7
commit
7e0037b06b
@ -89,7 +89,7 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
|||||||
groupedIssueIds={groupedIssueIds}
|
groupedIssueIds={groupedIssueIds}
|
||||||
layout={displayFilters?.calendar?.layout}
|
layout={displayFilters?.calendar?.layout}
|
||||||
showWeekends={displayFilters?.calendar?.show_weekends ?? false}
|
showWeekends={displayFilters?.calendar?.show_weekends ?? false}
|
||||||
quickActions={(issue, customActionButton) => (
|
quickActions={(issue, customActionButton, placement) => (
|
||||||
<QuickActions
|
<QuickActions
|
||||||
customActionButton={customActionButton}
|
customActionButton={customActionButton}
|
||||||
issue={issue}
|
issue={issue}
|
||||||
@ -101,6 +101,7 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
|||||||
handleArchive={async () => archiveIssue && archiveIssue(issue.project_id, issue.id)}
|
handleArchive={async () => archiveIssue && archiveIssue(issue.project_id, issue.id)}
|
||||||
handleRestore={async () => restoreIssue && restoreIssue(issue.project_id, issue.id)}
|
handleRestore={async () => restoreIssue && restoreIssue(issue.project_id, issue.id)}
|
||||||
readOnly={!isEditingAllowed || isCompletedCycle}
|
readOnly={!isEditingAllowed || isCompletedCycle}
|
||||||
|
placements={placement}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
addIssuesToView={addIssuesToView}
|
addIssuesToView={addIssuesToView}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Placement } from "@popperjs/core";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import type {
|
import type {
|
||||||
IIssueDisplayFilterOptions,
|
IIssueDisplayFilterOptions,
|
||||||
@ -37,7 +38,7 @@ type Props = {
|
|||||||
groupedIssueIds: TGroupedIssues;
|
groupedIssueIds: TGroupedIssues;
|
||||||
layout: "month" | "week" | undefined;
|
layout: "month" | "week" | undefined;
|
||||||
showWeekends: boolean;
|
showWeekends: boolean;
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
quickAddCallback?: (
|
quickAddCallback?: (
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Droppable } from "@hello-pangea/dnd";
|
import { Droppable } from "@hello-pangea/dnd";
|
||||||
|
import { Placement } from "@popperjs/core";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types";
|
import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
@ -19,7 +20,7 @@ type Props = {
|
|||||||
date: ICalendarDate;
|
date: ICalendarDate;
|
||||||
issues: TIssueMap | undefined;
|
issues: TIssueMap | undefined;
|
||||||
groupedIssueIds: TGroupedIssues;
|
groupedIssueIds: TGroupedIssues;
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
disableIssueCreation?: boolean;
|
disableIssueCreation?: boolean;
|
||||||
quickAddCallback?: (
|
quickAddCallback?: (
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { Placement } from "@popperjs/core";
|
||||||
// components
|
// components
|
||||||
import { TIssue, TIssueMap } from "@plane/types";
|
import { TIssue, TIssueMap } from "@plane/types";
|
||||||
import { CalendarIssueBlock } from "@/components/issues";
|
import { CalendarIssueBlock } from "@/components/issues";
|
||||||
@ -7,7 +8,7 @@ import { CalendarIssueBlock } from "@/components/issues";
|
|||||||
type Props = {
|
type Props = {
|
||||||
issues: TIssueMap | undefined;
|
issues: TIssueMap | undefined;
|
||||||
issueId: string;
|
issueId: string;
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
isDragging?: boolean;
|
isDragging?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useState, useRef } from "react";
|
import { useState, useRef } from "react";
|
||||||
|
import { Placement } from "@popperjs/core";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { MoreHorizontal } from "lucide-react";
|
import { MoreHorizontal } from "lucide-react";
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
@ -14,7 +15,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
issue: TIssue;
|
issue: TIssue;
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
isDragging?: boolean;
|
isDragging?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,6 +57,11 @@ export const CalendarIssueBlock: React.FC<Props> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isMenuActionRefAboveScreenBottom =
|
||||||
|
menuActionRef?.current && menuActionRef?.current?.getBoundingClientRect().bottom < window.innerHeight - 220;
|
||||||
|
|
||||||
|
const placement = isMenuActionRefAboveScreenBottom ? "bottom-end" : "top-end";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ControlLink
|
<ControlLink
|
||||||
href={`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`}
|
href={`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`}
|
||||||
@ -104,7 +110,7 @@ export const CalendarIssueBlock: React.FC<Props> = observer((props) => {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{quickActions(issue, customActionButton)}
|
{quickActions(issue, customActionButton, placement)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Draggable } from "@hello-pangea/dnd";
|
import { Draggable } from "@hello-pangea/dnd";
|
||||||
|
import { Placement } from "@popperjs/core";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { TIssue, TIssueMap } from "@plane/types";
|
import { TIssue, TIssueMap } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
@ -12,7 +13,7 @@ type Props = {
|
|||||||
date: Date;
|
date: Date;
|
||||||
issues: TIssueMap | undefined;
|
issues: TIssueMap | undefined;
|
||||||
issueIdList: string[] | null;
|
issueIdList: string[] | null;
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
isDragDisabled?: boolean;
|
isDragDisabled?: boolean;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
disableIssueCreation?: boolean;
|
disableIssueCreation?: boolean;
|
||||||
|
@ -230,7 +230,7 @@ export const CalendarQuickAddIssueForm: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
{!isOpen && (
|
{!isOpen && (
|
||||||
<div
|
<div
|
||||||
className={cn("md:hidden rounded md:border-[0.5px] border-custom-border-200 md:group-hover:block", {
|
className={cn("md:opacity-0 rounded md:border-[0.5px] border-custom-border-200 md:group-hover:opacity-100", {
|
||||||
block: isMenuOpen,
|
block: isMenuOpen,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Placement } from "@popperjs/core";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types";
|
import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
@ -16,7 +17,7 @@ type Props = {
|
|||||||
issues: TIssueMap | undefined;
|
issues: TIssueMap | undefined;
|
||||||
groupedIssueIds: TGroupedIssues;
|
groupedIssueIds: TGroupedIssues;
|
||||||
week: ICalendarWeek | undefined;
|
week: ICalendarWeek | undefined;
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
disableIssueCreation?: boolean;
|
disableIssueCreation?: boolean;
|
||||||
quickAddCallback?: (
|
quickAddCallback?: (
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Placement } from "@popperjs/core";
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
|
|
||||||
export interface IQuickActionProps {
|
export interface IQuickActionProps {
|
||||||
@ -10,4 +11,5 @@ export interface IQuickActionProps {
|
|||||||
customActionButton?: React.ReactElement;
|
customActionButton?: React.ReactElement;
|
||||||
portalElement?: HTMLDivElement | null;
|
portalElement?: HTMLDivElement | null;
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
|
placements?: Placement;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ export const CycleIssueQuickActions: React.FC<IQuickActionProps> = observer((pro
|
|||||||
customActionButton,
|
customActionButton,
|
||||||
portalElement,
|
portalElement,
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
|
placements = "bottom-start",
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false);
|
const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false);
|
||||||
@ -107,7 +108,7 @@ export const CycleIssueQuickActions: React.FC<IQuickActionProps> = observer((pro
|
|||||||
/>
|
/>
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
menuItemsClassName="z-[14]"
|
menuItemsClassName="z-[14]"
|
||||||
placement="bottom-start"
|
placement={placements}
|
||||||
customButton={customActionButton}
|
customButton={customActionButton}
|
||||||
portalElement={portalElement}
|
portalElement={portalElement}
|
||||||
maxHeight="lg"
|
maxHeight="lg"
|
||||||
|
@ -30,6 +30,7 @@ export const ModuleIssueQuickActions: React.FC<IQuickActionProps> = observer((pr
|
|||||||
customActionButton,
|
customActionButton,
|
||||||
portalElement,
|
portalElement,
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
|
placements = "bottom-start",
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false);
|
const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false);
|
||||||
@ -106,7 +107,7 @@ export const ModuleIssueQuickActions: React.FC<IQuickActionProps> = observer((pr
|
|||||||
/>
|
/>
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
menuItemsClassName="z-[14]"
|
menuItemsClassName="z-[14]"
|
||||||
placement="bottom-start"
|
placement={placements}
|
||||||
customButton={customActionButton}
|
customButton={customActionButton}
|
||||||
portalElement={portalElement}
|
portalElement={portalElement}
|
||||||
maxHeight="lg"
|
maxHeight="lg"
|
||||||
|
@ -28,6 +28,7 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = observer((p
|
|||||||
customActionButton,
|
customActionButton,
|
||||||
portalElement,
|
portalElement,
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
|
placements = "bottom-start",
|
||||||
} = props;
|
} = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -107,7 +108,7 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = observer((p
|
|||||||
/>
|
/>
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
menuItemsClassName="z-[14]"
|
menuItemsClassName="z-[14]"
|
||||||
placement="bottom-start"
|
placement={placements}
|
||||||
customButton={customActionButton}
|
customButton={customActionButton}
|
||||||
portalElement={portalElement}
|
portalElement={portalElement}
|
||||||
maxHeight="lg"
|
maxHeight="lg"
|
||||||
|
Loading…
Reference in New Issue
Block a user