|
|
@@ -1,83 +1,39 @@
|
|
|
-import { FC, useCallback } from 'react';
|
|
|
+import { FC } from 'react';
|
|
|
+import type { Dispatch, SetStateAction } from 'react';
|
|
|
|
|
|
-import nodePath from 'path';
|
|
|
-
|
|
|
-import { pathUtils } from '@growi/core/dist/utils';
|
|
|
+import type { IPagePopulatedToShowRevision } from '@growi/core';
|
|
|
import { useTranslation } from 'next-i18next';
|
|
|
|
|
|
-import { apiv3Put } from '~/client/util/apiv3-client';
|
|
|
import { ValidationTarget } from '~/client/util/input-validator';
|
|
|
-import { toastSuccess, toastError } from '~/client/util/toastr';
|
|
|
-import { useSWRMUTxCurrentPage } from '~/stores/page';
|
|
|
-import { mutatePageTree, mutatePageList } from '~/stores/page-listing';
|
|
|
-import { mutateSearching } from '~/stores/search';
|
|
|
|
|
|
import ClosableTextInput from '../Common/ClosableTextInput';
|
|
|
|
|
|
+import { usePagePathSubmitHandler } from './page-header-utils';
|
|
|
+
|
|
|
+type StateHandler = {
|
|
|
+ isRenameInputShown: boolean
|
|
|
+ setRenameInputShown: Dispatch<SetStateAction<boolean>>
|
|
|
+}
|
|
|
|
|
|
type Props = {
|
|
|
- currentPagePath
|
|
|
- currentPage
|
|
|
- stateHandler
|
|
|
- inputValue
|
|
|
- CustomComponent
|
|
|
+ currentPagePath: string
|
|
|
+ currentPage: IPagePopulatedToShowRevision
|
|
|
+ stateHandler: StateHandler
|
|
|
+ inputValue: string
|
|
|
+ CustomComponent: () => JSX.Element
|
|
|
+ handleInputChange?: (string) => void
|
|
|
}
|
|
|
|
|
|
export const TextInputForPageTitleAndPath: FC<Props> = (props) => {
|
|
|
const {
|
|
|
- currentPagePath, currentPage, stateHandler, inputValue, CustomComponent,
|
|
|
+ currentPagePath, currentPage, stateHandler, inputValue, CustomComponent, handleInputChange,
|
|
|
} = props;
|
|
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
|
- const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage();
|
|
|
-
|
|
|
const { isRenameInputShown, setRenameInputShown } = stateHandler;
|
|
|
|
|
|
- const page = currentPage;
|
|
|
-
|
|
|
- const onRenamed = useCallback((fromPath: string | undefined, toPath: string) => {
|
|
|
- mutatePageTree();
|
|
|
- mutateSearching();
|
|
|
- mutatePageList();
|
|
|
-
|
|
|
- if (currentPagePath === fromPath || currentPagePath === toPath) {
|
|
|
- mutateCurrentPage();
|
|
|
- }
|
|
|
- }, [currentPagePath, mutateCurrentPage]);
|
|
|
-
|
|
|
- if (currentPage == null) {
|
|
|
- return <></>;
|
|
|
- }
|
|
|
-
|
|
|
- const onPressEnterForRenameHandler = async(inputText: string) => {
|
|
|
- const parentPath = pathUtils.addTrailingSlash(nodePath.dirname(page.path ?? ''));
|
|
|
- const newPagePath = nodePath.resolve(parentPath, inputText);
|
|
|
-
|
|
|
- if (newPagePath === page.path) {
|
|
|
- setRenameInputShown(false);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- setRenameInputShown(false);
|
|
|
- await apiv3Put('/pages/rename', {
|
|
|
- pageId: page._id,
|
|
|
- revisionId: page.revision._id,
|
|
|
- newPagePath,
|
|
|
- });
|
|
|
-
|
|
|
- if (onRenamed != null) {
|
|
|
- onRenamed(page.path, newPagePath);
|
|
|
- }
|
|
|
-
|
|
|
- toastSuccess(t('renamed_pages', { path: page.path }));
|
|
|
- }
|
|
|
- catch (err) {
|
|
|
- setRenameInputShown(true);
|
|
|
- toastError(err);
|
|
|
- }
|
|
|
- };
|
|
|
+ const pagePathSubmitHandler = usePagePathSubmitHandler(currentPage, currentPagePath, setRenameInputShown);
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
@@ -87,8 +43,9 @@ export const TextInputForPageTitleAndPath: FC<Props> = (props) => {
|
|
|
value={inputValue}
|
|
|
placeholder={t('Input page name')}
|
|
|
onClickOutside={() => { setRenameInputShown(false) }}
|
|
|
- onPressEnter={onPressEnterForRenameHandler}
|
|
|
+ onPressEnter={pagePathSubmitHandler}
|
|
|
validationTarget={ValidationTarget.PAGE}
|
|
|
+ handleInputChange={handleInputChange}
|
|
|
/>
|
|
|
</div>
|
|
|
) : (
|