Skip to content

Commit 0d7052a

Browse files
AntoLClunika
authored andcommitted
✨(frontend) button access request on share modal
When a document is in public or connected mode, users can now request access to the document.
1 parent c6b9f21 commit 0d7052a

File tree

5 files changed

+100
-36
lines changed

5 files changed

+100
-36
lines changed

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

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { expect, test } from '@playwright/test';
22

33
import {
4+
BROWSERS,
45
createDoc,
56
expectLoginPage,
67
keyCloakSignIn,
78
verifyDocName,
89
} from './common';
910

10-
const browsersName = ['chromium', 'webkit', 'firefox'];
11-
1211
test.describe('Doc Visibility', () => {
1312
test.beforeEach(async ({ page }) => {
1413
await page.goto('/');
@@ -118,18 +117,20 @@ test.describe('Doc Visibility: Restricted', () => {
118117
})
119118
.click();
120119

121-
const otherBrowser = browsersName.find((b) => b !== browserName);
120+
const otherBrowser = BROWSERS.find((b) => b !== browserName);
122121

123122
await keyCloakSignIn(page, otherBrowser!);
124123

125124
await expect(
126125
page.getByRole('link', { name: 'Docs Logo Docs' }),
127-
).toBeVisible();
126+
).toBeVisible({
127+
timeout: 10000,
128+
});
128129

129130
await page.goto(urlDoc);
130131

131132
await expect(
132-
page.getByText('You do not have permission to view this document.'),
133+
page.getByText('Insufficient access rights to view the document.'),
133134
).toBeVisible({
134135
timeout: 10000,
135136
});
@@ -150,7 +151,7 @@ test.describe('Doc Visibility: Restricted', () => {
150151
name: 'Quick search input',
151152
});
152153

153-
const otherBrowser = browsersName.find((b) => b !== browserName);
154+
const otherBrowser = BROWSERS.find((b) => b !== browserName);
154155
const username = `user@${otherBrowser}.test`;
155156
await inputSearch.fill(username);
156157
await page.getByRole('option', { name: username }).click();
@@ -262,11 +263,20 @@ test.describe('Doc Visibility: Public', () => {
262263
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
263264
await expect(page.getByRole('button', { name: 'search' })).toBeHidden();
264265
await expect(page.getByRole('button', { name: 'New doc' })).toBeHidden();
265-
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
266266
const card = page.getByLabel('It is the card information');
267267
await expect(card).toBeVisible();
268-
269268
await expect(card.getByText('Reader')).toBeVisible();
269+
270+
await page.getByRole('button', { name: 'Share' }).click();
271+
await expect(
272+
page.getByText(
273+
'You do not have permission to view users sharing this document or modify link settings.',
274+
),
275+
).toBeVisible();
276+
277+
await expect(
278+
page.getByRole('button', { name: 'Request access' }),
279+
).toBeHidden();
270280
});
271281

272282
test('It checks a public doc in editable mode', async ({
@@ -430,7 +440,7 @@ test.describe('Doc Visibility: Authenticated', () => {
430440
})
431441
.click();
432442

433-
const otherBrowser = browsersName.find((b) => b !== browserName);
443+
const otherBrowser = BROWSERS.find((b) => b !== browserName);
434444
await keyCloakSignIn(page, otherBrowser!);
435445

436446
await expect(
@@ -443,6 +453,18 @@ test.describe('Doc Visibility: Authenticated', () => {
443453
await page.getByRole('button', { name: 'Share' }).click();
444454
await page.getByRole('button', { name: 'Copy link' }).click();
445455
await expect(page.getByText('Link Copied !')).toBeVisible();
456+
457+
await expect(
458+
page.getByText(
459+
'You do not have permission to view users sharing this document or modify link settings.',
460+
),
461+
).toBeVisible();
462+
463+
await page.getByRole('button', { name: 'Request access' }).click();
464+
465+
await expect(
466+
page.getByRole('button', { name: 'Request access' }),
467+
).toBeDisabled();
446468
});
447469

448470
test('It checks a authenticated doc in editable mode', async ({
@@ -490,7 +512,7 @@ test.describe('Doc Visibility: Authenticated', () => {
490512
})
491513
.click();
492514

493-
const otherBrowser = browsersName.find((b) => b !== browserName);
515+
const otherBrowser = BROWSERS.find((b) => b !== browserName);
494516
await keyCloakSignIn(page, otherBrowser!);
495517

496518
await expect(

src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
Button,
3+
ButtonProps,
34
VariantType,
45
useToastProvider,
56
} from '@openfun/cunningham-react';
@@ -11,10 +12,13 @@ import { Box, BoxButton, Icon, LoadMoreText } from '@/components';
1112
import { QuickSearchData, QuickSearchGroup } from '@/components/quick-search';
1213
import { useCunninghamTheme } from '@/cunningham';
1314
import { AccessRequest, Doc } from '@/docs/doc-management/';
15+
import { useAuth } from '@/features/auth';
1416

1517
import {
1618
useAcceptDocAccessRequest,
19+
useCreateDocAccessRequest,
1720
useDeleteDocAccessRequest,
21+
useDocAccessRequests,
1822
useDocAccessRequestsInfinite,
1923
} from '../api/useDocAccessRequest';
2024

@@ -147,3 +151,45 @@ export const QuickSearchGroupAccessRequest = ({
147151
</Box>
148152
);
149153
};
154+
155+
type ButtonAccessRequestProps = {
156+
docId: Doc['id'];
157+
} & ButtonProps;
158+
159+
export const ButtonAccessRequest = ({
160+
docId,
161+
...buttonProps
162+
}: ButtonAccessRequestProps) => {
163+
const { authenticated } = useAuth();
164+
const { data: requests } = useDocAccessRequests({
165+
docId,
166+
page: 1,
167+
});
168+
const { t } = useTranslation();
169+
const { toast } = useToastProvider();
170+
const { mutate: createRequest } = useCreateDocAccessRequest({
171+
onSuccess: () => {
172+
toast(t('Access request sent successfully.'), VariantType.SUCCESS, {
173+
duration: 3000,
174+
});
175+
},
176+
});
177+
178+
const hasRequested = !!(
179+
requests && requests?.results.find((request) => request.document === docId)
180+
);
181+
182+
if (!authenticated) {
183+
return null;
184+
}
185+
186+
return (
187+
<Button
188+
onClick={() => createRequest({ docId })}
189+
disabled={hasRequested}
190+
{...buttonProps}
191+
>
192+
{buttonProps.children || t('Request access')}
193+
</Button>
194+
);
195+
};

src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import { isValidEmail } from '@/utils';
1717

1818
import { KEY_LIST_USER, useUsers } from '../api';
1919

20-
import { QuickSearchGroupAccessRequest } from './DocShareAccessRequest';
20+
import {
21+
ButtonAccessRequest,
22+
QuickSearchGroupAccessRequest,
23+
} from './DocShareAccessRequest';
2124
import { DocShareAddMemberList } from './DocShareAddMemberList';
2225
import {
2326
DocShareModalInviteUserRow,
@@ -151,7 +154,12 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
151154

152155
<Box data-testid="doc-share-quick-search">
153156
{!canViewAccesses && (
154-
<Box $height={listHeight} $align="center" $justify="center">
157+
<Box
158+
$height={listHeight}
159+
$align="center"
160+
$justify="center"
161+
$gap="1rem"
162+
>
155163
<Text
156164
$maxWidth="320px"
157165
$textAlign="center"
@@ -162,6 +170,11 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
162170
'You do not have permission to view users sharing this document or modify link settings.',
163171
)}
164172
</Text>
173+
<ButtonAccessRequest
174+
docId={doc.id}
175+
color="tertiary"
176+
size="small"
177+
/>
165178
</Box>
166179
)}
167180
{canViewAccesses && (
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './DocShareModal';
2+
export * from './DocShareAccessRequest';

src/frontend/apps/impress/src/pages/docs/[id]/403.tsx

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
Button,
3-
VariantType,
4-
useToastProvider,
5-
} from '@openfun/cunningham-react';
1+
import { Button } from '@openfun/cunningham-react';
62
import Head from 'next/head';
73
import Image from 'next/image';
84
import { useRouter } from 'next/router';
@@ -13,10 +9,8 @@ import img403 from '@/assets/icons/icon-403.png';
139
import { Box, Icon, Loading, StyledLink, Text } from '@/components';
1410
import { DEFAULT_QUERY_RETRY } from '@/core';
1511
import { KEY_DOC, useDoc } from '@/features/docs';
16-
import {
17-
useCreateDocAccessRequest,
18-
useDocAccessRequests,
19-
} from '@/features/docs/doc-share/api/useDocAccessRequest';
12+
import { ButtonAccessRequest } from '@/features/docs/doc-share';
13+
import { useDocAccessRequests } from '@/features/docs/doc-share/api/useDocAccessRequest';
2014
import { MainLayout } from '@/layouts';
2115
import { NextPageWithLayout } from '@/types/next';
2216

@@ -54,16 +48,9 @@ const DocPage403 = ({ id }: DocProps) => {
5448
const { t } = useTranslation();
5549
const { data: requests, isLoading: isLoadingRequest } = useDocAccessRequests({
5650
docId: id,
51+
page: 1,
5752
});
5853
const { replace } = useRouter();
59-
const { toast } = useToastProvider();
60-
const { mutate: createRequest } = useCreateDocAccessRequest({
61-
onSuccess: () => {
62-
toast(t('Access request sent successfully.'), VariantType.SUCCESS, {
63-
duration: 3000,
64-
});
65-
},
66-
});
6754

6855
const hasRequested = !!requests?.results.find(
6956
(request) => request.document === id,
@@ -84,7 +71,7 @@ const DocPage403 = ({ id }: DocProps) => {
8471
},
8572
);
8673

87-
if (error?.status !== 403) {
74+
if (!isLoadingDoc && error?.status !== 403) {
8875
void replace(`/docs/${id}`);
8976
return <Loading />;
9077
}
@@ -137,12 +124,7 @@ const DocPage403 = ({ id }: DocProps) => {
137124
{t('Home')}
138125
</StyledButton>
139126
</StyledLink>
140-
<Button
141-
onClick={() => createRequest({ docId: id })}
142-
disabled={hasRequested}
143-
>
144-
{t('Request access')}
145-
</Button>
127+
<ButtonAccessRequest docId={id} />
146128
</Box>
147129
</Box>
148130
</Box>

0 commit comments

Comments
 (0)