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

Merge pull request #909 from weseek/feat/search-with-tag-brush-up

Feat/search with tag brush up
Yuki Takei 7 лет назад
Родитель
Сommit
8b6d03e839

+ 1 - 1
package.json

@@ -195,7 +195,7 @@
     "prettier-stylelint": "^0.4.2",
     "react": "^16.8.3",
     "react-bootstrap": "^0.32.1",
-    "react-bootstrap-typeahead": "^3.3.4",
+    "react-bootstrap-typeahead": "^3.4.2",
     "react-clipboard.js": "^2.0.0",
     "react-codemirror2": "^5.1.0",
     "react-dom": "^16.8.3",

+ 1 - 0
resource/locales/en-US/translation.json

@@ -11,6 +11,7 @@
   "Cancel": "Cancel",
   "Create": "Create",
   "Admin": "Admin",
+  "Tags": "Tags",
   "New": "New",
   "Shortcuts": "Shortcuts",
   "eg": "e.g.",

+ 7 - 0
resource/locales/ja/translation.json

@@ -11,6 +11,7 @@
   "Cancel": "キャンセル",
   "Create": "作成",
   "Admin": "管理",
+  "Tags": "タグ",
   "New": "作成",
   "Shortcuts": "ショートカット",
   "eg": "例:",
@@ -208,6 +209,12 @@
     },
     "exclude_prefix": {
       "desc": "ページ名が {{path}} から始まるページを除外"
+    },
+    "tag": {
+      "desc": "{{tag}} というタグを含むページを検索"
+    },
+    "exclude_tag": {
+      "desc": "{{tag}} というタグを含むページを除外"
     }
   },
   "search": {

+ 3 - 4
src/client/js/components/PageTagForm.jsx

@@ -28,16 +28,15 @@ export default class PageTagForm extends React.Component {
     return (
       <div className="tag-typeahead">
         <AsyncTypeahead
-          allowNew
+          id="async-typeahead"
           caseSensitive={false}
           defaultSelected={this.props.currentPageTags}
-          emptyLabel=""
           isLoading={this.state.isLoading}
           minLength={1}
           multiple
           newSelectionPrefix=""
-          onChange={(selected) => {
-            this.setState({ selected }, () => {
+          onChange={(list) => { // list is a list of object about value. an element have customOption, id and label properties
+            this.setState({ selected: list.map((obj) => { return obj.label }) }, () => {
               this.props.addNewTag(this.state.selected);
             });
           }}

+ 8 - 0
src/client/js/components/SearchForm.js

@@ -72,6 +72,14 @@ export default class SearchForm extends React.Component {
             <th className="text-right pt-2"><code>-prefix:/user/</code></th>
             <td><h6 className="m-0 pt-1">{ t('search_help.exclude_prefix.desc', { path: '/user/' }) }</h6></td>
           </tr>
+          <tr>
+            <th className="text-right pt-2"><code>tag:wiki</code></th>
+            <td><h6 className="m-0 pt-1">{ t('search_help.tag.desc', { tag: 'wiki' }) }</h6></td>
+          </tr>
+          <tr>
+            <th className="text-right pt-2"><code>-tag:wiki</code></th>
+            <td><h6 className="m-0 pt-1">{ t('search_help.exclude_tag.desc', { tag: 'wiki' }) }</h6></td>
+          </tr>
         </tbody>
       </table>
     );

+ 4 - 1
src/client/js/components/SearchPage/SearchResultList.js

@@ -17,7 +17,10 @@ export default class SearchResultList extends React.Component {
     const resultList = this.props.pages.map((page) => {
       return (
         <div id={page._id} key={page._id} className="search-result-page">
-          <h2><a href={page.path}>{page.path}</a></h2>
+          <h2 className="inline"><a href={page.path}>{page.path}</a></h2>
+          { page.tags.length > 0 && (
+            <span><i className="tag-icon icon-tag"></i> {page.tags.join(', ')}</span>
+          )}
           <RevisionLoader
             crowi={this.props.crowi}
             crowiRenderer={this.growiRenderer}

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

@@ -173,6 +173,7 @@ export default class SearchTypeahead extends React.Component {
       <div className="search-typeahead">
         <AsyncTypeahead
           {...this.props}
+          id="async-typeahead"
           ref={(c) => { this.typeahead = c }}
           inputProps={inputProps}
           isLoading={this.state.isLoading}

+ 6 - 5
src/client/styles/scss/_search.scss

@@ -45,7 +45,7 @@
         font-size: 0.9em;
         color: #999;
 
-        >span {
+        > span {
           margin-right: 0.3rem;
         }
       }
@@ -114,7 +114,6 @@
 }
 
 .search-sidebar {
-
   .search-form,
   .form-group,
   .rbt-input.form-control,
@@ -157,7 +156,7 @@
       }
 
       .nav {
-        >li {
+        > li {
           padding: 2px 8px;
 
           &.active {
@@ -187,12 +186,14 @@
       // adjust for anchor links by the height of fixed .search-page-input
       margin-top: -48px;
 
-      >h2 {
+      > h2 {
+        display: inline;
+        margin-right: 10px;
         font-size: 20px;
         line-height: 1em;
       }
 
-      &:first-child>h2 {
+      &:first-child > h2 {
         margin-top: 0;
       }
 

+ 9 - 1
src/server/routes/search.js

@@ -69,7 +69,15 @@ module.exports = function(crowi, app) {
         scoreMap[esPage._id] = esPage._score;
       }
 
-      const findResult = await Page.findListByPageIds(esResult.data);
+      const ids = esResult.data.map((page) => { return page._id });
+      const findResult = await Page.findListByPageIds(ids);
+
+      // add tag data to result pages
+      findResult.pages.map((page) => {
+        const data = esResult.data.find((data) => { return page.id === data._id });
+        page._doc.tags = data._source.tag_names;
+        return page;
+      });
 
       result.meta = esResult.meta;
       result.totalCount = findResult.totalCount;

+ 2 - 2
src/server/util/search.js

@@ -387,7 +387,7 @@ SearchClient.prototype.search = async function(query) {
 
 SearchClient.prototype.createSearchQuerySortedByUpdatedAt = function(option) {
   // getting path by default is almost for debug
-  let fields = ['path', 'bookmark_count'];
+  let fields = ['path', 'bookmark_count', 'tag_names'];
   if (option) {
     fields = option.fields || fields;
   }
@@ -408,7 +408,7 @@ SearchClient.prototype.createSearchQuerySortedByUpdatedAt = function(option) {
 };
 
 SearchClient.prototype.createSearchQuerySortedByScore = function(option) {
-  let fields = ['path', 'bookmark_count'];
+  let fields = ['path', 'bookmark_count', 'tag_names'];
   if (option) {
     fields = option.fields || fields;
   }

+ 5 - 3
src/server/views/layout/layout.html

@@ -153,9 +153,11 @@
           </a>
         </li>
         <li>
-          <a href="/tags">
-            <i class="fa fa-tags"></i>Tags
-          </a>
+          <li class="nav-item-admin">
+            <a href="/tags">
+              <i class="tag-icon icon-tag"></i><span>{{ t('Tags') }}</span>
+            </a>
+          </li>
         </li>
         <li>
           {% if searchConfigured() %}

Разница между файлами не показана из-за своего большого размера
+ 0 - 137
yarn.lock


Некоторые файлы не были показаны из-за большого количества измененных файлов