diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/SearchPage.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/SearchPage.tsx index 8027b2e4..06eddbf4 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/SearchPage.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/SearchPage.tsx @@ -3,6 +3,7 @@ import { StyleSchema, } from '@blocknote/core'; import { useBlockNoteEditor } from '@blocknote/react'; +import { useTreeContext } from '@gouvfr-lasuite/ui-kit'; import type { KeyboardEvent } from 'react'; import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -26,12 +27,14 @@ import { import FoundPageIcon from '@/docs/doc-editor/assets/doc-found.svg'; import AddPageIcon from '@/docs/doc-editor/assets/doc-plus.svg'; import { + Doc, getEmojiAndTitle, useCreateChildDocTree, useDocStore, useTrans, } from '@/docs/doc-management'; -import { DocSearchSubPageContent, DocSearchTarget } from '@/docs/doc-search'; +import { DocSearchTarget } from '@/docs/doc-search'; +import { DocSearchContent } from '@/docs/doc-search/components/DocSearchContent'; import { useResponsiveStore } from '@/stores'; const inputStyle = css` @@ -87,7 +90,7 @@ export const SearchPage = ({ const { isDesktop } = useResponsiveStore(); const { untitledDocument } = useTrans(); const isEditable = editor.isEditable; - + const treeContext = useTreeContext(); /** * createReactInlineContentSpec add automatically the focus after * the inline content, so we need to set the focus on the input @@ -225,14 +228,14 @@ export const SearchPage = ({ `} $margin={{ top: '0.5rem' }} > - { if (!isEditable) { return; } - updateInlineContent({ type: 'interlinkingSearchInline', props: { diff --git a/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchContent.tsx b/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchContent.tsx index a2b99cf8..bdee29c7 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchContent.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchContent.tsx @@ -4,6 +4,7 @@ import { InView } from 'react-intersection-observer'; import { QuickSearchData, QuickSearchGroup } from '@/components/quick-search'; import { useInfiniteSearchDocs } from '@/docs/doc-management/api/useSearchDocs'; +import { DocSearchTarget } from '@/docs/doc-search'; import { Doc } from '../../doc-management'; @@ -13,12 +14,20 @@ type DocSearchContentProps = { search: string; onSelect: (doc: Doc) => void; onLoadingChange?: (loading: boolean) => void; + renderElement?: (doc: Doc) => React.ReactNode; + target?: DocSearchTarget; + parentPath?: string; + emptySearchText?: string; }; export const DocSearchContent = ({ search, onSelect, onLoadingChange, + renderElement = (doc) => , + target, + parentPath, + emptySearchText, }: DocSearchContentProps) => { const { data, @@ -27,20 +36,29 @@ export const DocSearchContent = ({ isLoading, fetchNextPage, hasNextPage, - } = useInfiniteSearchDocs({ - page: 1, - q: search, - }); + } = useInfiniteSearchDocs( + { + q: search, + page: 1, + target, + parentPath, + }, + { + enabled: target !== DocSearchTarget.CURRENT || !!parentPath, + }, + ); const loading = isFetching || isRefetching || isLoading; const docsData: QuickSearchData = useMemo(() => { const docs = data?.pages.flatMap((page) => page.results) || []; + const defaultEmptyText = emptySearchText || t('No document found'); + const emptyText = search ? defaultEmptyText : t('Search by title'); return { groupName: docs.length > 0 ? t('Select a document') : '', elements: search ? docs : [], - emptyString: t('No document found'), + emptyString: target ? emptyText : defaultEmptyText, endActions: hasNextPage ? [ { @@ -49,7 +67,14 @@ export const DocSearchContent = ({ ] : [], }; - }, [search, data?.pages, fetchNextPage, hasNextPage]); + }, [ + search, + data?.pages, + fetchNextPage, + hasNextPage, + emptySearchText, + target, + ]); useEffect(() => { onLoadingChange?.(loading); @@ -59,7 +84,7 @@ export const DocSearchContent = ({ } + renderElement={renderElement} /> ); }; diff --git a/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx b/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx index 65f8a310..cfa679a1 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-search/components/DocSearchModal.tsx @@ -1,4 +1,5 @@ import { Modal, ModalSize } from '@gouvfr-lasuite/cunningham-react'; +import { TreeContextType, useTreeContext } from '@gouvfr-lasuite/ui-kit'; import Image from 'next/image'; import { useRouter } from 'next/router'; import { useState } from 'react'; @@ -8,45 +9,40 @@ import { useDebouncedCallback } from 'use-debounce'; import { Box, ButtonCloseModal, Text } from '@/components'; import { QuickSearch } from '@/components/quick-search'; import { Doc, useDocUtils } from '@/docs/doc-management'; +import { + DocSearchFilters, + DocSearchFiltersValues, + DocSearchTarget, +} from '@/docs/doc-search'; import { useResponsiveStore } from '@/stores'; import EmptySearchIcon from '../assets/illustration-docs-empty.png'; import { DocSearchContent } from './DocSearchContent'; -import { - DocSearchFilters, - DocSearchFiltersValues, - DocSearchTarget, -} from './DocSearchFilters'; import { DocSearchItem } from './DocSearchItem'; -import { DocSearchSubPageContent } from './DocSearchSubPageContent'; type DocSearchModalGlobalProps = { onClose: () => void; isOpen: boolean; showFilters?: boolean; defaultFilters?: DocSearchFiltersValues; + treeContext?: TreeContextType | null; }; const DocSearchModalGlobal = ({ showFilters = false, defaultFilters, + treeContext, ...modalProps }: DocSearchModalGlobalProps) => { const { t } = useTranslation(); const [loading, setLoading] = useState(false); - const router = useRouter(); - const isDocPage = router.pathname === '/docs/[id]'; - const [search, setSearch] = useState(''); const [filters, setFilters] = useState( defaultFilters ?? {}, ); - - const target = filters.target ?? DocSearchTarget.ALL; const { isDesktop } = useResponsiveStore(); - const handleInputSearch = useDebouncedCallback(setSearch, 300); const handleSelect = (doc: Doc) => { @@ -120,23 +116,22 @@ const DocSearchModalGlobal = ({ )} {search && ( - <> - {target === DocSearchTarget.ALL && ( - - )} - {isDocPage && target === DocSearchTarget.CURRENT && ( - } - /> - )} - + } + target={ + filters.target === DocSearchTarget.CURRENT + ? DocSearchTarget.CURRENT + : DocSearchTarget.ALL + } + parentPath={ + filters.target === DocSearchTarget.CURRENT + ? treeContext?.root?.path + : undefined + } + /> )} @@ -155,6 +150,7 @@ const DocSearchModalDetail = ({ }: DocSearchModalDetailProps) => { const { hasChildren, isChild } = useDocUtils(doc); const isWithChildren = isChild || hasChildren; + const treeContext = useTreeContext(); let defaultFilters = DocSearchTarget.ALL; let showFilters = false; @@ -168,6 +164,7 @@ const DocSearchModalDetail = ({ {...modalProps} showFilters={showFilters} defaultFilters={{ target: defaultFilters }} + treeContext={treeContext} /> ); }; diff --git a/src/frontend/apps/impress/src/features/docs/doc-search/components/index.ts b/src/frontend/apps/impress/src/features/docs/doc-search/components/index.ts index d5d0e0c4..1a088923 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-search/components/index.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-search/components/index.ts @@ -1,3 +1,2 @@ export * from './DocSearchModal'; export * from './DocSearchFilters'; -export * from './DocSearchSubPageContent';