Skip to content

Commit 4e34135

Browse files
committed
✨(frontend) create page from slash menu
We are now able to create a new page from the slash menu.
1 parent c689da6 commit 4e34135

File tree

6 files changed

+130
-4
lines changed

6 files changed

+130
-4
lines changed

src/frontend/apps/e2e/__tests__/app-impress/doc-create.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@ test.describe('Doc Create', () => {
2929
await expect(page.getByTestId('grid-loader')).toBeHidden();
3030
await expect(docsGrid.getByText(docTitle)).toBeVisible();
3131
});
32+
33+
test('it creates a sub doc from slash menu editor', async ({
34+
page,
35+
browserName,
36+
}) => {
37+
const [title] = await createDoc(page, 'my-new-slash-doc', browserName, 1);
38+
39+
await verifyDocName(page, title);
40+
41+
await page.locator('.bn-block-outer').last().fill('/');
42+
await page.getByText('Add a new page').click();
43+
44+
const input = page.getByRole('textbox', { name: 'doc title input' });
45+
await expect(input).toHaveText('');
46+
await expect(
47+
page.locator('.c__tree-view--row-content').getByText('Untitled page'),
48+
).toBeVisible();
49+
});
3250
});
3351

3452
test.describe('Doc Create: Not logged', () => {
Lines changed: 30 additions & 0 deletions
Loading

src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,51 @@ import {
99
import React, { useMemo } from 'react';
1010
import { useTranslation } from 'react-i18next';
1111

12-
import { DocsBlockSchema } from '../types';
12+
import {
13+
DocsBlockSchema,
14+
DocsInlineContentSchema,
15+
DocsStyleSchema,
16+
} from '../types';
1317

1418
import {
1519
getCalloutReactSlashMenuItems,
1620
getDividerReactSlashMenuItems,
1721
} from './custom-blocks';
22+
import { useGetInterlinkingMenuItems } from './custom-inline-content';
1823

1924
export const BlockNoteSuggestionMenu = () => {
20-
const editor = useBlockNoteEditor<DocsBlockSchema>();
25+
const editor = useBlockNoteEditor<
26+
DocsBlockSchema,
27+
DocsInlineContentSchema,
28+
DocsStyleSchema
29+
>();
2130
const { t } = useTranslation();
2231
const basicBlocksName = useDictionary().slash_menu.page_break.group;
32+
const getInterlinkingMenuItems = useGetInterlinkingMenuItems();
2333

2434
const getSlashMenuItems = useMemo(() => {
35+
// We insert it after the "Code Block" item to have the interlinking block displayed after the basic blocks
36+
const defaultMenu = getDefaultReactSlashMenuItems(editor);
37+
const index = defaultMenu.findIndex((item) => item.title === 'Code Block');
38+
const newSlashMenuItems = [
39+
...defaultMenu.slice(0, index + 1),
40+
...getInterlinkingMenuItems(t),
41+
...defaultMenu.slice(index + 1),
42+
];
43+
2544
return async (query: string) =>
2645
Promise.resolve(
2746
filterSuggestionItems(
2847
combineByGroup(
29-
getDefaultReactSlashMenuItems(editor),
48+
newSlashMenuItems,
3049
getPageBreakReactSlashMenuItems(editor),
3150
getCalloutReactSlashMenuItems(editor, t, basicBlocksName),
3251
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
3352
),
3453
query,
3554
),
3655
);
37-
}, [basicBlocksName, editor, t]);
56+
}, [basicBlocksName, editor, getInterlinkingMenuItems, t]);
3857

3958
return (
4059
<SuggestionMenuController
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { useTreeContext } from '@gouvfr-lasuite/ui-kit';
2+
import { TFunction } from 'i18next';
3+
import { useRouter } from 'next/navigation';
4+
import { useCallback } from 'react';
5+
6+
import AddPageIcon from '@/docs/doc-editor/assets/doc-plus.svg';
7+
import { Doc, useCreateChildDoc, useDocStore } from '@/docs/doc-management';
8+
9+
export const getInterlinkingMenuItems = (
10+
t: TFunction<'translation', undefined>,
11+
group: string,
12+
createPage: () => void,
13+
) => [
14+
{
15+
title: t('New page'),
16+
onItemClick: createPage,
17+
aliases: ['new page'],
18+
group,
19+
icon: <AddPageIcon />,
20+
subtext: t('Add a new page'),
21+
},
22+
];
23+
24+
export const useGetInterlinkingMenuItems = () => {
25+
const treeContext = useTreeContext<Doc>();
26+
const router = useRouter();
27+
const { currentDoc } = useDocStore();
28+
29+
const { mutate: createChildDoc } = useCreateChildDoc({
30+
onSuccess: (createdDoc) => {
31+
const newDoc = {
32+
...createdDoc,
33+
children: [],
34+
childrenCount: 0,
35+
parentId: currentDoc?.id ?? undefined,
36+
};
37+
treeContext?.treeData.addChild(currentDoc?.id || null, newDoc);
38+
39+
router.push(`/docs/${newDoc.id}`);
40+
treeContext?.treeData.setSelectedNode(createdDoc);
41+
},
42+
});
43+
44+
return useCallback(
45+
(t: TFunction<'translation', undefined>) =>
46+
getInterlinkingMenuItems(
47+
t,
48+
t('Links'),
49+
() =>
50+
currentDoc?.id &&
51+
createChildDoc({
52+
parentId: currentDoc.id,
53+
}),
54+
),
55+
[createChildDoc, currentDoc?.id],
56+
);
57+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './InterlinkingSearchInlineContent';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Interlinking';

0 commit comments

Comments
 (0)