From 530dd5ff7f7d25bf011e8af8224e994df2796aa6 Mon Sep 17 00:00:00 2001 From: Whitewater Date: Thu, 18 May 2023 13:07:05 -0700 Subject: [PATCH] feat: add new page button (#2417) --- apps/web/src/atoms/index.ts | 11 +- .../block-suite-page-list/index.tsx | 29 ++-- .../block-suite-page-list/utils.tsx | 40 +++++ .../src/components/root-app-sidebar/index.tsx | 2 +- apps/web/src/hooks/use-recent-views.ts | 29 +++- .../components/card/block-card/styles.css.ts | 1 + .../src/components/page-list/all-page.tsx | 158 ++++++++++-------- .../components/page-list/new-page-buttton.tsx | 85 ++++++++++ .../src/components/page-list/use-sorter.ts | 8 +- .../src/stories/page-list.stories.tsx | 58 +++++-- packages/component/src/ui/menu/menu.tsx | 15 +- packages/component/src/ui/menu/styles.ts | 5 +- packages/component/src/ui/table/styles.ts | 1 - .../src/use-block-suite-workspace-helper.ts | 2 +- packages/i18n/src/resources/en.json | 3 + tests/parallels/all-page.spec.ts | 47 +++++- 16 files changed, 378 insertions(+), 116 deletions(-) create mode 100644 apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx create mode 100644 packages/component/src/components/page-list/new-page-buttton.tsx diff --git a/apps/web/src/atoms/index.ts b/apps/web/src/atoms/index.ts index 6574d91046..209bd0cf49 100644 --- a/apps/web/src/atoms/index.ts +++ b/apps/web/src/atoms/index.ts @@ -96,7 +96,13 @@ export const openDisableCloudAlertModalAtom = atom(false); export { workspacesAtom } from './root'; -type View = { id: string; mode: 'page' | 'edgeless' }; +type View = { + id: string; + /** + * @deprecated Use `mode` from `useWorkspacePreferredMode` instead. + */ + mode: 'page' | 'edgeless'; +}; export type WorkspaceRecentViews = Record; @@ -106,6 +112,9 @@ export const workspaceRecentViewsAtom = atomWithStorage( ); export type PreferredModeRecord = Record; +/** + * @deprecated Use `useWorkspacePreferredMode` instead. + */ export const workspacePreferredModeAtom = atomWithStorage( 'preferredMode', {} diff --git a/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx b/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx index 5360933bd8..34cd2cff07 100644 --- a/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx +++ b/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx @@ -5,17 +5,14 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { EdgelessIcon, PageIcon } from '@blocksuite/icons'; import type { PageMeta } from '@blocksuite/store'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; -import dayjs from 'dayjs'; -import localizedFormat from 'dayjs/plugin/localizedFormat'; -import { useAtomValue } from 'jotai'; import type React from 'react'; import { useMemo } from 'react'; -import { workspacePreferredModeAtom } from '../../../atoms'; import { useBlockSuiteMetaHelper } from '../../../hooks/affine/use-block-suite-meta-helper'; import type { BlockSuiteWorkspace } from '../../../shared'; import { toast } from '../../../utils'; import { pageListEmptyStyle } from './index.css'; +import { formatDate, usePageHelper } from './utils'; export type BlockSuitePageListProps = { blockSuiteWorkspace: BlockSuiteWorkspace; @@ -34,13 +31,6 @@ const filter = { shared: (pageMeta: PageMeta) => pageMeta.isPublic && !pageMeta.trash, }; -dayjs.extend(localizedFormat); -const formatDate = (date?: number | unknown) => { - const dateStr = - typeof date === 'number' ? dayjs(date).format('YYYY-MM-DD HH:mm') : '--'; - return dateStr; -}; - const PageListEmpty = (props: { listType: BlockSuitePageListProps['listType']; }) => { @@ -80,12 +70,13 @@ export const BlockSuitePageList: React.FC = ({ permanentlyDeletePage, cancelPublicPage, } = useBlockSuiteMetaHelper(blockSuiteWorkspace); + const { createPage, createEdgeless, isPreferredEdgeless } = + usePageHelper(blockSuiteWorkspace); const t = useAFFiNEI18N(); const list = useMemo( () => pageMetas.filter(pageMeta => filter[listType](pageMeta, pageMetas)), [pageMetas, listType] ); - const record = useAtomValue(workspacePreferredModeAtom); if (list.length === 0) { return ; } @@ -93,8 +84,11 @@ export const BlockSuitePageList: React.FC = ({ if (listType === 'trash') { const pageList: TrashListData[] = list.map(pageMeta => { return { - icon: - record[pageMeta.id] === 'edgeless' ? : , + icon: isPreferredEdgeless(pageMeta.id) ? ( + + ) : ( + + ), pageId: pageMeta.id, title: pageMeta.title, createDate: formatDate(pageMeta.createDate), @@ -118,8 +112,7 @@ export const BlockSuitePageList: React.FC = ({ const pageList: ListData[] = list.map(pageMeta => { return { - icon: - record[pageMeta.id] === 'edgeless' ? : , + icon: isPreferredEdgeless(pageMeta.id) ? : , pageId: pageMeta.id, title: pageMeta.title, favorite: !!pageMeta.favorite, @@ -158,10 +151,10 @@ export const BlockSuitePageList: React.FC = ({ return ( ); }; diff --git a/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx b/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx new file mode 100644 index 0000000000..93b90da4ee --- /dev/null +++ b/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx @@ -0,0 +1,40 @@ +import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper'; +import dayjs from 'dayjs'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; +import { useRouter } from 'next/router'; + +import { useWorkspacePreferredMode } from '../../../hooks/use-recent-views'; +import { useRouterHelper } from '../../../hooks/use-router-helper'; +import type { BlockSuiteWorkspace } from '../../../shared'; + +dayjs.extend(localizedFormat); +export const formatDate = (date?: number | unknown) => { + const dateStr = + typeof date === 'number' ? dayjs(date).format('YYYY-MM-DD HH:mm') : '--'; + return dateStr; +}; + +export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => { + const router = useRouter(); + const { openPage } = useRouterHelper(router); + const { createPage } = useBlockSuiteWorkspaceHelper(blockSuiteWorkspace); + const { getPreferredMode, setPreferredMode } = useWorkspacePreferredMode(); + const isPreferredEdgeless = (pageId: string) => { + return getPreferredMode(pageId) === 'edgeless'; + }; + + const createPageAndOpen = () => { + const page = createPage(); + openPage(blockSuiteWorkspace.id, page.id); + }; + const createEdgelessAndOpen = () => { + const page = createPage(); + setPreferredMode(page.id, 'edgeless'); + openPage(blockSuiteWorkspace.id, page.id); + }; + return { + createPage: createPageAndOpen, + createEdgeless: createEdgelessAndOpen, + isPreferredEdgeless: isPreferredEdgeless, + }; +}; diff --git a/apps/web/src/components/root-app-sidebar/index.tsx b/apps/web/src/components/root-app-sidebar/index.tsx index 28dea48176..2efc375cc7 100644 --- a/apps/web/src/components/root-app-sidebar/index.tsx +++ b/apps/web/src/components/root-app-sidebar/index.tsx @@ -84,7 +84,7 @@ export const RootAppSidebar = ({ const blockSuiteWorkspace = currentWorkspace?.blockSuiteWorkspace; const t = useAFFiNEI18N(); const onClickNewPage = useCallback(async () => { - const page = await createPage(); + const page = createPage(); openPage(page.id); }, [createPage, openPage]); diff --git a/apps/web/src/hooks/use-recent-views.ts b/apps/web/src/hooks/use-recent-views.ts index 5a9d1c312a..7b6845581a 100644 --- a/apps/web/src/hooks/use-recent-views.ts +++ b/apps/web/src/hooks/use-recent-views.ts @@ -1,6 +1,6 @@ -import type { Workspace } from '@blocksuite/store'; +import type { Page, Workspace } from '@blocksuite/store'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; -import { useAtomValue, useSetAtom } from 'jotai'; +import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import type { NextRouter } from 'next/router'; import { useEffect } from 'react'; @@ -11,6 +11,19 @@ import { } from '../atoms'; import { useCurrentWorkspace } from './current/use-current-workspace'; +export const useWorkspacePreferredMode = () => { + const [record, setPreferred] = useAtom(workspacePreferredModeAtom); + return { + getPreferredMode: (pageId: Page['id']) => record[pageId] ?? 'page', + setPreferredMode: (pageId: Page['id'], mode: 'page' | 'edgeless') => { + setPreferred(record => ({ + ...record, + [pageId]: mode, + })); + }, + }; +}; + export function useRecentlyViewed() { const [workspace] = useCurrentWorkspace(); const workspaceId = workspace?.id || null; @@ -30,15 +43,19 @@ export function useSyncRecentViewsWithRouter( const meta = useBlockSuitePageMeta(blockSuiteWorkspace).find( meta => meta.id === pageId ); - const currentMode = useAtomValue(workspacePreferredModeAtom)[ - pageId as string - ]; + const { getPreferredMode } = useWorkspacePreferredMode(); + + const currentMode = + typeof pageId === 'string' ? getPreferredMode(pageId) : 'page'; useEffect(() => { if (!workspaceId) return; if (pageId && meta) { set(workspaceId, { id: pageId as string, - mode: currentMode ?? 'page', + /** + * @deprecated No necessary update `mode` at here, use `mode` from {@link useWorkspacePreferredMode} directly. + */ + mode: currentMode, }); } }, [pageId, meta, workspaceId, set, currentMode]); diff --git a/packages/component/src/components/card/block-card/styles.css.ts b/packages/component/src/components/card/block-card/styles.css.ts index 04e238d4f8..710ae3c8e7 100644 --- a/packages/component/src/components/card/block-card/styles.css.ts +++ b/packages/component/src/components/card/block-card/styles.css.ts @@ -9,6 +9,7 @@ export const blockCard = style({ borderRadius: '4px', userSelect: 'none', cursor: 'pointer', + textAlign: 'start', selectors: { '&:hover': { boxShadow: 'var(--affine-shadow-1)', diff --git a/packages/component/src/components/page-list/all-page.tsx b/packages/component/src/components/page-list/all-page.tsx index de10a620b7..945acadd7f 100644 --- a/packages/component/src/components/page-list/all-page.tsx +++ b/packages/component/src/components/page-list/all-page.tsx @@ -18,8 +18,10 @@ import { FavoriteIcon, } from '@blocksuite/icons'; import { useMediaQuery, useTheme } from '@mui/material'; +import type { CSSProperties } from 'react'; import { forwardRef } from 'react'; +import { NewPageButton } from './new-page-buttton'; import { StyledTableContainer, StyledTableRow, @@ -68,11 +70,8 @@ const FavoriteTag = forwardRef< export type PageListProps = { isPublicWorkspace?: boolean; list: ListData[]; - /** - * @deprecated - */ - listType: 'all' | 'favorite' | 'shared' | 'public'; - onClickPage: (pageId: string, newTab?: boolean) => void; + onCreateNewPage: () => void; + onCreateNewEdgeless: () => void; }; const TitleCell = ({ @@ -100,6 +99,80 @@ const TitleCell = ({ ); }; +const AllPagesHead = ({ + sorter, + createNewPage, + createNewEdgeless, +}: { + sorter: ReturnType>; + createNewPage: () => void; + createNewEdgeless: () => void; +}) => { + const t = useAFFiNEI18N(); + const titleList = [ + { + key: 'title', + content: t['Title'](), + proportion: 0.5, + }, + { + key: 'createDate', + content: t['Created'](), + proportion: 0.2, + }, + { + key: 'updatedDate', + content: t['Updated'](), + proportion: 0.2, + }, + { + key: 'unsortable_action', + content: ( + + ), + sortable: false, + styles: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + } satisfies CSSProperties, + }, + ]; + + return ( + + + {titleList.map( + ({ key, content, proportion, sortable = true, styles }) => ( + sorter.shiftOrder(key as keyof ListData) + : undefined + } + style={styles} + > + {content} + {sorter.key === key && + (sorter.order === 'asc' ? ( + + ) : ( + + ))} + + ) + )} + + + ); +}; + export type ListData = { pageId: string; icon: JSX.Element; @@ -119,7 +192,8 @@ export type ListData = { export const PageList: React.FC = ({ isPublicWorkspace = false, list, - listType, + onCreateNewPage, + onCreateNewEdgeless, }) => { const t = useAFFiNEI18N(); const sorter = useSorter({ @@ -128,70 +202,12 @@ export const PageList: React.FC = ({ order: 'desc', }); - const isShared = listType === 'shared'; - const theme = useTheme(); const isSmallDevices = useMediaQuery(theme.breakpoints.down('sm')); if (isSmallDevices) { return ; } - const ListHead = () => { - const t = useAFFiNEI18N(); - const titleList = [ - { - key: 'title', - text: t['Title'](), - proportion: 0.5, - }, - { - key: 'createDate', - text: t['Created'](), - proportion: 0.2, - }, - { - key: 'updatedDate', - text: isShared - ? // TODO deprecated - 'Shared' - : t['Updated'](), - proportion: 0.2, - }, - { key: 'unsortable_action', sortable: false }, - ]; - - return ( - - - {titleList.map(({ key, text, proportion, sortable = true }) => ( - sorter.shiftOrder(key as keyof ListData) - : undefined - } - > -
- {text} - {sorter.key === key && - (sorter.order === 'asc' ? ( - - ) : ( - - ))} -
-
- ))} -
-
- ); - }; - const ListItems = sorter.data.map( ( { @@ -237,7 +253,13 @@ export const PageList: React.FC = ({ {!isPublicWorkspace && ( = ({ return ( - + {ListItems}
diff --git a/packages/component/src/components/page-list/new-page-buttton.tsx b/packages/component/src/components/page-list/new-page-buttton.tsx new file mode 100644 index 0000000000..424a7ef377 --- /dev/null +++ b/packages/component/src/components/page-list/new-page-buttton.tsx @@ -0,0 +1,85 @@ +import { useAFFiNEI18N } from '@affine/i18n/hooks'; +import { EdgelessIcon, PageIcon } from '@blocksuite/icons'; +import { useState } from 'react'; + +import { DropdownButton } from '../../ui/button/dropdown'; +import { Menu } from '../../ui/menu/menu'; +import { BlockCard } from '../card/block-card'; + +type NewPageButtonProps = { + createNewPage: () => void; + createNewEdgeless: () => void; +}; + +export const CreateNewPagePopup = ({ + createNewPage, + createNewEdgeless, +}: NewPageButtonProps) => { + const t = useAFFiNEI18N(); + return ( +
+ } + onClick={createNewPage} + /> + } + onClick={createNewEdgeless} + /> + {/* TODO Import */} +
+ ); +}; + +export const NewPageButton = ({ + createNewPage, + createNewEdgeless, +}: NewPageButtonProps) => { + const t = useAFFiNEI18N(); + const [open, setOpen] = useState(false); + return ( + { + setOpen(false); + }} + menuStyles={{ padding: '0px' }} + content={ + { + createNewPage(); + setOpen(false); + }} + createNewEdgeless={() => { + createNewEdgeless(); + setOpen(false); + }} + /> + } + > + { + createNewPage(); + setOpen(false); + }} + onClickDropDown={() => setOpen(!open)} + > + {t['New Page']()} + + + ); +}; diff --git a/packages/component/src/components/page-list/use-sorter.ts b/packages/component/src/components/page-list/use-sorter.ts index 3613fcc704..77b18f3c89 100644 --- a/packages/component/src/components/page-list/use-sorter.ts +++ b/packages/component/src/components/page-list/use-sorter.ts @@ -1,6 +1,6 @@ import { useState } from 'react'; -type Sorter = { +type SorterConfig = { data: T[]; key: keyof T; order: 'asc' | 'desc' | 'none'; @@ -32,8 +32,8 @@ const defaultSortingFn = >( export const useSorter = >({ data, ...defaultSorter -}: Sorter & { order: 'asc' | 'desc' }) => { - const [sorter, setSorter] = useState, 'data'>>({ +}: SorterConfig & { order: 'asc' | 'desc' }) => { + const [sorter, setSorter] = useState, 'data'>>({ ...defaultSorter, // We should not show sorting icon at first time order: 'none', @@ -74,7 +74,7 @@ export const useSorter = >({ /** * @deprecated In most cases, we no necessary use `setSorter` directly. */ - updateSorter: (newVal: Partial>) => + updateSorter: (newVal: Partial>) => setSorter({ ...sorter, ...newVal }), shiftOrder, resetSorter: () => setSorter(defaultSorter), diff --git a/packages/component/src/stories/page-list.stories.tsx b/packages/component/src/stories/page-list.stories.tsx index 02cdda6313..129db8a061 100644 --- a/packages/component/src/stories/page-list.stories.tsx +++ b/packages/component/src/stories/page-list.stories.tsx @@ -1,5 +1,7 @@ import { PageIcon } from '@blocksuite/icons'; +import { expect } from '@storybook/jest'; import type { StoryFn } from '@storybook/react'; +import { userEvent } from '@storybook/testing-library'; import { AffineLoading } from '../components/affine-loading'; import type { @@ -8,6 +10,7 @@ import type { } from '../components/page-list/all-page'; import { PageListTrashView } from '../components/page-list/all-page'; import PageList from '../components/page-list/all-page'; +import { NewPageButton } from '../components/page-list/new-page-buttton'; import type { OperationCellProps } from '../components/page-list/operation-cell'; import { OperationCell } from '../components/page-list/operation-cell'; import { toast } from '../ui/toast'; @@ -19,11 +22,7 @@ export default { export const AffineOperationCell: StoryFn = ({ ...props -}) => ( -
- -
-); +}) => ; AffineOperationCell.args = { title: 'Example Page', @@ -34,16 +33,40 @@ AffineOperationCell.args = { onOpenPageInNewTab: () => toast('Open page in new tab'), onRemoveToTrash: () => toast('Remove to trash'), }; +AffineOperationCell.play = async ({ canvasElement }) => { + { + const button = canvasElement.querySelector( + '[data-testid="page-list-operation-button"]' + ) as HTMLButtonElement; + expect(button).not.toBeNull(); + userEvent.click(button); + } +}; + +export const AffineNewPageButton: StoryFn = ({ + ...props +}) => ; +AffineNewPageButton.args = { + createNewPage: () => toast('Create new page'), + createNewEdgeless: () => toast('Create new edgeless'), +}; + +AffineNewPageButton.play = async ({ canvasElement }) => { + const button = canvasElement.querySelector('button') as HTMLButtonElement; + expect(button).not.toBeNull(); + const dropdown = button.querySelector('svg') as SVGSVGElement; + expect(dropdown).not.toBeNull(); + userEvent.click(dropdown); +}; export const AffineAllPageList: StoryFn = ({ ...props }) => ( -
- -
+ ); AffineAllPageList.args = { isPublicWorkspace: false, - listType: 'all', + onCreateNewPage: () => toast('Create new page'), + onCreateNewEdgeless: () => toast('Create new edgeless'), list: [ { pageId: '1', @@ -76,13 +99,20 @@ AffineAllPageList.args = { ], }; +export const AffineAllPageMobileList: StoryFn = ({ + ...props +}) => ; + +AffineAllPageMobileList.args = AffineAllPageList.args; +AffineAllPageMobileList.parameters = { + viewport: { + defaultViewport: 'mobile2', + }, +}; + export const AffineTrashPageList: StoryFn<{ list: TrashListData[]; -}> = ({ ...props }) => ( -
- -
-); +}> = ({ ...props }) => ; AffineTrashPageList.args = { list: [ diff --git a/packages/component/src/ui/menu/menu.tsx b/packages/component/src/ui/menu/menu.tsx index 48ffabaf42..ca84b82eff 100644 --- a/packages/component/src/ui/menu/menu.tsx +++ b/packages/component/src/ui/menu/menu.tsx @@ -6,16 +6,27 @@ import { StyledMenuWrapper } from './styles'; export type MenuProps = { width?: CSSProperties['width']; + menuStyles?: CSSProperties; } & PopperProps & Omit; export const Menu = (props: MenuProps) => { - const { width, content, placement = 'bottom-start', children } = props; + const { + width, + menuStyles, + content, + placement = 'bottom-start', + children, + } = props; return content ? ( + {content} } diff --git a/packages/component/src/ui/menu/styles.ts b/packages/component/src/ui/menu/styles.ts index 8e18b66a2a..a06c96ca83 100644 --- a/packages/component/src/ui/menu/styles.ts +++ b/packages/component/src/ui/menu/styles.ts @@ -3,7 +3,10 @@ import type { CSSProperties } from 'react'; import { displayFlex, styled, textEllipsis } from '../../styles'; import StyledPopperContainer from '../shared/container'; -export const StyledMenuWrapper = styled(StyledPopperContainer)<{ +export const StyledMenuWrapper = styled(StyledPopperContainer, { + shouldForwardProp: propName => + !['width', 'height'].includes(propName as string), +})<{ width?: CSSProperties['width']; height?: CSSProperties['height']; }>(({ width, height }) => { diff --git a/packages/component/src/ui/table/styles.ts b/packages/component/src/ui/table/styles.ts index b4882e4831..6e0c7e26c2 100644 --- a/packages/component/src/ui/table/styles.ts +++ b/packages/component/src/ui/table/styles.ts @@ -37,7 +37,6 @@ export const StyledTableCell = styled('td')< return { width, height: '52px', - lineHeight: '52px', padding: '0 30px', boxSizing: 'border-box', textAlign: align, diff --git a/packages/hooks/src/use-block-suite-workspace-helper.ts b/packages/hooks/src/use-block-suite-workspace-helper.ts index 8866df05e2..47d4c714f9 100644 --- a/packages/hooks/src/use-block-suite-workspace-helper.ts +++ b/packages/hooks/src/use-block-suite-workspace-helper.ts @@ -10,7 +10,7 @@ import { useMemo } from 'react'; export function useBlockSuiteWorkspaceHelper(blockSuiteWorkspace: Workspace) { return useMemo( () => ({ - createPage: (pageId: string): Page => { + createPage: (pageId?: string): Page => { assertExists(blockSuiteWorkspace); return blockSuiteWorkspace.createPage({ id: pageId }); }, diff --git a/packages/i18n/src/resources/en.json b/packages/i18n/src/resources/en.json index 72d7848a52..f2d95d171d 100644 --- a/packages/i18n/src/resources/en.json +++ b/packages/i18n/src/resources/en.json @@ -19,6 +19,9 @@ "Import": "Import", "Trash": "Trash", "New Page": "New Page", + "com.affine.write_with_a_blank_page": "Write with a blank page", + "com.affine.new_edgeless": "New Edgeless", + "com.affine.draw_with_a_blank_whiteboard": "Draw with a blank whiteboard", "New Keyword Page": "New '{{query}}' page", "Find 0 result": "Find 0 result", "Find results": "Find {{number}} results", diff --git a/tests/parallels/all-page.spec.ts b/tests/parallels/all-page.spec.ts index 42ad63af51..4df7633a24 100644 --- a/tests/parallels/all-page.spec.ts +++ b/tests/parallels/all-page.spec.ts @@ -1,11 +1,56 @@ import { test } from '@affine-test/kit/playwright'; +import type { Page } from '@playwright/test'; +import { expect } from '@playwright/test'; import { openHomePage } from '../libs/load-page'; -import { waitMarkdownImported } from '../libs/page-logic'; +import { + getBlockSuiteEditorTitle, + waitMarkdownImported, +} from '../libs/page-logic'; import { clickSideBarAllPageButton } from '../libs/sidebar'; +function getAllPage(page: Page) { + const newPageButton = page + .locator('table') + .getByRole('button', { name: 'New Page' }); + const newPageDropdown = newPageButton.locator('svg'); + const edgelessBlockCard = page.locator('table').getByText('New Edgeless'); + + async function clickNewPageButton() { + return newPageButton.click(); + } + + async function clickNewEdgelessDropdown() { + await newPageDropdown.click(); + await edgelessBlockCard.click(); + } + return { clickNewPageButton, clickNewEdgelessDropdown }; +} + test('all page', async ({ page }) => { await openHomePage(page); await waitMarkdownImported(page); await clickSideBarAllPageButton(page); }); + +test('all page can create new page', async ({ page }) => { + const { clickNewPageButton } = getAllPage(page); + await openHomePage(page); + await waitMarkdownImported(page); + await clickSideBarAllPageButton(page); + await clickNewPageButton(); + const title = getBlockSuiteEditorTitle(page); + await title.fill('this is a new page'); + await clickSideBarAllPageButton(page); + const cell = page.getByRole('cell', { name: 'this is a new page' }); + expect(cell).not.toBeUndefined(); +}); + +test('all page can create new edgeless page', async ({ page }) => { + const { clickNewEdgelessDropdown } = getAllPage(page); + await openHomePage(page); + await waitMarkdownImported(page); + await clickSideBarAllPageButton(page); + await clickNewEdgelessDropdown(); + await expect(page.locator('affine-edgeless-page')).toBeVisible(); +});