Skip to content

Commit f606826

Browse files
committed
♻️(frontend) stop to use provider with version
Version are not editable, we don't need to activate the collaboration provider for them. Simplify the code by removing the provider from the version.
1 parent aff036d commit f606826

File tree

7 files changed

+108
-52
lines changed

7 files changed

+108
-52
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to
1919
- 🔨(frontend) encapsulated title to its own component #474
2020
- 🐛(frontend) Fix hidden menu on Firefox #468
2121
- ⚡️(backend) optimize number of queries on document list view #411
22+
- ♻️(frontend) stop to use provider with version #480
2223
- 🚚(collaboration) change the websocket key name #480
2324

2425

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

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useCreateBlockNote } from '@blocknote/react';
66
import { HocuspocusProvider } from '@hocuspocus/provider';
77
import React, { useEffect } from 'react';
88
import { useTranslation } from 'react-i18next';
9+
import * as Y from 'yjs';
910

1011
import { Box, TextErrors } from '@/components';
1112
import { useAuthStore } from '@/core/auth';
@@ -65,19 +66,14 @@ const cssEditor = (readonly: boolean) => `
6566
interface BlockNoteEditorProps {
6667
doc: Doc;
6768
provider: HocuspocusProvider;
68-
storeId: string;
6969
}
7070

71-
export const BlockNoteEditor = ({
72-
doc,
73-
provider,
74-
storeId,
75-
}: BlockNoteEditorProps) => {
76-
const isVersion = doc.id !== storeId;
71+
export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
7772
const { userData } = useAuthStore();
7873
const { setEditor } = useEditorStore();
7974
const { t } = useTranslation();
80-
const readOnly = !doc.abilities.partial_update || isVersion;
75+
76+
const readOnly = !doc.abilities.partial_update;
8177
useSaveDoc(doc.id, provider.document, !readOnly);
8278
const { setHeadings, resetHeadings } = useHeadingStore();
8379
const { i18n } = useTranslation();
@@ -174,3 +170,46 @@ export const BlockNoteEditor = ({
174170
</Box>
175171
);
176172
};
173+
174+
interface BlockNoteEditorVersionProps {
175+
initialContent: Y.XmlFragment;
176+
}
177+
178+
export const BlockNoteEditorVersion = ({
179+
initialContent,
180+
}: BlockNoteEditorVersionProps) => {
181+
const readOnly = true;
182+
const { setHeadings, resetHeadings } = useHeadingStore();
183+
184+
const editor = useCreateBlockNote(
185+
{
186+
collaboration: {
187+
fragment: initialContent,
188+
user: {
189+
name: '',
190+
color: '',
191+
},
192+
provider: undefined,
193+
},
194+
},
195+
[initialContent],
196+
);
197+
198+
useEffect(() => {
199+
setHeadings(editor);
200+
201+
editor?.onEditorContentChange(() => {
202+
setHeadings(editor);
203+
});
204+
205+
return () => {
206+
resetHeadings();
207+
};
208+
}, [editor, resetHeadings, setHeadings]);
209+
210+
return (
211+
<Box $css={cssEditor(readOnly)}>
212+
<BlockNoteView editor={editor} editable={!readOnly} theme="light" />
213+
</Box>
214+
);
215+
};

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

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import { Alert, Loader, VariantType } from '@openfun/cunningham-react';
22
import { useRouter } from 'next/router';
3-
import React, { useEffect } from 'react';
3+
import React, { useEffect, useState } from 'react';
44
import { useTranslation } from 'react-i18next';
5+
import * as Y from 'yjs';
56

67
import { Box, Card, Text, TextErrors } from '@/components';
7-
import { useCollaborationUrl } from '@/core';
88
import { useCunninghamTheme } from '@/cunningham';
99
import { DocHeader } from '@/features/docs/doc-header';
10-
import { Doc, useDocStore } from '@/features/docs/doc-management';
10+
import {
11+
Doc,
12+
base64ToBlocknoteXmlFragment,
13+
useDocStore,
14+
} from '@/features/docs/doc-management';
1115
import { Versions, useDocVersion } from '@/features/docs/doc-versioning/';
1216
import { useResponsiveStore } from '@/stores';
1317

1418
import { useHeadingStore } from '../stores';
1519

16-
import { BlockNoteEditor } from './BlockNoteEditor';
20+
import { BlockNoteEditor, BlockNoteEditorVersion } from './BlockNoteEditor';
1721
import { IconOpenPanelEditor, PanelEditor } from './PanelEditor';
1822

1923
interface DocEditorProps {
@@ -41,7 +45,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
4145

4246
return (
4347
<>
44-
<DocHeader doc={doc} versionId={versionId as Versions['version_id']} />
48+
<DocHeader doc={doc} />
4549
{!doc.abilities.partial_update && (
4650
<Box $margin={{ all: 'small', top: 'none' }}>
4751
<Alert type={VariantType.WARNING}>
@@ -71,9 +75,9 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
7175
$position="relative"
7276
>
7377
{isVersion ? (
74-
<DocVersionEditor doc={doc} versionId={versionId} />
78+
<DocVersionEditor docId={doc.id} versionId={versionId} />
7579
) : (
76-
<BlockNoteEditor doc={doc} storeId={doc.id} provider={provider} />
80+
<BlockNoteEditor doc={doc} provider={provider} />
7781
)}
7882
{!isMobile && <IconOpenPanelEditor headings={headings} />}
7983
</Card>
@@ -84,35 +88,34 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
8488
};
8589

8690
interface DocVersionEditorProps {
87-
doc: Doc;
91+
docId: Doc['id'];
8892
versionId: Versions['version_id'];
8993
}
9094

91-
export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => {
95+
export const DocVersionEditor = ({
96+
docId,
97+
versionId,
98+
}: DocVersionEditorProps) => {
9299
const {
93100
data: version,
94101
isLoading,
95102
isError,
96103
error,
97104
} = useDocVersion({
98-
docId: doc.id,
105+
docId,
99106
versionId,
100107
});
101-
const { createProvider, providers } = useDocStore();
102-
const collaborationUrl = useCollaborationUrl(versionId);
103108

104109
const { replace } = useRouter();
110+
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();
105111

106112
useEffect(() => {
107-
if (!version?.id || !collaborationUrl) {
113+
if (!version?.content) {
108114
return;
109115
}
110116

111-
const provider = providers?.[version.id];
112-
if (!provider || provider.document.guid !== version.id) {
113-
createProvider(collaborationUrl, version.id, version.content);
114-
}
115-
}, [createProvider, providers, version, collaborationUrl]);
117+
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
118+
}, [version?.content]);
116119

117120
if (isError && error) {
118121
if (error.status === 404) {
@@ -136,19 +139,13 @@ export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => {
136139
);
137140
}
138141

139-
if (isLoading || !version) {
142+
if (isLoading || !version || !initialContent) {
140143
return (
141144
<Box $align="center" $justify="center" $height="100%">
142145
<Loader />
143146
</Box>
144147
);
145148
}
146149

147-
const provider = providers?.[version.id];
148-
149-
if (!provider) {
150-
return null;
151-
}
152-
153-
return <BlockNoteEditor doc={doc} storeId={version.id} provider={provider} />;
150+
return <BlockNoteEditorVersion initialContent={initialContent} />;
154151
};

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { css } from 'styled-components';
55
import { Box, Card, StyledLink, Text } from '@/components';
66
import { useCunninghamTheme } from '@/cunningham';
77
import { Doc, currentDocRole, useTrans } from '@/features/docs/doc-management';
8-
import { Versions } from '@/features/docs/doc-versioning';
98
import { useDate } from '@/hook';
109
import { useResponsiveStore } from '@/stores';
1110

@@ -15,10 +14,9 @@ import { DocToolBox } from './DocToolBox';
1514

1615
interface DocHeaderProps {
1716
doc: Doc;
18-
versionId?: Versions['version_id'];
1917
}
2018

21-
export const DocHeader = ({ doc, versionId }: DocHeaderProps) => {
19+
export const DocHeader = ({ doc }: DocHeaderProps) => {
2220
const { colorsTokens } = useCunninghamTheme();
2321
const { t } = useTranslation();
2422
const { formatDate } = useDate();
@@ -69,7 +67,7 @@ export const DocHeader = ({ doc, versionId }: DocHeaderProps) => {
6967
$align="center"
7068
>
7169
<DocTitle doc={doc} />
72-
<DocToolBox doc={doc} versionId={versionId} />
70+
<DocToolBox doc={doc} />
7371
</Box>
7472
</Box>
7573
<Box

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
VariantType,
44
useToastProvider,
55
} from '@openfun/cunningham-react';
6+
import { useRouter } from 'next/router';
67
import React, { useState } from 'react';
78
import { useTranslation } from 'react-i18next';
89

@@ -17,17 +18,19 @@ import {
1718
ModalRemoveDoc,
1819
ModalShare,
1920
} from '@/features/docs/doc-management';
20-
import { ModalVersion, Versions } from '@/features/docs/doc-versioning';
21+
import { ModalVersion } from '@/features/docs/doc-versioning';
2122
import { useResponsiveStore } from '@/stores';
2223

2324
import { ModalPDF } from './ModalExport';
2425

2526
interface DocToolBoxProps {
2627
doc: Doc;
27-
versionId?: Versions['version_id'];
2828
}
2929

30-
export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
30+
export const DocToolBox = ({ doc }: DocToolBoxProps) => {
31+
const {
32+
query: { versionId },
33+
} = useRouter();
3134
const { t } = useTranslation();
3235
const [isModalShareOpen, setIsModalShareOpen] = useState(false);
3336
const [isModalRemoveOpen, setIsModalRemoveOpen] = useState(false);
@@ -194,7 +197,7 @@ export const DocToolBox = ({ doc, versionId }: DocToolBoxProps) => {
194197
<ModalVersion
195198
onClose={() => setIsModalVersionOpen(false)}
196199
docId={doc.id}
197-
versionId={versionId}
200+
versionId={versionId as string}
198201
/>
199202
)}
200203
</Box>

src/frontend/apps/impress/src/features/docs/doc-management/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,14 @@ export const blocksToYDoc = (blocks: BasicBlock[], doc: Y.Doc) => {
2828
xmlFragment.push([xmlElement]);
2929
});
3030
};
31+
32+
export const base64ToYDoc = (base64: string) => {
33+
const uint8Array = Buffer.from(base64, 'base64');
34+
const ydoc = new Y.Doc();
35+
Y.applyUpdate(ydoc, uint8Array);
36+
return ydoc;
37+
};
38+
39+
export const base64ToBlocknoteXmlFragment = (base64: string) => {
40+
return base64ToYDoc(base64).getXmlFragment('document-store');
41+
};

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

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@ import {
88
} from '@openfun/cunningham-react';
99
import { useRouter } from 'next/router';
1010
import { useTranslation } from 'react-i18next';
11-
import * as Y from 'yjs';
1211

1312
import { Box, Text } from '@/components';
14-
import { toBase64 } from '@/features/docs/doc-editor';
15-
import { Doc, useDocStore, useUpdateDoc } from '@/features/docs/doc-management';
13+
import {
14+
Doc,
15+
base64ToYDoc,
16+
useDocStore,
17+
useUpdateDoc,
18+
} from '@/features/docs/doc-management';
1619

20+
import { useDocVersion } from '../api';
1721
import { KEY_LIST_DOC_VERSIONS } from '../api/useDocVersions';
1822
import { Versions } from '../types';
1923
import { revertUpdate } from '../utils';
2024

2125
interface ModalVersionProps {
2226
onClose: () => void;
2327
docId: Doc['id'];
24-
2528
versionId: Versions['version_id'];
2629
}
2730

@@ -30,6 +33,10 @@ export const ModalVersion = ({
3033
docId,
3134
versionId,
3235
}: ModalVersionProps) => {
36+
const { data: version } = useDocVersion({
37+
docId,
38+
versionId,
39+
});
3340
const { t } = useTranslation();
3441
const { toast } = useToastProvider();
3542
const { push } = useRouter();
@@ -42,15 +49,15 @@ export const ModalVersion = ({
4249
void push(`/docs/${docId}`);
4350
};
4451

45-
if (!providers?.[docId] || !providers?.[versionId]) {
52+
if (!providers?.[docId] || !version?.content) {
4653
onDisplaySuccess();
4754
return;
4855
}
4956

5057
revertUpdate(
5158
providers[docId].document,
5259
providers[docId].document,
53-
providers[versionId].document,
60+
base64ToYDoc(version.content),
5461
);
5562

5663
onDisplaySuccess();
@@ -79,13 +86,13 @@ export const ModalVersion = ({
7986
color="primary"
8087
fullWidth
8188
onClick={() => {
82-
const newDoc = toBase64(
83-
Y.encodeStateAsUpdate(providers?.[versionId].document),
84-
);
89+
if (!version?.content) {
90+
return;
91+
}
8592

8693
updateDoc({
8794
id: docId,
88-
content: newDoc,
95+
content: version.content,
8996
});
9097

9198
onClose();

0 commit comments

Comments
 (0)