SearchResult.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import Page from '../PageList/Page';
  4. import SearchResultList from './SearchResultList';
  5. import SearchResultInput from './SearchResultInput';
  6. // Search.SearchResult
  7. export default class SearchResult extends React.Component {
  8. constructor(props) {
  9. super(props);
  10. this.state = {
  11. deletionMode : false,
  12. selectedPages : new Set(),
  13. }
  14. this.toggleCheckbox = this.toggleCheckbox.bind(this);
  15. }
  16. isNotSearchedYet() {
  17. return !this.props.searchResultMeta.took;
  18. }
  19. isNotFound() {
  20. return this.props.searchingKeyword !== '' && this.props.pages.length === 0;
  21. }
  22. isError() {
  23. if (this.props.searchError !== null) {
  24. return true;
  25. }
  26. return false;
  27. }
  28. toggleCheckbox(page) {
  29. if (this.state.selectedPages.has(page)) {
  30. this.state.selectedPages.delete(page);
  31. } else {
  32. this.state.selectedPages.add(page);
  33. }
  34. }
  35. handleDeletionModeChange() {
  36. this.setState({deletionMode: !this.state.deletionMode});
  37. }
  38. render() {
  39. const excludePathString = this.props.tree;
  40. //console.log(this.props.searchError);
  41. //console.log(this.isError());
  42. if (this.isError()) {
  43. return (
  44. <div className="content-main">
  45. <i className="searcing fa fa-warning"></i> Error on searching.
  46. </div>
  47. );
  48. }
  49. if (this.isNotSearchedYet()) {
  50. return <div />;
  51. }
  52. if (this.isNotFound()) {
  53. let under = '';
  54. if (this.props.tree !== '') {
  55. under = ` under "${this.props.tree}"`;
  56. }
  57. return (
  58. <div className="content-main">
  59. <i className="fa fa-meh-o" /> No page found with "{this.props.searchingKeyword}"{under}
  60. </div>
  61. );
  62. }
  63. let deletionModeButtons = '';
  64. if (this.state.deletionMode) {
  65. deletionModeButtons =
  66. <div className="btn-group">
  67. <button type="button" className="btn btn-danger" data-target="#deletePages" data-toggle="modal"><i className="fa fa-trash-o"/> Delete</button>
  68. <button type="button" className="btn btn-default" onClick={() => this.handleDeletionModeChange()}><i className="fa fa-undo"/> Cancel</button>
  69. </div>
  70. }
  71. else {
  72. deletionModeButtons =
  73. <div className="btn-group">
  74. <button type="button" className="btn btn-default" onClick={() => this.handleDeletionModeChange()}><i className="fa fa-trash-o"/> DeletionMode</button>
  75. </div>
  76. }
  77. const listView = this.props.pages.map((page) => {
  78. const pageId = "#" + page._id;
  79. return (
  80. <Page page={page}
  81. linkTo={pageId}
  82. key={page._id}
  83. excludePathString={excludePathString}
  84. >
  85. <SearchResultInput
  86. page={page}
  87. deletionMode={this.state.deletionMode}
  88. handleCheckboxChange={this.toggleCheckbox}/>
  89. <div className="page-list-option">
  90. <a href={page.path}><i className="fa fa-arrow-circle-right" /></a>
  91. </div>
  92. </Page>
  93. );
  94. });
  95. // TODO あとでなんとかする
  96. setTimeout(() => {
  97. $('#search-result-list > nav').affix({ offset: { top: 120 }});
  98. }, 1200);
  99. /*
  100. UI あとで考える
  101. <span className="search-result-meta">Found: {this.props.searchResultMeta.total} pages with "{this.props.searchingKeyword}"</span>
  102. */
  103. return (
  104. <div className="content-main">
  105. <div className="search-result row" id="search-result">
  106. <div className="col-md-4 hidden-xs hidden-sm page-list search-result-list" id="search-result-list">
  107. <nav data-spy="affix" data-offset-top="120">
  108. {deletionModeButtons}
  109. <ul className="page-list-ul page-list-ul-flat nav">
  110. {listView}
  111. </ul>
  112. </nav>
  113. </div>
  114. <div className="col-md-8 search-result-content" id="search-result-content">
  115. <div className="search-result-meta"><i className="fa fa-lightbulb-o" /> Found {this.props.searchResultMeta.total} pages with "{this.props.searchingKeyword}"</div>
  116. <SearchResultList
  117. pages={this.props.pages}
  118. searchingKeyword={this.props.searchingKeyword}
  119. />
  120. </div>
  121. </div>
  122. </div>
  123. );
  124. }
  125. }
  126. SearchResult.propTypes = {
  127. tree: PropTypes.string.isRequired,
  128. pages: PropTypes.array.isRequired,
  129. searchingKeyword: PropTypes.string.isRequired,
  130. searchResultMeta: PropTypes.object.isRequired,
  131. };
  132. SearchResult.defaultProps = {
  133. tree: '',
  134. pages: [],
  135. searchingKeyword: '',
  136. searchResultMeta: {},
  137. searchError: null,
  138. };