Skip to content

Commit accbda4

Browse files
committed
♻️(frontend) open version panel from docs options
Versions panel is a feature that will not be used by all users, so it should be hidden by default. The user can open it from the docs options.
1 parent f2a78ad commit accbda4

File tree

7 files changed

+203
-25
lines changed

7 files changed

+203
-25
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
import { createDoc, goToGridDoc, mockedDocument } from './common';
4+
5+
test.beforeEach(async ({ page }) => {
6+
await page.goto('/');
7+
});
8+
9+
test.describe('Doc Version', () => {
10+
test('it displays the doc versions', async ({ page, browserName }) => {
11+
const [randomDoc] = await createDoc(page, 'doc-version', browserName, 1);
12+
13+
await expect(page.locator('h2').getByText(randomDoc)).toBeVisible();
14+
15+
await page.getByLabel('Open the document options').click();
16+
await page
17+
.getByRole('button', {
18+
name: 'Version history',
19+
})
20+
.click();
21+
22+
const panel = page.getByLabel('Document version panel');
23+
24+
await expect(panel.getByText('Current version')).toBeVisible();
25+
expect(await panel.locator('li').count()).toBe(1);
26+
27+
await page.locator('.ProseMirror.bn-editor').click();
28+
await page.locator('.ProseMirror.bn-editor').last().fill('Hello World');
29+
30+
await goToGridDoc(page, {
31+
title: randomDoc,
32+
});
33+
34+
await expect(page.getByText('Hello World')).toBeVisible();
35+
36+
await page
37+
.locator('.ProseMirror .bn-block')
38+
.getByText('Hello World')
39+
.fill('It will create a version');
40+
41+
await goToGridDoc(page, {
42+
title: randomDoc,
43+
});
44+
45+
await expect(page.getByText('Hello World')).toBeHidden();
46+
await expect(page.getByText('It will create a version')).toBeVisible();
47+
48+
await expect(panel.getByText('Current version')).toBeVisible();
49+
expect(await panel.locator('li').count()).toBe(2);
50+
51+
await panel.locator('li').nth(1).click();
52+
await expect(
53+
page.getByText('Read only, you cannot edit document versions.'),
54+
).toBeVisible();
55+
await expect(page.getByText('Hello World')).toBeVisible();
56+
await expect(page.getByText('It will create a version')).toBeHidden();
57+
58+
await panel.getByText('Current version').click();
59+
await expect(page.getByText('Hello World')).toBeHidden();
60+
await expect(page.getByText('It will create a version')).toBeVisible();
61+
});
62+
63+
test('it does not display the doc versions if not allowed', async ({
64+
page,
65+
}) => {
66+
await mockedDocument(page, {
67+
abilities: {
68+
versions_list: false,
69+
partial_update: true,
70+
},
71+
});
72+
73+
await goToGridDoc(page);
74+
75+
await expect(page.locator('h2').getByText('Mocked document')).toBeVisible();
76+
77+
await page.getByLabel('Open the document options').click();
78+
await expect(
79+
page.getByRole('button', { name: 'Version history' }),
80+
).toBeHidden();
81+
82+
await expect(page.getByLabel('Document version panel')).toBeHidden();
83+
});
84+
85+
test('it restores the doc version', async ({ page, browserName }) => {
86+
const [randomDoc] = await createDoc(page, 'doc-version', browserName, 1);
87+
88+
await expect(page.locator('h2').getByText(randomDoc)).toBeVisible();
89+
90+
await page.locator('.bn-block-outer').last().click();
91+
await page.locator('.bn-block-outer').last().fill('Hello');
92+
93+
await goToGridDoc(page, {
94+
title: randomDoc,
95+
});
96+
97+
await expect(page.getByText('Hello')).toBeVisible();
98+
await page.locator('.bn-block-outer').last().click();
99+
await page.keyboard.press('Enter');
100+
await page.locator('.bn-block-outer').last().fill('World');
101+
102+
await goToGridDoc(page, {
103+
title: randomDoc,
104+
});
105+
106+
await expect(page.getByText('World')).toBeVisible();
107+
108+
await page.getByLabel('Open the document options').click();
109+
await page
110+
.getByRole('button', {
111+
name: 'Version history',
112+
})
113+
.click();
114+
115+
const panel = page.getByLabel('Document version panel');
116+
await panel.locator('li').nth(1).click();
117+
await expect(page.getByText('World')).toBeHidden();
118+
119+
await panel.getByLabel('Open the version options').click();
120+
await page.getByText('Restore the version').click();
121+
122+
await expect(panel.locator('li')).toHaveCount(3);
123+
124+
await panel.getByText('Current version').click();
125+
await expect(page.getByText('Hello')).toBeVisible();
126+
await expect(page.getByText('World')).toBeHidden();
127+
});
128+
});

src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import { Box, Card, Text, TextErrors } from '@/components';
88
import { useCunninghamTheme } from '@/cunningham';
99
import { DocHeader } from '@/features/docs/doc-header';
1010
import { Doc } from '@/features/docs/doc-management';
11-
import { Versions, useDocVersion } from '@/features/docs/doc-versioning/';
11+
import {
12+
Panel,
13+
Versions,
14+
useDocVersion,
15+
useDocVersionStore,
16+
} from '@/features/docs/doc-versioning/';
1217

1318
import { BlockNoteEditor } from './BlockNoteEditor';
1419

@@ -20,6 +25,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
2025
const {
2126
query: { versionId },
2227
} = useRouter();
28+
const { isPanelOpen } = useDocVersionStore();
2329

2430
const { t } = useTranslation();
2531

@@ -58,6 +64,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
5864
<BlockNoteEditor doc={doc} />
5965
)}
6066
</Card>
67+
{doc.abilities.versions_list && isPanelOpen && <Panel doc={doc} />}
6168
</Box>
6269
</>
6370
);

src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ModalShare,
1010
ModalUpdateDoc,
1111
} from '@/features/docs/doc-management';
12+
import { useDocVersionStore } from '@/features/docs/doc-versioning';
1213

1314
import { ModalPDF } from './ModalExport';
1415

@@ -23,6 +24,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
2324
const [isModalRemoveOpen, setIsModalRemoveOpen] = useState(false);
2425
const [isModalPDFOpen, setIsModalPDFOpen] = useState(false);
2526
const [isDropOpen, setIsDropOpen] = useState(false);
27+
const { setIsPanelOpen } = useDocVersionStore();
2628

2729
return (
2830
<Box
@@ -77,6 +79,19 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
7779
<Text $theme="primary">{t('Delete document')}</Text>
7880
</Button>
7981
)}
82+
{doc.abilities.versions_list && (
83+
<Button
84+
onClick={() => {
85+
setIsPanelOpen(true);
86+
setIsDropOpen(false);
87+
}}
88+
color="primary-text"
89+
icon={<span className="material-icons">history</span>}
90+
size="small"
91+
>
92+
<Text $theme="primary">{t('Version history')}</Text>
93+
</Button>
94+
)}
8095
<Button
8196
onClick={() => {
8297
setIsModalPDFOpen(true);

src/frontend/apps/impress/src/features/docs/doc-versioning/components/Panel.tsx

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import React, { useState } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import { useTranslation } from 'react-i18next';
33

44
import { Box, Card, IconBG, Text } from '@/components';
55
import { useCunninghamTheme } from '@/cunningham';
66
import { Doc } from '@/features/docs/doc-management';
77

8+
import { useDocVersionStore } from '../stores';
9+
810
import { VersionList } from './VersionList';
911

1012
interface PanelProps {
@@ -14,8 +16,13 @@ interface PanelProps {
1416
export const Panel = ({ doc }: PanelProps) => {
1517
const { t } = useTranslation();
1618
const { colorsTokens } = useCunninghamTheme();
19+
const { setIsPanelOpen } = useDocVersionStore();
20+
21+
const [isOpen, setIsOpen] = useState(false);
1722

18-
const [isOpen, setIsOpen] = useState(true);
23+
useEffect(() => {
24+
setIsOpen(true);
25+
}, []);
1926

2027
const closedOverridingStyles = !isOpen && {
2128
$width: '0',
@@ -46,28 +53,6 @@ export const Panel = ({ doc }: PanelProps) => {
4653
aria-label={t('Document version panel')}
4754
{...closedOverridingStyles}
4855
>
49-
<IconBG
50-
iconName="menu_open"
51-
aria-label={
52-
isOpen
53-
? t('Close the document version panel')
54-
: t('Open the document version panel')
55-
}
56-
$background="transparent"
57-
$size="h2"
58-
$zIndex={1}
59-
$css={`
60-
cursor: pointer;
61-
left: ${isOpen ? '0' : '-3.3'}rem;
62-
top: 0.1rem;
63-
transform: rotate(${isOpen ? '180' : '0'}deg);
64-
transition: ${transition};
65-
user-select: none;
66-
`}
67-
$position="absolute"
68-
onClick={() => setIsOpen(!isOpen)}
69-
$radius="2px"
70-
/>
7156
<Box
7257
$overflow="hidden"
7358
$css={`
@@ -82,6 +67,34 @@ export const Panel = ({ doc }: PanelProps) => {
8267
$justify="center"
8368
$css={`border-top: 2px solid ${colorsTokens()['primary-600']};`}
8469
>
70+
<IconBG
71+
iconName="menu_open"
72+
aria-label={
73+
isOpen
74+
? t('Close the document version panel')
75+
: t('Open the document version panel')
76+
}
77+
$background="transparent"
78+
$size="h2"
79+
$zIndex={1}
80+
$css={`
81+
cursor: pointer;
82+
left: 0rem;
83+
top: 0.1rem;
84+
transition: ${transition};
85+
transform: rotate(180deg);
86+
opacity: ${isOpen ? '1' : '0'};
87+
user-select: none;
88+
`}
89+
$position="absolute"
90+
onClick={() => {
91+
setIsOpen(false);
92+
setTimeout(() => {
93+
setIsPanelOpen(false);
94+
}, 400);
95+
}}
96+
$radius="2px"
97+
/>
8598
<Text $weight="bold" $size="l" $theme="primary">
8699
{t('VERSIONS')}
87100
</Text>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './api';
22
export * from './components';
3+
export * from './stores';
34
export * from './types';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './useDocVersionStore';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { create } from 'zustand';
2+
3+
export interface UseDocVersionStore {
4+
isPanelOpen: boolean;
5+
setIsPanelOpen: (isOpen: boolean) => void;
6+
}
7+
8+
export const useDocVersionStore = create<UseDocVersionStore>((set) => ({
9+
isPanelOpen: false,
10+
setIsPanelOpen: (isPanelOpen) => {
11+
set(() => ({ isPanelOpen }));
12+
},
13+
}));

0 commit comments

Comments
 (0)