aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/search
diff options
context:
space:
mode:
authorMohammad Amoush <mohammad_amoush@brown.edu>2019-07-22 13:57:10 -0400
committerMohammad Amoush <mohammad_amoush@brown.edu>2019-07-22 13:57:10 -0400
commit658ded478c273654174cd2706f8b3e021b8ceb95 (patch)
tree7526f7850dd3702b9746125d2f4349a0d6aea8ee /src/client/views/search
parent157060f7e6029c76765aa20d8fdbe325401a3880 (diff)
parent8db50c6ba0be83b85c896043da53e40c17523e90 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into youtube-api-muhammed
Diffstat (limited to 'src/client/views/search')
-rw-r--r--src/client/views/search/SearchBox.tsx35
-rw-r--r--src/client/views/search/SearchItem.scss12
-rw-r--r--src/client/views/search/SearchItem.tsx14
3 files changed, 39 insertions, 22 deletions
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index d07df7e58..2214ac8af 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -9,12 +9,12 @@ import { Docs } from '../../documents/Documents';
import { NumCast, Cast } from '../../../new_fields/Types';
import { Doc } from '../../../new_fields/Doc';
import { SearchItem } from './SearchItem';
-import { DocServer } from '../../DocServer';
import * as rp from 'request-promise';
import { Id } from '../../../new_fields/FieldSymbols';
import { SearchUtil } from '../../util/SearchUtil';
import { RouteStore } from '../../../server/RouteStore';
import { FilterBox } from './FilterBox';
+import { Utils } from '../../../Utils';
@observer
@@ -23,8 +23,8 @@ export class SearchBox extends React.Component {
@observable private _searchString: string = "";
@observable private _resultsOpen: boolean = false;
@observable private _searchbarOpen: boolean = false;
- @observable private _results: Doc[] = [];
- private _resultsSet = new Set<Doc>();
+ @observable private _results: [Doc, string[]][] = [];
+ private _resultsSet = new Map<Doc, number>();
@observable private _openNoResults: boolean = false;
@observable private _visibleElements: JSX.Element[] = [];
@@ -74,7 +74,7 @@ export class SearchBox extends React.Component {
public static async convertDataUri(imageUri: string, returnedFilename: string) {
try {
- let posting = DocServer.prepend(RouteStore.dataUriToImage);
+ let posting = Utils.prepend(RouteStore.dataUriToImage);
const returnedUri = await rp.post(posting, {
body: {
uri: imageUri,
@@ -119,7 +119,7 @@ export class SearchBox extends React.Component {
}
getAllResults = async (query: string) => {
- return SearchUtil.Search(query, this.filterQuery, true, 0, 10000000);
+ return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 });
}
private get filterQuery() {
@@ -136,21 +136,30 @@ export class SearchBox extends React.Component {
}
this.lockPromise = new Promise(async res => {
while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) {
- this._curRequest = SearchUtil.Search(query, this.filterQuery, true, this._maxSearchIndex, 10).then(action(async (res: SearchUtil.DocSearchResult) => {
+ this._curRequest = SearchUtil.Search(query, true, { fq: this.filterQuery, start: this._maxSearchIndex, rows: 10, hl: true, "hl.fl": "*" }).then(action(async (res: SearchUtil.DocSearchResult) => {
// happens at the beginning
if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) {
this._numTotalResults = res.numFound;
}
- const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any)));
+ const highlighting = res.highlighting || {};
+ const highlightList = res.docs.map(doc => highlighting[doc[Id]]);
+ const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc));
+ const highlights: typeof res.highlighting = {};
+ docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]);
let filteredDocs = FilterBox.Instance.filterDocsByType(docs);
runInAction(() => {
// this._results.push(...filteredDocs);
filteredDocs.forEach(doc => {
- if (!this._resultsSet.has(doc)) {
- this._results.push(doc);
- this._resultsSet.add(doc);
+ const index = this._resultsSet.get(doc);
+ const highlight = highlights[doc[Id]];
+ const hlights = highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)) : [];
+ if (index === undefined) {
+ this._resultsSet.set(doc, this._results.length);
+ this._results.push([doc, hlights]);
+ } else {
+ this._results[index][1].push(...hlights);
}
});
});
@@ -274,19 +283,19 @@ export class SearchBox extends React.Component {
}
else {
if (this._isSearch[i] !== "search") {
- let result: Doc | undefined = undefined;
+ let result: [Doc, string[]] | undefined = undefined;
if (i >= this._results.length) {
this.getResults(this._searchString);
if (i < this._results.length) result = this._results[i];
if (result) {
- this._visibleElements[i] = <SearchItem doc={result} key={result[Id]} />;
+ this._visibleElements[i] = <SearchItem doc={result[0]} key={result[0][Id]} highlighting={result[1]} />;
this._isSearch[i] = "search";
}
}
else {
result = this._results[i];
if (result) {
- this._visibleElements[i] = <SearchItem doc={result} key={result[Id]} />;
+ this._visibleElements[i] = <SearchItem doc={result[0]} key={result[0][Id]} highlighting={result[1]} />;
this._isSearch[i] = "search";
}
}
diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss
index 24dd2eaa3..273d49349 100644
--- a/src/client/views/search/SearchItem.scss
+++ b/src/client/views/search/SearchItem.scss
@@ -24,11 +24,15 @@
flex-direction: row;
width: 100%;
- .search-title {
- text-transform: uppercase;
- text-align: left;
+ .search-title-container {
width: 100%;
- font-weight: bold;
+
+ .search-title {
+ text-transform: uppercase;
+ text-align: left;
+ width: 100%;
+ font-weight: bold;
+ }
}
.search-info {
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index e34d101a8..a995140e2 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -26,6 +26,7 @@ import { faFile } from '@fortawesome/free-solid-svg-icons';
export interface SearchItemProps {
doc: Doc;
+ highlighting: string[];
}
library.add(faCaretUp);
@@ -51,9 +52,9 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> {
async fetchDocuments() {
let aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc);
- const { docs } = await SearchUtil.Search("", `data_l:"${this.props.doc[Id]}"`, true);
+ const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.doc[Id]}"` });
const map: Map<Doc, Doc> = new Map;
- const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", `data_l:"${doc[Id]}"`, true).then(result => result.docs)));
+ const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs)));
allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
docs.forEach(doc => map.delete(doc));
runInAction(() => {
@@ -100,8 +101,8 @@ export class SearchItem extends React.Component<SearchItemProps> {
onClick = () => {
// I dont think this is the best functionality because clicking the name of the collection does that. Change it back if you'd like
- // DocumentManager.Instance.jumpToDocument(this.props.doc, false);
- CollectionDockingView.Instance.AddRightSplit(this.props.doc, undefined);
+ DocumentManager.Instance.jumpToDocument(this.props.doc, false);
+ // CollectionDockingView.Instance.AddRightSplit(this.props.doc, undefined);
}
@observable _useIcons = true;
@observable _displayDim = 50;
@@ -243,7 +244,10 @@ export class SearchItem extends React.Component<SearchItemProps> {
onClick={this.onClick} onPointerDown={this.pointerDown} >
<div className="main-search-info">
<div title="Drag as document" onPointerDown={this.onPointerDown} style={{ marginRight: "7px" }}> <FontAwesomeIcon icon="file" size="lg" /> </div>
- <div className="search-title" id="result" >{StrCast(this.props.doc.title)}</div>
+ <div className="search-title-container">
+ <div className="search-title">{StrCast(this.props.doc.title)}</div>
+ <div className="search-highlighting">Matched fields: {this.props.highlighting.join(", ")}</div>
+ </div>
<div className="search-info" style={{ width: this._useIcons ? "15%" : "400px" }}>
<div className={`icon-${this._useIcons ? "icons" : "live"}`}>
<div className="search-type" title="Click to Preview">{this.DocumentIcon}</div>