⚗️(frontend) add button Restore this version near title
When a user is on a page version, we will display a button "Restore this version" near the title of the page. It gives an obvious way to restore the version of the doc.
This commit is contained in:
@@ -13,6 +13,7 @@ and this project adheres to
|
|||||||
|
|
||||||
- ✨Add image attachments with access control
|
- ✨Add image attachments with access control
|
||||||
- ✨(frontend) Upload image to a document #211
|
- ✨(frontend) Upload image to a document #211
|
||||||
|
- ✨(frontend) Versions #217
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
|
|||||||
@@ -133,4 +133,62 @@ test.describe('Doc Version', () => {
|
|||||||
await expect(page.getByText('Hello')).toBeVisible();
|
await expect(page.getByText('Hello')).toBeVisible();
|
||||||
await expect(page.getByText('World')).toBeHidden();
|
await expect(page.getByText('World')).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it restores the doc version from button title', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
const [randomDoc] = await createDoc(page, 'doc-version', browserName, 1);
|
||||||
|
|
||||||
|
await expect(page.locator('h2').getByText(randomDoc)).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.bn-block-outer').last().click();
|
||||||
|
await page.locator('.bn-block-outer').last().fill('Hello');
|
||||||
|
|
||||||
|
await goToGridDoc(page, {
|
||||||
|
title: randomDoc,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(page.getByText('Hello')).toBeVisible();
|
||||||
|
await page.locator('.bn-block-outer').last().click();
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.locator('.bn-block-outer').last().fill('World');
|
||||||
|
|
||||||
|
await goToGridDoc(page, {
|
||||||
|
title: randomDoc,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(page.getByText('World')).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByLabel('Open the document options').click();
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Version history',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const panel = page.getByLabel('Document version panel');
|
||||||
|
await panel.locator('li').nth(1).click();
|
||||||
|
await expect(page.getByText('World')).toBeHidden();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Restore this version',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Restore this version?')).toBeVisible();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Restore',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(panel.locator('li')).toHaveCount(3);
|
||||||
|
|
||||||
|
await panel.getByText('Current version').click();
|
||||||
|
await expect(page.getByText('Hello')).toBeVisible();
|
||||||
|
await expect(page.getByText('World')).toBeHidden();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DocHeader doc={doc} />
|
<DocHeader doc={doc} versionId={versionId as Versions['version_id']} />
|
||||||
{!doc.abilities.partial_update && (
|
{!doc.abilities.partial_update && (
|
||||||
<Box $margin={{ all: 'small', top: 'none' }}>
|
<Box $margin={{ all: 'small', top: 'none' }}>
|
||||||
<Alert type={VariantType.WARNING}>
|
<Alert type={VariantType.WARNING}>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { Fragment } from 'react';
|
import { Button } from '@openfun/cunningham-react';
|
||||||
|
import React, { Fragment, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { Box, Card, StyledLink, Text } from '@/components';
|
import { Box, Card, StyledLink, Text } from '@/components';
|
||||||
@@ -9,96 +10,124 @@ import {
|
|||||||
currentDocRole,
|
currentDocRole,
|
||||||
useTransRole,
|
useTransRole,
|
||||||
} from '@/features/docs/doc-management';
|
} from '@/features/docs/doc-management';
|
||||||
|
import { ModalVersion, Versions } from '@/features/docs/doc-versioning';
|
||||||
import { useDate } from '@/hook';
|
import { useDate } from '@/hook';
|
||||||
|
|
||||||
import { DocToolBox } from './DocToolBox';
|
import { DocToolBox } from './DocToolBox';
|
||||||
|
|
||||||
interface DocHeaderProps {
|
interface DocHeaderProps {
|
||||||
doc: Doc;
|
doc: Doc;
|
||||||
|
versionId?: Versions['version_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DocHeader = ({ doc }: DocHeaderProps) => {
|
export const DocHeader = ({ doc, versionId }: DocHeaderProps) => {
|
||||||
const { colorsTokens } = useCunninghamTheme();
|
const { colorsTokens } = useCunninghamTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { formatDate } = useDate();
|
const { formatDate } = useDate();
|
||||||
const transRole = useTransRole();
|
const transRole = useTransRole();
|
||||||
|
const [isModalVersionOpen, setIsModalVersionOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<>
|
||||||
$margin="small"
|
<Card
|
||||||
aria-label={t('It is the card information about the document.')}
|
$margin="small"
|
||||||
>
|
aria-label={t('It is the card information about the document.')}
|
||||||
<Box $padding="small" $direction="row" $align="center">
|
|
||||||
<StyledLink href="/">
|
|
||||||
<Text
|
|
||||||
$isMaterialIcon
|
|
||||||
$theme="primary"
|
|
||||||
$size="2rem"
|
|
||||||
$css={`&:hover {background-color: ${colorsTokens()['primary-100']}; };`}
|
|
||||||
$hasTransition
|
|
||||||
$radius="5px"
|
|
||||||
$padding="tiny"
|
|
||||||
>
|
|
||||||
home
|
|
||||||
</Text>
|
|
||||||
</StyledLink>
|
|
||||||
<Box
|
|
||||||
$width="1px"
|
|
||||||
$height="70%"
|
|
||||||
$background={colorsTokens()['greyscale-100']}
|
|
||||||
$margin={{ horizontal: 'small' }}
|
|
||||||
/>
|
|
||||||
<Text as="h2" $align="center" $margin={{ all: 'none', left: 'tiny' }}>
|
|
||||||
{doc.title}
|
|
||||||
</Text>
|
|
||||||
<DocToolBox doc={doc} />
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
$direction="row"
|
|
||||||
$align="center"
|
|
||||||
$css="border-top:1px solid #eee"
|
|
||||||
$padding={{ horizontal: 'big', vertical: 'tiny' }}
|
|
||||||
$gap="0.5rem 2rem"
|
|
||||||
$justify="space-between"
|
|
||||||
$wrap="wrap"
|
|
||||||
>
|
>
|
||||||
<Box $direction="row" $align="center" $gap="0.5rem 2rem" $wrap="wrap">
|
<Box $padding="small" $direction="row" $align="center">
|
||||||
{doc.is_public && (
|
<StyledLink href="/">
|
||||||
<Text
|
<Text
|
||||||
$weight="bold"
|
$isMaterialIcon
|
||||||
$background={colorsTokens()['primary-600']}
|
$theme="primary"
|
||||||
$color="white"
|
$size="2rem"
|
||||||
$padding="xtiny"
|
$css={`&:hover {background-color: ${colorsTokens()['primary-100']}; };`}
|
||||||
$radius="3px"
|
$hasTransition
|
||||||
$size="s"
|
$radius="5px"
|
||||||
|
$padding="tiny"
|
||||||
>
|
>
|
||||||
{t('Public')}
|
home
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
</StyledLink>
|
||||||
|
<Box
|
||||||
|
$width="1px"
|
||||||
|
$height="70%"
|
||||||
|
$background={colorsTokens()['greyscale-100']}
|
||||||
|
$margin={{ horizontal: 'small' }}
|
||||||
|
/>
|
||||||
|
<Box $gap="1rem" $direction="row">
|
||||||
|
<Text
|
||||||
|
as="h2"
|
||||||
|
$align="center"
|
||||||
|
$margin={{ all: 'none', left: 'tiny' }}
|
||||||
|
>
|
||||||
|
{doc.title}
|
||||||
|
</Text>
|
||||||
|
{versionId && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setIsModalVersionOpen(true);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{t('Restore this version')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<DocToolBox doc={doc} />
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
$direction="row"
|
||||||
|
$align="center"
|
||||||
|
$css="border-top:1px solid #eee"
|
||||||
|
$padding={{ horizontal: 'big', vertical: 'tiny' }}
|
||||||
|
$gap="0.5rem 2rem"
|
||||||
|
$justify="space-between"
|
||||||
|
$wrap="wrap"
|
||||||
|
>
|
||||||
|
<Box $direction="row" $align="center" $gap="0.5rem 2rem" $wrap="wrap">
|
||||||
|
{doc.is_public && (
|
||||||
|
<Text
|
||||||
|
$weight="bold"
|
||||||
|
$background={colorsTokens()['primary-600']}
|
||||||
|
$color="white"
|
||||||
|
$padding="xtiny"
|
||||||
|
$radius="3px"
|
||||||
|
$size="s"
|
||||||
|
>
|
||||||
|
{t('Public')}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
<Text $size="s" $display="inline">
|
||||||
|
{t('Created at')} <strong>{formatDate(doc.created_at)}</strong>
|
||||||
|
</Text>
|
||||||
|
<Text $size="s" $display="inline" $elipsis $maxWidth="60vw">
|
||||||
|
{t('Owners:')}{' '}
|
||||||
|
<strong>
|
||||||
|
{doc.accesses
|
||||||
|
.filter(
|
||||||
|
(access) => access.role === Role.OWNER && access.user.email,
|
||||||
|
)
|
||||||
|
.map((access, index, accesses) => (
|
||||||
|
<Fragment key={`access-${index}`}>
|
||||||
|
{access.user.email}{' '}
|
||||||
|
{index < accesses.length - 1 ? ' / ' : ''}
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</strong>
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
<Text $size="s" $display="inline">
|
<Text $size="s" $display="inline">
|
||||||
{t('Created at')} <strong>{formatDate(doc.created_at)}</strong>
|
{t('Your role:')}{' '}
|
||||||
</Text>
|
<strong>{transRole(currentDocRole(doc.abilities))}</strong>
|
||||||
<Text $size="s" $display="inline" $elipsis $maxWidth="60vw">
|
|
||||||
{t('Owners:')}{' '}
|
|
||||||
<strong>
|
|
||||||
{doc.accesses
|
|
||||||
.filter(
|
|
||||||
(access) => access.role === Role.OWNER && access.user.email,
|
|
||||||
)
|
|
||||||
.map((access, index, accesses) => (
|
|
||||||
<Fragment key={`access-${index}`}>
|
|
||||||
{access.user.email}{' '}
|
|
||||||
{index < accesses.length - 1 ? ' / ' : ''}
|
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</strong>
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Text $size="s" $display="inline">
|
</Card>
|
||||||
{t('Your role:')}{' '}
|
{isModalVersionOpen && versionId && (
|
||||||
<strong>{transRole(currentDocRole(doc.abilities))}</strong>
|
<ModalVersion
|
||||||
</Text>
|
onClose={() => setIsModalVersionOpen(false)}
|
||||||
</Box>
|
docId={doc.id}
|
||||||
</Card>
|
versionId={versionId}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
export * from './ModalVersion';
|
||||||
export * from './Panel';
|
export * from './Panel';
|
||||||
|
|||||||
Reference in New Issue
Block a user