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',