| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import React, {
- forwardRef,
- ForwardRefRenderFunction, useCallback, useImperativeHandle, useRef,
- } from 'react';
- import {
- type IPageInfoForListing, type IPageWithMeta, isIPageInfoForListing,
- } from '@growi/core';
- import { useTranslation } from 'next-i18next';
- import { ISelectable, ISelectableAll } from '~/client/interfaces/selectable-all';
- import { toastSuccess } from '~/client/util/toastr';
- import { IPageSearchMeta, IPageWithSearchMeta } from '~/interfaces/search';
- import { useIsGuestUser, useIsReadOnlyUser } from '~/stores/context';
- import { mutatePageTree, useSWRxPageInfoForList } from '~/stores/page-listing';
- import { mutateSearching } from '~/stores/search';
- import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
- import { PageListItemL } from '../PageList/PageListItemL';
- 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;
- const { t } = useTranslation();
- const pageIdsWithNoSnippet = pages
- .filter(page => (page.meta?.elasticSearchResult?.snippet?.length ?? 0) === 0)
- .map(page => page.data._id);
- const { data: isGuestUser } = useIsGuestUser();
- const { data: isReadOnlyUser } = useIsReadOnlyUser();
- const { data: idToPageInfo } = useSWRxPageInfoForList(pageIdsWithNoSnippet, null, true, true);
- const itemsRef = useRef<(ISelectable|null)[]>([]);
- // publish selectAll()
- useImperativeHandle(ref, () => ({
- selectAll: () => {
- const items = itemsRef.current;
- if (items != null) {
- items.forEach(item => item != null && item.select());
- }
- },
- deselectAll: () => {
- const items = itemsRef.current;
- if (items != null) {
- 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]);
- let injectedPages: (IPageWithSearchMeta | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>)[] | undefined;
- // inject data to list
- if (idToPageInfo != null) {
- injectedPages = pages.map((page) => {
- const pageInfo = idToPageInfo[page.data._id];
- if (!isIPageInfoForListing(pageInfo)) {
- // return as is
- return page;
- }
- return {
- data: page.data,
- meta: {
- ...page.meta,
- ...pageInfo,
- },
- } as IPageWithMeta<IPageInfoForListing & IPageSearchMeta>;
- });
- }
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const duplicatedHandler = useCallback((fromPath, toPath) => {
- toastSuccess(t('duplicated_pages', { fromPath }));
- mutatePageTree();
- mutateSearching();
- }, [t]);
- const renamedHandler = useCallback((path) => {
- toastSuccess(t('renamed_pages', { path }));
- mutatePageTree();
- 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();
- mutateSearching();
- }, [t]);
- return (
- <ul data-testid="search-result-list" className="page-list-ul list-group list-group-flush">
- { (injectedPages ?? pages).map((page, i) => {
- return (
- <PageListItemL
- key={page.data._id}
- // eslint-disable-next-line no-return-assign
- ref={c => itemsRef.current[i] = c}
- page={page}
- isEnableActions={!isGuestUser}
- isReadOnlyUser={!!isReadOnlyUser}
- isSelected={page.data._id === selectedPageId}
- forceHideMenuItems={forceHideMenuItems}
- onClickItem={clickItemHandler}
- onCheckboxChanged={props.onCheckboxChanged}
- onPageDuplicated={duplicatedHandler}
- onPageRenamed={renamedHandler}
- onPageDeleted={deletedHandler}
- />
- );
- })}
- </ul>
- );
- };
- export const SearchResultList = forwardRef(SearchResultListSubstance);
|