From 8a3dfe02525e4d269ff905eb889ae3eddc01bfa8 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Wed, 9 Jul 2025 12:41:10 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=82(frontend)=20blocked=20edition=20if?= =?UTF-8?q?=20multiple=20ancestors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With child documents we need to check the parent documents to know if the parent doc are collaborative or not. --- .../__tests__/app-impress/doc-editor.spec.ts | 41 ++++++++++++------- .../app-impress/doc-visibility.spec.ts | 2 +- .../hooks/useIsCollaborativeEditable.tsx | 37 +++++++++-------- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts index 9a187abb..dd47f2d0 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts @@ -10,6 +10,7 @@ import { overrideConfig, verifyDocName, } from './common'; +import { createRootSubPage } from './sub-pages-utils'; test.beforeEach(async ({ page }) => { await page.goto('/'); @@ -524,6 +525,8 @@ test.describe('Doc Editor', () => { page, browserName, }) => { + test.slow(); + /** * The good port is 4444, but we want to simulate a not connected * collaborative server. @@ -536,7 +539,12 @@ test.describe('Doc Editor', () => { await page.goto('/'); - const [title] = await createDoc(page, 'editing-blocking', browserName, 1); + const [parentTitle] = await createDoc( + page, + 'editing-blocking', + browserName, + 1, + ); const card = page.getByLabel('It is the card information'); await expect( @@ -571,12 +579,20 @@ test.describe('Doc Editor', () => { // Close the modal await page.getByRole('button', { name: 'close' }).first().click(); + const urlParentDoc = page.url(); + + const { name: childTitle } = await createRootSubPage( + page, + browserName, + 'editing-blocking - child', + ); + let responseCanEdit = await responseCanEditPromise; expect(responseCanEdit.ok()).toBeTruthy(); let jsonCanEdit = (await responseCanEdit.json()) as { can_edit: boolean }; expect(jsonCanEdit.can_edit).toBeTruthy(); - const urlDoc = page.url(); + const urlChildDoc = page.url(); /** * We open another browser that will connect to the collaborative server @@ -603,14 +619,14 @@ test.describe('Doc Editor', () => { }, ); - await otherPage.goto(urlDoc); + await otherPage.goto(urlChildDoc); const webSocket = await webSocketPromise; expect(webSocket.url()).toContain( 'ws://localhost:4444/collaboration/ws/?room=', ); - await verifyDocName(otherPage, title); + await verifyDocName(otherPage, childTitle); await page.reload(); @@ -633,6 +649,10 @@ test.describe('Doc Editor', () => { await expect(editor).toHaveAttribute('contenteditable', 'false'); + await page.goto(urlParentDoc); + + await verifyDocName(page, parentTitle); + await page.getByRole('button', { name: 'Share' }).click(); await page.getByLabel('Visibility mode').click(); @@ -641,18 +661,9 @@ test.describe('Doc Editor', () => { // Close the modal await page.getByRole('button', { name: 'close' }).first().click(); - await page.reload(); + await page.goto(urlChildDoc); - responseCanEditPromise = page.waitForResponse( - (response) => - response.url().includes(`/can-edit/`) && response.status() === 200, - ); - - responseCanEdit = await responseCanEditPromise; - expect(responseCanEdit.ok()).toBeTruthy(); - - jsonCanEdit = (await responseCanEdit.json()) as { can_edit: boolean }; - expect(jsonCanEdit.can_edit).toBeTruthy(); + await expect(editor).toHaveAttribute('contenteditable', 'true'); await expect( card.getByText('Others are editing. Your network prevent changes.'), diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts index a0833d43..89721ab9 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts @@ -441,7 +441,7 @@ test.describe('Doc Visibility: Authenticated', () => { const { name: childTitle } = await createRootSubPage( page, browserName, - 'Authenticated read onlyc - child', + 'Authenticated read only - child', ); const urlChildDoc = page.url(); diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/hooks/useIsCollaborativeEditable.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/hooks/useIsCollaborativeEditable.tsx index 1ad4ebd4..968ee5de 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/hooks/useIsCollaborativeEditable.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/hooks/useIsCollaborativeEditable.tsx @@ -5,15 +5,20 @@ import { useIsOffline } from '@/features/service-worker'; import { KEY_CAN_EDIT, useDocCanEdit } from '../api/useDocCanEdit'; import { useProviderStore } from '../stores'; -import { Doc, LinkReach } from '../types'; +import { Doc, LinkReach, LinkRole } from '../types'; export const useIsCollaborativeEditable = (doc: Doc) => { const { isConnected } = useProviderStore(); const { data: conf } = useConfig(); - const docIsPublic = doc.link_reach === LinkReach.PUBLIC; - const docIsAuth = doc.link_reach === LinkReach.AUTHENTICATED; - const docHasMember = doc.nb_accesses_direct > 1; + const docIsPublic = + doc.computed_link_reach === LinkReach.PUBLIC && + doc.computed_link_role === LinkRole.EDITOR; + const docIsAuth = + doc.computed_link_reach === LinkReach.AUTHENTICATED && + doc.computed_link_role === LinkRole.EDITOR; + const docHasMember = + doc.nb_accesses_direct > 1 || doc.nb_accesses_ancestors > 1; const isUserReader = !doc.abilities.partial_update; const isShared = docIsPublic || docIsAuth || docHasMember; const { isOffline } = useIsOffline(); @@ -21,23 +26,23 @@ export const useIsCollaborativeEditable = (doc: Doc) => { const [isEditable, setIsEditable] = useState(true); const [isLoading, setIsLoading] = useState(!_isEditable); const timeout = useRef(null); - const { - data: { can_edit } = { can_edit: _isEditable }, - isLoading: isLoadingCanEdit, - } = useDocCanEdit(doc.id, { - enabled: !_isEditable, - queryKey: [KEY_CAN_EDIT, doc.id], - staleTime: 0, - }); + const { data: editingRight, isLoading: isLoadingCanEdit } = useDocCanEdit( + doc.id, + { + enabled: !_isEditable, + queryKey: [KEY_CAN_EDIT, doc.id], + staleTime: 0, + }, + ); useEffect(() => { - if (isLoadingCanEdit) { + if (isLoadingCanEdit || _isEditable || !editingRight) { return; } // Connection to the WebSocket can take some time, so we set a timeout to ensure the loading state is cleared after a reasonable time. timeout.current = setTimeout(() => { - setIsEditable(can_edit); + setIsEditable(editingRight.can_edit); setIsLoading(false); }, 1500); @@ -46,7 +51,7 @@ export const useIsCollaborativeEditable = (doc: Doc) => { clearTimeout(timeout.current); } }; - }, [can_edit, isLoadingCanEdit]); + }, [editingRight, isLoadingCanEdit, _isEditable]); useEffect(() => { if (!_isEditable) { @@ -59,7 +64,7 @@ export const useIsCollaborativeEditable = (doc: Doc) => { setIsEditable(true); setIsLoading(false); - }, [_isEditable, isLoading]); + }, [_isEditable]); if (!conf?.COLLABORATION_WS_NOT_CONNECTED_READY_ONLY) { return {