[WEB-1204] fix: Kanban and calendar drag and drop in mobile (#4408)

* chore: don't show context menu on mobile devices

* fix: drag and drop in mobile

* chore: default show more options in mobile

* fix: dnd in calendar layout
This commit is contained in:
Aaryan Khandelwal 2024-05-16 23:42:54 +05:30 committed by GitHub
parent 33079c826d
commit 26188f208b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 34 additions and 25 deletions

View File

@ -38,3 +38,5 @@ export const ControlLink = React.forwardRef<HTMLAnchorElement, TControlLink>((pr
</a>
);
});
ControlLink.displayName = "ControlLink";

View File

@ -6,6 +6,7 @@ import { ContextMenuItem } from "./item";
import { cn } from "../../../helpers";
// hooks
import useOutsideClickDetector from "../../hooks/use-outside-click-detector";
import { usePlatformOS } from "../../hooks/use-platform-os";
export type TContextMenuItem = {
key: string;
@ -38,6 +39,7 @@ const ContextMenuWithoutPortal: React.FC<ContextMenuProps> = (props) => {
const contextMenuRef = useRef<HTMLDivElement>(null);
// derived values
const renderedItems = items.filter((item) => item.shouldRender !== false);
const { isMobile } = usePlatformOS();
const handleClose = () => {
setIsOpen(false);
@ -51,6 +53,8 @@ const ContextMenuWithoutPortal: React.FC<ContextMenuProps> = (props) => {
if (!parentElement || !contextMenu) return;
const handleContextMenu = (e: MouseEvent) => {
if (isMobile) return;
e.preventDefault();
e.stopPropagation();
@ -83,7 +87,7 @@ const ContextMenuWithoutPortal: React.FC<ContextMenuProps> = (props) => {
parentElement.removeEventListener("contextmenu", handleContextMenu);
window.removeEventListener("keydown", hideContextMenu);
};
}, [contextMenuRef, isOpen, parentRef, setIsOpen, setPosition]);
}, [contextMenuRef, isMobile, isOpen, parentRef, setIsOpen, setPosition]);
// handle keyboard navigation
useEffect(() => {

View File

@ -0,0 +1,15 @@
import { useEffect, useState } from "react";
export const usePlatformOS = () => {
// states
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const userAgent = window.navigator.userAgent;
const isMobile = /iPhone|iPad|iPod|Android/i.test(userAgent);
if (isMobile) setIsMobile(isMobile);
}, []);
return { isMobile };
};

View File

@ -71,7 +71,7 @@ export const CalendarIssueBlock = observer(
target="_blank"
onClick={() => handleIssuePeekOverview(issue)}
className="block w-full text-sm text-custom-text-100 rounded border-b md:border-[1px] border-custom-border-200 hover:border-custom-border-400"
disabled={!!issue?.tempId}
disabled={!!issue?.tempId || isMobile}
ref={ref}
>
<>
@ -105,9 +105,10 @@ export const CalendarIssueBlock = observer(
</Tooltip>
</div>
<div
className={`flex-shrink-0 md:hidden h-5 w-5 group-hover/calendar-block:block ${
isMenuActive ? "!block" : ""
}`}
className={cn("flex-shrink-0 size-5", {
"hidden group-hover/calendar-block:block": !isMobile,
block: isMenuActive,
})}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();

View File

@ -63,7 +63,9 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((prop
{getProjectIdentifierById(issue.project_id)}-{issue.sequence_id}
</div>
<div
className="absolute -top-1 right-0 hidden group-hover/kanban-block:block"
className={cn("absolute -top-1 right-0", {
"hidden group-hover/kanban-block:block": !isMobile,
})}
onClick={handleEventPropagation}
>
{quickActions({
@ -116,6 +118,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = observer((props) => {
// hooks
const { workspaceSlug } = useAppRouter();
const { getIsIssuePeeked, setPeekIssue } = useIssueDetail();
const { isMobile } = usePlatformOS();
const handleIssuePeekOverview = (issue: TIssue) =>
workspaceSlug &&
@ -210,7 +213,7 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = observer((props) => {
)}
target="_blank"
onClick={() => handleIssuePeekOverview(issue)}
disabled={!!issue?.tempId}
disabled={!!issue?.tempId || isMobile}
>
<RenderIfVisible
classNames="space-y-2 px-3 py-2"

View File

@ -7945,16 +7945,7 @@ streamx@^2.15.0, streamx@^2.16.1:
optionalDependencies:
bare-events "^2.2.0"
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0:
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -8034,14 +8025,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==