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

Merge remote-tracking branch 'origin/dev/4.0.x' into support/apply-bootstrap4

itizawa 6 лет назад
Родитель
Сommit
aeb14bc642

+ 1 - 1
src/client/js/components/Admin/UserGroupDetail/UserGroupPageList.jsx

@@ -56,7 +56,7 @@ class UserGroupPageList extends React.Component {
     return (
       <Fragment>
         <ul className="page-list-ul page-list-ul-flat mb-3">
-          {this.state.currentPages.map((page) => { return <Page key={page._id} page={page} /> })}
+          {this.state.currentPages.map(page => <li key={page._id}><Page page={page} /></li>)}
         </ul>
         {adminUserGroupDetailContainer.state.relatedPages.length === 0 ? <p>{t('admin:user_group_management.no_pages')}</p> : null}
         <PaginationWrapper

+ 1 - 1
src/client/js/components/Admin/UserGroupDetail/UserGroupUserFormByInput.jsx

@@ -98,7 +98,7 @@ class UserGroupUserFormByInput extends React.Component {
     const user = option;
     return (
       <React.Fragment>
-        <UserPicture user={user} size="sm" withoutLink />
+        <UserPicture user={user} size="sm" noLink noTooltip />
         <strong className="ml-2">{user.username}</strong>
         {adminUserGroupDetailContainer.state.isAlsoNameSearched && <span className="ml-2">{user.name}</span>}
         {adminUserGroupDetailContainer.state.isAlsoMailSearched && <span className="ml-2">{user.email}</span>}

+ 3 - 2
src/client/js/components/Navbar/PageCreator.jsx

@@ -1,8 +1,9 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
+import { userPageRoot } from '@commons/util/path-utils';
+
 import UserPicture from '../User/UserPicture';
-import { userPageRoot } from '../../../../lib/util/path-utils';
 
 const PageCreator = (props) => {
   const { creator, createdAt, isCompactMode } = props;
@@ -13,7 +14,7 @@ const PageCreator = (props) => {
 
   return (
     <div className="d-flex align-items-center">
-      <div className="mr-2" href={userPageRoot(creator)} data-toggle="tooltip" data-placement="bottom" title={creator.name}>
+      <div className="mr-2">
         <UserPicture user={creator} size={pictureSize} />
       </div>
       {creatInfo}

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

@@ -59,7 +59,7 @@ const PersonalDropdown = (props) => {
       {/* remove .dropdown-toggle for hide caret */}
       {/* See https://stackoverflow.com/a/44577512/13183572 */}
       <a className="nav-link waves-effect waves-light" data-toggle="dropdown">
-        <UserPicture user={user} withoutLink /><span className="d-none d-sm-inline-block">&nbsp;{user.name}</span>
+        <UserPicture user={user} noLink noTooltip /><span className="d-none d-sm-inline-block">&nbsp;{user.name}</span>
       </a>
 
       {/* Menu */}

+ 3 - 2
src/client/js/components/Navbar/RevisionAuthor.jsx

@@ -1,8 +1,9 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 
+import { userPageRoot } from '@commons/util/path-utils';
+
 import UserPicture from '../User/UserPicture';
-import { userPageRoot } from '../../../../lib/util/path-utils';
 
 const RevisionAuthor = (props) => {
   const { revisionAuthor, updatedAt, isCompactMode } = props;
@@ -13,7 +14,7 @@ const RevisionAuthor = (props) => {
 
   return (
     <div className="d-flex align-items-center">
-      <div className="mr-2" href={userPageRoot(revisionAuthor)} data-toggle="tooltip" data-placement="bottom" title={revisionAuthor.name}>
+      <div className="mr-2">
         <UserPicture user={revisionAuthor} size={pictureSize} />
       </div>
       {updateInfo}

+ 0 - 29
src/client/js/components/PageList/ListView.jsx

@@ -1,29 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import Page from './Page';
-
-export default class ListView extends React.Component {
-
-  render() {
-    const listView = this.props.pages.map((page) => {
-      return <Page page={page} key={`page-list:list-view:${page._id}`} />;
-    });
-
-    return (
-      <div className="page-list">
-        <ul className="page-list-ul page-list-ul-flat">
-          {listView}
-        </ul>
-      </div>
-    );
-  }
-
-}
-
-ListView.propTypes = {
-  pages: PropTypes.array.isRequired,
-};
-
-ListView.defaultProps = {
-};

+ 14 - 21
src/client/js/components/PageList/Page.jsx

@@ -8,27 +8,21 @@ import PagePath from './PagePath';
 export default class Page extends React.Component {
 
   render() {
-    const page = this.props.page;
-    let link = this.props.linkTo;
-    if (link === '') {
-      link = page.path;
-    }
+    const {
+      page, noLink, excludePathString,
+    } = this.props;
 
-    const hasChildren = this.props.children != null;
+    let pagePath = <PagePath page={page} excludePathString={excludePathString} />;
+    if (!noLink != null) {
+      pagePath = <a className="text-break" href={page.pagePath}>{pagePath}</a>;
+    }
 
     return (
-      <li className="nav-item page-list-li w-100">
-        <a className="nav-link page-list-link d-flex align-items-center" href={link}>
-          <UserPicture user={page.lastUpdateUser} />
-          <PagePath page={page} excludePathString={this.props.excludePathString} />
-          <PageListMeta page={page} />
-          { hasChildren && (
-            <React.Fragment>
-              {this.props.children}
-            </React.Fragment>
-          )}
-        </a>
-      </li>
+      <>
+        <UserPicture user={page.lastUpdateUser} noLink={noLink} />
+        {pagePath}
+        <PageListMeta page={page} />
+      </>
     );
   }
 
@@ -36,12 +30,11 @@ export default class Page extends React.Component {
 
 Page.propTypes = {
   page: PropTypes.object.isRequired,
-  linkTo: PropTypes.string,
   excludePathString: PropTypes.string,
-  children: PropTypes.array,
+  noLink: PropTypes.bool,
 };
 
 Page.defaultProps = {
-  linkTo: '',
   excludePathString: '',
+  noLink: false,
 };

+ 5 - 4
src/client/js/components/RecentCreated/RecentCreated.jsx

@@ -65,10 +65,11 @@ class RecentCreated extends React.Component {
    *
    */
   generatePageList(pages) {
-    return pages.map((page) => {
-      return <Page page={page} key={`recent-created:list-view:${page._id}`} />;
-    });
-
+    return pages.map(page => (
+      <li key={`recent-created:list-view:${page._id}`}>
+        <Page page={page} />
+      </li>
+    ));
   }
 
   render() {

+ 35 - 32
src/client/js/components/SearchPage/SearchResult.jsx

@@ -170,6 +170,40 @@ class SearchResult extends React.Component {
     });
   }
 
+  renderListView(pages) {
+    return pages.map((page) => {
+      // Add prefix 'id_' in pageId, because scrollspy of bootstrap doesn't work when the first letter of id attr of target component is numeral.
+      const pageId = `#id_${page._id}`;
+      return (
+        <li key={page._id} className="nav-item page-list-li w-100">
+          <a className="nav-link page-list-link d-flex align-items-center" href={pageId}>
+            <Page page={page} noLink />
+            <div className="ml-auto d-flex">
+              { this.state.deletionMode
+                && (
+                  <div className="custom-control custom-checkbox custom-checkbox-danger">
+                    <input
+                      type="checkbox"
+                      id={`page-delete-check-${page._id}`}
+                      className="custom-control-input search-result-list-delete-checkbox"
+                      value={pageId}
+                      checked={this.state.selectedPages.has(page)}
+                      onChange={() => { return this.toggleCheckbox(page) }}
+                    />
+                    <label className="custom-control-label" htmlFor={`page-delete-check-${page._id}`}></label>
+                  </div>
+                )
+              }
+              <div className="page-list-option">
+                <a href={page.path}><i className="icon-login" /></a>
+              </div>
+            </div>
+          </a>
+        </li>
+      );
+    });
+  }
+
   render() {
     if (this.isError()) {
       return (
@@ -238,38 +272,7 @@ class SearchResult extends React.Component {
       );
     }
 
-    const listView = this.props.pages.map((page) => {
-      // Add prefix 'id_' in pageId, because scrollspy of bootstrap doesn't work when the first letter of id attr of target component is numeral.
-      const pageId = `#id_${page._id}`;
-      return (
-        <Page
-          page={page}
-          linkTo={pageId}
-          key={page._id}
-        >
-          <div className="ml-auto d-flex">
-            { this.state.deletionMode
-              && (
-                <div className="custom-control custom-checkbox custom-checkbox-danger">
-                  <input
-                    type="checkbox"
-                    id={`page-delete-check-${page._id}`}
-                    className="custom-control-input search-result-list-delete-checkbox"
-                    value={pageId}
-                    checked={this.state.selectedPages.has(page)}
-                    onChange={() => { return this.toggleCheckbox(page) }}
-                  />
-                  <label className="custom-control-label" htmlFor={`page-delete-check-${page._id}`}></label>
-                </div>
-              )
-            }
-            <div className="page-list-option">
-              <a href={page.path}><i className="icon-login" /></a>
-            </div>
-          </div>
-        </Page>
-      );
-    });
+    const listView = this.renderListView(this.props.pages);
 
     /*
     UI あとで考える

+ 1 - 1
src/client/js/components/SearchTypeahead.jsx

@@ -163,7 +163,7 @@ class SearchTypeahead extends React.Component {
     const page = option;
     return (
       <span>
-        <UserPicture user={page.lastUpdateUser} size="sm" withoutLink />
+        <UserPicture user={page.lastUpdateUser} size="sm" noLink />
         <PagePath page={page} />
         <PageListMeta page={page} />
       </span>

+ 40 - 11
src/client/js/components/User/UserPicture.jsx

@@ -2,6 +2,8 @@ import React from 'react';
 import md5 from 'md5';
 import PropTypes from 'prop-types';
 
+import { userPageRoot } from '@commons/util/path-utils';
+
 const DEFAULT_IMAGE = '/images/icons/user.svg';
 
 // TODO UserComponent?
@@ -49,6 +51,26 @@ export default class UserPicture extends React.Component {
     );
   }
 
+  RootElmWithoutLink = (props) => {
+    return <span {...props}>{props.children}</span>;
+  }
+
+  RootElmWithLink = (props) => {
+    const { user } = this.props;
+    const href = userPageRoot(user);
+
+    return <a href={href} {...props}>{props.children}</a>;
+  }
+
+  withTooltip = (RootElm) => {
+    const { user } = this.props;
+    const title = `@${user.username}<br />${user.name}`;
+
+    return props => (
+      <RootElm data-toggle="tooltip" data-placement="bottom" data-html="true" title={title}>{props.children}</RootElm>
+    );
+  }
+
   render() {
     const user = this.props.user;
 
@@ -56,18 +78,22 @@ export default class UserPicture extends React.Component {
       return this.renderForNull();
     }
 
-    const imgElem = (
-      <img
-        src={this.getUserPicture(user)}
-        alt={user.username}
-        className={this.getClassName()}
-      />
-    );
+    const { noLink, noTooltip } = this.props;
+
+    // determine RootElm
+    let RootElm = noLink ? this.RootElmWithoutLink : this.RootElmWithLink;
+    if (!noTooltip) {
+      RootElm = this.withTooltip(RootElm);
+    }
 
     return (
-      (this.props.withoutLink)
-        ? <span>{imgElem}</span>
-        : <a href={`/user/${user.username}`}>{imgElem}</a>
+      <RootElm>
+        <img
+          src={this.getUserPicture(user)}
+          alt={user.username}
+          className={this.getClassName()}
+        />
+      </RootElm>
     );
   }
 
@@ -76,9 +102,12 @@ export default class UserPicture extends React.Component {
 UserPicture.propTypes = {
   user: PropTypes.object,
   size: PropTypes.string,
-  withoutLink: PropTypes.bool,
+  noLink: PropTypes.bool,
+  noTooltip: PropTypes.bool,
 };
 
 UserPicture.defaultProps = {
   size: null,
+  noLink: false,
+  noTooltip: false,
 };

+ 6 - 24
src/client/js/components/User/UserPictureList.jsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { UncontrolledTooltip } from 'reactstrap';
+
 import { createSubscribedElement } from '../UnstatedUtils';
 import AppContainer from '../../services/AppContainer';
 
@@ -24,30 +24,12 @@ class UserPictureList extends React.Component {
 
   }
 
-  renderPictAndTooltip(user) {
-    const userId = user._id;
-    const userPictureContainerId = `userPictureContainer-${userId}`;
-
-    return (
-      <span key={userId}>
-        <span id={userPictureContainerId}>
-          <UserPicture user={user} size="xs" />
-        </span>
-        <UncontrolledTooltip
-          key={`tooltip-${userId}`}
-          placement="bottom"
-          target={userPictureContainerId}
-        >
-          @{user.username}<br />{user.name}
-        </UncontrolledTooltip>
-      </span>
-    );
-  }
-
   render() {
-    return this.state.users.map((user) => {
-      return this.renderPictAndTooltip(user);
-    });
+    return this.state.users.map(user => (
+      <span key={user._id}>
+        <UserPicture user={user} size="xs" />
+      </span>
+    ));
   }
 
 }

+ 1 - 1
src/server/views/widget/page_list.html

@@ -10,7 +10,7 @@
 <li>
   <img src="{{ page.lastUpdateUser|picture }}" class="picture rounded-circle">
   <a href="{{ page.path }}"
-    class="page-list-link text-break"
+    class="text-break"
     data-path="{{ page.path }}">{{ decodeURIComponent(page.path) }}
   </a>
   <span class="page-list-meta">