(frontend) update document

We can now update a pad from a modal.
This commit is contained in:
Anthony LC
2024-05-23 17:01:33 +02:00
committed by Anthony LC
parent ef2f4d3250
commit 2813b2ca27
6 changed files with 200 additions and 1 deletions

View File

@@ -28,6 +28,7 @@ export const createPad = async (
padName: string, padName: string,
browserName: string, browserName: string,
length: number, length: number,
isPublic: boolean = false,
) => { ) => {
const panel = page.getByLabel('Pads panel').first(); const panel = page.getByLabel('Pads panel').first();
const buttonCreate = page.getByRole('button', { name: 'Create the pad' }); const buttonCreate = page.getByRole('button', { name: 'Create the pad' });
@@ -37,6 +38,11 @@ export const createPad = async (
for (let i = 0; i < randomPads.length; i++) { for (let i = 0; i < randomPads.length; i++) {
await panel.getByRole('button', { name: 'Add a pad' }).click(); await panel.getByRole('button', { name: 'Add a pad' }).click();
await page.getByText('Pad name').fill(randomPads[i]); await page.getByText('Pad name').fill(randomPads[i]);
if (isPublic) {
await page.getByText('Is it public ?').click();
}
await expect(buttonCreate).toBeEnabled(); await expect(buttonCreate).toBeEnabled();
await buttonCreate.click(); await buttonCreate.click();
await expect(panel.locator('li').getByText(randomPads[i])).toBeVisible(); await expect(panel.locator('li').getByText(randomPads[i])).toBeVisible();

View File

@@ -47,4 +47,59 @@ test.describe('Pad Tools', () => {
expect(pdfText).toContain('La directrice'); // This is the template text expect(pdfText).toContain('La directrice'); // This is the template text
expect(pdfText).toContain('Hello World'); // This is the pad text expect(pdfText).toContain('Hello World'); // This is the pad text
}); });
test('it updates the pad', async ({ page, browserName }) => {
const [randomPad] = await createPad(
page,
'pad-update',
browserName,
1,
true,
);
await expect(page.locator('h2').getByText(randomPad)).toBeVisible();
await page.getByLabel('Open the document options').click();
await page
.getByRole('button', {
name: 'Update document',
})
.click();
await expect(
page.locator('h2').getByText(`Update document "${randomPad}"`),
).toBeVisible();
await expect(
page.getByRole('checkbox', { name: 'Is it public ?' }),
).toBeChecked();
await page.getByText('Pad name').fill(`${randomPad}-updated`);
await page.getByText('Is it public ?').click();
await page
.getByRole('button', {
name: 'Validate the modification',
})
.click();
await expect(
page.getByText('The document has been updated.'),
).toBeVisible();
const panel = page.getByLabel('Pads panel').first();
await expect(
panel.locator('li').getByText(`${randomPad}-updated`),
).toBeVisible();
await page.getByLabel('Open the document options').click();
await page
.getByRole('button', {
name: 'Update document',
})
.click();
await expect(
page.getByRole('checkbox', { name: 'Is it public ?' }),
).not.toBeChecked();
});
}); });

View File

@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import { Box, DropButton, IconOptions, Text } from '@/components'; import { Box, DropButton, IconOptions, Text } from '@/components';
import { Pad } from '@/features/pads/pad'; import { Pad } from '@/features/pads/pad';
import { ModalUpdatePad } from '@/features/pads/pads-create';
import { TemplatesOrdering, useTemplates } from '../api/useTemplates'; import { TemplatesOrdering, useTemplates } from '../api/useTemplates';
@@ -18,6 +19,7 @@ export const PadToolBox = ({ pad }: PadToolBoxProps) => {
const { data: templates } = useTemplates({ const { data: templates } = useTemplates({
ordering: TemplatesOrdering.BY_CREATED_ON_DESC, ordering: TemplatesOrdering.BY_CREATED_ON_DESC,
}); });
const [isModalUpdateOpen, setIsModalUpdateOpen] = useState(false);
const [isModalPDFOpen, setIsModalPDFOpen] = useState(false); const [isModalPDFOpen, setIsModalPDFOpen] = useState(false);
const [isDropOpen, setIsDropOpen] = useState(false); const [isDropOpen, setIsDropOpen] = useState(false);
@@ -44,13 +46,23 @@ export const PadToolBox = ({ pad }: PadToolBoxProps) => {
button={ button={
<IconOptions <IconOptions
isOpen={isDropOpen} isOpen={isDropOpen}
aria-label={t('Open the team options')} aria-label={t('Open the document options')}
/> />
} }
onOpenChange={(isOpen) => setIsDropOpen(isOpen)} onOpenChange={(isOpen) => setIsDropOpen(isOpen)}
isOpen={isDropOpen} isOpen={isDropOpen}
> >
<Box> <Box>
<Button
onClick={() => {
setIsModalUpdateOpen(true);
setIsDropOpen(false);
}}
color="primary-text"
icon={<span className="material-icons">edit</span>}
>
<Text $theme="primary">{t('Update document')}</Text>
</Button>
<Button <Button
onClick={() => { onClick={() => {
setIsModalPDFOpen(true); setIsModalPDFOpen(true);
@@ -70,6 +82,9 @@ export const PadToolBox = ({ pad }: PadToolBoxProps) => {
pad={pad} pad={pad}
/> />
)} )}
{isModalUpdateOpen && (
<ModalUpdatePad onClose={() => setIsModalUpdateOpen(false)} pad={pad} />
)}
</Box> </Box>
); );
}; };

View File

@@ -0,0 +1,6 @@
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6 34.5002V42.0002H13.5L35.62 19.8802L28.12 12.3802L6 34.5002ZM42.82 12.6802L35.32 5.18018L30.26 10.2602L37.76 17.7602L42.82 12.6802Z"
fill="currentColor"
/>
</svg>

After

Width:  |  Height:  |  Size: 259 B

View File

@@ -0,0 +1,116 @@
import {
Button,
Modal,
ModalSize,
Switch,
VariantType,
useToastProvider,
} from '@openfun/cunningham-react';
import { t } from 'i18next';
import { useState } from 'react';
import { Box, Text } from '@/components';
import useCunninghamTheme from '@/cunningham/useCunninghamTheme';
import { KEY_PAD, Pad } from '@/features/pads/pad';
import { KEY_LIST_PAD } from '@/features/pads/pads-panel';
import { useUpdatePad } from '../api/useUpdatePad';
import IconEdit from '../assets/icon-edit.svg';
import { InputPadName } from './InputPadName';
interface ModalUpdatePadProps {
onClose: () => void;
pad: Pad;
}
export const ModalUpdatePad = ({ onClose, pad }: ModalUpdatePadProps) => {
const { colorsTokens } = useCunninghamTheme();
const [title, setTitle] = useState(pad.title);
const { toast } = useToastProvider();
const [padPublic, setPadPublic] = useState(pad.is_public);
const {
mutate: updatePad,
isError,
isPending,
error,
} = useUpdatePad({
onSuccess: () => {
toast(t('The document has been updated.'), VariantType.SUCCESS, {
duration: 4000,
});
onClose();
},
listInvalideQueries: [KEY_PAD, KEY_LIST_PAD],
});
return (
<Modal
isOpen
closeOnClickOutside
hideCloseButton
leftActions={
<Button
aria-label={t('Close the modal')}
color="secondary"
fullWidth
onClick={() => onClose()}
>
{t('Cancel')}
</Button>
}
onClose={() => onClose()}
rightActions={
<Button
aria-label={t('Validate the modification')}
color="primary"
fullWidth
onClick={() =>
updatePad({
title,
id: pad.id,
is_public: padPublic,
})
}
>
{t('Validate the modification')}
</Button>
}
size={ModalSize.MEDIUM}
title={
<Box $align="center" $gap="1rem">
<IconEdit width={48} color={colorsTokens()['primary-text']} />
<Text as="h2" $size="h3" $margin="none">
{t('Update document "{{documentTitle}}"', {
documentTitle: pad.title,
})}
</Text>
</Box>
}
>
<Box
$margin={{ bottom: 'xl' }}
aria-label={t('Content modal to update the document')}
>
<Text as="p" $margin={{ bottom: 'big' }}>
{t('Enter the new name of the selected document.')}
</Text>
<Box $gap="1rem">
<InputPadName
label={t('Pad name')}
defaultValue={title}
{...{ error, isError, isPending, setPadName: setTitle }}
/>
<Switch
label={t('Is it public ?')}
labelSide="right"
defaultChecked={padPublic}
onChange={() => setPadPublic(!padPublic)}
/>
</Box>
</Box>
</Modal>
);
};

View File

@@ -1 +1,2 @@
export * from './CardCreatePad'; export * from './CardCreatePad';
export * from './ModalUpdatePad';