Parcourir la source

create new page button handler

ryoji-s il y a 2 ans
Parent
commit
bc5e7bdab3

+ 30 - 7
apps/app/src/components/Sidebar/PageCreateButton.tsx

@@ -2,8 +2,16 @@ import React, { useCallback, useState } from 'react';
 
 import { useRouter } from 'next/router';
 
+import { apiv3Post } from '~/client/util/apiv3-client';
+import { toastError } from '~/client/util/toastr';
+import { useSWRxCurrentPage } from '~/stores/page';
+import loggerFactory from '~/utils/logger';
+
+const logger = loggerFactory('growi:cli:PageCreateButton');
+
 export const PageCreateButton = React.memo((): JSX.Element => {
   const router = useRouter();
+  const { data: currentPage, isLoading } = useSWRxCurrentPage();
 
   const [isHovered, setIsHovered] = useState(false);
 
@@ -16,12 +24,27 @@ export const PageCreateButton = React.memo((): JSX.Element => {
   };
 
   const iconName = 'create';
-  const isSelected = true;
-  // TODO: create page directly
-  // TODO: https://redmine.weseek.co.jp/issues/132680s
-  const onCreateNewPageButtonHandler = useCallback(() => {
-    // router.push(`${router.pathname}#edit`);
-  }, [router]);
+  const onCreateNewPageButtonHandler = useCallback(async() => {
+    if (isLoading) return;
+
+    try {
+      const parentPath = currentPage?.path || '/';
+
+      const response = await apiv3Post('/pages/', {
+        path: parentPath,
+        body: undefined,
+        grant: currentPage?.grant || 1,
+        grantUserGroupId: currentPage?.grantedGroup || null,
+        shouldGeneratePath: true,
+      });
+
+      router.push(`${response.data.page.path}#edit`);
+    }
+    catch (err) {
+      logger.warn(err);
+      toastError(err);
+    }
+  }, [currentPage, isLoading, router]);
   const onCreateTodaysButtonHandler = useCallback(() => {
     // router.push(`${router.pathname}#edit`);
   }, [router]);
@@ -44,7 +67,7 @@ export const PageCreateButton = React.memo((): JSX.Element => {
     >
       <div className="btn-group">
         <button
-          className={`d-block btn btn-primary ${isSelected ? 'active' : ''}`}
+          className="d-block btn btn-primary"
           onClick={onCreateNewPageButtonHandler}
           type="button"
           data-testid="grw-sidebar-nav-page-create-button"

+ 31 - 3
apps/app/src/server/routes/apiv3/pages.js

@@ -175,6 +175,7 @@ module.exports = (crowi) => {
       body('isSlackEnabled').if(value => value != null).isBoolean().withMessage('isSlackEnabled must be boolean'),
       body('slackChannels').if(value => value != null).isString().withMessage('slackChannels must be string'),
       body('pageTags').if(value => value != null).isArray().withMessage('pageTags must be array'),
+      body('shouldGeneratePath').optional().isBoolean().withMessage('shouldGeneratePath is must be boolean or undefined'),
     ],
     renamePage: [
       body('pageId').isMongoId().withMessage('pageId is required'),
@@ -238,6 +239,21 @@ module.exports = (crowi) => {
     return [];
   }
 
+  async function checkIsPathExists(path) {
+    const Page = mongoose.model('Page');
+    const response = await Page.findByPath(path);
+    return response != null;
+  }
+
+  async function generateUniquePath(basePath, index = 1) {
+    const path = basePath + index;
+    const isPathExists = await checkIsPathExists(path);
+    if (isPathExists) {
+      return generateUniquePath(basePath, index + 1);
+    }
+    return path;
+  }
+
   /**
    * @swagger
    *
@@ -266,9 +282,9 @@ module.exports = (crowi) => {
    *                    type: array
    *                    items:
    *                      $ref: '#/components/schemas/Tag'
-   *                  createFromPageTree:
+   *                  shouldGeneratePath:
    *                    type: boolean
-   *                    description: Whether the page was created from the page tree or not
+   *                    description: Determine whether a new path should be generated
    *                required:
    *                  - body
    *                  - path
@@ -295,7 +311,7 @@ module.exports = (crowi) => {
    */
   router.post('/', accessTokenParser, loginRequiredStrictly, excludeReadOnlyUser, addActivity, validator.createPage, apiV3FormValidator, async(req, res) => {
     const {
-      body, grant, grantUserGroupId, overwriteScopesOfDescendants, isSlackEnabled, slackChannels, pageTags,
+      body, grant, grantUserGroupId, overwriteScopesOfDescendants, isSlackEnabled, slackChannels, pageTags, shouldGeneratePath,
     } = req.body;
 
     let { path } = req.body;
@@ -303,6 +319,18 @@ module.exports = (crowi) => {
     // check whether path starts slash
     path = addHeadingSlash(path);
 
+    if (shouldGeneratePath) {
+      try {
+        const rootPath = '/';
+        const defaultTitle = '/Untitled';
+        const basePath = path === rootPath ? defaultTitle : path + defaultTitle;
+        path = await generateUniquePath(basePath);
+      }
+      catch (err) {
+        return res.apiv3Err(new ErrorV3('Failed to generate unique path'));
+      }
+    }
+
     if (!isCreatablePage(path)) {
       return res.apiv3Err(`Could not use the path '${path}'`);
     }