SearchForm.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import React from 'react';
  2. import { FormGroup, Button, InputGroup } from 'react-bootstrap';
  3. import { AsyncTypeahead } from 'react-bootstrap-typeahead';
  4. import axios from 'axios'
  5. import UserPicture from '../User/UserPicture';
  6. import PageListMeta from '../PageList/PageListMeta';
  7. import PagePath from '../PageList/PagePath';
  8. // Header.SearchForm
  9. export default class SearchForm extends React.Component {
  10. constructor(props) {
  11. super(props);
  12. this.crowi = window.crowi; // FIXME
  13. this.state = {
  14. keyword: '',
  15. searchedKeyword: '',
  16. pages: [],
  17. searchError: null,
  18. };
  19. this.search = this.search.bind(this);
  20. this.clearForm = this.clearForm.bind(this);
  21. this.getFormClearComponent = this.getFormClearComponent.bind(this);
  22. this.renderMenuItemChildren = this.renderMenuItemChildren.bind(this);
  23. }
  24. componentDidMount() {
  25. }
  26. componentWillUnmount() {
  27. }
  28. search(keyword) {
  29. if (keyword === '') {
  30. this.setState({
  31. keyword: '',
  32. searchedKeyword: '',
  33. });
  34. return;
  35. }
  36. this.crowi.apiGet('/search', {q: keyword})
  37. .then(res => {
  38. this.setState({
  39. keyword: '',
  40. pages: res.data,
  41. });
  42. }).catch(err => {
  43. this.setState({
  44. searchError: err
  45. });
  46. });
  47. }
  48. getFormClearComponent() {
  49. let isHidden = (this.state.keyword.length === 0);
  50. return isHidden ? <span></span> : (
  51. <a className="btn btn-link search-top-clear" onClick={this.clearForm} hidden={isHidden}>
  52. <i className="fa fa-times-circle" />
  53. </a>
  54. );
  55. }
  56. clearForm() {
  57. this._typeahead.getInstance().clear();
  58. this.setState({keyword: ''});
  59. }
  60. renderMenuItemChildren(option, props, index) {
  61. const page = option;
  62. return (
  63. <span>
  64. <UserPicture user={page.revision.author} />
  65. <PagePath page={page} />
  66. <PageListMeta page={page} />
  67. </span>
  68. );
  69. }
  70. render() {
  71. const emptyLabel = (this.state.searchError !== null) ? 'Error on searching.' : 'No matches found.';
  72. const formClear = this.getFormClearComponent();
  73. return (
  74. <form
  75. action="/_search"
  76. className="search-form form-group input-group search-top-input-group"
  77. >
  78. <FormGroup>
  79. <InputGroup>
  80. <AsyncTypeahead
  81. ref={ref => this._typeahead = ref}
  82. name="q"
  83. labelKey="path"
  84. minLength={2}
  85. options={this.state.pages}
  86. placeholder="Search ... Page Title (Path) and Content"
  87. submitFormOnEnter={true}
  88. onSearch={this.search}
  89. renderMenuItemChildren={this.renderMenuItemChildren}
  90. />
  91. {formClear}
  92. <InputGroup.Button>
  93. <Button type="submit">
  94. <i className="search-top-icon fa fa-search"></i>
  95. </Button >
  96. </InputGroup.Button>
  97. </InputGroup>
  98. </FormGroup>
  99. </form>
  100. );
  101. }
  102. }
  103. SearchForm.propTypes = {
  104. };
  105. SearchForm.defaultProps = {
  106. };