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 "{searchingKeyword}".</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)
|