🚚(frontend) change visibility in share modal
We stop to propose to make the document public from the doc creation modal. We now propose to change the visibility of the document from the share modal.
This commit is contained in:
@@ -13,6 +13,10 @@ and this project adheres to
|
||||
|
||||
- 🛂(frontend) access public docs without being logged #235
|
||||
|
||||
## Changed
|
||||
|
||||
- 🚚(frontend) change visibility in share modal #235
|
||||
|
||||
|
||||
## [1.3.0] - 2024-09-05
|
||||
|
||||
|
||||
@@ -55,14 +55,19 @@ export const createDoc = async (
|
||||
})
|
||||
.fill(randomDocs[i]);
|
||||
|
||||
if (isPublic) {
|
||||
await page.getByText('Is it public ?').click();
|
||||
}
|
||||
|
||||
await expect(buttonCreate).toBeEnabled();
|
||||
await buttonCreate.click();
|
||||
|
||||
await expect(page.locator('h2').getByText(randomDocs[i])).toBeVisible();
|
||||
|
||||
if (isPublic) {
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page.getByText('Doc private').click();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return randomDocs;
|
||||
|
||||
@@ -21,8 +21,6 @@ test.describe('Doc Create', () => {
|
||||
).toBeVisible();
|
||||
await expect(card.getByLabel('Document name')).toBeVisible();
|
||||
|
||||
await expect(card.getByText('Is it public ?')).toBeVisible();
|
||||
|
||||
await expect(
|
||||
card.getByRole('button', {
|
||||
name: 'Create the document',
|
||||
@@ -46,14 +44,8 @@ test.describe('Doc Create', () => {
|
||||
await expect(buttonCreateHomepage).toBeVisible();
|
||||
});
|
||||
|
||||
test('create a new public doc', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'My new doc',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
test('it creates a doc', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(page, 'My new doc', browserName, 1);
|
||||
|
||||
expect(await page.locator('title').textContent()).toMatch(
|
||||
/My new doc - Docs/,
|
||||
@@ -69,11 +61,5 @@ test.describe('Doc Create', () => {
|
||||
await expect(datagrid.getByLabel('Loading data')).toBeHidden();
|
||||
|
||||
await expect(datagrid.getByText(docTitle)).toBeVisible();
|
||||
|
||||
const row = datagrid.getByRole('row').filter({
|
||||
hasText: docTitle,
|
||||
});
|
||||
|
||||
await expect(row.getByRole('cell').nth(0)).toHaveText('Public');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -65,13 +65,7 @@ test.describe('Doc Header', () => {
|
||||
});
|
||||
|
||||
test('it updates the doc', async ({ page, browserName }) => {
|
||||
const [randomDoc] = await createDoc(
|
||||
page,
|
||||
'doc-update',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
const [randomDoc] = await createDoc(page, 'doc-update', browserName, 1);
|
||||
await expect(page.locator('h2').getByText(randomDoc)).toBeVisible();
|
||||
|
||||
await page.getByLabel('Open the document options').click();
|
||||
@@ -85,12 +79,7 @@ test.describe('Doc Header', () => {
|
||||
page.locator('h2').getByText(`Update document "${randomDoc}"`),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByRole('checkbox', { name: 'Is it public ?' }),
|
||||
).toBeChecked();
|
||||
|
||||
await page.getByText('Document name').fill(`${randomDoc}-updated`);
|
||||
await page.getByText('Is it public ?').click();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
@@ -116,8 +105,8 @@ test.describe('Doc Header', () => {
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByRole('checkbox', { name: 'Is it public ?' }),
|
||||
).not.toBeChecked();
|
||||
page.getByRole('textbox', { name: 'Document name' }),
|
||||
).toHaveValue(`${randomDoc}-updated`);
|
||||
});
|
||||
|
||||
test('it deletes the doc', async ({ page, browserName }) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc, keyCloakSignIn } from './common';
|
||||
import { keyCloakSignIn } from './common';
|
||||
|
||||
test.describe('Doc Routing', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -56,34 +56,4 @@ test.describe('Doc Routing: Not loggued', () => {
|
||||
}),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('A public doc is accessible even when not authentified.', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'My new doc',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc, keyCloakSignIn } from './common';
|
||||
|
||||
test.describe('Doc Visibility', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('Make a public doc', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'My new doc',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
|
||||
const header = page.locator('header').first();
|
||||
await header.locator('h2').getByText('Docs').click();
|
||||
|
||||
const datagrid = page
|
||||
.getByLabel('Datagrid of the documents page 1')
|
||||
.getByRole('table');
|
||||
|
||||
await expect(datagrid.getByLabel('Loading data')).toBeHidden();
|
||||
|
||||
await expect(datagrid.getByText(docTitle)).toBeVisible();
|
||||
|
||||
const row = datagrid.getByRole('row').filter({
|
||||
hasText: docTitle,
|
||||
});
|
||||
|
||||
await expect(row.getByRole('cell').nth(0)).toHaveText('Public');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Visibility: Not loggued', () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test('A public doc is accessible even when not authentified.', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'My new doc',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visiblitity has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -340,6 +340,10 @@ const config = {
|
||||
'forms-checkbox': {
|
||||
'border-radius': '0',
|
||||
color: 'var(--c--theme--colors--primary-text)',
|
||||
text: {
|
||||
color: 'var(--c--theme--colors--greyscale-text)',
|
||||
size: 'var(--c--theme--font--sizes--t)',
|
||||
},
|
||||
},
|
||||
'forms-datepicker': {
|
||||
'border-radius': '0',
|
||||
|
||||
@@ -308,6 +308,11 @@ input:-webkit-autofill:focus {
|
||||
transition: all 0.8s ease-in-out;
|
||||
}
|
||||
|
||||
.c__checkbox .c__field__text {
|
||||
color: var(--c--components--forms-checkbox--text--color);
|
||||
font-size: var(--c--components--forms-checkbox--text--size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Button
|
||||
*/
|
||||
|
||||
@@ -463,6 +463,10 @@
|
||||
);
|
||||
--c--components--forms-checkbox--border-radius: 0;
|
||||
--c--components--forms-checkbox--color: var(--c--theme--colors--primary-text);
|
||||
--c--components--forms-checkbox--text--color: var(
|
||||
--c--theme--colors--greyscale-text
|
||||
);
|
||||
--c--components--forms-checkbox--text--size: var(--c--theme--font--sizes--t);
|
||||
--c--components--forms-datepicker--border-radius: 0;
|
||||
--c--components--forms-fileuploader--border-radius: 0;
|
||||
--c--components--forms-field--color: var(--c--theme--colors--primary-text);
|
||||
|
||||
@@ -469,6 +469,10 @@ export const tokens = {
|
||||
'forms-checkbox': {
|
||||
'border-radius': '0',
|
||||
color: 'var(--c--theme--colors--primary-text)',
|
||||
text: {
|
||||
color: 'var(--c--theme--colors--greyscale-text)',
|
||||
size: 'var(--c--theme--font--sizes--t)',
|
||||
},
|
||||
},
|
||||
'forms-datepicker': { 'border-radius': '0' },
|
||||
'forms-fileuploader': { 'border-radius': '0' },
|
||||
|
||||
@@ -6,17 +6,13 @@ import { Doc } from '../types';
|
||||
|
||||
import { KEY_LIST_DOC } from './useDocs';
|
||||
|
||||
export type CreateDocParam = Pick<Doc, 'title' | 'is_public'>;
|
||||
export type CreateDocParam = Pick<Doc, 'title'>;
|
||||
|
||||
export const createDoc = async ({
|
||||
title,
|
||||
is_public,
|
||||
}: CreateDocParam): Promise<Doc> => {
|
||||
export const createDoc = async ({ title }: CreateDocParam): Promise<Doc> => {
|
||||
const response = await fetchAPI(`documents/`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
is_public,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import {
|
||||
Switch,
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Card, IconBG } from '@/components';
|
||||
|
||||
import { KEY_DOC, KEY_LIST_DOC, useUpdateDoc } from '../api';
|
||||
import { Doc } from '../types';
|
||||
|
||||
interface DocVisibilityProps {
|
||||
doc: Doc;
|
||||
}
|
||||
|
||||
export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [docPublic, setDocPublic] = useState(doc.is_public);
|
||||
const { toast } = useToastProvider();
|
||||
const api = useUpdateDoc({
|
||||
onSuccess: () => {
|
||||
toast(
|
||||
t('The document visiblitity has been updated.'),
|
||||
VariantType.SUCCESS,
|
||||
{
|
||||
duration: 4000,
|
||||
},
|
||||
);
|
||||
},
|
||||
listInvalideQueries: [KEY_LIST_DOC],
|
||||
});
|
||||
|
||||
return (
|
||||
<Card
|
||||
$margin="tiny"
|
||||
$padding="small"
|
||||
aria-label={t('Doc visibility card')}
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$justify="space-between"
|
||||
>
|
||||
<Box $direction="row" $gap="1rem">
|
||||
<IconBG iconName="public" $margin="none" />
|
||||
<Switch
|
||||
label={t(docPublic ? 'Doc public' : 'Doc private')}
|
||||
defaultChecked={docPublic}
|
||||
onChange={() => {
|
||||
api.mutate({
|
||||
id: doc.id,
|
||||
is_public: !docPublic,
|
||||
});
|
||||
setDocPublic(!docPublic);
|
||||
}}
|
||||
text={t(
|
||||
docPublic
|
||||
? 'Anyone on the internet with the link can view'
|
||||
: 'Only for people with access',
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalSize,
|
||||
Switch,
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
@@ -44,9 +43,8 @@ export const ModalCreateDoc = ({ onClose }: ModalCreateDocProps) => {
|
||||
onClose,
|
||||
isPublic: false,
|
||||
titleModal: t('Create a new document'),
|
||||
validate: (title, is_public) =>
|
||||
validate: (title) =>
|
||||
api.mutate({
|
||||
is_public,
|
||||
title,
|
||||
}),
|
||||
...api,
|
||||
@@ -85,9 +83,8 @@ export const ModalUpdateDoc = ({ onClose, doc }: ModalUpdateDocProps) => {
|
||||
titleModal: t('Update document "{{documentTitle}}"', {
|
||||
documentTitle: doc.title,
|
||||
}),
|
||||
validate: (title, is_public) =>
|
||||
validate: (title) =>
|
||||
api.mutate({
|
||||
is_public,
|
||||
title,
|
||||
id: doc.id,
|
||||
}),
|
||||
@@ -99,10 +96,9 @@ export const ModalUpdateDoc = ({ onClose, doc }: ModalUpdateDocProps) => {
|
||||
|
||||
type ModalDoc<T> = {
|
||||
buttonText: string;
|
||||
isPublic: boolean;
|
||||
onClose: () => void;
|
||||
titleModal: string;
|
||||
validate: (title: string, is_public: boolean) => void;
|
||||
validate: (title: string) => void;
|
||||
initialTitle?: string;
|
||||
infoText?: string;
|
||||
} & UseMutationResult<Doc, APIError<unknown>, T, unknown>;
|
||||
@@ -111,7 +107,6 @@ const ModalDoc = <T,>({
|
||||
buttonText,
|
||||
infoText,
|
||||
initialTitle,
|
||||
isPublic,
|
||||
onClose,
|
||||
titleModal,
|
||||
validate,
|
||||
@@ -121,8 +116,6 @@ const ModalDoc = <T,>({
|
||||
const { t } = useTranslation();
|
||||
const [title, setTitle] = useState(initialTitle || '');
|
||||
|
||||
const [docPublic, setDocPublic] = useState(isPublic);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen
|
||||
@@ -144,7 +137,7 @@ const ModalDoc = <T,>({
|
||||
aria-label={buttonText}
|
||||
color="primary"
|
||||
fullWidth
|
||||
onClick={() => validate(title, docPublic)}
|
||||
onClick={() => validate(title)}
|
||||
>
|
||||
{buttonText}
|
||||
</Button>
|
||||
@@ -177,12 +170,6 @@ const ModalDoc = <T,>({
|
||||
setDocName: setTitle,
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
label={t('Is it public ?')}
|
||||
labelSide="right"
|
||||
defaultChecked={docPublic}
|
||||
onChange={() => setDocPublic(!docPublic)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
|
||||
@@ -10,6 +10,8 @@ import { MemberList } from '@/features/docs/members/members-list';
|
||||
import { Doc } from '../types';
|
||||
import { currentDocRole } from '../utils';
|
||||
|
||||
import { DocVisibility } from './DocVisibility';
|
||||
|
||||
const ModalShareStyle = createGlobalStyle`
|
||||
& .c__modal__scroller{
|
||||
background: #FAFAFA;
|
||||
@@ -66,6 +68,7 @@ export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
|
||||
</Card>
|
||||
}
|
||||
>
|
||||
<DocVisibility doc={doc} />
|
||||
<AddMembers doc={doc} currentRole={currentDocRole(doc.abilities)} />
|
||||
<InvitationList doc={doc} />
|
||||
<MemberList doc={doc} />
|
||||
|
||||
Reference in New Issue
Block a user