import React, { useEffect, useState, useMemo, useCallback, } from 'react'; import path from 'path'; import { Origin } from '@growi/core'; import { pagePathUtils, pathUtils } from '@growi/core/dist/utils'; import { normalizePath } from '@growi/core/dist/utils/path-utils'; import { format } from 'date-fns/format'; 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 { useCreatePage } from '~/client/services/create-page/use-create-page'; import { useToastrOnError } from '~/client/services/use-toastr-on-error'; import { useCurrentUser, useIsSearchServiceReachable } from '~/stores-universal/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 isOpened = pageCreateModalData?.isOpened ?? false; const { create } = useCreatePage(); const { createTemplate } = useCreateTemplatePage(); const { data: isReachable } = useIsSearchServiceReachable(); const pathname = pageCreateModalData?.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 create( { path: joinedPath, parentPath: todaysParentPath, wip: true, origin: Origin.View, }, { onTerminated: closeCreateModal }, ); }, [closeCreateModal, create, todayInput, todaysParentPath]); /** * access input page */ const createInputPage = useCallback(async() => { const targetPath = normalizePath(pageNameInput); const parentPath = path.dirname(targetPath); return create( { path: targetPath, parentPath, wip: true, origin: Origin.View, }, { onTerminated: closeCreateModal }, ); }, [closeCreateModal, create, 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 (