import React, { useEffect, useState, useMemo, useCallback, } from 'react'; import { Origin } from '@growi/core'; import { pagePathUtils, pathUtils } from '@growi/core/dist/utils'; import { format } from 'date-fns'; import { useTranslation } from 'next-i18next'; import { Modal, ModalHeader, ModalBody, UncontrolledButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, } from 'reactstrap'; import { debounce } from 'throttle-debounce'; import { useCreateTemplatePage } from '~/client/services/create-page'; import { useCreatePageAndTransit } from '~/client/services/create-page/use-create-page-and-transit'; import { useToastrOnError } from '~/client/services/use-toastr-on-error'; import { useCurrentUser, useIsSearchServiceReachable } from '~/stores/context'; import { usePageCreateModal } from '~/stores/modal'; import PagePathAutoComplete from './PagePathAutoComplete'; import styles from './PageCreateModal.module.scss'; const { isCreatablePage, isUsersHomepage, } = pagePathUtils; const PageCreateModal: React.FC = () => { const { t } = useTranslation(); const { data: currentUser } = useCurrentUser(); const { data: pageCreateModalData, close: closeCreateModal } = usePageCreateModal(); const path = pageCreateModalData?.path; const isOpened = pageCreateModalData?.isOpened ?? false; const { createAndTransit } = useCreatePageAndTransit(); const { createTemplate } = useCreateTemplatePage(); 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 todaysParentPath = [userHomepagePath, t('create_page_dropdown.todays.memo', { ns: 'commons' }), now].join('/'); const [todayInput, setTodayInput] = useState(''); const [pageNameInput, setPageNameInput] = useState(pageNameInputInitialValue); const [template, setTemplate] = useState(null); const [isMatchedWithUserHomepagePath, setIsMatchedWithUserHomepagePath] = useState(false); const checkIsUsersHomepageDebounce = useMemo(() => { const checkIsUsersHomepage = () => { setIsMatchedWithUserHomepagePath(isUsersHomepage(pageNameInput)); }; return debounce(1000, checkIsUsersHomepage); }, [pageNameInput]); useEffect(() => { if (isOpened) { checkIsUsersHomepageDebounce(); } }, [isOpened, checkIsUsersHomepageDebounce, pageNameInput]); function transitBySubmitEvent(e, transitHandler) { // prevent page transition by submit e.preventDefault(); transitHandler(); } /** * change todayInput * @param {string} value */ function onChangeTodayInputHandler(value) { setTodayInput(value); } /** * change template * @param {string} value */ function onChangeTemplateHandler(value) { setTemplate(value); } /** * access today page */ const createTodayPage = useCallback(async() => { const joinedPath = [todaysParentPath, todayInput].join('/'); return createAndTransit( { path: joinedPath, wip: true, origin: Origin.View }, { shouldCheckPageExists: true, onTerminated: closeCreateModal }, ); }, [closeCreateModal, createAndTransit, todayInput, todaysParentPath]); /** * access input page */ const createInputPage = useCallback(async() => { return createAndTransit( { path: pageNameInput, wip: true, origin: Origin.View, }, { shouldCheckPageExists: true, onTerminated: closeCreateModal }, ); }, [closeCreateModal, createAndTransit, pageNameInput]); /** * access template page */ const createTemplatePage = useCallback(async() => { const label = (template === 'children') ? '_template' : '__template'; await createTemplate?.(label); closeCreateModal(); }, [closeCreateModal, createTemplate, template]); const createTodaysMemoWithToastr = useToastrOnError(createTodayPage); const createInputPageWithToastr = useToastrOnError(createInputPage); const createTemplateWithToastr = useToastrOnError(createTemplatePage); function renderCreateTodayForm() { if (!isOpened) { return <>; } return (

{t('create_page_dropdown.todays.desc', { ns: 'commons' })}

{todaysParentPath}/
{ transitBySubmitEvent(e, createTodaysMemoWithToastr) }}> onChangeTodayInputHandler(e.target.value)} />
); } function renderInputPageForm() { if (!isOpened) { return <>; } return (

{t('Create under')}

{isReachable ? ( setPageNameInput(value)} autoFocus /> ) : (
{ transitBySubmitEvent(e, createInputPageWithToastr) }}> 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;