diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts
new file mode 100644
index 00000000..330c989c
--- /dev/null
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts
@@ -0,0 +1,128 @@
+import { expect, test } from '@playwright/test';
+
+import { createDoc, goToGridDoc, mockedDocument } from './common';
+
+test.beforeEach(async ({ page }) => {
+ await page.goto('/');
+});
+
+test.describe('Doc Version', () => {
+ test('it displays the doc versions', async ({ page, browserName }) => {
+ const [randomDoc] = await createDoc(page, 'doc-version', browserName, 1);
+
+ await expect(page.locator('h2').getByText(randomDoc)).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 expect(panel.getByText('Current version')).toBeVisible();
+ expect(await panel.locator('li').count()).toBe(1);
+
+ await page.locator('.ProseMirror.bn-editor').click();
+ await page.locator('.ProseMirror.bn-editor').last().fill('Hello World');
+
+ await goToGridDoc(page, {
+ title: randomDoc,
+ });
+
+ await expect(page.getByText('Hello World')).toBeVisible();
+
+ await page
+ .locator('.ProseMirror .bn-block')
+ .getByText('Hello World')
+ .fill('It will create a version');
+
+ await goToGridDoc(page, {
+ title: randomDoc,
+ });
+
+ await expect(page.getByText('Hello World')).toBeHidden();
+ await expect(page.getByText('It will create a version')).toBeVisible();
+
+ await expect(panel.getByText('Current version')).toBeVisible();
+ expect(await panel.locator('li').count()).toBe(2);
+
+ await panel.locator('li').nth(1).click();
+ await expect(
+ page.getByText('Read only, you cannot edit document versions.'),
+ ).toBeVisible();
+ await expect(page.getByText('Hello World')).toBeVisible();
+ await expect(page.getByText('It will create a version')).toBeHidden();
+
+ await panel.getByText('Current version').click();
+ await expect(page.getByText('Hello World')).toBeHidden();
+ await expect(page.getByText('It will create a version')).toBeVisible();
+ });
+
+ test('it does not display the doc versions if not allowed', async ({
+ page,
+ }) => {
+ await mockedDocument(page, {
+ abilities: {
+ versions_list: false,
+ partial_update: true,
+ },
+ });
+
+ await goToGridDoc(page);
+
+ await expect(page.locator('h2').getByText('Mocked document')).toBeVisible();
+
+ await page.getByLabel('Open the document options').click();
+ await expect(
+ page.getByRole('button', { name: 'Version history' }),
+ ).toBeHidden();
+
+ await expect(page.getByLabel('Document version panel')).toBeHidden();
+ });
+
+ test('it restores the doc version', 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 panel.getByLabel('Open the version options').click();
+ await page.getByText('Restore the version').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();
+ });
+});
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx
index 1d8d2428..48b8a96e 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx
@@ -8,7 +8,12 @@ import { Box, Card, Text, TextErrors } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { DocHeader } from '@/features/docs/doc-header';
import { Doc } from '@/features/docs/doc-management';
-import { Versions, useDocVersion } from '@/features/docs/doc-versioning/';
+import {
+ Panel,
+ Versions,
+ useDocVersion,
+ useDocVersionStore,
+} from '@/features/docs/doc-versioning/';
import { BlockNoteEditor } from './BlockNoteEditor';
@@ -20,6 +25,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
const {
query: { versionId },
} = useRouter();
+ const { isPanelOpen } = useDocVersionStore();
const { t } = useTranslation();
@@ -58,6 +64,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
)}
+ {doc.abilities.versions_list && isPanelOpen && }
>
);
diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx
index 9ea72241..359564aa 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx
@@ -9,6 +9,7 @@ import {
ModalShare,
ModalUpdateDoc,
} from '@/features/docs/doc-management';
+import { useDocVersionStore } from '@/features/docs/doc-versioning';
import { ModalPDF } from './ModalExport';
@@ -23,6 +24,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
const [isModalRemoveOpen, setIsModalRemoveOpen] = useState(false);
const [isModalPDFOpen, setIsModalPDFOpen] = useState(false);
const [isDropOpen, setIsDropOpen] = useState(false);
+ const { setIsPanelOpen } = useDocVersionStore();
return (
{
{t('Delete document')}
)}
+ {doc.abilities.versions_list && (
+
+ )}