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

Merge pull request #2799 from weseek/feat/gw-3777

gw-3777
takeru0001 5 лет назад
Родитель
Сommit
968b202832

+ 12 - 34
src/client/js/components/BookmarkButton.jsx

@@ -2,49 +2,22 @@ import React from 'react';
 import PropTypes from 'prop-types';
 
 import { toastError } from '../util/apiNotification';
+import { withUnstatedContainers } from './UnstatedUtils';
+import PageContainer from '../services/PageContainer';
 
 class BookmarkButton extends React.Component {
 
   constructor(props) {
     super(props);
 
-    this.state = {
-      isBookmarked: false,
-      sumOfBookmarks: 0,
-    };
-
     this.handleClick = this.handleClick.bind(this);
   }
 
-  async componentDidMount() {
-    const { pageId, crowi } = this.props;
-    // if guest user
-    if (!this.isUserLoggedIn()) {
-      // do nothing
-      return;
-    }
-
-    try {
-      const response = await crowi.apiv3.get('/bookmarks', { pageId });
-      if (response.data.bookmark != null) {
-        this.setState({ isBookmarked: true });
-      }
-      const result = await crowi.apiv3.get('/bookmarks/count-bookmarks', { pageId });
-      this.setState({ sumOfBookmarks: result.data.sumOfBookmarks });
-    }
-    catch (err) {
-      toastError(err);
-    }
-
-  }
-
   async handleClick() {
-    const { crowi, pageId } = this.props;
-    const bool = !this.state.isBookmarked;
+    const { pageContainer } = this.props;
 
     try {
-      await crowi.apiv3.put('/bookmarks', { pageId, bool });
-      this.setState({ isBookmarked: bool });
+      pageContainer.toggleBookmark();
     }
     catch (err) {
       toastError(err);
@@ -56,6 +29,7 @@ class BookmarkButton extends React.Component {
   }
 
   render() {
+    const { pageContainer } = this.props;
     // if guest user
     if (!this.isUserLoggedIn()) {
       return <div></div>;
@@ -68,12 +42,12 @@ class BookmarkButton extends React.Component {
           onClick={this.handleClick}
           className={`btn rounded-circle btn-bookmark border-0 d-edit-none
           ${`btn-${this.props.size}`}
-          ${this.state.isBookmarked ? 'active' : ''}`}
+          ${pageContainer.state.isBookmarked ? 'active' : ''}`}
         >
           <i className="icon-star"></i>
         </button>
         <div className="total-bookmarks">
-          {this.state.sumOfBookmarks}
+          {pageContainer.state.sumOfBookmarks}
         </div>
       </div>
     );
@@ -81,7 +55,11 @@ class BookmarkButton extends React.Component {
 
 }
 
+const BookmarkButtonWrapper = withUnstatedContainers(BookmarkButton, [PageContainer]);
+
 BookmarkButton.propTypes = {
+  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
+
   pageId: PropTypes.string,
   crowi: PropTypes.object.isRequired,
   size: PropTypes.string,
@@ -91,4 +69,4 @@ BookmarkButton.defaultProps = {
   size: 'md',
 };
 
-export default BookmarkButton;
+export default BookmarkButtonWrapper;

+ 21 - 0
src/client/js/services/PageContainer.js

@@ -49,10 +49,12 @@ export default class PageContainer extends Container {
       path,
       tocHtml: '',
       isLiked: false,
+      isBookmarked: false,
       seenUsers: [],
       likerUsers: [],
       sumOfSeenUsers: 0,
       sumOfLikers: 0,
+      sumOfBookmarks: 0,
       createdAt: mainContent.getAttribute('data-page-created-at'),
       creator: JSON.parse(mainContent.getAttribute('data-page-creator')),
       updatedAt: mainContent.getAttribute('data-page-updated-at'),
@@ -150,9 +152,28 @@ export default class PageContainer extends Container {
       likerUsers: like.data.users.liker,
       isLiked: like.data.isLiked,
     });
+
+    this.retrieveBookmarkInfo();
     this.checkAndUpdateImageUrlCached(this.state.likerUsers);
   }
 
+  async retrieveBookmarkInfo() {
+    const response = await this.appContainer.apiv3Get('/bookmarks', { pageId: this.state.pageId });
+    if (response.data.bookmarks != null) {
+      this.setState({ isBookmarked: true });
+    }
+    else {
+      this.setState({ isBookmarked: false });
+    }
+    this.setState({ sumOfBookmarks: response.data.sumOfBookmarks });
+  }
+
+  async toggleBookmark() {
+    const bool = !this.state.isBookmarked;
+    await this.appContainer.apiv3Put('/bookmarks', { pageId: this.state.pageId, bool });
+    return this.retrieveBookmarkInfo();
+  }
+
   async checkAndUpdateImageUrlCached(users) {
     const noImageCacheUsers = users.filter((user) => { return user.imageUrlCached == null });
     if (noImageCacheUsers.length === 0) {

+ 7 - 21
src/server/routes/apiv3/bookmarks.js

@@ -63,11 +63,11 @@ module.exports = (crowi) => {
 
   const validator = {
     bookmarks: [
-      body('pageId').isString(),
+      body('pageId').isMongoId(),
       body('bool').isBoolean(),
     ],
-    CountBookmarks: [
-      query('pageId').isString(),
+    bookmarkInfo: [
+      query('pageId').isMongoId(),
     ],
   };
 
@@ -94,12 +94,13 @@ module.exports = (crowi) => {
    *                schema:
    *                  $ref: '#/components/schemas/Bookmark'
    */
-  router.get('/', accessTokenParser, loginRequired, async(req, res) => {
+  router.get('/', accessTokenParser, loginRequired, validator.bookmarkInfo, async(req, res) => {
     const { pageId } = req.query;
 
     try {
-      const bookmark = await Bookmark.findByPageIdAndUserId(pageId, req.user);
-      return res.apiv3({ bookmark });
+      const bookmarks = await Bookmark.findByPageIdAndUserId(pageId, req.user);
+      const sumOfBookmarks = await Bookmark.countByPageId(pageId);
+      return res.apiv3({ bookmarks, sumOfBookmarks });
     }
     catch (err) {
       logger.error('get-bookmark-failed', err);
@@ -179,20 +180,5 @@ module.exports = (crowi) => {
    *                  $ref: '#/components/schemas/Bookmark'
    */
 
-
-  router.get('/count-bookmarks', accessTokenParser, loginRequired, validator.CountBookmarks, apiV3FormValidator, async(req, res) => {
-    const { pageId } = req.query;
-
-    try {
-      const sumOfBookmarks = await Bookmark.countByPageId(pageId);
-      return res.apiv3({ sumOfBookmarks });
-    }
-    catch (err) {
-      logger.error('get-bookmarks-list-failed', err);
-      return res.apiv3Err(err, 500);
-    }
-  });
-
-
   return router;
 };

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

@@ -127,7 +127,6 @@ module.exports = (crowi) => {
     ],
     likeInfo: [
       query('_id').isMongoId(),
-      query('user._id').isMongoId(),
     ],
     export: [
       query('format').isString().isIn(['md', 'pdf']),