diff options
-rw-r--r-- | src/client/documents/DocumentTypes.ts | 1 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 4 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 11 | ||||
-rw-r--r-- | src/client/views/linking/LinkFollowBox.scss | 6 | ||||
-rw-r--r-- | src/client/views/linking/LinkFollowBox.tsx | 148 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 12 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 4 |
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} |