Skip to content

Commit 39c22b0

Browse files
committed
🚚(frontend) better separation concern doc-versioning features
We move some components related to doc versioning into the doc-versioning feature folder to have a better separation of concerns. We don't need a provider for the doc versioning components since they will receive the doc data directly via a request.
1 parent d5c3f24 commit 39c22b0

File tree

6 files changed

+136
-110
lines changed

6 files changed

+136
-110
lines changed
Lines changed: 45 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,28 @@
1-
import { Loader } from '@openfun/cunningham-react';
2-
import { useRouter } from 'next/router';
3-
import { useEffect, useState } from 'react';
1+
import { useEffect } from 'react';
42
import { css } from 'styled-components';
5-
import * as Y from 'yjs';
63

7-
import { Box, Loading, Text, TextErrors } from '@/components';
8-
import { DocHeader, DocVersionHeader } from '@/docs/doc-header/';
9-
import {
10-
Doc,
11-
base64ToBlocknoteXmlFragment,
12-
useProviderStore,
13-
} from '@/docs/doc-management';
4+
import { Box, Loading } from '@/components';
5+
import { DocHeader } from '@/docs/doc-header/';
6+
import { Doc, useProviderStore } from '@/docs/doc-management';
147
import { TableContent } from '@/docs/doc-table-content/';
15-
import { Versions, useDocVersion } from '@/docs/doc-versioning/';
168
import { useSkeletonStore } from '@/features/skeletons';
179
import { useResponsiveStore } from '@/stores';
1810

19-
import { BlockNoteEditor, BlockNoteEditorVersion } from './BlockNoteEditor';
11+
import { BlockNoteEditor } from './BlockNoteEditor';
2012

21-
interface DocEditorProps {
22-
doc: Doc;
23-
versionId?: Versions['version_id'];
13+
interface DocEditorContainerProps {
14+
docHeader: React.ReactNode;
15+
docEditor: React.ReactNode;
2416
}
2517

26-
export const DocEditor = ({ doc, versionId }: DocEditorProps) => {
18+
export const DocEditorContainer = ({
19+
docHeader,
20+
docEditor,
21+
}: DocEditorContainerProps) => {
2722
const { isDesktop } = useResponsiveStore();
28-
const isVersion = !!versionId && typeof versionId === 'string';
29-
const { provider, isReady } = useProviderStore();
30-
const { setIsSkeletonVisible } = useSkeletonStore();
31-
const isProviderReady = isReady && provider;
32-
33-
useEffect(() => {
34-
if (isProviderReady) {
35-
setIsSkeletonVisible(false);
36-
}
37-
}, [isProviderReady, setIsSkeletonVisible]);
38-
39-
if (!isProviderReady) {
40-
return <Loading />;
41-
}
4223

4324
return (
4425
<>
45-
{isDesktop && !isVersion && (
46-
<Box
47-
$position="absolute"
48-
$css={css`
49-
top: 72px;
50-
right: 20px;
51-
`}
52-
>
53-
<TableContent />
54-
</Box>
55-
)}
5626
<Box
5727
$maxWidth="868px"
5828
$width="100%"
@@ -63,7 +33,7 @@ export const DocEditor = ({ doc, versionId }: DocEditorProps) => {
6333
$padding={{ horizontal: isDesktop ? '54px' : 'base' }}
6434
className="--docs--doc-editor-header"
6535
>
66-
{isVersion ? <DocVersionHeader /> : <DocHeader doc={doc} />}
36+
{docHeader}
6737
</Box>
6838

6939
<Box
@@ -74,81 +44,51 @@ export const DocEditor = ({ doc, versionId }: DocEditorProps) => {
7444
className="--docs--doc-editor-content"
7545
>
7646
<Box $css="flex:1;" $position="relative" $width="100%">
77-
{isVersion ? (
78-
<DocVersionEditor docId={doc.id} versionId={versionId} />
79-
) : (
80-
<BlockNoteEditor doc={doc} provider={provider} />
81-
)}
47+
{docEditor}
8248
</Box>
8349
</Box>
8450
</Box>
8551
</>
8652
);
8753
};
8854

89-
interface DocVersionEditorProps {
90-
docId: Doc['id'];
91-
versionId: Versions['version_id'];
55+
interface DocEditorProps {
56+
doc: Doc;
9257
}
9358

94-
export const DocVersionEditor = ({
95-
docId,
96-
versionId,
97-
}: DocVersionEditorProps) => {
98-
const {
99-
data: version,
100-
isLoading,
101-
isError,
102-
error,
103-
} = useDocVersion({
104-
docId,
105-
versionId,
106-
});
107-
108-
const { replace } = useRouter();
109-
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();
59+
export const DocEditor = ({ doc }: DocEditorProps) => {
60+
const { isDesktop } = useResponsiveStore();
61+
const { provider, isReady } = useProviderStore();
62+
const { setIsSkeletonVisible } = useSkeletonStore();
63+
const isProviderReady = isReady && provider;
11064

11165
useEffect(() => {
112-
if (!version?.content) {
113-
return;
114-
}
115-
116-
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
117-
}, [version?.content]);
118-
119-
if (isError && error) {
120-
if (error.status === 404) {
121-
void replace(`/404`);
122-
return null;
66+
if (isProviderReady) {
67+
setIsSkeletonVisible(false);
12368
}
69+
}, [isProviderReady, setIsSkeletonVisible]);
12470

125-
return (
126-
<Box $margin="large" className="--docs--doc-version-editor-error">
127-
<TextErrors
128-
causes={error.cause}
129-
icon={
130-
error.status === 502 ? (
131-
<Text
132-
className="material-icons"
133-
$theme="danger"
134-
aria-hidden={true}
135-
>
136-
wifi_off
137-
</Text>
138-
) : undefined
139-
}
140-
/>
141-
</Box>
142-
);
143-
}
144-
145-
if (isLoading || !version || !initialContent) {
146-
return (
147-
<Box $align="center" $justify="center" $height="100%">
148-
<Loader />
149-
</Box>
150-
);
71+
if (!isProviderReady) {
72+
return <Loading />;
15173
}
15274

153-
return <BlockNoteEditorVersion initialContent={initialContent} />;
75+
return (
76+
<>
77+
{isDesktop && (
78+
<Box
79+
$position="absolute"
80+
$css={css`
81+
top: 72px;
82+
right: 20px;
83+
`}
84+
>
85+
<TableContent />
86+
</Box>
87+
)}
88+
<DocEditorContainer
89+
docHeader={<DocHeader doc={doc} />}
90+
docEditor={<BlockNoteEditor doc={doc} provider={provider} />}
91+
/>
92+
</>
93+
);
15494
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './BlockNoteEditor';
12
export * from './DocEditor';
23
export * from './EmojiPicker';
34
export * from './custom-blocks/';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export * from './DocHeader';
2-
export * from './DocVersionHeader';
2+
export * from './DocTitle';
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { Loader } from '@openfun/cunningham-react';
2+
import { useRouter } from 'next/router';
3+
import { useEffect, useState } from 'react';
4+
import * as Y from 'yjs';
5+
6+
import { Box, Text, TextErrors } from '@/components';
7+
import { BlockNoteEditorVersion, DocEditorContainer } from '@/docs/doc-editor/';
8+
import { Doc, base64ToBlocknoteXmlFragment } from '@/docs/doc-management';
9+
import { Versions, useDocVersion } from '@/docs/doc-versioning/';
10+
11+
import { DocVersionHeader } from './DocVersionHeader';
12+
13+
interface DocVersionEditorProps {
14+
docId: Doc['id'];
15+
versionId: Versions['version_id'];
16+
}
17+
18+
export const DocVersionEditor = ({
19+
docId,
20+
versionId,
21+
}: DocVersionEditorProps) => {
22+
const {
23+
data: version,
24+
isLoading,
25+
isError,
26+
error,
27+
} = useDocVersion({
28+
docId,
29+
versionId,
30+
});
31+
32+
const { replace } = useRouter();
33+
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();
34+
35+
useEffect(() => {
36+
if (!version?.content) {
37+
return;
38+
}
39+
40+
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
41+
}, [version?.content]);
42+
43+
if (isError && error) {
44+
if (error.status === 404) {
45+
void replace(`/404`);
46+
return null;
47+
}
48+
49+
return (
50+
<Box $margin="large" className="--docs--doc-version-editor-error">
51+
<TextErrors
52+
causes={error.cause}
53+
icon={
54+
error.status === 502 ? (
55+
<Text
56+
className="material-icons"
57+
$theme="danger"
58+
aria-hidden={true}
59+
>
60+
wifi_off
61+
</Text>
62+
) : undefined
63+
}
64+
/>
65+
</Box>
66+
);
67+
}
68+
69+
if (isLoading || !version || !initialContent) {
70+
return (
71+
<Box $align="center" $justify="center" $height="100%">
72+
<Loader />
73+
</Box>
74+
);
75+
}
76+
77+
return (
78+
<DocEditorContainer
79+
docHeader={<DocVersionHeader />}
80+
docEditor={<BlockNoteEditorVersion initialContent={initialContent} />}
81+
/>
82+
);
83+
};

src/frontend/apps/impress/src/features/docs/doc-header/components/DocVersionHeader.tsx renamed to src/frontend/apps/impress/src/features/docs/doc-versioning/components/DocVersionHeader.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { useTranslation } from 'react-i18next';
22

33
import { Box, HorizontalSeparator } from '@/components';
44
import { useCunninghamTheme } from '@/cunningham';
5-
6-
import { DocTitleText } from './DocTitle';
5+
import { DocTitleText } from '@/docs/doc-header';
76

87
export const DocVersionHeader = () => {
98
const { spacingsTokens } = useCunninghamTheme();

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { useTranslation } from 'react-i18next';
44
import { createGlobalStyle, css } from 'styled-components';
55

66
import { Box, ButtonCloseModal, Text } from '@/components';
7-
import { DocEditor } from '@/docs/doc-editor';
87
import { Doc } from '@/docs/doc-management';
98

109
import { Versions } from '../types';
1110

11+
import { DocVersionEditor } from './DocVersionEditor';
1212
import { ModalConfirmationVersion } from './ModalConfirmationVersion';
1313
import { VersionList } from './VersionList';
1414

@@ -81,7 +81,10 @@ export const ModalSelectVersion = ({
8181
$align="center"
8282
>
8383
{selectedVersionId && (
84-
<DocEditor doc={doc} versionId={selectedVersionId} />
84+
<DocVersionEditor
85+
docId={doc.id}
86+
versionId={selectedVersionId}
87+
/>
8588
)}
8689
{!selectedVersionId && (
8790
<Box $align="center" $justify="center" $height="100%">

0 commit comments

Comments
 (0)