From 4b28b3c23b5a06733e9118b844ed1739f26ae369 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Thu, 13 Mar 2025 14:14:17 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20add=20pinning=20on=20doc?= =?UTF-8?q?=20detail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add pinning button on doc detail page. --- CHANGELOG.md | 1 + .../__tests__/app-impress/doc-header.spec.ts | 75 ++++++++++++++----- .../docs/doc-header/components/DocToolBox.tsx | 29 ++++++- 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dacf924..9d9c5567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to ## Added +- ✨(frontend) add pinning on doc detail #711 - 🚩(frontend) feature flag analytic on copy as html #649 - ✨(frontend) Custom block divider with export #698 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts index 09b6bad0..be1bfcad 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts @@ -2,6 +2,7 @@ import { expect, test } from '@playwright/test'; import { createDoc, + getGridRow, goToGridDoc, mockedAccesses, mockedDocument, @@ -378,7 +379,12 @@ test.describe('Doc Header', () => { expect(clipboardContent.trim()).toBe(`

Hello World

`); }); - test('it checks the copy link button', async ({ page }) => { + test('it checks the copy link button', async ({ page, browserName }) => { + // eslint-disable-next-line playwright/no-skipped-test + test.skip( + browserName === 'webkit', + 'navigator.clipboard is not working with webkit and playwright', + ); await mockedDocument(page, { abilities: { destroy: false, // Means owner @@ -405,6 +411,50 @@ test.describe('Doc Header', () => { await shareButton.click(); await page.getByRole('button', { name: 'Copy link' }).click(); await expect(page.getByText('Link Copied !')).toBeVisible(); + + const handle = await page.evaluateHandle(() => + navigator.clipboard.readText(), + ); + const clipboardContent = await handle.jsonValue(); + + const origin = await page.evaluate(() => window.location.origin); + expect(clipboardContent.trim()).toMatch( + `${origin}/docs/mocked-document-id/`, + ); + }); + + test('it pins a document', async ({ page, browserName }) => { + const [docTitle] = await createDoc(page, `Favorite doc`, browserName); + + await page.getByLabel('Open the document options').click(); + + // Pin + await page.getByText('push_pin').click(); + await page.getByLabel('Open the document options').click(); + await expect(page.getByText('Unpin')).toBeVisible(); + + await page.goto('/'); + + const row = await getGridRow(page, docTitle); + + // Check is pinned + await expect(row.getByLabel('Pin document icon')).toBeVisible(); + const leftPanelFavorites = page.getByTestId('left-panel-favorites'); + await expect(leftPanelFavorites.getByText(docTitle)).toBeVisible(); + + await row.getByText(docTitle).click(); + await page.getByLabel('Open the document options').click(); + + // Unpin + await page.getByText('Unpin').click(); + await page.getByLabel('Open the document options').click(); + await expect(page.getByText('push_pin')).toBeVisible(); + + await page.goto('/'); + + // Check is unpinned + await expect(row.getByLabel('Pin document icon')).toBeHidden(); + await expect(leftPanelFavorites.getByText(docTitle)).toBeHidden(); }); }); @@ -415,12 +465,7 @@ test.describe('Documents Header mobile', () => { await page.goto('/'); }); - test('it checks the copy link button', async ({ page, browserName }) => { - // eslint-disable-next-line playwright/no-skipped-test - test.skip( - browserName === 'webkit', - 'navigator.clipboard is not working with webkit and playwright', - ); + test('it checks the copy link button is displayed', async ({ page }) => { await mockedDocument(page, { abilities: { destroy: false, @@ -440,19 +485,11 @@ test.describe('Documents Header mobile', () => { await expect(page.getByRole('button', { name: 'Copy link' })).toBeHidden(); await page.getByLabel('Open the document options').click(); + await expect( + page.getByRole('menuitem', { name: 'Copy link' }), + ).toBeVisible(); await page.getByLabel('Share').click(); - await page.getByRole('button', { name: 'Copy link' }).click(); - await expect(page.getByText('Link Copied !')).toBeVisible(); - // Test that clipboard is in HTML format - const handle = await page.evaluateHandle(() => - navigator.clipboard.readText(), - ); - const clipboardContent = await handle.jsonValue(); - - const origin = await page.evaluate(() => window.location.origin); - expect(clipboardContent.trim()).toMatch( - `${origin}/docs/mocked-document-id/`, - ); + await expect(page.getByRole('button', { name: 'Copy link' })).toBeVisible(); }); test('it checks the close button on Share modal', async ({ page }) => { diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx index 6df837e9..5f6c47e4 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx @@ -19,7 +19,15 @@ import { import { useCunninghamTheme } from '@/cunningham'; import { useEditorStore } from '@/docs/doc-editor/'; import { ModalExport } from '@/docs/doc-export/'; -import { Doc, ModalRemoveDoc, useCopyDocLink } from '@/docs/doc-management'; +import { + Doc, + KEY_DOC, + KEY_LIST_DOC, + ModalRemoveDoc, + useCopyDocLink, + useCreateFavoriteDoc, + useDeleteFavoriteDoc, +} from '@/docs/doc-management'; import { DocShareModal } from '@/docs/doc-share'; import { KEY_LIST_DOC_VERSIONS, @@ -52,6 +60,12 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => { const { toast } = useToastProvider(); const copyDocLink = useCopyDocLink(doc.id); const { isFeatureFlagActivated } = useAnalytics(); + const removeFavoriteDoc = useDeleteFavoriteDoc({ + listInvalideQueries: [KEY_LIST_DOC, KEY_DOC], + }); + const makeFavoriteDoc = useCreateFavoriteDoc({ + listInvalideQueries: [KEY_LIST_DOC, KEY_DOC], + }); const options: DropdownMenuOption[] = [ ...(isSmallMobile @@ -75,7 +89,18 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => { }, ] : []), - + { + label: doc.is_favorite ? t('Unpin') : t('Pin'), + icon: 'push_pin', + callback: () => { + if (doc.is_favorite) { + removeFavoriteDoc.mutate({ id: doc.id }); + } else { + makeFavoriteDoc.mutate({ id: doc.id }); + } + }, + testId: `docs-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`, + }, { label: t('Version history'), icon: 'history',