mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +00:00
feat(core): support sidebar page item dnd (#5132)
Added the ability to drag page items from the `all pages` view to the sidebar, including `favourites,` `collection` and `trash`. Page items in `favourites` and `collection` can also be dragged between each other. However, linked subpages cannot be dragged. Additionally, an operation menu and ‘add’ button have been provided for the sidebar’s page items, enabling the addition of a subpage, renaming, deletion or removal from the sidebar. On the code front, the `useSidebarDrag` hooks have been implemented for consolidating drag events. The functions `getDragItemId` and `getDropItemId` have been created, and they accept type and ID to obtain itemId. https://github.com/toeverything/AFFiNE/assets/102217452/d06bac18-3c28-41c9-a7d4-72de955d7b11
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import { dragTo, waitForEditorLoad } from '@affine-test/kit/utils/page-logic';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('drag a page from "All pages" list onto the "Trash" folder in the sidebar to move it to trash list', async ({
|
||||
page,
|
||||
}) => {
|
||||
// TODO-Doma
|
||||
// Init test db with known workspaces and open "All Pages" page via url directly
|
||||
{
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await page.getByTestId('app-sidebar').getByText('All Pages').click();
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
const title = 'AFFiNE - not just a note-taking app';
|
||||
|
||||
await dragTo(
|
||||
page,
|
||||
page.locator(`[role="button"]:has-text("${title}")`),
|
||||
page.getByTestId('app-sidebar').getByText('Trash')
|
||||
);
|
||||
|
||||
await expect(
|
||||
page.getByText('Successfully deleted'),
|
||||
'A toast containing success message is shown'
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByText(title),
|
||||
'The deleted post is no longer on the All Page list'
|
||||
).toHaveCount(0);
|
||||
|
||||
// TODO-Doma
|
||||
// Visit trash page via url
|
||||
await page.getByText('Trash', { exact: true }).click();
|
||||
await expect(
|
||||
page.getByText(title),
|
||||
'The deleted post exists in the Trash list'
|
||||
).toHaveCount(1);
|
||||
});
|
||||
145
tests/affine-local/e2e/drag-page.spec.ts
Normal file
145
tests/affine-local/e2e/drag-page.spec.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
dragTo,
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
import { expect, type Locator, type Page } from '@playwright/test';
|
||||
|
||||
const dragToFavourites = async (
|
||||
page: Page,
|
||||
dragItem: Locator,
|
||||
pageId: string
|
||||
) => {
|
||||
const favourites = page.getByTestId('favourites');
|
||||
await dragTo(page, dragItem, favourites);
|
||||
const favouritePage = page.getByTestId(`favourite-page-${pageId}`);
|
||||
expect(favouritePage).not.toBeUndefined();
|
||||
return favouritePage;
|
||||
};
|
||||
|
||||
const dragToCollection = async (page: Page, dragItem: Locator) => {
|
||||
await page.getByTestId('slider-bar-add-collection-button').click();
|
||||
const input = page.getByTestId('input-collection-title');
|
||||
await input.isVisible();
|
||||
await input.fill('test collection');
|
||||
await page.getByTestId('save-collection').click();
|
||||
const collection = page.getByTestId('collection-item');
|
||||
expect(collection).not.toBeUndefined();
|
||||
await clickSideBarAllPageButton(page);
|
||||
await dragTo(page, dragItem, collection);
|
||||
await page.waitForTimeout(500);
|
||||
await collection.getByTestId('fav-collapsed-button').click();
|
||||
const collectionPage = page.getByTestId('collection-page');
|
||||
expect(collectionPage).not.toBeUndefined();
|
||||
return collectionPage;
|
||||
};
|
||||
|
||||
const dragToTrash = async (page: Page, title: string, dragItem: Locator) => {
|
||||
// drag to trash
|
||||
await dragTo(page, dragItem, page.getByTestId('trash-page'));
|
||||
const confirmTip = page.getByText('Delete page?');
|
||||
expect(confirmTip).not.toBeUndefined();
|
||||
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
||||
await expect(
|
||||
page.getByText(title),
|
||||
'The deleted post is no longer on the All Page list'
|
||||
).toHaveCount(0);
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId('trash-page').click();
|
||||
|
||||
await expect(
|
||||
page.getByText(title),
|
||||
'The deleted post exists in the Trash list'
|
||||
).toHaveCount(1);
|
||||
};
|
||||
|
||||
test('drag a page from "All pages" list to favourites, then drag to trash', async ({
|
||||
page,
|
||||
}) => {
|
||||
const title = 'this is a new page to drag';
|
||||
{
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).fill(title);
|
||||
}
|
||||
const pageId = page.url().split('/').reverse()[0];
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const favouritePage = await dragToFavourites(
|
||||
page,
|
||||
page.locator(`[role="button"]:has-text("${title}")`),
|
||||
pageId
|
||||
);
|
||||
|
||||
await dragToTrash(page, title, favouritePage);
|
||||
});
|
||||
|
||||
test('drag a page from "All pages" list to collections, then drag to trash', async ({
|
||||
page,
|
||||
}) => {
|
||||
const title = 'this is a new page to drag';
|
||||
{
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).fill(title);
|
||||
}
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const collectionPage = await dragToCollection(
|
||||
page,
|
||||
page.locator(`[role="button"]:has-text("${title}")`)
|
||||
);
|
||||
|
||||
await dragToTrash(page, title, collectionPage);
|
||||
});
|
||||
|
||||
test('drag a page from "All pages" list to trash', async ({ page }) => {
|
||||
const title = 'this is a new page to drag';
|
||||
{
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).fill(title);
|
||||
}
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await dragToTrash(
|
||||
page,
|
||||
title,
|
||||
page.locator(`[role="button"]:has-text("${title}")`)
|
||||
);
|
||||
});
|
||||
|
||||
test('drag a page from favourites to collection', async ({ page }) => {
|
||||
const title = 'this is a new page to drag';
|
||||
{
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).fill(title);
|
||||
}
|
||||
const pageId = page.url().split('/').reverse()[0];
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// drag to favourites
|
||||
const favouritePage = await dragToFavourites(
|
||||
page,
|
||||
page.locator(`[role="button"]:has-text("${title}")`),
|
||||
pageId
|
||||
);
|
||||
|
||||
// drag to collections
|
||||
await dragToCollection(page, favouritePage);
|
||||
});
|
||||
@@ -60,18 +60,16 @@ test('Show collections items in sidebar', async ({ page }) => {
|
||||
const collectionPage = collections.getByTestId('collection-page').nth(0);
|
||||
expect(await collectionPage.textContent()).toBe('test page');
|
||||
await collectionPage.hover();
|
||||
await collectionPage.getByTestId('collection-page-options').click();
|
||||
const deletePage = page
|
||||
.getByTestId('collection-page-option')
|
||||
.getByText('Delete');
|
||||
await collectionPage
|
||||
.getByTestId('left-sidebar-page-operation-button')
|
||||
.click();
|
||||
const deletePage = page.getByText('Delete');
|
||||
await deletePage.click();
|
||||
await page.getByTestId('confirm-delete-page').click();
|
||||
expect(await collections.getByTestId('collection-page').count()).toBe(0);
|
||||
await first.hover();
|
||||
await first.getByTestId('collection-options').click();
|
||||
const deleteCollection = page
|
||||
.getByTestId('collection-option')
|
||||
.getByText('Delete');
|
||||
const deleteCollection = page.getByText('Delete');
|
||||
await deleteCollection.click();
|
||||
await page.waitForTimeout(50);
|
||||
expect(await items.count()).toBe(0);
|
||||
@@ -100,13 +98,10 @@ test('edit collection', async ({ page }) => {
|
||||
const first = items.first();
|
||||
await first.hover();
|
||||
await first.getByTestId('collection-options').click();
|
||||
const editCollection = page
|
||||
.getByTestId('collection-option')
|
||||
.getByText('Rename');
|
||||
const editCollection = page.getByText('Rename');
|
||||
await editCollection.click();
|
||||
const title = page.getByTestId('input-collection-title');
|
||||
await title.fill('123');
|
||||
await page.getByTestId('save-collection').click();
|
||||
await page.getByTestId('rename-modal-input').fill('123');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForTimeout(100);
|
||||
expect(await first.textContent()).toBe('123');
|
||||
});
|
||||
@@ -123,9 +118,8 @@ test('edit collection and change filter date', async ({ page }) => {
|
||||
.getByTestId('collection-option')
|
||||
.getByText('Rename');
|
||||
await editCollection.click();
|
||||
const title = page.getByTestId('input-collection-title');
|
||||
await title.fill('123');
|
||||
await page.getByTestId('save-collection').click();
|
||||
await page.getByTestId('rename-modal-input').fill('123');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForTimeout(100);
|
||||
expect(await first.textContent()).toBe('123');
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ test('Show favorite items in sidebar', async ({ page, workspace }) => {
|
||||
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
|
||||
await favoriteBtn.click();
|
||||
const favoriteListItemInSidebar = page.getByTestId(
|
||||
'favorite-list-item-' + newPageId
|
||||
'favourite-page-' + newPageId
|
||||
);
|
||||
expect(await favoriteListItemInSidebar.textContent()).toBe(
|
||||
'this is a new page to favorite'
|
||||
@@ -55,7 +55,7 @@ test('Show favorite reference in sidebar', async ({ page, workspace }) => {
|
||||
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
|
||||
await favoriteBtn.click();
|
||||
|
||||
const favItemTestId = 'favorite-list-item-' + newPageId;
|
||||
const favItemTestId = 'favourite-page-' + newPageId;
|
||||
|
||||
const favoriteListItemInSidebar = page.getByTestId(favItemTestId);
|
||||
expect(await favoriteListItemInSidebar.textContent()).toBe(
|
||||
@@ -69,7 +69,7 @@ test('Show favorite reference in sidebar', async ({ page, workspace }) => {
|
||||
await expect(collapseButton).toBeVisible();
|
||||
await collapseButton.click();
|
||||
await expect(
|
||||
page.locator('[data-type="favorite-list-item"] >> text=Another page')
|
||||
page.locator('[data-type="reference-page"] >> text=Another page')
|
||||
).toBeVisible();
|
||||
const currentWorkspace = await workspace.current();
|
||||
|
||||
@@ -110,7 +110,7 @@ test("Deleted page's reference will not be shown in sidebar", async ({
|
||||
// confirm delete
|
||||
await page.locator('button >> text=Delete').click();
|
||||
|
||||
const favItemTestId = 'favorite-list-item-' + newPageId;
|
||||
const favItemTestId = 'favourite-page-' + newPageId;
|
||||
|
||||
const favoriteListItemInSidebar = page.getByTestId(favItemTestId);
|
||||
expect(await favoriteListItemInSidebar.textContent()).toBe(
|
||||
@@ -137,7 +137,7 @@ test('Add new favorite page via sidebar', async ({ page }) => {
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new fav page');
|
||||
// check if the page title is shown in the favorite list
|
||||
const favItem = page.locator(
|
||||
'[data-type=favorite-list-item] >> text=this is a new fav page'
|
||||
'[data-type=favourite-list-item] >> text=this is a new fav page'
|
||||
);
|
||||
await expect(favItem).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -64,6 +64,7 @@ function useRegisterCommands() {
|
||||
createPage: createMockedPage,
|
||||
importFile: () => Promise.resolve(),
|
||||
isPreferredEdgeless: () => false,
|
||||
createLinkedPage: createMockedPage,
|
||||
},
|
||||
}),
|
||||
registerAffineLayoutCommands({
|
||||
|
||||
Reference in New Issue
Block a user