Explorar o código

create ChildPageCreateButton component

WNomunomu %!s(int64=2) %!d(string=hai) anos
pai
achega
790773babc

+ 134 - 0
apps/app/src/components/Sidebar/PageTree/PageTreeItemForModal.tsx

@@ -0,0 +1,134 @@
+import React, {
+  useCallback, useState, FC, ReactNode,
+} from 'react';
+
+import nodePath from 'path';
+
+import { pathUtils, pagePathUtils } from '@growi/core';
+import { useTranslation } from 'next-i18next';
+import { useDrag, useDrop } from 'react-dnd';
+
+import { apiv3Put, apiv3Post } from '~/client/util/apiv3-client';
+import { ValidationTarget } from '~/client/util/input-validator';
+import { toastWarning, toastError, toastSuccess } from '~/client/util/toastr';
+import { IPageHasId } from '~/interfaces/page';
+import { mutatePageTree, useSWRxPageChildren } from '~/stores/page-listing';
+import { usePageTreeDescCountMap } from '~/stores/ui';
+import loggerFactory from '~/utils/logger';
+
+import ClosableTextInput from '../../Common/ClosableTextInput';
+
+import { ItemNode } from './ItemNode';
+import SimpleItem, { SimpleItemProps } from './SimpleItem';
+
+const logger = loggerFactory('growi:cli:Item');
+
+type NotDraggableProps = {
+  children: ReactNode,
+};
+const NotDraggableForClosableTextInput = (props: NotDraggableProps): JSX.Element => {
+  return <div draggable onDragStart={e => e.preventDefault()}>{props.children}</div>;
+};
+
+const ChildPageCreateButton = (props) => {
+  const { t } = useTranslation();
+
+  const {
+    page, isOpen: _isOpen = false, isEnableActions, children,
+  } = props;
+
+  const [currentChildren, setCurrentChildren] = useState(children);
+  const [isNewPageInputShown, setNewPageInputShown] = useState(false);
+  const [isCreating, setCreating] = useState(false);
+  const [isOpen, setIsOpen] = useState(_isOpen);
+
+  const { data, mutate: mutateChildren } = useSWRxPageChildren(isOpen ? page._id : null);
+
+  // descendantCount
+  const { getDescCount } = usePageTreeDescCountMap();
+  const descendantCount = getDescCount(page._id) || page.descendantCount || 0;
+
+  const isChildrenLoaded = currentChildren?.length > 0;
+  const hasDescendants = descendantCount > 0 || isChildrenLoaded;
+
+  const onPressEnterForCreateHandler = async(inputText: string) => {
+    setNewPageInputShown(false);
+    const parentPath = pathUtils.addTrailingSlash(page.path as string);
+    const newPagePath = nodePath.resolve(parentPath, inputText);
+    const isCreatable = pagePathUtils.isCreatablePage(newPagePath);
+
+    if (!isCreatable) {
+      toastWarning(t('you_can_not_create_page_with_this_name'));
+      return;
+    }
+
+    try {
+      setCreating(true);
+
+      await apiv3Post('/pages/', {
+        path: newPagePath,
+        body: undefined,
+        grant: page.grant,
+        grantUserGroupId: page.grantedGroup,
+      });
+
+      mutateChildren();
+
+      if (!hasDescendants) {
+        setIsOpen(true);
+      }
+
+      toastSuccess(t('successfully_saved_the_page'));
+    }
+    catch (err) {
+      toastError(err);
+    }
+    finally {
+      setCreating(false);
+    }
+  };
+
+  return (
+    <>
+      {isEnableActions && isNewPageInputShown && (
+        <div className="flex-fill">
+          <NotDraggableForClosableTextInput>
+            <ClosableTextInput
+              placeholder={t('Input page name')}
+              onClickOutside={() => { setNewPageInputShown(false) }}
+              onPressEnter={onPressEnterForCreateHandler}
+              validationTarget={ValidationTarget.PAGE}
+            />
+          </NotDraggableForClosableTextInput>
+        </div>
+      )}
+    </>
+  );
+};
+
+type Optional = 'itemRef' | 'itemClass' | 'mainClassName';
+type PageTreeItemProps = Omit<SimpleItemProps, Optional> & {key};
+
+export const PageTreeItemForModal = (props) => {
+  const {
+    itemNode, isOpen: _isOpen = false, onRenamed,
+  } = props;
+  const { page } = itemNode;
+  const [isOpen, setIsOpen] = useState(_isOpen);
+  const [shouldHide, setShouldHide] = useState(false);
+  const { mutate: mutateChildren } = useSWRxPageChildren(isOpen ? page._id : null);
+
+  return (
+    <SimpleItem
+      key={props.key}
+      targetPathOrId={props.targetPathOrId}
+      itemNode={props.itemNode}
+      isOpen
+      isEnableActions={props.isEnableActions}
+      isReadOnlyUser={props.isReadOnlyUser}
+      onRenamed={props.onRenamed}
+      onClickDuplicateMenuItem={props.onClickDuplicateMenuItem}
+      onClickDeleteMenuItem={props.onClickDeleteMenuItem}
+    />
+  );
+};