Skip to content

Commit d89e3dc

Browse files
committed
🛂(frontend) display the AI buttons depend abilities
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.
1 parent 91cf5f9 commit d89e3dc

File tree

5 files changed

+179
-71
lines changed

5 files changed

+179
-71
lines changed

src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint-disable playwright/no-conditional-expect */
2+
/* eslint-disable playwright/no-conditional-in-test */
13
import path from 'path';
24

35
import { expect, test } from '@playwright/test';
@@ -368,4 +370,77 @@ test.describe('Doc Editor', () => {
368370

369371
await expect(editor.getByText('Bonjour le monde')).toBeVisible();
370372
});
373+
374+
[
375+
{ ai_transform: false, ai_translate: false },
376+
{ ai_transform: true, ai_translate: false },
377+
{ ai_transform: false, ai_translate: true },
378+
].forEach(({ ai_transform, ai_translate }) => {
379+
test(`it checks AI buttons when can transform is at "${ai_transform}" and can translate is at "${ai_translate}"`, async ({
380+
page,
381+
}) => {
382+
await mockedDocument(page, {
383+
accesses: [
384+
{
385+
id: 'b0df4343-c8bd-4c20-9ff6-fbf94fc94egg',
386+
role: 'owner',
387+
user: {
388+
389+
full_name: 'Super Owner',
390+
},
391+
},
392+
],
393+
abilities: {
394+
destroy: true, // Means owner
395+
link_configuration: true,
396+
ai_transform,
397+
ai_translate,
398+
accesses_manage: true,
399+
accesses_view: true,
400+
update: true,
401+
partial_update: true,
402+
retrieve: true,
403+
},
404+
link_reach: 'public',
405+
link_role: 'editor',
406+
created_at: '2021-09-01T09:00:00Z',
407+
});
408+
409+
await goToGridDoc(page);
410+
411+
await verifyDocName(page, 'Mocked document');
412+
413+
await page.locator('.bn-block-outer').last().fill('Hello World');
414+
415+
const editor = page.locator('.ProseMirror');
416+
await editor.getByText('Hello').dblclick();
417+
418+
if (!ai_transform && !ai_translate) {
419+
await expect(page.getByRole('button', { name: 'AI' })).toBeHidden();
420+
return;
421+
}
422+
423+
await page.getByRole('button', { name: 'AI' }).click();
424+
425+
if (ai_transform) {
426+
await expect(
427+
page.getByRole('menuitem', { name: 'Use as prompt' }),
428+
).toBeVisible();
429+
} else {
430+
await expect(
431+
page.getByRole('menuitem', { name: 'Use as prompt' }),
432+
).toBeHidden();
433+
}
434+
435+
if (ai_translate) {
436+
await expect(
437+
page.getByRole('menuitem', { name: 'Language' }),
438+
).toBeVisible();
439+
} else {
440+
await expect(
441+
page.getByRole('menuitem', { name: 'Language' }),
442+
).toBeHidden();
443+
}
444+
});
445+
});
371446
});

src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx

Lines changed: 82 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ export function AIGroupButton() {
9292
return null;
9393
}
9494

95+
const canAITransform = currentDoc.abilities.ai_transform;
96+
const canAITranslate = currentDoc.abilities.ai_translate;
97+
98+
if (!canAITransform && !canAITranslate) {
99+
return null;
100+
}
101+
95102
return (
96103
<Components.Generic.Menu.Root>
97104
<Components.Generic.Menu.Trigger>
@@ -111,79 +118,85 @@ export function AIGroupButton() {
111118
className="bn-menu-dropdown bn-drag-handle-menu"
112119
sub={true}
113120
>
114-
<AIMenuItemTransform
115-
action="prompt"
116-
docId={currentDoc.id}
117-
icon={
118-
<Text $isMaterialIcon $size="s">
119-
text_fields
120-
</Text>
121-
}
122-
>
123-
{t('Use as prompt')}
124-
</AIMenuItemTransform>
125-
<AIMenuItemTransform
126-
action="rephrase"
127-
docId={currentDoc.id}
128-
icon={
129-
<Text $isMaterialIcon $size="s">
130-
refresh
131-
</Text>
132-
}
133-
>
134-
{t('Rephrase')}
135-
</AIMenuItemTransform>
136-
<AIMenuItemTransform
137-
action="summarize"
138-
docId={currentDoc.id}
139-
icon={
140-
<Text $isMaterialIcon $size="s">
141-
summarize
142-
</Text>
143-
}
144-
>
145-
{t('Summarize')}
146-
</AIMenuItemTransform>
147-
<AIMenuItemTransform
148-
action="correct"
149-
docId={currentDoc.id}
150-
icon={
151-
<Text $isMaterialIcon $size="s">
152-
check
153-
</Text>
154-
}
155-
>
156-
{t('Correct')}
157-
</AIMenuItemTransform>
158-
<Components.Generic.Menu.Root position="right" sub={true}>
159-
<Components.Generic.Menu.Trigger sub={false}>
160-
<Components.Generic.Menu.Item
161-
className="bn-menu-item"
162-
subTrigger={true}
121+
{canAITransform && (
122+
<>
123+
<AIMenuItemTransform
124+
action="prompt"
125+
docId={currentDoc.id}
126+
icon={
127+
<Text $isMaterialIcon $size="s">
128+
text_fields
129+
</Text>
130+
}
163131
>
164-
<Box $direction="row" $gap="0.6rem">
132+
{t('Use as prompt')}
133+
</AIMenuItemTransform>
134+
<AIMenuItemTransform
135+
action="rephrase"
136+
docId={currentDoc.id}
137+
icon={
165138
<Text $isMaterialIcon $size="s">
166-
translate
139+
refresh
167140
</Text>
168-
{t('Language')}
169-
</Box>
170-
</Components.Generic.Menu.Item>
171-
</Components.Generic.Menu.Trigger>
172-
<Components.Generic.Menu.Dropdown
173-
sub={true}
174-
className="bn-menu-dropdown"
175-
>
176-
{languages.map((language) => (
177-
<AIMenuItemTranslate
178-
key={language.value}
179-
language={language.value}
180-
docId={currentDoc.id}
141+
}
142+
>
143+
{t('Rephrase')}
144+
</AIMenuItemTransform>
145+
<AIMenuItemTransform
146+
action="summarize"
147+
docId={currentDoc.id}
148+
icon={
149+
<Text $isMaterialIcon $size="s">
150+
summarize
151+
</Text>
152+
}
153+
>
154+
{t('Summarize')}
155+
</AIMenuItemTransform>
156+
<AIMenuItemTransform
157+
action="correct"
158+
docId={currentDoc.id}
159+
icon={
160+
<Text $isMaterialIcon $size="s">
161+
check
162+
</Text>
163+
}
164+
>
165+
{t('Correct')}
166+
</AIMenuItemTransform>
167+
</>
168+
)}
169+
{canAITranslate && (
170+
<Components.Generic.Menu.Root position="right" sub={true}>
171+
<Components.Generic.Menu.Trigger sub={false}>
172+
<Components.Generic.Menu.Item
173+
className="bn-menu-item"
174+
subTrigger={true}
181175
>
182-
{language.display_name}
183-
</AIMenuItemTranslate>
184-
))}
185-
</Components.Generic.Menu.Dropdown>
186-
</Components.Generic.Menu.Root>
176+
<Box $direction="row" $gap="0.6rem">
177+
<Text $isMaterialIcon $size="s">
178+
translate
179+
</Text>
180+
{t('Language')}
181+
</Box>
182+
</Components.Generic.Menu.Item>
183+
</Components.Generic.Menu.Trigger>
184+
<Components.Generic.Menu.Dropdown
185+
sub={true}
186+
className="bn-menu-dropdown"
187+
>
188+
{languages.map((language) => (
189+
<AIMenuItemTranslate
190+
key={language.value}
191+
language={language.value}
192+
docId={currentDoc.id}
193+
>
194+
{language.display_name}
195+
</AIMenuItemTranslate>
196+
))}
197+
</Components.Generic.Menu.Dropdown>
198+
</Components.Generic.Menu.Root>
199+
)}
187200
</Components.Generic.Menu.Dropdown>
188201
</Components.Generic.Menu.Root>
189202
);

src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const DocEditor = ({ doc, versionId }: DocEditorProps) => {
6565
$css="overflow-x: clip; flex: 1;"
6666
$position="relative"
6767
>
68-
<Box $css="flex:1;" $overflow="auto" $position="relative">
68+
<Box $css="flex:1;" $position="relative">
6969
{isVersion ? (
7070
<DocVersionEditor docId={doc.id} versionId={versionId} />
7171
) : (

src/frontend/apps/impress/src/features/docs/doc-management/types.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,20 @@ export interface Doc {
4848
abilities: {
4949
accesses_manage: boolean;
5050
accesses_view: boolean;
51-
attachment_upload: true;
51+
ai_transform: boolean;
52+
ai_translate: boolean;
53+
attachment_upload: boolean;
54+
children_create: boolean;
55+
children_list: boolean;
56+
collaboration_auth: boolean;
5257
destroy: boolean;
58+
favorite: boolean;
59+
invite_owner: boolean;
5360
link_configuration: boolean;
61+
media_auth: boolean;
62+
move: boolean;
5463
partial_update: boolean;
64+
restore: boolean;
5565
retrieve: boolean;
5666
update: boolean;
5767
versions_destroy: boolean;

src/frontend/apps/impress/src/features/service-worker/ApiPlugin.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,20 @@ export class ApiPlugin implements WorkboxPlugin {
195195
abilities: {
196196
accesses_manage: true,
197197
accesses_view: true,
198+
ai_transform: true,
199+
ai_translate: true,
198200
attachment_upload: true,
201+
children_create: true,
202+
children_list: true,
203+
collaboration_auth: true,
199204
destroy: true,
205+
favorite: true,
206+
invite_owner: true,
200207
link_configuration: true,
208+
media_auth: true,
209+
move: true,
201210
partial_update: true,
211+
restore: true,
202212
retrieve: true,
203213
update: true,
204214
versions_destroy: true,

0 commit comments

Comments
 (0)