🛂(frontend) block drag n drop when not desktop
Scrolling on mobile devices was causing issues with drag and drop functionality, documents were being moved unintentionally. This commit disables drag and drop on mobile devices to prevent this issue.
This commit is contained in:
@@ -23,6 +23,7 @@ and this project adheres to
|
||||
- 🔧(project) change env.d system by using local files #1200
|
||||
- ⚡️(frontend) improve tree stability #1207
|
||||
- ⚡️(frontend) improve accessibility #1232
|
||||
- 🛂(frontend) block drag n drop when not desktop #1239
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc, mockedListDocs } from './utils-common';
|
||||
import { createRootSubPage } from './utils-sub-pages';
|
||||
|
||||
test.describe('Doc grid dnd', () => {
|
||||
test('it creates a doc', async ({ page, browserName }) => {
|
||||
@@ -165,6 +166,40 @@ test.describe('Doc grid dnd', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc grid dnd mobile', () => {
|
||||
test.use({ viewport: { width: 500, height: 1200 } });
|
||||
|
||||
test('DND is deactivated on mobile', async ({ page, browserName }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const docsGrid = page.getByTestId('docs-grid');
|
||||
await expect(page.getByTestId('docs-grid')).toBeVisible();
|
||||
await expect(page.getByTestId('grid-loader')).toBeHidden();
|
||||
|
||||
await expect(docsGrid.getByRole('row').first()).toBeVisible();
|
||||
await expect(docsGrid.locator('.--docs--grid-droppable')).toHaveCount(0);
|
||||
|
||||
await createDoc(page, 'Draggable doc mobile', browserName, 1, false, true);
|
||||
|
||||
await createRootSubPage(
|
||||
page,
|
||||
browserName,
|
||||
'Draggable doc mobile child',
|
||||
true,
|
||||
);
|
||||
|
||||
await page
|
||||
.getByRole('button', { name: 'Open the header menu' })
|
||||
.getByText('menu')
|
||||
.click();
|
||||
|
||||
await expect(page.locator('.--docs-sub-page-item').first()).toHaveAttribute(
|
||||
'draggable',
|
||||
'false',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const data = [
|
||||
{
|
||||
id: 'can-drop-and-drag',
|
||||
|
||||
@@ -79,15 +79,23 @@ export const createDoc = async (
|
||||
browserName: string,
|
||||
length: number = 1,
|
||||
isChild: boolean = false,
|
||||
isMobile: boolean = false,
|
||||
) => {
|
||||
const randomDocs = randomName(docName, browserName, length);
|
||||
|
||||
for (let i = 0; i < randomDocs.length; i++) {
|
||||
if (!isChild) {
|
||||
if (!isChild && !isMobile) {
|
||||
const header = page.locator('header').first();
|
||||
await header.locator('h2').getByText('Docs').click();
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
await page
|
||||
.getByRole('button', { name: 'Open the header menu' })
|
||||
.getByText('menu')
|
||||
.click();
|
||||
}
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'New doc',
|
||||
|
||||
@@ -10,7 +10,15 @@ export const createRootSubPage = async (
|
||||
page: Page,
|
||||
browserName: string,
|
||||
docName: string,
|
||||
isMobile: boolean = false,
|
||||
) => {
|
||||
if (isMobile) {
|
||||
await page
|
||||
.getByRole('button', { name: 'Open the header menu' })
|
||||
.getByText('menu')
|
||||
.click();
|
||||
}
|
||||
|
||||
// Get response
|
||||
const responsePromise = waitForResponseCreateDoc(page);
|
||||
await clickOnAddRootSubPage(page);
|
||||
@@ -18,6 +26,13 @@ export const createRootSubPage = async (
|
||||
expect(response.ok()).toBeTruthy();
|
||||
const subPageJson = (await response.json()) as { id: string };
|
||||
|
||||
if (isMobile) {
|
||||
await page
|
||||
.getByRole('button', { name: 'Open the header menu' })
|
||||
.getByText('menu')
|
||||
.click();
|
||||
}
|
||||
|
||||
// Get doc tree
|
||||
const docTree = page.getByTestId('doc-tree');
|
||||
await expect(docTree).toBeVisible();
|
||||
@@ -29,6 +44,13 @@ export const createRootSubPage = async (
|
||||
await expect(subPageItem).toBeVisible();
|
||||
await subPageItem.click();
|
||||
|
||||
if (isMobile) {
|
||||
await page
|
||||
.getByRole('button', { name: 'Open the header menu' })
|
||||
.getByText('close')
|
||||
.click();
|
||||
}
|
||||
|
||||
// Update sub page name
|
||||
const randomDocs = randomName(docName, browserName, 1);
|
||||
await updateDocTitle(page, randomDocs[0]);
|
||||
|
||||
@@ -71,6 +71,7 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
|
||||
return (
|
||||
<Box
|
||||
className="--docs-sub-page-item"
|
||||
draggable={doc.abilities.move && isDesktop}
|
||||
$position="relative"
|
||||
$css={css`
|
||||
background-color: ${actionsOpen
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
OpenMap,
|
||||
TreeView,
|
||||
TreeViewMoveResult,
|
||||
useResponsive,
|
||||
useTreeContext,
|
||||
} from '@gouvfr-lasuite/ui-kit';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -29,6 +30,7 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
|
||||
const [rootActionsOpen, setRootActionsOpen] = useState(false);
|
||||
const treeContext = useTreeContext<Doc | null>();
|
||||
const router = useRouter();
|
||||
const { isDesktop } = useResponsive();
|
||||
|
||||
const [initialOpenState, setInitialOpenState] = useState<OpenMap | undefined>(
|
||||
undefined,
|
||||
@@ -243,13 +245,13 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
|
||||
canDrop={({ parentNode }) => {
|
||||
const parentDoc = parentNode?.data.value as Doc;
|
||||
if (!parentDoc) {
|
||||
return currentDoc.abilities.move;
|
||||
return currentDoc.abilities.move && isDesktop;
|
||||
}
|
||||
return parentDoc.abilities.move;
|
||||
return parentDoc.abilities.move && isDesktop;
|
||||
}}
|
||||
canDrag={(node) => {
|
||||
const doc = node.value as Doc;
|
||||
return doc.abilities.move;
|
||||
return doc.abilities.move && isDesktop;
|
||||
}}
|
||||
rootNodeId={treeContext.root.id}
|
||||
renderNode={DocSubPageItem}
|
||||
|
||||
@@ -51,7 +51,9 @@ type DocGridContentListProps = {
|
||||
docs: Doc[];
|
||||
};
|
||||
|
||||
export const DocGridContentList = ({ docs }: DocGridContentListProps) => {
|
||||
export const DraggableDocGridContentList = ({
|
||||
docs,
|
||||
}: DocGridContentListProps) => {
|
||||
const { mutateAsync: handleMove, isError } = useMoveDoc();
|
||||
const queryClient = useQueryClient();
|
||||
const modalConfirmation = useModal();
|
||||
@@ -223,7 +225,7 @@ export const DocGridContentList = ({ docs }: DocGridContentListProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
interface DocGridItemProps {
|
||||
interface DraggableDocGridItemProps {
|
||||
doc: Doc;
|
||||
dragMode: boolean;
|
||||
canDrag: boolean;
|
||||
@@ -235,7 +237,7 @@ export const DraggableDocGridItem = ({
|
||||
dragMode,
|
||||
canDrag,
|
||||
updateCanDrop,
|
||||
}: DocGridItemProps) => {
|
||||
}: DraggableDocGridItemProps) => {
|
||||
const canDrop = doc.abilities.move;
|
||||
|
||||
return (
|
||||
@@ -252,3 +254,13 @@ export const DraggableDocGridItem = ({
|
||||
</Droppable>
|
||||
);
|
||||
};
|
||||
|
||||
export const DocGridContentList = ({ docs }: DocGridContentListProps) => {
|
||||
if (docs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return docs.map((doc) => (
|
||||
<DocsGridItem dragMode={false} doc={doc} key={doc.id} />
|
||||
));
|
||||
};
|
||||
|
||||
@@ -9,7 +9,10 @@ import { useResponsiveStore } from '@/stores';
|
||||
|
||||
import { useResponsiveDocGrid } from '../hooks/useResponsiveDocGrid';
|
||||
|
||||
import { DocGridContentList } from './DocGridContentList';
|
||||
import {
|
||||
DocGridContentList,
|
||||
DraggableDocGridContentList,
|
||||
} from './DocGridContentList';
|
||||
import { DocsGridLoader } from './DocsGridLoader';
|
||||
|
||||
type DocsGridProps = {
|
||||
@@ -118,7 +121,11 @@ export const DocsGrid = ({
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<DocGridContentList docs={docs} />
|
||||
{isDesktop ? (
|
||||
<DraggableDocGridContentList docs={docs} />
|
||||
) : (
|
||||
<DocGridContentList docs={docs} />
|
||||
)}
|
||||
|
||||
{hasNextPage && !loading && (
|
||||
<InView
|
||||
|
||||
Reference in New Issue
Block a user