🚚(frontend) move useDocStore to doc-management

We want to make more accessible the doc store
to every feature, so we move it to the
doc-management folder.
This commit is contained in:
Anthony LC
2024-10-25 10:42:13 +02:00
committed by Anthony LC
parent bc14d1d0f8
commit 8bd83cbfcd
14 changed files with 78 additions and 68 deletions

View File

@@ -14,14 +14,13 @@ import { useTranslation } from 'react-i18next';
import { isAPIError } from '@/api'; import { isAPIError } from '@/api';
import { Box, Text } from '@/components'; import { Box, Text } from '@/components';
import { useDocOptions } from '@/features/docs/doc-management/'; import { useDocOptions, useDocStore } from '@/features/docs/doc-management/';
import { import {
AITransformActions, AITransformActions,
useDocAITransform, useDocAITransform,
useDocAITranslate, useDocAITranslate,
} from '../api/'; } from '../api/';
import { useDocStore } from '../stores';
type LanguageTranslate = { type LanguageTranslate = {
value: string; value: string;

View File

@@ -11,12 +11,11 @@ import { useTranslation } from 'react-i18next';
import { Box, TextErrors } from '@/components'; import { Box, TextErrors } from '@/components';
import { mediaUrl } from '@/core'; import { mediaUrl } from '@/core';
import { useAuthStore } from '@/core/auth'; import { useAuthStore } from '@/core/auth';
import { Doc } from '@/features/docs/doc-management'; import { Doc, useDocStore } from '@/features/docs/doc-management';
import { Version } from '@/features/docs/doc-versioning/';
import { useCreateDocAttachment } from '../api/useCreateDocUpload'; import { useCreateDocAttachment } from '../api/useCreateDocUpload';
import useSaveDoc from '../hook/useSaveDoc'; import useSaveDoc from '../hook/useSaveDoc';
import { useDocStore, useHeadingStore } from '../stores'; import { useHeadingStore } from '../stores';
import { randomColor } from '../utils'; import { randomColor } from '../utils';
import { BlockNoteToolbar } from './BlockNoteToolbar'; import { BlockNoteToolbar } from './BlockNoteToolbar';
@@ -75,40 +74,16 @@ const cssEditor = (readonly: boolean) => `
`; `;
interface BlockNoteEditorProps { interface BlockNoteEditorProps {
doc: Doc;
version?: Version;
}
export const BlockNoteEditor = ({ doc, version }: BlockNoteEditorProps) => {
const { createProvider, docsStore } = useDocStore();
const storeId = version?.id || doc.id;
const initialContent = version?.content || doc.content;
const provider = docsStore?.[storeId]?.provider;
useEffect(() => {
if (!provider || provider.document.guid !== storeId) {
createProvider(storeId, initialContent);
}
}, [createProvider, initialContent, provider, storeId]);
if (!provider) {
return null;
}
return <BlockNoteContent doc={doc} provider={provider} storeId={storeId} />;
};
interface BlockNoteContentProps {
doc: Doc; doc: Doc;
provider: HocuspocusProvider; provider: HocuspocusProvider;
storeId: string; storeId: string;
} }
export const BlockNoteContent = ({ export const BlockNoteEditor = ({
doc, doc,
provider, provider,
storeId, storeId,
}: BlockNoteContentProps) => { }: BlockNoteEditorProps) => {
const isVersion = doc.id !== storeId; const isVersion = doc.id !== storeId;
const { userData } = useAuthStore(); const { userData } = useAuthStore();
const { setStore, docsStore } = useDocStore(); const { setStore, docsStore } = useDocStore();

View File

@@ -1,13 +1,13 @@
import { Alert, Loader, VariantType } from '@openfun/cunningham-react'; import { Alert, Loader, VariantType } from '@openfun/cunningham-react';
import { useRouter as useNavigate } from 'next/navigation'; import { useRouter as useNavigate } from 'next/navigation';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Box, Card, Text, TextErrors } from '@/components'; import { Box, Card, Text, TextErrors } from '@/components';
import { useCunninghamTheme } from '@/cunningham'; import { useCunninghamTheme } from '@/cunningham';
import { DocHeader } from '@/features/docs/doc-header'; import { DocHeader } from '@/features/docs/doc-header';
import { Doc } from '@/features/docs/doc-management'; import { Doc, useDocStore } from '@/features/docs/doc-management';
import { Versions, useDocVersion } from '@/features/docs/doc-versioning/'; import { Versions, useDocVersion } from '@/features/docs/doc-versioning/';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
@@ -32,6 +32,13 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
const { colorsTokens } = useCunninghamTheme(); const { colorsTokens } = useCunninghamTheme();
const { docsStore } = useDocStore();
const provider = docsStore?.[doc.id]?.provider;
if (!provider) {
return null;
}
return ( return (
<> <>
<DocHeader doc={doc} versionId={versionId as Versions['version_id']} /> <DocHeader doc={doc} versionId={versionId as Versions['version_id']} />
@@ -66,7 +73,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
{isVersion ? ( {isVersion ? (
<DocVersionEditor doc={doc} versionId={versionId} /> <DocVersionEditor doc={doc} versionId={versionId} />
) : ( ) : (
<BlockNoteEditor doc={doc} /> <BlockNoteEditor doc={doc} storeId={doc.id} provider={provider} />
)} )}
{!isMobile && <IconOpenPanelEditor headings={headings} />} {!isMobile && <IconOpenPanelEditor headings={headings} />}
</Card> </Card>
@@ -91,9 +98,21 @@ export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => {
docId: doc.id, docId: doc.id,
versionId, versionId,
}); });
const { createProvider, docsStore } = useDocStore();
const navigate = useNavigate(); const navigate = useNavigate();
useEffect(() => {
if (!version?.id) {
return;
}
const provider = docsStore?.[version.id]?.provider;
if (!provider || provider.document.guid !== version.id) {
createProvider(version.id, version.content);
}
}, [createProvider, docsStore, version]);
if (isError && error) { if (isError && error) {
if (error.status === 404) { if (error.status === 404) {
navigate.replace(`/404`); navigate.replace(`/404`);
@@ -124,5 +143,11 @@ export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => {
); );
} }
return <BlockNoteEditor doc={doc} version={version} />; const provider = docsStore?.[version.id]?.provider;
if (!provider) {
return null;
}
return <BlockNoteEditor doc={doc} storeId={version.id} provider={provider} />;
}; };

View File

@@ -1,3 +1,2 @@
export * from './useDocStore';
export * from './useHeadingStore'; export * from './useHeadingStore';
export * from './usePanelEditorStore'; export * from './usePanelEditorStore';

View File

@@ -1,5 +1,3 @@
import * as Y from 'yjs';
export const randomColor = () => { export const randomColor = () => {
const randomInt = (min: number, max: number) => { const randomInt = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
@@ -28,20 +26,3 @@ function hslToHex(h: number, s: number, l: number) {
export const toBase64 = ( export const toBase64 = (
str: WithImplicitCoercion<ArrayBuffer | SharedArrayBuffer>, str: WithImplicitCoercion<ArrayBuffer | SharedArrayBuffer>,
) => Buffer.from(str).toString('base64'); ) => Buffer.from(str).toString('base64');
type BasicBlock = {
type: string;
content: string;
};
export const blocksToYDoc = (blocks: BasicBlock[], doc: Y.Doc) => {
const xmlFragment = doc.getXmlFragment('document-store');
blocks.forEach((block) => {
const xmlElement = new Y.XmlElement(block.type);
if (block.content) {
xmlElement.insert(0, [new Y.XmlText(block.content)]);
}
xmlFragment.push([xmlElement]);
});
};

View File

@@ -8,11 +8,12 @@ import { useTranslation } from 'react-i18next';
import { Box, DropButton, IconOptions } from '@/components'; import { Box, DropButton, IconOptions } from '@/components';
import { useAuthStore } from '@/core'; import { useAuthStore } from '@/core';
import { useDocStore, usePanelEditorStore } from '@/features/docs/doc-editor/'; import { usePanelEditorStore } from '@/features/docs/doc-editor/';
import { import {
Doc, Doc,
ModalRemoveDoc, ModalRemoveDoc,
ModalShare, ModalShare,
useDocStore,
} from '@/features/docs/doc-management'; } from '@/features/docs/doc-management';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';

View File

@@ -14,8 +14,7 @@ import { t } from 'i18next';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { Box, Text } from '@/components'; import { Box, Text } from '@/components';
import { useDocStore } from '@/features/docs/doc-editor/'; import { Doc, useDocStore } from '@/features/docs/doc-management';
import { Doc } from '@/features/docs/doc-management';
import { useExport } from '../api/useExport'; import { useExport } from '../api/useExport';
import { TemplatesOrdering, useTemplates } from '../api/useTemplates'; import { TemplatesOrdering, useTemplates } from '../api/useTemplates';

View File

@@ -1,5 +1,6 @@
export * from './api'; export * from './api';
export * from './components'; export * from './components';
export * from './hooks'; export * from './hooks';
export * from './stores';
export * from './types'; export * from './types';
export * from './utils'; export * from './utils';

View File

@@ -0,0 +1 @@
export * from './useDocStore';

View File

@@ -4,9 +4,7 @@ import * as Y from 'yjs';
import { create } from 'zustand'; import { create } from 'zustand';
import { providerUrl } from '@/core'; import { providerUrl } from '@/core';
import { Base64, Doc } from '@/features/docs/doc-management'; import { Base64, Doc, blocksToYDoc } from '@/features/docs/doc-management';
import { blocksToYDoc } from '../utils';
interface DocStore { interface DocStore {
provider: HocuspocusProvider; provider: HocuspocusProvider;

View File

@@ -1,3 +1,5 @@
import * as Y from 'yjs';
import { Doc, Role } from './types'; import { Doc, Role } from './types';
export const currentDocRole = (abilities: Doc['abilities']): Role => { export const currentDocRole = (abilities: Doc['abilities']): Role => {
@@ -9,3 +11,20 @@ export const currentDocRole = (abilities: Doc['abilities']): Role => {
? Role.EDITOR ? Role.EDITOR
: Role.READER; : Role.READER;
}; };
type BasicBlock = {
type: string;
content: string;
};
export const blocksToYDoc = (blocks: BasicBlock[], doc: Y.Doc) => {
const xmlFragment = doc.getXmlFragment('document-store');
blocks.forEach((block) => {
const xmlElement = new Y.XmlElement(block.type);
if (block.content) {
xmlElement.insert(0, [new Y.XmlText(block.content)]);
}
xmlFragment.push([xmlElement]);
});
};

View File

@@ -2,8 +2,8 @@ import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Box, BoxButton, Text } from '@/components'; import { Box, BoxButton, Text } from '@/components';
import { HeadingBlock, useDocStore } from '@/features/docs/doc-editor'; import { HeadingBlock } from '@/features/docs/doc-editor';
import { Doc } from '@/features/docs/doc-management'; import { Doc, useDocStore } from '@/features/docs/doc-management';
import { useResponsiveStore } from '@/stores'; import { useResponsiveStore } from '@/stores';
import { Heading } from './Heading'; import { Heading } from './Heading';

View File

@@ -11,8 +11,8 @@ import { useRouter } from 'next/navigation';
import * as Y from 'yjs'; import * as Y from 'yjs';
import { Box, Text } from '@/components'; import { Box, Text } from '@/components';
import { toBase64, useDocStore } from '@/features/docs/doc-editor'; import { toBase64 } from '@/features/docs/doc-editor';
import { Doc, useUpdateDoc } from '@/features/docs/doc-management'; import { Doc, useDocStore, useUpdateDoc } from '@/features/docs/doc-management';
import { KEY_LIST_DOC_VERSIONS } from '../api/useDocVersions'; import { KEY_LIST_DOC_VERSIONS } from '../api/useDocVersions';
import { Versions } from '../types'; import { Versions } from '../types';

View File

@@ -7,8 +7,8 @@ import { useEffect, useState } from 'react';
import { Box, Text } from '@/components'; import { Box, Text } from '@/components';
import { TextErrors } from '@/components/TextErrors'; import { TextErrors } from '@/components/TextErrors';
import { useAuthStore } from '@/core/auth'; import { useAuthStore } from '@/core/auth';
import { DocEditor, useDocStore } from '@/features/docs'; import { DocEditor } from '@/features/docs/doc-editor';
import { useDoc } from '@/features/docs/doc-management'; import { useDoc, useDocStore } from '@/features/docs/doc-management';
import { MainLayout } from '@/layouts'; import { MainLayout } from '@/layouts';
import { NextPageWithLayout } from '@/types/next'; import { NextPageWithLayout } from '@/types/next';
@@ -41,7 +41,7 @@ const DocPage = ({ id }: DocProps) => {
const { login } = useAuthStore(); const { login } = useAuthStore();
const { data: docQuery, isError, error } = useDoc({ id }); const { data: docQuery, isError, error } = useDoc({ id });
const [doc, setDoc] = useState(docQuery); const [doc, setDoc] = useState(docQuery);
const { setCurrentDoc } = useDocStore(); const { setCurrentDoc, createProvider, docsStore } = useDocStore();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -66,6 +66,18 @@ const DocPage = ({ id }: DocProps) => {
}; };
}, [docQuery, setCurrentDoc]); }, [docQuery, setCurrentDoc]);
useEffect(() => {
if (!doc?.id) {
return;
}
const provider = docsStore?.[doc.id]?.provider;
if (!provider || provider.document.guid !== doc.id) {
createProvider(doc.id, doc.content);
}
}, [createProvider, doc, docsStore]);
if (isError && error) { if (isError && error) {
if (error.status === 404) { if (error.status === 404) {
navigate.replace(`/404`); navigate.replace(`/404`);