aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/search/CheckBox.scss34
-rw-r--r--src/client/views/search/CheckBox.tsx40
-rw-r--r--src/client/views/search/IconBar.scss7
-rw-r--r--src/client/views/search/IconBar.tsx145
-rw-r--r--src/client/views/search/SearchBox.tsx31
-rw-r--r--src/client/views/search/SearchItem.scss13
-rw-r--r--src/client/views/search/SearchItem.tsx15
-rw-r--r--src/client/views/search/minus.svg5
-rw-r--r--src/client/views/search/plus.svg5
9 files changed, 249 insertions, 46 deletions
diff --git a/src/client/views/search/CheckBox.scss b/src/client/views/search/CheckBox.scss
new file mode 100644
index 000000000..8eee9176b
--- /dev/null
+++ b/src/client/views/search/CheckBox.scss
@@ -0,0 +1,34 @@
+@import "../globalCssVariables";
+
+.checkbox {
+ display: flex;
+
+ .check-box {
+ z-index: 900;
+ position: relative;
+ height: 20px;
+ width: 20px;
+ overflow: visible;
+ background-color: transparent;
+ border-style: solid;
+ border-color: $alt-accent;
+ border-width: 2px;
+ }
+
+ .box:hover {
+ background-color: $intermediate-color;
+ }
+
+ .checkmark {
+ z-index: 1000;
+ position: relative;
+ fill-opacity: 0;
+ stroke-width: 4px;
+ stroke: white;
+ }
+
+}
+
+.checkbox-title {
+ text-transform: uppercase;
+} \ No newline at end of file
diff --git a/src/client/views/search/CheckBox.tsx b/src/client/views/search/CheckBox.tsx
new file mode 100644
index 000000000..8b5f7d7c1
--- /dev/null
+++ b/src/client/views/search/CheckBox.tsx
@@ -0,0 +1,40 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { observable, action, runInAction } from 'mobx';
+import "./CheckBox.scss";
+
+interface CheckBoxProps {
+ originalStatus: boolean;
+ updateStatus(newStatus: boolean): void;
+ title: string;
+}
+
+@observer
+export class CheckBox extends React.Component<CheckBoxProps>{
+ @observable _status: boolean;
+
+ constructor(props: CheckBoxProps) {
+ super(props);
+
+ this._status = this.props.originalStatus;
+ }
+
+ onClick = () => {
+ this._status = !this._status;
+ this.props.updateStatus(this._status);
+ }
+
+ render() {
+ return (
+ <div className="checkbox">
+ <div className="check-box">
+ <svg viewBox="10 10 20 20">
+ <path className="checkmark" d="M14.1 27.2l7.1 7.2 16.7-16.8" />
+ </svg>
+ </div>
+ <div className="checkbox-title">{this.props.title}</div>
+ </div>
+ )
+ }
+
+} \ No newline at end of file
diff --git a/src/client/views/search/IconBar.scss b/src/client/views/search/IconBar.scss
index e08e09702..3d38b7ac3 100644
--- a/src/client/views/search/IconBar.scss
+++ b/src/client/views/search/IconBar.scss
@@ -32,7 +32,8 @@
font-size: 2em;
}
-.type-icon.selected {
+
+.type-icon.add.selected {
background-color: $alt-accent;
opacity: 1;
}
@@ -47,6 +48,10 @@
width: 28px;
}
+.filter-description{
+ text-transform: capitalize;
+}
+
.type-icon.filter:hover {
transform: scale(1.1);
background-color: $alt-accent;
diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx
index 8fb7d0959..ba337dcab 100644
--- a/src/client/views/search/IconBar.tsx
+++ b/src/client/views/search/IconBar.tsx
@@ -9,7 +9,7 @@ import { faSearch, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMu
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import * as _ from "lodash";
-var classNames = require('classnames');
+import $ from 'jquery';
library.add(faSearch);
library.add(faObjectGroup);
@@ -25,7 +25,8 @@ library.add(faBan);
export interface IconBarProps {
updateIcon(icons: string[]): void;
- getIcons(): string[];
+ getSelectedTypes(): string[];
+ getRemovedTypes(): string[];
}
@observer
@@ -45,13 +46,45 @@ export class IconBar extends React.Component<IconBarProps> {
@observable webRef = React.createRef<HTMLDivElement>();
@observable allRefs: React.RefObject<HTMLDivElement>[] = [this.colRef, this.imgRef, this.textRef, this.pdfRef, this.vidRef, this.audioRef, this.linkRef, this.histRef, this.webRef];
- @observable originalFilteredNodes: string[] = this.props.getIcons();
+ @observable originalSelectedNodes: string[] = this.props.getSelectedTypes();
+ @observable originalRemovedNodes: string[] = this.props.getSelectedTypes();
+
+ @observable removeType: boolean = false;
constructor(props: IconBarProps){
super(props);
IconBar.Instance = this;
}
+ @action
+ downKeyHandler = (e: KeyboardEvent) => {
+ if (e.key !== "Control") return;
+ this.removeType = true;
+ e.preventDefault();
+ e.stopPropagation();
+
+ }
+
+ @action
+ upKeyHandler = (e: KeyboardEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ this.removeType = false;
+ }
+
+ componentWillMount() {
+ document.removeEventListener("keydown", this.downKeyHandler);
+ document.addEventListener("keydown", this.downKeyHandler);
+ document.removeEventListener("keyup", this.upKeyHandler);
+ document.addEventListener("keyup", this.upKeyHandler);
+ }
+
+ componentWillUnMount() {
+ document.removeEventListener("keyup", this.upKeyHandler);
+ document.removeEventListener("keydown", this.downKeyHandler);
+ }
+
+
componentDidMount = () => {
//i KNOW this is bad i just can't get this to re render eeeeeeeek
this.forceUpdate();
@@ -113,25 +146,40 @@ export class IconBar extends React.Component<IconBarProps> {
this.allRefs.forEach(element => {
if (element.current) {
element.current.setAttribute("data-selected", "false");
+ element.current.setAttribute("data-removed", "false");
}
});
}
@action.bound
- alternateRef(ref: any) {
+ alternateSelectedRef(ref: any) {
if (ref.getAttribute("data-selected") === "true") {
ref.setAttribute("data-selected", "false");
}
else {
ref.setAttribute("data-selected", "true");
+ ref.setAttribute("data-removed", "false")
}
}
+ //TODO: this needs help
+ @action.bound
+ alternateRemovedRef(ref: any) {
+ if (ref.getAttribute("data-removed") === "true") {
+ ref.setAttribute("data-removed", "false");
+ }
+ else {
+ ref.setAttribute("data-removed", "true");
+ ref.setAttribute("data-selected", "false")
+ }
+ }
+
+ //TODO: this needs help
@action.bound
onClick = (value: string) => {
- let icons: string[] = this.props.getIcons();
+ let icons: string[] = this.props.getSelectedTypes();
let ref = this.getRef(value);
- this.alternateRef(ref);
+ this.alternateSelectedRef(ref);
if (value === DocTypes.NONE) {
icons = [];
// if its none, change the color of all the other circles
@@ -164,107 +212,148 @@ export class IconBar extends React.Component<IconBarProps> {
}
}
- getInitialStatus = (type: string) => {
- if (this.originalFilteredNodes.includes(type)) {
+ //checks attribues of ref to return whether or not a type should be specifically included in the search
+ @action.bound
+ getInitialSelectedStatus = (type: string) => {
+ if (this.originalSelectedNodes.includes(type)) {
return "true";
}
return "false";
}
+ //checks attributes of ref to return whether or not it should be excluded from search results
+ @action.bound
+ isRemoved = (ref: React.RefObject<HTMLDivElement>) => {
+ if(ref.current){
+ if(ref.current.getAttribute("data-removed") === "true") {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ //gets status upon mounting if a doc type should be removed from the results
+ @action.bound
+ getInitialRemovedStatus = (type: string) => {
+ if (this.originalRemovedNodes.includes(type)) {
+ return "true";
+ }
+ return "false";
+ }
+
+ @action.bound
+ changeCursor() {
+ if(!this.removeType)
+ {document.body.style.cursor = 'url(".\noun_Plus_2224963.svg")';}
+ else{
+ {document.body.style.cursor = 'url(".\noun_Plus_2224963.svg")';}
+ }
+ }
+
render() {
return (
<div>
<div className="filter icon-title">Filter by type of node</div>
- <div className="filter icon-bar">
+ <div className="filter icon-bar" onMouseOver={this.changeCursor}>
<div className="filter type-outer">
<div className={"type-icon none not-selected"}
ref={this.noneRef}
data-selected={"false"}
+ data-removed = {"false"}
onClick={() => { this.onClick(DocTypes.NONE); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: -2 }} icon={faBan} />
</div>
<div className="filter-description">Clear</div>
</div>
<div className="type-outer">
- <div className={"type-icon filter " + (this.isRefSelected(this.pdfRef) ? "selected" : "not-selected")}
+ <div className={"type-icon filter " + (this.isRemoved(this.pdfRef) ? "add" : "remove") + (this.isRefSelected(this.pdfRef) ? "selected" : "not-selected")}
ref={this.pdfRef}
- data-selected={this.getInitialStatus(DocTypes.PDF)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.PDF)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.PDF)}
onClick={() => { this.onClick(DocTypes.PDF); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 0 }} icon={faFilePdf} />
</div>
- <div className="filter-description">PDF</div>
+ <div className="filter-description">{DocTypes.PDF}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.histRef) ? "selected" : "not-selected")}
ref={this.histRef}
- data-selected={this.getInitialStatus(DocTypes.HIST)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.HIST)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.HIST)}
onClick={() => { this.onClick(DocTypes.HIST); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 1 }} icon={faChartBar} />
</div>
- <div className="filter-description">Histogram</div>
+ <div className="filter-description">{DocTypes.HIST}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.colRef) ? "selected" : "not-selected")}
ref={this.colRef}
- data-selected={this.getInitialStatus(DocTypes.COL)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.COL)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.COL)}
onClick={() => { this.onClick(DocTypes.COL); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 2 }} icon={faObjectGroup} />
</div>
- <div className="filter-description">Collection</div>
+ <div className="filter-description">{DocTypes.COL}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.imgRef) ? "selected" : "not-selected")}
ref={this.imgRef}
- data-selected={this.getInitialStatus(DocTypes.IMG)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.IMG)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.IMG)}
onClick={() => { this.onClick(DocTypes.IMG); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 3 }} icon={faImage} />
</div>
- <div className="filter-description">Image</div>
+ <div className="filter-description">{DocTypes.IMG}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.vidRef) ? "selected" : "not-selected")}
ref={this.vidRef}
- data-selected={this.getInitialStatus(DocTypes.VID)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.VID)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.VID)}
onClick={() => { this.onClick(DocTypes.VID); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 4 }} icon={faFilm} />
</div>
- <div className="filter-description">Video</div>
+ <div className="filter-description">{DocTypes.VID}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.webRef) ? "selected" : "not-selected")}
ref={this.webRef}
- data-selected={this.getInitialStatus(DocTypes.WEB)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.WEB)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.WEB)}
onClick={() => { this.onClick(DocTypes.WEB); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 5 }} icon={faGlobeAsia} />
</div>
- <div className="filter-description">Web</div>
+ <div className="filter-description">{DocTypes.WEB}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.linkRef) ? "selected" : "not-selected")}
ref={this.linkRef}
- data-selected={this.getInitialStatus(DocTypes.LINK)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.LINK)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.LINK)}
onClick={() => { this.onClick(DocTypes.LINK); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 6 }} icon={faLink} />
</div>
- <div className="filter-description">Link</div>
+ <div className="filter-description">{DocTypes.LINK}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.audioRef) ? "selected" : "not-selected")}
ref={this.audioRef}
- data-selected={this.getInitialStatus(DocTypes.AUDIO)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.AUDIO)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.AUDIO)}
onClick={() => { this.onClick(DocTypes.AUDIO); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 7 }} icon={faMusic} />
</div>
- <div className="filter-description">Audio</div>
+ <div className="filter-description">{DocTypes.AUDIO}</div>
</div>
<div className="type-outer">
<div className={"type-icon filter " + (this.isRefSelected(this.textRef) ? "selected" : "not-selected")}
ref={this.textRef}
- data-selected={this.getInitialStatus(DocTypes.TEXT)}
+ data-selected={this.getInitialSelectedStatus(DocTypes.TEXT)}
+ data-removed = {this.getInitialRemovedStatus(DocTypes.TEXT)}
onClick={() => { this.onClick(DocTypes.TEXT); }}>
<FontAwesomeIcon className="fontawesome-icon filter" style={{ order: 8 }} icon={faStickyNote} />
</div>
- <div className="filter-description">Text</div>
+ <div className="filter-description">{DocTypes.TEXT}</div>
</div>
</div>
</div>
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 622fa27f0..fc54d87e2 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -23,7 +23,11 @@ import { findDOMNode } from 'react-dom';
import { ToggleBar } from './ToggleBar';
import { IconBar } from './IconBar';
import { type } from 'os';
+import { CheckBox } from './CheckBox';
+export enum Keys {
+ TITLE = "title",
+}
@observer
export class SearchBox extends React.Component {
@@ -64,8 +68,8 @@ export class SearchBox extends React.Component {
@action.bound
onChange(e: React.ChangeEvent<HTMLInputElement>) {
this._searchString = e.target.value;
-
- if(this._searchString === ""){
+
+ if (this._searchString === "") {
this._results = [];
this._openNoResults = false;
}
@@ -86,12 +90,13 @@ export class SearchBox extends React.Component {
query = newWords.join(" ");
}
- if(query === ""){
+ if (query === "") {
results = [];
}
- else{
+ else {
//gets json result into a list of documents that can be used
- results = await this.getResults(query);}
+ results = await this.getResults(query);
+ }
runInAction(() => {
this._resultsOpen = true;
@@ -250,6 +255,10 @@ export class SearchBox extends React.Component {
this._pointerTime = e.timeStamp;
}
+ updateCheckStatus(newStat: boolean) {
+ console.log("updating!")
+ }
+
// Useful queries:
// Delegates of a document: {!join from=id to=proto_i}id:{protoId}
// Documents in a collection: {!join from=data_l to=id}id:{collectionProtoId}
@@ -268,10 +277,10 @@ export class SearchBox extends React.Component {
</div>
{this._resultsOpen ? (
<div className="searchBox-results">
- { (this._results.length !== 0) ? (
+ {(this._results.length !== 0) ? (
this._results.map(result => <SearchItem doc={result} key={result[Id]} />)
- ) :
- this._openNoResults ? (<div className = "no-result">No Search Results</div>) : null }
+ ) :
+ this._openNoResults ? (<div className="no-result">No Search Results</div>) : null}
</div>
) : undefined}
@@ -285,16 +294,16 @@ export class SearchBox extends React.Component {
<ToggleBar originalStatus={this._wordStatus} optionOne={"Include Any Keywords"} optionTwo={"Include All Keywords"} changeStatus={this.handleWordQueryChange} />
</div>
<div className="type-of-node filter-div">
- <IconBar updateIcon={this.updateIcon} getIcons={this.getIcons} />
+ <IconBar updateIcon={this.updateIcon} getSelectedTypes={this.getIcons} />
</div>
<div className="filter-collection filter-div">
temp for filtering by collection
</div>
<div className="where-in-doc filter-div">
- temp for filtering where in doc the keywords are found
+ <CheckBox originalStatus={true} updateStatus={this.updateCheckStatus} title={Keys.TITLE} />
</div>
</div>
- <button className="reset-filter" onClick = {this.resetFilters}>Reset Filters</button>
+ <button className="reset-filter" onClick={this.resetFilters}>Reset Filters</button>
</div>
) : undefined}
</div>
diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss
index 5afb69164..630d27cc3 100644
--- a/src/client/views/search/SearchItem.scss
+++ b/src/client/views/search/SearchItem.scss
@@ -131,4 +131,17 @@
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
+}
+
+.search-label{
+ text-transform: capitalize;
+ opacity: 0;
+ -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;
+}
+
+.search-type:hover +.search-label{
+ opacity: 1;
} \ No newline at end of file
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index fb0eade4b..c19057819 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -152,21 +152,24 @@ export class SearchItem extends React.Component<SearchItemProps> {
render() {
return (
- <div className="search-overview" onPointerDown = {this.pointerDown}>
- <div className="search-item" onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc} ref={this.collectionRef} id="result" onClick={this.onClick} onPointerDown={ () => {
+ <div className="search-overview" onPointerDown={this.pointerDown}>
+ <div className="search-item" onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc} ref={this.collectionRef} id="result" onClick={this.onClick} onPointerDown={() => {
this.pointerDown;
- SetupDrag(this.collectionRef, this.startDocDrag);}} >
+ SetupDrag(this.collectionRef, this.startDocDrag);
+ }} >
<div className="main-search-info">
<div className="search-title" id="result" >{this.props.doc.title}</div>
<div className="search-info">
<div className="link-container item">
<div className="link-count">{this.linkCount}</div>
- <div className = "link-extended">{this.linkString}</div>
+ <div className="link-extended">{this.linkString}</div>
+ </div>
+ <div className="icon">
+ <div className="search-type" >{this.DocumentIcon}</div>
+ <div className="search-label">{this.props.doc.type}</div>
</div>
- <div className="search-type" >{this.DocumentIcon}</div>
</div>
</div>
- <div className="found">Where Found: (i.e. title, body, etc)</div>
</div>
<div className="searchBox-instances">
<SelectorContextMenu {...this.props} />
diff --git a/src/client/views/search/minus.svg b/src/client/views/search/minus.svg
new file mode 100644
index 000000000..63cd809f6
--- /dev/null
+++ b/src/client/views/search/minus.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" version="1.1" style="shape-rendering:geometricPrecision;text-rendering:geometricPrecision;image-rendering:optimizeQuality;" viewBox="0 0 738 922.5" x="0px" y="0px" fill-rule="evenodd" clip-rule="evenodd"><defs><style type="text/css">
+
+ .fil0 {fill:black}
+
+ </style></defs><g><path class="fil0" d="M369 0c203,0 369,165 369,369 0,203 -166,369 -369,369 -204,0 -369,-166 -369,-369 0,-204 165,-369 369,-369zm-197 305l394 0c35,0 64,29 64,64 0,35 -29,64 -64,64l-394 0c-36,0 -65,-29 -65,-64 0,-36 29,-64 65,-64z"/></g><text x="0" y="753" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by Manaqib S</text><text x="0" y="758" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg> \ No newline at end of file
diff --git a/src/client/views/search/plus.svg b/src/client/views/search/plus.svg
new file mode 100644
index 000000000..deb855637
--- /dev/null
+++ b/src/client/views/search/plus.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" version="1.1" style="shape-rendering:geometricPrecision;text-rendering:geometricPrecision;image-rendering:optimizeQuality;" viewBox="0 0 443 553.75" x="0px" y="0px" fill-rule="evenodd" clip-rule="evenodd"><defs><style type="text/css">
+
+ .fil0 {fill:black}
+
+ </style></defs><g><path class="fil0" d="M221 0c123,0 222,99 222,221 0,123 -99,222 -222,222 -122,0 -221,-99 -221,-222 0,-122 99,-221 221,-221zm0 46c18,0 33,15 33,33l0 109 109 0c19,0 34,15 34,33 0,18 -15,33 -34,33l-109 0 0 109c0,19 -15,34 -33,34 -18,0 -33,-15 -33,-34l0 -109 -109 0c-18,0 -33,-15 -33,-33 0,-18 15,-33 33,-33l109 0 0 -109c0,-18 15,-33 33,-33z"/></g><text x="0" y="458" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by mohkamil</text><text x="0" y="463" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg> \ No newline at end of file