2019-02-13 10:09:01 +00:00
|
|
|
import React, { Component, Fragment } from 'react';
|
2018-10-16 10:19:51 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2023-10-08 09:20:38 +00:00
|
|
|
import isHotkey from 'is-hotkey';
|
2019-02-13 10:09:01 +00:00
|
|
|
import MediaQuery from 'react-responsive';
|
2019-07-08 08:47:04 +00:00
|
|
|
import { seafileAPI } from '../../utils/seafile-api';
|
2019-07-10 03:46:02 +00:00
|
|
|
import { gettext, siteRoot, username } from '../../utils/constants';
|
2018-09-04 09:16:50 +00:00
|
|
|
import SearchResultItem from './search-result-item';
|
2020-04-01 03:35:40 +00:00
|
|
|
import { Utils } from '../../utils/utils';
|
2023-10-09 09:32:13 +00:00
|
|
|
import { isMac } from '../../utils/extra-attributes';
|
2020-04-01 03:35:40 +00:00
|
|
|
import toaster from '../toast';
|
2018-08-06 10:29:12 +00:00
|
|
|
|
2018-10-16 10:19:51 +00:00
|
|
|
const propTypes = {
|
2018-12-07 02:36:59 +00:00
|
|
|
repoID: PropTypes.string,
|
2018-12-13 12:42:51 +00:00
|
|
|
placeholder: PropTypes.string,
|
2018-10-16 10:19:51 +00:00
|
|
|
onSearchedClick: PropTypes.func.isRequired,
|
2023-09-13 00:40:50 +00:00
|
|
|
isPublic: PropTypes.bool,
|
2018-10-16 10:19:51 +00:00
|
|
|
};
|
|
|
|
|
2023-10-08 09:20:38 +00:00
|
|
|
const PER_PAGE = 10;
|
2023-10-09 09:32:13 +00:00
|
|
|
const controlKey = isMac() ? '⌘' : 'Ctrl';
|
2023-10-08 09:20:38 +00:00
|
|
|
|
2018-08-06 10:29:12 +00:00
|
|
|
class Search extends Component {
|
2018-08-17 04:23:55 +00:00
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2021-12-17 03:16:33 +00:00
|
|
|
this.baseSearchPageURL = `${siteRoot}search/`;
|
2018-08-17 04:23:55 +00:00
|
|
|
this.state = {
|
|
|
|
width: 'default',
|
|
|
|
value: '',
|
|
|
|
resultItems: [],
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2023-10-08 09:20:38 +00:00
|
|
|
page: 0,
|
|
|
|
isLoading: false,
|
|
|
|
hasMore: true,
|
2018-08-17 04:23:55 +00:00
|
|
|
isMaskShow: false,
|
|
|
|
isResultShow: false,
|
|
|
|
isResultGetted: false,
|
2019-02-13 10:09:01 +00:00
|
|
|
isCloseShow: false,
|
|
|
|
isSearchInputShow: false, // for mobile
|
2021-12-17 03:16:33 +00:00
|
|
|
searchPageUrl: this.baseSearchPageURL
|
2018-08-17 04:23:55 +00:00
|
|
|
};
|
|
|
|
this.inputValue = '';
|
2018-12-20 07:37:14 +00:00
|
|
|
this.source = null; // used to cancel request;
|
2023-10-08 09:20:38 +00:00
|
|
|
this.inputRef = React.createRef();
|
|
|
|
this.searchResultListRef = React.createRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
document.addEventListener('keydown', this.onDocumentKeydown);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
document.removeEventListener('keydown', this.onDocumentKeydown);
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-08 09:20:38 +00:00
|
|
|
onDocumentKeydown = (e) => {
|
|
|
|
if (isHotkey('mod+f')(e)) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.onFocusHandler();
|
|
|
|
if (this.inputRef && this.inputRef.current) {
|
|
|
|
this.inputRef.current.focus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (isHotkey('esc', e)) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.resetToDefault();
|
|
|
|
}
|
2023-10-11 07:58:06 +00:00
|
|
|
else if (isHotkey('enter', e)) {
|
|
|
|
e.preventDefault();
|
|
|
|
let item = this.state.resultItems[this.state.highlightIndex];
|
|
|
|
if (item) {
|
|
|
|
if (document.activeElement) {
|
|
|
|
document.activeElement.blur();
|
|
|
|
}
|
|
|
|
this.onItemClickHandler(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (isHotkey('up', e)) {
|
|
|
|
this.setState({
|
|
|
|
highlightIndex: Math.max(this.state.highlightIndex - 1, 0),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else if (isHotkey('down', e)) {
|
|
|
|
this.setState({
|
|
|
|
highlightIndex: Math.min(this.state.highlightIndex + 1, this.state.resultItems.length - 1),
|
|
|
|
});
|
|
|
|
}
|
2023-10-08 09:20:38 +00:00
|
|
|
};
|
|
|
|
|
2018-08-17 04:23:55 +00:00
|
|
|
onFocusHandler = () => {
|
|
|
|
this.setState({
|
2023-10-08 09:20:38 +00:00
|
|
|
width: '570px',
|
2018-08-17 04:23:55 +00:00
|
|
|
isMaskShow: true,
|
|
|
|
isCloseShow: true
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
|
|
|
onCloseHandler = () => {
|
|
|
|
this.resetToDefault();
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
2018-09-18 02:11:37 +00:00
|
|
|
onItemClickHandler = (item) => {
|
2018-08-17 04:23:55 +00:00
|
|
|
this.resetToDefault();
|
2018-09-18 02:11:37 +00:00
|
|
|
this.props.onSearchedClick(item);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
|
|
|
onChangeHandler = (event) => {
|
|
|
|
let _this = this;
|
|
|
|
this.setState({value: event.target.value});
|
|
|
|
let newValue = event.target.value;
|
|
|
|
if (this.inputValue === newValue.trim()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this.inputValue = newValue.trim();
|
|
|
|
|
|
|
|
if (this.inputValue === '' || _this.getValueLength(this.inputValue) < 3) {
|
|
|
|
this.setState({
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2023-10-08 09:20:38 +00:00
|
|
|
resultItems: [],
|
2018-08-17 04:23:55 +00:00
|
|
|
isResultShow: false,
|
|
|
|
isResultGetted: false
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-08-17 04:23:55 +00:00
|
|
|
return false;
|
|
|
|
}
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-08-17 04:23:55 +00:00
|
|
|
let queryData = {
|
|
|
|
q: newValue,
|
2018-09-18 02:11:37 +00:00
|
|
|
search_repo: repoID ? repoID : 'all',
|
2018-12-13 12:42:51 +00:00
|
|
|
search_ftypes: 'all',
|
2018-09-29 10:32:53 +00:00
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
|
|
|
if (this.timer) {
|
|
|
|
clearTimeout(this.timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.timer = setTimeout(_this.getSearchResult(queryData), 500);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
|
|
|
getSearchResult(queryData) {
|
2023-10-08 09:20:38 +00:00
|
|
|
if (this.source) {
|
|
|
|
this.source.cancel('prev request is cancelled');
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
this.setState({
|
|
|
|
isResultShow: true,
|
2023-10-08 09:20:38 +00:00
|
|
|
isResultGetted: false,
|
|
|
|
resultItems: [],
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2019-12-31 08:58:45 +00:00
|
|
|
this.source = seafileAPI.getSource();
|
2023-10-08 09:20:38 +00:00
|
|
|
this.sendRequest(queryData, this.source.token, 1);
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-08 09:20:38 +00:00
|
|
|
sendRequest = (queryData, cancelToken, page) => {
|
2019-07-08 08:47:04 +00:00
|
|
|
let isPublic = this.props.isPublic;
|
2023-10-08 09:20:38 +00:00
|
|
|
this.queryData = queryData;
|
2019-07-08 08:47:04 +00:00
|
|
|
|
|
|
|
if (isPublic) {
|
2023-10-08 09:20:38 +00:00
|
|
|
seafileAPI.searchFilesInPublishedRepo(queryData.search_repo, queryData.q, page, PER_PAGE).then(res => {
|
|
|
|
this.source = null;
|
|
|
|
if (res.data.total > 0) {
|
|
|
|
this.setState({
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2023-10-08 09:20:38 +00:00
|
|
|
resultItems: [...this.state.resultItems, this.formatResultItems(res.data.results)],
|
|
|
|
isResultGetted: true,
|
|
|
|
page: page + 1,
|
|
|
|
isLoading: false,
|
|
|
|
hasMore: res.data.has_more,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setState({
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2019-07-08 08:47:04 +00:00
|
|
|
resultItems: [],
|
2023-10-08 09:20:38 +00:00
|
|
|
isLoading: false,
|
|
|
|
isResultGetted: true,
|
|
|
|
hasMore: res.data.has_more,
|
2019-07-08 08:47:04 +00:00
|
|
|
});
|
|
|
|
}
|
2019-07-16 02:01:09 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2023-10-08 09:20:38 +00:00
|
|
|
this.setState({ isLoading: false });
|
2019-12-31 08:58:45 +00:00
|
|
|
});
|
2019-07-08 08:47:04 +00:00
|
|
|
} else {
|
2021-12-17 03:16:33 +00:00
|
|
|
this.updateSearchPageURL(queryData);
|
2023-10-08 09:20:38 +00:00
|
|
|
queryData['per_page'] = PER_PAGE;
|
|
|
|
queryData['page'] = page;
|
|
|
|
seafileAPI.searchFiles(queryData, cancelToken).then(res => {
|
|
|
|
this.source = null;
|
|
|
|
if (res.data.total > 0) {
|
|
|
|
this.setState({
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2023-10-08 09:20:38 +00:00
|
|
|
resultItems: [...this.state.resultItems, ...this.formatResultItems(res.data.results)],
|
|
|
|
isResultGetted: true,
|
|
|
|
isLoading: false,
|
|
|
|
page: page + 1,
|
|
|
|
hasMore: res.data.has_more,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setState({
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2019-07-08 08:47:04 +00:00
|
|
|
resultItems: [],
|
2023-10-08 09:20:38 +00:00
|
|
|
isLoading: false,
|
|
|
|
isResultGetted: true,
|
|
|
|
hasMore: res.data.has_more,
|
2019-07-08 08:47:04 +00:00
|
|
|
});
|
|
|
|
}
|
2023-10-08 09:20:38 +00:00
|
|
|
}).catch(error => {
|
2019-07-08 08:47:04 +00:00
|
|
|
/* eslint-disable */
|
2023-10-08 09:20:38 +00:00
|
|
|
console.log(error);
|
2019-07-08 08:47:04 +00:00
|
|
|
/* eslint-enable */
|
2023-10-08 09:20:38 +00:00
|
|
|
this.setState({ isLoading: false });
|
2019-07-08 08:47:04 +00:00
|
|
|
});
|
|
|
|
}
|
2023-10-08 09:20:38 +00:00
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
2023-10-08 09:20:38 +00:00
|
|
|
onResultListScroll = (e) => {
|
|
|
|
// Load less than 100 results
|
|
|
|
if (!this.state.hasMore || this.state.isLoading || this.state.resultItems.length > 100) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const listPadding = 20;
|
|
|
|
if (e.target.scrollTop + e.target.clientHeight + listPadding > this.searchResultListRef.current.clientHeight - 10) {
|
|
|
|
this.setState({isLoading: true}, () => {
|
|
|
|
this.source = seafileAPI.getSource();
|
|
|
|
this.sendRequest(this.queryData, this.source.token, this.state.page);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2018-08-17 04:23:55 +00:00
|
|
|
|
2021-12-17 03:16:33 +00:00
|
|
|
updateSearchPageURL(queryData) {
|
|
|
|
let params = '';
|
|
|
|
for (let key in queryData) {
|
|
|
|
params += key + '=' + encodeURIComponent(queryData[key]) + '&';
|
|
|
|
}
|
|
|
|
this.setState({searchPageUrl: `${this.baseSearchPageURL}?${params.substring(0, params.length - 1)}`});
|
|
|
|
}
|
|
|
|
|
2018-08-17 04:23:55 +00:00
|
|
|
getValueLength(str) {
|
|
|
|
var i = 0, code, len = 0;
|
|
|
|
for (; i < str.length; i++) {
|
|
|
|
code = str.charCodeAt(i);
|
|
|
|
if (code == 10) { //solve enter problem
|
|
|
|
len += 2;
|
|
|
|
} else if (code < 0x007f) {
|
|
|
|
len += 1;
|
|
|
|
} else if (code >= 0x0080 && code <= 0x07ff) {
|
|
|
|
len += 2;
|
|
|
|
} else if (code >= 0x0800 && code <= 0xffff) {
|
|
|
|
len += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
formatResultItems(data) {
|
|
|
|
let items = [];
|
2023-10-08 09:20:38 +00:00
|
|
|
for (let i = 0; i < data.length; i++) {
|
2018-08-17 04:23:55 +00:00
|
|
|
items[i] = {};
|
|
|
|
items[i]['index'] = [i];
|
|
|
|
items[i]['name'] = data[i].name;
|
2018-09-18 02:11:37 +00:00
|
|
|
items[i]['path'] = data[i].fullpath;
|
|
|
|
items[i]['repo_id'] = data[i].repo_id;
|
2018-12-13 12:42:51 +00:00
|
|
|
items[i]['repo_name'] = data[i].repo_name;
|
|
|
|
items[i]['is_dir'] = data[i].is_dir;
|
2018-08-17 04:23:55 +00:00
|
|
|
items[i]['link_content'] = decodeURI(data[i].fullpath).substring(1);
|
|
|
|
items[i]['content'] = data[i].content_highlight;
|
2021-01-21 03:51:16 +00:00
|
|
|
items[i]['thumbnail_url'] = data[i].thumbnail_url;
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
|
|
|
|
resetToDefault() {
|
|
|
|
this.inputValue = null;
|
|
|
|
this.setState({
|
|
|
|
width: '',
|
|
|
|
value: '',
|
|
|
|
isMaskShow: false,
|
|
|
|
isCloseShow: false,
|
|
|
|
isResultShow: false,
|
|
|
|
isResultGetted: false,
|
2019-02-13 10:09:01 +00:00
|
|
|
resultItems: [],
|
2023-10-11 07:58:06 +00:00
|
|
|
highlightIndex: 0,
|
2019-02-13 10:09:01 +00:00
|
|
|
isSearchInputShow: false,
|
2018-09-29 10:32:53 +00:00
|
|
|
});
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
renderSearchResult() {
|
2023-10-11 07:58:06 +00:00
|
|
|
const { resultItems, highlightIndex } = this.state;
|
2018-08-17 04:23:55 +00:00
|
|
|
if (!this.state.isResultShow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!this.state.isResultGetted || this.getValueLength(this.inputValue) < 3) {
|
|
|
|
return (
|
|
|
|
<span className="loading-icon loading-tip"></span>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
2023-10-08 09:20:38 +00:00
|
|
|
if (!resultItems.length) {
|
2018-08-17 04:23:55 +00:00
|
|
|
return (
|
2019-03-09 04:06:11 +00:00
|
|
|
<div className="search-result-none">{gettext('No results matching.')}</div>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
return (
|
2023-10-08 09:20:38 +00:00
|
|
|
<ul className="search-result-list" ref={this.searchResultListRef}>
|
|
|
|
{resultItems.map((item, index) => {
|
2018-08-17 04:23:55 +00:00
|
|
|
return (
|
|
|
|
<SearchResultItem
|
2019-12-31 08:58:45 +00:00
|
|
|
key={index}
|
2018-08-17 04:23:55 +00:00
|
|
|
item={item}
|
2023-10-08 09:20:38 +00:00
|
|
|
onItemClickHandler={this.onItemClickHandler}
|
2023-10-11 07:58:06 +00:00
|
|
|
isHighlight={index === highlightIndex}
|
2018-08-17 04:23:55 +00:00
|
|
|
/>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-17 04:23:55 +00:00
|
|
|
})}
|
|
|
|
</ul>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-17 04:23:55 +00:00
|
|
|
}
|
|
|
|
|
2019-02-13 10:09:01 +00:00
|
|
|
onSearchToggle = () => {
|
|
|
|
this.setState({
|
|
|
|
isSearchInputShow: !this.state.isSearchInputShow,
|
|
|
|
isMaskShow: !this.state.isMaskShow,
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-02-13 10:09:01 +00:00
|
|
|
|
2018-08-06 10:29:12 +00:00
|
|
|
render() {
|
2018-08-17 04:23:55 +00:00
|
|
|
let width = this.state.width !== 'default' ? this.state.width : '';
|
|
|
|
let style = {'width': width};
|
2023-10-09 09:32:13 +00:00
|
|
|
const { searchPageUrl, isMaskShow } = this.state;
|
|
|
|
const placeholder = `${this.props.placeholder}${isMaskShow ? '' : ` (${controlKey} + f )`}`;
|
2018-08-06 10:29:12 +00:00
|
|
|
return (
|
2019-02-13 10:09:01 +00:00
|
|
|
<Fragment>
|
|
|
|
<MediaQuery query="(min-width: 768px)">
|
|
|
|
<div className="search">
|
2023-10-09 09:32:13 +00:00
|
|
|
<div className={`search-mask ${isMaskShow ? 'show' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
|
|
|
<div className={`search-container ${isMaskShow ? 'show' : ''}`}>
|
|
|
|
<div className={`input-icon ${isMaskShow ? 'mb-1' : ''}`}>
|
2019-02-13 10:09:01 +00:00
|
|
|
<i className="search-icon-left input-icon-addon fas fa-search"></i>
|
2020-11-02 05:56:35 +00:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
className="form-control search-input"
|
2019-02-13 10:09:01 +00:00
|
|
|
name="query"
|
2023-10-09 09:32:13 +00:00
|
|
|
placeholder={placeholder}
|
2019-02-13 10:09:01 +00:00
|
|
|
style={style}
|
|
|
|
value={this.state.value}
|
|
|
|
onFocus={this.onFocusHandler}
|
|
|
|
onChange={this.onChangeHandler}
|
|
|
|
autoComplete="off"
|
2023-10-08 09:20:38 +00:00
|
|
|
ref={this.inputRef}
|
2019-02-13 10:09:01 +00:00
|
|
|
/>
|
2019-07-10 03:46:02 +00:00
|
|
|
{(this.state.isCloseShow && username) &&
|
2021-12-17 03:16:33 +00:00
|
|
|
<a href={searchPageUrl} className="search-icon-right input-icon-addon fas fa-external-link-alt search-icon-arrow"></a>
|
2021-09-17 07:13:22 +00:00
|
|
|
}
|
|
|
|
{this.state.isCloseShow &&
|
2023-10-08 09:20:38 +00:00
|
|
|
<button type="button" className="search-icon-right input-icon-addon fas fa-times border-0 bg-transparent mr-4" onClick={this.onCloseHandler} aria-label={gettext('Close')}></button>
|
2019-04-24 03:10:59 +00:00
|
|
|
}
|
2019-02-13 10:09:01 +00:00
|
|
|
</div>
|
2023-10-08 09:20:38 +00:00
|
|
|
<div className="search-result-container dropdown-search-result-container" onScroll={this.onResultListScroll}>
|
2019-02-13 10:09:01 +00:00
|
|
|
{this.renderSearchResult()}
|
|
|
|
</div>
|
|
|
|
</div>
|
2018-08-17 04:23:55 +00:00
|
|
|
</div>
|
2019-02-13 10:09:01 +00:00
|
|
|
</MediaQuery>
|
2019-07-10 13:51:30 +00:00
|
|
|
<MediaQuery query="(max-width: 767.8px)">
|
2019-02-13 10:09:01 +00:00
|
|
|
<div className="search-icon-container">
|
|
|
|
<i className="search-icon fas fa-search" onClick={this.onSearchToggle}></i>
|
2018-08-17 04:23:55 +00:00
|
|
|
</div>
|
2020-11-02 05:56:35 +00:00
|
|
|
{this.state.isSearchInputShow &&
|
2019-02-13 10:09:01 +00:00
|
|
|
<div className="search">
|
2023-10-09 09:32:13 +00:00
|
|
|
<div className={`search-mask ${isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
2019-02-13 10:09:01 +00:00
|
|
|
<div className="search-container">
|
|
|
|
<div className="input-icon">
|
|
|
|
<i className="search-icon-left input-icon-addon fas fa-search"></i>
|
2020-11-02 05:56:35 +00:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
className="form-control search-input"
|
2019-02-13 10:09:01 +00:00
|
|
|
name="query"
|
2023-10-09 09:32:13 +00:00
|
|
|
placeholder={placeholder}
|
2019-02-13 10:09:01 +00:00
|
|
|
style={style}
|
|
|
|
value={this.state.value}
|
|
|
|
onFocus={this.onFocusHandler}
|
|
|
|
onChange={this.onChangeHandler}
|
|
|
|
autoComplete="off"
|
|
|
|
/>
|
2019-07-10 03:46:02 +00:00
|
|
|
{(this.state.isCloseShow && username) &&
|
2021-12-17 03:16:33 +00:00
|
|
|
<a href={searchPageUrl} className="search-icon-right input-icon-addon fas fa-external-link-alt search-icon-arrow"></a>
|
2021-09-17 07:13:22 +00:00
|
|
|
}
|
|
|
|
{this.state.isCloseShow &&
|
|
|
|
<button type="button" className="search-icon-right input-icon-addon fas fa-times border-0 bg-transparent" onClick={this.onCloseHandler} aria-label={gettext('Close')}></button>
|
2019-04-24 03:10:59 +00:00
|
|
|
}
|
2019-02-13 10:09:01 +00:00
|
|
|
</div>
|
2023-10-08 09:20:38 +00:00
|
|
|
<div className="search-result-container dropdown-search-result-container" onScroll={this.onResultListScroll}>
|
2019-02-13 10:09:01 +00:00
|
|
|
{this.renderSearchResult()}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</MediaQuery>
|
|
|
|
</Fragment>
|
2018-09-29 10:32:53 +00:00
|
|
|
);
|
2018-08-06 10:29:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-16 10:19:51 +00:00
|
|
|
Search.propTypes = propTypes;
|
|
|
|
|
2018-08-06 10:29:12 +00:00
|
|
|
export default Search;
|