aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/DocumentTypes.ts3
-rw-r--r--src/client/documents/Documents.ts10
-rw-r--r--src/client/views/GlobalKeyHandler.ts4
-rw-r--r--src/client/views/MainView.tsx10
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx5
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx3
-rw-r--r--src/client/views/nodes/QueryBox.scss0
-rw-r--r--src/client/views/nodes/QueryBox.tsx50
-rw-r--r--src/client/views/search/FilterBox.tsx4
-rw-r--r--src/client/views/search/IconBar.tsx14
-rw-r--r--src/client/views/search/SearchBox.scss17
-rw-r--r--src/client/views/search/SearchBox.tsx2
-rw-r--r--src/client/views/search/SearchItem.scss39
-rw-r--r--src/client/views/search/SearchItem.tsx19
-rw-r--r--src/server/authentication/models/current_user_utils.ts6
15 files changed, 120 insertions, 66 deletions
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index e5d5885cd..7abaa4043 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -20,5 +20,6 @@ export enum DocumentType {
DRAGBOX = "dragbox",
PRES = "presentation",
LINKFOLLOW = "linkfollow",
- PRESELEMENT = "preselement"
+ PRESELEMENT = "preselement",
+ QUERY = "search",
} \ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0114f82d8..7f6ab50d8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -45,6 +45,7 @@ import { ProxyField } from "../../new_fields/Proxy";
import { DocumentType } from "./DocumentTypes";
import { LinkFollowBox } from "../views/linking/LinkFollowBox";
import { PresElementBox } from "../views/presentationview/PresElementBox";
+import { QueryBox } from "../views/nodes/QueryBox";
var requestImageSize = require('../util/request-image-size');
var path = require('path');
@@ -62,6 +63,7 @@ export interface DocumentOptions {
panY?: number;
page?: number;
scale?: number;
+ fitWidth?: boolean;
layout?: string | Doc;
isTemplate?: boolean;
templates?: List<string>;
@@ -119,6 +121,10 @@ export namespace Docs {
layout: { view: HistogramBox, collectionView: [CollectionView, data] as CollectionViewType },
options: { height: 300, backgroundColor: "black" }
}],
+ [DocumentType.QUERY, {
+ layout: { view: QueryBox },
+ options: { width: 400, fitWidth: true }
+ }],
[DocumentType.IMG, {
layout: { view: ImageBox, ext: anno },
options: {}
@@ -374,6 +380,10 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.HIST), new HistogramField(histoOp), options);
}
+ export function QueryDocument(options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options);
+ }
+
export function TextDocument(options: DocumentOptions = {}) {
return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options);
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index c519991a5..6815ff926 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -7,6 +7,8 @@ import { action, runInAction } from "mobx";
import { Doc } from "../../new_fields/Doc";
import { DictationManager } from "../util/DictationManager";
import SharingManager from "../util/SharingManager";
+import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
+import { Cast, PromiseValue } from "../../new_fields/Types";
const modifiers = ["control", "meta", "shift", "alt"];
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise<KeyControlInfo>;
@@ -162,6 +164,8 @@ export default class KeyManager {
break;
case "f":
MainView.Instance.isSearchVisible = !MainView.Instance.isSearchVisible;
+ MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0;
+ PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0)));
break;
case "o":
let target = SelectionManager.SelectedDocuments()[0];
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ba4224875..1ec21f638 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -12,7 +12,7 @@ import { Id } from '../../new_fields/FieldSymbols';
import { InkTool } from '../../new_fields/InkField';
import { List } from '../../new_fields/List';
import { listSpec } from '../../new_fields/Schema';
-import { BoolCast, Cast, FieldValue, StrCast } from '../../new_fields/Types';
+import { BoolCast, Cast, FieldValue, StrCast, PromiseValue } from '../../new_fields/Types';
import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
import { RouteStore } from '../../server/RouteStore';
import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils';
@@ -463,7 +463,7 @@ export class MainView extends React.Component {
return (null);
}
return <DocumentView
- Document={sidebar}
+ Document={this.isSearchVisible ? Cast(CurrentUserUtils.UserDocument.searchBox, Doc) as Doc : sidebar}
DataDoc={undefined}
addDocument={undefined}
addDocTab={this.addDocTabFunc}
@@ -640,7 +640,7 @@ export class MainView extends React.Component {
@computed
get miscButtons() {
return [
- this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <FilterBox /> </div> : null,
+ //this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <FilterBox /> </div> : null,
];
}
@@ -648,7 +648,9 @@ export class MainView extends React.Component {
@observable isSearchVisible = false;
@action.bound
toggleSearch = () => {
- this.isSearchVisible = !this.isSearchVisible;
+ this.isSearchVisible = !MainView.Instance.isSearchVisible;
+ MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0;
+ PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0)));
}
@computed private get dictationOverlay() {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 37eb151b1..6f5587b5a 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -260,7 +260,10 @@ class TreeView extends React.Component<TreeViewProps> {
let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth);
if (aspect) return this.docWidth() * aspect;
if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x);
- return NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50;
+ return this.props.document.fitWidth ? (!this.props.document.nativeHeight ? NumCast(this.props.containingCollection.height) :
+ Math.min(this.docWidth() * NumCast(this.props.document.scrollHeight, NumCast(this.props.document.nativeHeight)) / NumCast(this.props.document.nativeWidth,
+ NumCast(this.props.containingCollection.height)))) :
+ NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50;
})());
}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e4b2ecffd..d4e7c6d4e 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -24,6 +24,7 @@ import { ImageBox } from "./ImageBox";
import { KeyValueBox } from "./KeyValueBox";
import { PDFBox } from "./PDFBox";
import { PresBox } from "./PresBox";
+import { QueryBox } from "./QueryBox";
import { PresElementBox } from "../presentationview/PresElementBox";
import { VideoBox } from "./VideoBox";
import { WebBox } from "./WebBox";
@@ -99,7 +100,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
if (!this.layout && this.props.layoutKey !== "overlayLayout") return (null);
return <ObserverJsxParser
blacklistedAttrs={[]}
- components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox, PresElementBox }}
+ components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox, PresElementBox, QueryBox }}
bindings={this.CreateBindings()}
jsx={this.finalLayout}
showWarnings={true}
diff --git a/src/client/views/nodes/QueryBox.scss b/src/client/views/nodes/QueryBox.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/client/views/nodes/QueryBox.scss
diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx
new file mode 100644
index 000000000..7a8e0df63
--- /dev/null
+++ b/src/client/views/nodes/QueryBox.tsx
@@ -0,0 +1,50 @@
+import React = require("react");
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed, reaction, IReactionDisposer } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
+import { listSpec } from "../../../new_fields/Schema";
+import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
+import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
+import { DocumentManager } from "../../util/DocumentManager";
+import { undoBatch } from "../../util/UndoManager";
+import { CollectionViewType } from "../collections/CollectionBaseView";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionView } from "../collections/CollectionView";
+import { ContextMenu } from "../ContextMenu";
+import { FieldView, FieldViewProps } from './FieldView';
+import "./PresBox.scss";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { Docs } from "../../documents/Documents";
+import { ComputedField } from "../../../new_fields/ScriptField";
+import { SearchBox } from "../search/SearchBox";
+import { FilterBox } from "../search/FilterBox";
+
+library.add(faArrowLeft);
+library.add(faArrowRight);
+library.add(faPlay);
+library.add(faStop);
+library.add(faPlus);
+library.add(faTimes);
+library.add(faMinus);
+library.add(faEdit);
+
+@observer
+export class QueryBox extends React.Component<FieldViewProps> {
+ public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(QueryBox, fieldKey); }
+ _docListChangedReaction: IReactionDisposer | undefined;
+ componentDidMount() {
+ }
+
+ componentWillUnmount() {
+ this._docListChangedReaction && this._docListChangedReaction();
+ }
+
+ render() {
+ return <div style={{ width: "100%", height: "100%", position: "absolute", pointerEvents: "all" }}>
+ <FilterBox></FilterBox>
+ </div>
+ }
+} \ No newline at end of file
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx
index da733d64b..b841190d4 100644
--- a/src/client/views/search/FilterBox.tsx
+++ b/src/client/views/search/FilterBox.tsx
@@ -33,7 +33,7 @@ export enum Keys {
export class FilterBox extends React.Component {
static Instance: FilterBox;
- public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.HIST, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB];
+ public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB];
//if true, any keywords can be used. if false, all keywords are required.
//this also serves as an indicator if the word status filter is applied
@@ -393,7 +393,7 @@ export class FilterBox extends React.Component {
<div>
<div style={{ display: "flex", flexDirection: "row-reverse" }}>
<SearchBox />
- {this.getActiveFilters()}
+ {/* {this.getActiveFilters()} */}
</div>
{this._filterOpen ? (
<div className="filter-form" onPointerDown={this.stopProp} id="filter-form" style={this._filterOpen ? { display: "flex" } : { display: "none" }}>
diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx
index c9924222f..bdeb57d5c 100644
--- a/src/client/views/search/IconBar.tsx
+++ b/src/client/views/search/IconBar.tsx
@@ -59,23 +59,9 @@ export class IconBar extends React.Component {
render() {
return (
<div className="icon-bar">
- <div className="type-outer">
- <div className={"type-icon all"}
- onClick={this.selectAll}>
- <FontAwesomeIcon className="fontawesome-icon" icon={faCheckCircle} />
- </div>
- <div className="filter-description">Select All</div>
- </div>
{FilterBox.Instance._allIcons.map((type: string) =>
<IconButton type={type} />
)}
- <div className="type-outer">
- <div className={"type-icon none"}
- onClick={this.resetSelf}>
- <FontAwesomeIcon className="fontawesome-icon" icon={faTimesCircle} />
- </div>
- <div className="filter-description">Clear</div>
- </div>
</div>
);
}
diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss
index 0dd4d3dc5..bc11604a5 100644
--- a/src/client/views/search/SearchBox.scss
+++ b/src/client/views/search/SearchBox.scss
@@ -1,6 +1,15 @@
@import "../globalCssVariables";
@import "./NaviconButton.scss";
+.searchBox-container {
+ display: flex;
+ flex-direction: column;
+ width:100%;
+ height:100%;
+ position: absolute;
+ font-size: 10px;
+ line-height: 1;
+}
.searchBox-bar {
height: 32px;
display: flex;
@@ -49,17 +58,17 @@
}
.searchBox-quickFilter {
- width: 500px;
- margin-left: 25px;
+ width: 100%;
+ height: 40px;
margin-top: 10px;
}
.searchBox-results {
- margin-right: 136px;
+ display:flex;
+ flex-direction: column;
top: 300px;
display: flex;
flex-direction: column;
- margin-right: 72px;
// height: 560px;
height: 100%;
// overflow: hidden;
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index be75a29e0..62c8c255e 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -346,8 +346,6 @@ export class SearchBox extends React.Component {
className="searchBox-barChild searchBox-input" onPointerDown={this.openSearch} onKeyPress={this.enter} onFocus={this.openSearch}
style={{ width: this._searchbarOpen ? "500px" : "100px" }} />
<button className="searchBox-barChild searchBox-filter" title="Advanced Filtering Options" onClick={FilterBox.Instance.openFilter} onPointerDown={FilterBox.Instance.stopProp}><FontAwesomeIcon icon="ellipsis-v" color="white" /></button>
- <button className="searchBox-barChild searchBox-submit" onClick={this.submitSearch} onPointerDown={FilterBox.Instance.stopProp}>Submit</button>
- <button className="searchBox-barChild searchBox-close" title={"Close Search Bar"} onPointerDown={MainView.Instance.toggleSearch}><FontAwesomeIcon icon={faTimes} size="lg" /></button>
</div>
{(this._numTotalResults > 0 || !this._searchbarOpen) ? (null) :
(<div className="searchBox-quickFilter" onPointerDown={this.openSearch}>
diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss
index 62715c5eb..9f12994c3 100644
--- a/src/client/views/search/SearchItem.scss
+++ b/src/client/views/search/SearchItem.scss
@@ -2,19 +2,27 @@
.search-overview {
display: flex;
- flex-direction: row-reverse;
+ flex-direction: reverse;
justify-content: flex-end;
z-index: 0;
}
+.link-count {
+ background: black;
+ border-radius: 20px;
+ color: white;
+ width: 15px;
+ text-align: center;
+ margin-top: 5px;
+}
.searchBox-placeholder,
.search-overview .search-item {
- width: 500px;
+ width: 100%;
background: $light-color-secondary;
border-color: $intermediate-color;
border-bottom-style: solid;
padding: 10px;
- min-height: 70px;
+ min-height: 50px;
max-height: 150px;
height: auto;
z-index: 0;
@@ -61,16 +69,6 @@
overflow: hidden;
position: relative;
- .link-count {
- opacity: 1;
- position: absolute;
- z-index: 1000;
- text-align: center;
- -webkit-transition: opacity 0.2s ease-in-out;
- -moz-transition: opacity 0.2s ease-in-out;
- -o-transition: opacity 0.2s ease-in-out;
- transition: opacity 0.2s ease-in-out;
- }
.link-extended {
// display: none;
@@ -112,7 +110,7 @@
.icon-icons,
.icon-live {
- height: 50px;
+ height: auto;
margin: auto;
overflow: hidden;
@@ -174,9 +172,7 @@
.searchBox-instances:active {
opacity: 1;
background: $lighter-alt-accent;
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
+ width:150px
}
.search-item:hover {
@@ -193,13 +189,10 @@
.searchBox-instances {
float: left;
opacity: 1;
- width: 150px;
+ width: 0px;
transition: all 0.2s ease;
color: black;
- transform-origin: top right;
- -webkit-transform: scale(0);
- -ms-transform: scale(0);
- transform: scale(0);
+ overflow: hidden;
}
@@ -208,7 +201,7 @@
}
.searchBox-placeholder {
- min-height: 70px;
+ min-height: 50px;
margin-left: 150px;
text-transform: uppercase;
text-align: left;
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index a7822ed46..b8cff16f2 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -213,15 +213,6 @@ export class SearchItem extends React.Component<SearchItemProps> {
@computed
get linkCount() { return LinkManager.Instance.getAllRelatedLinks(this.props.doc).length; }
- @computed
- get linkString(): string {
- let num = this.linkCount;
- if (num === 1) {
- return num.toString() + " link";
- }
- return num.toString() + " links";
- }
-
@action
pointerDown = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); }
@@ -290,7 +281,11 @@ export class SearchItem extends React.Component<SearchItemProps> {
<div className="search-item" onPointerDown={this.nextHighlight} onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc} id="result"
onClick={this.onClick}>
<div className="main-search-info">
- <div title="Drag as document" onPointerDown={this.onPointerDown} style={{ marginRight: "7px" }}> <FontAwesomeIcon icon="file" size="lg" /> </div>
+ <div title="Drag as document" onPointerDown={this.onPointerDown} style={{ marginRight: "7px" }}> <FontAwesomeIcon icon="file" size="lg" />
+ <div className="link-container item">
+ <div className="link-count" title={`${this.linkCount + " links"}`}>{this.linkCount}</div>
+ </div>
+ </div>
<div className="search-title-container">
<div className="search-title">{StrCast(this.props.doc.title)}</div>
<div className="search-highlighting">{this.props.highlighting.length ? "Matched fields:" + this.props.highlighting.join(", ") : this.props.lines.length ? this.props.lines[0] : ""}</div>
@@ -301,10 +296,6 @@ export class SearchItem extends React.Component<SearchItemProps> {
<div className="search-type" title="Click to Preview">{this.DocumentIcon()}</div>
<div className="search-label">{this.props.doc.type ? this.props.doc.type : "Other"}</div>
</div>
- <div className="link-container item">
- <div className="link-count">{this.linkCount}</div>
- <div className="link-extended">{this.linkString}</div>
- </div>
</div>
</div>
</div>
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index f3d5555ed..32da29932 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -97,6 +97,12 @@ export class CurrentUserUtils {
curPresentation.boxShadow = "0 0";
doc.curPresentation = curPresentation;
}
+ if (doc.searchBox === undefined) {
+ const searchBox = Docs.Create.QueryDocument({ title: "Searching" });
+ searchBox.boxShadow = "0 0";
+ searchBox.ignoreClick = true;
+ doc.searchBox = searchBox;
+ }
if (doc.sidebar === undefined) {
const sidebar = Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" });