✨(frontend) update document
We can now update a pad from a modal.
This commit is contained in:
@@ -28,6 +28,7 @@ export const createPad = async (
|
||||
padName: string,
|
||||
browserName: string,
|
||||
length: number,
|
||||
isPublic: boolean = false,
|
||||
) => {
|
||||
const panel = page.getByLabel('Pads panel').first();
|
||||
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++) {
|
||||
await panel.getByRole('button', { name: 'Add a pad' }).click();
|
||||
await page.getByText('Pad name').fill(randomPads[i]);
|
||||
|
||||
if (isPublic) {
|
||||
await page.getByText('Is it public ?').click();
|
||||
}
|
||||
|
||||
await expect(buttonCreate).toBeEnabled();
|
||||
await buttonCreate.click();
|
||||
await expect(panel.locator('li').getByText(randomPads[i])).toBeVisible();
|
||||
|
||||
@@ -47,4 +47,59 @@ test.describe('Pad Tools', () => {
|
||||
expect(pdfText).toContain('La directrice'); // This is the template 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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, DropButton, IconOptions, Text } from '@/components';
|
||||
import { Pad } from '@/features/pads/pad';
|
||||
import { ModalUpdatePad } from '@/features/pads/pads-create';
|
||||
|
||||
import { TemplatesOrdering, useTemplates } from '../api/useTemplates';
|
||||
|
||||
@@ -18,6 +19,7 @@ export const PadToolBox = ({ pad }: PadToolBoxProps) => {
|
||||
const { data: templates } = useTemplates({
|
||||
ordering: TemplatesOrdering.BY_CREATED_ON_DESC,
|
||||
});
|
||||
const [isModalUpdateOpen, setIsModalUpdateOpen] = useState(false);
|
||||
const [isModalPDFOpen, setIsModalPDFOpen] = useState(false);
|
||||
const [isDropOpen, setIsDropOpen] = useState(false);
|
||||
|
||||
@@ -44,13 +46,23 @@ export const PadToolBox = ({ pad }: PadToolBoxProps) => {
|
||||
button={
|
||||
<IconOptions
|
||||
isOpen={isDropOpen}
|
||||
aria-label={t('Open the team options')}
|
||||
aria-label={t('Open the document options')}
|
||||
/>
|
||||
}
|
||||
onOpenChange={(isOpen) => setIsDropOpen(isOpen)}
|
||||
isOpen={isDropOpen}
|
||||
>
|
||||
<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
|
||||
onClick={() => {
|
||||
setIsModalPDFOpen(true);
|
||||
@@ -70,6 +82,9 @@ export const PadToolBox = ({ pad }: PadToolBoxProps) => {
|
||||
pad={pad}
|
||||
/>
|
||||
)}
|
||||
{isModalUpdateOpen && (
|
||||
<ModalUpdatePad onClose={() => setIsModalUpdateOpen(false)} pad={pad} />
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 |
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
export * from './CardCreatePad';
|
||||
export * from './ModalUpdatePad';
|
||||
|
||||
Reference in New Issue
Block a user