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 e4191f0b..5915d697 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
@@ -1,14 +1,13 @@
import { expect, test } from '@playwright/test';
import {
+ BROWSERS,
createDoc,
expectLoginPage,
keyCloakSignIn,
verifyDocName,
} from './common';
-const browsersName = ['chromium', 'webkit', 'firefox'];
-
test.describe('Doc Visibility', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
@@ -118,18 +117,20 @@ test.describe('Doc Visibility: Restricted', () => {
})
.click();
- const otherBrowser = browsersName.find((b) => b !== browserName);
+ const otherBrowser = BROWSERS.find((b) => b !== browserName);
await keyCloakSignIn(page, otherBrowser!);
await expect(
page.getByRole('link', { name: 'Docs Logo Docs' }),
- ).toBeVisible();
+ ).toBeVisible({
+ timeout: 10000,
+ });
await page.goto(urlDoc);
await expect(
- page.getByText('You do not have permission to view this document.'),
+ page.getByText('Insufficient access rights to view the document.'),
).toBeVisible({
timeout: 10000,
});
@@ -150,7 +151,7 @@ test.describe('Doc Visibility: Restricted', () => {
name: 'Quick search input',
});
- const otherBrowser = browsersName.find((b) => b !== browserName);
+ const otherBrowser = BROWSERS.find((b) => b !== browserName);
const username = `user@${otherBrowser}.test`;
await inputSearch.fill(username);
await page.getByRole('option', { name: username }).click();
@@ -262,11 +263,20 @@ test.describe('Doc Visibility: Public', () => {
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
await expect(page.getByRole('button', { name: 'search' })).toBeHidden();
await expect(page.getByRole('button', { name: 'New doc' })).toBeHidden();
- await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
const card = page.getByLabel('It is the card information');
await expect(card).toBeVisible();
-
await expect(card.getByText('Reader')).toBeVisible();
+
+ await page.getByRole('button', { name: 'Share' }).click();
+ await expect(
+ page.getByText(
+ 'You do not have permission to view users sharing this document or modify link settings.',
+ ),
+ ).toBeVisible();
+
+ await expect(
+ page.getByRole('button', { name: 'Request access' }),
+ ).toBeHidden();
});
test('It checks a public doc in editable mode', async ({
@@ -430,7 +440,7 @@ test.describe('Doc Visibility: Authenticated', () => {
})
.click();
- const otherBrowser = browsersName.find((b) => b !== browserName);
+ const otherBrowser = BROWSERS.find((b) => b !== browserName);
await keyCloakSignIn(page, otherBrowser!);
await expect(
@@ -443,6 +453,18 @@ test.describe('Doc Visibility: Authenticated', () => {
await page.getByRole('button', { name: 'Share' }).click();
await page.getByRole('button', { name: 'Copy link' }).click();
await expect(page.getByText('Link Copied !')).toBeVisible();
+
+ await expect(
+ page.getByText(
+ 'You do not have permission to view users sharing this document or modify link settings.',
+ ),
+ ).toBeVisible();
+
+ await page.getByRole('button', { name: 'Request access' }).click();
+
+ await expect(
+ page.getByRole('button', { name: 'Request access' }),
+ ).toBeDisabled();
});
test('It checks a authenticated doc in editable mode', async ({
@@ -490,7 +512,7 @@ test.describe('Doc Visibility: Authenticated', () => {
})
.click();
- const otherBrowser = browsersName.find((b) => b !== browserName);
+ const otherBrowser = BROWSERS.find((b) => b !== browserName);
await keyCloakSignIn(page, otherBrowser!);
await expect(
diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx
index 4def720d..31b83f39 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareAccessRequest.tsx
@@ -1,5 +1,6 @@
import {
Button,
+ ButtonProps,
VariantType,
useToastProvider,
} from '@openfun/cunningham-react';
@@ -11,10 +12,13 @@ import { Box, BoxButton, Icon, LoadMoreText } from '@/components';
import { QuickSearchData, QuickSearchGroup } from '@/components/quick-search';
import { useCunninghamTheme } from '@/cunningham';
import { AccessRequest, Doc } from '@/docs/doc-management/';
+import { useAuth } from '@/features/auth';
import {
useAcceptDocAccessRequest,
+ useCreateDocAccessRequest,
useDeleteDocAccessRequest,
+ useDocAccessRequests,
useDocAccessRequestsInfinite,
} from '../api/useDocAccessRequest';
@@ -147,3 +151,45 @@ export const QuickSearchGroupAccessRequest = ({
);
};
+
+type ButtonAccessRequestProps = {
+ docId: Doc['id'];
+} & ButtonProps;
+
+export const ButtonAccessRequest = ({
+ docId,
+ ...buttonProps
+}: ButtonAccessRequestProps) => {
+ const { authenticated } = useAuth();
+ const { data: requests } = useDocAccessRequests({
+ docId,
+ page: 1,
+ });
+ const { t } = useTranslation();
+ const { toast } = useToastProvider();
+ const { mutate: createRequest } = useCreateDocAccessRequest({
+ onSuccess: () => {
+ toast(t('Access request sent successfully.'), VariantType.SUCCESS, {
+ duration: 3000,
+ });
+ },
+ });
+
+ const hasRequested = !!(
+ requests && requests?.results.find((request) => request.document === docId)
+ );
+
+ if (!authenticated) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx
index a207010e..19d0fcc6 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx
@@ -17,7 +17,10 @@ import { isValidEmail } from '@/utils';
import { KEY_LIST_USER, useUsers } from '../api';
-import { QuickSearchGroupAccessRequest } from './DocShareAccessRequest';
+import {
+ ButtonAccessRequest,
+ QuickSearchGroupAccessRequest,
+} from './DocShareAccessRequest';
import { DocShareAddMemberList } from './DocShareAddMemberList';
import {
DocShareModalInviteUserRow,
@@ -151,7 +154,12 @@ export const DocShareModal = ({ doc, onClose }: Props) => {
{!canViewAccesses && (
-
+
{
'You do not have permission to view users sharing this document or modify link settings.',
)}
+
)}
{canViewAccesses && (
diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/index.ts b/src/frontend/apps/impress/src/features/docs/doc-share/components/index.ts
index aa4746c3..b85c96e3 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-share/components/index.ts
+++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/index.ts
@@ -1 +1,2 @@
export * from './DocShareModal';
+export * from './DocShareAccessRequest';
diff --git a/src/frontend/apps/impress/src/pages/docs/[id]/403.tsx b/src/frontend/apps/impress/src/pages/docs/[id]/403.tsx
index 3eb96173..145c03bc 100644
--- a/src/frontend/apps/impress/src/pages/docs/[id]/403.tsx
+++ b/src/frontend/apps/impress/src/pages/docs/[id]/403.tsx
@@ -1,8 +1,4 @@
-import {
- Button,
- VariantType,
- useToastProvider,
-} from '@openfun/cunningham-react';
+import { Button } from '@openfun/cunningham-react';
import Head from 'next/head';
import Image from 'next/image';
import { useRouter } from 'next/router';
@@ -13,10 +9,8 @@ import img403 from '@/assets/icons/icon-403.png';
import { Box, Icon, Loading, StyledLink, Text } from '@/components';
import { DEFAULT_QUERY_RETRY } from '@/core';
import { KEY_DOC, useDoc } from '@/features/docs';
-import {
- useCreateDocAccessRequest,
- useDocAccessRequests,
-} from '@/features/docs/doc-share/api/useDocAccessRequest';
+import { ButtonAccessRequest } from '@/features/docs/doc-share';
+import { useDocAccessRequests } from '@/features/docs/doc-share/api/useDocAccessRequest';
import { MainLayout } from '@/layouts';
import { NextPageWithLayout } from '@/types/next';
@@ -54,16 +48,9 @@ const DocPage403 = ({ id }: DocProps) => {
const { t } = useTranslation();
const { data: requests, isLoading: isLoadingRequest } = useDocAccessRequests({
docId: id,
+ page: 1,
});
const { replace } = useRouter();
- const { toast } = useToastProvider();
- const { mutate: createRequest } = useCreateDocAccessRequest({
- onSuccess: () => {
- toast(t('Access request sent successfully.'), VariantType.SUCCESS, {
- duration: 3000,
- });
- },
- });
const hasRequested = !!requests?.results.find(
(request) => request.document === id,
@@ -84,7 +71,7 @@ const DocPage403 = ({ id }: DocProps) => {
},
);
- if (error?.status !== 403) {
+ if (!isLoadingDoc && error?.status !== 403) {
void replace(`/docs/${id}`);
return ;
}
@@ -137,12 +124,7 @@ const DocPage403 = ({ id }: DocProps) => {
{t('Home')}
-
+