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

Add components for search page

Sotaro KARASAWA 10 лет назад
Родитель
Сommit
882505368f

+ 5 - 1
lib/views/layout/layout.html

@@ -18,7 +18,11 @@
 {% endblock %}
 
 {% block html_body %}
-<body class="crowi main-container {% block html_base_css %}{% endblock %}" data-me="{{ user._id.toString() }}">
+<body
+  class="crowi main-container {% block html_base_css %}{% endblock %}"
+  data-me="{{ user._id.toString() }}"
+ {% block html_base_attr %}{% endblock %}
+ >
 <div id="fb-root"></div>
 <script>
   window.fbAsyncInit = function() {

+ 5 - 19
lib/views/search.html

@@ -1,30 +1,16 @@
 {% extends 'layout/single.html' %}
 
 {% block main_css_class %}search-page{% endblock %}
+{% block html_base_attr %}
+  data-spy="scroll"
+  data-target="#search-result-list"
+{% endblock %}
 
 {% block html_title %}Search {% endblock %}
 
-{% block content_head %}
-  {% block content_head_before %}
-  {% endblock %}
-
-  <div class="header-wrap">
-    <header class="">
-      <input type="text" name="q" value="{{ q }}" class="form-control">
-    </header>
-  </div>
-{% endblock %}
-
 {% block content_main %}
 
-<div class="search-list content-main" id="content-main">
-  <div class="search-result row">
-    <div class="col-md-3 page-list">
-    </div>
-    <div class="col-md-9">
-      pages ...
-    </div>
-  </div>
+<div class="" id="search-page">
 </div>
 
 {% endblock %}

+ 1 - 0
resource/css/_page_list.scss

@@ -35,6 +35,7 @@
       }
 
       > a {
+        display: inline;
         padding: 0 4px;
         font-size: 1.1em;
         color: #666;

+ 30 - 1
resource/css/_search.scss

@@ -1,4 +1,3 @@
-
 .search-listpage-icon {
   font-size: 16px;
   color: #999;
@@ -39,3 +38,33 @@
 
 }
 
+
+// search page
+#content-main {
+  position: relative;
+}
+.search-result {
+
+  .search-result-list {
+    nav {
+      &.affix {
+        top: 8px;
+        width: 25%;
+        padding-right: 30px;
+      }
+      .nav {
+
+        > li {
+          padding: 0px 8px;
+          &.active {
+            border-right: solid 3px #666;
+            background: #f0f0f0;
+          }
+        }
+      }
+    }
+  }
+
+  .search-result-content {
+  }
+}

+ 3 - 1
resource/js/app.js

@@ -1,7 +1,8 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
 
-import  SearchBox  from './components/Header/SearchBox';
+import SearchBox  from './components/Header/SearchBox';
+import SearchPage  from './components/Search/SearchPage';
 
 /*
 class Crowi extends React.Component {
@@ -21,6 +22,7 @@ class Crowi extends React.Component {
 
 var componentMappings = {
   'search-top': <SearchBox />,
+  'search-page': <SearchPage />,
 };
 
 Object.keys(componentMappings).forEach((key) => {

+ 8 - 8
resource/js/components/Header/SearchForm.js

@@ -1,5 +1,6 @@
 import React from 'react';
 
+// Header.SearchForm
 export default class SearchForm extends React.Component {
 
   constructor(props) {
@@ -10,12 +11,16 @@ export default class SearchForm extends React.Component {
       searchedKeyword: '',
     };
 
-    this.handleSubmit= this.handleSubmit.bind(this);
-    this.handleChange= this.handleChange.bind(this);
+    this.handleChange = this.handleChange.bind(this);
+    this.ticker = null;
   }
 
   componentDidMount() {
-    setInterval(this.searchFieldTicker.bind(this), this.props.pollInterval);
+    this.ticker = setInterval(this.searchFieldTicker.bind(this), this.props.pollInterval);
+  }
+
+  componentWillUnmount() {
+    clearInterval(this.ticker);
   }
 
   search() {
@@ -29,11 +34,6 @@ export default class SearchForm extends React.Component {
     this.search();
   }
 
-  handleSubmit(event) {
-    event.preventDefault();
-    this.search();
-  }
-
   handleChange(event) {
     const keyword = event.target.value;
     this.setState({keyword});

+ 60 - 0
resource/js/components/Search/SearchForm.js

@@ -0,0 +1,60 @@
+import React from 'react';
+
+// Search.SearchForm
+export default class SearchForm extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      keyword: this.props.keyword,
+      searchedKeyword: this.props.keyword,
+    };
+
+    this.handleSubmit = this.handleSubmit.bind(this);
+    this.handleChange = this.handleChange.bind(this);
+  }
+
+  componentDidMount() {
+  }
+
+  componentWillUnmount() {
+  }
+
+  search() {
+    if (this.state.searchedKeyword != this.state.keyword) {
+      this.props.onSearchFormChanged({keyword: this.state.keyword});
+      this.setState({searchedKeyword: this.state.keyword});
+    }
+  }
+
+  handleSubmit(event) {
+    event.preventDefault();
+    this.search({keyword: this.state.keyword});
+  }
+
+  handleChange(event) {
+    const keyword = event.target.value;
+    this.setState({keyword});
+  }
+
+  render() {
+    return (
+      <form className="form" onSubmit={this.handleSubmit}>
+        <input
+          type="text"
+          name="q"
+          value={this.state.keyword}
+          onChange={this.handleChange}
+          className="form-control"
+          />
+      </form>
+    );
+  }
+}
+
+SearchForm.propTypes = {
+  onSearchFormChanged: React.PropTypes.func.isRequired,
+};
+SearchForm.defaultProps = {
+};

+ 99 - 0
resource/js/components/Search/SearchPage.js

@@ -0,0 +1,99 @@
+// This is the root component for #search-page
+
+import React from 'react';
+
+import SearchForm from './SearchForm';
+import SearchResult from './SearchResult';
+import axios from 'axios'
+
+export default class SearchPage extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      location: location,
+      searchingKeyword: this.props.query.q || '',
+      searchedPages: [],
+      searchError: null,
+    }
+
+    this.search = this.search.bind(this);
+  }
+
+  componentDidMount() {
+    if (this.state.searchingKeyword !== '')  {
+      this.search({keyword: this.state.searchingKeyword});
+      this.setState({searchedKeyword: this.state.keyword});
+    }
+  }
+
+  static getQueryByLocation(location) {
+    let search = location.search || '';
+    let query = {};
+
+    search.replace(/^\?/, '').split('&').forEach(function(element) {
+      let queryParts = element.split('=');
+      query[queryParts[0]] = queryParts[1];
+    });
+
+    console.log(query);
+    return query;
+  }
+
+  search(data) {
+    const keyword = data.keyword;
+    if (keyword === '') {
+      this.setState({
+        searchingKeyword: '',
+        searchedPages: [],
+      });
+
+      return true;
+    }
+
+    this.setState({
+      searchingKeyword: keyword,
+    });
+
+    axios.get('/_api/search', {params: {q: keyword}})
+    .then((res) => {
+      if (res.data.ok) {
+        this.setState({
+          searchingKeyword: keyword,
+          searchedPages: res.data.data,
+        });
+      }
+      // TODO error
+    })
+    .catch((res) => {
+      // TODO error
+    });
+  };
+
+  render() {
+    return (
+      <div>
+        <div className="header-wrap">
+          <header>
+            <SearchForm
+              onSearchFormChanged={this.search}
+              keyword={this.state.searchingKeyword}
+              />
+          </header>
+        </div>
+
+        <SearchResult pages={this.state.searchedPages} />
+      </div>
+    );
+  }
+}
+
+SearchPage.propTypes = {
+  query: React.PropTypes.object,
+};
+SearchPage.defaultProps = {
+  //pollInterval: 1000,
+  query: SearchPage.getQueryByLocation(location || {}),
+};
+

+ 32 - 0
resource/js/components/Search/SearchResult.js

@@ -0,0 +1,32 @@
+import React from 'react';
+
+// Search.SearchResult
+export default class SearchResult extends React.Component {
+
+  render() {
+
+
+    return (
+      <div className="content-main" id="content-main">
+        <div className="search-result row" id="search-result">
+          <div className="col-md-3 page-list search-result-list" id="search-result-list">
+          row
+          </div>
+          <div className="col-md-9 search-result-content" id="search-result-content">
+          content
+          </div>
+        </div>
+      </div>
+    );
+  }
+}
+
+SearchResult.propTypes = {
+  searchedPages: React.PropTypes.array.isRequired,
+  searchingKeyword: React.PropTypes.string.isRequired,
+};
+SearchResult.defaultProps = {
+  searchedPages: [],
+  searchingKeyword: '',
+};
+