|
@@ -24,56 +24,70 @@ import {
|
|
|
import { mutateSearching } from '~/stores/search';
|
|
import { mutateSearching } from '~/stores/search';
|
|
|
|
|
|
|
|
type Props = {
|
|
type Props = {
|
|
|
- pages: IPageWithSearchMeta[],
|
|
|
|
|
- selectedPageId?: string,
|
|
|
|
|
- forceHideMenuItems?: ForceHideMenuItems,
|
|
|
|
|
- onPageSelected?: (page?: IPageWithSearchMeta) => void,
|
|
|
|
|
- onCheckboxChanged?: (isChecked: boolean, pageId: string) => void,
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props> = (props:Props, ref) => {
|
|
|
|
|
- const {
|
|
|
|
|
- pages, selectedPageId,
|
|
|
|
|
- forceHideMenuItems,
|
|
|
|
|
- onPageSelected,
|
|
|
|
|
- } = props;
|
|
|
|
|
|
|
+ pages: IPageWithSearchMeta[];
|
|
|
|
|
+ selectedPageId?: string;
|
|
|
|
|
+ forceHideMenuItems?: ForceHideMenuItems;
|
|
|
|
|
+ onPageSelected?: (page?: IPageWithSearchMeta) => void;
|
|
|
|
|
+ onCheckboxChanged?: (isChecked: boolean, pageId: string) => void;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const SearchResultListSubstance: ForwardRefRenderFunction<
|
|
|
|
|
+ ISelectableAll,
|
|
|
|
|
+ Props
|
|
|
|
|
+> = (props: Props, ref) => {
|
|
|
|
|
+ const { pages, selectedPageId, forceHideMenuItems, onPageSelected } = props;
|
|
|
|
|
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
|
|
|
|
|
const pageIdsWithNoSnippet = pages
|
|
const pageIdsWithNoSnippet = pages
|
|
|
- .filter(page => (page.meta?.elasticSearchResult?.snippet?.length ?? 0) === 0)
|
|
|
|
|
- .map(page => page.data._id);
|
|
|
|
|
|
|
+ .filter(
|
|
|
|
|
+ (page) => (page.meta?.elasticSearchResult?.snippet?.length ?? 0) === 0,
|
|
|
|
|
+ )
|
|
|
|
|
+ .map((page) => page.data._id);
|
|
|
|
|
|
|
|
const isGuestUser = useIsGuestUser();
|
|
const isGuestUser = useIsGuestUser();
|
|
|
const isReadOnlyUser = useIsReadOnlyUser();
|
|
const isReadOnlyUser = useIsReadOnlyUser();
|
|
|
- const { data: idToPageInfo } = useSWRxPageInfoForList(pageIdsWithNoSnippet, null, true, true);
|
|
|
|
|
|
|
+ const { data: idToPageInfo } = useSWRxPageInfoForList(
|
|
|
|
|
+ pageIdsWithNoSnippet,
|
|
|
|
|
+ null,
|
|
|
|
|
+ true,
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
- const itemsRef = useRef<(ISelectable|null)[]>([]);
|
|
|
|
|
|
|
+ const itemsRef = useRef<(ISelectable | null)[]>([]);
|
|
|
|
|
|
|
|
// publish selectAll()
|
|
// publish selectAll()
|
|
|
useImperativeHandle(ref, () => ({
|
|
useImperativeHandle(ref, () => ({
|
|
|
selectAll: () => {
|
|
selectAll: () => {
|
|
|
const items = itemsRef.current;
|
|
const items = itemsRef.current;
|
|
|
if (items != null) {
|
|
if (items != null) {
|
|
|
- items.forEach(item => item != null && item.select());
|
|
|
|
|
|
|
+ items.forEach((item) => item != null && item.select());
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
deselectAll: () => {
|
|
deselectAll: () => {
|
|
|
const items = itemsRef.current;
|
|
const items = itemsRef.current;
|
|
|
if (items != null) {
|
|
if (items != null) {
|
|
|
- items.forEach(item => item != null && item.deselect());
|
|
|
|
|
|
|
+ items.forEach((item) => item != null && item.deselect());
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
}));
|
|
}));
|
|
|
|
|
|
|
|
- const clickItemHandler = useCallback((pageId: string) => {
|
|
|
|
|
- if (onPageSelected != null) {
|
|
|
|
|
- const selectedPage = pages.find(page => page.data._id === pageId);
|
|
|
|
|
- onPageSelected(selectedPage);
|
|
|
|
|
- }
|
|
|
|
|
- }, [onPageSelected, pages]);
|
|
|
|
|
|
|
+ const clickItemHandler = useCallback(
|
|
|
|
|
+ (pageId: string) => {
|
|
|
|
|
+ if (onPageSelected != null) {
|
|
|
|
|
+ const selectedPage = pages.find((page) => page.data._id === pageId);
|
|
|
|
|
+ onPageSelected(selectedPage);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ [onPageSelected, pages],
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
- let injectedPages: (IPageWithSearchMeta | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>)[] | undefined;
|
|
|
|
|
|
|
+ let injectedPages:
|
|
|
|
|
+ | (
|
|
|
|
|
+ | IPageWithSearchMeta
|
|
|
|
|
+ | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>
|
|
|
|
|
+ )[]
|
|
|
|
|
+ | undefined;
|
|
|
// inject data to list
|
|
// inject data to list
|
|
|
if (idToPageInfo != null) {
|
|
if (idToPageInfo != null) {
|
|
|
injectedPages = pages.map((page) => {
|
|
injectedPages = pages.map((page) => {
|
|
@@ -95,47 +109,60 @@ const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props>
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
- const duplicatedHandler = useCallback((fromPath, toPath) => {
|
|
|
|
|
- toastSuccess(t('duplicated_pages', { fromPath }));
|
|
|
|
|
-
|
|
|
|
|
- mutatePageTree();
|
|
|
|
|
- mutateRecentlyUpdated();
|
|
|
|
|
- mutateSearching();
|
|
|
|
|
- }, [t]);
|
|
|
|
|
-
|
|
|
|
|
- const renamedHandler = useCallback((path) => {
|
|
|
|
|
- toastSuccess(t('renamed_pages', { path }));
|
|
|
|
|
-
|
|
|
|
|
- mutatePageTree();
|
|
|
|
|
- mutateRecentlyUpdated();
|
|
|
|
|
- mutateSearching();
|
|
|
|
|
- }, [t]);
|
|
|
|
|
-
|
|
|
|
|
- const deletedHandler = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => {
|
|
|
|
|
- if (typeof pathOrPathsToDelete !== 'string') {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const path = pathOrPathsToDelete;
|
|
|
|
|
-
|
|
|
|
|
- if (isCompletely) {
|
|
|
|
|
- toastSuccess(t('deleted_pages_completely', { path }));
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- toastSuccess(t('deleted_pages', { path }));
|
|
|
|
|
- }
|
|
|
|
|
- mutatePageTree();
|
|
|
|
|
- mutateRecentlyUpdated();
|
|
|
|
|
- mutateSearching();
|
|
|
|
|
- }, [t]);
|
|
|
|
|
|
|
+ const duplicatedHandler = useCallback(
|
|
|
|
|
+ (fromPath, toPath) => {
|
|
|
|
|
+ toastSuccess(t('duplicated_pages', { fromPath }));
|
|
|
|
|
+
|
|
|
|
|
+ mutatePageTree();
|
|
|
|
|
+ mutateRecentlyUpdated();
|
|
|
|
|
+ mutateSearching();
|
|
|
|
|
+ },
|
|
|
|
|
+ [t],
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ const renamedHandler = useCallback(
|
|
|
|
|
+ (path) => {
|
|
|
|
|
+ toastSuccess(t('renamed_pages', { path }));
|
|
|
|
|
+
|
|
|
|
|
+ mutatePageTree();
|
|
|
|
|
+ mutateRecentlyUpdated();
|
|
|
|
|
+ mutateSearching();
|
|
|
|
|
+ },
|
|
|
|
|
+ [t],
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ const deletedHandler = useCallback(
|
|
|
|
|
+ (pathOrPathsToDelete, isRecursively, isCompletely) => {
|
|
|
|
|
+ if (typeof pathOrPathsToDelete !== 'string') {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const path = pathOrPathsToDelete;
|
|
|
|
|
+
|
|
|
|
|
+ if (isCompletely) {
|
|
|
|
|
+ toastSuccess(t('deleted_pages_completely', { path }));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ toastSuccess(t('deleted_pages', { path }));
|
|
|
|
|
+ }
|
|
|
|
|
+ mutatePageTree();
|
|
|
|
|
+ mutateRecentlyUpdated();
|
|
|
|
|
+ mutateSearching();
|
|
|
|
|
+ },
|
|
|
|
|
+ [t],
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
- <ul data-testid="search-result-list" className="page-list-ul list-group list-group-flush">
|
|
|
|
|
- { (injectedPages ?? pages).map((page, i) => {
|
|
|
|
|
|
|
+ <ul
|
|
|
|
|
+ data-testid="search-result-list"
|
|
|
|
|
+ className="page-list-ul list-group list-group-flush"
|
|
|
|
|
+ >
|
|
|
|
|
+ {(injectedPages ?? pages).map((page, i) => {
|
|
|
return (
|
|
return (
|
|
|
<PageListItemL
|
|
<PageListItemL
|
|
|
key={page.data._id}
|
|
key={page.data._id}
|
|
|
- ref={(c) => { itemsRef.current[i] = c }}
|
|
|
|
|
|
|
+ ref={(c) => {
|
|
|
|
|
+ itemsRef.current[i] = c;
|
|
|
|
|
+ }}
|
|
|
page={page}
|
|
page={page}
|
|
|
isEnableActions={!isGuestUser}
|
|
isEnableActions={!isGuestUser}
|
|
|
isReadOnlyUser={!!isReadOnlyUser}
|
|
isReadOnlyUser={!!isReadOnlyUser}
|
|
@@ -151,7 +178,6 @@ const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props>
|
|
|
})}
|
|
})}
|
|
|
</ul>
|
|
</ul>
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export const SearchResultList = forwardRef(SearchResultListSubstance);
|
|
export const SearchResultList = forwardRef(SearchResultListSubstance);
|