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

Merge pull request #4525 from weseek/feat/77750-modify-search-result-item-layout

Feat/77750 modify search result item layout
Yuki Takei 4 лет назад
Родитель
Сommit
c3c0d2d35f

+ 1 - 0
packages/app/config/logger/config.dev.js

@@ -35,5 +35,6 @@ module.exports = {
   'growi:services:*': 'debug',
   'growi:services:*': 'debug',
   // 'growi:StaffCredit': 'debug',
   // 'growi:StaffCredit': 'debug',
   // 'growi:cli:StickyStretchableScroller': 'debug',
   // 'growi:cli:StickyStretchableScroller': 'debug',
+  'growi:searchResultList': 'debug',
 
 
 };
 };

+ 6 - 66
packages/app/src/components/SearchPage/SearchResultList.jsx

@@ -1,82 +1,23 @@
 import React from 'react';
 import React from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
-import Page from '../PageList/Page';
-import loggerFactory from '~/utils/logger';
+import SearchResultListItem from './SearchResultListItem';
 
 
-const logger = loggerFactory('growi:searchResultList');
 class SearchResultList extends React.Component {
 class SearchResultList extends React.Component {
 
 
   render() {
   render() {
     return this.props.pages.map((page) => {
     return 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 = `#${page._id}`;
       return (
       return (
-        <li key={page._id} className="nav-item page-list-li w-100 m-0 border-bottom">
-          <a
-            className="nav-link page-list-link d-flex align-items-baseline"
-            href={pageId}
-            onClick={() => {
-              try {
-                if (this.props.onClickInvoked == null) { throw new Error('onClickInvoked is null') }
-                this.props.onClickInvoked(page._id);
-              }
-              catch (error) {
-                logger.error(error);
-              }
-            }}
-          >
-            <div className="form-check my-auto">
-              <input className="form-check-input my-auto" type="checkbox" value="" id="flexCheckDefault" />
-            </div>
-            {/* TODO: remove dummy snippet and adjust style */}
-            <div className="d-block">
-              <Page page={page} noLink />
-              <div className="border-gray mt-5">{page.snippet}</div>
-            </div>
-            <div className="ml-auto d-flex">
-              {this.props.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.props.selectedPages.has(page)}
-                    onChange={() => {
-                      try {
-                        if (this.props.onChangeInvoked == null) { throw new Error('onChnageInvoked is null') }
-                        return this.props.onChangeInvoked(page);
-                      }
-                      catch (error) {
-                        logger.error(error);
-                      }
-                    }}
-                  />
-                  <label className="custom-control-label" htmlFor={`page-delete-check-${page._id}`}></label>
-                </div>
-              )}
-              <div className="page-list-option">
-                <button
-                  type="button"
-                  className="btn btn-link p-0"
-                  value={page.path}
-                  onClick={(e) => {
-                    window.location.href = e.currentTarget.value;
-                  }}
-                >
-                  <i className="icon-login" />
-                </button>
-              </div>
-            </div>
-          </a>
-        </li>
+        <SearchResultListItem
+          page={page}
+          onClickInvoked={this.props.onClickInvoked}
+          noLink
+        />
       );
       );
     });
     });
   }
   }
 
 
 }
 }
 
 
-
 SearchResultList.propTypes = {
 SearchResultList.propTypes = {
   pages: PropTypes.array.isRequired,
   pages: PropTypes.array.isRequired,
   deletionMode: PropTypes.bool.isRequired,
   deletionMode: PropTypes.bool.isRequired,
@@ -85,5 +26,4 @@ SearchResultList.propTypes = {
   onChangeInvoked: PropTypes.func,
   onChangeInvoked: PropTypes.func,
 };
 };
 
 
-
 export default SearchResultList;
 export default SearchResultList;

+ 92 - 0
packages/app/src/components/SearchPage/SearchResultListItem.tsx

@@ -0,0 +1,92 @@
+import React, { FC } from 'react';
+
+import { UserPicture, PageListMeta, PagePathLabel } from '@growi/ui';
+import { DevidedPagePath } from '@growi/core';
+
+import loggerFactory from '~/utils/logger';
+
+const logger = loggerFactory('growi:searchResultList');
+
+type Props ={
+  page: {
+    _id: string,
+    snippet: string,
+    path: string,
+    noLink: boolean,
+    lastUpdateUser: any
+  },
+  onClickInvoked: (data: string) => void,
+}
+
+const SearchResultListItem: FC<Props> = (props:Props) => {
+
+  const { page, onClickInvoked } = props;
+
+  // 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 = `#${page._id}`;
+
+  const dPagePath = new DevidedPagePath(page.path, false, true);
+  const pagePathElem = <PagePathLabel page={page} isFormerOnly />;
+
+  return (
+    <li key={page._id} className="page-list-li w-100 border-bottom pr-4">
+      <a
+        className="d-block pt-3"
+        href={pageId}
+        onClick={() => {
+          try {
+            if (onClickInvoked == null) { throw new Error('onClickInvoked is null') }
+            onClickInvoked(page._id);
+          }
+          catch (error) {
+            logger.error(error);
+          }
+        }}
+      >
+        <div className="d-flex">
+          {/* checkbox */}
+          <div className="form-check my-auto mx-2">
+            <input className="form-check-input my-auto" type="checkbox" value="" id="flexCheckDefault" />
+          </div>
+          <div className="w-100">
+            {/* page path */}
+            <small className="mb-1">
+              <i className="icon-fw icon-home"></i>
+              {pagePathElem}
+            </small>
+            <div className="d-flex my-1 align-items-center">
+              {/* page title */}
+              <h3 className="mb-0">
+                <UserPicture user={page.lastUpdateUser} />
+                <span className="mx-2">{dPagePath.latter}</span>
+              </h3>
+              {/* page meta */}
+              <div className="d-flex mx-2">
+                <PageListMeta page={page} />
+              </div>
+              {/* doropdown icon */}
+              <div className="ml-auto">
+                <i className="fa fa-ellipsis-v text-muted"></i>
+              </div>
+
+              {/* Todo: add the following icon into dropdown menu */}
+              {/* <button
+                type="button"
+                className="btn btn-link p-0"
+                value={page.path}
+                onClick={(e) => {
+                  window.location.href = e.currentTarget.value;
+                }}
+              >
+                <i className="icon-login" />
+              </button> */}
+
+            </div>
+            <div className="mt-1">{page.snippet}</div>
+          </div>
+        </div>
+      </a>
+    </li>
+  );
+};
+export default SearchResultListItem;

+ 8 - 0
packages/ui/src/components/PagePath/PagePathLabel.jsx

@@ -14,6 +14,13 @@ export const PagePathLabel = (props) => {
     return <span className={classNames.join(' ')}>{dPagePath.latter}</span>;
     return <span className={classNames.join(' ')}>{dPagePath.latter}</span>;
   }
   }
 
 
+  if (props.isFormerOnly) {
+    const textElem = dPagePath.isFormerRoot
+      ? <>/</>
+      : <>{dPagePath.former}</>;
+    return <span className={classNames.join(' ')}>{textElem}</span>;
+  }
+
   const textElem = dPagePath.isRoot
   const textElem = dPagePath.isRoot
     ? <><strong>/</strong></>
     ? <><strong>/</strong></>
     : <>{dPagePath.former}/<strong>{dPagePath.latter}</strong></>;
     : <>{dPagePath.former}/<strong>{dPagePath.latter}</strong></>;
@@ -24,6 +31,7 @@ export const PagePathLabel = (props) => {
 PagePathLabel.propTypes = {
 PagePathLabel.propTypes = {
   page: PropTypes.object.isRequired,
   page: PropTypes.object.isRequired,
   isLatterOnly: PropTypes.bool,
   isLatterOnly: PropTypes.bool,
+  isFormerOnly: PropTypes.bool,
   additionalClassNames: PropTypes.arrayOf(PropTypes.string),
   additionalClassNames: PropTypes.arrayOf(PropTypes.string),
 };
 };