🐛(frontend) fix versioning conflict
We switching from one version to the other, depending on the blocks inside, the version editor could crash due to conflicts between the different versions. We now reset the previous content when switching version to avoid these conflicts.
This commit is contained in:
@@ -26,6 +26,7 @@ and this project adheres to
|
|||||||
|
|
||||||
- 🐛(frontend) paste content with comments from another document #1732
|
- 🐛(frontend) paste content with comments from another document #1732
|
||||||
- 🐛(frontend) Select text + Go back one page crash the app #1733
|
- 🐛(frontend) Select text + Go back one page crash the app #1733
|
||||||
|
- 🐛(frontend) fix versioning conflict #1742
|
||||||
|
|
||||||
|
|
||||||
## [4.1.0] - 2025-12-09
|
## [4.1.0] - 2025-12-09
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
mockedDocument,
|
mockedDocument,
|
||||||
verifyDocName,
|
verifyDocName,
|
||||||
} from './utils-common';
|
} from './utils-common';
|
||||||
|
import { openSuggestionMenu, writeInEditor } from './utils-editor';
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
@@ -17,6 +18,7 @@ test.describe('Doc Version', () => {
|
|||||||
|
|
||||||
await verifyDocName(page, randomDoc);
|
await verifyDocName(page, randomDoc);
|
||||||
|
|
||||||
|
// Initially, there is no version
|
||||||
await page.getByLabel('Open the document options').click();
|
await page.getByLabel('Open the document options').click();
|
||||||
await page.getByRole('menuitem', { name: 'Version history' }).click();
|
await page.getByRole('menuitem', { name: 'Version history' }).click();
|
||||||
await expect(page.getByText('History', { exact: true })).toBeVisible();
|
await expect(page.getByText('History', { exact: true })).toBeVisible();
|
||||||
@@ -26,31 +28,49 @@ test.describe('Doc Version', () => {
|
|||||||
await expect(panel).toBeVisible();
|
await expect(panel).toBeVisible();
|
||||||
await expect(modal.getByText('No versions')).toBeVisible();
|
await expect(modal.getByText('No versions')).toBeVisible();
|
||||||
|
|
||||||
const editor = page.locator('.ProseMirror');
|
|
||||||
await modal.getByRole('button', { name: 'close' }).click();
|
await modal.getByRole('button', { name: 'close' }).click();
|
||||||
await editor.click();
|
|
||||||
await page.keyboard.type('# Hello World');
|
|
||||||
|
|
||||||
|
await writeInEditor({ page, text: 'Hello World' });
|
||||||
|
|
||||||
|
// It will trigger a save, no version created yet (initial version is not counted)
|
||||||
await goToGridDoc(page, {
|
await goToGridDoc(page, {
|
||||||
title: randomDoc,
|
title: randomDoc,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(
|
await expect(page.getByText('Hello World')).toBeVisible();
|
||||||
page.getByRole('heading', { name: 'Hello World' }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
await page
|
// Write more
|
||||||
.locator('.ProseMirror .bn-block')
|
await writeInEditor({ page, text: 'It will create a version' });
|
||||||
.getByRole('heading', { name: 'Hello World' })
|
|
||||||
.fill('It will create a version');
|
|
||||||
|
|
||||||
|
await openSuggestionMenu({ page });
|
||||||
|
await page.getByText('Add a callout block').click();
|
||||||
|
|
||||||
|
const calloutBlock = page
|
||||||
|
.locator('div[data-content-type="callout"]')
|
||||||
|
.first();
|
||||||
|
|
||||||
|
await expect(calloutBlock).toBeVisible();
|
||||||
|
|
||||||
|
// It will trigger a save and create a version this time
|
||||||
await goToGridDoc(page, {
|
await goToGridDoc(page, {
|
||||||
title: randomDoc,
|
title: randomDoc,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(page.getByText('Hello World')).toBeHidden();
|
await expect(page.getByText('Hello World')).toBeHidden();
|
||||||
|
await expect(page.getByText('It will create a version')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(calloutBlock).toBeVisible();
|
||||||
|
|
||||||
|
// Write more
|
||||||
|
await writeInEditor({ page, text: 'It will create a second version' });
|
||||||
|
|
||||||
|
// It will trigger a save and create a second version
|
||||||
|
await goToGridDoc(page, {
|
||||||
|
title: randomDoc,
|
||||||
|
});
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('heading', { name: 'It will create a version' }),
|
page.getByText('It will create a second version'),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
|
|
||||||
await page.getByLabel('Open the document options').click();
|
await page.getByLabel('Open the document options').click();
|
||||||
@@ -60,11 +80,33 @@ test.describe('Doc Version', () => {
|
|||||||
await expect(page.getByText('History', { exact: true })).toBeVisible();
|
await expect(page.getByText('History', { exact: true })).toBeVisible();
|
||||||
await expect(page.getByRole('status')).toBeHidden();
|
await expect(page.getByRole('status')).toBeHidden();
|
||||||
const items = await panel.locator('.version-item').all();
|
const items = await panel.locator('.version-item').all();
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(2);
|
||||||
await items[0].click();
|
await items[1].click();
|
||||||
|
|
||||||
await expect(modal.getByText('Hello World')).toBeVisible();
|
await expect(modal.getByText('Hello World')).toBeVisible();
|
||||||
await expect(modal.getByText('It will create a version')).toBeHidden();
|
await expect(modal.getByText('It will create a version')).toBeHidden();
|
||||||
|
await expect(
|
||||||
|
modal.locator('div[data-content-type="callout"]').first(),
|
||||||
|
).toBeHidden();
|
||||||
|
|
||||||
|
await items[0].click();
|
||||||
|
|
||||||
|
await expect(modal.getByText('Hello World')).toBeVisible();
|
||||||
|
await expect(modal.getByText('It will create a version')).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
modal.locator('div[data-content-type="callout"]').first(),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
modal.getByText('It will create a second version'),
|
||||||
|
).toBeHidden();
|
||||||
|
|
||||||
|
await items[1].click();
|
||||||
|
|
||||||
|
await expect(modal.getByText('Hello World')).toBeVisible();
|
||||||
|
await expect(modal.getByText('It will create a version')).toBeHidden();
|
||||||
|
await expect(
|
||||||
|
modal.locator('div[data-content-type="callout"]').first(),
|
||||||
|
).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it does not display the doc versions if not allowed', async ({
|
test('it does not display the doc versions if not allowed', async ({
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ export function useDocVersionsInfiniteQuery(
|
|||||||
getNextPageParam(lastPage) {
|
getNextPageParam(lastPage) {
|
||||||
return lastPage.next_version_id_marker || undefined;
|
return lastPage.next_version_id_marker || undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
...queryConfig,
|
...queryConfig,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,18 @@ export const DocVersionEditor = ({
|
|||||||
const { replace } = useRouter();
|
const { replace } = useRouter();
|
||||||
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();
|
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();
|
||||||
|
|
||||||
|
// Reset initialContent when versionId changes to avoid conflicts between versions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!version?.content) {
|
setInitialContent(undefined);
|
||||||
|
}, [versionId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!version?.content || isLoading || initialContent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
|
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
|
||||||
}, [version?.content]);
|
}, [versionId, version?.content, isLoading, initialContent]);
|
||||||
|
|
||||||
if (isError && error) {
|
if (isError && error) {
|
||||||
if (error.status === 404) {
|
if (error.status === 404) {
|
||||||
|
|||||||
Reference in New Issue
Block a user