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

Merge pull request #2788 from weseek/feat/gw-3776

gw-3776
Yuki Takei 5 лет назад
Родитель
Сommit
04bc8987f8

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

@@ -4,25 +4,29 @@ import PropTypes from 'prop-types';
 import { toastError } from '../util/apiNotification';
 import { withUnstatedContainers } from './UnstatedUtils';
 import AppContainer from '../services/AppContainer';
+import PageContainer from '../services/PageContainer';
 
 class LikeButton extends React.Component {
 
   constructor(props) {
     super(props);
 
-    this.state = {
-      isLiked: props.isLiked,
-    };
-
     this.handleClick = this.handleClick.bind(this);
   }
 
   async handleClick() {
-    const { appContainer, pageId } = this.props;
-    const bool = !this.state.isLiked;
+    const { appContainer, pageContainer } = this.props;
+    const pageId = pageContainer.state.pageId;
+    const bool = !pageContainer.state.isLiked;
     try {
       await appContainer.apiv3.put('/page/likes', { pageId, bool });
-      this.setState({ isLiked: bool });
+      if (pageContainer.state.isLiked) {
+        pageContainer.setState({ sumOfLikers: pageContainer.state.sumOfLikers - 1 });
+      }
+      else {
+        pageContainer.setState({ sumOfLikers: pageContainer.state.sumOfLikers + 1 });
+      }
+      pageContainer.setState({ isLiked: bool });
     }
     catch (err) {
       toastError(err);
@@ -34,20 +38,26 @@ class LikeButton extends React.Component {
   }
 
   render() {
+    const { pageContainer } = this.props;
     // if guest user
     if (!this.isUserLoggedIn()) {
       return <div></div>;
     }
 
     return (
-      <button
-        type="button"
-        onClick={this.handleClick}
-        className={`btn rounded-circle btn-like border-0 d-edit-none
-        ${this.state.isLiked ? 'active' : ''}`}
-      >
-        <i className="icon-like"></i>
-      </button>
+      <div className="d-flex">
+        <button
+          type="button"
+          onClick={this.handleClick}
+          className={`btn rounded-circle btn-like border-0 d-edit-none
+        ${pageContainer.state.isLiked ? 'active' : ''}`}
+        >
+          <i className="icon-like"></i>
+        </button>
+        <div className="total-likes">
+          {pageContainer.state.sumOfLikers}
+        </div>
+      </div>
     );
   }
 
@@ -56,13 +66,12 @@ class LikeButton extends React.Component {
 /**
  * Wrapper component for using unstated
  */
-const LikeButtonWrapper = withUnstatedContainers(LikeButton, [AppContainer]);
+const LikeButtonWrapper = withUnstatedContainers(LikeButton, [AppContainer, PageContainer]);
 
 LikeButton.propTypes = {
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
 
-  pageId: PropTypes.string,
-  isLiked: PropTypes.bool,
   size: PropTypes.string,
 };
 

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

@@ -109,7 +109,7 @@ const UserInfo = ({ pageUser }) => {
 const PageReactionButtons = ({ appContainer, pageContainer }) => {
 
   const {
-    pageId, isLiked, pageUser, sumOfLikers,
+    pageId, isLiked, pageUser,
   } = pageContainer.state;
 
   return (
@@ -119,9 +119,6 @@ const PageReactionButtons = ({ appContainer, pageContainer }) => {
         <LikeButton pageId={pageId} isLiked={isLiked} />
       </span>
       )}
-      <span className="mr-2 total-likes">
-        {sumOfLikers}
-      </span>
       <span className="mr-2">
         <BookmarkButton pageId={pageId} crowi={appContainer} />
       </span>

+ 8 - 16
src/client/js/services/PageContainer.js

@@ -48,7 +48,7 @@ export default class PageContainer extends Container {
       revisionAuthor: JSON.parse(mainContent.getAttribute('data-page-revision-author')),
       path,
       tocHtml: '',
-      isLiked: JSON.parse(mainContent.getAttribute('data-page-is-liked')),
+      isLiked: false,
       seenUsers: [],
       likerUsers: [],
       sumOfSeenUsers: 0,
@@ -144,21 +144,13 @@ export default class PageContainer extends Container {
       this.checkAndUpdateImageUrlCached(users);
     }
 
-
-    const likerListElem = document.getElementById('liker-list');
-    if (likerListElem != null) {
-      const { userIdsStr, sumOfLikers } = likerListElem.dataset;
-      this.setState({ sumOfLikers });
-
-      if (userIdsStr === '') {
-        return;
-      }
-
-      const { users } = await this.appContainer.apiGet('/users.list', { user_ids: userIdsStr });
-      this.setState({ likerUsers: users });
-
-      this.checkAndUpdateImageUrlCached(users);
-    }
+    const like = await this.appContainer.apiv3Get('/page/like-info', { _id: this.state.pageId });
+    this.setState({
+      sumOfLikers: like.data.sumOfLikers,
+      likerUsers: like.data.users.liker,
+      isLiked: like.data.isLiked,
+    });
+    this.checkAndUpdateImageUrlCached(this.state.likerUsers);
   }
 
   async checkAndUpdateImageUrlCached(users) {

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

@@ -117,7 +117,7 @@ module.exports = (crowi) => {
   const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
 
   const globalNotificationService = crowi.getGlobalNotificationService();
-  const { Page, GlobalNotificationSetting } = crowi.models;
+  const { Page, GlobalNotificationSetting, User } = crowi.models;
   const { exportService } = crowi;
 
   const validator = {
@@ -125,6 +125,10 @@ module.exports = (crowi) => {
       body('pageId').isString(),
       body('bool').isBoolean(),
     ],
+    likeInfo: [
+      query('_id').isMongoId(),
+      query('user._id').isMongoId(),
+    ],
     export: [
       query('format').isString().isIn(['md', 'pdf']),
       query('revisionId').isString(),
@@ -196,6 +200,23 @@ module.exports = (crowi) => {
     return res.apiv3({ result });
   });
 
+  router.get('/like-info', loginRequired, validator.likeInfo, async(req, res) => {
+    const pageId = req.query._id;
+    const userId = req.user._id;
+    try {
+      const page = await Page.findById(pageId);
+      const users = await Page.findById(pageId).populate('liker', User.USER_PUBLIC_FIELDS);
+      const sumOfLikers = page.liker.length;
+      const isLiked = page.liker.includes(userId);
+
+      return res.apiv3({ users, sumOfLikers, isLiked });
+    }
+    catch (err) {
+      logger.error('error like info', err);
+      return res.apiv3Err(err, 500);
+    }
+  });
+
   /**
   * @swagger
   *

+ 0 - 5
src/server/views/layout-growi/widget/liker-and-seenusers.html

@@ -1,9 +1,4 @@
 <div class="liker-and-seenusers">
-  <div
-    id="liker-list"
-    data-user-ids-str="{{ page.liker|slice(-15)|default([])|reverse|join(',') }}"
-    data-sum-of-likers="{{ page.liker.length|default(0) }}"
-  ></div>
   <div
     id="seen-user-list"
     data-user-ids-str="{{ page.seenUsers|slice(-15)|default([])|reverse|join(',') }}"