aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts23
-rw-r--r--src/client/util/SearchUtil.ts4
-rw-r--r--src/client/views/SearchBox.scss72
-rw-r--r--src/client/views/SearchBox.tsx17
-rw-r--r--src/client/views/SearchItem.tsx155
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss2
6 files changed, 228 insertions, 45 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ab61b915c..2da4c8d88 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -41,6 +41,7 @@ var path = require('path');
export interface DocumentOptions {
x?: number;
y?: number;
+ type?: string;
ink?: InkField;
width?: number;
height?: number;
@@ -73,7 +74,7 @@ export namespace DocUtils {
let protoSrc = source.proto ? source.proto : source;
let protoTarg = target.proto ? target.proto : target;
UndoManager.RunInBatch(() => {
- let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 });
+ let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1, type: "link" });
//let linkDoc = new Doc;
linkDoc.proto!.title = "-link name-";
linkDoc.proto!.linkDescription = "";
@@ -154,54 +155,54 @@ export namespace Docs {
function CreateImagePrototype(): Doc {
let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("annotations"),
- { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0 });
+ { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0, type: "image" });
return imageProto;
}
function CreateHistogramPrototype(): Doc {
let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"),
- { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString() });
+ { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString(), type: "histogram" });
return histoProto;
}
function CreateIconPrototype(): Doc {
let iconProto = setupPrototypeOptions(iconProtoId, "ICON_PROTO", IconBox.LayoutString(),
- { x: 0, y: 0, width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE) });
+ { x: 0, y: 0, width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE), type: "icon" });
return iconProto;
}
function CreateTextPrototype(): Doc {
let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150, backgroundColor: "#f1efeb" });
+ { x: 0, y: 0, width: 300, height: 150, backgroundColor: "#f1efeb", type: "text" });
return textProto;
}
function CreatePdfPrototype(): Doc {
let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
- { x: 0, y: 0, nativeWidth: 1200, width: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1 });
+ { x: 0, y: 0, nativeWidth: 1200, width: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1, type: "pdf" });
return pdfProto;
}
function CreateWebPrototype(): Doc {
let webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 300 });
+ { x: 0, y: 0, width: 300, height: 300, type: "web" });
return webProto;
}
function CreateCollectionPrototype(): Doc {
let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("data"),
- { panX: 0, panY: 0, scale: 1, width: 500, height: 500 });
+ { panX: 0, panY: 0, scale: 1, width: 500, height: 500, type: "collection" });
return collProto;
}
function CreateKVPPrototype(): Doc {
let kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150 });
+ { x: 0, y: 0, width: 300, height: 150, type: "kvp" });
return kvpProto;
}
function CreateVideoPrototype(): Doc {
let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("annotations"),
- { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0 });
+ { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0, type: "video" });
return videoProto;
}
function CreateAudioPrototype(): Doc {
let audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150 });
+ { x: 0, y: 0, width: 300, height: 150, type: "audio" });
return audioProto;
}
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 28ec8ca14..27d27a3b8 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -23,4 +23,8 @@ export namespace SearchUtil {
return Search(`proto_i:"${protoId}"`, true);
// return Search(`{!join from=id to=proto_i}id:${protoId}`, true);
}
+
+ export async function GetViewsOfDocument(doc: Doc): Promise<Doc[]> {
+ return Search(`proto_i:"${doc[Id]}"`, true);
+ }
} \ No newline at end of file
diff --git a/src/client/views/SearchBox.scss b/src/client/views/SearchBox.scss
index b38e6091d..c8f139144 100644
--- a/src/client/views/SearchBox.scss
+++ b/src/client/views/SearchBox.scss
@@ -48,7 +48,6 @@
.filter-form {
background: $dark-color;
height: 400px;
- width: 400px;
position: relative;
right: 1px;
color: $light-color;
@@ -71,15 +70,16 @@
top: 300px;
display: flex;
flex-direction: column;
+ margin-right: 72px;
.search-item {
+ position: relative;
+ z-index: 1000;
+ pointer-events: auto;
width: 500px;
- height: 50px;
background: $light-color-secondary;
- display: flex;
justify-content: space-between;
align-items: center;
- transition: all 0.1s;
border-width: 0.11px;
border-style: none;
border-color: $intermediate-color;
@@ -87,6 +87,19 @@
padding: 10px;
white-space: nowrap;
font-size: 13px;
+ height: 70px;
+ }
+
+ .search-info {
+ display: flex;
+ justify-content: flex-end;
+ width: 100%;
+ }
+
+ .main-search-info {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
}
.search-item:hover {
@@ -98,5 +111,56 @@
text-transform: uppercase;
text-align: left;
width: 8vw;
+ font-weight: bold;
+ }
+
+ .more-search-info {
+ text-align: left;
+ }
+
+ .link-count {
+ height: 25px;
+ width: 25px;
+ border-radius: 50%;
+ background: $dark-color;
+ color: $light-color-secondary;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-right: 10px;
+ }
+
+ .search-type {
+ width: 25PX;
+ height: 25PX;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+
+ .searchBox-instances {
+ display: block;
+ background: $light-color-secondary;
+ opacity: 0;
+ width: 150px;
+ transition: all 0.2s ease;
+ color: black;
+ transform: translateX(150px);
+ }
+
+
+ .search-overview {
+ display: flex;
+ // float: left;
+ justify-content: flex-end;
+ height: 70px;
+ }
+
+ .search-overview:hover {
+ .searchBox-instances {
+ transform: translateX(0px);
+ opacity: 1;
+ }
}
} \ No newline at end of file
diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx
index 63d2065e2..0fd3c0904 100644
--- a/src/client/views/SearchBox.tsx
+++ b/src/client/views/SearchBox.tsx
@@ -22,6 +22,7 @@ import { SetupDrag } from '../util/DragManager';
import { Docs } from '../documents/Documents';
import { RouteStore } from '../../server/RouteStore';
import { NumCast } from '../../new_fields/Types';
+import { SearchUtil } from '../util/SearchUtil';
library.add(faSearch);
library.add(faObjectGroup);
@@ -37,6 +38,7 @@ export class SearchBox extends React.Component {
@observable
private _results: Doc[] = [];
+
@action.bound
onChange(e: React.ChangeEvent<HTMLInputElement>) {
this.searchString = e.target.value;
@@ -72,6 +74,7 @@ export class SearchBox extends React.Component {
}
return docs;
}
+
public static async convertDataUri(imageUri: string, returnedFilename: string) {
try {
let posting = DocServer.prepend(RouteStore.dataUriToImage);
@@ -169,6 +172,18 @@ export class SearchBox extends React.Component {
return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this.searchString}"` });
}
+ @action
+ getViews = async (doc: Doc) => {
+ console.log("getting view")
+ const results = await SearchUtil.GetViewsOfDocument(doc);
+ let toReturn: Doc[] = [];
+ await runInAction(() => {
+ toReturn = results;
+ });
+ return toReturn;
+ }
+
+
// 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}
@@ -183,7 +198,7 @@ export class SearchBox extends React.Component {
<input value={this.searchString} onChange={this.onChange} type="text" placeholder="Search..."
className="searchBox-barChild searchBox-input" onKeyPress={this.enter}
style={{ width: this._resultsOpen ? "500px" : undefined }} />
- {/* <button className="searchBox-barChild searchBox-filter" onClick={this.toggleFilterDisplay}>Filter</button> */}
+ <button className="searchBox-barChild searchBox-filter" onClick={this.toggleFilterDisplay}>Filter</button>
{/* <FontAwesomeIcon icon="search" size="lg" className="searchBox-barChild searchBox-submit" /> */}
</div>
{this._resultsOpen ? (
diff --git a/src/client/views/SearchItem.tsx b/src/client/views/SearchItem.tsx
index 6901f60da..ae9bc350f 100644
--- a/src/client/views/SearchItem.tsx
+++ b/src/client/views/SearchItem.tsx
@@ -1,14 +1,27 @@
import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Cast, NumCast } from "../../new_fields/Types";
+import { FieldView, FieldViewProps } from './nodes/FieldView';
+import { computed, observable, action, runInAction } from "mobx";
+import { IconField } from "../../new_fields/IconField";
+import { listSpec } from "../../new_fields/Schema";
+import { Transform } from "../util/Transform";
+import { ObjectField } from "../../new_fields/ObjectField";
+import { RichTextField } from "../../new_fields/RichTextField";
import { Doc } from "../../new_fields/Doc";
import { DocumentManager } from "../util/DocumentManager";
import { SetupDrag } from "../util/DragManager";
+import { SearchUtil } from "../util/SearchUtil";
+import { Id } from "../../new_fields/FieldSymbols";
+import { CollectionDockingView } from "./collections/CollectionDockingView";
+import { observer } from "mobx-react";
+import { CollectionViewType } from "./collections/CollectionBaseView";
-
-export interface SearchProps {
+export interface SearchItemProps {
doc: Doc;
+ // addDocTab(doc: Doc, location: string): void
}
library.add(faCaretUp);
@@ -16,33 +29,87 @@ library.add(faObjectGroup);
library.add(faStickyNote);
library.add(faFilePdf);
library.add(faFilm);
+library.add(faMusic);
+library.add(faLink);
+library.add(faChartBar);
+library.add(faGlobeAsia);
-export class SearchItem extends React.Component<SearchProps> {
+@observer
+export class SelectorContextMenu extends React.Component<SearchItemProps> {
+ @observable private _docs: { col: Doc, target: Doc }[] = [];
+ @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
- onClick = () => {
- DocumentManager.Instance.jumpToDocument(this.props.doc);
+ constructor(props: SearchItemProps) {
+ super(props);
+
+ this.fetchDocuments();
}
- //needs help
- // @computed get layout(): string { const field = Cast(this.props.doc[fieldKey], IconField); return field ? field.icon : "<p>Error loading icon data</p>"; }
+ async fetchDocuments() {
+ console.log("fetching");
+ let aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc);
+ const docs = await SearchUtil.Search(`data_l:"${this.props.doc[Id]}"`, true);
+ const map: Map<Doc, Doc> = new Map;
+ const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search(`data_l:"${doc[Id]}"`, true)));
+ allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
+ docs.forEach(doc => map.delete(doc));
+ runInAction(() => {
+ console.log("action running")
+ this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: this.props.doc }));
+ this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target }));
+ });
+ }
+ getOnClick({ col, target }: { col: Doc, target: Doc }) {
+ return () => {
+ console.log("returning!")
+ // col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+ // if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+ // const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2;
+ // const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2;
+ // col.panX = newPanX;
+ // col.panY = newPanY;
+ // }
+ // this.props.addDocTab(col, "inTab");
+ };
+ }
- public static DocumentIcon(layout: string) {
- let button = layout.indexOf("PDFBox") !== -1 ? faFilePdf :
- layout.indexOf("ImageBox") !== -1 ? faImage :
- layout.indexOf("Formatted") !== -1 ? faStickyNote :
- layout.indexOf("Video") !== -1 ? faFilm :
- layout.indexOf("Collection") !== -1 ? faObjectGroup :
- faCaretUp;
- return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />;
+ render() {
+ return (
+ <>
+ <p>Contexts:</p>
+ {this._docs.map(doc => <p><a onClick={this.getOnClick(doc)}>{doc.col.title}</a></p>)}
+ {this._otherDocs.length ? <hr></hr> : null}
+ {this._otherDocs.map(doc => <p><a onClick={this.getOnClick(doc)}>{doc.col.title}</a></p>)}
+ </>
+ );
}
- onPointerEnter = (e: React.PointerEvent) => {
- this.props.doc.libraryBrush = true;
- Doc.SetOnPrototype(this.props.doc, "protoBrush", true);
+}
+
+@observer
+export class SearchItem extends React.Component<SearchItemProps> {
+
+ @observable _selected: boolean = false;
+ @observable hover = false;
+
+ onClick = () => {
+ DocumentManager.Instance.jumpToDocument(this.props.doc);
}
- onPointerLeave = (e: React.PointerEvent) => {
- this.props.doc.libraryBrush = false;
- Doc.SetOnPrototype(this.props.doc, "protoBrush", false);
+
+ public DocumentIcon() {
+ let layoutresult = Cast(this.props.doc.type, "string", "");
+
+ let button = layoutresult.indexOf("pdf") !== -1 ? faFilePdf :
+ layoutresult.indexOf("image") !== -1 ? faImage :
+ layoutresult.indexOf("text") !== -1 ? faStickyNote :
+ layoutresult.indexOf("video") !== -1 ? faFilm :
+ layoutresult.indexOf("collection") !== -1 ? faObjectGroup :
+ layoutresult.indexOf("audio") !== -1 ? faMusic :
+ layoutresult.indexOf("link") !== -1 ? faLink :
+ layoutresult.indexOf("histogram") !== -1 ? faChartBar :
+ layoutresult.indexOf("web") !== -1 ? faGlobeAsia :
+ faCaretUp;
+ return <FontAwesomeIcon icon={button} size="2x" />;
}
collectionRef = React.createRef<HTMLDivElement>();
@@ -55,14 +122,46 @@ export class SearchItem extends React.Component<SearchProps> {
return Doc.MakeAlias(doc);
}
}
+
+ linkCount = () => {
+ return Cast(this.props.doc.linkedToDocs, listSpec(Doc), []).length + Cast(this.props.doc.linkedFromDocs, listSpec(Doc), []).length;
+ }
+
+ // @action
+ // onMouseLeave = () => {
+ // this.hover = false;
+ // }
+
+ // @action
+ // onMouseEnter = () => {
+ // this.hover = true;
+ // }
+
render() {
return (
- <div className="search-item" ref={this.collectionRef} id="result"
- onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}
- onClick={this.onClick} onPointerDown={SetupDrag(this.collectionRef, this.startDocDrag)} >
- <div className="search-title" id="result" >title: {this.props.doc.title}</div>
- {/* <div className="search-type" id="result" >Type: {this.props.doc.layout}</div> */}
- {/* <div className="search-type" >{SearchItem.DocumentIcon(this.layout)}</div> */}
+ <div className="search-overview">
+ {/* onMouseEnter={this.onMouseEnter}
+ onMouseLeave={this.onMouseLeave}> */}
+ <div className="searchBox-instances">
+ <SelectorContextMenu {...this.props} />
+ </div>
+ {/* {this.hover ? (
+ <div className="searchBox-instances">
+ <SelectorContextMenu {...this.props} />
+ </div>
+ ) : null} */}
+ <div className="search-item" ref={this.collectionRef} id="result" onClick={this.onClick} onPointerDown={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-count">{this.linkCount()}</div>
+ <div className="search-type" >{this.DocumentIcon()}</div>
+ </div>
+ </div>
+ <div className="more-search-info">
+ <div className="found">Where Found: (i.e. title, body, etc)</div>
+ </div>
+ </div>
</div>
);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss
index 30e158603..a80e09fa8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss
@@ -1,4 +1,4 @@
-.collectionfreeformlinksview-svgCanvas{
+p.collectionfreeformlinksview-svgCanvas{
transform: translate(-10000px,-10000px);
position: absolute;
top: 0;