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

apply containers to LikeButton, SeenUser, Likers

Yuki Takei 6 лет назад
Родитель
Сommit
32040980de

+ 3 - 31
src/client/js/app.js

@@ -278,6 +278,9 @@ if (pageContainer.state.pageId != null) {
     'page-comments-list': <PageComments />,
     'page-attachment':  <PageAttachment />,
     'page-comment-write':  <CommentEditorLazyRenderer />,
+    'like-button': <LikeButton pageId={pageContainer.state.pageId} isLiked={pageContainer.state.isLiked} />,
+    'seen-user-list': <UserPictureList userIds={pageContainer.state.seenUserIds} />,
+    'liker-list': <UserPictureList userIds={pageContainer.state.likerUserIds} />,
     'bookmark-button':  <BookmarkButton pageId={pageContainer.state.pageId} crowi={crowi} />,
     'bookmark-button-lg':  <BookmarkButton pageId={pageContainer.state.pageId} crowi={crowi} size="lg" />,
     'rename-page-name-input':  <PagePathAutoComplete crowi={crowi} initializedPath={pageContainer.state.path} />,
@@ -307,37 +310,6 @@ Object.keys(componentMappings).forEach((key) => {
   }
 });
 
-// render LikeButton
-const likeButtonElem = document.getElementById('like-button');
-if (likeButtonElem) {
-  const isLiked = likeButtonElem.dataset.liked === 'true';
-  ReactDOM.render(
-    <LikeButton crowi={crowi} pageId={pageContainer.state.pageId} isLiked={isLiked} />,
-    likeButtonElem,
-  );
-}
-
-// render UserPictureList for seen-user-list
-const seenUserListElem = document.getElementById('seen-user-list');
-if (seenUserListElem) {
-  const userIdsStr = seenUserListElem.dataset.userIds;
-  const userIds = userIdsStr.split(',');
-  ReactDOM.render(
-    <UserPictureList crowi={crowi} userIds={userIds} />,
-    seenUserListElem,
-  );
-}
-// render UserPictureList for liker-list
-const likerListElem = document.getElementById('liker-list');
-if (likerListElem) {
-  const userIdsStr = likerListElem.dataset.userIds;
-  const userIds = userIdsStr.split(',');
-  ReactDOM.render(
-    <UserPictureList crowi={crowi} userIds={userIds} />,
-    likerListElem,
-  );
-}
-
 // render for admin
 const customCssEditorElem = document.getElementById('custom-css-editor');
 if (customCssEditorElem != null) {

+ 19 - 5
src/client/js/components/LikeButton.jsx

@@ -1,7 +1,10 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
-export default class LikeButton extends React.Component {
+import { createSubscribedElement } from './UnstatedUtils';
+import AppContainer from '../services/AppContainer';
+
+class LikeButton extends React.Component {
 
   constructor(props) {
     super(props);
@@ -16,16 +19,17 @@ export default class LikeButton extends React.Component {
   handleClick(event) {
     event.preventDefault();
 
+    const { appContainer } = this.props;
     const pageId = this.props.pageId;
 
     if (!this.state.isLiked) {
-      this.props.crowi.apiPost('/likes.add', { page_id: pageId })
+      appContainer.apiPost('/likes.add', { page_id: pageId })
         .then((res) => {
           this.setState({ isLiked: true });
         });
     }
     else {
-      this.props.crowi.apiPost('/likes.remove', { page_id: pageId })
+      appContainer.apiPost('/likes.remove', { page_id: pageId })
         .then((res) => {
           this.setState({ isLiked: false });
         });
@@ -33,7 +37,7 @@ export default class LikeButton extends React.Component {
   }
 
   isUserLoggedIn() {
-    return this.props.crowi.me !== '';
+    return this.props.appContainer.me !== '';
   }
 
   render() {
@@ -64,9 +68,19 @@ export default class LikeButton extends React.Component {
 
 }
 
+/**
+ * Wrapper component for using unstated
+ */
+const LikeButtonWrapper = (props) => {
+  return createSubscribedElement(LikeButton, props, [AppContainer]);
+};
+
 LikeButton.propTypes = {
-  crowi: PropTypes.object.isRequired,
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+
   pageId: PropTypes.string,
   isLiked: PropTypes.bool,
   size: PropTypes.string,
 };
+
+export default LikeButtonWrapper;

+ 16 - 3
src/client/js/components/User/UserPictureList.jsx

@@ -4,9 +4,12 @@ import PropTypes from 'prop-types';
 import OverlayTrigger from 'react-bootstrap/es/OverlayTrigger';
 import Tooltip from 'react-bootstrap/es/Tooltip';
 
+import { createSubscribedElement } from '../UnstatedUtils';
+import AppContainer from '../../services/AppContainer';
+
 import UserPicture from './UserPicture';
 
-export default class UserPictureList extends React.Component {
+class UserPictureList extends React.Component {
 
   constructor(props) {
     super(props);
@@ -15,7 +18,7 @@ export default class UserPictureList extends React.Component {
 
     const users = this.props.users.concat(
       // FIXME: user data cache
-      this.props.crowi.findUserByIds(userIds),
+      this.props.appContainer.findUserByIds(userIds),
     );
 
     this.state = {
@@ -47,8 +50,16 @@ export default class UserPictureList extends React.Component {
 
 }
 
+/**
+ * Wrapper component for using unstated
+ */
+const UserPictureListWrapper = (props) => {
+  return createSubscribedElement(UserPictureList, props, [AppContainer]);
+};
+
 UserPictureList.propTypes = {
-  crowi: PropTypes.object.isRequired,
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+
   userIds: PropTypes.arrayOf(PropTypes.string),
   users: PropTypes.arrayOf(PropTypes.object),
 };
@@ -57,3 +68,5 @@ UserPictureList.defaultProps = {
   userIds: [],
   users: [],
 };
+
+export default UserPictureListWrapper;

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

@@ -35,6 +35,9 @@ export default class PageContainer extends Container {
       revisionId,
       revisionCreatedAt: +mainContent.getAttribute('data-page-revision-created'),
       path: mainContent.getAttribute('data-path'),
+      isLiked: false,
+      seenUserIds: [],
+      likerUserIds: [],
 
       tags: [],
       templateTagData: mainContent.getAttribute('data-template-tags') || '',
@@ -49,6 +52,7 @@ export default class PageContainer extends Container {
     };
 
     this.initStateMarkdown();
+    this.initStateOthers();
     this.initDrafts();
 
     this.addWebSocketEventHandlers = this.addWebSocketEventHandlers.bind(this);
@@ -70,6 +74,26 @@ export default class PageContainer extends Container {
     this.state.markdown = markdown;
   }
 
+  initStateOthers() {
+    const likeButtonElem = document.getElementById('like-button');
+    if (likeButtonElem != null) {
+      this.state.isLiked = likeButtonElem.dataset.liked === 'true';
+    }
+
+    const seenUserListElem = document.getElementById('seen-user-list');
+    if (seenUserListElem != null) {
+      const userIdsStr = seenUserListElem.dataset.userIds;
+      this.state.seenUserIds = userIdsStr.split(',');
+    }
+
+
+    const likerListElem = document.getElementById('liker-list');
+    if (likerListElem != null) {
+      const userIdsStr = likerListElem.dataset.userIds;
+      this.state.likerUserIds = userIdsStr.split(',');
+    }
+  }
+
   /**
    * initialize state for drafts
    */

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

@@ -346,8 +346,8 @@ module.exports = function(crowi) {
   };
 
   pageSchema.methods.isLiked = function(userData) {
-    return this.liker.some((likedUser) => {
-      return likedUser === userData._id.toString();
+    return this.liker.some((likedUserId) => {
+      return likedUserId.toString() === userData._id.toString();
     });
   };
 
@@ -366,7 +366,7 @@ module.exports = function(crowi) {
         });
       }
       else {
-        debug('liker not updated');
+        this.logger.warn('liker not updated');
         return reject(self);
       }
     }));