diff options
-rw-r--r-- | src/client/views/Main.scss | 3 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 4 | ||||
-rw-r--r-- | src/client/views/SearchBox.scss | 99 | ||||
-rw-r--r-- | src/client/views/SearchBox.tsx | 121 | ||||
-rw-r--r-- | src/client/views/SearchItem.tsx | 34 | ||||
-rw-r--r-- | src/server/Search.ts | 2 |
6 files changed, 261 insertions, 2 deletions
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..677902c5b 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-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <SearchBox /> </div>, <div className="main-buttonDiv" key="logout" style={{ top: '34px', 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..a52598f4c --- /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'; + + +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; + console.log(this.searchString) + } + + @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..82cb5404c --- /dev/null +++ b/src/client/views/SearchItem.tsx @@ -0,0 +1,34 @@ +import React = require("react"); +import { Doc } from "../../new_fields/Doc"; + +export interface SearchProps { + doc: Doc; + //description: string; + //event: (e: React.MouseEvent<HTMLDivElement>) => void; +} + +// export interface SubmenuProps { +// description: string; +// subitems: ContextMenuProps[]; +// } + +// export interface ContextMenuItemProps { +// type: ContextMenuProps | SubmenuProps; +// } + + + +export class SearchItem extends React.Component<SearchProps> { + + onClick = () => { + console.log("document clicked: ", 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/server/Search.ts b/src/server/Search.ts index 4911edd1d..6e7883bc9 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -40,6 +40,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 |