import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; import { Modal, ModalHeader, ModalBody, ModalFooter, } from 'reactstrap'; import { withTranslation } from 'react-i18next'; import { debounce } from 'throttle-debounce'; import { withUnstatedContainers } from './UnstatedUtils'; import { toastError } from '../util/apiNotification'; import AppContainer from '../services/AppContainer'; import PageContainer from '../services/PageContainer'; import PagePathAutoComplete from './PagePathAutoComplete'; import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; import ComparePathsTable from './ComparePathsTable'; import DuplicatePathsTable from './DuplicatedPathsTable'; const LIMIT_FOR_LIST = 10; const PageDuplicateModal = (props) => { const { t, appContainer, pageContainer } = props; const config = appContainer.getConfig(); const isReachable = config.isSearchServiceReachable; const { pageId, path } = pageContainer.state; const { crowi } = appContainer.config; const [pageNameInput, setPageNameInput] = useState(path); const [errs, setErrs] = useState(null); const [subordinatedPages, setSubordinatedPages] = useState([]); const [isDuplicateRecursively, setIsDuplicateRecursively] = useState(true); const [isDuplicateRecursivelyWithoutExistPath, setIsDuplicateRecursivelyWithoutExistPath] = useState(true); const [isDuplicateRecursivelyExist] = useState(false); const [existingPaths, setExistingPaths] = useState([]); const checkExistPaths = async(newParentPath) => { try { const res = await appContainer.apiv3Get('/page/exist-paths', { fromPath: path, toPath: newParentPath }); const { existPaths } = res.data; setExistingPaths(existPaths); } catch (err) { setErrs(err); toastError(t('modal_rename.label.Fail to get exist path')); } }; // eslint-disable-next-line react-hooks/exhaustive-deps const checkExistPathsDebounce = useCallback( debounce(1000, checkExistPaths), [], ); useEffect(() => { if (pageNameInput !== path) { checkExistPathsDebounce(pageNameInput, subordinatedPages); } }, [pageNameInput, subordinatedPages, path, checkExistPathsDebounce]); /** * change pageNameInput for PagePathAutoComplete * @param {string} value */ function ppacInputChangeHandler(value) { setErrs(null); setPageNameInput(value); } /** * change pageNameInput * @param {string} value */ function inputChangeHandler(value) { setErrs(null); setPageNameInput(value); } function changeIsDuplicateRecursivelyHandler() { setIsDuplicateRecursively(!isDuplicateRecursively); } const getSubordinatedList = useCallback(async() => { try { const res = await appContainer.apiv3Get('/pages/subordinated-list', { path, limit: LIMIT_FOR_LIST }); const { subordinatedPaths } = res.data; setSubordinatedPages(subordinatedPaths); } catch (err) { setErrs(err); toastError(t('modal_duplicate.label.Fail to get subordinated pages')); } }, [appContainer, path, t]); useEffect(() => { if (props.isOpen) { getSubordinatedList(); } }, [props.isOpen, getSubordinatedList]); function changeIsDuplicateRecursivelyWithoutExistPathHandler() { setIsDuplicateRecursivelyWithoutExistPath(!isDuplicateRecursivelyWithoutExistPath); } async function duplicate() { setErrs(null); try { await appContainer.apiv3Post('/pages/duplicate', { pageId, pageNameInput, isDuplicateRecursively }); window.location.href = encodeURI(`${pageNameInput}?duplicated=${path}`); } catch (err) { setErrs(err); } } function ppacSubmitHandler() { duplicate(); } return ( { t('modal_duplicate.label.Duplicate page') }

{path}

{crowi.url}
{isReachable ? ( ) : ( inputChangeHandler(e.target.value)} required /> )}
{isDuplicateRecursively && } {isDuplicateRecursively && existingPaths.length !== 0 && } {isDuplicateRecursively && (
)}
); }; /** * Wrapper component for using unstated */ const PageDuplicateModallWrapper = withUnstatedContainers(PageDuplicateModal, [AppContainer, PageContainer]); PageDuplicateModal.propTypes = { t: PropTypes.func.isRequired, // i18next appContainer: PropTypes.instanceOf(AppContainer).isRequired, pageContainer: PropTypes.instanceOf(PageContainer).isRequired, isOpen: PropTypes.bool.isRequired, onClose: PropTypes.func.isRequired, }; export default withTranslation()(PageDuplicateModallWrapper);