1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-06 17:33:18 +00:00

merge seasearch and es (#6632)

* merge seasearch and es

* rebase

* update
This commit is contained in:
JoinTyang
2024-08-24 23:08:18 +08:00
committed by GitHub
parent b0e62adc64
commit 56999ee4c5
17 changed files with 281 additions and 1241 deletions

View File

@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Input } from 'reactstrap';
import { seafileAPI } from '../../utils/seafile-api';
import { gettext, isPro, enableSeasearch, enableElasticsearch } from '../../utils/constants';
import { gettext, isPro } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import toaster from '../toast';
import RepoInfo from '../../models/repo-info';
@@ -257,16 +257,7 @@ class FileChooser extends React.Component {
return results;
};
if (isPro && enableSeasearch && !enableElasticsearch) {
seafileAPI.aiSearchFiles(queryData, cancelToken).then(res => {
const filteredResults = filterCurrentRepo(res.data.results.filter(item => item.is_dir));
this.setState({
searchResults: filteredResults.length > 0 ? this.formatResultItems(filteredResults) : [],
isResultGot: true
});
this.source = null;
});
} else {
if (isPro) {
seafileAPI.searchFiles(queryData, cancelToken).then(res => {
const filteredResults = filterCurrentRepo(res.data.results);
this.setState({

View File

@@ -1,821 +0,0 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import isHotkey from 'is-hotkey';
import classnames from 'classnames';
import MediaQuery from 'react-responsive';
import { seafileAPI } from '../../utils/seafile-api';
import searchAPI from '../../utils/search-api';
import Icon from '../icon';
import { gettext, siteRoot, username } from '../../utils/constants';
import SearchResultItem from './search-result-item';
import SearchResultLibrary from './search-result-library';
import { Utils } from '../../utils/utils';
import Loading from '../loading';
const INDEX_STATE = {
RUNNING: 'running',
UNCREATED: 'uncreated',
FINISHED: 'finished'
};
const PER_PAGE = 10;
const controlKey = Utils.isMac() ? '⌘' : 'Ctrl';
export default class AISearch extends Component {
static propTypes = {
repoID: PropTypes.string,
path: PropTypes.string,
placeholder: PropTypes.string,
onSearchedClick: PropTypes.func.isRequired,
currentRepoInfo: PropTypes.object,
isViewFile: PropTypes.bool,
isLibView: PropTypes.bool,
};
constructor(props) {
super(props);
this.baseSearchPageURL = `${siteRoot}search/`;
this.state = {
width: 'default',
value: '',
inputValue: '',
resultItems: [],
highlightIndex: 0,
page: 0,
isLoading: false,
hasMore: true,
isMaskShow: false,
showRecent: true,
isResultGetted: false,
isCloseShow: false,
isSearchInputShow: false, // for mobile
searchPageUrl: this.baseSearchPageURL,
indexState: '',
searchTypesMax: 0,
highlightSearchTypesIndex: 0,
};
this.highlightRef = null;
this.source = null; // used to cancel request;
this.inputRef = React.createRef();
this.searchContainer = React.createRef();
this.searchResultListRef = React.createRef();
this.searchResultListContainerRef = React.createRef();
this.indexStateTimer = null;
this.isChineseInput = false;
this.calculateStoreKey(props);
}
componentDidMount() {
document.addEventListener('keydown', this.onDocumentKeydown);
document.addEventListener('compositionstart', this.onCompositionStart);
document.addEventListener('compositionend', this.onCompositionEnd);
document.addEventListener('click', this.handleOutsideClick);
}
calculateStoreKey = (props) => {
if (props.isLibView && props.currentRepoInfo) {
this.isRepoOwner = props.currentRepoInfo.owner_email === username;
this.isAdmin = props.currentRepoInfo.is_admin;
} else {
this.isRepoOwner = false;
this.isAdmin = false;
}
let storeKey = 'sfVisitedAISearchItems';
if (props.repoID) {
storeKey += props.repoID;
}
this.storeKey = storeKey;
};
componentWillUnmount() {
document.removeEventListener('keydown', this.onDocumentKeydown);
document.removeEventListener('compositionstart', this.onCompositionStart);
document.removeEventListener('compositionend', this.onCompositionEnd);
document.removeEventListener('click', this.handleOutsideClick);
this.isChineseInput = false;
if (this.indexStateTimer) {
clearInterval(this.indexStateTimer);
this.indexStateTimer = null;
}
}
onCompositionStart = () => {
this.isChineseInput = true;
};
onCompositionEnd = () => {
this.isChineseInput = false;
};
onDocumentKeydown = (e) => {
if (isHotkey('mod+k')(e)) {
e.preventDefault();
this.onFocusHandler();
if (this.inputRef && this.inputRef.current) {
this.inputRef.current.focus();
}
}
if (this.state.isMaskShow) {
if (isHotkey('esc', e)) {
e.preventDefault();
this.inputRef && this.inputRef.current && this.inputRef.current.blur();
this.resetToDefault();
} else if (isHotkey('enter', e)) {
this.onEnter(e);
} else if (isHotkey('up', e)) {
this.onUp(e);
} else if (isHotkey('down', e)) {
this.onDown(e);
}
}
};
onFocusHandler = () => {
this.setState({ width: '570px', isMaskShow: true, isCloseShow: true });
this.calculateHighlightType();
};
onCloseHandler = () => {
this.resetToDefault();
};
onUp = (e) => {
e.preventDefault();
e.stopPropagation();
const { highlightIndex, resultItems } = this.state;
if (this.state.showRecent) {
if (highlightIndex > 0) {
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
if (this.highlightRef) {
const { top, height } = this.highlightRef.getBoundingClientRect();
if (top - height < 0) {
this.searchResultListContainerRef.current.scrollTop -= height;
}
}
});
}
return;
}
// global searching, searched repos needs to support up and down keys
if (!this.props.repoID && resultItems.length > 0) {
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
if (highlightSearchTypesIndex < 0) {
highlightSearchTypesIndex = resultItems.length;
}
this.setState({ highlightSearchTypesIndex }, () => {
if (this.highlightRef) {
const { top, height } = this.highlightRef.getBoundingClientRect();
if (top - height < 0) {
this.searchResultListContainerRef.current.scrollTop -= height;
}
}
});
return;
}
if (!this.state.isResultGetted) {
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
if (highlightSearchTypesIndex < 0) {
highlightSearchTypesIndex = this.state.searchTypesMax;
}
this.setState({ highlightSearchTypesIndex });
return;
}
if (highlightIndex > 0) {
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
if (this.highlightRef) {
const { top, height } = this.highlightRef.getBoundingClientRect();
if (top - height < 0) {
this.searchResultListContainerRef.current.scrollTop -= height;
}
}
});
}
};
onDown = (e) => {
e.preventDefault();
e.stopPropagation();
const { highlightIndex, resultItems } = this.state;
if (this.state.showRecent) {
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
if (highlightIndex < visitedItems.length - 1) {
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
if (this.highlightRef) {
const { top, height } = this.highlightRef.getBoundingClientRect();
const outerHeight = 300;
if (top > outerHeight) {
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
}
}
});
}
return;
}
// global searching, searched repos needs to support up and down keys
if (!this.props.repoID && resultItems.length > 0) {
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
if (highlightSearchTypesIndex > resultItems.length) {
highlightSearchTypesIndex = 0;
}
this.setState({ highlightSearchTypesIndex }, () => {
if (this.highlightRef) {
const { top, height } = this.highlightRef.getBoundingClientRect();
const outerHeight = 300;
if (top > outerHeight) {
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
}
}
});
return;
}
if (!this.state.isResultGetted) {
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
if (highlightSearchTypesIndex > this.state.searchTypesMax) {
highlightSearchTypesIndex = 0;
}
this.setState({ highlightSearchTypesIndex });
return;
}
if (highlightIndex < resultItems.length - 1) {
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
if (this.highlightRef) {
const { top, height } = this.highlightRef.getBoundingClientRect();
const outerHeight = 300;
if (top > outerHeight) {
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
}
}
});
}
};
onEnter = (e) => {
e.preventDefault();
if (this.state.showRecent) {
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
const item = visitedItems[this.state.highlightIndex];
if (item) {
if (document.activeElement) {
document.activeElement.blur();
}
this.onItemClickHandler(item);
}
return;
}
// global searching, searched repos needs to support enter
const { highlightSearchTypesIndex, resultItems } = this.state;
if (!this.props.repoID && resultItems.length > 0) {
if (highlightSearchTypesIndex === 0) {
this.searchAllRepos();
} else {
let item = this.state.resultItems[highlightSearchTypesIndex - 1];
if (item) {
if (document.activeElement) {
document.activeElement.blur();
}
this.onItemClickHandler(item);
}
}
}
if (!this.state.isResultGetted) {
let highlightDom = document.querySelector('.search-types-highlight');
if (highlightDom) {
if (highlightDom.classList.contains('search-types-folder')) {
this.searchFolder();
}
else if (highlightDom.classList.contains('search-types-repo')) {
this.searchRepo();
}
else if (highlightDom.classList.contains('search-types-repos')) {
this.searchAllRepos();
}
return;
}
}
let item = this.state.resultItems[this.state.highlightIndex];
if (item) {
if (document.activeElement) {
document.activeElement.blur();
}
this.onItemClickHandler(item);
}
};
onItemClickHandler = (item) => {
this.resetToDefault();
this.keepVisitedItem(item);
this.props.onSearchedClick(item);
};
calculateHighlightType = () => {
let searchTypesMax = 0;
const { repoID, path, isViewFile } = this.props;
if (repoID) {
searchTypesMax++;
}
if (path && path !== '/' && !isViewFile) {
searchTypesMax++;
}
this.setState({
searchTypesMax,
highlightSearchTypesIndex: 0,
});
};
keepVisitedItem = (targetItem) => {
let targetIndex;
const items = JSON.parse(localStorage.getItem(this.storeKey)) || [];
for (let i = 0, len = items.length; i < len; i++) {
const { repo_id, path } = items[i];
const { repo_id: targetRepoID, path: targetPath } = targetItem;
if (repo_id == targetRepoID && path == targetPath) {
targetIndex = i;
break;
}
}
if (targetIndex != undefined) {
items.splice(targetIndex, 1);
}
items.unshift(targetItem);
if (items.length > 50) { // keep 50 items at most
items.pop();
}
localStorage.setItem(this.storeKey, JSON.stringify(items));
};
onChangeHandler = (event) => {
const newValue = event.target.value;
if (this.state.showRecent) {
this.setState({ showRecent: false });
}
this.setState({ value: newValue });
setTimeout(() => {
const trimmedValue = newValue.trim();
const isInRepo = this.props.repoID;
if (this.isChineseInput === false && this.state.inputValue !== newValue) {
this.setState({
inputValue: newValue,
isLoading: false,
highlightIndex: 0,
// resultItems: [],
isResultGetted: false,
}, () => {
if (!isInRepo && trimmedValue !== '') {
this.getRepoSearchResult(newValue);
}
});
}
}, 1);
};
getRepoSearchResult = (query_str) => {
if (this.source) {
this.source.cancel('prev request is cancelled');
}
this.source = seafileAPI.getSource();
const query_type = 'library';
let results = [];
searchAPI.searchItems(query_str, query_type, this.source.token).then(res => {
results = [...results, ...this.formatResultItems(res.data.results)];
this.setState({
resultItems: results,
isLoading: false,
hasMore: false,
});
}).catch(error => {
// eslint-disable-next-line no-console
console.log(error);
this.setState({ isLoading: false });
});
};
getSearchResult = (queryData) => {
if (this.source) {
this.source.cancel('prev request is cancelled');
}
this.setState({
isLoading: true,
isResultGetted: false,
resultItems: [],
highlightIndex: 0,
});
this.source = seafileAPI.getSource();
this.sendRequest(queryData, this.source.token, 1);
};
sendRequest = (queryData, cancelToken, page) => {
this.queryData = queryData;
this.updateSearchPageURL(queryData);
queryData['per_page'] = PER_PAGE;
queryData['page'] = page;
this.onAiSearch(queryData, cancelToken, page);
};
onAiSearch = (queryData, cancelToken, page) => {
let results = [];
seafileAPI.aiSearchFiles(queryData, cancelToken).then(res => {
results = [...results, ...this.formatResultItems(res.data.results)];
this.setState({
resultItems: results,
isResultGetted: true,
isLoading: false,
page: page + 1,
hasMore: false,
});
}).catch(error => {
/* eslint-disable */
console.log(error);
this.setState({ isLoading: false });
});
};
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);
});
}
};
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)}`});
}
formatResultItems(data) {
let items = [];
for (let i = 0; i < data.length; i++) {
items[i] = {};
let name = data[i].is_dir ? data[i].name : data[i].fullpath.split('/').pop();
items[i]['index'] = [i];
items[i]['name'] = name;
items[i]['path'] = data[i].fullpath;
items[i]['repo_id'] = data[i].repo_id;
items[i]['repo_name'] = data[i].repo_name;
items[i]['is_dir'] = data[i].is_dir;
items[i]['content'] = data[i].content;
items[i]['link_content'] = decodeURI(data[i].fullpath).substring(1);
}
return items;
}
resetToDefault() {
this.setState({
width: '',
value: '',
inputValue: '',
isMaskShow: false,
isCloseShow: false,
isResultGetted: false,
resultItems: [],
highlightIndex: 0,
isSearchInputShow: false,
showRecent: true,
});
}
renderVisitedItems = (items) => {
const { highlightIndex } = this.state;
const results = (
<>
<h4 className="visited-search-results-title">{gettext('Search results visited recently')}</h4>
<ul className="search-result-list" ref={this.searchResultListRef}>
{items.map((item, index) => {
const isHighlight = index === highlightIndex;
return (
<SearchResultItem
key={index}
item={item}
onItemClickHandler={this.onItemClickHandler}
isHighlight={isHighlight}
setRef={isHighlight ? (ref) => {this.highlightRef = ref;} : () => {}}
/>
);
})}
</ul>
</>
);
return (
<>
<MediaQuery query="(min-width: 768px)">
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>{results}</div>
</MediaQuery>
<MediaQuery query="(max-width: 767.8px)">
{results}
</MediaQuery>
</>
);
};
renderSearchTypes = (inputValue) => {
const highlightIndex = this.state.highlightSearchTypesIndex;
const { resultItems } = this.state;
if (!this.props.repoID) {
return (
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>
<div className="search-types">
<div
className={classnames('search-types-repos', { 'search-types-highlight': highlightIndex === 0 })}
onClick={this.searchAllRepos}
tabIndex={0}
>
<i className="search-icon-left input-icon-addon sf3-font sf3-font-search"></i>
{inputValue}
<span className="search-types-text">{gettext('in all libraries')}</span>
<i className="sf3-font sf3-font-enter"></i>
</div>
</div>
{resultItems.length > 0 && (
<div className="library-result-container">
<hr className="library-result-divider" />
<div className="library-result-header">{gettext('Libraries')}</div>
<ul
className="library-result-list"
ref={this.searchResultListRef}
>
{resultItems.map((item, index) => {
return (
<SearchResultLibrary
key={index}
item={item}
onClick={this.onItemClickHandler}
isHighlight={highlightIndex === index + 1}
setRef={highlightIndex === index + 1 ? (ref) => {this.highlightRef = ref;} : () => {}}
/>
);
})}
</ul>
</div>
)}
</div>
);
}
if (this.props.repoID) {
if (this.props.path && this.props.path !== '/' && !this.props.isViewFile) {
return (
<div className="search-types">
<div className={`search-types-repo ${highlightIndex === 0 ? 'search-types-highlight' : ''}`} onClick={this.searchRepo} tabIndex={0}>
<i className="search-icon-left input-icon-addon sf3-font sf3-font-search"></i>
{inputValue}
<span className="search-types-text">{gettext('in this library')}</span>
{highlightIndex === 0 && <i className="sf3-font sf3-font-enter"></i>}
</div>
<div className={`search-types-folder ${highlightIndex === 1 ? 'search-types-highlight' : ''}`} onClick={this.searchFolder} tabIndex={0}>
<i className="search-icon-left input-icon-addon sf3-font sf3-font-search"></i>
{inputValue}
<span className="search-types-text">{gettext('in this folder')}</span>
{highlightIndex === 1 && <i className="sf3-font sf3-font-enter"></i>}
</div>
<div className={`search-types-repos ${highlightIndex === 2 ? 'search-types-highlight' : ''}`} onClick={this.searchAllRepos} tabIndex={0}>
<i className="search-icon-left input-icon-addon sf3-font sf3-font-search"></i>
{inputValue}
<span className="search-types-text">{gettext('in all libraries')}</span>
{highlightIndex === 2 && <i className="sf3-font sf3-font-enter"></i>}
</div>
</div>
);
} else {
return (
<div className="search-types">
<div className={`search-types-repo ${highlightIndex === 0 ? 'search-types-highlight' : ''}`} onClick={this.searchRepo} tabIndex={0}>
<i className="search-icon-left input-icon-addon sf3-font sf3-font-search"></i>
{inputValue}
<span className="search-types-text">{gettext('in this library')}</span>
{highlightIndex === 0 && <i className="sf3-font sf3-font-enter"></i>}
</div>
<div className={`search-types-repos ${highlightIndex === 1 ? 'search-types-highlight' : ''}`} onClick={this.searchAllRepos} tabIndex={0}>
<i className="search-icon-left input-icon-addon sf3-font sf3-font-search"></i>
{inputValue}
<span className="search-types-text">{gettext('in all libraries')}</span>
{highlightIndex === 1 && <i className="sf3-font sf3-font-enter"></i>}
</div>
</div>
);
}
}
};
searchRepo = () => {
const { value } = this.state;
const queryData = {
q: value,
search_repo: this.props.repoID,
search_ftypes: 'all',
};
this.getSearchResult(queryData);
};
searchFolder = () => {
const { value } = this.state;
const queryData = {
q: value,
search_repo: this.props.repoID,
search_ftypes: 'all',
search_path: this.props.path,
};
this.getSearchResult(queryData);
};
searchAllRepos = () => {
const { value } = this.state;
const queryData = {
q: value,
search_repo: 'all',
search_ftypes: 'all',
};
this.getSearchResult(queryData);
};
renderSearchResult() {
const { resultItems, highlightIndex, width, isResultGetted, isLoading } = this.state;
if (!width || width === 'default') return null;
if (this.state.showRecent) {
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
if (visitedItems.length) {
return this.renderVisitedItems(visitedItems);
}
}
if (isLoading) {
return <Loading />;
}
else if (this.state.inputValue.trim().length === 0) {
return <div className="search-result-none">{gettext('Type characters to start search')}</div>;
}
else if (!isResultGetted) {
return this.renderSearchTypes(this.state.inputValue.trim());
}
else if (resultItems.length === 0) {
return <div className="search-result-none">{gettext('No results matching')}</div>;
}
const results = (
<ul className="search-result-list" ref={this.searchResultListRef}>
{resultItems.map((item, index) => {
const isHighlight = index === highlightIndex;
return (
<SearchResultItem
key={index}
item={item}
onItemClickHandler={this.onItemClickHandler}
isHighlight={isHighlight}
setRef={isHighlight ? (ref) => {this.highlightRef = ref;} : () => {}}
/>
);
})}
</ul>
);
return (
<>
<MediaQuery query="(min-width: 768px)">
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>{results}</div>
</MediaQuery>
<MediaQuery query="(max-width: 767.8px)">
{results}
</MediaQuery>
</>
);
}
onSearchToggle = () => {
this.setState({
isSearchInputShow: !this.state.isSearchInputShow,
isMaskShow: !this.state.isMaskShow,
});
};
setSettingsContainerRef = (ref) => {
this.settingsContainer = ref;
};
renderSearchIcon = () => {
const { indexState } = this.state;
if (indexState === INDEX_STATE.RUNNING || indexState === INDEX_STATE.FINISHED) {
return <Icon symbol='AI-search' className='input-icon-addon' />;
} else {
return <Icon symbol='search' className='input-icon-addon' />;
}
};
render() {
let width = this.state.width !== 'default' ? this.state.width : '';
let style = {'width': width};
const { isMaskShow } = this.state;
const placeholder = `${this.props.placeholder}${isMaskShow ? '' : ` (${controlKey} + k )`}`;
return (
<Fragment>
<MediaQuery query="(min-width: 768px)">
<div className="search">
<div className={`search-mask ${isMaskShow ? 'show' : 'hide'}`} onClick={this.onCloseHandler}></div>
<div className={`search-container ${isMaskShow ? 'show' : ''}`}>
<div className={`input-icon ${isMaskShow ? 'mb-1' : ''}`}>
{this.renderSearchIcon()}
<input
type="text"
className="form-control search-input"
name="query"
placeholder={placeholder}
style={style}
value={this.state.value}
onFocus={this.onFocusHandler}
onChange={this.onChangeHandler}
autoComplete="off"
ref={this.inputRef}
/>
{this.state.isCloseShow &&
<>
{(this.isRepoOwner || this.isAdmin) &&
<button
type="button"
className="search-icon-right input-icon-addon sf3-font-set-up sf3-font border-0 bg-transparent mr-3"
onClick={this.toggleSettingsShown}
aria-label={gettext('Settings')}
ref={ref => this.settingIcon = ref}
></button>
}
<button
type="button"
className="search-icon-right input-icon-addon sf3-font sf3-font-x-01 border-0 bg-transparent mr-4"
onClick={this.onCloseHandler}
aria-label={gettext('Close')}
></button>
</>
}
</div>
<div
className="search-result-container dropdown-search-result-container"
onScroll={this.onResultListScroll}
ref={this.searchContainer}
>
{this.renderSearchResult()}
</div>
</div>
</div>
</MediaQuery>
<MediaQuery query="(max-width: 767.8px)">
<div className="search-icon-container" onClick={this.onSearchToggle}>
{this.renderSearchIcon()}
</div>
{this.state.isSearchInputShow &&
<div className="search">
<div className={`search-mask ${isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
<div className="search-container">
<div className="input-icon">
{this.renderSearchIcon()}
<input
type="text"
className="form-control search-input"
name="query"
placeholder={placeholder}
style={style}
value={this.state.value}
onFocus={this.onFocusHandler}
onChange={this.onChangeHandler}
autoComplete="off"
/>
{this.state.isCloseShow &&
<button type="button" className="search-icon-right input-icon-addon sf3-font sf3-font-x-01 border-0 bg-transparent" onClick={this.onCloseHandler} aria-label={gettext('Close')}></button>
}
</div>
<div className="search-result-container dropdown-search-result-container" onScroll={this.onResultListScroll}>
{this.renderSearchResult()}
</div>
</div>
</div>
}
</MediaQuery>
</Fragment>
);
}
}

View File

@@ -1,8 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { isPro, gettext, showLogoutIcon, enableSeasearch, enableElasticsearch } from '../../utils/constants';
import { isPro, gettext, showLogoutIcon } from '../../utils/constants';
import Search from '../search/search';
import AISearch from '../search/ai-search';
import SearchByName from '../search/search-by-name';
import Notification from '../common/notification';
import Account from '../common/account';
@@ -60,35 +59,21 @@ class CommonToolbar extends React.Component {
};
renderSearch = () => {
const { repoID, repoName, isLibView, path, isViewFile, currentRepoInfo } = this.state;
const { repoID, repoName, isLibView, path, isViewFile } = this.state;
const { searchPlaceholder } = this.props;
const placeholder = searchPlaceholder || gettext('Search files');
if (isPro) {
if (enableSeasearch && !enableElasticsearch) {
return (
<AISearch
repoID={repoID}
path={path}
isViewFile={isViewFile}
placeholder={placeholder}
currentRepoInfo={currentRepoInfo}
onSearchedClick={this.onSearchedClick}
isLibView={isLibView}
/>
);
} else {
return (
<Search
repoID={repoID}
placeholder={placeholder}
onSearchedClick={this.onSearchedClick}
isViewFile={isViewFile}
isPublic={false}
path={path}
/>
);
}
return (
<Search
repoID={repoID}
placeholder={placeholder}
onSearchedClick={this.onSearchedClick}
isViewFile={isViewFile}
isPublic={false}
path={path}
/>
);
} else {
if (isLibView) {
return (