Просмотр исходного кода

create pagetitle component and pagepath component

WNomunomu 2 лет назад
Родитель
Сommit
2adf4aff0e

+ 2 - 1
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -53,6 +53,7 @@ import { useNextThemes } from '~/stores/use-next-themes';
 import { useGlobalSocket } from '~/stores/websocket';
 import loggerFactory from '~/utils/logger';
 
+import { PageHeader } from '../PageHeader/PageHeader';
 
 // import { ConflictDiffModal } from './PageEditor/ConflictDiffModal';
 // import { ConflictDiffModal } from './ConflictDiffModal';
@@ -565,7 +566,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
   return (
     <div data-testid="page-editor" id="page-editor" className={`flex-expand-vert ${props.visibility ? '' : 'd-none'}`}>
       <div className="flex-expand-vert justify-content-center align-items-center" style={{ minHeight: '72px' }}>
-        <div>Header</div>
+        <PageHeader />
       </div>
       <div className={`flex-expand-horiz ${props.visibility ? '' : 'd-none'}`}>
         <div className="page-editor-editor-container flex-expand-vert">

+ 25 - 0
apps/app/src/components/PageHeader/PageHeader.tsx

@@ -0,0 +1,25 @@
+import { useCurrentPagePath, useSWRxCurrentPage } from '~/stores/page';
+
+import { PagePath } from './PagePath';
+import { PageTitle } from './PageTitle';
+
+export const PageHeader = () => {
+  const { data: currentPagePath } = useCurrentPagePath();
+  const { data: currentPage } = useSWRxCurrentPage();
+
+  if (currentPage == null) {
+    return <></>;
+  }
+
+  return (
+    <>
+      <div className="pull-left">
+        <PagePath />
+        <PageTitle
+          currentPagePath={currentPagePath}
+          currentPage={currentPage}
+        />
+      </div>
+    </>
+  );
+};

+ 20 - 0
apps/app/src/components/PageHeader/PagePath.tsx

@@ -0,0 +1,20 @@
+export const PagePath = () => {
+
+  return (
+    <>
+      <div className="container">
+        <div className="row">
+          <div className="col-4">
+            <div>PagePath</div>
+          </div>
+          <div className="col-4">
+            <button type="button">編集ボタン</button>
+          </div>
+          <div className="col-4">
+            <button type="button">ページツリーボタン</button>
+          </div>
+        </div>
+      </div>
+    </>
+  );
+};

+ 101 - 0
apps/app/src/components/PageHeader/PageTitle.tsx

@@ -0,0 +1,101 @@
+import { FC, useState, useCallback } from 'react';
+
+import nodePath from 'path';
+
+import type { IPagePopulatedToShowRevision } from '@growi/core';
+import { pathUtils } from '@growi/core/dist/utils';
+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';
+
+
+type Props = {
+  currentPagePath?: string,
+  currentPage?: IPagePopulatedToShowRevision;
+}
+
+export const PageTitle: FC<Props> = (props) => {
+  const { currentPagePath, currentPage } = props;
+
+  const [isRenameInputShown, setRenameInputShown] = useState(false);
+  const { t } = useTranslation();
+
+  const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage();
+
+  const onRenamed = useCallback((fromPath: string | undefined, toPath: string) => {
+    mutatePageTree();
+    mutateSearching();
+    mutatePageList();
+
+    if (currentPagePath === fromPath || currentPagePath === toPath) {
+      mutateCurrentPage();
+    }
+  }, [currentPagePath, mutateCurrentPage]);
+
+  if (currentPage == null) {
+    return <></>;
+  }
+
+  const page = currentPage;
+
+  const pageName = nodePath.basename(currentPagePath ?? '') || '/';
+
+  const onClickPageNameHandler = () => {
+    setRenameInputShown(true);
+  };
+
+
+  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);
+    }
+  };
+
+  return (
+    <>
+      {isRenameInputShown ? (
+        <div className="flex-fill">
+          <ClosableTextInput
+            value={pageName}
+            placeholder={t('Input page name')}
+            onClickOutside={() => { setRenameInputShown(false) }}
+            onPressEnter={onPressEnterForRenameHandler}
+            validationTarget={ValidationTarget.PAGE}
+          />
+        </div>
+      ) : (
+        <div onClick={onClickPageNameHandler}>{pageName}</div>
+      )}
+    </>
+  );
+};