aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormonikahedman <monika_hedman@brown.edu>2019-08-21 15:08:39 -0400
committermonikahedman <monika_hedman@brown.edu>2019-08-21 15:08:39 -0400
commit5c9f40006aa157c58ec40828ebd4845c16daa8af (patch)
tree0df2f2754f2dcda9381a71cdf93eb78181a860fe /src
parent11d2743b553da47da88e77de1ac758e16e09b3e0 (diff)
start of making link follow
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/DocumentTypes.ts1
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/views/MainView.tsx11
-rw-r--r--src/client/views/linking/LinkFollowBox.scss6
-rw-r--r--src/client/views/linking/LinkFollowBox.tsx148
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx12
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx4
7 files changed, 179 insertions, 7 deletions
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 1578e49fe..381981e1b 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -19,4 +19,5 @@ export enum DocumentType {
YOUTUBE = "youtube",
DRAGBOX = "dragbox",
PRES = "presentation",
+ LINKFOLLOW = "linkfollow",
} \ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 47df17329..cd612aaa9 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -45,6 +45,7 @@ import { PresBox } from "../views/nodes/PresBox";
import { ComputedField } from "../../new_fields/ScriptField";
import { ProxyField } from "../../new_fields/Proxy";
import { DocumentType } from "./DocumentTypes";
+import { LinkFollowBox } from "../views/linking/LinkFollowBox";
//import { PresBox } from "../views/nodes/PresBox";
//import { PresField } from "../../new_fields/PresField";
var requestImageSize = require('../util/request-image-size');
@@ -169,6 +170,9 @@ export namespace Docs {
[DocumentType.DRAGBOX, {
layout: { view: DragBox },
options: { width: 40, height: 40 },
+ }],
+ [DocumentType.LINKFOLLOW, {
+ layout: { view: LinkFollowBox }
}]
]);
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f28844009..f3c8a176c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -40,6 +40,7 @@ import { PreviewCursor } from './PreviewCursor';
import { FilterBox } from './search/FilterBox';
import PresModeMenu from './presentationview/PresentationModeMenu';
import { PresBox } from './nodes/PresBox';
+import { LinkFollowBox } from './linking/LinkFollowBox';
@observer
export class MainView extends React.Component {
@@ -55,6 +56,8 @@ export class MainView extends React.Component {
public overlayTimeout: NodeJS.Timeout | undefined;
+ @observable private _linkFollowBox = false;
+
public initiateDictationFade = () => {
let duration = DictationManager.Commands.dictationFadeDuration;
this.overlayTimeout = setTimeout(() => {
@@ -498,6 +501,12 @@ export class MainView extends React.Component {
this._colorPickerDisplay = close ? false : !this._colorPickerDisplay;
}
+ @action
+ toggleLinkFollowBox = () => {
+ console.log("toggling link editor")
+ this._linkFollowBox = !this._linkFollowBox;
+ }
+
/* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */
@computed
get miscButtons() {
@@ -506,6 +515,7 @@ export class MainView extends React.Component {
return [
this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <FilterBox /> </div> : null,
<div className="main-buttonDiv" key="logout" style={{ bottom: '0px', right: '1px', position: 'absolute' }} ref={logoutRef}>
+ <button onClick={this.toggleLinkFollowBox}>Open Link Editor</button>
<button onClick={() => window.location.assign(Utils.prepend(RouteStore.logout))}>Log Out</button></div>
];
@@ -564,6 +574,7 @@ export class MainView extends React.Component {
<PDFMenu />
<MainOverlayTextBox firstinstance={true} />
<OverlayView />
+ {/* <LinkFollowBox /> */}
</div >
);
}
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
new file mode 100644
index 000000000..c764b002f
--- /dev/null
+++ b/src/client/views/linking/LinkFollowBox.scss
@@ -0,0 +1,6 @@
+@import "../globalCssVariables";
+
+.linkFollowBox-main {
+ position: absolute;
+ background: $main-accent;
+} \ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 061a4fa93..7fc4449d3 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -2,9 +2,157 @@ import { observable, computed, action, trace } from "mobx";
import React = require("react");
import { observer } from "mobx-react";
import { FieldViewProps, FieldView } from "../nodes/FieldView";
+import { Doc } from "../../../new_fields/Doc";
+import { undoBatch } from "../../util/UndoManager";
+import { NumCast, FieldValue, Cast } from "../../../new_fields/Types";
+import { CollectionViewType } from "../collections/CollectionBaseView";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { SelectionManager } from "../../util/SelectionManager";
+import { DocumentManager } from "../../util/DocumentManager";
@observer
export class LinkFollowBox extends React.Component<FieldViewProps> {
public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
+ public static Instance: LinkFollowBox;
+ //set this to be the default link behavior, can be any of the above
+
+ unhighlight = () => {
+ Doc.UnhighlightAll();
+ document.removeEventListener("pointerdown", this.unhighlight);
+ }
+
+ @action
+ highlightDoc = (destinationDoc: Doc) => {
+ document.removeEventListener("pointerdown", this.unhighlight);
+ Doc.HighlightDoc(destinationDoc);
+ window.setTimeout(() => {
+ document.addEventListener("pointerdown", this.unhighlight);
+ }, 10000);
+ }
+
+ // NOT TESTED
+ // col = collection the doc is in
+ // target = the document to center on
+ @undoBatch
+ openLinkColRight = (destinationDoc: Doc, col: Doc) => {
+ col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+ if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+ const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+ const newPanY = NumCast(destinationDoc.y) + NumCast(destinationDoc.height) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+ col.panX = newPanX;
+ col.panY = newPanY;
+ }
+ CollectionDockingView.Instance.AddRightSplit(col, undefined);
+ }
+
+ // DONE
+ // this opens the linked doc in a right split, NOT in its collection
+ @undoBatch
+ openLinkRight = (destinationDoc: Doc) => {
+ this.highlightDoc(destinationDoc);
+ let alias = Doc.MakeAlias(destinationDoc);
+ CollectionDockingView.Instance.AddRightSplit(alias, undefined);
+ SelectionManager.DeselectAll();
+ }
+
+ // DONE
+ // this is the standard "follow link" (jump to document)
+ // taken from follow link
+ @undoBatch
+ jumpToLink = async (destinationDoc: Doc, shouldZoom: boolean, linkDoc: Doc) => {
+ //there is an issue right now so this will be false automatically
+ shouldZoom = false;
+ this.highlightDoc(destinationDoc);
+ let jumpToDoc = destinationDoc;
+ let pdfDoc = FieldValue(Cast(destinationDoc, Doc));
+ if (pdfDoc) {
+ jumpToDoc = pdfDoc;
+ }
+ let proto = Doc.GetProto(linkDoc);
+ let targetContext = await Cast(proto.targetContext, Doc);
+ let sourceContext = await Cast(proto.sourceContext, Doc);
+
+ let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
+
+ if (destinationDoc === linkDoc.anchor2 && targetContext) {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
+ }
+ else if (destinationDoc === linkDoc.anchor1 && sourceContext) {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!));
+ }
+ else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, NumCast((destinationDoc === linkDoc.anchor2 ? linkDoc.anchor2Page : linkDoc.anchor1Page)));
+
+ }
+ else {
+ DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, dockingFunc);
+ }
+ }
+
+ // DONE
+ // opens link in new tab (not in a collection)
+ // this opens it full screen, do we need a separate full screen option?
+ @undoBatch
+ openLinkTab = (destinationDoc: Doc) => {
+ this.highlightDoc(destinationDoc);
+ let fullScreenAlias = Doc.MakeAlias(destinationDoc);
+ this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+ SelectionManager.DeselectAll();
+ }
+
+ // NOT TESTED
+ // opens link in new tab in collection
+ // col = collection the doc is in
+ // target = the document to center on
+ @undoBatch
+ openLinkColTab = (destinationDoc: Doc, col: Doc) => {
+ this.highlightDoc(destinationDoc);
+ col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+ if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+ const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+ const newPanY = NumCast(destinationDoc.y) + NumCast(destinationDoc.height) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+ col.panX = newPanX;
+ col.panY = newPanY;
+ }
+ // CollectionDockingView.Instance.AddRightSplit(col, undefined);
+ this.props.addDocTab(col, undefined, "inTab");
+ SelectionManager.DeselectAll();
+ }
+
+ // DONE
+ // this will open a link next to the source doc
+ @undoBatch
+ openLinkInPlace = (destinationDoc: Doc, sourceDoc: Doc) => {
+ this.highlightDoc(destinationDoc);
+
+ let alias = Doc.MakeAlias(destinationDoc);
+ let y = NumCast(sourceDoc.y);
+ let x = NumCast(sourceDoc.x);
+
+ let width = NumCast(sourceDoc.width);
+ let height = NumCast(sourceDoc.height);
+
+ alias.x = x + width + 30;
+ alias.y = y;
+ alias.width = width;
+ alias.height = height;
+
+ SelectionManager.SelectedDocuments().map(dv => {
+ if (dv.props.Document === sourceDoc) {
+ dv.props.addDocument && dv.props.addDocument(alias, false);
+ }
+ });
+ }
+
+ private defaultLinkBehavior: any = this.openLinkInPlace;
+ private currentLinkBehavior: any = this.defaultLinkBehavior;
+
+ render() {
+ return (
+ <div className="linkFollowBox-main">
+
+ </div>
+ );
+ }
} \ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 65516b374..41723030d 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -52,11 +52,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
// col = collection the doc is in
// target = the document to center on
@undoBatch
- openLinkColRight = ({ col, target }: { col: Doc, target: Doc }) => {
+ openLinkColRight = (col: Doc) => {
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;
+ const newPanX = NumCast(this.props.destinationDoc.x) + NumCast(this.props.destinationDoc.width) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
+ const newPanY = NumCast(this.props.destinationDoc.y) + NumCast(this.props.destinationDoc.height) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
col.panX = newPanX;
col.panY = newPanY;
}
@@ -124,12 +124,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
// col = collection the doc is in
// target = the document to center on
@undoBatch
- openLinkColTab = ({ col, target }: { col: Doc, target: Doc }) => {
+ openLinkColTab = (col: Doc) => {
this.highlightDoc();
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;
+ const newPanX = NumCast(this.props.destinationDoc.x) + NumCast(this.props.destinationDoc.width) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
+ const newPanY = NumCast(this.props.destinationDoc.y) + NumCast(this.props.destinationDoc.height) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
col.panX = newPanX;
col.panY = newPanY;
}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index d77662355..d0e117fe4 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -14,6 +14,7 @@ import { ImageBox } from "./ImageBox";
import { DragBox } from "./DragBox";
import { ButtonBox } from "./ButtonBox";
import { PresBox } from "./PresBox";
+import { LinkFollowBox } from "../linking/LinkFollowBox";
import { IconBox } from "./IconBox";
import { KeyValueBox } from "./KeyValueBox";
import { PDFBox } from "./PDFBox";
@@ -30,6 +31,7 @@ import { List } from "../../../new_fields/List";
import { Doc } from "../../../new_fields/Doc";
import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox";
import { ScriptField } from "../../../new_fields/ScriptField";
+import { fromPromise } from "mobx-utils";
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -108,7 +110,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
return <ObserverJsxParser
blacklistedAttrs={[]}
- components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox }}
+ components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox }}
bindings={this.CreateBindings()}
jsx={this.finalLayout}
showWarnings={true}