Browse Source

Merge pull request #1805 from weseek/support/search-result-page

Support/search result page
Yuki Takei 6 years ago
parent
commit
0e6a7547de

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

@@ -14,25 +14,20 @@ export default class Page extends React.Component {
       link = page.path;
     }
 
-    const styleFlex = {
-      flex: 1,
-    };
-
     const hasChildren = this.props.children != null;
 
     return (
-      <li className="page-list-li d-flex align-items-center">
-        <UserPicture user={page.lastUpdateUser} />
-        <a className="page-list-link" href={link}>
+      <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>
-        <PageListMeta page={page} />
-        { hasChildren && (
-          <React.Fragment>
-            <a style={styleFlex} href={link}>&nbsp;</a>
-            {this.props.children}
-          </React.Fragment>
-        ) }
       </li>
     );
   }

+ 1 - 1
src/client/js/components/SearchPage/DeletePageListModal.jsx

@@ -41,7 +41,7 @@ export default class DeletePageListModal extends React.Component {
           <div className="d-flex justify-content-between">
             <span className="text-danger">{this.props.errorMessage}</span>
             <span className="d-flex align-items-center">
-              <div className="custom-control custom-checkbox">
+              <div className="custom-control custom-checkbox custom-checkbox-danger">
                 <input type="checkbox" className="custom-control-input" id="customCheck-delete-completely" />
                 <label
                   className="custom-control-label text-danger"

+ 10 - 8
src/client/js/components/SearchPage/SearchPageForm.jsx

@@ -32,15 +32,17 @@ class SearchPageForm extends React.Component {
 
   render() {
     return (
-      <div className="input-group mb-3">
-        <SearchForm
-          t={this.props.t}
-          onSubmit={this.search}
-          keyword={this.state.searchedKeyword}
-          onInputChange={this.onInputChange}
-        />
+      <div className="input-group mb-3 d-flex">
+        <div className="flex-fill">
+          <SearchForm
+            t={this.props.t}
+            onSubmit={this.search}
+            keyword={this.state.searchedKeyword}
+            onInputChange={this.onInputChange}
+          />
+        </div>
         <div className="input-group-append">
-          <button className="btn btn-outline-secondary" type="button" id="button-addon2" onClick={this.search}>
+          <button className="btn btn-light" type="button" id="button-addon2" onClick={this.search}>
             <i className="icon-magnifier"></i>
           </button>
         </div>

+ 47 - 44
src/client/js/components/SearchPage/SearchResult.jsx

@@ -202,12 +202,12 @@ class SearchResult extends React.Component {
     if (this.state.deletionMode) {
       deletionModeButtons = (
         <div className="btn-group">
-          <button type="button" className="btn btn-rounded btn-default btn-xs" onClick={() => { return this.handleDeletionModeChange() }}>
+          <button type="button" className="btn btn-rounded btn-light btn-sm" onClick={() => { return this.handleDeletionModeChange() }}>
             <i className="icon-ban" /> Cancel
           </button>
           <button
             type="button"
-            className="btn btn-rounded btn-danger btn-xs"
+            className="btn btn-rounded btn-danger btn-sm"
             onClick={() => { return this.showDeleteConfirmModal() }}
             disabled={this.state.selectedPages.size === 0}
           >
@@ -216,22 +216,22 @@ class SearchResult extends React.Component {
         </div>
       );
       allSelectCheck = (
-        <div>
-          <label>
-            <input
-              type="checkbox"
-              onChange={() => { return this.handleAllSelect() }}
-              checked={this.isAllSelected()}
-            />
-            &nbsp;Check All
-          </label>
+        <div className="custom-control custom-checkbox custom-checkbox-danger">
+          <input
+            id="all-select-check"
+            className="custom-control-input"
+            type="checkbox"
+            onChange={() => { return this.handleAllSelect() }}
+            checked={this.isAllSelected()}
+          />
+          <label className="custom-control-label" htmlFor="all-select-check">&nbsp;Check All</label>
         </div>
       );
     }
     else {
       deletionModeButtons = (
         <div className="btn-group">
-          <button type="button" className="btn btn-default btn-rounded btn-xs" onClick={() => { return this.handleDeletionModeChange() }}>
+          <button type="button" className="btn btn-light rounded-pill btn-sm" onClick={() => { return this.handleDeletionModeChange() }}>
             <i className="ti-check-box" /> DeletionMode
           </button>
         </div>
@@ -239,26 +239,33 @@ class SearchResult extends React.Component {
     }
 
     const listView = this.props.pages.map((page) => {
-      const pageId = `#${page._id}`;
+      // 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}
         >
-          { this.state.deletionMode
-            && (
-              <input
-                type="checkbox"
-                className="search-result-list-delete-checkbox"
-                value={pageId}
-                checked={this.state.selectedPages.has(page)}
-                onChange={() => { return this.toggleCheckbox(page) }}
-              />
-            )
+          <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 className="page-list-option">
+              <a href={page.path}><i className="icon-login" /></a>
+            </div>
           </div>
         </Page>
       );
@@ -271,28 +278,25 @@ class SearchResult extends React.Component {
     return (
       <div className="content-main">
         <div className="search-result row" id="search-result">
-          <div className="col-md-4 hidden-xs hidden-sm page-list search-result-list" id="search-result-list">
-            <nav data-spy="affix" data-offset-top="50">
-              <div className="float-right">
-                {deletionModeButtons}
-                {allSelectCheck}
+          <div className="col-lg-4 d-none d-lg-block page-list search-result-list" id="search-result-list">
+            <nav>
+              <div className="d-flex align-items-start justify-content-between mt-1">
+                <div className="search-result-meta">
+                  <i className="icon-magnifier" /> Found {this.props.searchResultMeta.total} pages with &quot;{this.props.searchingKeyword}&quot;
+                </div>
+                <div className="text-nowrap">
+                  {deletionModeButtons}
+                  {allSelectCheck}
+                </div>
               </div>
-              <div className="search-result-meta">
-                <i className="icon-magnifier" /> Found {this.props.searchResultMeta.total} pages with &quot;{this.props.searchingKeyword}&quot;
-              </div>
-              <div className="clearfix"></div>
+
               <div className="page-list">
-                <ul className="page-list-ul page-list-ul-flat nav">
-                  {listView}
-                </ul>
+                <ul className="page-list-ul page-list-ul-flat nav nav-pills">{listView}</ul>
               </div>
             </nav>
           </div>
-          <div className="col-md-8 search-result-content" id="search-result-content">
-            <SearchResultList
-              pages={this.props.pages}
-              searchingKeyword={this.props.searchingKeyword}
-            />
+          <div className="col-lg-8 search-result-content" id="search-result-content">
+            <SearchResultList pages={this.props.pages} searchingKeyword={this.props.searchingKeyword} />
           </div>
         </div>
         <DeletePageListModal
@@ -303,8 +307,7 @@ class SearchResult extends React.Component {
           confirmedToDelete={this.deleteSelectedPages}
           toggleDeleteCompletely={this.toggleDeleteCompletely}
         />
-
-      </div>// content-main
+      </div> // content-main
     );
   }
 

+ 2 - 1
src/client/js/components/SearchPage/SearchResultList.jsx

@@ -18,7 +18,8 @@ class SearchResultList extends React.Component {
       const showTags = (page.tags != null) && (page.tags.length > 0);
 
       return (
-        <div id={page._id} key={page._id} className="search-result-page mb-5">
+        // Add prefix 'id_' in id attr, because scrollspy of bootstrap doesn't work when the first letter of id of target component is numeral.
+        <div id={`id_${page._id}`} key={page._id} className="search-result-page mb-5">
           <h2>
             <a href={page.path}>{page.path}</a>
             { showTags && (

+ 16 - 11
src/client/styles/scss/_page_list.scss

@@ -6,10 +6,8 @@
 
   .page-list-ul {
     padding-left: 0;
-    margin: 0;
 
     > li {
-      margin: 0;
       list-style: none;
 
       .picture {
@@ -18,20 +16,27 @@
       }
 
       > a {
-        display: inline;
-        padding: 0 4px;
+        padding: 0px;
         color: inherit;
-      }
 
-      > span.page-list-meta {
-        font-size: 0.9em;
+        &:hover {
+          color: inherit;
+        }
 
-        > span {
-          margin-right: 0.3rem;
+        span.page-path {
+          padding: 0 4px;
         }
 
-        i {
-          margin-right: 2px;
+        > span.page-list-meta {
+          font-size: 0.9em;
+
+          > span {
+            margin-right: 0.3rem;
+          }
+
+          i {
+            margin-right: 2px;
+          }
         }
       }
     }

+ 17 - 20
src/client/styles/scss/_search.scss

@@ -115,26 +115,23 @@
 
 .search-result {
   .search-result-list {
-    nav {
-      padding-right: 0;
-
-      &.affix {
-        top: 64px;
-        width: 33%;
-        height: 100%;
-        padding-right: 5px;
-        padding-bottom: 50px;
-        overflow-y: scroll;
-      }
-
-      .nav {
-        > li {
-          padding: 2px 8px;
-
-          &.active {
-            padding-right: 5px;
-            border-right: solid 3px transparent;
-          }
+    position: sticky;
+    top: 64px;
+    height: 100vh;
+    overflow-y: scroll;
+
+    .nav.nav-pills {
+      > li > a {
+        padding: 2px 8px;
+        border-radius: 0;
+
+        &:hover {
+          color: inherit;
+          text-decoration: none;
+        }
+        &.active {
+          padding: 2px 5px;
+          border-right: solid 3px transparent;
         }
       }
     }

+ 10 - 9
src/client/styles/scss/theme/_apply-colors.scss

@@ -276,17 +276,18 @@ body.on-edit {
   .search-result-list {
     .page-list {
       .page-list-ul {
-        > li > a {
-          background-color: transparent;
+        > li.nav-item > a.nav-link {
+          color: inherit;
         }
 
-        li:hover {
-          background-color: darken($bgcolor-global, 4%);
-        }
-
-        li.active {
-          background-color: darken($bgcolor-global, 8%);
-          border-color: theme-color('primary');
+        a {
+          &.hover {
+            background-color: darken($bgcolor-global, 4%);
+          }
+          &.active {
+            background-color: darken($bgcolor-global, 8%);
+            border-color: theme-color('primary');
+          }
         }
       }
     }

+ 1 - 1
src/server/views/search.html

@@ -15,7 +15,7 @@
 <div class="container-fluid">
 
   <div class="row">
-    <div id="main" class="main col-md-12 search-page">
+    <div id="main" class="main col-lg-12 search-page">
       <div class="" id="search-page"></div>
     </div>
   </div>