import React, { useCallback, useMemo, useRef, useState, } from 'react'; import { useTranslation } from 'react-i18next'; import { UncontrolledButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, } from 'reactstrap'; import { IFormattedSearchResult } from '~/interfaces/search'; import AppContainer from '~/client/services/AppContainer'; import { ISelectableAll, ISelectableAndIndeterminatable } from '~/client/interfaces/selectable-all'; import { toastSuccess } from '~/client/util/apiNotification'; import { useSWRxSearch, } from '~/stores/search'; import { ILegacyPrivatePage, useLegacyPrivatePagesMigrationModal, } from '~/stores/modal'; import PaginationWrapper from './PaginationWrapper'; import { OperateAllControl } from './SearchPage/OperateAllControl'; import { IReturnSelectedPageIds, SearchPageBase, usePageDeleteModalForBulkDeletion } from './SearchPage2/SearchPageBase'; import { MenuItemType } from './Common/Dropdown/PageItemControl'; import { LegacyPrivatePagesMigrationModal } from './LegacyPrivatePagesMigrationModal'; import SearchControl from './SearchPage/SearchControl'; import { useSWRxV5MigrationStatus } from '~/stores/page-listing'; // TODO: replace with "customize:showPageLimitationS" const INITIAL_PAGING_SIZE = 20; const initQ = '/'; /** * SearchResultListHead */ type SearchResultListHeadProps = { searchResult: IFormattedSearchResult, offset: number, pagingSize: number, onPagingSizeChanged: (size: number) => void, } const SearchResultListHead = React.memo((props: SearchResultListHeadProps): JSX.Element => { const { t } = useTranslation(); const { data: migrationStatus } = useSWRxV5MigrationStatus(); if (migrationStatus == null) { return <>; } const { searchResult, offset, pagingSize, onPagingSizeChanged, } = props; const { took, total, hitsCount } = searchResult.meta; const leftNum = offset + 1; const rightNum = offset + hitsCount; const isSuccess = migrationStatus.migratablePagesCount === 0; if (isSuccess) { return (

{t('private_legacy_pages.nopages_title')}

{t('private_legacy_pages.nopages_desc1')}
{/* eslint-disable-next-line react/no-danger */}

); } return ( <>
{t('search_result.result_meta')} {`${leftNum}-${rightNum}`} / {total} { took != null && ( ({took}ms) ) }

{t('private_legacy_pages.alert_title')}

{t('private_legacy_pages.alert_desc1', { delete_all_selected_page: t('search_result.delete_all_selected_page') })}
{/* eslint-disable-next-line react/no-danger */}

); }); /** * LegacyPage */ type Props = { appContainer: AppContainer, } export const PrivateLegacyPages = (props: Props): JSX.Element => { const { t } = useTranslation(); const { appContainer, } = props; const [keyword, setKeyword] = useState(initQ); const [offset, setOffset] = useState(0); const [limit, setLimit] = useState(INITIAL_PAGING_SIZE); const [isControlEnabled, setControlEnabled] = useState(false); const selectAllControlRef = useRef(null); const searchPageBaseRef = useRef(null); const { data, conditions, mutate } = useSWRxSearch(keyword, 'PrivateLegacyPages', { offset, limit, includeUserPages: true, includeTrashPages: false, }); const searchInvokedHandler = useCallback((_keyword: string) => { setKeyword(_keyword); setOffset(0); }, []); const { open: openModal, close: closeModal } = useLegacyPrivatePagesMigrationModal(); const selectAllCheckboxChangedHandler = useCallback((isChecked: boolean) => { const instance = searchPageBaseRef.current; if (instance == null) { return; } if (isChecked) { instance.selectAll(); setControlEnabled(true); } else { instance.deselectAll(); setControlEnabled(false); } }, []); const selectedPagesByCheckboxesChangedHandler = useCallback((selectedCount: number, totalCount: number) => { const instance = selectAllControlRef.current; if (instance == null) { return; } if (selectedCount === 0) { instance.deselect(); setControlEnabled(false); } else if (selectedCount === totalCount) { instance.select(); setControlEnabled(true); } else { instance.setIndeterminate(); setControlEnabled(true); } }, []); // for bulk deletion const deleteAllButtonClickedHandler = usePageDeleteModalForBulkDeletion(data, searchPageBaseRef, () => mutate()); const convertMenuItemClickedHandler = useCallback(() => { if (data == null) { return; } const instance = searchPageBaseRef.current; if (instance == null || instance.getSelectedPageIds == null) { return; } const selectedPageIds = instance.getSelectedPageIds(); if (selectedPageIds.size === 0) { return; } const selectedPages = data.data .filter(pageWithMeta => selectedPageIds.has(pageWithMeta.data._id)) .map(pageWithMeta => ({ pageId: pageWithMeta.data._id, path: pageWithMeta.data.path } as ILegacyPrivatePage)); openModal( selectedPages, () => { toastSuccess(t('Successfully requested')); closeModal(); mutate(); }, ); }, [data, mutate, openModal, closeModal]); const pagingSizeChangedHandler = useCallback((pagingSize: number) => { setOffset(0); setLimit(pagingSize); mutate(); }, [mutate]); const pagingNumberChangedHandler = useCallback((activePage: number) => { setOffset((activePage - 1) * limit); mutate(); }, [limit, mutate]); const hitsCount = data?.meta.hitsCount; const searchControlAllAction = useMemo(() => { const isCheckboxDisabled = hitsCount === 0; return (
{t('private_legacy_pages.bulk_operation')} {t('private_legacy_pages.convert_all_selected_pages')} {t('search_result.delete_all_selected_page')}
); }, [convertMenuItemClickedHandler, deleteAllButtonClickedHandler, hitsCount, isControlEnabled, selectAllCheckboxChangedHandler, t]); const searchControl = useMemo(() => { return ( ); }, [searchInvokedHandler, searchControlAllAction]); const searchResultListHead = useMemo(() => { if (data == null) { return <>; } return ( ); }, [data, limit, offset, pagingSizeChangedHandler]); const searchPager = useMemo(() => { // when pager is not needed if (data == null || data.meta.hitsCount === data.meta.total) { return <>; } const { total } = data.meta; const { offset, limit } = conditions; return ( ); }, [conditions, data, pagingNumberChangedHandler]); return ( <> ); };