Jelajahi Sumber

commonize SeenUserList component

Yuki Takei 7 tahun lalu
induk
melakukan
627ecb5140

+ 15 - 5
src/client/js/app.js

@@ -25,13 +25,13 @@ import PageComments     from './components/PageComments';
 import CommentForm from './components/PageComment/CommentForm';
 import PageAttachment   from './components/PageAttachment';
 import PageStatusAlert  from './components/PageStatusAlert';
-import SeenUserList     from './components/SeenUserList';
 import RevisionPath     from './components/Page/RevisionPath';
 import RevisionUrl      from './components/Page/RevisionUrl';
 import BookmarkButton   from './components/BookmarkButton';
 import LikeButton       from './components/LikeButton';
 import PagePathAutoComplete from './components/PagePathAutoComplete';
 import RecentCreated from './components/RecentCreated/RecentCreated';
+import UserCountAndList from './components/UserCountAndList';
 
 import CustomCssEditor  from './components/Admin/CustomCssEditor';
 import CustomScriptEditor from './components/Admin/CustomScriptEditor';
@@ -319,16 +319,26 @@ if (likeButtonElem) {
   );
 }
 
-// render SeenUserList
+// render UserCountAndList for seen-user-list
 const seenUserListElem = document.getElementById('seen-user-list');
 if (seenUserListElem) {
-  const seenUserIdsStr = seenUserListElem.dataset.seenUsers;
-  const seenUserIds = seenUserIdsStr.split(',');
+  const userIdsStr = seenUserListElem.dataset.userIds;
+  const userIds = userIdsStr.split(',');
   ReactDOM.render(
-    <SeenUserList crowi={crowi} seenUserIds={seenUserIds} />,
+    <UserCountAndList crowi={crowi} userIds={userIds} />,
     seenUserListElem
   );
 }
+// render UserCountAndList for liker-list
+const likerListElem = document.getElementById('liker-list');
+if (likerListElem) {
+  const userIdsStr = likerListElem.dataset.userIds;
+  const userIds = userIdsStr.split(',');
+  ReactDOM.render(
+    <UserCountAndList crowi={crowi} userIds={userIds} />,
+    likerListElem
+  );
+}
 
 // render SavePageControls
 let savePageControls = null;

+ 3 - 16
src/client/js/components/SeenUserList/UserList.js → src/client/js/components/Common/UserPictureList.jsx

@@ -3,22 +3,9 @@ import PropTypes from 'prop-types';
 
 import UserPicture from '../User/UserPicture';
 
-export default class UserList extends React.Component {
-
-  isSeenUserListShown() {
-    const userCount = this.props.users.length;
-    if (0 < userCount && userCount <= 10) {
-      return true;
-    }
-
-    return false;
-  }
+export default class UserPictureList extends React.Component {
 
   render() {
-    if (!this.isSeenUserListShown()) {
-      return null;
-    }
-
     const users = this.props.users.map((user) => {
       return (
         <a key={user._id} data-user-id={user._id} href={'/user/' + user.username} title={user.name}>
@@ -35,10 +22,10 @@ export default class UserList extends React.Component {
   }
 }
 
-UserList.propTypes = {
+UserPictureList.propTypes = {
   users: PropTypes.array,
 };
 
-UserList.defaultProps = {
+UserPictureList.defaultProps = {
   users: [],
 };

+ 0 - 43
src/client/js/components/SeenUserList.js

@@ -1,43 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import UserList from './SeenUserList/UserList';
-
-export default class SeenUserList extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.state = {
-      seenUsers: [],
-    };
-  }
-
-  componentDidMount() {
-    const seenUserIds = this.props.seenUserIds;
-
-    if (seenUserIds.length > 0) {
-      // FIXME: user data cache
-      this.setState({seenUsers: this.props.crowi.findUserByIds(seenUserIds)});
-    }
-  }
-
-  render() {
-    return (
-      <div className="seen-user-list">
-        <p className="seen-user-count">
-          {this.state.seenUsers.length}
-        </p>
-        <UserList users={this.state.seenUsers} />
-      </div>
-    );
-  }
-}
-
-SeenUserList.propTypes = {
-  crowi: PropTypes.object.isRequired,
-  seenUserIds: PropTypes.arrayOf(PropTypes.string),
-};
-SeenUserList.defaultProps = {
-  seenUserIds: [],
-};

+ 43 - 0
src/client/js/components/UserCountAndList.jsx

@@ -0,0 +1,43 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import UserPictureList from './Common/UserPictureList';
+
+export default class UserCountAndList extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      users: [],
+    };
+  }
+
+  componentDidMount() {
+    const userIds = this.props.userIds;
+
+    if (userIds.length > 0) {
+      // FIXME: user data cache
+      this.setState({users: this.props.crowi.findUserByIds(userIds)});
+    }
+  }
+
+  render() {
+    return (
+      <div className="user-list">
+        <p className="user-count">
+          {this.state.users.length}
+        </p>
+        <UserPictureList users={this.state.users} />
+      </div>
+    );
+  }
+}
+
+UserCountAndList.propTypes = {
+  crowi: PropTypes.object.isRequired,
+  userIds: PropTypes.arrayOf(PropTypes.string),
+};
+UserCountAndList.defaultProps = {
+  userIds: [],
+};

+ 0 - 31
src/client/js/legacy/crowi.js

@@ -581,37 +581,6 @@ $(function() {
       top.location.href = `${path}#edit`;
     });
 
-    const $likerList = $('#liker-list');
-    const likers = $likerList.data('likers');
-    if (likers && likers.length > 0) {
-      const users = crowi.findUserByIds(likers.split(','));
-      if (users) {
-        AddToLikers(users);
-      }
-    }
-
-    /* eslint-disable no-inner-declarations */
-    function AddToLikers(users) {
-      $.each(users, function(i, user) {
-        $likerList.append(CreateUserLinkWithPicture(user));
-      });
-    }
-
-    function CreateUserLinkWithPicture(user) {
-      const $userHtml = $('<a>');
-      $userHtml.data('user-id', user._id);
-      $userHtml.attr('href', '/user/' + user.username);
-      $userHtml.attr('title', user.name);
-
-      const $userPicture = $('<img class="picture picture-xs img-circle">');
-      $userPicture.attr('alt', user.name);
-      $userPicture.attr('src',  Crowi.userPicture(user));
-
-      $userHtml.append($userPicture);
-      return $userHtml;
-    }
-    /* eslint-enable */
-
     if (!isSeen) {
       $.post('/_api/pages.seen', {page_id: pageId}, function(res) {
         // ignore unless response has error

+ 202 - 202
src/client/styles/scss/_layout_crowi_sidebar.scss

@@ -1,202 +1,202 @@
-.crowi-sidebar { // {{{
-  position: fixed;
-  padding: 65px 0 0 0;
-  height: 100%;
-  right: 0;
-  top: 0;
-  overflow: auto;
-  border-left: solid 1px transparent;
-
-  transition: .3s ease;
-
-
-  .page-meta {
-    padding: 15px 15px 5px 15px;
-    font-size: .9em;
-    border-bottom: solid 1px #ccc;
-
-    line-height: 1.4em;
-    p {
-      line-height: 1.4em;
-    }
-
-    .creator-picture {
-      text-align: center;
-      img {
-        width: 48px;
-        height: 48px;
-        border: 1px solid #ccc;
-      }
-    }
-    .creator {
-      font-size: 1.3em;
-      font-weight: bold;
-    }
-    .created-at {
-    }
-
-    .like-box {
-      padding-bottom: 0;
-
-      .dl-horizontal {
-        margin-bottom: 0;
-
-        dt, dd {
-          border-top: solid 1px #ccc;
-          padding-top: 5px;
-          padding-bottom: 5px;
-        }
-        dt {
-          width: 80px;
-        }
-        dd {
-          margin-left: 90px;
-          text-align: right;
-        }
-      }
-    }
-
-    .liker-count, .contributor-count, .seen-user-count {
-      font-size: 1.2em;
-      font-weight: bold;
-      margin-bottom: 5px;
-    }
-    .contributor-list, .seen-user-list {
-    }
-  }
-
-  .side-content {
-    margin-bottom: 100px;
-    padding: 15px;
-
-    h3 {
-      font-size: 1.1em;
-    }
-
-    ul.fitted-list {
-      padding-left: 0;
-      li {
-        margin-bottom: 2px;
-
-        .input-group-addon {
-          padding: 5px 6px;
-        }
-      }
-    }
-
-    .page-comments {
-      margin: 8px 0 0 0;
-
-      .page-comment-form {
-        margin-top: 16px;
-
-        .comment-form {
-        }
-
-        .comment-form-main {
-
-          .comment-form-comment {
-            height: 60px;
-          }
-
-          .comment-submit {
-            margin-top: 8px;
-            text-align: right;
-          }
-        }
-      }
-
-      .page-comments-list {
-        .page-comment {
-          margin-top: 8px;
-          padding-top: 8px;
-
-          .picture {
-            float: left;
-            width: 24px;
-            height: 24px;
-          }
-
-          .page-comment-creator {
-            font-weight: bold;
-          }
-
-          .page-comment-main {
-            position: relative;
-            margin-left: 40px;
-
-            .page-comment-meta {
-              color: #aaa;
-              font-size: .9em;
-            }
-            .page-comment-body {
-              padding: 8px 0;
-              word-wrap: break-word;
-            }
-            .page-comment-control {
-              position: absolute;
-              display: none;    // default hidden
-              top: 0;
-              right: 0;
-            }
-          }
-
-          // show controls when hover
-          .page-comment-main:hover > .page-comment-control {
-            display: block;
-          }
-        }
-      }
-    }
-
-  }
-
-  .portal-form-button {
-    text-align: center;
-  }
-
-  .system-version {
-    position: fixed;
-    z-index: 1;
-    right: 1.4em;
-    width: calc(25% - 1.5em);
-    bottom: 0.1em;
-    padding-right: 1em;
-    opacity: 1;
-
-    display: flex;
-    justify-content: space-between;
-
-    transition: .3s ease;
-  }
-
-} // }}}
-
-body:not(.aside-hidden) #toggle-sidebar {
-  i.ti-angle-left {
-    display: none;
-  }
-  i.ti-angle-right {
-    display: block;
-  }
-}
-.aside-hidden { // {{{
-  #toggle-sidebar {
-    right: 0;
-    i.ti-angle-right {
-      display: block;
-    }
-    i.ti-angle-right {
-      display: none;
-    }
-  }
-
-  .crowi-sidebar, .system-version { // {{{
-    right: -25%;
-  } // }}}
-
-  .bg-title .col-md-9,
-  .main {
-    width: 100%;
-  }
-} // }}}
+.crowi-sidebar { // {{{
+  position: fixed;
+  padding: 65px 0 0 0;
+  height: 100%;
+  right: 0;
+  top: 0;
+  overflow: auto;
+  border-left: solid 1px transparent;
+
+  transition: .3s ease;
+
+
+  .page-meta {
+    padding: 15px 15px 5px 15px;
+    font-size: .9em;
+    border-bottom: solid 1px #ccc;
+
+    line-height: 1.4em;
+    p {
+      line-height: 1.4em;
+    }
+
+    .creator-picture {
+      text-align: center;
+      img {
+        width: 48px;
+        height: 48px;
+        border: 1px solid #ccc;
+      }
+    }
+    .creator {
+      font-size: 1.3em;
+      font-weight: bold;
+    }
+    .created-at {
+    }
+
+    .like-box {
+      padding-bottom: 0;
+
+      .dl-horizontal {
+        margin-bottom: 0;
+
+        dt, dd {
+          border-top: solid 1px #ccc;
+          padding-top: 5px;
+          padding-bottom: 5px;
+        }
+        dt {
+          width: 80px;
+        }
+        dd {
+          margin-left: 90px;
+          text-align: right;
+        }
+      }
+    }
+
+    #liker-list, #seen-user-list {
+      .user-count {
+        font-size: 1.2em;
+        font-weight: bold;
+        margin-bottom: 5px;
+      }
+    }
+  }
+
+  .side-content {
+    margin-bottom: 100px;
+    padding: 15px;
+
+    h3 {
+      font-size: 1.1em;
+    }
+
+    ul.fitted-list {
+      padding-left: 0;
+      li {
+        margin-bottom: 2px;
+
+        .input-group-addon {
+          padding: 5px 6px;
+        }
+      }
+    }
+
+    .page-comments {
+      margin: 8px 0 0 0;
+
+      .page-comment-form {
+        margin-top: 16px;
+
+        .comment-form {
+        }
+
+        .comment-form-main {
+
+          .comment-form-comment {
+            height: 60px;
+          }
+
+          .comment-submit {
+            margin-top: 8px;
+            text-align: right;
+          }
+        }
+      }
+
+      .page-comments-list {
+        .page-comment {
+          margin-top: 8px;
+          padding-top: 8px;
+
+          .picture {
+            float: left;
+            width: 24px;
+            height: 24px;
+          }
+
+          .page-comment-creator {
+            font-weight: bold;
+          }
+
+          .page-comment-main {
+            position: relative;
+            margin-left: 40px;
+
+            .page-comment-meta {
+              color: #aaa;
+              font-size: .9em;
+            }
+            .page-comment-body {
+              padding: 8px 0;
+              word-wrap: break-word;
+            }
+            .page-comment-control {
+              position: absolute;
+              display: none;    // default hidden
+              top: 0;
+              right: 0;
+            }
+          }
+
+          // show controls when hover
+          .page-comment-main:hover > .page-comment-control {
+            display: block;
+          }
+        }
+      }
+    }
+
+  }
+
+  .portal-form-button {
+    text-align: center;
+  }
+
+  .system-version {
+    position: fixed;
+    z-index: 1;
+    right: 1.4em;
+    width: calc(25% - 1.5em);
+    bottom: 0.1em;
+    padding-right: 1em;
+    opacity: 1;
+
+    display: flex;
+    justify-content: space-between;
+
+    transition: .3s ease;
+  }
+
+} // }}}
+
+body:not(.aside-hidden) #toggle-sidebar {
+  i.ti-angle-left {
+    display: none;
+  }
+  i.ti-angle-right {
+    display: block;
+  }
+}
+.aside-hidden { // {{{
+  #toggle-sidebar {
+    right: 0;
+    i.ti-angle-right {
+      display: block;
+    }
+    i.ti-angle-right {
+      display: none;
+    }
+  }
+
+  .crowi-sidebar, .system-version { // {{{
+    right: -25%;
+  } // }}}
+
+  .bg-title .col-md-9,
+  .main {
+    width: 100%;
+  }
+} // }}}

+ 2 - 6
src/server/views/layout-crowi/widget/page_side_header.html

@@ -24,16 +24,12 @@
         <i class="icon-like"></i> {{ t('Like!') }}
       </dt>
       <dd>
-        <p class="liker-count">
-          <span id="like-count">{{ page.liker.length }}</span>
-        </p>
-        <p id="liker-list" class="liker-list" data-likers="{{ page.liker|default([])|join(',') }}">
-        </p>
+        <div id="liker-list" data-user-ids="{{ page.liker|default([])|join(',') }}"></div>
       </dd>
 
       <dt><i class="fa fa-paw"></i> {{ t('Seen by') }}</dt>
       <dd>
-        <div id="seen-user-list" data-seen-users="{{ page.seenUsers|default([])|join(',') }}"></div>
+        <div id="seen-user-list" data-user-ids="{{ page.seenUsers|default([])|join(',') }}"></div>
       </dd>
     </dl>
   </div>