mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-15 16:04:01 +00:00
[search] keep & display items visited recently(for both global search & search in a single library) (#5826)
This commit is contained in:
parent
2927c2ce02
commit
ce2df5f223
@ -197,9 +197,36 @@ export default class AISearch extends Component {
|
|||||||
|
|
||||||
onItemClickHandler = (item) => {
|
onItemClickHandler = (item) => {
|
||||||
this.resetToDefault();
|
this.resetToDefault();
|
||||||
|
this.keepVisitedItem(item);
|
||||||
this.props.onSearchedClick(item);
|
this.props.onSearchedClick(item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
keepVisitedItem = (targetItem) => {
|
||||||
|
const { repoID } = this.props;
|
||||||
|
let targetIndex;
|
||||||
|
let storeKey = 'sfVisitedAISearchItems';
|
||||||
|
if (repoID) {
|
||||||
|
storeKey += repoID;
|
||||||
|
}
|
||||||
|
const items = JSON.parse(localStorage.getItem(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(storeKey, JSON.stringify(items));
|
||||||
|
};
|
||||||
|
|
||||||
onChangeHandler = (event) => {
|
onChangeHandler = (event) => {
|
||||||
const newValue = event.target.value;
|
const newValue = event.target.value;
|
||||||
this.setState({ value: newValue }, () => {
|
this.setState({ value: newValue }, () => {
|
||||||
@ -342,11 +369,54 @@ export default class AISearch extends Component {
|
|||||||
this.setState({ searchMode: SEARCH_MODE.COMBINED });
|
this.setState({ searchMode: SEARCH_MODE.COMBINED });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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">{results}</div>
|
||||||
|
</MediaQuery>
|
||||||
|
<MediaQuery query="(max-width: 767.8px)">
|
||||||
|
{results}
|
||||||
|
</MediaQuery>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderSearchResult() {
|
renderSearchResult() {
|
||||||
const { resultItems, highlightIndex, width, searchMode, answeringResult } = this.state;
|
const { resultItems, highlightIndex, width, searchMode, answeringResult } = this.state;
|
||||||
if (!width || width === 'default') return null;
|
if (!width || width === 'default') return null;
|
||||||
|
|
||||||
if (!this.state.isResultShow) return null;
|
if (!this.state.isResultShow) {
|
||||||
|
const { repoID } = this.props;
|
||||||
|
let storeKey = 'sfVisitedAISearchItems';
|
||||||
|
if (repoID) {
|
||||||
|
storeKey += repoID;
|
||||||
|
}
|
||||||
|
const visitedItems = JSON.parse(localStorage.getItem(storeKey)) || [];
|
||||||
|
return visitedItems.length ? this.renderVisitedItems(visitedItems) : null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted || getValueLength(this.inputValue) < 3) {
|
if (!this.state.isResultGetted || getValueLength(this.inputValue) < 3) {
|
||||||
return (
|
return (
|
||||||
<span className="loading-icon loading-tip"></span>
|
<span className="loading-icon loading-tip"></span>
|
||||||
|
@ -163,9 +163,36 @@ class Search extends Component {
|
|||||||
|
|
||||||
onItemClickHandler = (item) => {
|
onItemClickHandler = (item) => {
|
||||||
this.resetToDefault();
|
this.resetToDefault();
|
||||||
|
this.keepVisitedItem(item);
|
||||||
this.props.onSearchedClick(item);
|
this.props.onSearchedClick(item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
keepVisitedItem = (targetItem) => {
|
||||||
|
const { repoID } = this.props;
|
||||||
|
let targetIndex;
|
||||||
|
let storeKey = 'sfVisitedSearchItems';
|
||||||
|
if (repoID) {
|
||||||
|
storeKey += repoID;
|
||||||
|
}
|
||||||
|
const items = JSON.parse(localStorage.getItem(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(storeKey, JSON.stringify(items));
|
||||||
|
};
|
||||||
|
|
||||||
onChangeHandler = (event) => {
|
onChangeHandler = (event) => {
|
||||||
const newValue = event.target.value;
|
const newValue = event.target.value;
|
||||||
this.setState({ value: newValue }, () => {
|
this.setState({ value: newValue }, () => {
|
||||||
@ -341,7 +368,16 @@ class Search extends Component {
|
|||||||
const { resultItems, highlightIndex, width } = this.state;
|
const { resultItems, highlightIndex, width } = this.state;
|
||||||
if (!width || width === 'default') return null;
|
if (!width || width === 'default') return null;
|
||||||
|
|
||||||
if (!this.state.isResultShow) return null;
|
if (!this.state.isResultShow) {
|
||||||
|
const { repoID } = this.props;
|
||||||
|
let storeKey = 'sfVisitedSearchItems';
|
||||||
|
if (repoID) {
|
||||||
|
storeKey += repoID;
|
||||||
|
}
|
||||||
|
const visitedItems = JSON.parse(localStorage.getItem(storeKey)) || [];
|
||||||
|
return visitedItems.length ? this.renderResults(visitedItems, true) : null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted || getValueLength(this.inputValue) < 3) {
|
if (!this.state.isResultGetted || getValueLength(this.inputValue) < 3) {
|
||||||
return (
|
return (
|
||||||
<span className="loading-icon loading-tip"></span>
|
<span className="loading-icon loading-tip"></span>
|
||||||
@ -353,7 +389,14 @@ class Search extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.renderResults(resultItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderResults = (resultItems, isVisited) => {
|
||||||
|
const { highlightIndex } = this.state;
|
||||||
const results = (
|
const results = (
|
||||||
|
<>
|
||||||
|
{isVisited && <h4 className="visited-search-results-title">{gettext('Search results visited recently')}</h4>}
|
||||||
<ul className="search-result-list" ref={this.searchResultListRef}>
|
<ul className="search-result-list" ref={this.searchResultListRef}>
|
||||||
{resultItems.map((item, index) => {
|
{resultItems.map((item, index) => {
|
||||||
const isHighlight = index === highlightIndex;
|
const isHighlight = index === highlightIndex;
|
||||||
@ -368,6 +411,7 @@ class Search extends Component {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -346,3 +346,10 @@
|
|||||||
.search-result-container .search-mode-similarity-index-status.index-status-uncreated {
|
.search-result-container .search-mode-similarity-index-status.index-status-uncreated {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visited-search-results-title {
|
||||||
|
color: #999;
|
||||||
|
font-size: .875rem;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 7px 0 10px;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user