From 8bd83cbfcdc37df6c7174a8c1167789b9bf211bb Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 25 Oct 2024 10:42:13 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=9A(frontend)=20move=20useDocStore=20t?= =?UTF-8?q?o=20doc-management?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to make more accessible the doc store to every feature, so we move it to the doc-management folder. --- .../docs/doc-editor/components/AIButton.tsx | 3 +- .../doc-editor/components/BlockNoteEditor.tsx | 33 +++---------------- .../docs/doc-editor/components/DocEditor.tsx | 33 ++++++++++++++++--- .../features/docs/doc-editor/stores/index.ts | 1 - .../src/features/docs/doc-editor/utils.ts | 19 ----------- .../docs/doc-header/components/DocToolBox.tsx | 3 +- .../doc-header/components/ModalExport.tsx | 3 +- .../src/features/docs/doc-management/index.ts | 1 + .../docs/doc-management/stores/index.tsx | 1 + .../stores/useDocStore.tsx | 4 +-- .../src/features/docs/doc-management/utils.ts | 19 +++++++++++ .../components/TableContent.tsx | 4 +-- .../components/ModalVersion.tsx | 4 +-- .../impress/src/pages/docs/[id]/index.tsx | 18 ++++++++-- 14 files changed, 78 insertions(+), 68 deletions(-) create mode 100644 src/frontend/apps/impress/src/features/docs/doc-management/stores/index.tsx rename src/frontend/apps/impress/src/features/docs/{doc-editor => doc-management}/stores/useDocStore.tsx (93%) diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx index 5746c44a..c7915bfe 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/AIButton.tsx @@ -14,14 +14,13 @@ import { useTranslation } from 'react-i18next'; import { isAPIError } from '@/api'; import { Box, Text } from '@/components'; -import { useDocOptions } from '@/features/docs/doc-management/'; +import { useDocOptions, useDocStore } from '@/features/docs/doc-management/'; import { AITransformActions, useDocAITransform, useDocAITranslate, } from '../api/'; -import { useDocStore } from '../stores'; type LanguageTranslate = { value: string; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx index bbb29a61..3c1a9527 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx @@ -11,12 +11,11 @@ import { useTranslation } from 'react-i18next'; import { Box, TextErrors } from '@/components'; import { mediaUrl } from '@/core'; import { useAuthStore } from '@/core/auth'; -import { Doc } from '@/features/docs/doc-management'; -import { Version } from '@/features/docs/doc-versioning/'; +import { Doc, useDocStore } from '@/features/docs/doc-management'; import { useCreateDocAttachment } from '../api/useCreateDocUpload'; import useSaveDoc from '../hook/useSaveDoc'; -import { useDocStore, useHeadingStore } from '../stores'; +import { useHeadingStore } from '../stores'; import { randomColor } from '../utils'; import { BlockNoteToolbar } from './BlockNoteToolbar'; @@ -75,40 +74,16 @@ const cssEditor = (readonly: boolean) => ` `; 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 ; -}; - -interface BlockNoteContentProps { doc: Doc; provider: HocuspocusProvider; storeId: string; } -export const BlockNoteContent = ({ +export const BlockNoteEditor = ({ doc, provider, storeId, -}: BlockNoteContentProps) => { +}: BlockNoteEditorProps) => { const isVersion = doc.id !== storeId; const { userData } = useAuthStore(); const { setStore, docsStore } = useDocStore(); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx index 4782aee1..902b2792 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx @@ -1,13 +1,13 @@ import { Alert, Loader, VariantType } from '@openfun/cunningham-react'; import { useRouter as useNavigate } from 'next/navigation'; import { useRouter } from 'next/router'; -import React from 'react'; +import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Box, Card, Text, TextErrors } from '@/components'; import { useCunninghamTheme } from '@/cunningham'; 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 { useResponsiveStore } from '@/stores'; @@ -32,6 +32,13 @@ export const DocEditor = ({ doc }: DocEditorProps) => { const { colorsTokens } = useCunninghamTheme(); + const { docsStore } = useDocStore(); + const provider = docsStore?.[doc.id]?.provider; + + if (!provider) { + return null; + } + return ( <> @@ -66,7 +73,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => { {isVersion ? ( ) : ( - + )} {!isMobile && } @@ -91,9 +98,21 @@ export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => { docId: doc.id, versionId, }); + const { createProvider, docsStore } = useDocStore(); 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 (error.status === 404) { navigate.replace(`/404`); @@ -124,5 +143,11 @@ export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => { ); } - return ; + const provider = docsStore?.[version.id]?.provider; + + if (!provider) { + return null; + } + + return ; }; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/stores/index.ts b/src/frontend/apps/impress/src/features/docs/doc-editor/stores/index.ts index 52c5b509..71a6b765 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/stores/index.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/stores/index.ts @@ -1,3 +1,2 @@ -export * from './useDocStore'; export * from './useHeadingStore'; export * from './usePanelEditorStore'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/utils.ts b/src/frontend/apps/impress/src/features/docs/doc-editor/utils.ts index 2c9495ec..aa0d43ba 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/utils.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/utils.ts @@ -1,5 +1,3 @@ -import * as Y from 'yjs'; - export const randomColor = () => { const randomInt = (min: number, max: number) => { return Math.floor(Math.random() * (max - min + 1)) + min; @@ -28,20 +26,3 @@ function hslToHex(h: number, s: number, l: number) { export const toBase64 = ( str: WithImplicitCoercion, ) => 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]); - }); -}; diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx index 2ce583e9..6095a102 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx @@ -8,11 +8,12 @@ import { useTranslation } from 'react-i18next'; import { Box, DropButton, IconOptions } from '@/components'; import { useAuthStore } from '@/core'; -import { useDocStore, usePanelEditorStore } from '@/features/docs/doc-editor/'; +import { usePanelEditorStore } from '@/features/docs/doc-editor/'; import { Doc, ModalRemoveDoc, ModalShare, + useDocStore, } from '@/features/docs/doc-management'; import { useResponsiveStore } from '@/stores'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx index 2dc57569..c22dc151 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx @@ -14,8 +14,7 @@ import { t } from 'i18next'; import { useEffect, useMemo, useState } from 'react'; import { Box, Text } from '@/components'; -import { useDocStore } from '@/features/docs/doc-editor/'; -import { Doc } from '@/features/docs/doc-management'; +import { Doc, useDocStore } from '@/features/docs/doc-management'; import { useExport } from '../api/useExport'; import { TemplatesOrdering, useTemplates } from '../api/useTemplates'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/index.ts b/src/frontend/apps/impress/src/features/docs/doc-management/index.ts index 6d490e09..a30fbe25 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/index.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-management/index.ts @@ -1,5 +1,6 @@ export * from './api'; export * from './components'; export * from './hooks'; +export * from './stores'; export * from './types'; export * from './utils'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/stores/index.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/stores/index.tsx new file mode 100644 index 00000000..e742cba5 --- /dev/null +++ b/src/frontend/apps/impress/src/features/docs/doc-management/stores/index.tsx @@ -0,0 +1 @@ +export * from './useDocStore'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/stores/useDocStore.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/stores/useDocStore.tsx similarity index 93% rename from src/frontend/apps/impress/src/features/docs/doc-editor/stores/useDocStore.tsx rename to src/frontend/apps/impress/src/features/docs/doc-management/stores/useDocStore.tsx index c75fe5ef..8d38fb56 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/stores/useDocStore.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/stores/useDocStore.tsx @@ -4,9 +4,7 @@ import * as Y from 'yjs'; import { create } from 'zustand'; import { providerUrl } from '@/core'; -import { Base64, Doc } from '@/features/docs/doc-management'; - -import { blocksToYDoc } from '../utils'; +import { Base64, Doc, blocksToYDoc } from '@/features/docs/doc-management'; interface DocStore { provider: HocuspocusProvider; diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts b/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts index 07c751b4..7ba6571a 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts @@ -1,3 +1,5 @@ +import * as Y from 'yjs'; + import { Doc, Role } from './types'; export const currentDocRole = (abilities: Doc['abilities']): Role => { @@ -9,3 +11,20 @@ export const currentDocRole = (abilities: Doc['abilities']): Role => { ? Role.EDITOR : 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]); + }); +}; diff --git a/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx b/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx index e16141d7..f9740030 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx @@ -2,8 +2,8 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Box, BoxButton, Text } from '@/components'; -import { HeadingBlock, useDocStore } from '@/features/docs/doc-editor'; -import { Doc } from '@/features/docs/doc-management'; +import { HeadingBlock } from '@/features/docs/doc-editor'; +import { Doc, useDocStore } from '@/features/docs/doc-management'; import { useResponsiveStore } from '@/stores'; import { Heading } from './Heading'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-versioning/components/ModalVersion.tsx b/src/frontend/apps/impress/src/features/docs/doc-versioning/components/ModalVersion.tsx index 2484803c..bc7a0d9b 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-versioning/components/ModalVersion.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-versioning/components/ModalVersion.tsx @@ -11,8 +11,8 @@ import { useRouter } from 'next/navigation'; import * as Y from 'yjs'; import { Box, Text } from '@/components'; -import { toBase64, useDocStore } from '@/features/docs/doc-editor'; -import { Doc, useUpdateDoc } from '@/features/docs/doc-management'; +import { toBase64 } from '@/features/docs/doc-editor'; +import { Doc, useDocStore, useUpdateDoc } from '@/features/docs/doc-management'; import { KEY_LIST_DOC_VERSIONS } from '../api/useDocVersions'; import { Versions } from '../types'; diff --git a/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx b/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx index 61b6834d..7a976bbf 100644 --- a/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx +++ b/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx @@ -7,8 +7,8 @@ import { useEffect, useState } from 'react'; import { Box, Text } from '@/components'; import { TextErrors } from '@/components/TextErrors'; import { useAuthStore } from '@/core/auth'; -import { DocEditor, useDocStore } from '@/features/docs'; -import { useDoc } from '@/features/docs/doc-management'; +import { DocEditor } from '@/features/docs/doc-editor'; +import { useDoc, useDocStore } from '@/features/docs/doc-management'; import { MainLayout } from '@/layouts'; import { NextPageWithLayout } from '@/types/next'; @@ -41,7 +41,7 @@ const DocPage = ({ id }: DocProps) => { const { login } = useAuthStore(); const { data: docQuery, isError, error } = useDoc({ id }); const [doc, setDoc] = useState(docQuery); - const { setCurrentDoc } = useDocStore(); + const { setCurrentDoc, createProvider, docsStore } = useDocStore(); const navigate = useNavigate(); @@ -66,6 +66,18 @@ const DocPage = ({ id }: DocProps) => { }; }, [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 (error.status === 404) { navigate.replace(`/404`);