From 2da4ae2298c82e46a2555a04ae401c1dba404029 Mon Sep 17 00:00:00 2001 From: fch-aa <21101725+fch-aa@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:04:27 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20refresh=20pins=20after?= =?UTF-8?q?=20document=20deletion=20and=20restoration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Favorite relationships persist across soft deletion, while the sidebar keeps a stale cached list until reload. Invalidate the favorites query after deletion and restoration so deleted documents disappear immediately and their pins return when restored. Signed-off-by: fch-aa <21101725+fch-aa@users.noreply.github.com> --- CHANGELOG.md | 1 + .../e2e/__tests__/app-impress/doc-grid.spec.ts | 12 +++++++++++- .../__tests__/app-impress/doc-trashbin.spec.ts | 16 ++++++++++++++++ .../docs/doc-header/components/AlertRestore.tsx | 8 +++++++- .../doc-management/components/ModalRemoveDoc.tsx | 9 +++++++-- .../components/DocsGridTrashbinActions.tsx | 7 ++++++- 6 files changed, 48 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83b3ea289..defbd42f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to ### Fixed +- 🐛(frontend) refresh pins after document deletion and restoration - 🐛(frontend) redirect homepage to login when homepage feat is disabled #2521 - 🐛(backend) ignore CSPs for API docs in development - 🐛(frontend) export images embedded with a relative url #2573 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts index 3cef7cd75..f4cb20c90 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts @@ -146,6 +146,13 @@ test.describe('Document grid item options', () => { await expect(page.getByText(docTitle)).toBeVisible(); const row = await getGridRow(page, docTitle); + + await row.getByRole('button', { name: /Open the menu of actions/ }).click(); + await page.getByRole('menuitem', { name: 'Pin' }).click(); + + const leftPanelFavorites = page.getByTestId('left-panel-favorites'); + await expect(leftPanelFavorites.getByText(docTitle)).toBeVisible(); + await row.getByRole('button', { name: /Open the menu of actions/ }).click(); await page.getByRole('menuitem', { name: 'Delete' }).click(); @@ -164,7 +171,10 @@ test.describe('Document grid item options', () => { page.getByText('The document has been deleted.'), ).toBeVisible(); - await expect(page.getByText(docTitle)).toBeHidden(); + await expect( + page.getByLabel('Documents grid').getByText(docTitle), + ).toBeHidden(); + await expect(leftPanelFavorites.getByText(docTitle)).toBeHidden(); }); test('it checks the leave feature', async ({ page, browserName }) => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts index 456df240c..9a3d2ae9e 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts @@ -38,9 +38,14 @@ test.describe('Doc Trashbin', () => { await expect(row1.getByText(title1)).toBeHidden(); const row2 = await getGridRow(page, title2); + await clickInGridMenu(page, row2, 'Pin'); + const leftPanelFavorites = page.getByTestId('left-panel-favorites'); + await expect(leftPanelFavorites.getByText(title2)).toBeVisible(); + await clickInGridMenu(page, row2, 'Delete'); await page.getByRole('button', { name: 'Delete document' }).click(); await expect(row2.getByText(title2)).toBeHidden(); + await expect(leftPanelFavorites.getByText(title2)).toBeHidden(); await page.getByRole('link', { name: 'Trashbin' }).click(); @@ -81,6 +86,7 @@ test.describe('Doc Trashbin', () => { await clickInGridMenu(page, row2, 'Restore'); await expect(row2.getByText(title2)).toBeHidden(); + await expect(leftPanelFavorites.getByText(title2)).toBeVisible(); await page.getByRole('link', { name: 'All docs' }).click(); const row2Restored = await getGridRow(page, title2); await expect(row2Restored.getByText(title2)).toBeVisible(); @@ -127,11 +133,19 @@ test.describe('Doc Trashbin', () => { await navigateToPageFromTree({ page, title: subDocName }); await verifyDocName(page, subDocName); + await clickInEditorMenu(page, 'Pin'); + await page.getByRole('button', { name: 'Back to homepage' }).click(); + const leftPanelFavorites = page.getByTestId('left-panel-favorites'); + await expect(leftPanelFavorites.getByText(subDocName)).toBeVisible(); + await leftPanelFavorites.getByText(subDocName).click(); + await verifyDocName(page, subDocName); + await clickInEditorMenu(page, 'Delete'); await page.getByRole('button', { name: 'Delete document' }).click(); await verifyDocName(page, topParent); await page.getByRole('button', { name: 'Back to homepage' }).click(); + await expect(leftPanelFavorites.getByText(subDocName)).toBeHidden(); await page.getByRole('link', { name: 'Trashbin' }).click(); let row; @@ -179,5 +193,7 @@ test.describe('Doc Trashbin', () => { ); await expect(page.getByRole('button', { name: 'Share' })).toBeEnabled(); await expect(docTree.getByText(topParent)).toBeVisible(); + await page.getByRole('button', { name: 'Back to homepage' }).click(); + await expect(leftPanelFavorites.getByText(subDocName)).toBeVisible(); }); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/AlertRestore.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/AlertRestore.tsx index 22c6d61de..667b01c0c 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/AlertRestore.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/AlertRestore.tsx @@ -12,6 +12,7 @@ import { Doc, KEY_DOC, KEY_LIST_DOC, + KEY_LIST_FAVORITE_DOC, useRestoreDoc, } from '@/docs/doc-management'; import { KEY_LIST_DOC_TRASHBIN } from '@/docs/docs-grid'; @@ -22,7 +23,12 @@ export const AlertRestore = ({ doc }: { doc: Doc }) => { const treeContext = useTreeContext(); const { spacingsTokens } = useCunninghamTheme(); const { mutate: restoreDoc, error } = useRestoreDoc({ - listInvalidQueries: [KEY_LIST_DOC, KEY_LIST_DOC_TRASHBIN, KEY_DOC], + listInvalidQueries: [ + KEY_LIST_DOC, + KEY_LIST_DOC_TRASHBIN, + KEY_DOC, + KEY_LIST_FAVORITE_DOC, + ], options: { onSuccess: (_data) => { // It will force the tree to be reloaded diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalRemoveDoc.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalRemoveDoc.tsx index cc9c5e4af..7cf9f1ba8 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalRemoveDoc.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalRemoveDoc.tsx @@ -14,7 +14,7 @@ import { useConfig } from '@/core'; import { KEY_LIST_DOC_TRASHBIN } from '@/docs/docs-grid'; import { useKeyboardAction } from '@/hooks'; -import { KEY_DOC } from '../api'; +import { KEY_DOC, KEY_LIST_FAVORITE_DOC } from '../api'; import { KEY_LIST_DOC } from '../api/useDocs'; import { useRemoveDoc } from '../api/useRemoveDoc'; import { useDocUtils } from '../hooks'; @@ -43,7 +43,12 @@ export const ModalRemoveDoc = ({ isError, error, } = useRemoveDoc({ - listInvalidQueries: [KEY_LIST_DOC, KEY_LIST_DOC_TRASHBIN, KEY_DOC], + listInvalidQueries: [ + KEY_LIST_DOC, + KEY_LIST_DOC_TRASHBIN, + KEY_DOC, + KEY_LIST_FAVORITE_DOC, + ], options: { onSuccess: () => { if (onSuccess) { diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridTrashbinActions.tsx b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridTrashbinActions.tsx index 14f68e357..ebfa592e9 100644 --- a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridTrashbinActions.tsx +++ b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridTrashbinActions.tsx @@ -9,6 +9,7 @@ import { DropdownMenu, DropdownMenuOption, Icon } from '@/components'; import { Doc, KEY_LIST_DOC, + KEY_LIST_FAVORITE_DOC, useRestoreDoc, useTrans, } from '@/docs/doc-management'; @@ -26,7 +27,11 @@ export const DocsGridTrashbinActions = ({ const { untitledDocument } = useTrans(); const { toast } = useToastProvider(); const { mutate: restoreDoc, error } = useRestoreDoc({ - listInvalidQueries: [KEY_LIST_DOC, KEY_LIST_DOC_TRASHBIN], + listInvalidQueries: [ + KEY_LIST_DOC, + KEY_LIST_DOC_TRASHBIN, + KEY_LIST_FAVORITE_DOC, + ], options: { onSuccess: (_data) => { toast(t('The document has been restored.'), VariantType.SUCCESS, {