diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts index 7a66acdb..8b9ce931 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts @@ -321,8 +321,20 @@ test.describe('Doc Tree', () => { 'doc-child-emoji-child', ); - // Update the emoji from the tree const row = await getTreeRow(page, docChild); + + // Check Remove emoji is not present initially + await row.hover(); + const menu = row.getByText(`more_horiz`); + await menu.click(); + await expect( + page.getByRole('menuitem', { name: 'Remove emoji' }), + ).toBeHidden(); + + // Close the menu + await page.keyboard.press('Escape'); + + // Update the emoji from the tree await row.locator('.--docs--doc-icon').click(); await page.getByRole('button', { name: '😀' }).first().click(); @@ -331,6 +343,16 @@ test.describe('Doc Tree', () => { await expect( page.getByRole('textbox', { name: 'Document title' }), ).toContainText('😀'); + + // Now remove the emoji using the new action + await row.hover(); + await menu.click(); + await page.getByRole('menuitem', { name: 'Remove emoji' }).click(); + + await expect(row.getByText('😀')).toBeHidden(); + await expect( + page.getByRole('textbox', { name: 'Document title' }), + ).not.toContainText('😀'); }); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx index 0ed7b8b7..da056301 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx @@ -13,8 +13,10 @@ import { Doc, ModalRemoveDoc, Role, + getEmojiAndTitle, useCopyDocLink, useCreateChildDoc, + useDocTitleUpdate, useDuplicateDoc, } from '@/docs/doc-management'; @@ -44,6 +46,7 @@ export const DocTreeItemActions = ({ const copyLink = useCopyDocLink(doc.id); const { mutate: detachDoc } = useDetachDoc(); const treeContext = useTreeContext(); + const { mutate: duplicateDoc } = useDuplicateDoc({ onSuccess: (duplicatedDoc) => { // Reset the tree context root will reset the full tree view. @@ -52,6 +55,13 @@ export const DocTreeItemActions = ({ }, }); + // Emoji Management + const { emoji } = getEmojiAndTitle(doc.title ?? ''); + const { updateDocEmoji } = useDocTitleUpdate(); + const removeEmoji = () => { + updateDocEmoji(doc.id, doc.title ?? '', ''); + }; + const handleDetachDoc = () => { if (!treeContext?.root) { return; @@ -82,6 +92,15 @@ export const DocTreeItemActions = ({ }, ...(!isRoot ? [ + ...(emoji && doc.abilities.partial_update + ? [ + { + label: t('Remove emoji'), + icon: , + callback: removeEmoji, + }, + ] + : []), { label: t('Move to my docs'), isDisabled: doc.user_role !== Role.OWNER,