import React, { useEffect, useState, useMemo, useCallback, } from 'react'; import { pagePathUtils, pathUtils } from '@growi/core/dist/utils'; import { format } from 'date-fns'; import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; import { Modal, ModalHeader, ModalBody, UncontrolledButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, } from 'reactstrap'; import { debounce } from 'throttle-debounce'; import { toastError } from '~/client/util/toastr'; import { useCurrentUser, useIsSearchServiceReachable } from '~/stores/context'; import { usePageCreateModal } from '~/stores/modal'; import { EditorMode, useEditorMode } from '~/stores/ui'; import PagePathAutoComplete from './PagePathAutoComplete'; import styles from './PageCreateModal.module.scss'; const { isCreatablePage, generateEditorPath, isUsersHomepage, } = pagePathUtils; const PageCreateModal = () => { const { t } = useTranslation(); const router = useRouter(); const { data: currentUser } = useCurrentUser(); const { data: pageCreateModalData, close: closeCreateModal } = usePageCreateModal(); const { isOpened, path } = pageCreateModalData; const { data: isReachable } = useIsSearchServiceReachable(); const pathname = path || ''; const userHomepagePath = pagePathUtils.userHomepagePath(currentUser); const isCreatable = isCreatablePage(pathname) || isUsersHomepage(pathname); const pageNameInputInitialValue = isCreatable ? pathUtils.addTrailingSlash(pathname) : '/'; const now = format(new Date(), 'yyyy/MM/dd'); const { mutate: mutateEditorMode } = useEditorMode(); const [todayInput1, setTodayInput1] = useState(t('Memo')); const [todayInput2, setTodayInput2] = useState(''); const [pageNameInput, setPageNameInput] = useState(pageNameInputInitialValue); const [template, setTemplate] = useState(null); const [isMatchedWithUserHomepagePath, setIsMatchedWithUserHomepagePath] = useState(false); // ensure pageNameInput is synced with selectedPagePath || currentPagePath useEffect(() => { if (isOpened) { setPageNameInput(isCreatable ? pathUtils.addTrailingSlash(pathname) : '/'); } }, [isOpened, pathname, isCreatable]); useEffect(() => { setTodayInput1(t('Memo')); }, [t]); const checkIsUsersHomepageDebounce = useMemo(() => { const checkIsUsersHomepage = () => { setIsMatchedWithUserHomepagePath(isUsersHomepage(pageNameInput)); }; return debounce(1000, checkIsUsersHomepage); }, [pageNameInput]); useEffect(() => { if (isOpened) { checkIsUsersHomepageDebounce(pageNameInput); } }, [isOpened, checkIsUsersHomepageDebounce, pageNameInput]); function transitBySubmitEvent(e, transitHandler) { // prevent page transition by submit e.preventDefault(); transitHandler(); } /** * change todayInput1 * @param {string} value */ function onChangeTodayInput1Handler(value) { setTodayInput1(value); } /** * change todayInput2 * @param {string} value */ function onChangeTodayInput2Handler(value) { setTodayInput2(value); } /** * change template * @param {string} value */ function onChangeTemplateHandler(value) { setTemplate(value); } /** * join path, check if creatable, then redirect * @param {string} paths */ const redirectToEditor = useCallback(async(...paths) => { try { const editorPath = generateEditorPath(...paths); await router.push(editorPath); mutateEditorMode(EditorMode.Editor); // close modal closeCreateModal(); } catch (err) { toastError(err); } }, [closeCreateModal, mutateEditorMode, router]); /** * access today page */ function createTodayPage() { let tmpTodayInput1 = todayInput1; if (tmpTodayInput1 === '') { tmpTodayInput1 = t('Memo'); } redirectToEditor(userHomepagePath, tmpTodayInput1, now, todayInput2); } /** * access input page */ function createInputPage() { redirectToEditor(pageNameInput); } const ppacSubmitHandler = useCallback((input) => { redirectToEditor(input); }, [redirectToEditor]); /** * access template page */ function createTemplatePage(e) { const pageName = (template === 'children') ? '_template' : '__template'; redirectToEditor(pathname, pageName); } function renderCreateTodayForm() { if (!isOpened) { return <>; } return (

{t("Create today's")}

{userHomepagePath}/
transitBySubmitEvent(e, createTodayPage)}> onChangeTodayInput1Handler(e.target.value)} />
/{now}/
transitBySubmitEvent(e, createTodayPage)}> onChangeTodayInput2Handler(e.target.value)} />
); } function renderInputPageForm() { if (!isOpened) { return <>; } return (

{t('Create under')}

{isReachable ? ( setPageNameInput(value)} autoFocus /> ) : (
transitBySubmitEvent(e, createInputPage)}> setPageNameInput(e.target.value)} required />
)}
{ isMatchedWithUserHomepagePath && (

Error: Cannot create page under /user page directory.

) }
); } function renderTemplatePageForm() { if (!isOpened) { return <>; } return (

{t('template.modal_label.Create template under')}
{pathname}

{template == null && t('template.option_label.select')} {template === 'children' && t('template.children.label')} {template === 'descendants' && t('template.descendants.label')} onChangeTemplateHandler('children')}> {t('template.children.label')} (_template)
- {t('template.children.desc')}
onChangeTemplateHandler('descendants')}> {t('template.descendants.label')} (__template)
- {t('template.descendants.desc')}
); } return ( closeCreateModal()} data-testid="page-create-modal" className={`grw-create-page ${styles['grw-create-page']}`} autoFocus={false} > closeCreateModal()} className="bg-primary text-light"> {t('New Page')} {renderCreateTodayForm()} {renderInputPageForm()} {renderTemplatePageForm()} ); }; export default PageCreateModal;