From d89e3dc6d47554f5c4801f7ad35915e725632a53 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Tue, 11 Feb 2025 10:26:16 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=82(frontend)=20display=20the=20AI=20b?= =?UTF-8?q?uttons=20depend=20abilities?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anybody with edit right could use the AI. We changed this behavior, now we have to be authentified with edit right. We update the UI to display the AI buttons only if the user has the correct AI ability. --- .../__tests__/app-impress/doc-editor.spec.ts | 75 +++++++++ .../docs/doc-editor/components/AIButton.tsx | 153 ++++++++++-------- .../docs/doc-editor/components/DocEditor.tsx | 2 +- .../features/docs/doc-management/types.tsx | 12 +- .../src/features/service-worker/ApiPlugin.ts | 10 ++ 5 files changed, 180 insertions(+), 72 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 476510e1..035e39e0 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 @@ -1,3 +1,5 @@ +/* eslint-disable playwright/no-conditional-expect */ +/* eslint-disable playwright/no-conditional-in-test */ import path from 'path'; import { expect, test } from '@playwright/test'; @@ -368,4 +370,77 @@ test.describe('Doc Editor', () => { await expect(editor.getByText('Bonjour le monde')).toBeVisible(); }); + + [ + { ai_transform: false, ai_translate: false }, + { ai_transform: true, ai_translate: false }, + { ai_transform: false, ai_translate: true }, + ].forEach(({ ai_transform, ai_translate }) => { + test(`it checks AI buttons when can transform is at "${ai_transform}" and can translate is at "${ai_translate}"`, async ({ + page, + }) => { + await mockedDocument(page, { + accesses: [ + { + id: 'b0df4343-c8bd-4c20-9ff6-fbf94fc94egg', + role: 'owner', + user: { + email: 'super@owner.com', + full_name: 'Super Owner', + }, + }, + ], + abilities: { + destroy: true, // Means owner + link_configuration: true, + ai_transform, + ai_translate, + accesses_manage: true, + accesses_view: true, + update: true, + partial_update: true, + retrieve: true, + }, + link_reach: 'public', + link_role: 'editor', + created_at: '2021-09-01T09:00:00Z', + }); + + await goToGridDoc(page); + + await verifyDocName(page, 'Mocked document'); + + await page.locator('.bn-block-outer').last().fill('Hello World'); + + const editor = page.locator('.ProseMirror'); + await editor.getByText('Hello').dblclick(); + + if (!ai_transform && !ai_translate) { + await expect(page.getByRole('button', { name: 'AI' })).toBeHidden(); + return; + } + + await page.getByRole('button', { name: 'AI' }).click(); + + if (ai_transform) { + await expect( + page.getByRole('menuitem', { name: 'Use as prompt' }), + ).toBeVisible(); + } else { + await expect( + page.getByRole('menuitem', { name: 'Use as prompt' }), + ).toBeHidden(); + } + + if (ai_translate) { + await expect( + page.getByRole('menuitem', { name: 'Language' }), + ).toBeVisible(); + } else { + await expect( + page.getByRole('menuitem', { name: 'Language' }), + ).toBeHidden(); + } + }); + }); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx index 31c98291..f30ccc5b 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx @@ -92,6 +92,13 @@ export function AIGroupButton() { return null; } + const canAITransform = currentDoc.abilities.ai_transform; + const canAITranslate = currentDoc.abilities.ai_translate; + + if (!canAITransform && !canAITranslate) { + return null; + } + return ( @@ -111,79 +118,85 @@ export function AIGroupButton() { className="bn-menu-dropdown bn-drag-handle-menu" sub={true} > - - text_fields - - } - > - {t('Use as prompt')} - - - refresh - - } - > - {t('Rephrase')} - - - summarize - - } - > - {t('Summarize')} - - - check - - } - > - {t('Correct')} - - - - - + {canAITransform && ( + <> + - translate + text_fields - {t('Language')} - - - - - {languages.map((language) => ( - + {t('Use as prompt')} + + + refresh + + } + > + {t('Rephrase')} + + + summarize + + } + > + {t('Summarize')} + + + check + + } + > + {t('Correct')} + + + )} + {canAITranslate && ( + + + - {language.display_name} - - ))} - - + + + translate + + {t('Language')} + + + + + {languages.map((language) => ( + + {language.display_name} + + ))} + + + )} ); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx index 6beabd79..e000a488 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx @@ -65,7 +65,7 @@ export const DocEditor = ({ doc, versionId }: DocEditorProps) => { $css="overflow-x: clip; flex: 1;" $position="relative" > - + {isVersion ? ( ) : ( diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx index 6afcc517..8462df0e 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx @@ -48,10 +48,20 @@ export interface Doc { abilities: { accesses_manage: boolean; accesses_view: boolean; - attachment_upload: true; + ai_transform: boolean; + ai_translate: boolean; + attachment_upload: boolean; + children_create: boolean; + children_list: boolean; + collaboration_auth: boolean; destroy: boolean; + favorite: boolean; + invite_owner: boolean; link_configuration: boolean; + media_auth: boolean; + move: boolean; partial_update: boolean; + restore: boolean; retrieve: boolean; update: boolean; versions_destroy: boolean; diff --git a/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts b/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts index 2195c00b..875bb87c 100644 --- a/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts +++ b/src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts @@ -195,10 +195,20 @@ export class ApiPlugin implements WorkboxPlugin { abilities: { accesses_manage: true, accesses_view: true, + ai_transform: true, + ai_translate: true, attachment_upload: true, + children_create: true, + children_list: true, + collaboration_auth: true, destroy: true, + favorite: true, + invite_owner: true, link_configuration: true, + media_auth: true, + move: true, partial_update: true, + restore: true, retrieve: true, update: true, versions_destroy: true,