All files / client/components/HeaderSearchBox SearchSuggest.tsx

0% Statements 0/32
0% Branches 0/14
0% Functions 0/9
0% Lines 0/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123                                                                                                                                                                                                                                                     
import React from 'react'
import { Card } from 'reactstrap'
import { withTranslation, WithTranslation } from 'react-i18next'
import queryString from 'query-string'
import Icon, { IconName } from 'components/Common/Icon'
import ListView from 'components/PageList/ListView'
import RecentlyViewedPageList from './RecentlyViewedPageList'
import { Page } from 'client/types/crowi'
import Crowi from 'client/util/Crowi'
 
interface Props extends WithTranslation {
  searchedPages: {
    portalPages?: []
    publicPages?: []
    userPages?: []
  }
  searchingKeyword: string
  searching: boolean
  searchError: Error | null
  focused: boolean
  crowi: Crowi
}
 
class SearchSuggest extends React.Component<Props> {
  static defaultProps = {
    searchedPages: {},
    searchingKeyword: '',
    searchError: null,
    searching: false,
    focused: false,
  }
 
  constructor(props: Props) {
    super(props)
 
    this.buildSearchUrl = this.buildSearchUrl.bind(this)
    this.renderList = this.renderList.bind(this)
  }
 
  buildSearchUrl(type: string) {
    const q = this.props.searchingKeyword
    const query = queryString.stringify({ q, type })
    return `/_search?${query}`
  }
 
  getNumberOfResults() {
    const { searchedPages } = this.props
    const groupedPages = Object.values(searchedPages)
    const sum = (array: any[]): number => array.reduce((p, c) => p + c, 0)
    return sum(groupedPages.map((r = []) => r.length))
  }
 
  renderList(title: string, icon: IconName, type: string, pages?: Page[]) {
    const { t } = this.props
    return (
      pages &&
      pages.length > 0 && (
        <div className="grouped-page-list" key={type}>
          <h6>
            <Icon name={icon} /> <span className="title">{title}</span>
            <a className="more text-muted" href={this.buildSearchUrl(type)}>
              {t('search.suggest.more')}
              <Icon name="chevronRight" />
            </a>
          </h6>
          <ListView pages={pages} />
        </div>
      )
    )
  }
 
  renderBody() {
    const { t, searching, searchError, searchedPages, searchingKeyword } = this.props
    const numberOfResults = this.getNumberOfResults()
    const { portalPages, publicPages, userPages } = searchedPages
    if (searchingKeyword === '') {
      return <RecentlyViewedPageList crowi={this.props.crowi} />
    }
 
    if (searching) {
      return (
        <div>
          <Icon name="loading" spin /> Searching ...
        </div>
      )
    }
 
    if (searchError !== null) {
      return (
        <div>
          <Icon name="alert" /> Error on searching.
        </div>
      )
    }
 
    if (numberOfResults === 0) {
      return <div>No results for &quot;{searchingKeyword}&quot;.</div>
    }
 
    return [
      this.renderList(t('page_types.portal'), 'fileDocumentBoxMultipleOutline', 'portal', portalPages),
      this.renderList(t('page_types.public'), 'fileDocumentBoxOutline', 'public', publicPages),
      this.renderList(t('page_types.user'), 'account', 'user', userPages),
    ]
  }
 
  render() {
    const { focused } = this.props
 
    if (!focused) {
      return <div />
    }
 
    return (
      <Card body className="search-suggest" id="search-suggest">
        {this.renderBody()}
      </Card>
    )
  }
}
 
export default withTranslation()(SearchSuggest)