aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2020-04-20 22:34:29 -0400
committerBob Zeleznik <zzzman@gmail.com>2020-04-20 22:34:29 -0400
commita9b6fba3a742f95815e2664770079bebd3b87d5f (patch)
tree8befbba81a9dc88436d8129dbdf352b1dc70e831
parent38a0f3f0b690599d72e52456ecfc14c081811e89 (diff)
fixed search to avoid server crashes by stripping off initial ?*+ characters. made search parameters persistent on queryBox
-rw-r--r--src/client/documents/Documents.ts1
-rw-r--r--src/client/util/SearchUtil.ts2
-rw-r--r--src/client/views/nodes/QueryBox.tsx13
-rw-r--r--src/client/views/search/IconBar.tsx4
-rw-r--r--src/client/views/search/SearchBox.tsx40
-rw-r--r--src/server/ApiManagers/SearchManager.ts17
-rw-r--r--src/server/authentication/models/current_user_utils.ts1
7 files changed, 42 insertions, 36 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e3cc8ccfe..5ff8f29ec 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -140,6 +140,7 @@ export interface DocumentOptions {
icon?: string;
sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script
targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script
+ searchFileTypes?: List<string>; // file types allowed in a search query
strokeWidth?: number;
treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view
treeViewHideTitle?: boolean; // whether to hide the title of a tree view
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 2026bf940..6501da34a 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -44,7 +44,7 @@ export namespace SearchUtil {
const { ids, highlighting } = result;
const txtresult = query !== "*" && JSON.parse(await rp.get(Utils.prepend("/textsearch"), {
- qs: { ...options, q: query },
+ qs: { ...options, q: query.replace(/^[ \+\?\*\|]*/, "") }, // a leading '+' leads to a server crash since findInFiles doesn't handle regex failures
}));
const fileids = txtresult ? txtresult.ids : [];
diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx
index 947167200..76885eada 100644
--- a/src/client/views/nodes/QueryBox.tsx
+++ b/src/client/views/nodes/QueryBox.tsx
@@ -3,13 +3,14 @@ import { IReactionDisposer } from "mobx";
import { observer } from "mobx-react";
import { documentSchema } from "../../../new_fields/documentSchemas";
import { Id } from '../../../new_fields/FieldSymbols';
-import { makeInterface } from "../../../new_fields/Schema";
-import { StrCast } from "../../../new_fields/Types";
+import { makeInterface, listSpec } from "../../../new_fields/Schema";
+import { StrCast, Cast } from "../../../new_fields/Types";
import { SelectionManager } from "../../util/SelectionManager";
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { SearchBox } from "../search/SearchBox";
import { FieldView, FieldViewProps } from './FieldView';
import "./QueryBox.scss";
+import { List } from "../../../new_fields/List";
type QueryDocument = makeInterface<[typeof documentSchema]>;
const QueryDocument = makeInterface(documentSchema);
@@ -28,7 +29,13 @@ export class QueryBox extends ViewBoxAnnotatableComponent<FieldViewProps, QueryD
render() {
const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging";
return <div className={`queryBox${dragging}`} onWheel={(e) => e.stopPropagation()} >
- <SearchBox id={this.props.Document[Id]} searchQuery={StrCast(this.dataDoc.searchQuery)} filterQquery={StrCast(this.dataDoc.filterQuery)} />
+ <SearchBox
+ id={this.props.Document[Id]}
+ setSearchQuery={q => this.dataDoc.searchQuery = q}
+ searchQuery={StrCast(this.dataDoc.searchQuery)}
+ setSearchFileTypes={q => this.dataDoc.searchFileTypes = new List<string>(q)}
+ searchFileTypes={Cast(this.dataDoc.searchFileTypes, listSpec("string"), [])}
+ filterQquery={StrCast(this.dataDoc.filterQuery)} />
</div >;
}
} \ No newline at end of file
diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx
index 9cf5a9c87..9b7cf2fc6 100644
--- a/src/client/views/search/IconBar.tsx
+++ b/src/client/views/search/IconBar.tsx
@@ -25,7 +25,7 @@ library.add(faGlobeAsia);
library.add(faBan);
export interface IconBarProps {
- setIcons: (icons: string[]) => {};
+ setIcons: (icons: string[]) => void;
}
@@ -44,7 +44,7 @@ export class IconBar extends React.Component<IconBarProps> {
@action.bound
updateIcon(newArray: string[]) {
- this._icons = newArray;
+ this._icons = newArray;
this.props.setIcons?.(this._icons);
}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index f332104fc..b0a49f750 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -19,13 +19,17 @@ import { FieldView } from '../nodes/FieldView';
import { DocumentType } from "../../documents/DocumentTypes";
import { DocumentView } from '../nodes/DocumentView';
import { SelectionManager } from '../../util/SelectionManager';
+import { listSpec } from '../../../new_fields/Schema';
library.add(faTimes);
export interface SearchProps {
id: string;
- searchQuery?: string;
+ searchQuery: string;
filterQquery?: string;
+ setSearchQuery: (q: string) => {};
+ searchFileTypes: string[];
+ setSearchFileTypes: (types: string[]) => {}
}
export enum Keys {
@@ -37,7 +41,8 @@ export enum Keys {
@observer
export class SearchBox extends React.Component<SearchProps> {
- @observable private _searchString: string = "";
+ private get _searchString() { return this.props.searchQuery; }
+ private set _searchString(value) { this.props.setSearchQuery(value); }
@observable private _resultsOpen: boolean = false;
@observable private _searchbarOpen: boolean = false;
@observable private _results: [Doc, string[], string[]][] = [];
@@ -72,20 +77,16 @@ export class SearchBox extends React.Component<SearchProps> {
this.resultsScrolled = this.resultsScrolled.bind(this);
}
- componentDidMount = () => {
+ componentDidMount = action(() => {
if (this.inputRef.current) {
this.inputRef.current.focus();
- runInAction(() => this._searchbarOpen = true);
+ this._searchbarOpen = true;
}
- if (this.props.searchQuery && this.props.filterQquery) {
- console.log(this.props.searchQuery);
- const sq = this.props.searchQuery;
- runInAction(() => {
- this._searchString = sq;
- this.submitSearch();
- });
+ if (this.props.searchQuery) { // bcz: why was this here? } && this.props.filterQquery) {
+ this._searchString = this.props.searchQuery;
+ this.submitSearch();
}
- }
+ })
@action
@@ -133,7 +134,10 @@ export class SearchBox extends React.Component<SearchProps> {
//this also serves as an indicator if the word status filter is applied
@observable private _filterOpen: boolean = false;
//if icons = all icons, then no icon filter is applied
- @observable private _icons: string[] = this._allIcons;
+ get _icons() { return this.props.searchFileTypes; }
+ set _icons(value) {
+ this.props.setSearchFileTypes(value);
+ }
//if all of these are true, no key filter is applied
@observable private _titleFieldStatus: boolean = true;
@observable private _authorFieldStatus: boolean = true;
@@ -206,12 +210,6 @@ export class SearchBox extends React.Component<SearchProps> {
return this._icons.length === this._allIcons.length ? undefined : this._icons;
}
- @action.bound
- updateIcon(newArray: string[]) { this._icons = newArray; }
-
- @action.bound
- getIcons(): string[] { return this._icons; }
-
//TODO: basically all of this
//gets all of the collections of all the docviews that are selected
//if a collection is the only thing selected, search only in that collection (not its container)
@@ -648,7 +646,9 @@ export class SearchBox extends React.Component<SearchProps> {
<button className="filter-item" style={this._nodeStatus ? { background: "#aaaaa3" } : {}} onClick={this.handleNodeChange}>Nodes</button>
</div>
<div id={`node${this.props.id}`} className="filter-body" style={this._nodeStatus ? { borderTop: "grey 1px solid" } : { borderTop: "0px" }}>
- <IconBar setIcons={(icons: string[]) => this._icons = icons} />
+ <IconBar setIcons={(icons: string[]) => {
+ this._icons = icons;
+ }} />
</div>
<div className="filter-key" id={`key${this.props.id}`} style={this._keyStatus ? { borderTop: "grey 1px solid" } : { borderTop: "0px" }}>
<div className="filter-keybar">
diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts
index 9e1cc120d..753c31fcf 100644
--- a/src/server/ApiManagers/SearchManager.ts
+++ b/src/server/ApiManagers/SearchManager.ts
@@ -45,16 +45,13 @@ export class SearchManager extends ApiManager {
return;
}
const resObj: { ids: string[], numFound: number, lines: string[] } = { ids: [], numFound: 0, lines: [] };
- try {
- const results = await findInFiles.find({ 'term': q, 'flags': 'ig' }, pathToDirectory(Directory.text), ".txt$");
- for (const result in results) {
- resObj.ids.push(path.basename(result, ".txt").replace(/upload_/, ""));
- resObj.lines.push(results[result].line);
- resObj.numFound++;
- }
- }
- catch (e) {
- console.error(e);
+ let results: any;
+ const dir = pathToDirectory(Directory.text);
+ results = await findInFiles.find({ 'term': q, 'flags': 'ig' }, dir, ".txt$");
+ for (const result in results) {
+ resObj.ids.push(path.basename(result, ".txt").replace(/upload_/, ""));
+ resObj.lines.push(results[result].line);
+ resObj.numFound++;
}
res.send(resObj);
}
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index e0ca5a468..3955f64fc 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -413,6 +413,7 @@ export class CurrentUserUtils {
_width: 50, _height: 25, title: "Search", fontSize: 10,
letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
sourcePanel: new PrefetchProxy(Docs.Create.QueryDocument({ title: "search stack", })) as any as Doc,
+ searchFileTypes: new List<string>([DocumentType.RTF, DocumentType.IMG, DocumentType.PDF, DocumentType.VID, DocumentType.WEB, DocumentType.SCRIPTING]),
targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc,
lockedPosition: true,
onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel")