aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-05-07 19:27:12 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-05-07 19:27:12 -0400
commit19bca65d863d1f40bd663f0aa5ed61ad92b6a764 (patch)
tree1c5e3ff76f4b3545552d244d37b469b688cf0f9b /src
parent152fadbad5d3c4e9c452bb6a1ade543bd84c6416 (diff)
parent11ab63f6c91093951fdc293c3d67e63073fb2f4c (diff)
Merge branch 'monika-search' of github-tsch-brown:browngraphicslab/Dash-Web into new_search
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DocumentManager.ts30
-rw-r--r--src/client/views/Main.scss3
-rw-r--r--src/client/views/Main.tsx6
-rw-r--r--src/client/views/SearchBox.scss99
-rw-r--r--src/client/views/SearchBox.tsx121
-rw-r--r--src/client/views/SearchItem.tsx22
-rw-r--r--src/client/views/nodes/LinkBox.tsx23
-rw-r--r--src/server/Search.ts2
8 files changed, 280 insertions, 26 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 69964e2c9..3151bcfb5 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,8 +1,10 @@
import { computed, observable } from 'mobx';
import { DocumentView } from '../views/nodes/DocumentView';
import { Doc } from '../../new_fields/Doc';
-import { FieldValue, Cast } from '../../new_fields/Types';
+import { FieldValue, Cast, NumCast } from '../../new_fields/Types';
import { listSpec } from '../../new_fields/Schema';
+import { undoBatch } from './UndoManager';
+import { CollectionDockingView } from '../views/collections/CollectionDockingView';
export class DocumentManager {
@@ -87,4 +89,30 @@ export class DocumentManager {
return pairs;
}, [] as { a: DocumentView, b: DocumentView, l: Doc }[]);
}
+
+ @undoBatch
+ public jumpToDocument = async (doc: Doc): Promise<void> => {
+ let docView = DocumentManager.Instance.getDocumentView(doc);
+ if (docView) {
+ docView.props.focus(docView.props.Document);
+ } else {
+ const contextDoc = await Cast(doc.annotationOn, Doc);
+ if (!contextDoc) {
+ CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(doc));
+ } else {
+ const page = NumCast(doc.page, undefined);
+ const curPage = NumCast(contextDoc.curPage, undefined);
+ if (page !== curPage) {
+ contextDoc.curPage = page;
+ }
+ let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
+ if (contextView) {
+ contextDoc.panTransformType = "Ease";
+ contextView.props.focus(contextDoc);
+ } else {
+ CollectionDockingView.Instance.AddRightSplit(contextDoc);
+ }
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 5c5c252e9..2430e8f6c 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -47,7 +47,7 @@ h1 {
}
.jsx-parser {
- width:100%;
+ width: 100%;
pointer-events: none;
border-radius: inherit;
}
@@ -184,6 +184,7 @@ button:hover {
overflow: scroll;
z-index: 1;
}
+
#mainContent-div {
width: 100%;
height: 100%;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 617580332..c9d5c395c 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -31,6 +31,7 @@ import "./Main.scss";
import { MainOverlayTextBox } from './MainOverlayTextBox';
import { DocumentView } from './nodes/DocumentView';
import { PreviewCursor } from './PreviewCursor';
+import { SearchBox } from './SearchBox';
import { SelectionManager } from '../util/SelectionManager';
import { FieldResult, Field, Doc, Opt } from '../../new_fields/Doc';
import { Cast, FieldValue, StrCast } from '../../new_fields/Types';
@@ -38,7 +39,6 @@ import { DocServer } from '../DocServer';
import { listSpec } from '../../new_fields/Schema';
import { Id } from '../../new_fields/RefField';
-
@observer
export class Main extends React.Component {
public static Instance: Main;
@@ -266,9 +266,11 @@ export class Main extends React.Component {
<button className="toolbar-button round-button" title="Redo" onClick={() => UndoManager.Redo()}><FontAwesomeIcon icon="redo-alt" size="sm" /></button>
<button className="toolbar-button round-button" title="Ink" onClick={() => InkingControl.Instance.toggleDisplay()}><FontAwesomeIcon icon="pen-nib" size="sm" /></button>
</div >,
- <div className="main-buttonDiv" key="logout" style={{ top: '34px', right: '1px', position: 'absolute' }} ref={logoutRef}>
+ <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <SearchBox /> </div>,
+ <div className="main-buttonDiv" key="logout" style={{ bottom: '0px', right: '1px', position: 'absolute' }} ref={logoutRef}>
<button onClick={() => request.get(DocServer.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
];
+
}
render() {
diff --git a/src/client/views/SearchBox.scss b/src/client/views/SearchBox.scss
new file mode 100644
index 000000000..f4fc0029e
--- /dev/null
+++ b/src/client/views/SearchBox.scss
@@ -0,0 +1,99 @@
+@import "globalCssVariables";
+
+.searchBox {
+ height: 32px;
+ //display: flex;
+ //padding: 4px;
+ -webkit-transition: width 0.4s ease-in-out;
+ transition: width 0.4s ease-in-out;
+ align-items: center;
+
+
+
+ input[type=text] {
+ width: 130px;
+ -webkit-transition: width 0.4s;
+ transition: width 0.4s;
+ position: absolute;
+ right: 100px;
+ }
+
+ input[type=text]:focus {
+ width: 500px;
+ outline: 3px solid lightblue;
+ }
+
+ .filter-button {
+ position: absolute;
+ right: 30px;
+ }
+
+ .submit-search {
+ text-align: right;
+ color: $dark-color;
+ -webkit-transition: right 0.4s;
+ transition: right 0.4s;
+ }
+
+ .submit-search:hover {
+ color: $main-accent;
+ transform: scale(1.05);
+ cursor: pointer;
+ }
+}
+
+.filter-form {
+ background: $dark-color;
+ height: 400px;
+ width: 400px;
+ position: relative;
+ right: 1px;
+ color: $light-color;
+ padding: 10px;
+ flex-direction: column;
+}
+
+#header {
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ font-size: 100%;
+ height: 40px;
+}
+
+#option {
+ height: 20px;
+}
+
+.results {
+ top: 300px;
+ display: flex;
+ flex-direction: column;
+}
+
+.search-item {
+ width: 500px;
+ height: 50px;
+ background: $light-color-secondary;
+ display: flex;
+ justify-content: left;
+ align-items: center;
+ transition: all 0.1s;
+ border-width: 0.11px;
+ border-style: none;
+ border-color: $intermediate-color;
+ border-bottom-style: solid;
+ padding: 10px;
+ white-space: nowrap;
+ font-size: 13px;
+}
+
+.search-item:hover {
+ transition: all 0.1s;
+ background: $lighter-alt-accent;
+}
+
+.search-title {
+ text-transform: uppercase;
+ text-align: left;
+ width: 8vw;
+} \ No newline at end of file
diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx
new file mode 100644
index 000000000..827d468df
--- /dev/null
+++ b/src/client/views/SearchBox.tsx
@@ -0,0 +1,121 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { observable, action, runInAction } from 'mobx';
+import { Utils } from '../../Utils';
+import { MessageStore } from '../../server/Message';
+import "./SearchBox.scss";
+import { faSearch } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { library } from '@fortawesome/fontawesome-svg-core';
+// const app = express();
+// import * as express from 'express';
+import { Search } from '../../server/Search';
+import * as rp from 'request-promise';
+import { SearchItem } from './SearchItem';
+import { isString } from 'util';
+import { constant } from 'async';
+import { DocServer } from '../DocServer';
+import { Doc } from '../../new_fields/Doc';
+import { Id } from '../../new_fields/RefField';
+import { DocumentManager } from '../util/DocumentManager';
+
+
+library.add(faSearch);
+
+@observer
+export class SearchBox extends React.Component {
+ @observable
+ searchString: string = "";
+
+ @observable private _open: boolean = false;
+ @observable private _resultsOpen: boolean = false;
+
+ @observable
+ private _results: Doc[] = [];
+
+ @action.bound
+ onChange(e: React.ChangeEvent<HTMLInputElement>) {
+ this.searchString = e.target.value;
+ }
+
+ @action
+ submitSearch = async () => {
+ runInAction(() => this._results = []);
+ let query = this.searchString;
+
+ let response = await rp.get('http://localhost:1050/search', {
+ qs: {
+ query
+ }
+ });
+ let results = JSON.parse(response);
+
+ //gets json result into a list of documents that can be used
+ this.getResults(results);
+
+ runInAction(() => { this._resultsOpen = true; });
+ }
+
+ @action
+ getResults = async (res: string[]) => {
+ res.map(async result => {
+ const doc = await DocServer.GetRefField(result);
+ if (doc instanceof Doc) {
+ runInAction(() => this._results.push(doc));
+ }
+ });
+ }
+
+ @action
+ handleClick = (e: Event): void => {
+ var className = (e.target as any).className;
+ var id = (e.target as any).id;
+ if (className !== "filter-button" && className !== "filter-form") {
+ this._open = false;
+ }
+
+ }
+
+ componentWillMount() {
+ document.addEventListener('mousedown', this.handleClick, false);
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('mousedown', this.handleClick, false);
+ }
+
+ @action
+ toggleDisplay = () => {
+ this._open = !this._open;
+ }
+
+ enter = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ if (e.key === "Enter") {
+ this.submitSearch();
+ }
+ }
+
+ render() {
+ return (
+ <div id="outer">
+ <div className="searchBox" id="outer">
+
+ <input value={this.searchString} onChange={this.onChange} type="text" placeholder="Search.." className="search" id="input" onKeyPress={this.enter} />
+ <button className="filter-button" onClick={this.toggleDisplay}> Filter </button>
+ <div className="submit-search" id="submit" onClick={this.submitSearch}><FontAwesomeIcon style={{ height: "100%" }} icon="search" size="lg" /></div>
+ <div className="results" style={this._resultsOpen ? { display: "flex" } : { display: "none" }}>
+ {this._results.map(result => <SearchItem doc={result} key={result[Id]} />)}
+ </div>
+ </div>
+ <div className="filter-form" id="filter" style={this._open ? { display: "flex" } : { display: "none" }}>
+ <div className="filter-form" id="header">Filter Search Results</div>
+ <div className="filter-form" id="option">
+ filter by collection, key, type of node
+ </div>
+
+ </div>
+ </div>
+
+ );
+ }
+} \ No newline at end of file
diff --git a/src/client/views/SearchItem.tsx b/src/client/views/SearchItem.tsx
new file mode 100644
index 000000000..81da7ebd2
--- /dev/null
+++ b/src/client/views/SearchItem.tsx
@@ -0,0 +1,22 @@
+import React = require("react");
+import { Doc } from "../../new_fields/Doc";
+import { DocumentManager } from "../util/DocumentManager";
+
+export interface SearchProps {
+ doc: Doc;
+}
+
+export class SearchItem extends React.Component<SearchProps> {
+
+ onClick = () => {
+ DocumentManager.Instance.jumpToDocument(this.props.doc)
+ }
+
+ render() {
+ return (
+ <div className="search-item" onClick={this.onClick}>
+ <div className="search-title">{this.props.doc.title}</div>
+ </div>
+ );
+ }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 08cfa590b..611cb66b6 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -31,28 +31,7 @@ export class LinkBox extends React.Component<Props> {
@undoBatch
onViewButtonPressed = async (e: React.PointerEvent): Promise<void> => {
e.stopPropagation();
- let docView = DocumentManager.Instance.getDocumentView(this.props.pairedDoc);
- if (docView) {
- docView.props.focus(docView.props.Document);
- } else {
- const contextDoc = await Cast(this.props.pairedDoc.annotationOn, Doc);
- if (!contextDoc) {
- CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(this.props.pairedDoc));
- } else {
- const page = NumCast(this.props.pairedDoc.page, undefined);
- const curPage = NumCast(contextDoc.curPage, undefined);
- if (page !== curPage) {
- contextDoc.curPage = page;
- }
- let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
- if (contextView) {
- contextDoc.panTransformType = "Ease";
- contextView.props.focus(contextDoc);
- } else {
- CollectionDockingView.Instance.AddRightSplit(contextDoc);
- }
- }
- }
+ DocumentManager.Instance.jumpToDocument(this.props.pairedDoc);
}
onEditButtonPressed = (e: React.PointerEvent): void => {
diff --git a/src/server/Search.ts b/src/server/Search.ts
index 59bdd4803..7a670e21b 100644
--- a/src/server/Search.ts
+++ b/src/server/Search.ts
@@ -14,6 +14,8 @@ export class Search {
}
public async search(query: string) {
+ console.log("____________________________");
+ console.log(query);
const searchResults = JSON.parse(await rp.get(this.url + "dash/select", {
qs: {
q: query