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

Merge pull request #1876 from weseek/support/create-apiV3-for-update-like-status

Support/create api v3 for update like status
itizawa 6 лет назад
Родитель
Сommit
8092cfbb0c

+ 6 - 18
src/client/js/components/LikeButton.jsx

@@ -19,25 +19,13 @@ class LikeButton extends React.Component {
 
   async handleClick() {
     const { appContainer, pageId } = this.props;
-    const { isLiked } = this.state;
-
-    if (!isLiked) {
-      try {
-        await appContainer.apiPost('/likes.add', { page_id: pageId });
-        this.setState({ isLiked: true });
-      }
-      catch (err) {
-        toastError(err);
-      }
+    const bool = !this.state.isLiked;
+    try {
+      await appContainer.apiv3.put('/page/likes', { pageId, bool });
+      this.setState({ isLiked: bool });
     }
-    else {
-      try {
-        await appContainer.apiPost('/likes.remove', { page_id: pageId });
-        this.setState({ isLiked: false });
-      }
-      catch (err) {
-        toastError(err);
-      }
+    catch (err) {
+      toastError(err);
     }
   }
 

+ 1 - 1
src/client/js/components/Navbar/GrowiSubNavigation.jsx

@@ -48,7 +48,7 @@ const GrowiSubNavigation = (props) => {
 
       {/* Header Button */}
       <div className="mr-2">
-        <LikeButton pageId={pageId} />
+        <LikeButton pageId={pageId} isLiked={pageContainer.state.isLiked} />
       </div>
       <div>
         <BookmarkButton pageId={pageId} crowi={appContainer} />

+ 1 - 1
src/client/js/services/PageContainer.js

@@ -41,7 +41,7 @@ export default class PageContainer extends Container {
       revisionAuthor: JSON.parse(mainContent.getAttribute('data-page-revision-author')),
       path: mainContent.getAttribute('data-path'),
       tocHtml: '',
-      isLiked: mainContent.getAttribute('data-page-is-liked'),
+      isLiked: JSON.parse(mainContent.getAttribute('data-page-is-liked')),
       seenUserIds: [],
       likerUserIds: [],
       createdAt: mainContent.getAttribute('data-page-created-at'),

+ 4 - 3
src/server/models/page.js

@@ -2,6 +2,7 @@
 /* eslint-disable no-return-await */
 
 /* eslint-disable no-use-before-define */
+const logger = require('@alias/logger')('growi:models:page');
 
 const debug = require('debug')('growi:models:page');
 const nodePath = require('path');
@@ -367,12 +368,12 @@ module.exports = function(crowi) {
           if (err) {
             return reject(err);
           }
-          debug('liker updated!', added);
+          logger.debug('liker updated!', added);
           return resolve(data);
         });
       }
       else {
-        this.logger.warn('liker not updated');
+        logger.debug('liker not updated');
         return reject(self);
       }
     }));
@@ -393,7 +394,7 @@ module.exports = function(crowi) {
         });
       }
       else {
-        debug('liker not updated');
+        logger.debug('liker not updated');
         return reject(self);
       }
     }));

+ 2 - 2
src/server/routes/apiv3/index.js

@@ -18,9 +18,7 @@ module.exports = (crowi) => {
   router.use('/markdown-setting', require('./markdown-setting')(crowi));
   router.use('/app-settings', require('./app-settings')(crowi));
   router.use('/customize-setting', require('./customize-setting')(crowi));
-
   router.use('/notification-setting', require('./notification-setting')(crowi));
-
   router.use('/users', require('./users')(crowi));
   router.use('/user-groups', require('./user-group')(crowi));
   router.use('/export', require('./export')(crowi));
@@ -39,5 +37,7 @@ module.exports = (crowi) => {
 
   router.use('/search', require('./search')(crowi));
 
+  router.use('/page', require('./page')(crowi));
+
   return router;
 };

+ 187 - 0
src/server/routes/apiv3/page.js

@@ -0,0 +1,187 @@
+const loggerFactory = require('@alias/logger');
+
+const logger = loggerFactory('growi:routes:apiv3:page'); // eslint-disable-line no-unused-vars
+
+const express = require('express');
+const { body } = require('express-validator');
+
+const router = express.Router();
+
+// const ErrorV3 = require('../../models/vo/error-apiv3');
+
+/**
+ * @swagger
+ *  tags:
+ *    name: Page
+ */
+
+/**
+ * @swagger
+ *
+ *  components:
+ *    schemas:
+ *      Page:
+ *        description: Page
+ *        type: object
+ *        properties:
+ *          _id:
+ *            type: string
+ *            description: page ID
+ *            example: 5e07345972560e001761fa63
+ *          __v:
+ *            type: number
+ *            description: DB record version
+ *            example: 0
+ *          commentCount:
+ *            type: number
+ *            description: count of comments
+ *            example: 3
+ *          createdAt:
+ *            type: string
+ *            description: date created at
+ *            example: 2010-01-01T00:00:00.000Z
+ *          creator:
+ *            $ref: '#/components/schemas/User'
+ *          extended:
+ *            type: object
+ *            description: extend data
+ *            example: {}
+ *          grant:
+ *            type: number
+ *            description: grant
+ *            example: 1
+ *          grantedUsers:
+ *            type: array
+ *            description: granted users
+ *            items:
+ *              type: string
+ *              description: user ID
+ *            example: ["5ae5fccfc5577b0004dbd8ab"]
+ *          lastUpdateUser:
+ *            $ref: '#/components/schemas/User'
+ *          liker:
+ *            type: array
+ *            description: granted users
+ *            items:
+ *              type: string
+ *              description: user ID
+ *            example: []
+ *          path:
+ *            type: string
+ *            description: page path
+ *            example: /
+ *          redirectTo:
+ *            type: string
+ *            description: redirect path
+ *            example: ""
+ *          revision:
+ *            type: string
+ *            description: page revision
+ *          seenUsers:
+ *            type: array
+ *            description: granted users
+ *            items:
+ *              type: string
+ *              description: user ID
+ *            example: ["5ae5fccfc5577b0004dbd8ab"]
+ *          status:
+ *            type: string
+ *            description: status
+ *            enum:
+ *              - 'wip'
+ *              - 'published'
+ *              - 'deleted'
+ *              - 'deprecated'
+ *            example: published
+ *          updatedAt:
+ *            type: string
+ *            description: date updated at
+ *            example: 2010-01-01T00:00:00.000Z
+ *
+ *      LikeParams:
+ *        description: LikeParams
+ *        type: object
+ *        properties:
+ *          pageId:
+ *            type: string
+ *            description: page ID
+ *            example: 5e07345972560e001761fa63
+ *          bool:
+ *            type: boolean
+ *            description: boolean for like status
+ */
+module.exports = (crowi) => {
+  const accessTokenParser = require('../../middleware/access-token-parser')(crowi);
+  const loginRequired = require('../../middleware/login-required')(crowi);
+  const csrf = require('../../middleware/csrf')(crowi);
+
+  const globalNotificationService = crowi.getGlobalNotificationService();
+  const { Page, GlobalNotificationSetting } = crowi.models;
+  const { ApiV3FormValidator } = crowi.middlewares;
+
+
+  const validator = {
+    likes: [
+      body('pageId').isString(),
+      body('bool').isBoolean(),
+    ],
+  };
+
+  /**
+   * @swagger
+   *
+   *    /page/likes:
+   *      put:
+   *        tags: [Page]
+   *        summary: /page/likes
+   *        description: Update liked status
+   *        operationId: updateLikedStatus
+   *        requestBody:
+   *          content:
+   *            application/json:
+   *              schema:
+   *                $ref: '#/components/schemas/LikeParams'
+   *        responses:
+   *          200:
+   *            description: Succeeded to update liked status.
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  $ref: '#/components/schemas/Page'
+   */
+  router.put('/likes', accessTokenParser, loginRequired, csrf, validator.likes, ApiV3FormValidator, async(req, res) => {
+    const { pageId, bool } = req.body;
+
+    let page;
+    try {
+      page = await Page.findByIdAndViewer(pageId, req.user);
+      if (page == null) {
+        return res.apiv3Err(`Page '${pageId}' is not found or forbidden`);
+      }
+      if (bool) {
+        page = await page.like(req.user);
+      }
+      else {
+        page = await page.unlike(req.user);
+      }
+    }
+    catch (err) {
+      logger.error('update-like-failed', err);
+      return res.apiv3Err(err, 500);
+    }
+
+    try {
+      // global notification
+      await globalNotificationService.fire(GlobalNotificationSetting.EVENT.PAGE_LIKE, page, req.user);
+    }
+    catch (err) {
+      logger.error('Like notification failed', err);
+    }
+
+    const result = { page };
+    result.seenUser = page.seenUsers;
+    return res.apiv3({ result });
+  });
+
+  return router;
+};