🚚(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:
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
export * from './useDocStore';
|
|
||||||
export * from './useHeadingStore';
|
export * from './useHeadingStore';
|
||||||
export * from './usePanelEditorStore';
|
export * from './usePanelEditorStore';
|
||||||
|
|||||||
@@ -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]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './useDocStore';
|
||||||
@@ -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;
|
||||||
@@ -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]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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`);
|
||||||
|
|||||||
Reference in New Issue
Block a user